- BrainTools - https://www.braintools.ru -

Всем привет! Я Виктор Загускин, руководитель отдела голосового ML в MWS AI. Мы разрабатываем продукт формата «спичкит» — распознавание и синтез речи, анализ ее содержания. Наши клиенты используют эту технологию как кубики для создания прикладных продуктов. Чтобы лучше прочувствовать их потребности [1] и боли [2], лучше познакомиться с тем, как реализовать голосовые ассистенты на основе современных решений, я решил попробовать сделать подобный продукт самостоятельно. Это будет работающий на локальном устройстве голосовой ассистент со встроенной LLM.
В этом цикле материалов я буду рассказывать о процессе создания ассистента, примененных технологиях, выбранном железе, трудностях и путях их преодоления, буду демонстрировать этапы работ. Попутно расскажу основные концепции, необходимые для реализации голосовых технологий.
Для создания промышленного решения я бы, конечно, взял собственные продукты MWS AI. Но поскольку хочется рассказать об этой активности широко, я решил использовать открытые решения, доступные каждому, а не только корпоративному сегменту. Это даст дополнительную возможность обсудить критерии выбора голосовых технологий и тонкости, на которые стоит обратить внимание [3].
Первая часть цикла посвящена базе — выбору «железа», тулкитов для инференса, моделей для синтеза и распознавания речи и LLM. Поехали!
Когда я изучал потенциальные аппаратные платформы для нашего продукта, мне попалось на глаза довольно любопытное семейство одноплатников Rockchip [4]. Их старшие модели довольно производительны в плане обычных вычислений и подходят для запуска инференса нейросетей. Для последнего есть специальный NPU производительностью до 6TOPS, который может решать довольно широкий класс задач. При этом, компактный форм-фактор позволяет реализовывать на их основе нечто вроде голосовой колонки.
Альтернативой могут быть устройства семейства Jetson от Nvidia либо какие-то компактные сборки на базе x86 семейства. Но не могу сказать, чтобы какие-то из них существенно выигрывали у «рокчипов» в соотношении цены, производительности и доступности.
«Джетсоны» существенно мощнее и, скорее всего экономичнее по энергии, но цена на них в российских онлайн-магазинах за комплект разработки начинается от 80 тыс. рублей за младшие модели. x86 — дороже, больше, прожорливее. Поэтому довольно много edge AI-решений сейчас делаются именно на «рокчипах».
В таблице я сравнил разные варианты «железяк» по цене, доступности, производительности и энергоэффективности. Не благодарите☺
|
Платформа / Модель |
Примерная цена (devkit / модуль) |
Доступность (СНГ) |
Доступность (США) |
TDP (Вт) |
ИИ-производительность (INT8) |
Энергоэффективность (TOPS/Вт) |
|
NVIDIA Jetson Orin Nano 8/16 GB |
$800 – $1000 |
⚠️ Ограниченная |
✅ Хорошая |
10–15 |
40 TOPS |
~2.7 – 4.0 |
|
NVIDIA Jetson Orin NX 16 GB |
$800 – $1000 |
⚠️ Ограниченная |
✅ Хорошая |
15–25 |
70 TOPS |
~2.8 – 4.7 |
|
NVIDIA Jetson AGX Orin 64 GB |
$3,499 – $3,999 |
❌ Очень низкая |
✅ Хорошая |
20–60 |
275 TOPS |
~4.6 – 5.5 |
|
Rockchip RK3588″ (e.g. Orange Pi 5 Plus, Radxa ROCK 5B)” |
$120 – $250 |
✅ Высокая |
✅ Хорошая |
8–12 (до 20 под пик) |
6 TOPS |
~0.5 – 0.75 |
|
Intel Core i3-N305″ (Alder Lake-edge-ПК/NUC)” |
$200 – $350 (мат. плата) |
✅ Высокая |
✅ Хорошая |
7–15 |
~6–10 TOPS |
~0.6 – 1.0 |
|
AMD Ryzen Embedded R2000 (e.g. R2314) |
$250 – $400 (SBC) |
✅ Средняя |
✅ Хорошая |
12–25 |
~8–12 TOPS |
~0.5 – 1.0 |
Для эксперимента я выбрал одноплатный компьютер Nanopi M6 [5] от компании FriendlyElec. Устройство поставляют собранным, в корпусе, и стоит оно в российских интернет-магазинах порядка 20 тыс. рублей (август 2025). На борту 8-ядерный ARM-процессор, 16Гб ОЗУ, видеокарта и NPU на 6TOPS. Последний, собственно, и позволяет «гонять» на нем довольно серьезные ML-модельки.
У моего устройства нет WiFi и встроенной карты eMMC. Есть порт LAN, HDMI, 3 USB, jack 3.5 и питание Type-C и слот для MicroSD карты.
Для комфортной работы на устройстве нужны:
Кабель LAN.
MicroSD карта хорошего качества (после двух неудачных попыток на Kingston и еще каком-то «ноунейм», заработало на Samsung EVO 64Gb).
Кардридер SD с адаптером/MicroSD («ноунейм» за 200 рублей с «Озона» работает нормально).
Программа Balena Etcher для прошивки флешки (бесплатно можно скачать под любую ОС).
Компьютер/ноутбук для прошивки флешки.
Опционально, но желательно: мышь, клава, монитор, колонки/наушники/микрофонная гарнитура, LAN-коммутатор.

Начало работы, в целом, простое: скачиваем образ ОС и прошиваем на карту с помощью Etcher. Ошибиться сложно: выбрали файл образа архивом, как скачали с сайта, выбрали карту, нажали кнопку «Прошить». Прошло 10 минут, дождались валидации. Видим сообщение об успехе — извлекаем карту. Мак может ругаться, что не может карту прочитать — это нормально.
Лучше взять ubuntu как образ — там точно найдется/запустится весь нужный софт. Более экономичный FriendlyWRT от производителя обладает экзотическим C++ рантаймом, и там многое не получается сразу поставить.
Вставляем карту в слот устройства, втыкаем кабель монитора в слот HDMI и включаем питание. Можно и сеть сразу подключить. Мы должны почти сразу увидеть эмблемку FriendlyElec и затем обычный вид десктопа ubuntu. Заходим юзером pi с паролем sudo pi.
Сеть должна сразу настроиться.
Если что-то идет не так — проверяем в первую очередь работоспособность SD-карты, адаптер питания и все соединительные кабели. Если подключить монитор, то в нормальном сценарии мы увидим обычный десктоп ubuntu.

Для того чтобы запускать нейросетевые модели на аппаратном ускорителе (NPU) в устройствах Rockchip, компания предоставляет собственный инструментарий — RKNN Toolkit (и его «брат» для LLM — RKNN-LLM). Эти библиотеки позволяют не просто запускать модели, а оптимизировать их под конкретную архитектуру NPU, используя квантование, слияние операций и другие трюки, чтобы получить максимальную производительность при минимальном энергопотреблении.
Что делают rknn и rknn-llm?
– RKNN — основной тулкит для конвертации и инференса классических моделей (CV/Speech/NLP). Он принимает модели из форматов ONNX, TensorFlow, PyTorch (через ONNX), и конвертирует их в .rknn — специальный бинарный формат, оптимизированный под NPU.
– RKNN-LLM — отдельный пакет, предназначенный для работы с большими языковыми моделями (LLM). Он обрабатывает модели в форматах GGUF, Hugging Face Transformers, ONNX, и также конвертирует их в .rknn, но с учётом особенностей работы с последовательностями, кэширования внимания и т.п.
Оба тулкита предоставляют API на Python и C++, командные утилиты для конвертации (rknn-toolkit2, rknn-llm-toolkit) и запуска.
Как это работает на практике? Пример конвертации
Представьте, что вы хотите запустить модель Whisper-tiny для распознавания речи. Вы берете ее из Hugging Face, конвертируете в ONNX, затем через RKNN превращаете в .rknn.
from rknn.api import RKNN
rknn = RKNN()
rknn.config(mean_values=[[0, 0, 0]], std_values=[[1, 1, 1]])
rknn.load_onnx(model='whisper_tiny.onnx')
rknn.build(do_quantization=True, dataset='./dataset.txt') # квантуем!
rknn.export_rknn('whisper_tiny.rknn')
Здесь:
– config() — задаём нормализацию входных данных (если нужно).
– load_onnx() — загружаем модель.
– build() — конвертируем и квантуем модель (обязательно указываем датасет для калибровки!).
– export_rknn() — сохраняем готовую модель.
Важно: не все модели конвертируются. Особенно проблемные те, что используют динамические формы (например, переменную длину текста или изображений), слои, которые еще не реализованы в RKNN (например, LayerNorm с нестандартными параметрами, GroupNorm, некоторые attention-слои). Они просто «падают» без понятной ошибки [7]. Это частая боль при работе с RKNN.
Что делать, если конвертация не работает?
Решение — использовать rknn_model_zoo (https://github.com/airockchip/rknn_model_zoo [8]).
Это официальный репозиторий, где Rockchip уже подготовил готовые модели и скрипты конвертации для самых популярных задач: объектное детектирование, сегментация, ASR, TTS и т.д.
Вы просто клонируете репозиторий, запускаете скрипт конвертации (если нужно), и сразу можете использовать модель в своём проекте.
cd python
python convert.py [9] <onnx_model> <TARGET_PLATFORM> <dtype(optional)> <output_rknn_path(optional)>
например:
python convert.py [9] ../model/whisper_encoder_base_20s.onnx rk3588
python convert.py [9] ../model/whisper_decoder_base_20s.onnx rk3588
Запуск инференса: Python и C++
В rknn_model_zoo есть примеры инференса на Python и C++. Для нашего ассистента мы будем использовать Python-скрипты — они проще для прототипирования.
Инференс через ONNX
python whisper.py [10] --encoder_model_path <onnx_model> -decoder_model_path <onnx_model> --task <TASK> --audio_path <AUDIO_PATH>
например:
python whisper.py [10] --encoder_model_path ../model/whisper_encoder_base_20s.onnx --decoder_model_path ../model/whisper_decoder_base_20s.onnx --task en --audio_path ../model/test_en.wav
Инференс через RKNN
python whisper.py [10] --encoder_model_path <rknn_model> -decoder_model_path <rknn_model> --task <TASK> --audio_path <AUDIO_PATH> --target <TARGET_PLATFORM>
например
python whisper.py [10] --encoder_model_path ../model/whisper_encoder_base_20s.rknn --decoder_model_path ../model/whisper_decoder_base_20s.rknn --task en --audio_path ../model/test_en.wav --target rk3588
Для использования NPU необходимо вызывать модели в .rknn формате, onnx – выполняется на CPU.
Из готовых моделей синтеза речи с поддержкой русского языка в rknn_model_zoo есть только сконвертированная модель mms_tts на основе архитектуры VITS. Это довольно современная, легковесная flow-matching модель, которая дает неплохие интонации. Внутри тулкита модель англоязычная, но доступны необходимые скрипты для конвертации русскоязычного варианта (есть на Hugging Face [11]).
В будущем можно попытаться сконвертировать что-то из более современных моделей, или более адаптированный к русскому языку вариант, но для первой версии голосового ассистента этой модели будет вполне достаточно — со своими задачами она справляется (если не считать легкого английского акцента и неумения озвучивать цифры).
Все довольно просто: в скрипте export_onnx.py [12] меняем в model, tokenizer = setup_model ("facebook/mms-tts-eng") на “mms-tts-rus”, запускаем python export-onnx.py [13]
” и получаем onnx модельки для русского языка.
Затем для каждой модельки (энкодер и декодер) вызываем
convert.py [9] mms_tts_eng_encoder_200.onnx rk3588
и получаем сконвертированные файлы с расширением .rknn — это готовые к запуску образы моделей.
Теперь осталось «подшаманить» со скриптом запуска. В скрипте mms_tts.py [14] заменим словарь токенизатора (vocab) на русский, пример текста тоже заменим на какой-то русский текст. Словарь для русского берем вот отсюда [15], для проверки работы выдумываем текст из 200 (не более) символов, или того количества символов, которое мы указали при конвертации. Но указывать много не нужно — длинный текст при синтезе стоит разбивать на предложения.
После этого можно запускать скрипт, указав ему пути к .rknn моделям через encoder(decoder)-model-path опцию. Будет создан .wav файл озвученного текста, который можно послушать в наушниках, например через aplay ../output.wav.
Звучит средне, относительно чисто, интонации неплохие, но мы слышим акцент и некоторые звуки произносятся неестественно. Для продакшн-решения придется еще поработать — подыскать либо дообучить хорошую модель, решить вопросы с предобработкой текста, расстановкой ударений, раскрытием сокращений и чисел. Но для быстрой демки вполне подойдет.
Итого: нам нужна функция для проигрывания аудио на устройстве и код вызова моделей синтеза речи. Выглядит это вот так:
def play_audio(waveform, samplerate=16000):
"""
Проигрывает аудио из numpy-массива через наушники.
waveform: numpy.ndarray формы (n_samples,) или (n_samples, channels)
samplerate: частота дискретизации (например, 16000)
"""
# Нормализуем аудио в диапазон [-1, 1] (если не нормализовано)
waveform = np.asarray(waveform, dtype=np.float32)
if np.max(np.abs(waveform)) > 1.0:
waveform = waveform / np.max(np.abs(waveform))
print("🔊 Проигрывание аудио...")
print(waveform.shape, max(waveform), waveform.mean())
sd.play [16](waveform, samplerate=samplerate, device=0)
sd.wait() # Ждём окончания проигрывания
print("✅ Проигрывание завершено.")
class TTSVocaliser:
def init(self):
encoder_path = os.path.join(MODEL_DIR, ENCODER)
decoder_path = os.path.join(MODEL_DIR, DECODER)
self.encoder = self.init_rknn_model(encoder_path)
self.decoder = self.init_rknn_model(decoder_path)
def init_rknn_model(self, model_path):
model = RKNN()
ret = model.load_rknn(model_path)
ret = model.init_runtime(target="rk3588", device_id=None)
return model
def vocalise(self, inp: str):
input_ids_array, attention_mask_array = preprocess_input(inp, vocab, max_length=MAX_LENGTH)
# Encode
log_duration, input_padding_mask, prior_means, prior_log_variances = run_encoder(self.encoder, input_ids_array, attention_mask_array)
# Middle process
attn, output_padding_mask, predicted_lengths_max_real = middle_process(log_duration, input_padding_mask, MAX_LENGTH)
# Decode
waveform = run_decoder(self.decoder, attn, output_padding_mask, prior_means, prior_log_variances)
#audio_save_path = "test_output.wav"
#sf.write(file=audio_save_path, data=np.array(waveform[0][:predicted_lengths_max_real * 256]), samplerate=16000)
audio_data=np.array(waveform[0][:predicted_lengths_max_real * 256])
play_audio(audio_data)
Итак, теперь нам нужна модель распознавания речи, которая была бы:
легковесной;
русскоязычной;
без проблем конвертировалась на rknn;
умела распознавать в потоковом режиме.
Начнем с того, что уже присутствует в зоопарке — с Whisper. Модель от OpenAI, одна из лидеров по качеству распознавания на английском, есть разные размеры, от компактных, до огромной на 1.5B параметров.
Готовый скрипт есть для английского и китайского языков. Для русского придется поправить детокенизацию и промпт, что в принципе несложно.
Проблема в другом:
– Потокового распознавания нет, надо кидать целиком фразу длиной обычно 10 или 20 секунд (зависит от настроек конвертации модели), затем ждать, когда она целиком распознается, а это еще несколько секунд — для голосового ассистента, простите за слово, «неюзабельно».
– Хотя формальные метрики качества у Whisper очень неплохи, особенно у адаптированных версий (см. например https://alphacephei.com/nsh/2023/01/22/russian-models.html [17]), на практике регулярно встречаются сюрпризы в виде текста, абсолютно не соответствующего произносимому. Модель может зациклиться (или не к месту вспомнить имя создателя субтитров из своей обучающей выборки).
Второй вариант – модель Vosk (https://huggingface.co/alphacep/vosk-model-small-streaming-ru/tree/main [18]). Она сделана на основе тулкита K2-FSA (https://github.com/k2-fsa [19]), поэтому для нее доступены и код инференса, и скрипты конвертации. Сконвертированные модельки и короткую инструкцию по конвертации и запуску я положил сюда https://huggingface.co/vzaguskin/vosk_rknn [20].
Оказалось довольно неплохо — почти всегда качества расшифровки достаточно, чтобы намерение было понятно LLMке, плюс есть готовые скрипты потокового распознавания и детекции окончания фраз. Эти скрипты работают и на «рокчипе» — не нужно реализовывать довольно сложный кусок логики.
Итоговый код выглядит вот так:
MODEL_DIR = "models/vosk-asr"
import sherpa_onnx
def create_recognizer():
# Создаём распознаватель напрямую через конструктор
recognizer = sherpa_onnx.OnlineRecognizer.from_transducer(
tokens = os.path.join(MODEL_DIR, "tokens.txt"),
encoder = os.path.join(MODEL_DIR, "vosk-ru-encoder.rknn"),
decoder = os.path.join(MODEL_DIR, "vosk-ru-decoder.rknn"),
joiner = os.path.join(MODEL_DIR, "vosk-ru-joiner.rknn"),
num_threads=4,
sample_rate=16000,
feature_dim=80,
enable_endpoint_detection=True, # ← Включаем детекцию конца фразы!
rule1_min_trailing_silence=1.0, # 1 сек тишины = конец фразы
rule2_min_trailing_silence=0.8,
rule3_min_utterance_length=3.0, # мин. длина фразы 3 сек
provider="rknn", # ← важно для Rockchip!
model_type="zipformer",
debug=False,
)
return recognizer
def listen_and_recognize_phrase(device=0, sample_rate=16000, timeout=15.0):
recognizer = create_recognizer()
stream = recognizer.create_stream()
print("🎙️ Говорите... (ждём конца фразы, таймаут 15 сек)")
start_time = time.time()
def callback(indata, frames, time_info, status):
if status:
print(status)
samples = indata[:, 0]
stream.accept_waveform(sample_rate, samples)
with sd.InputStream(
device=device,
channels=1,
samplerate=sample_rate,
dtype='float32',
callback=callback,
blocksize=4000
):
while time.time() - start_time < timeout:
while recognizer.is [21]_ready(stream):
recognizer.decode_stream(stream)
if recognizer.is [21]_endpoint(stream):
result = recognizer.get_result(stream).strip()
if result:
print(f"✅ Распознано: {result}")
return result
recognizer.reset(stream)
time.sleep(0.01)
print("⏰ Таймаут — ничего не распознано.")
return ""
Если мы делаем полноценного ассистента, который постоянно слушает микрофон, еще нужен детектор голосовой активности, чтобы модели распознавания включались только тогда, когда слышат реальную речь, и так экономили энергию устройства. Дополнительно обычно реализуют реакцию [22] на ключевое слово (Алиса, Siri, и т.п.). Это мы перенесем на следующий этап. Пока будем вручную запускать демку, когда захотим пообщаться с моделью .
Из коробки в RKNN-LLM доступны модели Qwen разных размеров, от 0.6 до 4B, сконвертированные в Int8. Модель 4B получается запустить отдельно, несмотря на то, что по документации на устройстве всего 2 Gb NPU-памяти. Но вместе с распознаванием и синтезом она уже не влазит.
Инструментов профилирования не хватает. Я не нашел, как посмотреть физически доступный и занятый объем NPU памяти [23]. Для rknn-моделей можно из python api посмотреть в отладочных логах, сколько они занимают, но для rknn-llm нет ни питоновского API, ни аналогичных логов. Возможно, я не там искал.
Модель размером 1.7B откликается достаточно живо и демонстрирует больше признаков интеллекта [24], чем 0.6. Последняя летает, но совсем простенькая. Есть, конечно, вариант перед каждой генерацией выгружать из памяти другие модели и загружать туда LLMку, а для работы с голосом опять выгружать. Но в сочетании с медленной скоростью генерации самой модели это будет (и снова простите) «неюзабельно».
В RKNN-LLM есть готовый пример запуска Flask-сервера с выбранной моделью, и клиент для этого API.
Поэтому пока я остановился на варианте 1.7B.
Код запроса к Flask-серверу в простейшем случае выглядит так:
def send_chat_request(user_message, is_streaming=True, voice_callback = None):
print("Поступил запрос:", user_message)
headers = {
'Content-Type': 'application/json',
'Authorization': 'not_required'
}
data = {
"model": MODEL,
"messages": [{"role": "user", "content": user_message}],
"stream": is_streaming,
"enable_thinking": False,
"tools": None
}
print("Data:", data)
# Send a POST request
responses = session.post [25](server_url, json=data, headers=headers, stream=is_streaming, verify=False)
if not is_streaming:
# Parse the response
if responses.status_code == 200:
print("Q:", data["messages"][-1]["content"])
reply = json.loads(responses.text)["choices"][-1]["message"]["content"]
print("A:", reply)
if voice_callback:
voice_callback(reply)
else:
print("Error:", responses.text)
else:
if responses.status_code == 200:
print("Q:", data["messages"][-1]["content"])
print("A:", end="")
buff = ""
for line in responses.iter_lines():
if line:
line = json.loads(line.decode('utf-8'))
if line["choices"][-1]["finish_reason"] != "stop":
reply = line["choices"][-1]["delta"]["content"]
#print("reply:", reply, end="")
buff += reply
sys.stdout.flush()
if len(buff) > 200 or buff[-1] in ['.', '?', '!']:
print("озвучиваю:", buff)
if voice_callback:
voice_callback(buff)
buff = ""
if buff and voice_callback:
voice_callback(buff)
print("озвучиваю:", buff)
else:
print('Error:', responses.text)
Ну что ж, теперь есть все, чтобы собрать минимально работающего на локальном устройстве голосового чат-бота. Работать он будет так:
Приветствуем пользователя голосовым сообщением.
Слушаем его реплику с таймаутом 15 секунд.
Отправляем реплику в LLM-сервер.
В потоковом режиме получаем ответ.
После накопления достаточного количества текста (200 символов), либо концу предложения, осуществляем синтез и озвучиваем. Повторяем [26], пока приходит ответ.
Снова слушаем реплику пользователя.
На данном этапе сделаем это в виде очень простого цикла, вызывающего реализованные выше функции.
voc = TTSVocaliser()
def run_agent():
say_message(WELCOME_MESSAGE)
while True:
inp = listen_and_recognize_phrase()
send_chat_request(inp, voc.vocalise)
Итак, мы получили полностью локального голосового ассистента на одноплатном компьютере с применением большой (относительно) языковой модели.
Что нам не хватает для счастья:
Качественного синтеза речи, способного в том числе озвучивать числа и латинские символы, правильно ставить ударения.
Параллельного выполнения долгих операций: ожидание следующей части ответа LLM, озвучивание предыдущей и ее проигрывание — может происходить одновременно.
Эхоподавления и возможности слушать и говорить одновременно.
Истории разговоров и какой-то устойчивой личности самого ассистента.
Способности выполнять какую-то полезную работу: искать информацию, управлять списками задач, смотреть календарь.
Асинхронного взаимодействия — способности отправлять сообщения в Telegram или email.
Возможности подключать действительно мощную модельку (даже не локальную) для каких-то серьезных задач.
Внешнего хранилища для постоянных данных.
Решению этих вопросов мы посвятим следующие публикации, stay tuned!
Более детальную реализацию проекта можно посмотреть на GitHub [27], а о новостях и обновлениях узнавать в Telegram [28].
На десерт — Здесь [29] можно посмотреть демонстрацию работы.
В статье упоминаются опенсорсные технологические решения компании Meta Platform, признанной экстремистской и запрещенной в РФ.
Автор: vzaguskin
Источник [30]
Сайт-источник BrainTools: https://www.braintools.ru
Путь до страницы источника: https://www.braintools.ru/article/22480
URLs in this post:
[1] потребности: http://www.braintools.ru/article/9534
[2] боли: http://www.braintools.ru/article/9901
[3] внимание: http://www.braintools.ru/article/7595
[4] Rockchip: https://ru.wikipedia.org/wiki/Rockchip
[5] Nanopi M6: https://www.friendlyelec.com/index.php?route=product/product&product_id=301
[6] Amazon.com: http://Amazon.com
[7] ошибки: http://www.braintools.ru/article/4192
[8] https://github.com/airockchip/rknn_model_zoo: https://github.com/airockchip/rknn_model_zoo
[9] convert.py: http://convert.py
[10] whisper.py: http://whisper.py
[11] есть на Hugging Face: https://huggingface.co/facebook/mms-tts-rus/tree/main
[12] onnx.py: http://onnx.py
[13] export-onnx.py: http://export-onnx.py
[14] tts.py: http://tts.py
[15] вот отсюда: https://huggingface.co/facebook/mms-tts-rus/blob/main/vocab.json
[16] sd.play: http://sd.play
[17] https://alphacephei.com/nsh/2023/01/22/russian-models.html: https://alphacephei.com/nsh/2023/01/22/russian-models.html
[18] https://huggingface.co/alphacep/vosk-model-small-streaming-ru/tree/main: https://huggingface.co/alphacep/vosk-model-small-streaming-ru/tree/main
[19] https://github.com/k2-fsa: https://github.com/k2-fsa
[20] https://huggingface.co/vzaguskin/vosk_rknn: https://huggingface.co/vzaguskin/vosk_rknn
[21] recognizer.is: http://recognizer.is
[22] реакцию: http://www.braintools.ru/article/1549
[23] памяти: http://www.braintools.ru/article/4140
[24] интеллекта: http://www.braintools.ru/article/7605
[25] session.post: http://session.post
[26] Повторяем: http://www.braintools.ru/article/4012
[27] GitHub: https://github.com/vzaguskin/orin/
[28] Telegram: https://t.me/SpeechAIPro
[29] Здесь: https://rutube.ru/video/64a89fb95b4b940f2c7b61c8494f132a/
[30] Источник: https://habr.com/ru/companies/mts_ai/articles/970434/?utm_source=habrahabr&utm_medium=rss&utm_campaign=970434
Нажмите здесь для печати.