Closes#33. Clients can add a soundtrack by uploading its songs, without waiting for the next sync. Used by Sansan/MusicPlayer#50.
Endpoints (token required)
POST /api/v1/soundtracks/uploads{"name": "…"}
Start an upload, returns its ID (201)
PUT .../uploads/{id}/files/{file}
One MP3 as the raw body; sending the same name again replaces it
GET .../uploads/{id}
Songs received so far, for resuming
POST .../uploads/{id}/finish
Move the folder into the music folder, sync only that folder, return the soundtrack
DELETE .../uploads/{id}
Cancel and delete the songs
Rules
Names must work as file names on every system and be free: no soundtrack, folder or other upload with the same name, ignoring case (409).
File names are plain: clients flatten disc folders, e.g. 1-01 Title.mp3. A /, also as %2F, gets a 400.
Only .mp3 files with MP3 content, like the sync.
Size limits from UPLOAD_MAX_FILE_MB (default 50) and UPLOAD_MAX_TOTAL_MB (default 2048).
Refused while a sync runs (423), and a sync cannot start while an upload is being finished.
Songs equal to an existing soundtrack's are refused (409); the sync would otherwise take them for that soundtrack renamed.
After finishing, the soundtrack is in the lists, search and library count right away. Play queues are not reset.
Deploy notes
The music volume must be writable for uid 1000.
Unfinished uploads live in MUSIC_PATH/.uploads. The sync now skips every hidden folder. Add .uploads to ResilioSync's ignore list (.sync/IgnoreList) so half-finished uploads are not copied to other devices.
Unfinished uploads older than a day are removed at startup and when a new upload starts.
Tests
Unit tests for the service and endpoints, OpenAPI response checks, and an integration test against PostgreSQL (upload, duplicate refusal, a sync afterwards changes nothing).
Closes #33. Clients can add a soundtrack by uploading its songs, without waiting for the next sync. Used by Sansan/MusicPlayer#50.
## Endpoints (token required)
| | |
|---|---|
| `POST /api/v1/soundtracks/uploads` `{"name": "…"}` | Start an upload, returns its ID (201) |
| `PUT .../uploads/{id}/files/{file}` | One MP3 as the raw body; sending the same name again replaces it |
| `GET .../uploads/{id}` | Songs received so far, for resuming |
| `POST .../uploads/{id}/finish` | Move the folder into the music folder, sync only that folder, return the soundtrack |
| `DELETE .../uploads/{id}` | Cancel and delete the songs |
## Rules
- Names must work as file names on every system and be free: no soundtrack, folder or other upload with the same name, ignoring case (409).
- File names are plain: clients flatten disc folders, e.g. `1-01 Title.mp3`. A `/`, also as `%2F`, gets a 400.
- Only `.mp3` files with MP3 content, like the sync.
- Size limits from `UPLOAD_MAX_FILE_MB` (default 50) and `UPLOAD_MAX_TOTAL_MB` (default 2048).
- Refused while a sync runs (423), and a sync cannot start while an upload is being finished.
- Songs equal to an existing soundtrack's are refused (409); the sync would otherwise take them for that soundtrack renamed.
- After finishing, the soundtrack is in the lists, search and library count right away. Play queues are not reset.
## Deploy notes
- The music volume must be writable for uid 1000.
- Unfinished uploads live in `MUSIC_PATH/.uploads`. The sync now skips every hidden folder. Add `.uploads` to ResilioSync's ignore list (`.sync/IgnoreList`) so half-finished uploads are not copied to other devices.
- Unfinished uploads older than a day are removed at startup and when a new upload starts.
## Tests
Unit tests for the service and endpoints, OpenAPI response checks, and an integration test against PostgreSQL (upload, duplicate refusal, a sync afterwards changes nothing).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sansan
added the feature label 2026-10-15 21:40:44 +02:00
A client starts an upload with the soundtrack's name, sends one MP3 per
request, and finishes it. The server then moves the songs into a new folder
in the music folder and syncs only that folder, so the soundtrack is in the
library, lists and search right away.
- POST /api/v1/soundtracks/uploads, GET/DELETE .../uploads/{id},
PUT .../uploads/{id}/files/{file} and POST .../uploads/{id}/finish.
- Names must work as file names on every system and be free, ignoring case.
File names are plain: clients flatten disc folders.
- Only MP3 files. Size limits from UPLOAD_MAX_FILE_MB (50) and
UPLOAD_MAX_TOTAL_MB (2048).
- Refused while a sync runs, and a sync cannot start while an upload is
finished. Songs equal to an existing soundtrack's are refused, as the sync
would take them for that soundtrack renamed.
- Unfinished uploads live in MUSIC_PATH/.uploads and are removed after a day.
The sync now skips every hidden folder.
Closes#33
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Closes #33. Clients can add a soundtrack by uploading its songs, without waiting for the next sync. Used by Sansan/MusicPlayer#50.
Endpoints (token required)
POST /api/v1/soundtracks/uploads{"name": "…"}PUT .../uploads/{id}/files/{file}GET .../uploads/{id}POST .../uploads/{id}/finishDELETE .../uploads/{id}Rules
1-01 Title.mp3. A/, also as%2F, gets a 400..mp3files with MP3 content, like the sync.UPLOAD_MAX_FILE_MB(default 50) andUPLOAD_MAX_TOTAL_MB(default 2048).Deploy notes
MUSIC_PATH/.uploads. The sync now skips every hidden folder. Add.uploadsto ResilioSync's ignore list (.sync/IgnoreList) so half-finished uploads are not copied to other devices.Tests
Unit tests for the service and endpoints, OpenAPI response checks, and an integration test against PostgreSQL (upload, duplicate refusal, a sync afterwards changes nothing).
🤖 Generated with Claude Code
A client starts an upload with the soundtrack's name, sends one MP3 per request, and finishes it. The server then moves the songs into a new folder in the music folder and syncs only that folder, so the soundtrack is in the library, lists and search right away. - POST /api/v1/soundtracks/uploads, GET/DELETE .../uploads/{id}, PUT .../uploads/{id}/files/{file} and POST .../uploads/{id}/finish. - Names must work as file names on every system and be free, ignoring case. File names are plain: clients flatten disc folders. - Only MP3 files. Size limits from UPLOAD_MAX_FILE_MB (50) and UPLOAD_MAX_TOTAL_MB (2048). - Refused while a sync runs, and a sync cannot start while an upload is finished. Songs equal to an existing soundtrack's are refused, as the sync would take them for that soundtrack renamed. - Unfinished uploads live in MUSIC_PATH/.uploads and are removed after a day. The sync now skips every hidden folder. Closes #33 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.