Skip to main content

echovoice

Sentence-level TTS audio cache for pipecat voice pipelines. In-memory only for now — audio captured on one call is served on every later call in the same process; no external service, no persistence.

Layout

echovoice/
  defaults.py   every SDK-wide tunable default, in one place
  common/       shared dataclasses (CachedAudio, AudioMeta) + logger shim
  cache/        keying (normalization + cache keys) and the in-memory store
  pipecat_tts/  pipeline integration — mixin.py (read), capture.py (write),
                pending.py (read→write handoff), bracket_filter.py (merges
                per-sentence Started/Stopped into turn-level brackets so the
                transport behaves like stock); needs pipecat-ai
  remote/       dormant echo-service HTTP path (client + config)

How it works

Two pieces, wired around the host's existing TTS service:

  • Read — EnableTTSCache (echovoice.pipecat_tts.mixin): drop-in replacement for instantiating the provider class. Every sentence's run_tts first checks the shared in-memory store: a hit replays the cached PCM as TTSAudioRawFrames (zero provider traffic, barge-in aware), a miss synthesizes live and marks the sentence for capture.
  • Write — TTSCacheCapture (echovoice.pipecat_tts.capture): a pass-through processor placed right after the TTS service in the pipeline. It buffers each miss-marked sentence's audio and stores the finished sentence in the shared store (echovoice.cache.store.AUDIO_STORE, a bounded LRU map — 500 entries / 200 MB by default). Interruptions discard partial buffers, so truncated audio is never stored.

Cache keys (echovoice.cache.keying) hash normalized text + provider + voice

  • model + sample rate, so whitespace/casing never causes a false miss and two voices in one process can never serve each other's audio. Normalization is for key matching only — synthesis always uses the real text.

ElevenLabs specifics handled by the wrapper (validated against the multi-context websocket API):

  • One provider context per sentence, closed right after its text is sent (close is graceful — the provider flushes the audio, then sends the final).
  • A client-side gate caps simultaneous contexts (default 4 — ElevenLabs kills the socket at >5; tune via EnableTTSCache(cache_config={"max_concurrent_context": ..., "sentence_wait_timeout_s": ...}), all defaults live in echovoice/defaults.py). Slots free on the context's final, interruption, or websocket reconnect.
  • Cache hits take no context and no gate slot; the replayed context is completed explicitly so the sentence serializer never stalls.

Install

pip install -e /path/to/echovoice             # core (no pipecat needed)
pip install -e "/path/to/echovoice[pipecat]"  # with the pipecat wrapper

With uv, in the host app's pyproject.toml:

dependencies = ["echovoice"]

[tool.uv.sources]
echovoice = { path = "../echovoice", editable = true }

Usage (fw-aisha style)

from echovoice.pipecat_tts import EnableTTSCache, TTSCacheCapture

# read side — instead of CustomElevenLabsTTSService(...):
tts = EnableTTSCache(CustomElevenLabsTTSService,
    url="wss://api.in.residency.elevenlabs.io",
    api_key=ELEVENLABS_API_KEY,
    settings=ElevenLabsTTSService.Settings(model=..., voice=...),
)

# write side + bracket filter — right after the TTS service in the pipeline:
pipeline = Pipeline([..., tts, TTSCacheCapture(), TTSTurnBracketFilter(),
                     transport.output(), ...])

No configuration needed. The wrapped service exposes get_and_reset_turn_stats() and log_cache_summary(call_sid=...) for call logs. Skip both pieces and the provider runs fully stock.

echovoice.remote holds the HTTP client for a future server-backed cache (echo-service); it is dormant — nothing on the active path uses it.

Tests

uv sync && uv run pytest

Metadata

Release files for echospeaks 0.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for echospeaks 0.0.1
File Size Uploaded Provenance Actions
echospeaks-0.0.1.tar.gz 19.2 kB Without provenance Details for echospeaks-0.0.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for echospeaks 0.0.1
File Interpreter ABI Platform Actions
echospeaks-0.0.1-py3-none-any.whl Python 3 none any Details for echospeaks-0.0.1-py3-none-any.whl

Total release size: 43.0 kB

Release files / echospeaks-0.0.1.tar.gz

Download URL echospeaks-0.0.1.tar.gz
Size 19.2 kB
Tags Source
SHA-256 checksum
How to use checksums
aa7c852414da5164a8ea8986b8719638eb92837cf568b4ad13bfb6fd993bf1ab
BLAKE2b-256 checksum
How to use checksums
8db1bbdf7156fb6496ba52130b29bc789560624b16aeb81c01b74e39d1a0cc88
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.13 {"installer":{"name":"uv","version":"0.11.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / echospeaks-0.0.1-py3-none-any.whl

Download URL echospeaks-0.0.1-py3-none-any.whl
Size 23.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3797b88d4f4948bc6c4461b069cee636f0dc7fb8068b5dc861c8018d686681dd
BLAKE2b-256 checksum
How to use checksums
26564c61fb85a1ca35bd6d30d0075a4ada1cd131043679e1fb273822703f6216
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.13 {"installer":{"name":"uv","version":"0.11.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Security for echospeaks 0.0.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page