Spaces:
Sleeping
Sleeping
| # 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. | |