#!/usr/bin/env python3 import json import subprocess import sys from pathlib import Path import shutil def run(cmd): print(f"[*] Running: {' '.join(map(str, cmd))}") subprocess.run(cmd, check=True) def get_tracks(video): result = subprocess.run( ["mkvmerge", "-J", str(video)], capture_output=True, text=True, check=True, ) data = json.loads(result.stdout) return [t for t in data["tracks"] if t["type"] == "audio"] def codec_to_ext(codec): codec = codec.lower() if "aac" in codec: return "aac" if "ac-3" in codec or "ac3" in codec: return "ac3" if "dts" in codec: return "dts" if "flac" in codec: return "flac" if "opus" in codec: return "opus" return "mka" def clean(text): return "".join(c if c.isalnum() or c in "-_." else "_" for c in text) def extract(vdir, outdir): outdir.mkdir(parents=True, exist_ok=True) for video in vdir.iterdir(): if not video.is_file(): continue name = video.stem print(f"\n=== Scanning {video.name} ===") for track in get_tracks(video): tid = track["id"] props = track.get("properties", {}) lang = props.get("language", "und") tname = props.get("track_name", "") codec = track.get("codec", "") ext = codec_to_ext(codec) suffix = lang if tname: suffix += "-" + clean(tname) outfile = outdir / f"{name}-{suffix}.{ext}" print(f"Extracting track {tid}: lang={lang}, name={tname}, codec={codec}") run(["mkvextract", "tracks", str(video), f"{tid}:{outfile}"]) def include(vdir, adir): for video in vdir.iterdir(): if not video.is_file(): continue name = video.stem tmp = video.with_name(name + "-tmp.mkv") print(f"\n=== Processing {video.name} ===") audios = list(adir.glob(f"{name}-*")) if not audios: print("No matching audio found.") continue unknown = [] known = [] for a in audios: meta = a.stem[len(name)+1:] # remove "name-" parts = meta.split("-", 1) lang = parts[0] tname = parts[1] if len(parts) > 1 else "" entry = (a, lang, tname) if lang in ("und", "unknown", ""): unknown.append(entry) else: known.append(entry) cmd = ["mkvmerge", "-o", str(tmp), str(video)] for file, lang, tname in unknown + known: print(f"Adding {file.name} lang={lang} name={tname}") cmd += ["--language", f"0:{lang}"] if tname: cmd += ["--track-name", f"0:{tname}"] cmd.append(str(file)) run(cmd) shutil.move(tmp, video) print(f"Finished {video.name}") def main(): if len(sys.argv) < 3: print("Usage:") print(" script extract [audio_out_dir]") print(" script include [audio_dir]") sys.exit(1) action = sys.argv[1] vdir = Path(sys.argv[2]).resolve() adir = Path(sys.argv[3]).resolve() if len(sys.argv) > 3 else vdir if not vdir.is_dir(): print("Video directory not found.") sys.exit(1) if action == "extract": extract(vdir, adir) elif action == "include": include(vdir, adir) else: print("Unknown action.") sys.exit(1) if __name__ == "__main__": main()