What Is Vocalizer?
Vocalizer is a native PHP extension by Akram Zerarka that brings local text-to-speech (TTS) synthesis to PHP applications. It embeds two inference backends — sherpa-onnx (ONNX Runtime) and audio.cpp (ggml) — and ships as a prebuilt .so binary for Linux x86-64. There is nothing to compile and no external API to call.
Eight Model Families, One API
Engine::load() points at a model directory, auto-detects the backend from its contents, and exposes a single speak() call:
use Vocalizer\Engine;
$engine = Engine::load('/opt/voices/sherpa-onnx-supertonic-3-tts-int8-2026-05-11');
$res = $engine->speak('Votre commande est prête.', [
'lang' => 'fr',
'voice' => 0,
'speed' => 1.0,
'timeout_ms' => 30_000,
]);
$res->save('/var/www/audio/notice.wav');
echo $res->seconds, " s in ", $res->generationMs, " ms\n";
The supported model families and their trade-offs:
| Goal | Model | Latency (CPU) | |---|---|---| | Best realism, voice cloning | Chatterbox | Slow (~20× real time) | | Fast multi-language (31 languages) | Supertonic 3 | Real-time | | Lightweight FR/EN cloning | Pocket TTS | Fast | | Fastest, one model per locale | Piper/VITS | Very fast |
Voice Cloning with Chatterbox
Chatterbox covers 23 languages with a single ~7.5 GB model and clones a voice from a 3–10 second reference WAV:
$engine = Engine::load('/opt/voices/chatterbox', [
'threads' => 4,
'opts' => ['weight_type' => 'f16'],
]);
$res = $engine->speak('Bonjour, votre commande est prête.', [
'lang' => 'fr',
'reference' => '/opt/voices/refs/fr.wav',
'opts' => [
'temperature' => 0.6,
'repetition_penalty' => 1.2,
'seed' => 42,
],
'timeout_ms' => 600_000,
]);
Because autoregressive TTS models can skip text, loop, or produce silence, Vocalizer includes an anti-hallucination guard. Every Chatterbox output is checked against text length and signal energy. Suspicious audio is re-synthesized with a new seed (two extra attempts by default). If all attempts fail, a Vocalizer\Exception is thrown, making a fallback to a faster model straightforward:
try {
$res = $engine->speak($text, ['lang' => 'fr', 'reference' => $ref]);
} catch (\Vocalizer\Exception $e) {
$res = Engine::load('/opt/voices/sherpa-onnx-supertonic-3-tts-int8-2026-05-11')
->speak($text, ['lang' => 'fr']);
}
Crash Isolation and Async Synthesis
Native inference engines can segfault. Vocalizer's default fork isolation mode runs synthesis in a child process, so a crash is caught, retried, and the model reloaded — surfacing as a Vocalizer\CrashException only when recovery fails. Chatterbox always runs in direct mode because its ggml thread pool is not fork-safe.
For longer texts, speakAsync() moves synthesis off the request path:
$job = $engine->speakAsync($paragraph);
$res = $job->wait(30_000) ?? throw new RuntimeException('still running');
Key php.ini directives: vocalizer.isolation, vocalizer.timeout_ms, vocalizer.max_models (LRU model cache per worker), and vocalizer.max_concurrency for the async pool.
Installation
Vocalizer requires Linux x86-64, glibc ≥ 2.28, and PHP 8.4 or 8.5 NTS. Alpine/musl, ARM, and ZTS builds are not supported.
curl -fsSL https://raw.githubusercontent.com/akramzerarka/vocalizer/main/install.sh | bash
Models are downloaded separately:
./scripts/download-model.sh chatterbox # ~7.5 GB
./scripts/download-model.sh sherpa-onnx-supertonic-3-tts-int8-2026-05-11 # ~120 MB
./scripts/download-model.sh vits-piper-en_US-amy-low # ~65 MB
Key Takeaways
- Runs entirely on-device — no API keys, no network calls, no runtime dependencies to compile.
- Eight TTS model families auto-detected from a directory; one unified
speak()API. - Voice cloning from a short WAV reference via Chatterbox (23 languages, ~7.5 GB model).
- Anti-hallucination guard re-synthesizes suspicious output before throwing an exception.
- Fork isolation protects PHP-FPM workers from native engine crashes.
speakAsync()keeps long synthesis jobs off the request path.- Requires Linux x86-64, glibc ≥ 2.28, PHP 8.4/8.5 NTS; MIT-licensed.
Source: Vocalizer: Local Text-to-Speech for PHP — Laravel News