Быстрое распознавание речи с помощью модели NVIDIA Parakeet на чистом C++.
Построен на Axiom — легкой тензорной библиотеке с автоматическим ускорением Metal GPU. Никакой среды выполнения ONNX, среды выполнения Python и тяжелых зависимостей. Только C++ и тензорная библиотека, которая переопределяет PyTorch MPS.
Оценка кодировщика ~27 мс на графическом процессоре Apple Silicon Для звука 10 с (модель 110M) — в 96 раз быстрее, чем процессор.
| Образец | Сорт | размер | Тип | Описание |
|---|---|---|---|---|
tdt-ctc-110m |
ParakeetTDTCTC |
110 м | оффлайн | Английский, двойная декодерная головка CTC/TDT |
tdt-600m |
ParakeetTDT |
600 метров | оффлайн | Многоязычный декодер TDT |
eou-120m |
ParakeetEOU |
120 м | потоковая передача | Английский, с отслеживанием произношения окончания rnnt |
nemotron-600m |
ParakeetNemotron |
600 метров | потоковая передача | Многоязычная, настраиваемая задержка (80–1120 мс) |
sortformer |
Sortformer |
117 м | потоковая передача | Диаризизация спикеров (до 4 спикеров) |
Все модели ASR используют один и тот же аудиоконвейер: моно WAV 16 кГц → 80-битная Mel-спектрограмма → кодер FastConformer.
#include <parakeet/parakeet.hpp>
parakeet::Transcriber t("model.safetensors", "vocab.txt");
t.to_gpu(); // optional — Metal acceleration
auto result = t.transcribe("audio.wav");
std::cout << result.text << std::endl;
Выберите декодер на месте вызова:
auto result = t.transcribe("audio.wav", parakeet::Decoder::CTC); // fast greedy
auto result = t.transcribe("audio.wav", parakeet::Decoder::TDT); // better accuracy (default)
Временная метка на уровне слова:
auto result = t.transcribe("audio.wav", parakeet::Decoder::TDT, /*timestamps=*/true);
for (const auto &w : result.word_timestamps) {
std::cout << "[" << w.start << "s - " << w.end << "s] " << w.word << std::endl;
}
Автономная транскрипция (TDT-CTC 110M)
parakeet::Transcriber t("model.safetensors", "vocab.txt");
t.to_gpu();
auto result = t.transcribe("audio.wav");
Автономная транскрипция (TDT 600M многоязычный)
parakeet::TDTTranscriber t("model.safetensors", "vocab.txt",
parakeet::make_tdt_600m_config());
auto result = t.transcribe("audio.wav");
Потоковая транскрипция (120 млн евро)
parakeet::StreamingTranscriber t("model.safetensors", "vocab.txt",
parakeet::make_eou_120m_config());
// Feed audio chunks (e.g., from microphone)
while (auto chunk = get_audio_chunk()) {
auto text = t.transcribe_chunk(chunk);
if (!text.empty()) std::cout << text << std::flush;
}
std::cout << t.get_text() << std::endl;
Потоковая транскрипция (Немотрон 600М)
// Latency modes: 0=80ms, 1=160ms, 6=560ms, 13=1120ms
auto cfg = parakeet::make_nemotron_600m_config(/*latency_frames=*/1);
parakeet::NemotronTranscriber t("model.safetensors", "vocab.txt", cfg);
while (auto chunk = get_audio_chunk()) {
auto text = t.transcribe_chunk(chunk);
if (!text.empty()) std::cout << text << std::flush;
}
Диаризация спикера (Сортформер 117М)
Определите, кто и когда говорил. Обнаруживает до 4 говорящих с возможностью покадровой активности:
parakeet::Sortformer model(parakeet::make_sortformer_117m_config());
model.load_state_dict(axiom::io::safetensors::load("sortformer.safetensors"));
auto wav = parakeet::read_wav("meeting.wav");
auto features = parakeet::preprocess_audio(wav.samples, {.normalize = false});
auto segments = model.diarize(features);
for (const auto &seg : segments) {
std::cout << "Speaker " << seg.speaker_id
<< ": [" << seg.start << "s - " << seg.end << "s]" << std::endl;
}
// Speaker 0: [0.56s - 2.96s]
// Speaker 0: [3.36s - 4.40s]
// Speaker 1: [4.80s - 6.24s]
Потоковая диаризация с отслеживанием ордера по порядку прибытия:
parakeet::Sortformer model(parakeet::make_sortformer_117m_config());
model.load_state_dict(axiom::io::safetensors::load("sortformer.safetensors"));
parakeet::EncoderCache enc_cache;
parakeet::AOSCCache aosc_cache(4); // max 4 speakers
while (auto chunk = get_audio_chunk()) {
auto features = parakeet::preprocess_audio(chunk, {.normalize = false});
auto segments = model.diarize_chunk(features, enc_cache, aosc_cache);
for (const auto &seg : segments) {
std::cout << "Speaker " << seg.speaker_id
<< ": [" << seg.start << "s - " << seg.end << "s]" << std::endl;
}
}
Для полного контроля над трубопроводом:
КТК (английский, пунктуация и заглавные буквы):
auto cfg = parakeet::make_110m_config();
parakeet::ParakeetTDTCTC model(cfg);
model.load_state_dict(axiom::io::safetensors::load("model.safetensors"));
auto wav = parakeet::read_wav("audio.wav");
auto features = parakeet::preprocess_audio(wav.samples);
auto encoder_out = model.encoder()(features);
auto log_probs = model.ctc_decoder()(encoder_out);
auto tokens = parakeet::ctc_greedy_decode(log_probs);
parakeet::Tokenizer tokenizer;
tokenizer.load("vocab.txt");
std::cout << tokenizer.decode(tokens[0]) << std::endl;
ТДТ (преобразователь токена и продолжительности):
auto encoder_out = model.encoder()(features);
auto tokens = parakeet::tdt_greedy_decode(model, encoder_out, cfg.durations);
std::cout << tokenizer.decode(tokens[0]) << std::endl;
тюлень (CTC или TDT):
// CTC timestamps
auto ts = parakeet::ctc_greedy_decode_with_timestamps(log_probs);
// TDT timestamps
auto ts = parakeet::tdt_greedy_decode_with_timestamps(model, encoder_out, cfg.durations);
// Group into word-level timestamps
auto words = parakeet::group_timestamps(ts[0], tokenizer.pieces());
ускорение графического процессора (Металл):
model.to(axiom::Device::GPU);
auto features_gpu = features.gpu();
auto encoder_out = model.encoder()(features_gpu);
// Decode on CPU
auto tokens = parakeet::ctc_greedy_decode(
model.ctc_decoder()(encoder_out).cpu()
);
Usage: parakeet [options]
Model types:
--model TYPE Model type (default: tdt-ctc-110m)
Types: tdt-ctc-110m, tdt-600m, eou-120m,
nemotron-600m, sortformer
Decoder options:
--ctc Use CTC decoder (default: TDT)
--tdt Use TDT decoder
Other options:
--vocab PATH SentencePiece vocab file
--gpu Run on Metal GPU
--timestamps Show word-level timestamps
--streaming Use streaming mode (eou/nemotron models)
--latency N Right context frames for nemotron (0/1/6/13)
--features PATH Load pre-computed features from .npy file
Пример:
# Basic transcription (TDT decoder, default)
./build/parakeet model.safetensors audio.wav --vocab vocab.txt
# CTC decoder
./build/parakeet model.safetensors audio.wav --vocab vocab.txt --ctc
# GPU acceleration
./build/parakeet model.safetensors audio.wav --vocab vocab.txt --gpu
# Word-level timestamps
./build/parakeet model.safetensors audio.wav --vocab vocab.txt --timestamps
# 600M multilingual TDT model
./build/parakeet model.safetensors audio.wav --vocab vocab.txt --model tdt-600m
# Streaming with EOU
./build/parakeet model.safetensors audio.wav --vocab vocab.txt --model eou-120m
# Nemotron streaming with configurable latency
./build/parakeet model.safetensors audio.wav --vocab vocab.txt --model nemotron-600m --latency 6
# Speaker diarization
./build/parakeet sortformer.safetensors meeting.wav --model sortformer
# Speaker 0: [0.56s - 2.96s]
# Speaker 0: [3.36s - 4.40s]
# Speaker 1: [4.80s - 6.24s]
Требуется С++20. Axiom — единственная зависимость (включенная как подмодуль).
git clone --recursive https://github.com/noahkay13/parakeet.cpp
cd parakeet.cpp
make build
Загрузите NeMo Checkpoint с сайта NVIDIA и конвертируйте в Softensor:
# Download from HuggingFace (requires pip install huggingface_hub)
huggingface-cli download nvidia/parakeet-tdt_ctc-110m --include "*.nemo" --local-dir .
# Convert to safetensors
pip install safetensors torch
python scripts/convert_nemo.py parakeet-tdt_ctc-110m.nemo -o model.safetensors
Поддерживает все типы моделей через конвертер --model флаг:
# 110M TDT-CTC (default)
python scripts/convert_nemo.py checkpoint.nemo -o model.safetensors --model 110m-tdt-ctc
# 600M multilingual TDT
python scripts/convert_nemo.py checkpoint.nemo -o model.safetensors --model 600m-tdt
# 120M EOU streaming
python scripts/convert_nemo.py checkpoint.nemo -o model.safetensors --model eou-120m
# 600M Nemotron streaming
python scripts/convert_nemo.py checkpoint.nemo -o model.safetensors --model nemotron-600m
# 117M Sortformer diarization
python scripts/convert_nemo.py checkpoint.nemo -o model.safetensors --model sortformer
Также поддерживает сырой .ckpt Файлы и проверка:
python scripts/convert_nemo.py model_weights.ckpt -o model.safetensors
python scripts/convert_nemo.py --dump model.nemo # inspect checkpoint keys
Получите словарь SentencePiece из того же репозитория HuggingFace. файл находится в .nemo Архивируйте или скачайте напрямую:
# Extract from .nemo
tar xf parakeet-tdt_ctc-110m.nemo ./tokenizer.model
# or use the vocab.txt from the HF files page
Построен на общем кодировщике FastConformer (Conv2d с 8-кратной субдискретизацией → N конформных блоков с относительным позиционным вниманием):
| Образец | Сорт | декодер | Пример |
|---|---|---|---|
| КТК | ParakeetCTC |
жадный аргамакс | быстро, только английский |
| рннт | ParakeetRNNT |
Авторегрессионный LSTM | потоковая передача включена |
| ТДТ | ParakeetTDT |
LSTM+прогноз периода | Лучшая точность, чем RNNT |
| ТДТ-СТЦ | ParakeetTDTCTC |
TDT и CTC — оба основные | переключить декодер по предположению |
Потоковая передача с поддержкой кэша, построенная на кодере FastConverter со случайной сверткой и вниманием к ограниченному контексту:
| Образец | Сорт | декодер | Пример |
|---|---|---|---|
| ЕОУ | ParakeetEOU |
Потоковое RNNT | Находим конец произношения |
| немотрон | ParakeetNemotron |
Потоковое ТДТ | Настраиваемая задержка потоковой передачи |
| Образец | Сорт | архитектура | Пример |
|---|---|---|---|
| сортировщик | Sortformer |
Nest Encoder → Трансформатор → Сигмовидная | Диаризизация спикеров (до 4 спикеров) |
Измерено на Apple M3 16 ГБ с имитацией аудиовхода (Tensor::randn). Время указано для каждого прямого прохода кодировщика (сортировщик: полный прямой проход).
Пропускная способность кодировщика — аудио 10 с:
| Образец | параметры | ЦП (мс) | графический процессор (МС) | ускорение графического процессора |
|---|---|---|---|---|
| 110 метров (TDT-CTC) | 110 м | 2581 | 27 | 96x |
| ТДТ-600М | 600 метров | 10,779 | 520 | 21x |
| РНТ-600М | 600 метров | 10 648 | 1468 | 7x |
| сортировочная машина | 117 м | 3195 | 479 | 7x |
Масштабирование длины звука на 110 м с помощью графического процессора:
| аудио | ЦП (мс) | графический процессор (МС) | rtf | Поток |
|---|---|---|---|---|
| 1 с | 262 | 24 | 0,024 | 41x |
| 5 с | 1222 | 26 | 0,005 | 190x |
| 10 с | 2581 | 27 | 0,003 | 370x |
| 30 лет | 10 061 | 32 | 0,001 | 935x |
| 60 | 26 559 | 72 | 0,001 | 833x |
Ускорение графического процессора на основе компилятора Metal Graph от Axiom, который объединяет полный кодировщик в оптимизированные операции MPSGraph.
# Full suite
make bench ARGS="--110m=models/model.safetensors --tdt-600m=models/tdt.safetensors"
# Single model
make bench-single ARGS="--110m=models/model.safetensors --benchmark_filter=110m"
# Markdown table output
./build/parakeet_bench --110m=models/model.safetensors --markdown
# Skip GPU benchmarks
./build/parakeet_bench --110m=models/model.safetensors --no-gpu
Доступные флаги модели: --110m, --tdt-600m, --rnnt-600m, --sortformer. Все флаги тестов Google (--benchmark_filter, --benchmark_format=json, --benchmark_repetitions=N) прошли.
- Аудио: моно WAV 16 кГц (16-битный PCM или 32-битный с плавающей запятой)
- Автономные модели имеют ограничение продолжительности звука ~ 4–5 минут; Разделяйте длинные файлы или используйте потоковую модель
- Пустой идентификатор токена: 1024 (110M) или 8192 (600M).
- Для ускорения графического процессора требуется процессор Apple с поддержкой Metal.
- Временные метки используют выравнивание на уровне кадра:
frame * 0.08s(8x субдискретизация × 160 скачков/16 кГц) - Диаризизация сортформера использует необычные функции (
normalize = false) — отличается от модели ASR.
Массачусетский технологический институт