The C library
libpktito, the C11 library under the app, with what it needs, its API, its backends and how to build it.
libpktito is NVIDIA’s Parakeet-TDT speech models in C11, the engine under the app, with no Python, PyTorch or ONNX Runtime. It lives at github.com/peterheb/libpktito.
What it needs
The C library, libm and pthreads. It builds on Linux, macOS, and Windows 10 and later (with MSYS2’s MinGW-w64 gcc).
A model is one .pkf file, mapped rather than copied: about 650 MB of memory in all while transcribing.
The API
core/pktito.h is the whole interface:
#include "pktito.h"
pk_model *m = pk_model_load("models/parakeet-tdt-0.6b-v2.pkf", err, sizeof err);
pk_asr *a = pk_asr_new(m, 0); /* 0: a thread a core */
const pk_tok *t;
long n = pk_asr_run(a, samples, n_samples, &t); /* 16 kHz mono float */
pk_text(m, t, (size_t)n, text, sizeof text); /* NeMo's transcript */
/* t[i].frame * pk_model_frame_seconds(m) is when token i was heard */
| Function | What it does |
|---|---|
pk_model_load |
Maps a .pkf and checks it before anything in it is used. |
pk_asr_new, pk_asr_run |
A transcriber, and 16 kHz mono samples in, tokens with times out. |
pk_text, pk_words |
Tokens to UTF-8 text as NeMo writes it, and to words with their times. |
pk_vad_probs, pk_segments |
Silero VAD’s speech probabilities, and the speech segments from them. |
pk_chunks |
A long recording cut at its silences into pieces the model hears whole. |
pk_captions |
Words with times to subtitle cues: lines of 42 characters, one or two to a cue. |
pk_language |
Which of the multilingual model’s 25 languages a transcript’s words are in. |
pk_backend |
The backend in use. |
A loaded model can be shared across threads; each transcriber belongs to one thread at a time. The library keeps no global state and prints nothing. Recordings longer than about 30 seconds go through pk_chunks first. examples/transcribe.c is a complete program in one page.
Backends
A build holds every backend for its CPU family, and the fastest one the CPU supports is picked at load time.
| Backend | CPUs |
|---|---|
neon-dp |
ARMv8.2 with SDOT: Raspberry Pi 5’s Cortex-A76, Apple M chips |
neon |
ARMv8.0: Raspberry Pi 3’s Cortex-A53, Pi 4’s A72 |
avx512-vnni |
AVX512-VNNI: Ice Lake, Tiger Lake, Zen 4 |
avx2-vnni |
AVX-VNNI: Alder Lake and later, Zen 5 |
avx2 |
Haswell and later |
ref |
Scalar C, for anything |
All compute the same bits as ref. PKTITO_KERNELS=neon forces a backend, to compare.
Build
make # every backend of this machine's family, and ref
make BACKEND=ref # scalar C alone, for anything
make libpktito.a # the library alone
make check-c # the checks: a compiler and a model, on any board
On Windows, the same in an MSYS2 UCRT64 shell with pacman -S make diffutils mingw-w64-ucrt-x86_64-gcc.
The models can be downloaded ready to use, or converted from NVIDIA’s checkpoints with the repository’s converter, which is Python with numpy alone. The README has the steps.
Agreement with NeMo
The repository holds pktito to NeMo at three levels:
- The model: a float64 reference written from NeMo’s code gives NeMo’s token ids and timestamps exactly, for both models, on four test recordings in English, German and French.
- The numerics: pktito multiplies in int8. Against float32 on 200 LibriSpeech recordings, the English model’s word error rate is 1.51% for both; on 360 FLEURS recordings in six languages, the multilingual model’s is 4.42% against 4.41%.
- The text: the detokenizer gives NeMo’s text on every vocabulary piece and on thousands of random sequences.
The README has the method and the machines.