Spaces:
Sleeping
Sleeping
File size: 18,944 Bytes
eb1a122 b8fa9bf eb1a122 b8fa9bf eb1a122 b8fa9bf fa35534 b8fa9bf fa35534 b8fa9bf eb1a122 ce84147 eb1a122 b8fa9bf eb1a122 fa35534 eb1a122 ce84147 eb1a122 b8fa9bf eb1a122 b8fa9bf eb1a122 b8fa9bf eb1a122 b8fa9bf 3703c4e 0b5f0f0 3703c4e eb1a122 0b5f0f0 eb1a122 0b5f0f0 eb1a122 3703c4e eb1a122 3703c4e eb1a122 b8fa9bf eb1a122 b8fa9bf eb1a122 fa35534 b8fa9bf fa35534 03d531b e07820e 03d531b e07820e 03d531b e07820e 03d531b e07820e 0b5f0f0 e07820e 03d531b 7f1f066 fa35534 7f1f066 fa35534 7f1f066 fa35534 7f1f066 ab6f318 5a90820 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 | # API documentation
Last updated: 2026-05-12
The active app is `app.py`, a FastAPI application.
## Start server
```bash
uvicorn app:app --host 0.0.0.0 --port 7860
```
## `GET /api/health`
Returns backend health.
```json
{"status":"ok"}
```
## `GET /api/config`
Returns supported models, stems, default pipeline params, stage definitions, and clustering mode labels.
```bash
curl http://127.0.0.1:7860/api/config
```
Important response keys:
| Key | Meaning |
|---|---|
| `separation_backends` | Supported separation engines: `spleeter`, `demucs`, and `none`. |
| `spleeter_models` | Supported Spleeter model profiles. |
| `spleeter_stems` | Valid stems per Spleeter model, plus `all`. |
| `demucs_models` | Supported Demucs model names. |
| `demucs_stems` | Valid stems per Demucs model, plus `all`. |
| `defaults` | Default `PipelineParams`. |
| `stages` | Pipeline stage definitions. |
| `clustering_modes` | Human-readable labels for batch and online clustering modes. |
## `GET /api/jobs`
Lists active in-memory jobs and completed run manifests found under `.runs/`.
```bash
curl http://127.0.0.1:7860/api/jobs?limit=50
```
Response:
```json
{
"active": [],
"history": [
{
"id": "58ca0db4ac74",
"status": "complete",
"filename": "song.wav",
"created_at": 1778540000.0,
"duration_sec": 2.4,
"audio_duration_sec": 8.0,
"realtime_factor": 0.3,
"bpm": 120.0,
"hit_count": 32,
"cluster_count": 8,
"clustering_mode": "online_preview",
"stem": "all",
"error": null
}
]
}
```
`created_at` is the manifest file modification time as a Unix timestamp.
## `POST /api/jobs`
Creates an extraction job.
The endpoint accepts browser-form-style JSON values for numeric and boolean params. For example, `{ "subdivision": "16" }` is coerced to integer `16` before validation. Invalid values return `400` with an actionable `detail` message suitable for direct UI display.
Content type: `multipart/form-data`
Fields:
| Field | Type | Required | Description |
|---|---|---:|---|
| `file` | file | yes | Audio source. |
| `params` | JSON string | no | Partial or full pipeline params. |
Example:
```bash
curl -F 'file=@song.wav' \
-F 'params={"separation_backend":"spleeter","spleeter_model":"spleeter:4stems","stem":"drums","clustering_mode":"online_preview","target_min":4,"target_max":12,"synthesize":true}' \
http://127.0.0.1:7860/api/jobs
```
Response status: `202 Accepted`
Invalid params response example:
```json
{"detail":"Invalid extraction parameter: subdivision must be one of 4, 8, 16, 32, 64"}
```
```json
{
"id": "58ca0db4ac74",
"status": "pending",
"filename": "song.wav",
"params": {"stem": "all", "clustering_mode": "online_preview"},
"stages": [],
"logs": [],
"result": null,
"error": null
}
```
## `GET /api/jobs/{job_id}`
Poll job status and retrieve results. This works for active in-memory jobs and completed historical jobs whose manifest is still present in `.runs/`.
Statuses:
| Status | Meaning |
|---|---|
| `pending` | Job is queued. |
| `running` | Job is executing. |
| `complete` | Result and artifacts are ready. |
| `error` | Pipeline failed; `error` and `traceback` are populated. |
Completed jobs contain:
| Key | Meaning |
|---|---|
| `duration_sec` | Total wall time. |
| `audio_duration_sec` | Duration of processed stem/source. |
| `realtime_factor` | `duration_sec / audio_duration_sec`. |
| `bpm` | Detected tempo. |
| `hit_count` | Number of accepted onsets/hits. |
| `cluster_count` | Number of sample clusters. |
| `stages` | Per-stage timing/status/detail list. |
| `samples` | Representative sample rows with score, duration, first onset, and playback/download URL. |
| `hits` | Per-detected-hit review rows with onset, duration, label, cluster, representative flag, and playback/download URL. |
| `overview` | Decimated envelope and clickable onset markers for waveform display. |
| `files` | Relative artifact paths. Includes `source`, `stem`, `context_bed`, `target_reconstruction`, `reconstruction`, `midi`, and `archive` when available. |
| `file_urls` | Direct API URLs for top-level artifacts. |
## `GET /api/jobs/{job_id}/events`
Streams job snapshots as server-sent events. This is the preferred progress channel for the frontend; polling remains supported via `GET /api/jobs/{job_id}`.
```bash
curl -N http://127.0.0.1:7860/api/jobs/58ca0db4ac74/events
```
Event shape:
```text
event: job
data: {"id":"58ca0db4ac74","status":"running","stages":[...]}
```
The stream closes after `complete` or `error`. Completed historical jobs emit one final `job` event and close.
## Top-level artifact meanings
| Key | Path | Meaning |
|---|---|---|
| `source` | `source.wav` | Normalized source mix used for source preview. |
| `stem` | `stem.wav` | Target stem being sampled. |
| `context_bed` | `context_bed.wav` | Non-target stems/context bed; silent for `stem=all`. |
| `target_reconstruction` | `target_reconstruction.wav` | Sample-triggered reconstruction of only the target stem. |
| `reconstruction` | `reconstruction.wav` | Full-context reproduced mix: context bed plus target reconstruction. |
| `midi` | `reconstruction.mid` | MIDI trigger reconstruction. |
| `archive` | `sample-pack.zip` | Complete sample pack and reproduction artifacts. |
## `GET /api/jobs/{job_id}/files/{relative_path}`
Downloads an artifact from a completed job.
Examples:
```bash
curl -O http://127.0.0.1:7860/api/jobs/58ca0db4ac74/files/sample-pack.zip
curl -O http://127.0.0.1:7860/api/jobs/58ca0db4ac74/files/reconstruction.mid
curl -O http://127.0.0.1:7860/api/jobs/58ca0db4ac74/files/reconstruction.wav
curl -O http://127.0.0.1:7860/api/jobs/58ca0db4ac74/files/target_reconstruction.wav
curl -O http://127.0.0.1:7860/api/jobs/58ca0db4ac74/files/samples/hihat_open_0.wav
curl -O http://127.0.0.1:7860/api/jobs/58ca0db4ac74/files/review/hits/hit_00000_kick.wav
```
The endpoint prevents path traversal by resolving downloads under `.runs/<job-id>/output/` and requiring the final path to remain relative to that output root.
## `POST /api/cache/clear`
Clears the in-memory DSP cache and disk stem/source cache.
```bash
curl -X POST http://127.0.0.1:7860/api/cache/clear
```
Response:
```json
{"status":"cleared","scope":"memory+disk"}
```
## Pipeline parameters
Defined in `pipeline_runner.PipelineParams`.
| Parameter | Default | Meaning |
|---|---:|---|
| `stem` | `drums` | Source/stem to extract, or `all` to bypass source separation. Valid values depend on the selected backend/model. |
| `separation_backend` | `spleeter` | Source-separation engine: `spleeter`, `demucs`, or `none`. |
| `spleeter_model` | `spleeter:4stems` | Spleeter model profile used by the default backend. |
| `demucs_model` | `htdemucs_ft` | Demucs model used when `separation_backend=demucs` or fallback is needed. |
| `demucs_shifts` | `1` | Test-time shifts for Demucs quality/speed tradeoff. |
| `demucs_overlap` | `0.25` | Demucs chunk overlap. |
| `onset_mode` | `auto` | `auto`, `percussive`, `harmonic`, or `broadband`. |
| `onset_delta` | `0.12` | Peak-pick threshold. |
| `energy_threshold_db` | `-35` | RMS gate for accepting hits. |
| `pre_pad` | `0.003` | Seconds of audio before onset. |
| `min_dur` | `0.02` | Minimum hit duration. |
| `max_dur` | `1.5` | Maximum hit duration. |
| `min_gap` | `0.03` | Minimum time between onsets. |
| `ncc_threshold` | `0.80` | Similarity threshold. Also used by online clustering assignment. |
| `attack_ms` | `25` | Transient window used for NCC/prototypes. |
| `mel_threshold` | `0.75` | Candidate prefilter threshold. For online mode, lower values such as `0.62` are useful. |
| `linkage` | `average` | Agglomerative linkage for `batch_quality`. |
| `clustering_mode` | `batch_quality` | `batch_quality` or `online_preview`. |
| `target_min` | `5` | Lower cluster target; `0` disables target mode in batch mode. |
| `target_max` | `20` | Upper cluster target; `0` disables target/cap mode. |
| `synthesize` | `true` | Write synthesized alternates for clusters with multiple hits. |
| `quantize_midi` | `true` | Snap MIDI notes to grid. |
| `subdivision` | `16` | MIDI grid subdivision. |
| `device` | `cpu` | Torch device for Demucs. |
| `use_disk_cache` | `true` | Cache decoded full mix/stems by source digest and extraction settings. |
| `allow_backend_fallback` | `true` | If Spleeter is selected but unavailable/fails, fall back to Demucs instead of failing the job. |
## Sample-card action API
These endpoints back the simplified card workflow in the reference-style UI. They mutate `supervision_state.json` and preserve the original batch manifest.
### `POST /api/jobs/{job_id}/export-selected`
Exports only the currently selected representative sample labels into `selected/` artifacts.
Body:
```json
{"labels":["kick_0","snare_0"],"synthesize":true}
```
Response shape:
```json
{
"export": {
"kind": "selected-sample-export",
"files": {"archive": "selected/sample-pack.zip", "midi": "selected/reconstruction.mid"},
"file_urls": {}
},
"state": {}
}
```
Rules:
- `labels` must contain at least one visible sample label.
- Only selected semantic clusters are rendered.
- Suppressed hits remain excluded.
- Pinned/drawn representatives are honored.
- The export is written under `.runs/<job-id>/output/selected/` and does not mutate the original pack.
### `POST /api/jobs/{job_id}/samples/{sample_label}/draw`
Cycles a card to the next active representative hit in that semantic cluster. The chosen hit is persisted as a representative override, so later selected/all edited exports use the same choice.
Response:
```json
{"sample": {"label": "kick_0", "url": "..."}, "state": {}}
```
### `POST /api/jobs/{job_id}/samples/{sample_label}/edit`
Applies a timing edit to the current representative and rewrites its preview WAV immediately.
Body:
```json
{"start_offset_ms":-8,"tail_offset_ms":24}
```
The backend slices from `stem.wav`, writes `overrides/hits/*_edited.wav`, updates the representative hit in semantic state, and returns a refreshed card row.
## Interactive supervision API
The interactive supervision API is backed by `supervised_state.py` and persists state as:
```text
.runs/<job_id>/output/supervision_state.json
```
The batch `manifest.json` remains immutable. Supervised edits update semantic state and can be rendered into a separate edited export under `supervised/` without mutating original artifacts.
### `GET /api/jobs/{job_id}/state`
Returns the supervised state for a completed job. If the state file does not exist yet, it is created from the batch manifest.
Response keys:
| Key | Meaning |
|---|---|
| `summary` | Counts for hits, clusters, constraints, events, suggestions, suppressed/forced hits, locked clusters, latest export, undo availability. |
| `hits` | Semantic hit rows with confidence, suppression/favorite/review flags, file URLs, and current cluster assignment. |
| `clusters` | Semantic clusters with hit IDs, representative hit, confidence, locked state, and suppressed count. |
| `review_queue` | Low-confidence/high-priority hits sorted for review. |
| `constraints` | Recent replayable constraints. |
| `events` | Recent state mutation events. |
| `suggestions` | Open move/split/suppress suggestions, including exact `diff` previews. |
```bash
curl http://127.0.0.1:7860/api/jobs/<job-id>/state
```
### `POST /api/jobs/{job_id}/hits/force-onset`
Creates a user-forced hit slice from `stem.wav` and adds it to semantic state.
Body:
```json
{
"onset_sec": 0.123,
"duration_ms": 160,
"target_cluster_id": "cluster:0",
"label": "snare"
}
```
Required fields:
| Field | Required | Meaning |
|---|---:|---|
| `onset_sec` | yes | Onset location in seconds. |
| `duration_ms` | no | Slice length. If omitted, the system slices until the next active onset or a bounded default. |
| `target_cluster_id` | no | Existing cluster to place the hit into. If omitted, a new user cluster is created. |
| `label` | no | Override label. If omitted, the rule-based classifier labels the forced slice. |
Effects:
- writes `review/hits/hit_NNNNN_<label>_forced.wav`,
- creates a semantic hit with `source=forced`,
- creates `force-onset` and `force-cluster` constraints,
- appends `hit.force_onset`,
- recomputes confidence and review queue.
### `POST /api/jobs/{job_id}/hits/{hit_id}/restore`
Restores a suppressed hit.
Effects:
- sets `suppressed=false`,
- clears `review_status=suppressed` back to `unreviewed`,
- creates a `restore-hit` constraint,
- appends `hit.restored`,
- recomputes confidence and review queue.
### `POST /api/jobs/{job_id}/export`
Renders the current semantic state into edited artifacts under `supervised/`. This does not modify the original `manifest.json`, original samples, or original ZIP.
Body:
```json
{
"synthesize": true,
"quantize": true,
"subdivision": 16
}
```
Response shape:
```json
{
"export": {
"kind": "supervised-export",
"hit_count": 17,
"cluster_count": 10,
"files": {
"archive": "supervised/sample-pack.zip",
"midi": "supervised/reconstruction.mid",
"target_reconstruction": "supervised/target_reconstruction.wav",
"reconstruction": "supervised/reconstruction.wav"
},
"file_urls": {}
},
"state": {}
}
```
Export rules:
- suppressed hits are excluded,
- forced hits are included,
- moved/pulled hits use current semantic cluster membership,
- favorite/pinned representatives are honored before quality scoring,
- cluster labels are sanitized for filenames,
- `supervision_state.json` receives `latest_export` and a `supervised.exported` event.
### `POST /api/jobs/{job_id}/hits/{hit_id}/move`
Moves a hit into an existing target cluster.
Body:
```json
{"target_cluster_id":"cluster:0"}
```
Effects:
- updates hit membership in `supervision_state.json`,
- creates `force-cluster`,
- creates `must-link` to the target representative when possible,
- appends events,
- recomputes confidence/review queue,
- may create similar-hit move suggestions,
- pushes an undo snapshot.
Example:
```bash
curl -X POST http://127.0.0.1:7860/api/jobs/<job-id>/hits/hit%3A00003/move \
-H 'Content-Type: application/json' \
-d '{"target_cluster_id":"cluster:0"}'
```
### `POST /api/jobs/{job_id}/hits/{hit_id}/pull-out`
Pulls a hit into a new user cluster.
Optional body:
```json
{"label":"snare_user_1"}
```
Effects:
- creates a new `cluster:user:*` cluster,
- creates `cannot-link` from the source representative when possible,
- creates `force-cluster`,
- may create split suggestions,
- pushes an undo snapshot.
### `POST /api/jobs/{job_id}/hits/{hit_id}/suppress`
Marks a hit as bleed/noise/non-sample material.
Body:
```json
{"reason":"bleed"}
```
Effects:
- marks the hit `suppressed`,
- creates `suppress-pattern`,
- may create similar suppression suggestions,
- recomputes confidence and review priority.
### `POST /api/jobs/{job_id}/hits/{hit_id}/review`
Stores a review decision for a hit.
Body:
```json
{"status":"accepted"}
```
Supported statuses:
| Status | Meaning |
|---|---|
| `unreviewed` | Clear explicit review status. |
| `accepted` | Mark the hit as reviewed/accepted. |
| `favorite` | Mark as favorite and pin as semantic representative for its cluster. |
### `POST /api/jobs/{job_id}/clusters/{cluster_id}/lock`
Locks or unlocks a cluster.
Body:
```json
{"locked":true}
```
Lock state is persisted and shown in the cluster board. It does not yet alter future full pipeline reruns.
### `GET /api/jobs/{job_id}/suggestions`
Returns open suggestions and the state summary.
```bash
curl http://127.0.0.1:7860/api/jobs/<job-id>/suggestions
```
### `POST /api/jobs/{job_id}/suggestions/{suggestion_id}/accept`
Applies a suggestion and records accepted constraints/examples.
Supported suggestion types:
- `move-hits`,
- `split-hits`,
- `suppress-hits`.
### `POST /api/jobs/{job_id}/suggestions/{suggestion_id}/reject`
Marks a suggestion rejected and records an event.
### `GET /api/jobs/{job_id}/explain/cluster/{cluster_id}`
Returns explanation data for one cluster:
- label,
- locked state,
- confidence and reasons,
- representative hit,
- hit counts,
- label distribution,
- lowest-confidence outliers,
- relevant constraints,
- summary string.
### `POST /api/jobs/{job_id}/undo`
Restores the previous semantic state snapshot if available.
```bash
curl -X POST http://127.0.0.1:7860/api/jobs/<job-id>/undo
```
## Job progress contract
Every serialized job now includes a top-level `progress` object. The same object is sent through `GET /api/jobs/{job_id}`, `GET /api/jobs`, and `GET /api/jobs/{job_id}/events` job events.
Example:
```json
{
"fraction": 0.1875,
"completed_steps": 1,
"total_steps": 8,
"completed_units": 12.0,
"total_units": 64.0,
"stage_key": "stem",
"stage_label": "Stem separation / source load",
"stage_fraction": 0.5,
"stage_work_done": 4,
"stage_work_total": 8,
"basis": "exact completed work units: Demucs chunks when available; Spleeter and non-instrumented stages advance only at real stage boundaries; no time-based estimates"
}
```
Semantics:
- `fraction` is the completed work-unit fraction used by the UI waveform progress tint.
- `stage_fraction` is the current stage-local progress when known.
- `stage_work_done` and `stage_work_total` are exact work-unit counters when a stage exposes work units.
- Demucs separated-stem extraction exposes exact completed split chunks.
- Spleeter reports coarse start/complete boundaries because the backend does not expose reliable chunk callbacks here.
- Non-instrumented stages update at exact stage boundaries only.
- The API does not provide guessed ETA or interpolated time progress.
## Progressive `partial_samples`
Active/running jobs may include `partial_samples` before `result` is available. These rows are emitted only after the corresponding sample WAV has been written, and they include the same `url` decoration used by final samples.
Final results remain authoritative under `result.samples`.
## `PipelineParams.auto_tune`
`auto_tune` defaults to `true`. When enabled, the pipeline tunes onset sensitivity and group bounds from the loaded target stem before final onset detection. The effective tuned values are returned in the job params/result manifest.
## Upload/runtime fallback update (2026-05-12)
- Added a visible top-bar `Choose audio` affordance in addition to whole-app drag/drop.
- Fixed the default hidden state of the error banner so placeholder errors are not shown on page load.
- API errors now surface request path/status/detail in the visible banner and pipeline logs.
- `/api/config` now includes runtime diagnostics for optional separation backends.
- If Spleeter is unavailable, the simple UI keeps the app usable by switching to full-mix mode; backend fallback also uses full-mix rather than silently launching Demucs.
|