The Problem
Echo-TTS solves multi-speaker text-to-speech with reference-audio conditioning: you supply a short clip of a target voice and a text prompt, and the model generates speech in that voice. The pain point is voice cloning without fine-tuning — the reference audio conditions generation at inference time via speaker latents and KV scaling, so no per-speaker training is needed.
What This Does
This is the inference codebase for the Echo-TTS model (jordand/echo-tts-base on HuggingFace). It loads a transformer backbone (model.py), a Fish-style autoencoder (autoencoder.py), and a PCA state, then samples audio conditioned on text and a speaker reference. gradio_app.py wraps the pipeline in a UI; inference.py exposes the Python API; inference_blockwise.py adds continuation/blockwise generation for longer outputs.
The repo also ships sampler_presets.json and text_presets.txt for sampler configuration, and audio_prompts/ with example reference clips.
How It Is Wired
Execution starts in one of two entry points: gradio_app.py (UI) or inference.py (API). The traced path is sample_pipeline → sample_euler_cfg_independent_guidances → _concat_kv_caches (called 3 times from that sampler). Models load from HuggingFace on first run via load_model_from_hf, load_fish_ae_from_hf, and load_pca_state_from_hf in inference.py.
The widest blast radius is weight_norm in autoencoder.py, called from 4 distinct places — changing it breaks the most callers. Also hot: ae_decode and precompute_freqs_cis (3 callers each). autoencoder.py is the hub: 85 functions and 23 classes, imported by 2 other files. model.py (32 functions, 10 classes) is imported by 3 files and has zero instability — stable, but everything depends on it.
Two files carry instability 1.0: gradio_app.py and inference_blockwise.py — they depend on everything and nothing depends on them, so they're safe to refactor. There are no circular dependencies (0 modules), which keeps the graph tractable. gradio_app.py is the only file touching the filesystem (audio read/write) and performing a secret-generating operation.
File map: autoencoder.py owns the neural codec (WNConv1d, Snake1d, ResidualVectorQuantize, from_codes); model.py owns the transformer (rotary embeddings, timestep embeddings); inference.py owns model loading and the main sampling loop; inference_blockwise.py owns the blockwise continuation sampler; gradio_app.py owns the UI, audio I/O, and format conversion.
How To Use It
Setup: Python 3.10+ and a CUDA GPU with ≥8GB VRAM. Install with pip install -r requirements.txt.
Running it: Start the Gradio UI with python gradio_app.py, or use the Python API documented in the README — load_model_from_hf, load_audio, sample_pipeline, then torchaudio.save. For 8GB VRAM, set FISH_AE_DTYPE = torch.bfloat16 and DEFAULT_SAMPLE_LATENT_LENGTH = 576 in gradio_app.py.
Real-World Use
A content-localization pipeline: ingest a 10-second reference clip from a licensed voice actor, generate narration for a script, and batch-produce audio in that voice. The sample_euler_cfg_independent_guidances sampler with cfg_scale_speaker=8.0 and sequence_length=640 (~30s) is the documented production configuration; enable "Force Speaker" KV scaling (default 1.5) when out-of-distribution text drifts the speaker identity.
Code Health & Issues
Static analysis found 6 issues (3 high, 3 medium). Deep nesting (max indentation depth 10) in autoencoder.py and gradio_app.py — hard-to-follow control flow; fix with early returns and guard clauses. Duplicated code: 26 repeated 6-line blocks across gradio_app.py, inference_blockwise.py, and inference.py — extract shared helpers. Oversized files: autoencoder.py and gradio_app.py at ~975 lines each. Broad exception handling in gradio_app.py swallows errors — catch specific exceptions.
SDLC gaps visible from the structure: no test files, no CI pipeline, no dependency lockfile (non-reproducible builds), and no Dependabot/Renovate configured despite the manifest in requirements.txt. A license file is present; no committed secrets detected.
The Bottom Line
The core design is sound — clean module separation, no circular imports, and a stable model.py/autoencoder.py core. The maintenance risk is concentrated in gradio_app.py and autoencoder.py, which need deduplication and flattening before they grow further. This is a solid inference codebase for teams needing reference-conditioned TTS without fine-tuning; add tests and a lockfile before trusting it in production.