Expose initial_prompt and vad_parameters as flat client parameters
(consistent with hotwords, send_last_n_segments, etc.), send them as
flat handshake keys, and read them server-side with null-safe
options.get(...). Supersedes #283; avoids the options-bag None.get crash.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- New params: max_retries (default 0), retry_delay (default 5s)
- On unexpected close, retries up to max_retries times
- Does not retry on server_error (server rejected connection)
- Extracted _create_websocket() helper for reuse
- Added 4 unit tests for reconnect behavior
MagicMock auto-attributes are not JSON serializable. Set language,
language_probability, and duration explicitly. Also exclude metadata
events from segment count assertion.
- stream=true now returns text/event-stream with per-segment SSE events
- Each segment yields 'data: {json}' followed by 'data: [DONE]'
- Error events streamed as 'data: {"error": ...}'
- Temp files cleaned up in finally block
- 5 new tests in test_server_extended.py (183 total passing)
Add a minimal, non-breaking hook to WhisperLive that allows external
projects to post-process transcription segments before they are sent
to the client.
Changes:
- ServeClientBase: add segment_post_processor attribute (default None)
- ServeClientBase.send_transcription_to_client: apply post_processor
per-segment with error handling (falls back to original segment)
- TranscriptionServer: add segment_post_processor parameter to run()
and wire it to each client on creation
This enables downstream projects to plug in custom processing
(e.g. formatting, PII redaction, diarization tagging) without
modifying WhisperLive core code.
- New word_timestamps option (default False) in client handshake
- When enabled, each segment includes 'words' array with per-word
start/end times and probability scores
- Wired through entire pipeline: client → server → backend → transcribe()
- Words include timestamp_offset for accurate absolute times
- REST API already supported word timestamps; now WebSocket does too
- Added 9 unit tests for word timestamp extraction and formatting
- New whisper_live/diarization.py: SpeakerDiarizer with online clustering
- Uses pyannote.audio speaker embeddings (optional dependency)
- Cosine similarity threshold for speaker matching (default 0.55)
- Running average embedding update for speaker stability
- Configurable max_speakers limit (default 10)
- Client options: enable_diarization, max_speakers
- Segments include 'speaker' field when diarization is active
- Graceful fallback: logs warning if pyannote not installed
- Added 12 unit tests (mock-based, no GPU required)
- New whisper_live/metrics.py with Counter, Gauge, Histogram metrics
- Track connections (opened/closed/rejected), transcription latency,
audio processed, segments emitted, REST requests, and errors
- All metric helpers are no-ops when prometheus_client not installed
- --metrics_port CLI flag to expose /metrics endpoint (0 = disabled)
- Metrics integrated into server.py, base.py at key instrumentation points
- 17 new tests in tests/test_metrics.py (178 total passing)
- MAX_BUFFER_DURATION_S (45): max audio buffer before trimming
- BUFFER_TRIM_DURATION_S (30): duration to discard on trim
- CLIP_THRESHOLD_DURATION_S (25): stale audio clip threshold
- CLIP_TAIL_DURATION_S (5): audio tail to keep after clipping
- All values can now be overridden by subclasses
- max_clients must be >= 1
- max_connection_time must be > 0
- batch_max_size must be >= 1 (when batch enabled)
- batch_window_ms must be >= 0 (when batch enabled)
- Added 5 new tests for parameter validation
- Add MAX_TRANSCRIPT_LENGTH (500) and MAX_TRANSLATION_QUEUE_SIZE (100)
class constants to ServeClientBase
- Trim transcript and text lists after each update_segments() call
- Create translation queue with maxsize to prevent unbounded growth
- Added tests for _trim_transcript()
- All ClientManager methods (add_client, get_client, remove_client,
get_wait_time, is_server_full, is_client_timeout) now protected by
a threading.Lock
- cleanup() called outside the lock to avoid holding it during I/O
- is_server_full() computes wait time inline under lock instead of
calling get_wait_time() to avoid nested lock acquisition
- Added concurrent thread safety tests for add/remove and get operations
When VAD removes all speech from an audio chunk, transcriber.transcribe() returns (None, info). Calling list(None) raises TypeError. The _process_multi path already handles this case; this aligns _process_single to match.
Replace hardcoded [-4:] truncation with a configurable display_segments
parameter (default: 4) in both Client and TranscriptionClient classes.
Fixes#377
Add `--enable-timestamps` option to `run_client.py`
script to print out transcripted text with timestamps.
Sample output with translation enabled:
```
[0.000 -> 7.440] And so, my fellow Americans, ask not what your country can do for you.
[7.440 -> 10.300] Ask what you can do for your country.
TRANSLATION to fr:
[0.000 -> 7.440] Et donc, mes camarades américains, ne demandez pas ce que votre pays peut faire pour vous.
[7.440 -> 10.300] Demandez ce que vous pouvez faire pour votre pays.
```
Signed-off-by: Jeny Sadadia <jeny.sadadia@collabora.com>
Previously, the server only accepted local file paths for custom Faster Whisper
models. This change allows passing HuggingFace repo IDs which are automatically
downloaded and converted to CTranslate2 format by the backend if not already in
CTranslate2 format.
Signed-off-by: makaveli10 <vineet.suryan@collabora.com>
Translate from any language to any language with alirezamsh/small100
running in a thread and reading from a queue shared with transcription thread.
Signed-off-by: makaveli10 <vineet.suryan@collabora.com>