MusicUtils / separate.py
sathvik77's picture
feat(backend): demucs two-stem -> mp3 adapter
0abe23e
Raw
History Blame Contribute Delete
1.35 kB
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")