Skip to content

feat(server): expose transcription progress via GET /progress - #408

Merged
CrispStrobe merged 2 commits into
CrispStrobe:mainfrom
tilllt:feat/server-progress
Aug 29, 2026
Merged

CrispStrobe merged 2 commits into
CrispStrobe:mainfrom
tilllt:feat/server-progress

Conversation

@tilllt

@tilllt tilllt commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Description

Adds a pollable progress endpoint to the HTTP server. While a job runs, do_transcribe updates a server-side progress value (0..100) in its chunk loop; GET /progress returns {"busy": bool, "progress": -1..100} (-1 = idle).

Motivation

Long-running jobs (ASR transcription, speaker diarization, and every other backend that flows through the chunk loop in do_transcribe) are submitted as a single synchronous POST. The server previously had no progress channel over HTTP — the whisper progress callback only printed to stderr, so clients could only show a heartbeat. With /progress, any client can poll honest 0..100 progress for the active job.

What it covers

  • ASR transcription — chunk-loop progress, 0..100.
  • Speaker diarization and other backends routed through the same server path — the endpoint is backend-agnostic and reports whatever the active job is doing.
  • Idle state{"busy": false, "progress": -1} when no job is running.

Design notes

  • One job per container today, so a single pair of atomics is honest. With --server-workers concurrency this needs per-request scoping — flagged as future work in the code comment.
  • A progress_scope guard resets busy/progress on every exit path (including error returns).

Verification

  • Built locally (ggml native, parakeet-tdt backend) — clean build.
  • Smoke-tested: /health ok, /progress idle {"busy": false, "progress": -1}, and during a transcription {"busy": true, "progress": 0..100}.
  • CI on the fork has not been exercised yet; the change is a single-file additive server change.

Drafted with assistance from an AI agent (Hermes) on behalf of the contributor.

Adds a pollable progress endpoint to the HTTP server: while a
transcription runs, do_transcribe updates g_server_progress (0..100)
in its chunk loop; GET /progress returns {"busy": bool, "progress": -1..100}.

Motivation: long-running jobs (ASR transcription, speaker diarization,
and other backends routed through the same server path) are submitted
as a single synchronous POST; the server previously had no progress
channel over HTTP (the whisper progress callback only printed to stderr).

Notes:
- One job per container today, so a single atomic is honest; with
  --server-workers concurrency this needs per-request scoping (future work).
- progress_scope guard resets busy/progress on every exit path.
@tilllt
tilllt force-pushed the feat/server-progress branch from 60f9206 to 7031685 Compare August 28, 2026 21:44
Fixes the clang-format (style) lint check in PR CI: alignment of the
atomic globals, brace layout of progress_scope, and comment spacing
in the chunk loop and GET /progress handler.
CrispStrobe pushed a commit that referenced this pull request Aug 29, 2026
#408 GET /progress:
- progress_scope moved INSIDE the model-mutex block: a request queued
  behind a running job used to reset the live job's progress to 0, and
  whichever job finished first flipped the server 'idle' while the other
  still ran
- busy is an active-job counter, so it stays honest under --server-workers
- the chunk loop claims a chunk when it STARTS (i, not i+1, which read 100
  while the last chunk was still decoding) and pins 100 through the
  diarize/punc/truecase tail
- route auth-gated like /backends (/health stays the public probe)
- docs/server.md section + tests/test-server-progress.sh integration test
  (idle/busy/reset contract + auth), registered as a live test

#406 SIMDCONV:
- chatterbox gate uses core_cpu_backend::is_cpu() instead of the
  backend==backend_cpu pointer compare (the parakeet pick_backend lesson:
  the compare can read GPU under --no-gpu and silently keep the feature
  off on the machines it exists for)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0138mFhGiCzAwiNqdtwtq439
@CrispStrobe
CrispStrobe merged commit 7881ba6 into CrispStrobe:main Aug 29, 2026
30 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants