yt2stems is a CLI for downloading audio from YouTube with yt-dlp and separating it into stems with Demucs.
It is tuned for a practical local workflow on macOS and Apple Silicon, but the codebase is structured as a small Python package with tests, CI, release docs, and packaging scaffolding so it can be maintained in the open.
- Normalizes YouTube URLs before processing
- Downloads the best available audio track with
yt-dlp - Runs Demucs with configurable model and device selection
- Supports
htdemucs,htdemucs_ft, andhtdemucs_6s - Auto-benchmarks
cpuvsmpsand chooses sensible defaults during setup - Supports
yt-dlpbrowser-cookie authentication for YouTube bot-check challenges - Retries transient YouTube anti-bot failures automatically
- Keeps runtime output readable with a simplified stem-splitting progress display
- Writes a single
metadata.txtfile alongside the generated stems
- Python 3.10+
ffmpegavailable on yourPATH- enough disk space for model downloads and separated stems
On macOS with Homebrew:
brew install ffmpeg pythonUse the public tap and then run the bootstrap setup command:
brew tap wenda-gu/tap
brew install yt2stems
yt2stems-setupIf you usually need browser cookies for YouTube, you can save that preference during setup:
yt2stems-setup --cookies-from-browser chromeThe Homebrew formula installs the bootstrap commands. yt2stems-setup then creates the dedicated runtime environment, installs the heavy audio stack, and links yt2stems and yt2stems-benchmark into ~/.local/bin by default.
If ~/.local/bin is not already on your PATH, add it to your shell profile.
If Python package downloads are slow or unstable in China, you can point setup at the Tsinghua PyPI mirror:
PIP_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple \
PIP_TRUSTED_HOST=pypi.tuna.tsinghua.edu.cn \
yt2stems-setup --cookies-from-browser chromeClone the repository and run the setup command:
git clone https://github.com/wenda-gu/yt2stems.git
cd yt2stems
./yt2stems-setupyt2stems-setup creates a dedicated virtual environment, installs the runtime dependencies, benchmarks your machine, and links the commands into ~/.local/bin by default.
If ~/.local/bin is not already on your PATH, add it to your shell profile.
./yt2stems-setup --skip-benchmark
BIN_DIR=/usr/local/bin ./yt2stems-setup
PYTHON_BIN=/opt/homebrew/bin/python3.12 ./yt2stems-setup
YT2STEMS_TORCH_SPEC='torch==2.8.*' YT2STEMS_TORCHAUDIO_SPEC='torchaudio==2.8.*' ./yt2stems-setup
./yt2stems-setup --cookies-from-browser safariyt2stems "https://www.youtube.com/watch?v=..."
yt2stems "https://www.youtube.com/watch?v=..." --model htdemucs --device cpu
yt2stems "https://www.youtube.com/watch?v=..." --model htdemucs_6s
yt2stems "https://www.youtube.com/watch?v=..." --voice
yt2stems "https://www.youtube.com/watch?v=..." --cookies-from-browser safari
yt2stems "https://www.youtube.com/watch?v=..." --cookies ~/Downloads/youtube-cookies.txt
yt2stems --versionIf YouTube asks yt-dlp to sign in and confirm you are not a bot, pass authenticated browser cookies for that run or save the preference once with yt2stems-install --cookies-from-browser safari.
When --cookies-from-browser is used, yt2stems passes that browser source directly through to yt-dlp. If browser-cookie extraction or YouTube session acceptance fails, yt2stems surfaces the auth error more clearly and suggests the next best recovery options.
yt2stems also runs its internal yt-dlp commands with --ignore-config so personal yt-dlp config files do not accidentally override metadata, auth, or download behavior inside the pipeline.
Each completed run produces a folder containing:
- one WAV per stem
metadata.txtexport_warning.txtonly when torchaudio downgraded the requested WAV precision during export
The setup flow defaults to yt-dlp[default] instead of plain yt-dlp, because YouTube challenge solving may require the yt-dlp-ejs support package that ships through the default extras set.
The runtime defaults also pin:
torch==2.8.*torchaudio==2.8.*soundfile>=0.13
That combination avoids newer TorchCodec-related Demucs export failures and ensures torchaudio has a working WAV backend for stem export.
For intermittent YouTube anti-bot failures, yt2stems automatically retries its internal yt-dlp commands a few times before giving up.
yt2stems-benchmark
yt2stems-benchmark --devices cpu,mps --models htdemucs,htdemucs_ft
yt2stems-benchmark --versionCreate a development environment and install the package in editable mode:
python3 -m venv .venv
. .venv/bin/activate
python -m pip install --upgrade pip setuptools wheel
python -m pip install -e '.[dev]'
python -m pip install torch torchaudio demucs==4.0.1 "yt-dlp[default]" "soundfile>=0.13"
python -m unittest
ruff check .
python -m buildThe package deliberately avoids hard runtime dependency declarations for the heavy audio stack. The runtime tools are installed by the setup script or manually during development.
src/yt2stems/: package sourcetests/: unit testsyt2stems-setup: friendly bootstrap entry point for end usersinstall-yt2stems.sh: bootstrap implementation used by the setup wrapperyt2stems: development wrapper for the main CLIdemucs_benchmark.sh: development wrapper for the benchmark CLIdocs/releasing.md: release process notesCHANGELOG.md: human-readable change history
This project is available under the MIT License.
Make sure your usage complies with YouTube's terms of service and the rights associated with the media you download and process.