Spaces:
Sleeping
Sleeping
Hit review and progress streaming
Last updated: 2026-05-12
Purpose
This pass moves the app closer to a review workstation by making detected hits individually inspectable and by replacing frontend-only polling with a server-sent-events progress channel.
Implemented behavior
| Area | Implementation | Files |
|---|---|---|
| Review hit artifacts | Every accepted detected hit is written as an individual WAV under review/hits/. |
pipeline_runner.py |
| Manifest hit rows | manifest.json now includes a top-level hits array with onset, duration, label, cluster, representative flag, and relative file path. |
pipeline_runner.py |
| Hit URLs | API serialization adds direct download/playback URLs to every hit row. | app.py |
| Waveform selection | Clicking the waveform selects the nearest detected onset marker. | web/app.js |
| Hit audition | Clicking a hit row or waveform marker loads that hit into the selected-hit audio player. | web/index.html, web/app.js |
| Sample audition | Representative sample rows now have explicit Audition buttons and a dedicated selected-sample player. | web/index.html, web/app.js |
| SSE progress | GET /api/jobs/{job_id}/events streams job snapshots whenever state changes. |
app.py, web/app.js |
| Poll fallback | The frontend falls back to polling if EventSource is unavailable or errors. |
web/app.js |
| Artifact serving hardening | File downloads now use Path.relative_to() against the resolved run output directory. |
app.py |
Manifest shape additions
Completed results now include:
{
"hits": [
{
"index": 0,
"label": "kick",
"cluster_id": 3,
"cluster_label": "kick_0",
"is_representative": true,
"onset_sec": 0.002993,
"duration_ms": 255.0,
"rms_energy": 0.141768,
"spectral_centroid_hz": 773.4,
"file": "review/hits/hit_00000_kick.wav"
}
]
}
API responses add url to each hit row, for example:
{
"file": "review/hits/hit_00000_kick.wav",
"url": "/api/jobs/<job-id>/files/review/hits/hit_00000_kick.wav"
}
The overview.onsets entries now also carry index and duration_sec, allowing the waveform to map markers back to review hit rows.
Streaming endpoint
GET /api/jobs/{job_id}/events returns text/event-stream.
Each emitted event has type job and contains the same serialized shape as GET /api/jobs/{job_id}:
event: job
data: {"id":"...","status":"running",...}
The stream ends after complete or error. Completed historical jobs stream one final event and then close.
Current limitations
- Hit review is read-only. It does not yet support delete/shift/relabel actions.
- Every accepted hit is exported as a WAV. This is correct for review UX, but large files with thousands of hits may produce many small artifacts.
- SSE streams job snapshots, not fine-grained internal Demucs progress.
- The waveform is an overview canvas, not an editable detailed waveform yet.
Next editor step
Add an edit state layer on top of the hit manifest:
- Mark hit deleted/restored.
- Shift onset and duration bounds.
- Reassign cluster label.
- Merge/split clusters.
- Re-render/repack from edited manifest without rerunning Demucs or onset detection.