# matrx_ai.providers.eleven_labs — Module Overview


## IMPORTANT: Do not edit auto-generated sections.

> This document is partially auto-generated. Sections tagged `<!-- AUTO:id -->` are refreshed by the generator.
> Everything else is yours to edit freely and will never be overwritten.

<!-- AUTO:meta -->
## About This Document

This file is **partially auto-generated**. Sections wrapped in `<!-- AUTO:id -->` tags
are overwritten each time the generator runs. Everything else is yours to edit freely.

| Field | Value |
|-------|-------|
| Module | `packages/matrx-ai/matrx_ai/providers/eleven_labs` |
| Last generated | 2026-08-08 08:51 |
| Output file | `packages/matrx-ai/matrx_ai/providers/eleven_labs/MODULE_README.md` |
| Signature mode | `signatures` |

**To refresh auto-sections:**
```bash
python utils/code_context/generate_module_readme.py packages/matrx-ai/matrx_ai/providers/eleven_labs --mode signatures
```

**To add permanent notes:** Write anywhere outside the `<!-- AUTO:... -->` blocks.
<!-- /AUTO:meta -->

<!-- HUMAN-EDITABLE: This section is yours. Agents & Humans can edit this section freely — it will not be overwritten. -->

## Architecture

> **Fill this in.** Describe the execution flow and layer map for this module.
> See `utils/code_context/MODULE_README_SPEC.md` for the recommended format.
>
> Suggested structure:
>
> ### Layers
> | File | Role |
> |------|------|
> | `entry.py` | Public entry point — receives requests, returns results |
> | `engine.py` | Core dispatch logic |
> | `models.py` | Shared data types |
>
> ### Call Flow (happy path)
> ```
> entry_function() → engine.dispatch() → implementation()
> ```


<!-- AUTO:tree -->
## Directory Tree

> Auto-generated. 7 files across 1 directories.

```
packages/matrx-ai/matrx_ai/providers/eleven_labs/
├── MODULE_README.md
├── __init__.py
├── client.py
├── direct_dialogue.py
├── elevenlabs_api.py
├── pronunciation_dict.py
├── tts_streaming.py
# excluded: 2 .md
```
<!-- /AUTO:tree -->

<!-- AUTO:signatures -->
## API Signatures

> Auto-generated via `output_mode="signatures"`. ~5-10% token cost vs full source.
> For full source, open the individual files directly.

```
---
Filepath: packages/matrx-ai/matrx_ai/providers/eleven_labs/client.py  [python]

  def get_elevenlabs_client() -> ElevenLabs


---
Filepath: packages/matrx-ai/matrx_ai/providers/eleven_labs/__init__.py  [python]



---
Filepath: packages/matrx-ai/matrx_ai/providers/eleven_labs/elevenlabs_api.py  [python]

  class ElevenLabsChat:
      def __init__(self) -> None
      async def execute(self, unified_config: UnifiedConfig, profile: ResolvedCallProfile, debug: bool = False) -> UnifiedResponse
      async def _build_locators(unified_config: UnifiedConfig) -> list
      async def _execute_tts(self, unified_config: UnifiedConfig, profile: ResolvedCallProfile, emitter: Emitter, matrx_model_name: str) -> UnifiedResponse
  def _run_batch(turns: list[dict]) -> bytes


---
Filepath: packages/matrx-ai/matrx_ai/providers/eleven_labs/direct_dialogue.py  [python]

  AUDIO_DIR = settings.temp_dir / 'audio'
  MAX_CHARS = 4800
  def _unique_audio_path(stem: str = 'dialogue') -> Path
  def save_audio(audio_bytes: bytes, output_path: str | Path | None = None) -> Path
  def _chunk_inputs(dialogue_inputs: list[dict]) -> list[list[dict]]
  def _collect_stream(audio_stream) -> bytes
  async def get_audio_bytes(dialogue_inputs: list[dict]) -> bytes
  def stream_audio(dialogue_inputs: list[dict]) -> bytes
  async def main(play_type: Literal['real_time', 'save_to_file'] = 'save_to_file', dialogue_inputs: list[dict] = None) -> None
  def tee_stream(source)


---
Filepath: packages/matrx-ai/matrx_ai/providers/eleven_labs/tts_streaming.py  [python]

  MIN_FLUSH_CHARS = 100
  MAX_BUFFER_CHARS = 300
  AUDIO_DIR = settings.temp_dir / 'audio'
  def _get_sync_client() -> ElevenLabs
  def _unique_audio_path(stem: str = 'tts') -> Path
  def _split_on_sentence_boundary(text: str, min_chars: int = MIN_FLUSH_CHARS) -> tuple[str, str]
  def _tts_worker(chunk_queue: queue.Queue, model_id: str, collected: list[bytes]) -> None
  async def play_and_save_tagged_stream(tagged_stream: AsyncIterator[str | tuple[str, str]], *, model_ref: str, voice_id: str | None = None, cycle_voices: list[str] | None = None, stem: str = 'tts') -> Path
  async def save_streamed_audio(tagged_stream: AsyncIterator[str | tuple[str, str]], *, model_ref: str, voice_id: str | None = None, cycle_voices: list[str] | None = None, stem: str = 'tts') -> Path
  async def _mock_tagged_stream(reasoning: str, content: str, voice_id: str, token_delay: float = 0.03) -> AsyncGenerator[tuple[str, str]]
  def _current_voice() -> str
  def _advance() -> None
  def enqueue(text: str, vid: str) -> None
  async def _demo() -> None
  def tee(source)


---
Filepath: packages/matrx-ai/matrx_ai/providers/eleven_labs/pronunciation_dict.py  [python]

  def _api_key() -> str
  def _headers() -> dict[str, str]
  def entries_to_rules(entries: list[dict[str, Any]]) -> list[dict[str, Any]]
  def rule_strings(rules: list[dict[str, Any]]) -> list[str]
  def canonical_hash(rules: list[dict[str, Any]]) -> str
  async def create_from_rules(name: str, rules: list[dict[str, Any]]) -> dict[str, str]
  async def add_rules(dictionary_id: str, rules: list[dict[str, Any]]) -> dict[str, str]
  async def remove_rules(dictionary_id: str, strings: list[str]) -> dict[str, str]
  def _add(rule: dict[str, Any]) -> None
```
<!-- /AUTO:signatures -->

<!-- AUTO:callers -->
## Upstream Callers

> Auto-discovered by scanning all project files that import from this module.
> Set `ENTRY_POINTS` in `generate_readme.py` to pin specific functions.

| Caller | Calls |
|--------|-------|
| `matrx_ai/providers/generic_openai/test_huggingface.py` | `save_streamed_audio()` |
<!-- /AUTO:callers -->

<!-- AUTO:dependencies -->
## Dependencies

**External packages:** dotenv, elevenlabs, httpx, matrx_ai, matrx_connect, matrx_utils
<!-- /AUTO:dependencies -->

<!-- AUTO:config -->
## Generation Config

> Auto-managed. Contains the exact parameters used to generate this README.
> Used by parent modules to auto-refresh this file when it is stale.
> Do not edit manually — changes will be overwritten on the next run.

```json
{
  "subdirectory": "packages/matrx-ai/matrx_ai/providers/eleven_labs",
  "mode": "signatures",
  "scope": null,
  "project_noise": null,
  "include_call_graph": false,
  "entry_points": null,
  "call_graph_exclude": null
}
```
<!-- /AUTO:config -->

<!-- AUTO:call_graph -->
## Call Graph

> Auto-generated. All Python files.
> Shows which functions call which. `async` prefix = caller is an async function.
> Method calls shown as `receiver.method()`. Private methods (`_`) excluded by default.

### Call graph: packages.matrx-ai.matrx_ai.providers.eleven_labs.client

```
Global Scope → packages.matrx-ai.matrx_ai.providers.eleven_labs.client.load_dotenv() (line 6)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.client.get_elevenlabs_client → packages.matrx-ai.matrx_ai.providers.eleven_labs.client.resolve_api_key('ELEVENLABS_API_KEY') (line 15)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.client.get_elevenlabs_client → _clients.get(api_key) (line 16)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.client.get_elevenlabs_client → packages.matrx-ai.matrx_ai.providers.eleven_labs.client.ElevenLabs() (line 18)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.client.get_elevenlabs_client → _clients.clear() (line 19)
```

### Call graph: packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api

```
packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api.__init__ → packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api.get_elevenlabs_client() (line 37)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api.execute → packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api.get_app_context() (line 47)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api.execute → packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api.classify_elevenlabs_error(e) (line 57)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._build_locators → packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api.get_pronunciation_locator_resolver() (line 71)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._build_locators → packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api.get_app_context() (line 75)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._build_locators → packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api.resolver() (line 76)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._build_locators → item.get('pronunciation_dictionary_id') (line 87)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._build_locators → item.get('version_id') (line 88)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._build_locators → out.append(PronunciationDictionaryVersionLocator(pronunciation_dictionary_id=pid, version_id=vid)) (line 90)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._build_locators → packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api.PronunciationDictionaryVersionLocator() (line 91)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._execute_tts → lower() (line 112)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._execute_tts → mime_map.get(codec, 'audio/mpeg') (line 122)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._execute_tts → packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api.validate_tts_voices(profile, [turn.voice_id for turn in tts.dialogue_turns]) (line 128)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._execute_tts → packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api.resolve_tts_voice(profile, tts._primary_voice()) (line 130)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._execute_tts → tts.to_elevenlabs() (line 135)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._execute_tts → text_parts.append(c.text) (line 142)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._execute_tts → strip() (line 143)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._execute_tts → join(text_parts) (line 143)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._execute_tts → tts.strip_speaker_labels(input_text) (line 144)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._execute_tts → tts.to_elevenlabs() (line 145)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._execute_tts → DictionaryConfig.coerce(unified_config.dictionary) (line 157)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._execute_tts → _turn.get('text') (line 162)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._execute_tts → packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api.apply_tts_dictionary(_dconf, _t) (line 164)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._execute_tts → emitter.send_info(InfoPayload(code='tts_generating', system_message=f'Generating audio ({sum((len(b) for b in batched_inputs))} dialogue turns)...', user_message='Generating audio...')) (line 174)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._execute_tts → packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api.InfoPayload() (line 175)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._execute_tts → emitter.send_info(InfoPayload(code='tts_batch_progress', system_message=f'Processing batch {batch_num}/{total_batches}...', user_message=f'Generating audio part {batch_num} of {total_batches}...')) (line 220)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._execute_tts → packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api.InfoPayload() (line 221)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._execute_tts → packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api.stamp_call_meta() (line 228)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._execute_tts → packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api.emit_explicit_context_analysis() (line 235)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._run_batch → ...stream() (line 257)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._run_batch → join((chunk for chunk in audio_stream if isinstance(chunk, bytes))) (line 258)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._run_batch → ...stream() (line 270)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._run_batch → join((chunk for chunk in turn_stream if isinstance(chunk, bytes))) (line 271)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._execute_tts → run_in_executor(None, _run_batch, batch) (line 274)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._execute_tts → asyncio.get_event_loop() (line 274)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._execute_tts → emitter.send_info(InfoPayload(code='tts_saving', system_message=f'Audio received ({len(all_audio_bytes):,} bytes). Saving...', user_message='Audio received. Saving...')) (line 281)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._execute_tts → packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api.InfoPayload() (line 282)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._execute_tts → first_input.get('voice_id') (line 303)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._execute_tts → strip() (line 313)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._execute_tts → join((t.get('text', '') for b in batched_inputs for t in b)) (line 313)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._execute_tts → t.get('text', '') (line 313)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._execute_tts → packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api.map_elevenlabs_audio_response() (line 315)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._execute_tts → packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api.save_media_envelope_async() (line 327)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._execute_tts → gen_meta.model_dump() (line 335)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._execute_tts → packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api.AudioContent() (line 339)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._execute_tts → gen_meta.model_dump() (line 345)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._execute_tts → packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api.UnifiedMessage() (line 347)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._execute_tts → packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api.build_character_billed_usage_async() (line 354)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._execute_tts → packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api.UnifiedResponse() (line 361)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._execute_tts → gen_meta.model_dump() (line 378)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._execute_tts → emitter.send_data(MediaBlockData(block=cloud_file_to_media_block(synthetic_record, url_set=url_set, kind_override='audio'))) (line 387)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._execute_tts → packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api.MediaBlockData() (line 388)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._execute_tts → packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api.cloud_file_to_media_block(synthetic_record) (line 389)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.elevenlabs_api._execute_tts → asyncio.sleep(0) (line 396)
```

### Call graph: packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue

```
Global Scope → packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue.get_ext('settings') (line 11)
  Global Scope → AUDIO_DIR.mkdir() (line 14)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue._unique_audio_path → strftime('%Y%m%d_%H%M%S_%f') (line 18)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue._unique_audio_path → datetime.now() (line 18)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue.save_audio → packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue.Path(output_path) (line 23)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue.save_audio → packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue._unique_audio_path() (line 23)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue.save_audio → ...mkdir() (line 24)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue.save_audio → packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue.open(path, 'wb') (line 25)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue.save_audio → f.write(audio_bytes) (line 26)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue._chunk_inputs → turn.get('text', '') (line 40)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue._chunk_inputs → batches.append(current) (line 42)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue._chunk_inputs → current.append(turn) (line 45)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue._chunk_inputs → batches.append(current) (line 48)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue.get_audio_bytes → packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue.get_elevenlabs_client() (line 61)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue.get_audio_bytes → packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue._chunk_inputs(dialogue_inputs) (line 62)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue.get_audio_bytes → t.get('text', '') (line 65)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue.get_audio_bytes → ...stream() (line 66)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue.get_audio_bytes → packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue._collect_stream(audio_stream) (line 67)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue.stream_audio → packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue.get_elevenlabs_client() (line 72)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue.stream_audio → packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue._chunk_inputs(dialogue_inputs) (line 73)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue.stream_audio → t.get('text', '') (line 76)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue.stream_audio → ...stream() (line 77)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue.stream_audio → packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue.play_stream(tee_stream(audio_stream)) (line 87)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue.stream_audio → packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue.tee_stream(audio_stream) (line 87)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue.main → packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue.stream_audio(dialogue_inputs) (line 94)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue.main → packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue.save_audio(audio_bytes) (line 95)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue.main → packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue.get_audio_bytes(dialogue_inputs) (line 97)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue.main → packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue.save_audio(audio_bytes) (line 98)
  Global Scope → asyncio.run(main(play_type='real_time', dialogue_inputs=english_sample)) (line 397)
  Global Scope → packages.matrx-ai.matrx_ai.providers.eleven_labs.direct_dialogue.main() (line 397)
```

### Call graph: packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming

```
Global Scope → packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.get_ext('settings') (line 46)
  Global Scope → re.compile('[.!?…]\\s*') (line 48)
  Global Scope → AUDIO_DIR.mkdir() (line 53)
  Global Scope → packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.object() (line 55)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming._get_sync_client → packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.load_dotenv() (line 68)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming._get_sync_client → packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.ElevenLabs() (line 69)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming._get_sync_client → packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.resolve_api_key('ELEVENLABS_API_KEY') (line 69)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming._unique_audio_path → strftime('%Y%m%d_%H%M%S_%f') (line 73)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming._unique_audio_path → datetime.now() (line 73)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming._split_on_sentence_boundary → _SENTENCE_ENDINGS.finditer(text) (line 83)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming._split_on_sentence_boundary → m.end() (line 85)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming._split_on_sentence_boundary → last.end() (line 89)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming._split_on_sentence_boundary → last.end() (line 89)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming._tts_worker → packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming._get_sync_client() (line 107)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming._tts_worker → chunk_queue.get() (line 110)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming._tts_worker → text.strip() (line 115)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming._tts_worker → ...stream() (line 121)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.tee → chunk_bytes.append(chunk) (line 133)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming._tts_worker → packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.play_stream(tee(audio_stream)) (line 136)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming._tts_worker → packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.tee(audio_stream) (line 136)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming._tts_worker → collected.extend(chunk_bytes) (line 137)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.play_and_save_tagged_stream → packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.resolve_tts_call_profile(model_ref) (line 169)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.play_and_save_tagged_stream → packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.validate_tts_voices(profile, cycle_voices) (line 176)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.play_and_save_tagged_stream → packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.resolve_tts_voice(profile, voice_id) (line 179)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.play_and_save_tagged_stream → queue.Queue() (line 189)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.play_and_save_tagged_stream → threading.Thread() (line 192)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.play_and_save_tagged_stream → worker.start() (line 197)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.play_and_save_tagged_stream → asyncio.get_running_loop() (line 199)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.enqueue → text.strip() (line 202)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.enqueue → chunk_queue.put((text, vid)) (line 203)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.play_and_save_tagged_stream → packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming._split_on_sentence_boundary(buffer) (line 211)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.play_and_save_tagged_stream → packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.enqueue(chunk, _current_voice()) (line 216)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.play_and_save_tagged_stream → packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming._current_voice() (line 216)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.play_and_save_tagged_stream → packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming._advance() (line 217)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.play_and_save_tagged_stream → buffer.strip() (line 220)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.play_and_save_tagged_stream → packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.enqueue(buffer, _current_voice()) (line 221)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.play_and_save_tagged_stream → packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming._current_voice() (line 221)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.play_and_save_tagged_stream → chunk_queue.put(_SENTINEL) (line 223)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.play_and_save_tagged_stream → loop.run_in_executor(None, worker.join) (line 224)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.play_and_save_tagged_stream → join(collected) (line 226)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.play_and_save_tagged_stream → packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming._unique_audio_path(stem) (line 227)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.play_and_save_tagged_stream → path.write_bytes(all_audio) (line 228)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.save_streamed_audio → packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.play_and_save_tagged_stream(tagged_stream) (line 246)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming._mock_tagged_stream → reasoning.split() (line 266)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming._mock_tagged_stream → asyncio.sleep(token_delay) (line 268)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming._mock_tagged_stream → content.split() (line 269)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming._mock_tagged_stream → asyncio.sleep(token_delay) (line 271)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming._demo → strip() (line 282)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming._demo → packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.input('Catalog model or alias: ') (line 282)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming._demo → strip() (line 283)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming._demo → packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.input('Catalog-linked voice ID (blank for default): ') (line 283)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming._demo → packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.resolve_tts_call_profile(model_ref) (line 284)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming._demo → packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.resolve_tts_voice(profile, voice_id) (line 285)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming._demo → packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming.play_and_save_tagged_stream(_mock_tagged_stream(reasoning, content, resolved_voice)) (line 286)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming._demo → packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming._mock_tagged_stream(reasoning, content, resolved_voice) (line 287)
  Global Scope → asyncio.run(_demo()) (line 294)
  Global Scope → packages.matrx-ai.matrx_ai.providers.eleven_labs.tts_streaming._demo() (line 294)
```

### Call graph: packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict

```
packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict._api_key → packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict.resolve_api_key('ELEVENLABS_API_KEY') (line 34)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict._headers → packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict._api_key() (line 43)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict._add → strip() (line 59)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict._add → seen.add(s) (line 62)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict._add → rules.append(rule) (line 64)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict.entries_to_rules → strip() (line 67)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict.entries_to_rules → e.get('pronunciation') (line 67)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict.entries_to_rules → strip() (line 68)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict.entries_to_rules → e.get('ipa') (line 68)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict.entries_to_rules → e.get('term') (line 69)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict.entries_to_rules → e.get('sounds_like') (line 69)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict.entries_to_rules → strip() (line 71)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict.entries_to_rules → packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict._add({'string_to_replace': form, 'type': 'alias', 'alias': say_as}) (line 75)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict.entries_to_rules → packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict._add({'string_to_replace': form, 'type': 'phoneme', 'phoneme': ipa, 'alphabet': 'ipa'}) (line 77)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict.entries_to_rules → rules.sort() (line 86)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict.canonical_hash → json.dumps(rules) (line 95)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict.canonical_hash → hexdigest() (line 96)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict.canonical_hash → hashlib.sha256(payload.encode('utf-8')) (line 96)
  packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict.canonical_hash → payload.encode('utf-8') (line 96)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict.create_from_rules → httpx.AsyncClient() (line 101)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict.create_from_rules → http.post(f'{_BASE}/add-from-rules') (line 102)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict.create_from_rules → packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict._headers() (line 104)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict.create_from_rules → resp.raise_for_status() (line 107)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict.create_from_rules → resp.json() (line 108)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict.add_rules → httpx.AsyncClient() (line 113)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict.add_rules → http.post(f'{_BASE}/{dictionary_id}/add-rules') (line 114)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict.add_rules → packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict._headers() (line 116)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict.add_rules → resp.raise_for_status() (line 119)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict.add_rules → resp.json() (line 120)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict.add_rules → data.get('id', dictionary_id) (line 121)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict.remove_rules → httpx.AsyncClient() (line 125)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict.remove_rules → http.post(f'{_BASE}/{dictionary_id}/remove-rules') (line 126)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict.remove_rules → packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict._headers() (line 128)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict.remove_rules → resp.raise_for_status() (line 131)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict.remove_rules → resp.json() (line 132)
  async packages.matrx-ai.matrx_ai.providers.eleven_labs.pronunciation_dict.remove_rules → data.get('id', dictionary_id) (line 133)
```
<!-- /AUTO:call_graph -->
