How a 220-Line Local API Bridge Brought GigaAM to Vocalinux
This case study connects Vocalinux, transcribe.cpp and the 261 MB GigaAM v3 E2E-RNNT model on one Linux laptop. The result is an offline Russian dictation backend exposed through an OpenAI-compatible endpoint, accelerated by Vulkan on Intel Iris Xe graphics and kept separate from Vocalinux so normal application updates can continue.
1. A failed Handy experiment revealed 60+ model variants
The project started with a small disappointment. Handy looked interesting because its speech recognition catalog was much broader than the models already available in the author’s dictation setup, but the packaged Linux application did not run reliably on this machine. Uninstalling it did not make the experiment useless: its Hugging Face cache still contained a Russian GigaAM model named gigaam-v3-e2e-rnnt-Q8_0.gguf.
That 261 MB file led to transcribe.cpp, Handy’s MIT-licensed inference engine. The project currently covers 16 speech model families and more than 60 model variants, with CPU, Metal, CUDA and Vulkan backends. This was a larger opportunity than adding one Russian model: a small compatibility layer could give Vocalinux access to the same expanding engine catalog.
The experiment also fit the practical focus of Ravlik’s AI Experiments: reuse an existing local asset, measure it on ordinary hardware, and publish the glue instead of keeping it as a one-off shell script.
2. A GGUF extension does not make two engines compatible
The tempting shortcut was to copy the model into Vocalinux’s model directory. It could not work. GGUF is a container format, not a universal speech-model interface. A Whisper loader understands Whisper tensors and its decoding pipeline; GigaAM v3 uses a Conformer encoder and either CTC or RNNT decoding. Two files can end in .gguf while requiring completely different inference code.
Vocalinux already supports several local backends, including Whisper, Faster-Whisper, Vosk and Parakeet. Its whisper.cpp integration therefore cannot interpret GigaAM. The compatible runtime is transcribe.cpp, whose GigaAM documentation explicitly lists the v3 GGUF variants and their decoders.
3. Why the 261 MB GigaAM E2E-RNNT model was worth keeping
GigaAM v3 is optimized for Russian rather than multilingual recognition. The E2E-RNNT variant is especially suitable for dictation because its 1,024-token SentencePiece vocabulary produces capitalization and punctuation directly. The upstream table reports about 180 million parameters for this variant and a 5.36% word error rate on the Russian FLEURS benchmark for the Q8_0 quantization.
| Variant | Q8_0 size | FLEURS Russian WER | Output |
|---|---|---|---|
| E2E-RNNT | 261 MB | 5.36% | Cased, punctuated |
| E2E-CTC | 260 MB | 5.50% | Cased, punctuated |
| RNNT | 260 MB | 8.08% | Normalized |
| CTC | 259 MB | 8.40% | Normalized |
The Q8_0 score is effectively tied with the 5.35% result reported for the much larger F32 E2E-RNNT file. That makes 261 MB an unusually sensible compromise for a laptop. The limits matter too: GigaAM v3 is Russian-only, expects 16 kHz mono audio and is intended for utterances of roughly 25 seconds or less. It does not provide translation, diarization or built-in voice activity detection.
4. The bridge uses one standard HTTP request
Vocalinux already solves the integration problem through its documented Remote API mode. It records 16-bit, 16 kHz mono PCM, packages the sample as WAV in memory and sends a multipart request to POST /v1/audio/transcriptions. A valid server only needs to return JSON in the form {"text":"..."}.
Vocalinux
? HTTP on 127.0.0.1:8765
? vocalinux-transcribe-cpp-bridge
? Python bindings for libtranscribe.so
? GigaAM GGUF
? Intel Iris Xe through Vulkan
The resulting vocalinux-transcribe-cpp-bridge is roughly 220 lines of Python. It validates the uploaded file, invokes the already loaded model and returns the transcript in the format Vocalinux expects. Although HTTP appears in the diagram, the server listens on 127.0.0.1; audio never has to leave the laptop or travel across the internet.
5. Building for Vulkan exposed 2 useful Debian details
transcribe.cpp was compiled as a shared Release build with TRANSCRIBE_VULKAN=ON and TRANSCRIBE_BUILD_SHARED=ON. The documented Debian packages include CMake, a C++ toolchain, Vulkan development files, glslc and OpenBLAS. On this installation, spirv-headers was also required before the Vulkan shaders compiled successfully.
cmake -S . -B build-vulkan \
-DCMAKE_BUILD_TYPE=Release \
-DTRANSCRIBE_VULKAN=ON \
-DTRANSCRIBE_BUILD_SHARED=ON
cmake --build build-vulkan --parallel
OpenBLAS is not merely a box-ticking dependency. The upstream build notes say it can accelerate the host-side decoder by roughly 10–15 times. Vulkan then moves the model’s heavier tensor work to the integrated GPU. The compiled runtime identified the Intel Iris Xe device correctly, so no discrete NVIDIA or AMD card was needed.
6. An 11-second test finished in 1.22 seconds
The first repeatable smoke test used an 11-second, 16 kHz WAV sample. The complete transcription call took about 1.2247 seconds, close to 9 times real time. Reported timing included 248.81 ms for model loading, 13.78 ms for mel processing, 922.18 ms for encoding and 288.69 ms for decoding; overlapping internal stages mean those counters should not be added as if they were wall-clock totals.
The sample was English, while this GigaAM checkpoint is Russian-only, so its text output was deliberately ignored. The useful result was operational: the GGUF loaded, Vulkan executed on Iris Xe, and the CLI returned without errors. In actual Russian dictation the model felt roughly three times faster than the previous setup and subjectively more accurate. That last comparison is an observation, not a controlled benchmark; the 1.22-second smoke test is the reproducible number.
7. A separate service protects future Vocalinux updates
Patching Vocalinux’s recognition manager would remove one HTTP hop, but it would also create a private fork to reconcile after every update. Remote API mode leaves the installed application untouched. A user-level systemd unit starts the bridge at login, restarts it after failures and points it at the existing model cache through environment variables.
The running service used about 329 MB of RAM and exposed one local port, 8765. Vocalinux retained responsibility for push-to-talk, local VAD, segmentation and typing into the focused window. The bridge retained one narrow responsibility: turn an uploaded WAV file into text. This same separation principle appears in the Ubuntu Workshop sandbox discussion—small boundaries make experimental tools easier to replace and safer to operate.
8. The 20-minute workaround became a reusable MIT project
The initial request to the coding agent was simple: make this leftover Handy model work inside the already installed dictation application. Around 20 minutes of inspection, compilation, dependency fixes and API testing produced a working path. The process resembled the agent-assisted reconstruction described in Dead Games Are Coming Back, but at a much smaller scale: understand two interfaces, build the missing connector, then test every boundary.
The connector was generalized before publication. Its name refers to transcribe.cpp rather than GigaAM because the server accepts a configurable model path and model identifier. Compatibility still depends on what the installed transcribe.cpp build supports, and models may impose different audio or decoding requirements. GigaAM E2E-RNNT is the tested configuration, not a hard-coded limitation.
The public repository uses the MIT license and contains example environment and systemd files without redistributing the 261 MB model. Model files retain their own licenses and must be downloaded from their original publishers. That distinction keeps the bridge small, makes provenance visible and turns an accidental cache discovery into a reproducible open-source component.
How this was checked: local build and runtime measurements were taken on the working laptop; API behavior and model limits were cross-checked against the official Vocalinux, transcribe.cpp and GigaAM documentation linked above. Measurements describe this machine, not a universal performance guarantee.