import subprocess import sys from pathlib import Path from processor import _get_device def _run_demucs(audio_path: Path) -> Path: """Run demucs in two-stems mode targeting vocals; return path to no_vocals stem.""" out_root = audio_path.parent / "demucs_out" out_root.mkdir(parents=True, exist_ok=True) cmd = [ sys.executable, "-m", "demucs", "--two-stems", "vocals", "-n", "htdemucs", "--device", _get_device(), "--mp3", "--mp3-bitrate", "192", "-o", str(out_root), str(audio_path), ] subprocess.run(cmd, check=True) # demucs writes to {out_root}/htdemucs/{audio_stem}/no_vocals.mp3 candidate = out_root / "htdemucs" / audio_path.stem / "no_vocals.mp3" if not candidate.exists(): raise RuntimeError(f"demucs did not produce {candidate}") return candidate def _encode_mp3(wav_path: Path, mp3_path: Path) -> Path: """Re-encode (or copy) a stem file to the target mp3_path.""" subprocess.run( ["ffmpeg", "-y", "-i", str(wav_path), "-b:a", "192k", str(mp3_path)], check=True, capture_output=True, ) return mp3_path def separate_vocals_to_mp3(audio_path: Path) -> Path: no_vocals_stem = _run_demucs(audio_path) return _encode_mp3(no_vocals_stem, audio_path.parent / "no_vocals.mp3")