TTS OutieTTS 1.0 + cloning audio#63
Conversation
|
@mirek190 For new models/frameork module change, please check https://github.com/0xShug0/audio.cpp?tab=contributing-ov-file#new-model-prs and report parity and perf mertics as in #19. Your framework changes look fine since they're additive. For the Python side, you only need to provide the setup instructions. I’ll handle the setup and validation myself. Beyond #19:
(Originally, I only cared about performance and VRAM usage stability, but more and more users asked for VRAM reduction, so I started adding VRAM optimization to new models.) If you compare the final shape of Moss TTS Local with the original PR, you can see that there were many changes. Because of that, I’d like to make the tests stricter. I’ll create a checklist later. This is not meant to discourage the PR. The current direction looks good; I just want the validation to be strict enough that we can merge it with confidence and avoid another large cleanup pass later. |
Sure Updated to your request
RTX 3090 with gguf Q8 benchmark:
making more tests ... |
|
@mirek190 Could you report parity and performance vs. python on a per-request basis instead of only reporting aggregated results? For parity with python, the metric is wav cosine or log-mel similarity. CPU performance is good to have but not required. CUDA optimization is the priority. So mem saver on is always faster than off? If this case there is no need to add the mem saver option. |
First post updated |
|
@mirek190 Thanks for the update! Generally I expect the log mel > 85%. For most of the models the parity can be 99% when randomness is fully controlled. several suggestions: (1) test temperature=0 / greedy, at least it isolates drifts in the sampling part. Make sure the randomness control is wired correctly in python. E.g., acestep requires two seeds, so setting only the outer one won’t work. The framework has a TorchRandn which matches torch.randn closely enough for model parity tests. Let me know if you have any questions about my suggestions. |
|
(1) test temperature=0 / greedy, at least it isolates drifts in the sampling part. This specific model has ONLY one specific stable temperature and is set already. When you change it the model just collapses. the rest in progress .... |
First post updated with your suggestions |
|
@mirek190 Thank you! The results look promising. Would you be willing to refactor the asset and loader code to match the current style (same high-level interface, remove the usage of "as_xx, etc)? This will make the later abstraction easier. I did a large refactor sweep last night, so you can use the updated code as a reference for the new style. |
|
@mirek190 Also, could you create a small separate PR for the framework extension? I’d like to merge that first because I’m currently extending the AR template and want to include your changes. |
…ning # Conflicts: # docs/gguf.md
done |
|
Thanks! I'll do my tests after I wrap up the Voxtral real-time model. |
Sure |
|
Hey 0xShug0 how fast is you higgs v3 implementation as I do not see how it looks your work. I remember you mentioned about you were working on higgs v3. If you want I can push my implementation I was working on mine for 3 weeks and could only compare to qwen 3 tts which is implemented under audiocpp. Because mine my Higgs v3 TTS 4B is substantially faster than even much smaller audio.cpp’s Qwen3-TTS 0.6B on the RTX 3090. Implementation Audio length Inference RTF Speed I was testing with this sample |
|
@mirek190 Current warm Higgs TTS RTF is ~7.7x realtime Q8 while Qwen3-TTS 1.7B native is 5.7x realtime on RTX5090. So yes, Higgs TTS is faster than Qwen3. It currently still stays at the "parity safe" stage without further perf optimization (e.g., still using naive attention). I got distracted by the World Cup and by upgrading GGML to v0.16 or v0.17 (just released). Couldn’t decide whether to upgrade yet because the performance impact has been mixed. Let me know if you're interested in integrating your implementation into audio.cpp. I can push my current half-baked implementation to the dev branch so you can check. (It uses the refactored framework AR template.) No pressure at all. I completely understand if you'd rather publish it as a dedicated project. |
Sure pusch to dev and I compare to my implementation |
|
@mirek190 Pushed! Feel free to submit a PR to optimize the implementation. |
Summary
Normal TTS does not initialize the embedded aligner. It is loaded only when cloning needs reference word timing. Safetensors packages and older OuteTTS GGUFs without the embedded aligner can use
outetts.aligner_model_path.Model setup and tested paths
Package id
outetts_1_0_1binstalls:models/Llama-OuteTTS-1.0-1Bmodels/DAC.speech.v1.0models/Qwen3-ForcedAligner-0.6BThe standalone path test used only this file outside the PR worktree:
Exact build commands
Windows CPU:
Windows CUDA 12.4:
Both command sequences passed.
torch_random_testalso passed on Windows CPU.Exact standalone run commands
Normal TTS:
One-file voice cloning:
Both loaded with no adjacent sidecar or external
model_specsdirectory and passed ffmpeg decoding.Controlled Python parity
The official HF reference uses OuteTTS commit
f5eac6e70d792844c6a6959d900a47af2c061a5b, FP32 CUDA weights, and the official IBM DAC checkpoint. Temperature zero/greedy was deliberately not used: the model's officialgeneration_config.json, README example, and Python API specify sampled generation at temperature0.4. Both sides use temperature0.4, repetition penalty1.1over 64 tokens, top-k40, top-p0.9, min-p0.05, and the request-file seed.OuteTTS has no diffusion or latent-noise input; language-model sampling is its only request-time random boundary. C++ CUDA now uses the framework's PyTorch-compatible exponential-race stream. The committed Python driver resets both the CPU and CUDA generators immediately before every
model.generate, after prompt/profile construction:Matching C++ FP32 run:
Temporary trace logs compared Python/C++ prompt strings, token IDs, generated IDs, codec codes, and frame counts at component boundaries, then were removed to avoid runtime log spam. The committed Python driver writes
boundaries.json. All six ordinary-TTS chunks had zero sampled prompt/generated boundary mismatches. Clone prompts are 2367 tokens on both sides. All FP32 WAV frame counts match exactly. The remaining clone drift is isolated to the reference DAC encoder: among 1046 profile frames, C1 differs on 48 and C2 on 118.Primary FP32 parity:
tts_coldtts_repeattts_longformclone_coldclone_repeatOnly after FP32 boundary/frame parity was clean was Q8 compared with the same FP32 Python reference. Quantized autoregressive sampling drift is expected:
tts_coldtts_repeattts_longformclone_coldclone_repeatPerformance per request
Measured on an RTX 3090 with CUDA 12.4 in one loaded session. Python/C++ FP32 are single runs. Q8 values are mean +/- sample standard deviation from three fresh processes; model loading is excluded.
tts_coldtts_repeattts_longformclone_coldclone_repeatMemory-saver A/B per request
Three fresh processes per mode were alternated to reduce order bias:
tts_coldtts_repeattts_longformclone_coldclone_repeatMemory saver is not faster: the +0.35% to +0.53% per-request differences are close to normal run variance, and the mean sequence cost is +0.44%. It remains useful because measured peak VRAM fell from 17653 MiB to 5780 MiB (67.3%), with the same 294 MiB post-session resident VRAM. It is a memory/latency tradeoff, not a speed optimization.
Generated artifacts
..\outputs\outetts_path_test_tts.wav..\outputs\outetts_path_test_clone.wavbuild\reference\official_script_fp32\outputs\*.wavbuild\reference\official_script_fp32\boundaries.jsonbuild\reference\cpp_f32_final_explicit\*.wavbuild\reference\cpp_q8_torch_sampler\*.wavbuild\logs\warmbench\outetts-ab-torch-sampler\{default,mem_saver}-{1,2,3}-audio\*.wavThese are reproducible local validation outputs and are not committed.
Backend coverage
Known limitations
max_tokensapplies per chunkDocumentation
docs/tts.mddocs/outetts_validation.mddocs/memory_saver.mdConverted GGUF: https://huggingface.co/mirek190/audio.cpp/tree/main