feat(stt): serve /tasks/audio/transcriptions from the 51-language ASR model#241
Merged
Conversation
Replace the Modal/RunPod dispatch behind POST /tasks/audio/transcriptions with Sunbird's faster-whisper ASR deployment (Sunbird/faster-whisper-51-african-languages), expanding coverage from 10 to 51 African languages. All ten previously supported languages remain. The deployment is OpenAI-compatible and maps Sunbird ISO 639-3 codes to Whisper's language-token slots server-side, so codes are forwarded verbatim. Because the fine-tune reuses those slots, auto-detection is unreliable and `language` stays required. BREAKING CHANGE: the endpoint no longer accepts `platform`, `adapter`, `whisper`, `recognise_speakers`, `org`, or `gcs_blob_name`; they now return 422. Speaker diarization and the organization workflow remain available on the deprecated /tasks/stt* routes. - add ASRService (app/services/asr_service.py) wrapping the deployment, mapping HTTP/timeout/connection/parse failures to ExternalServiceError - add ASR_BASE_URL, ASR_MODEL_NAME and ASR_TIMEOUT_SECONDS settings; promote RUNPOD_API_KEY to a Settings field and document all four in .env.example. ASR_BASE_URL has no working default and must be set. - add ASRLanguage (51 codes) and TranscriptionSegment; STTTranscript gains optional `segments` (via timestamps=true) and `duration_seconds` - retire TranscriptionService, which existed only to dispatch across the removed platforms - update app/docs.py, docs/tutorial.md and the React Tutorial page with the full 51-language list and the breaking-change notice Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Replaces the Modal/RunPod dispatch behind
POST /tasks/audio/transcriptionswith Sunbird's faster-whisper ASR deployment (Sunbird/faster-whisper-51-african-languages, a Whisper large-v3 fine-tune), taking the endpoint from 10 to 51 African languages.The 51-code list was taken from
language_map.jsonin the converted repo rather than the prose model card. All ten previously supported languages (ach teo eng lug lgg nyn swa kin xog myx) are still served — no language regresses.The deployment is OpenAI-compatible and maps Sunbird ISO 639-3 codes to Whisper's language-token slots server-side, so codes are forwarded verbatim. Because the fine-tune reuses those slots, auto-detection is meaningless and
languagestays required.The endpoint no longer accepts
platform,adapter,whisper,recognise_speakers,org, orgcs_blob_name— these now return422. Speaker diarization and the organization workflow remain available on the deprecated/tasks/stt*routes.New contract:
ASR_BASE_URLmust be set in Cloud Run before this ships. It has no working default — the fallback is a literal<ENDPOINT_ID>placeholder, so an unconfigured deploy fails at request time, not at boot. It must include the trailing/v1. Auth reuses the existingRUNPOD_API_KEY.ASR_MODEL_NAME(sunbird-asr-51) andASR_TIMEOUT_SECONDS(600, generous for cold starts) are optional.Changes
app/services/asr_service.pyASRService— httpx client for the deployment; maps HTTP/timeout/connection/parse failures toExternalServiceError.app/core/config.pyasr_base_url,asr_model_name,asr_timeout_seconds; promotesRUNPOD_API_KEYto a real Settings field.app/schemas/stt.pyASRLanguage(51 codes),ASR_LANGUAGE_NAMES,TranscriptionSegment.STTTranscriptgainssegments+duration_seconds.SttbLanguageuntouched for the legacy routes.app/routers/audio.pyapp/deps.pyTranscriptionServiceDep→ASRServiceDep.app/services/transcription_service.py.env.example,app/docs.py,docs/tutorial.md,frontend/src/pages/Tutorial.tsxTwo behavioural notes:
audio_urlis ags://URI (matching what the legacy RunPod path returned, not a signed HTTPS URL), and the GCS upload is best-effort — if it fails, transcription still succeeds withaudio_url/audio_transcription_idasnull.Test plan
pytest app/tests/— 1189 passed. 6 failures intest_config.py/test_inference_service.pyreproduce on a cleangit stash: pre-existing, caused by a local.envleaking intoSettings.test_asr_service.py(12 tests, mocked httpx transport: request shape, verbose_json/segments, language fallback, HTTP/timeout/connection/malformed-body error mapping, health check).test_audio_transcriptions.pyrewritten — new contract, removed-param rejection, segments on/off, 51-code enum, upstream-error → 502.make lint-check— black/isort clean; only pre-existingnode_modules/flattedE722 remains.npm run build(incl.tsc) passes.npm run lint— pre-existing breakage, ESLint 10.5.0 installed against an.eslintrc.*config (v9+ requireseslint.config.js). Unrelated to this PR; no JS dependencies added.ASR_BASE_URLpointed at a running worker.npm auditreports 8 pre-existing vulnerabilities (3 high,vite/launch-editor); the fix is a breakingvite@8major, left for a separate PR.🤖 Generated with Claude Code