Skip to content

Instantly share code, notes, and snippets.

@steveherrin
Last active August 9, 2023 20:34
Show Gist options
  • Save steveherrin/cb307fe81319f2c68fd3314f6422f91b to your computer and use it in GitHub Desktop.
Save steveherrin/cb307fe81319f2c68fd3314f6422f91b to your computer and use it in GitHub Desktop.
Reencode a music library from FLAC to Opus
import pathlib
import subprocess
import sys
REENCODE_EXTENSIONS = {'.flac', '.m4a', '.alac'}
COPY_EXTENSIONS = {'.jpg', '.jpeg', '.png', '.mp3', '.opus', '.ogg'}
IGNORE_EXTENSIONS = {'.log', '.cue', '.txt'}
def _iter_tree(root: pathlib.Path):
if not root.is_dir():
raise ValueError(f'{root} is not a directory')
for child in sorted(root.iterdir()):
if not child.is_dir():
yield child
elif child.is_dir():
for descendent in _iter_tree(child):
yield descendent
def encode_music_tree(src: pathlib.Path, dest: pathlib.Path):
for src_file in _iter_tree(src):
rel = src_file.relative_to(src)
dest_file = dest / rel
file_name = src_file.name
if file_name.startswith('.') or any(file_name.lower().endswith(ext) for ext in IGNORE_EXTENSIONS):
continue
elif any(file_name.lower().endswith(ext) for ext in COPY_EXTENSIONS):
command = ['cp', src_file, dest_file]
elif any(file_name.lower().endswith(ext) for ext in REENCODE_EXTENSIONS):
dest_file = dest_file.parent / (file_name.rsplit('.', 1)[0] + '.opus')
command = ['ffmpeg', '-i', src_file, '-vn', '-c:a', 'libopus', '-b:a', '128000', dest_file]
else:
ext = file_name.rsplit('.', 1)[-1]
if ext != file_name: # don't print this for files with no extension
print(f'unrecognized extension: .{ext}', file=sys.stderr)
continue
dest_file.parent.mkdir(parents=True, exist_ok=True)
result = subprocess.run(command, capture_output=True, encoding='utf-8')
if result.returncode != 0:
print(result.stderr, file=sys.stderr)
raise Exception(f"Error running '{' '.join(map(str, command))}'")
if __name__ == '__main__':
src = pathlib.Path(sys.argv[1]).resolve()
dest = pathlib.Path(sys.argv[2]).resolve()
encode_music_tree(src, dest)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment