README: make it generic (no host paths, IPs or personal examples)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
cdnutterandClaude Sonnet 5.5 committed 2026-10-20 15:09:12 -07:00
1 parent 1cf9341cda
commit d69c44eff9
1 file changed
+35 -35
+35 -35
View File
@@ -20,7 +20,7 @@ It runs on iPhone (with CarPlay), Android (with Android Auto) and Linux desktop.
## How it works
The stems folder mirrors the music folder. If a song lives at `Kansas/Leftoverture/01 Carry On.flac`, its stems live in `Stems/Kansas/Leftoverture/01 Carry On/`.
The stems folder mirrors the music folder. If a song lives at `Artist/Album/01 Song.flac`, its stems live in `Stems/Artist/Album/01 Song/`.
```
your server
@@ -63,48 +63,48 @@ Mix presets are Full, Karaoke, A Cappella, No Drums, Rhythm, No Guitar and No Ba
## Setup
Set up the server first, then the apps. The examples use Unraid paths and `192.168.86.2` for the server; use your own.
Set up the server first, then the apps. The examples use `/srv/stemify` for app data, `/srv/music/library` for your music, `/srv/music/stems` for the output and `SERVER_IP` for the machine running the containers. Change them to match your setup.
### Server
You need Docker, and an NVIDIA GPU for stemd (on Unraid, install the Nvidia-Driver plugin). A CPU build exists for testing, but it's far too slow for a whole library.
You need Docker, and an NVIDIA GPU for stemd (with the NVIDIA container toolkit installed). A CPU build exists for testing, but it's far too slow for a whole library.
Make the folders, owned by `99:100` (Unraid's nobody:users):
Make the folders, owned by whatever user the containers run as (`1000:1000` here):
```sh
mkdir -p /mnt/user/appdata/stemserve/cache \
/mnt/user/appdata/stemd/models \
/mnt/user/appdata/stemd/state/queue
chown -R 99:100 /mnt/user/appdata/stemserve /mnt/user/appdata/stemd
mkdir -p /srv/stemify/stemserve/cache \
/srv/stemify/stemd/models \
/srv/stemify/stemd/state/queue
chown -R 1000:1000 /srv/stemify/stemserve /srv/stemify/stemd
```
**stemd** builds from the repo root because it uses the `stemify` package. Copy the repo (at least `stemify/`, `server/` and `.dockerignore`) to `/mnt/user/appdata/stemd/src`, then:
**stemd** builds from the repo root because it uses the `stemify` package. Copy the repo (at least `stemify/`, `server/` and `.dockerignore`) to `/srv/stemify/stemd/src`, then:
```sh
docker build -f /mnt/user/appdata/stemd/src/server/stemd.Dockerfile -t stemd /mnt/user/appdata/stemd/src
docker build -f /srv/stemify/stemd/src/server/stemd.Dockerfile -t stemd /srv/stemify/stemd/src
docker run -d --name stemd --restart unless-stopped --stop-timeout 60 \
--runtime=nvidia -e NVIDIA_VISIBLE_DEVICES=all -e NVIDIA_DRIVER_CAPABILITIES=compute,utility \
-v "/mnt/user/Music/Actual music/Flacs":/music:ro \
-v /mnt/user/Music/Stems:/stems \
-v /mnt/user/appdata/stemd/models:/models \
-v /mnt/user/appdata/stemd/state:/state \
-v /srv/music/library:/music:ro \
-v /srv/music/stems:/stems \
-v /srv/stemify/stemd/models:/models \
-v /srv/stemify/stemd/state:/state \
stemd
```
The first song downloads the model (about 700 MB). After that the log shows what's left, what it's on, and how fast it's going.
**stemserve** is one Python file using only the standard library. It also serves the web player from `web/`. Copy the repo's `server/` and `web/` folders to `/mnt/user/appdata/stemserve` and run `docker compose up -d --build` in `server/`, or by hand:
**stemserve** is one Python file using only the standard library. It also serves the web player from `web/`. Copy the repo's `server/` and `web/` folders to `/srv/stemify/stemserve` and run `docker compose up -d --build` in `server/`, or by hand:
```sh
docker build -f /mnt/user/appdata/stemserve/server/Dockerfile -t stemserve /mnt/user/appdata/stemserve
docker build -f /srv/stemify/stemserve/server/Dockerfile -t stemserve /srv/stemify/stemserve
docker run -d --name stemserve --restart unless-stopped -p 8765:8765 \
-v /mnt/user/Music/Stems:/stems:ro \
-v /mnt/user/appdata/stemserve/cache:/cache \
-v /mnt/user/appdata/stemd/state/queue:/queue \
-v /srv/music/stems:/stems:ro \
-v /srv/stemify/stemserve/cache:/cache \
-v /srv/stemify/stemd/state/queue:/queue \
stemserve
```
`curl http://192.168.86.2:8765/api/info` should return JSON with a track count.
`curl http://SERVER_IP:8765/api/info` should return JSON with a track count.
To update, copy the new files, rebuild, `docker rm -f` the container and run it again. Everything that matters lives in the mounted folders. Update stemd before stemserve.
@@ -155,14 +155,14 @@ The apps check stemserve for newly separated songs every minute, so the library
## iOS
A SwiftUI app for iOS 17 or newer, with CarPlay and Siri ("play Paranoid in Stemify").
A SwiftUI app for iOS 17 or newer, with CarPlay and Siri ("play <song> in Stemify").
### Install
Grab `stemify-<version>.ipa` from [Releases](https://git.iamchrisama.com/cdnutter/stemify/releases) and sideload it with AltStore, SideStore, Sideloadly or Feather. To get updates in AltStore, SideStore or Feather, add this source:
Grab `stemify-<version>.ipa` from the repo's Releases page and sideload it with AltStore, SideStore, Sideloadly or Feather. `ios/source.json` is an AltStore-style source. Add its raw URL to AltStore, SideStore or Feather for updates:
```
https://git.iamchrisama.com/cdnutter/stemify/raw/branch/main/ios/source.json
https://<your-git-host>/<owner>/stemify/raw/branch/main/ios/source.json
```
CarPlay and Siri need the `carplay-audio` and `siri` entitlements, which a free Apple ID can't sign. On a free sideload the app works on the phone but not in CarPlay or Siri. A paid developer account covers Siri; CarPlay audio also needs Apple to approve the entitlement for your team.
@@ -186,7 +186,7 @@ CarPlay and Siri need the `carplay-audio` and `siri` entitlements, which a free
## Android
Kotlin and Jetpack Compose, built and tested on a OnePlus 15. Grab `Stemify.apk` from Releases (or [build it](#building-and-testing)) and `adb install -r Stemify.apk`.
Kotlin and Jetpack Compose, [build it](#building-and-testing) or grab `Stemify.apk` from Releases if one is attached, and `adb install -r Stemify.apk`.
### Using it
@@ -194,7 +194,7 @@ Kotlin and Jetpack Compose, built and tested on a OnePlus 15. Grab `Stemify.apk`
- **Badges:** songs without stems yet say NO STEMS, and albums and artists show NO STEMS or a count like 7/10 STEMS. They still play from the original file.
- **Now Playing:** waveform seek bar (drag sideways to seek, up and down for volume), mixer, meters and queue. Your mix can carry over between songs or reset.
- **Stem Quality:** lossless FLAC, or Opus at a bitrate you choose (about an eighth of the size, transcoded and cached on the server).
- **Streaming** needs your home network, since Plex and stemserve are plain HTTP on the LAN. Downloads and already-streamed songs play anywhere.
- **Streaming** works anywhere you can reach Plex and stemserve. Both are plain HTTP by default, so use HTTPS or a VPN away from home. Downloads and already-streamed songs play anywhere.
### Equalizer
@@ -209,12 +209,12 @@ Profiles are tied to outputs (speaker, wired, each Bluetooth device, USB DACs) a
### Android Auto
Built for a 2016 Mazda MX-5 with Mazda Connect: 800×480, no touch, knob and wheel buttons only.
Designed for small non-touch head units (800×480, knob and wheel buttons only), and it works the same on larger screens.
- Tabs for Playlists, Albums, Artists and Downloads (Downloads first when you're away from home).
- Every song list starts with Shuffle all, and lists over 40 items split into A to Z folders.
- Now Playing has a Vocals on/off button and a Mix button that cycles presets. The mix shows on the artist line, like "Black Sabbath · Karaoke".
- Voice: "play Paranoid on Stemify" works for playlists, artists, albums and songs.
- Now Playing has a Vocals on/off button and a Mix button that cycles presets. The mix shows on the artist line, like "Artist · Karaoke".
- Voice: "play <song> on Stemify" works for playlists, artists, albums and songs.
- Away from home it notices the server is gone and only lists songs that will play.
Android Auto hides sideloaded apps until you allow them: in the phone's Android Auto settings, tap Version ten times, then ⋮ → Developer settings → Unknown sources.
@@ -279,11 +279,11 @@ Requests run oldest first and survive restarts. stemd matches Plex's paths to it
### Folder layout
```
Music/Kansas/Leftoverture/01 Carry On Wayward Son.flac
Stems/Kansas/Leftoverture/01 Carry On Wayward Son/
Music/Artist/Album/01 Song.flac
Stems/Artist/Album/01 Song/
.stemify.json done marker
01 Carry On Wayward Son - vocals.flac
01 Carry On Wayward Son - drums.flac
01 Song - vocals.flac
01 Song - drums.flac
...
```
@@ -303,7 +303,7 @@ Stems/Kansas/Leftoverture/01 Carry On Wayward Son/
| `GET /file/K/<file>.flac[?fmt=opus&br=256]` | The stem, with range support |
| `GET /` | The web player from `web/` (or `WEB_DIR`), no token needed |
`K` is the song's folder under the stems root, like `Kansas/Leftoverture/01 Carry On Wayward Son`. Outside Docker:
`K` is the song's folder under the stems root, like `Artist/Album/01 Song`. Outside Docker:
```sh
STEMS_DIR=/path/to/Stems CACHE_DIR=~/.cache/stemserve python3 server/stemserve.py
@@ -358,7 +358,7 @@ QT_QPA_PLATFORM=offscreen uv run stemify-player --no-mpris --screenshot /tmp/p.p
**A song says NO STEMS.** Hold it and choose Stem Now.
**Stem Now says "stemserve needs updating" or "queue folder isn't mounted".** stemserve is older than the app or is missing the `/queue` mount. The queue folder has to be owned by `99:100` before the container first starts, or Docker creates it as root.
**Stem Now says "stemserve needs updating" or "queue folder isn't mounted".** stemserve is older than the app or is missing the `/queue` mount. The queue folder has to be writable by the container user before the container first starts, or Docker creates it as root.
**stemd is separating on the CPU.** The container can't see the GPU. Run it with `--runtime=nvidia` and the NVIDIA variables above.
@@ -381,7 +381,7 @@ QT_QPA_PLATFORM=offscreen uv run stemify-player --no-mpris --screenshot /tmp/p.p
- [LRCLIB](https://lrclib.net) for synced lyrics
- Inter, Selawik and Carlito fonts (licenses included alongside them)
Stemify isn't affiliated with Plex, Apple, Google, Microsoft or Mazda.
Stemify isn't affiliated with Plex, Apple, Google or Microsoft.
## License