110 lines
3.8 KiB
Python
110 lines
3.8 KiB
Python
#!/usr/bin/env python
|
|
|
|
import argparse
|
|
from pathlib import Path
|
|
from progress.bar import Bar
|
|
import shutil
|
|
import subprocess
|
|
|
|
def files_and_dirs_for_directory(path):
|
|
filepaths = []
|
|
dirpaths = []
|
|
|
|
for dirpath, dirnames, filenames in path.walk():
|
|
dirpaths.append(dirpath)
|
|
|
|
for filename in filenames:
|
|
filepath = dirpath / filename
|
|
filepaths.append(filepath)
|
|
|
|
return set(filepaths), set(dirpaths)
|
|
|
|
def make_paths_relative(paths, relative_to_path):
|
|
return set(path.relative_to(relative_to_path) for path in paths)
|
|
|
|
def replace_suffix(path, suffix):
|
|
return path.with_name(path.stem + suffix)
|
|
|
|
def convert_filepath(path):
|
|
if path.suffix == ".flac":
|
|
return replace_suffix(path, ".mp3")
|
|
|
|
return path
|
|
|
|
def ffmpeg_flac_to_mp3(in_path, out_path):
|
|
print("")
|
|
subprocess.run(["ffmpeg", "-hide_banner", "-loglevel", "warning", "-stats", "-i", in_path, "-ab", "320k", "-map_metadata", "0", "-id3v2_version", "3", out_path], check=True)
|
|
print("")
|
|
|
|
if __name__ == "__main__":
|
|
|
|
parser = argparse.ArgumentParser(prog="convert-flac-dir-to-mp3")
|
|
parser.add_argument("from_dir", type=Path)
|
|
parser.add_argument("to_dir", type=Path)
|
|
|
|
args = parser.parse_args()
|
|
|
|
from_path = args.from_dir.absolute()
|
|
to_path = args.to_dir.absolute()
|
|
|
|
if not from_path.exists():
|
|
raise Exception("from_path does not exist")
|
|
|
|
if not to_path.exists():
|
|
raise Exception("to_path does not exist")
|
|
|
|
if not from_path.is_dir():
|
|
raise Exception("from_path is not a directory")
|
|
|
|
if not to_path.is_dir():
|
|
raise Exception("to_path is not a directory")
|
|
|
|
print(f"Converting {from_path} to {to_path}…")
|
|
|
|
from_filepaths, from_dirpaths = files_and_dirs_for_directory(from_path)
|
|
to_filepaths, to_dirpaths = files_and_dirs_for_directory(to_path)
|
|
|
|
|
|
relative_from_filepaths = make_paths_relative(from_filepaths, from_path)
|
|
relative_to_filepaths = make_paths_relative(to_filepaths, to_path)
|
|
|
|
converted_from_filepaths = set(convert_filepath(filepath) for filepath in relative_from_filepaths)
|
|
|
|
filepaths_missing_in_to_path = converted_from_filepaths - relative_to_filepaths
|
|
|
|
|
|
relative_from_dirpaths = make_paths_relative(from_dirpaths, from_path)
|
|
relative_to_dirpaths = make_paths_relative(to_dirpaths, to_path)
|
|
|
|
dirpaths_missing_in_to_path = relative_from_dirpaths - relative_to_dirpaths
|
|
|
|
print(f"Missing {len(filepaths_missing_in_to_path)} files and {len(dirpaths_missing_in_to_path)} directories")
|
|
|
|
if len(dirpaths_missing_in_to_path) > 0:
|
|
for dirpath in Bar("Creating directories").iter(dirpaths_missing_in_to_path):
|
|
(to_path / dirpath).mkdir(parents=True, exist_ok=True)
|
|
|
|
if len(filepaths_missing_in_to_path) > 0:
|
|
for filepath in Bar("Creating files").iter(filepaths_missing_in_to_path):
|
|
if filepath in relative_from_filepaths:
|
|
# Just copy the file
|
|
shutil.copy(from_path / filepath, to_path / filepath)
|
|
elif filepath.suffix == ".mp3" and replace_suffix(filepath, ".flac") in relative_from_filepaths:
|
|
# Convert from flac
|
|
print("")
|
|
print(f"Converting {to_path / filepath}…")
|
|
|
|
# Tempfile for ffmpeg
|
|
tmpfilepath = filepath.with_name(".~" + filepath.name)
|
|
(to_path / tmpfilepath).unlink(missing_ok=True)
|
|
|
|
print(f"Using tempfile for ffmpeg {to_path / tmpfilepath}…")
|
|
|
|
# Convert
|
|
ffmpeg_flac_to_mp3(from_path / replace_suffix(filepath, ".flac"), to_path / tmpfilepath)
|
|
|
|
# Rename tempfile
|
|
(to_path / tmpfilepath).rename(to_path / filepath)
|
|
else:
|
|
raise Exception("Unable to figure out how to get {to_path / filepath} from {from_path}")
|