Add support for inflect_v2 TTS model - #125
Conversation
Integrates a full `inflect_v2` pipeline for Inflect Micro v2 and Nano v2, including loader/session/runtime/frontend code, model registration, and build wiring. Adds model specs, a converter for pinned official ONNX exports to FP32 safetensors, and model-manager install support for `inflect_micro_v2` and `inflect_nano_v2`. Documentation and CLI long-form coverage were expanded, and a new frontend unit test was added for normalization, tokenization, chunking, and fade behavior.
Extends the inflect_v2 community model doc with WSL2 Debian 13 CPU benchmark results for both Micro and Nano v2 models, including SHA-256 hashes, RTF figures, and reproduction steps. Updates the validated platform list and known limitations accordingly.
|
@0xShug0 The eSpeak part is a bit different from the other models, please let me know if you are okay with that. |
|
@JanWerder Thanks! I think runtime-loading eSpeak-ng is a reasonable workaround here. I had considered writing a minimal built-in eSpeak-compatible frontend, but that would be a much larger effort and probably not worth it for this integration. This approach also gives us a path to integrate Kokoro and KittenTTS. I had previously set those (and inflect micro v2) aside because of the frontend problem (the code is ready if you’re interested). Could you take a look at my earlier Inflect v2 attempt on preview/inflect-micro-v2 and compare performance?https://github.com/0xShug0/audio.cpp/tree/preview/inflect-micro-v2. Some of the optimizations there may be useful for your implementation. |
|
BTW, move assets/resources/inflect_v2/misaki_en/ into the model weights directory before running the model. Another minor issue is if eSpeak is missing, a bad task or bad option may fail with "missing eSpeak" first instead of the real validation error. This is because frontend_ is a direct member and is constructed before the constructor body validates task/options. |
|
@JanWerder Please check #128. The example is Confucius4-TTS. |
Migrate inflect_v2 to the shared spec-backed model loader path by removing the custom loader, wiring loader creation through session, and switching asset loading to family-based spec resolution. Update the model spec to schema_version 1 in model_specs and remove the legacy v1 spec copy. Also optimize runtime graph execution with backend-layout-aware contiguous handling, 1x1 conv matmul/bias fast paths, indexed channel reversal, and a direct CPU conv-transpose path. Session construction now validates task/options against the model contract before eSpeak init, with unit tests added for validation ordering, and docs refreshed with expanded Micro/Nano benchmark and parity data.
|
Thanks for the feedback. I’ve addressed all three points:
Micro and Nano were revalidated on Windows CPU/CUDA and Debian under WSL2. |
|
@JanWerder Merged! Thank you for contributing the new model! |
* Add inflect_v2 community TTS model support Integrates a full `inflect_v2` pipeline for Inflect Micro v2 and Nano v2, including loader/session/runtime/frontend code, model registration, and build wiring. Adds model specs, a converter for pinned official ONNX exports to FP32 safetensors, and model-manager install support for `inflect_micro_v2` and `inflect_nano_v2`. Documentation and CLI long-form coverage were expanded, and a new frontend unit test was added for normalization, tokenization, chunking, and fade behavior. * Add WSL2 Linux CPU benchmark results Extends the inflect_v2 community model doc with WSL2 Debian 13 CPU benchmark results for both Micro and Nano v2 models, including SHA-256 hashes, RTF figures, and reproduction steps. Updates the validated platform list and known limitations accordingly. * Refactor inflect_v2 loader and runtime Migrate inflect_v2 to the shared spec-backed model loader path by removing the custom loader, wiring loader creation through session, and switching asset loading to family-based spec resolution. Update the model spec to schema_version 1 in model_specs and remove the legacy v1 spec copy. Also optimize runtime graph execution with backend-layout-aware contiguous handling, 1x1 conv matmul/bias fast paths, indexed channel reversal, and a direct CPU conv-transpose path. Session construction now validates task/options against the model contract before eSpeak init, with unit tests added for validation ordering, and docs refreshed with expanded Micro/Nano benchmark and parity data.
Summary
This PR adds native GGML support for the Apache-2.0 licensed Inflect Micro v2 and Inflect Nano v2 models as the new
inflect_v2community TTS family.Both variants use the same configurable runtime and provide:
ONNX Runtime and PyTorch are not used during synthesis. The official FP32 ONNX exports are used only as pinned conversion sources and numerical parity references.
Implementation
The new community model is implemented under
src/community_models/inflect_v2/and includes:variation;Micro and Nano select different validated model dimensions while sharing the same runtime implementation. Unexpected variants, tensor names, shapes, or non-FP32 tensors are rejected while loading.
The loader is registered as:
inflect_v2ttsofflineenlong_formBoth the legacy model specification and the current
model_specs_v1catalog are included.Request options
speaking_rate0.5–2.01.0variation0.0–1.00.667seed0seed + chunk_indextext_chunk_modeword_budgetword_budgettext_chunk_size280The model intentionally exposes no language selection, speaker selection, voice cloning, or streaming controls.
eSpeak-ng frontend
Inflect requires the English eSpeak-ng frontend before neural inference.
The runtime dynamically opens the user-provided or system eSpeak-ng shared library:
libespeak-ng.so.1orlibespeak-ng.solibespeak-ng.dyliborlibespeak-ng.1.dylibespeak-ng.dllorlibespeak-ng.dllIt initializes eSpeak-ng once per process, selects
en-us, requests IPA with stress and preserved punctuation, and serializes access through a shared mutex because the eSpeak C API uses global process state.Optional explicit paths are available through:
inflect_v2.espeak_library_pathinflect_v2.espeak_data_pathA missing library, invalid data directory, or missing
en-usvoice fails session creation with an actionable error.No eSpeak binary, source, voice data, or Python package is vendored, downloaded by the model manager, embedded in GGUF, or distributed by this PR.
On Windows, users without a system installation can use
espeakng-loader==0.2.4as an external source for the DLL and data directory:Python is only used here to locate the external files. Synthesis remains inside the native audio.cpp process.
Model installation and provenance
The model manager downloads pinned official ONNX snapshots:
inflect_micro_v2owensong/Inflect-Micro-v2-ONNX91b1ab6432323064ec0e8e9704d92fcecd24855finflect_nano_v2owensong/Inflect-Nano-v2-ONNXdf3627e44c26192714c9dcba6b8e9b47e7a6e3d9The converter validates both ONNX initializer inventories and dimensions, then writes one FP32
model.safetensorsplus the native configuration.Generated weight files:
PyTorch is not required for installation or inference.
Standalone FP32 GGUF packages embed the model specification and
config.json. eSpeak-ng remains an external runtime dependency.Licensing
The model releases explicitly identify the original Inflect code and weights as Apache-2.0. eSpeak-ng remains under its own GPL-3.0 license.
Dynamic loading is the technical packaging boundary used by this implementation; this PR does not claim that every possible downstream combined distribution is automatically license-compliant. Distributors remain responsible for satisfying the licenses of the components they package.
Numerical parity
Frontend goldens use
phonemizer==3.3.0andespeakng-loader==0.2.4.Fixed-latent CPU output was compared with the official FP32 ONNX graphs:
1.54e-59.16e-50.9999999761.53e-59.16e-50.999999964Fixed-input CUDA comparisons produced:
2.81e-40.9998923.39e-40.999832The component validation also covered deterministic seeds, variation and rate controls, long-form output without NaN/Inf, the 4000-frame rejection, and standalone FP32 GGUF loading.
Real-time performance
All tested paths ran faster than real time (
RTF < 1.0). For the 48.544-second Micro v2 long-form output, Windows CPU reached0.246 / 0.237RTF for cold/repeated requests, CUDA reached0.0138 / 0.0116, and WSL2 CPU reached0.257 / 0.272. Nano v2 produced 48.512 seconds of audio under WSL2 with observed RTFs ranging from0.139to0.475; the wider range reflects WSL host-scheduling variance. The slowest measured run was still approximately2.1×faster than real time.Platform coverage
CPU and CUDA are deterministic within the same backend and configuration.
Bit-identical output across different backends is not claimed.
CUDA deliberately keeps duration alignment on CPU so small TF32 differences cannot alter monotonic expansion. The flows and waveform decoder execute on CUDA.
Reproduction
Windows CPU and CUDA builds:
Linux/WSL2 CPU build:
Representative system-eSpeak run:
build-inflect-wsl/bin/audiocpp_cli \ --task tts --family inflect_v2 \ --model build-inflect/models/Inflect-Micro-v2 \ --backend cpu \ --text "Hello from Inflect Micro version two." \ --seed 0 --out inflect.wavLong-form path test:
Replace the model path with
Inflect-Nano-v2to exercise Nano.Tests
The following checks pass:
The catalog check reports the existing unrelated warning that
bs_roformerhas no installable standaloneModelPackage; installable catalog families still match all registered loaders.Known limitations