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

OptionRangeDefaultMeaning
speaking_rate0.52.01.0Inflect speed multiplier; larger values shorten the output.
variation0.01.00.667Scale of the seed-based Gaussian latent variation.
seednon-negative integer0Latent noise seed. Long-form chunks use seed + chunk_index.
text_chunk_modeword_budgetword_budgetLong-form splitting mode.
text_chunk_sizepositive integer280Maximum 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:

VariantMean absolute errorMaximum errorCorrelation
Micro v21.54e-59.16e-50.999999976
Nano v21.53e-59.16e-50.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:

EnvironmentCold requestRepeated requestRTF cold / repeatMemory
Windows CPU, Micro v212180.5 ms11901.2 ms0.251 / 0.245352.04 MiB observed peak RSS
Windows CPU, Nano v25776.82 ms5670.52 ms0.119 / 0.117220.94 MiB observed peak RSS
Windows CUDA, Micro v2714.823 ms535.650 ms0.0147 / 0.0110Per-process VRAM unavailable from NVML under Windows WDDM
Windows CUDA, Nano v2531.946 ms443.968 ms0.0110 / 0.00915Per-process VRAM unavailable from NVML under Windows WDDM
WSL2 Debian 13 CPU, Micro v28848.11 ms8737.13 ms0.182 / 0.180Not measured
WSL2 Debian 13 CPU, Nano v24652.59 ms4044.53 ms0.0959 / 0.0834Not 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:

ImplementationWall timeAudio durationRTFReal-time factor
preview/inflect-micro-v2102.178 s330.096 s0.30953.23x
This implementation96.825 s335.269 s0.28883.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.