feat(sync): add AsyncSyncTranscriber for asyncio callers - #229
Conversation
Live parity test: threading vs asyncioRan a side-by-side comparison of Scenarios (threading side also covers the
Transcript text, word texts, and word timestamps were identical between the two wrappers in every run (3 consecutive full passes). One non-SDK observation surfaced while testing: word/overall confidence values can jitter in the 4th–5th decimal place (observed deltas 4.6e-05 to 7.3e-04) when requests are in flight concurrently. This was isolated to the server, not the wrapper: two identical concurrent requests through the same threading wrapper showed the same drift, while sequential requests were bit-for-bit deterministic every time — consistent with dynamic batching in the inference backend. The comparison treats confidences as equal within a 0.01 tolerance for that reason; text, words, and timestamps compare exactly. 🤖 Generated with Claude Code |
The asyncio counterpart of SyncTranscriber: same input types, config, result, and errors, with transcribe() and warm() as coroutines. Reuses the sync/v1 base (_resolve_audio, _config_to_json, error mapping) and follows the AsyncClient ownership pattern from prerecorded/v2 — owns its HTTP pool by default, leaves a passed-in AsyncClient alone. Path and file-object reads run off the event loop. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Both sync-product exports now come from the canonical sync/v1 module; the sync/__init__.py shim stays for backwards-compatible imports only. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The 0.66.00 slot was taken by the LeMUR removal (#228) this branch is now rebased onto. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
780e197 to
2ad7961
Compare
Summary
Adds
aai.AsyncSyncTranscriber, the asyncio counterpart ofSyncTranscriber, closing the gap where the sync product was the only wrapper without an asyncio implementation (prerecorded hasTranscriber/AsyncTranscriber, streaming hasStreamingClient/AsyncStreamingClient).sync/v1/async_api.py—httpx.AsyncClienttwin ofapi.py'stranscribe(); reuses the endpoint constants and_error_from_response, so error mapping (problem-details envelope,retry_after, legacy envelopes) stays shared.sync/v1/async_client.py—AsyncSyncTranscriberwith coroutinetranscribe()/warm(). Same input types (path/bytes/file object — no URLs), sameSyncTranscriptionConfig,SyncTranscriptResponse, andSyncTranscriptError. Reuses the existing_base.pyhelpers; path and file-object reads run off the event loop.AsyncTranscriber: owns an HTTP pool by default (async with/aclose()), or shares a passed-inaai.AsyncClient, which stays the caller's to close. Notranscribe_async()— fan-out is plainasyncio.gather.sync/v1and the top-level package; thesync/__init__.pyshim stays backwards-compat-only.test_sync.pyplus async-lifecycle cases; README and CLAUDE.md updated (both previously documented this class as a planned follow-up).AsyncTranscriber.Test plan
pytest tests/unit— full suite green (only pre-existing pyaudio-missing extras failures)ruff check+ruff format --checkclean on changed files with CI-pinned 0.3.5🤖 Generated with Claude Code