Spaces:
Sleeping
API documentation
Last updated: 2026-05-12
The active app is app.py, a FastAPI application.
Start server
uvicorn app:app --host 0.0.0.0 --port 7860
GET /api/health
Returns backend health.
{"status":"ok"}
GET /api/config
Returns supported models, stems, default pipeline params, stage definitions, and clustering mode labels.
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/.
curl http://127.0.0.1:7860/api/jobs?limit=50
Response:
{
"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:
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:
{"detail":"Invalid extraction parameter: subdivision must be one of 4, 8, 16, 32, 64"}
{
"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}.
curl -N http://127.0.0.1:7860/api/jobs/58ca0db4ac74/events
Event shape:
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:
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.
curl -X POST http://127.0.0.1:7860/api/cache/clear
Response:
{"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:
{"labels":["kick_0","snare_0"],"synthesize":true}
Response shape:
{
"export": {
"kind": "selected-sample-export",
"files": {"archive": "selected/sample-pack.zip", "midi": "selected/reconstruction.mid"},
"file_urls": {}
},
"state": {}
}
Rules:
labelsmust 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:
{"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:
{"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:
.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. |
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:
{
"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-onsetandforce-clusterconstraints, - 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=suppressedback tounreviewed, - creates a
restore-hitconstraint, - 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:
{
"synthesize": true,
"quantize": true,
"subdivision": 16
}
Response shape:
{
"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.jsonreceiveslatest_exportand asupervised.exportedevent.
POST /api/jobs/{job_id}/hits/{hit_id}/move
Moves a hit into an existing target cluster.
Body:
{"target_cluster_id":"cluster:0"}
Effects:
- updates hit membership in
supervision_state.json, - creates
force-cluster, - creates
must-linkto the target representative when possible, - appends events,
- recomputes confidence/review queue,
- may create similar-hit move suggestions,
- pushes an undo snapshot.
Example:
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:
{"label":"snare_user_1"}
Effects:
- creates a new
cluster:user:*cluster, - creates
cannot-linkfrom 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:
{"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:
{"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:
{"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.
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.
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:
{
"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:
fractionis the completed work-unit fraction used by the UI waveform progress tint.stage_fractionis the current stage-local progress when known.stage_work_doneandstage_work_totalare 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 audioaffordance 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/confignow 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.