Inflect Micro v2 and Nano v2
July 31, 2026 · View on GitHub
Default model-manager downloads use the published GGUF package when available; the original source/conversion instructions below remain valid for manual use.
inflect_v2 provides native GGML inference for the English
Inflect Micro v2 and
Inflect Nano v2 TTS models.
Both variants use the same runtime and produce 24 kHz mono audio. The initial
integration supports offline FP32 inference only.
The runtime does not use ONNX Runtime. The default download is the published GGUF package. The deprecated converter can still rebuild local safetensors from the official ONNX exports for manual testing.
Install
Install eSpeak-ng and its English voice data first. On Debian or Ubuntu:
sudo apt install espeak-ng libespeak-ng1
On macOS:
brew install espeak-ng
Then install the default GGUF package:
python tools/model_manager_v2.py install inflect_micro_v2_orig --models-root models
The deprecated source-conversion workflow remains available through
tools/model_manager_deprecated.py for users who want to rebuild from the
upstream ONNX assets themselves.
Run
audiocpp_cli --task tts --family inflect_v2 \
--model models/Inflect-Micro-v2 --backend cpu \
--text "Hello from Inflect Micro version two." \
--seed 0 --out inflect.wav
Use models/Inflect-Nano-v2 to run Nano. CUDA uses the same model layout and
request surface. CUDA sessions keep duration alignment on the native CPU GGML
path so small TF32 differences cannot change the monotone expansion; the four
flows and waveform decoder execute on CUDA.
If eSpeak-ng is installed outside the dynamic loader's search path, provide the library and data paths explicitly:
audiocpp_cli --task tts --family inflect_v2 \
--model models/Inflect-Micro-v2 --backend cpu \
--session-option inflect_v2.espeak_library_path=/path/to/libespeak-ng.so \
--session-option inflect_v2.espeak_data_path=/path/to/espeak-ng-data \
--text "A configured eSpeak installation." --out inflect.wav
On Windows, espeak-ng.dll and libespeak-ng.dll are searched automatically.
If eSpeak-ng is not installed system-wide, espeakng-loader can provide the
external DLL and data directory:
$espeakPaths = uv run --with espeakng-loader==0.2.4 python -c `
"import espeakng_loader; print(espeakng_loader.get_library_path()); print(espeakng_loader.get_data_path())"
$espeakLibrary = $espeakPaths[0]
$espeakData = $espeakPaths[1]
.\audiocpp_cli.exe --task tts --family inflect_v2 `
--model ../../models/Inflect-Micro-v2 --backend cpu `
--session-option "inflect_v2.espeak_library_path=$espeakLibrary" `
--session-option "inflect_v2.espeak_data_path=$espeakData" `
--text "Hello from Inflect Micro version two." `
--seed 0 --out inflect.wav
Python is used only to locate the external files. Synthesis remains entirely inside the native audio.cpp process.
Options
| Option | Range | Default | Meaning |
|---|---|---|---|
speaking_rate | 0.5–2.0 | 1.0 | Inflect speed multiplier; larger values shorten the output. |
variation | 0.0–1.0 | 0.667 | Scale of the seed-based Gaussian latent variation. |
seed | non-negative integer | 0 | Latent noise seed. Long-form chunks use seed + chunk_index. |
text_chunk_mode | word_budget | word_budget | Long-form splitting mode. |
text_chunk_size | positive integer | 280 | Maximum Unicode codepoints per chunk. |
Long-form text is split near punctuation. Adjacent chunks receive 5 ms edge fades and punctuation-dependent pauses. A request is rejected if its expanded latent would exceed 4000 frames. The model has one fixed voice and exposes no language, speaker, cloning, or streaming controls.
Standalone GGUF
The inflect_v2 model specification supports standalone GGUF packaging. Pack
the FP32 model.safetensors together with config.json:
audiocpp_gguf \
--input weights=models/Inflect-Nano-v2/model.safetensors \
--root models/Inflect-Nano-v2 \
--output models/Inflect-Nano-v2-FP32/model.gguf \
--type orig --family inflect_v2 \
--model-spec model_specs/inflect_v2.json
eSpeak-ng remains an external runtime dependency and is never embedded in the GGUF.
FP16 and quantized packages are intentionally unsupported until separate parity and listening validation is available.
Validation
The frontend goldens use phonemizer==3.3.0 and
espeakng-loader==0.2.4. Fixed-latent CPU output was checked against the
official FP32 ONNX graphs:
| Variant | Mean absolute error | Maximum error | Correlation |
|---|---|---|---|
| Micro v2 | 1.54e-5 | 9.16e-5 | 0.999999976 |
| Nano v2 | 1.53e-5 | 9.16e-5 | 0.999999964 |
Fixed-input CUDA comparisons produced mean absolute errors of 2.81e-4 and
3.39e-4, with correlations of 0.999892 and 0.999832, respectively.
The component run also covered deterministic seeds, rate control, long-form
output without non-finite samples, the 4000-frame rejection, and standalone
FP32 GGUF loading.
The committed inflect_v2_tts_longform path case runs two 783-codepoint
requests through one loaded session. Each Micro request produces 12 chunks
and a 48.544-second WAV. The Windows host used a Ryzen 7 7800X3D and RTX 4090
with CUDA 13.3. The Linux CPU run used Debian 13 under WSL2, GCC 14.2, and
the system libespeak-ng.so.1 without explicit session paths:
| Environment | Cold request | Repeated request | RTF cold / repeat | Memory |
|---|---|---|---|---|
| Windows CPU, Micro v2 | 12180.5 ms | 11901.2 ms | 0.251 / 0.245 | 352.04 MiB observed peak RSS |
| Windows CPU, Nano v2 | 5776.82 ms | 5670.52 ms | 0.119 / 0.117 | 220.94 MiB observed peak RSS |
| Windows CUDA, Micro v2 | 714.823 ms | 535.650 ms | 0.0147 / 0.0110 | Per-process VRAM unavailable from NVML under Windows WDDM |
| Windows CUDA, Nano v2 | 531.946 ms | 443.968 ms | 0.0110 / 0.00915 | Per-process VRAM unavailable from NVML under Windows WDDM |
| WSL2 Debian 13 CPU, Micro v2 | 8848.11 ms | 8737.13 ms | 0.182 / 0.180 | Not measured |
| WSL2 Debian 13 CPU, Nano v2 | 4652.59 ms | 4044.53 ms | 0.0959 / 0.0834 | Not measured |
For Micro v2, the two generated WAVs have identical frame counts and SHA-256
hashes within each environment:
f78254203b26d28f4acd97bf8883617f21c2f33f38cf43452a7640aba1acb778
on Windows CPU,
01b0d2e3bd035bb942a2626c73680d442ebd18388f98d144a381134adb801e9e
on CUDA, and
03a4b533ce442bab73c169426335f56d3908cc9112ca4c4858bf455ba74e30f6
under WSL2. Trace output records duration- and decoder-graph cache hits; the
retained caches are bounded to four duration shapes and two decoder shapes.
On Windows CPU, Nano v2 produced two byte-identical 48.512-second WAVs with
SHA-256
37de9733c5db6827c5875865cbce3fb63b632e846508e9572e6e67c2184da5aa.
The Windows CUDA Nano v2 outputs were byte-identical with SHA-256
99c5c76f794adc12d491978e63346dabf0619714dc02d1291a99dadecca7ecab.
The WSL2 Nano v2 outputs were also byte-identical, with SHA-256
56679f720574b6bd0470eed8ee82c0b7147be2d514ddf71afc9a53ea94c440fd.
The CUDA figures are cold and repeated requests within a fresh session after
the NVIDIA kernel cache has been populated. The first request immediately
after a new CUDA build spent an additional 9.5 seconds compiling kernels.
For the complete long-form outputs, CPU-to-CUDA correlation was 0.999889
for Micro and 0.999759 for Nano; mean absolute errors were 2.43e-4 and
3.38e-4, respectively.
The maintainer's preview/inflect-micro-v2 branch was measured separately
with the same 6026-codepoint input, Micro v2 weights, CPU, eight threads, and
Ryzen 7 7800X3D host:
| Implementation | Wall time | Audio duration | RTF | Real-time factor |
|---|---|---|---|---|
preview/inflect-micro-v2 | 102.178 s | 330.096 s | 0.3095 | 3.23x |
| This implementation | 96.825 s | 335.269 s | 0.2888 | 3.46x |
This implementation has a 6.7% lower RTF in that comparison. The preview branch uses its bundled Misaki G2P resources while this implementation uses the approved external eSpeak-ng frontend, so waveform and duration parity are not implied. The native runtime incorporates the preview branch's useful backend-addressable layout reuse, indexed channel reversal, 1x1 convolution matmul, broadcast bias, and direct CPU transposed-convolution paths.
Reproduce the validation
Run the build commands from an MSVC x64 developer shell:
cmake -S . -B build-inflect -G Ninja `
-DCMAKE_BUILD_TYPE=Release -DENGINE_BUILD_TESTS=ON
cmake --build build-inflect --parallel 8 `
--target audiocpp_cli inflect_v2_frontend_test
cmake -S . -B build-inflect-cuda -G Ninja `
-DCMAKE_BUILD_TYPE=Release -DENGINE_BUILD_TESTS=OFF -DGGML_CUDA=ON
cmake --build build-inflect-cuda --parallel 8 --target audiocpp_cli
Install the exact package used by the path test and resolve the external eSpeak-ng paths:
uv run --with onnx --with safetensors python tools/model_manager_deprecated.py `
install inflect_micro_v2 --models-root build-inflect/models
$espeakLibrary = uv run --with espeakng-loader python -c `
"import espeakng_loader; print(espeakng_loader.get_library_path())"
$espeakData = uv run --with espeakng-loader python -c `
"import espeakng_loader; print(espeakng_loader.get_data_path())"
Run the catalog, frontend, CPU long-form, and CUDA long-form checks:
uv run python tools/check_loader_catalog_sync.py --self-test
uv run python tools/check_loader_catalog_sync.py
ctest --test-dir build-inflect -R "inflect_v2_frontend_test|model_spec_system_test" `
--output-on-failure
uv run --with psutil --with nvidia-ml-py python `
tools/audiocpp_cli/run_audiocpp_cli_path_tests.py `
--cases tools/audiocpp_cli/audiocpp_cli_longform_tts_clone_cases.json `
--only inflect_v2_tts_longform `
--audiocpp-cli-bin build-inflect/bin/audiocpp_cli.exe `
--model-path build-inflect/models/Inflect-Micro-v2 `
--backend cpu --threads 8 --measure-resources `
--out-root build-inflect/validation/inflect-v2-cpu `
--session-option "inflect_v2.espeak_library_path=$espeakLibrary" `
--session-option "inflect_v2.espeak_data_path=$espeakData" --log
uv run python tools/audiocpp_cli/run_audiocpp_cli_path_tests.py `
--cases tools/audiocpp_cli/audiocpp_cli_longform_tts_clone_cases.json `
--only inflect_v2_tts_longform `
--audiocpp-cli-bin build-inflect-cuda/bin/audiocpp_cli.exe `
--model-path build-inflect/models/Inflect-Micro-v2 `
--backend cuda --threads 8 `
--out-root build-inflect-cuda/validation/inflect-v2-cuda `
--session-option "inflect_v2.espeak_library_path=$espeakLibrary" `
--session-option "inflect_v2.espeak_data_path=$espeakData" --log
The generated WAVs, request files, commands, logs, and summaries are under:
build-inflect/validation/inflect-v2-cpu/inflect_v2_tts_longform/build-inflect-cuda/validation/inflect-v2-cuda/inflect_v2_tts_longform/
The Linux CPU validation can be reproduced from Debian 13 under WSL2. A system eSpeak-ng installation is discovered automatically, so no session options are needed:
sudo apt install build-essential cmake python3 espeak-ng libespeak-ng1
cmake -S . -B build-inflect-wsl \
-DCMAKE_BUILD_TYPE=Release -DENGINE_BUILD_TESTS=ON
cmake --build build-inflect-wsl --parallel "$(nproc)" \
--target audiocpp_cli inflect_v2_frontend_test
build-inflect-wsl/bin/inflect_v2_frontend_test
build-inflect-wsl/bin/audiocpp_cli --list-loaders --json
python3 tools/audiocpp_cli/run_audiocpp_cli_path_tests.py \
--cases tools/audiocpp_cli/audiocpp_cli_longform_tts_clone_cases.json \
--only inflect_v2_tts_longform \
--audiocpp-cli-bin build-inflect-wsl/bin/audiocpp_cli \
--model-path build-inflect/models/Inflect-Micro-v2 \
--backend cpu --threads 8 \
--out-root build-inflect-wsl/validation/inflect-v2-wsl --log
Use build-inflect/models/Inflect-Nano-v2 as --model-path to repeat the
same path test with Nano.
Known limitations
- English, one fixed voice, and offline TTS only.
- eSpeak-ng and its data remain external runtime dependencies.
- Only FP32 packages are supported.
- Windows CPU/CUDA and Linux CPU under WSL2 are runtime-validated. Native Linux CUDA, Vulkan, and Metal are not practically validated for this release.
- CUDA deliberately performs duration alignment on CPU. CPU and CUDA are deterministic within a backend but are not bit-identical to each other.
- Windows WDDM did not expose per-process VRAM through NVML, so no CUDA peak VRAM figure is claimed.