Music transcoder!!
This commit is contained in:
commit
e48574b4ce
4 changed files with 413 additions and 0 deletions
107
music_transcoder/__main__.py
Normal file
107
music_transcoder/__main__.py
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
from dataclasses import dataclass
|
||||
import click
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
INPUT_FILE_EXTS_OPUSENC = [
|
||||
".flac",
|
||||
".wav",
|
||||
".aiff",
|
||||
]
|
||||
INPUT_FILE_EXTS_COPY = [
|
||||
".opus",
|
||||
".ogg", # this can also contain FLAC (fry about it)
|
||||
".mp3",
|
||||
".m4a",
|
||||
]
|
||||
|
||||
|
||||
def get_opusenc_args(
|
||||
input_path: str,
|
||||
output_path: str,
|
||||
bitrate: int = 192,
|
||||
) -> list[str]:
|
||||
return [
|
||||
"opusenc",
|
||||
"--bitrate",
|
||||
str(bitrate),
|
||||
"--music",
|
||||
input_path,
|
||||
output_path,
|
||||
]
|
||||
|
||||
|
||||
@dataclass
|
||||
class InputFile:
|
||||
filepath: str
|
||||
relpath: str
|
||||
relpath_noext: str
|
||||
transcode: bool
|
||||
|
||||
|
||||
@click.option(
|
||||
"--input-dir",
|
||||
"-i",
|
||||
type=click.Path(exists=True, dir_okay=True, file_okay=False, resolve_path=True),
|
||||
)
|
||||
@click.option(
|
||||
"--output-dir",
|
||||
"-o",
|
||||
type=click.Path(
|
||||
exists=False, dir_okay=True, file_okay=False, writable=True, resolve_path=True
|
||||
),
|
||||
)
|
||||
@click.command()
|
||||
def music_transcoder(input_dir, output_dir):
|
||||
input_files: list[InputFile] = []
|
||||
|
||||
for dirpath, _, filenames in os.walk(input_dir):
|
||||
for filename in filenames:
|
||||
_, ext = os.path.splitext(filename)
|
||||
|
||||
transcode: bool
|
||||
if ext in INPUT_FILE_EXTS_OPUSENC:
|
||||
transcode = True
|
||||
elif ext in INPUT_FILE_EXTS_COPY:
|
||||
transcode = False
|
||||
else:
|
||||
print("[WARN] rejecting file:", dirpath, filename)
|
||||
continue
|
||||
|
||||
filepath = os.path.join(dirpath, filename)
|
||||
relpath = os.path.relpath(filepath, input_dir)
|
||||
relpath_noext, _ = os.path.splitext(relpath)
|
||||
input_files.append(
|
||||
InputFile(
|
||||
filepath=filepath,
|
||||
relpath=relpath,
|
||||
relpath_noext=relpath_noext,
|
||||
transcode=transcode,
|
||||
)
|
||||
)
|
||||
|
||||
for input_file in input_files:
|
||||
if input_file.transcode:
|
||||
output_path = os.path.join(output_dir, input_file.relpath_noext + ".opus")
|
||||
else:
|
||||
output_path = os.path.join(output_dir, input_file.relpath)
|
||||
|
||||
if os.path.exists(output_path):
|
||||
print("[WARN] skipping existing file", output_path)
|
||||
continue
|
||||
|
||||
output_path_dir, _ = os.path.split(output_path)
|
||||
os.makedirs(output_path_dir, exist_ok=True)
|
||||
|
||||
if not input_file.transcode:
|
||||
print("[INFO] hardlinking lossy file →", output_path)
|
||||
os.link(input_file.filepath, output_path)
|
||||
continue
|
||||
|
||||
print("[INFO] transcoding lossless file →", output_path)
|
||||
opusenc_args = get_opusenc_args(input_file.filepath, output_path)
|
||||
subprocess.run(opusenc_args, check=True)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
music_transcoder()
|
||||
Loading…
Add table
Add a link
Reference in a new issue