Takes a Rocksmith 2014 .psarc, splits its audio with Demucs, drops the chosen stems
(guitar by default), and repacks a .psarc the game will play.
Unlike FeedForge — which converts CDLC into the
open .feedpak format for FeedBack — Stemify keeps everything in .psarc, so the output
works with Rocksmith 2014 itself.
M1, M2 and M3 (the Electron app) implemented; M4 (packaging) not started. The
CLI (src/stemify/) runs the full pipeline for real - decode, Demucs separation,
Wwise encode under Wine, the encode-verification round trip, and the surgical
soundbank and identity rewrites - and has been exercised end to end against the
synthetic test fixture with real Wwise/Wine/Demucs. The packaging invariants and the
[SILENT] coexistence guard (spec §12) run on CI with no GPU and no Wine, against a
committed synthetic fixture (tests/fixtures/testsong.psarc); pytest -m real_deps
opts into the real-tool tests, which need a local Wwise/Wine/Demucs setup.
The implementation spec is docs/spec.md.
- Read the
.psarc, derive the song's identity, and locate the full-mix.wemand its soundbank. - Decode the audio (vgmstream).
- Separate into six stems (Demucs
htdemucs_6s). - Mix down the kept stems, resampling back to the source rate and managing headroom.
- Re-encode to Wwise Vorbis (Wwise 2013.2.10, via Wine on Linux), calibrating the quality factor per file.
- Verify the encode by decoding it back and checking the sample count — an unverified encode is how a package ends up installing, listing, and playing silence.
- Rewrite the soundbank and the song's identity so the result is a distinct song that coexists with the original, then repack.
Step 7 is not optional. Packages sharing a DLC key do not sit side by side — they mount at the same paths and one silently replaces the other's audio. See ADR-0002.
- Audiokinetic Wwise 2013.2.10 — user-supplied, never bundled. Runs under Wine on Linux. It is the only source of a Wwise Vorbis encoder; no open-source equivalent exists. Audiokinetic no longer distributes a version this old, so in practice it comes from the Rocksmith CDLC community: CustomsForge's tools page hosts the 2013.2.10 installer and the project template that goes with it.
- Demucs with the
htdemucs_6smodel — the only Demucs model that isolates guitar. Unlike Wwise, this can be fetched, so the app builds and owns its own environment rather than hunting for one. - vgmstream for decoding, ffmpeg for resampling.
python3 -m venv .venv
.venv/bin/pip install -e '.[dev]'
.venv/bin/pytest # packaging invariants + coexistence guard, no GPU/Wine
.venv/bin/python -m stemify.cli in.psarc -o out.psarc --drop guitar
pytest -m real_deps additionally exercises real vgmstream/Wine/Wwise/Demucs; it needs
STEMIFY_WWISE_ROOT, STEMIFY_WWISE_TEMPLATE and (for a full local Demucs venv)
STEMIFY_DEMUCS_VENV set, and is never run on CI.
MIT. See THIRD_PARTY.md for the licensing of code this project builds on, and for what must never be bundled.
The desktop app lives in gui/ and drives the CLI as a subprocess — it does not
reimplement any of it. Packaging is M4; for now it runs from source:
cd gui
npm install
npm run devIt looks for the CLI at ../.venv/bin/python -m stemify.cli. Override with
STEMIFY_PYTHON=/path/to/python npm run dev.
First launch opens Setup, because the Wwise paths are not set yet. Point it at your
Wwise 2013.2.10 install and project template, press Run Setup checks, and it will prove
the Wwise round trip, build the Demucs venv from requirements.txt, and run a test
separation. After that it opens on Convert: drop a .psarc, untick what to remove,
convert, and optionally install into any Steam library's dlc/.
npm start runs the built app instead of the dev server. If it exits with
Error: Electron uninstall, npm install skipped the Electron binary download — rerun it
with node node_modules/electron/install.js.
Tests: cd gui && npm test.
Setup's path rows are the whole configuration surface. Each one is saved immediately to
settings.json under the app's user-data directory (~/.config/stemify/settings.json on
Linux) and handed to every CLI subprocess as an environment variable, so the CLI and the
app are configured by the same values. The file is plain JSON and can be edited by hand;
Setup prints its path.
| Setup row | Env var | What it is, and where to get it |
|---|---|---|
| Wwise install (required) | STEMIFY_WWISE_ROOT |
The Wwise 2013.2.10 installation directory. Stemify searches underneath it for WwiseCLI.exe, so any ancestor of Authoring/x64/Release/bin/ works. Proprietary and never bundled — get 2013.2.10 from CustomsForge and install it yourself, on Linux into a Wine prefix, where it lands under drive_c/Program Files (x86)/Audiokinetic/Wwise v2013.2.10 build 4884. |
| Wwise project template (.tar) (required) | STEMIFY_WWISE_TEMPLATE |
A tarball of a minimal Wwise 2013 project, unpacked per conversion to drive the encoder. The Rocksmith Custom Song Toolkit ships one, as does the CustomsForge download above; see THIRD_PARTY.md — its licensing is why this is a path you supply rather than a file in this repo. |
| Wine prefix | STEMIFY_WINEPREFIX |
The prefix Wwise was installed into. Defaults to ~/.local/share/wineprefixes/wwise2013. Linux only — see Platform support. |
| Demucs environment | STEMIFY_DEMUCS_VENV |
A virtualenv with demucs and torch. Leave it unset and Run Setup checks builds one from requirements.txt at ~/.local/share/stemify/venv — several GB, and deliberately outside the app so an update never re-downloads it. Point it at an existing venv to skip that. |
| Where to write variants | — | Output directory for converted packages. Defaults to ~/Downloads. |
| Rocksmith DLC folder | — | Where Install copies a finished variant, and where Stemify checks whether a DLC key is already taken. Defaults to the dlc/ folders found by parsing Steam's libraryfolders.vdf; set it when the game lives on a drive Steam's own config points at ambiguously, or when the scan finds an empty leftover directory first. |
STEMIFY_PYTHON is separate: it tells the app which Python runs the CLI, is read from the
real environment rather than the settings file, and defaults to ../.venv/bin/python.
Setting any of the four environment variables directly configures the CLI on its own —
that is what the Makefile does for pytest -m real_deps.
Linux only. Windows is not supported yet, and the gaps are structural rather than cosmetic:
wwise_adapterinvokeswineandwinepathunconditionally. On Windows, WwiseCLI runs natively and needs no path translation, and neither branch exists.- The Demucs venv is looked up at
venv/bin/python(demucs_adapter,gui'ssetup.tsandipc.ts); Windows puts it invenv\Scripts\. - Cancel signals
SIGINTto a negative pid — a process group, which Windows has no equivalent of. That signal is what lets the CLI unwind itsTemporaryDirectory, so there is deliberately no cleanup code to fall back on; on Windows a cancelled run would leak a multi-GB temp directory and orphan Demucs. - Steam library detection searches three Linux paths under
$HOME. Windows keepslibraryfolders.vdfunderC:\Program Files (x86)\Steam. The DLC-folder setting is a workaround, not a fix.
electron-builder.yml still carries the template's win/nsis targets, so an installer
would build; it just would not convert anything. Wwise 2013.2.10 itself runs natively on
Windows, so the port is a set of platform branches rather than a rewrite.
