This commit adds word boundary support to AzureTTSService and fixes
the race condition that causes scrambled TTS output across multiple
sentences.
## Features Added
- Change AzureTTSService to inherit from WordTTSService
- Subscribe to Azure SDK's synthesis_word_boundary event
- Emit word-level text with timing information via _words_queue
- Add synthesis lock for sequential sentence processing
## Race Condition Fix
Previously, each sentence's word boundary timestamps reset to 0,
causing downstream components to interleave words when reordering
frames by PTS. This resulted in scrambled output like:
'Hello ! I What am questions AI have assistant...'
The fix adds cumulative audio offset tracking to ensure monotonically
increasing PTS across all sentences:
Sentence 1: pts = 0.1s, 0.5s, 0.8s (cumulative at end: 0.8s)
Sentence 2: pts = 0.9s, 1.2s, 1.5s (0.8s + relative offset)
## Key Changes
- _cumulative_audio_offset: tracks total audio duration
- _handle_word_boundary: adds cumulative offset to timestamps
- _handle_completed: accumulates audio duration for next sentence
- flush_audio: resets cumulative offset at end of LLM response
- _handle_interruption: resets state on user interruption
- run_tts: uses synthesis lock for sequential processing
Fixes#2918🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>