tayuLuc/dsh-ru-voice-input ↗★ 0

dsh-ru-voice-input

Russian-first Voice input bundle for DeepSeek Harness: a microphone in the composer that already understands Russian. Local GigaAM v3 CTC (int8) is the default recognizer, ru is the default language, and the speech registry is forked so switching recognizers actually works. 适合需要俄语语音输入的用户,默认使用本地GigaAM模型识别。

Package
dsh-ru-voice-input
Compatibility
Unverified
Version
0.1.0
License
NOASSERTION
Last updated
Sep 27, 2026

Install

$npx -p @deepseek-ai/dsh dsh plugin --profile web add github:tayuLuc/dsh-ru-voice-input

dsh-ru-voice-input

Русский Voice input для DeepSeek Harness. Одна установка — и в композере микрофон, который сразу понимает русский.

Зачем он существует

Штатный плагин Voice input заточен под китайский: единственный провайдер — SenseVoice, и в релизном чекпойнте русского нет. Замер на Apple M1 (26.09.2026, 28.6 с русской речи): SenseVoice int8 вернул пустую расшифровку (0 слов, WER 100 %) и всё равно занял ~600 МБ RAM.

Замеры — на M1 / 8.6 ГБ, синтез речи macOS say -v Milena. Это смоук, а не бенчмарк.

Установка

dsh plugin --profile web add https://github.com/tayuLuc/dsh-ru-voice-input

Перезапустите Web UI. Дальше — кнопка микрофона между моделью и Send: нажать, разрешить доступ, записать, Stop. Расшифровка вставляется в черновик.

Первое использование скачивает и проверяет модель (ревизия и SHA-256 закреплены) в ~/.dsh/models/gigaam-v3-ctc/. SenseVoice не качается: в этом бандле его нет, у него нет русского.

Если pnpm ругается на ERR_PNPM_IGNORED_BUILDS — разрешите сборку нативного рантайма в ~/.dsh/profiles/ /pnpm-workspace.yaml:

allowBuilds:
  onnxruntime-node: true
  koffi: true

Что внутри

Один пакет, четыре слоя, формально те же четыре строки, что у штатного Voice input:

СлойЧто это
./lib/registry.jsфорк speech-to-text с починенным configure()
./lib/gigaam/index.jsпровайдер GigaAM v3 CTC на onnxruntime-node или transcribe-cpp
@deepseek-ai/dsh-experimental-api-speech-to-textмост браузер↔хост, штатный
@deepseek-ai/dsh-experimental-client-ui-voice-inputкнопка микрофона, штатная

Дефолты: распознаватель gigaam-v3-ctc-local, язык ru. Свежий профиль работает без кликов.

Слои 1 и 2 заданы относительными спецификаторами — загрузчик их резолвит внутри пакета. Так бандл остаётся самодостаточным: пакет, поставленный из git, не может зависеть от собственных подкаталогов.

Движки

Движок выбирается конфигом engine, по умолчанию e2e. Замер на этом хосте (Apple M1), прогретый, русская речь 5 с и 28.6 с:

engineРантаймRTF (5 с)RTF (28.6 с)Пунктуация
e2e (по умолчанию)MLX, gigaam-mlx через Python-сайдкар0.0270.017есть
metalGGUF Q8_0, transcribe-cpp—0.016нет
onnxint8, onnxruntime-node0.0380.043нет

Только e2e даёт пунктуацию и заглавные. Словарь CTC-голов GigaAM — 34 токена: ▁, 32 русские буквы и ``. Знаков препинания в нём нет физически, поэтому metal и onnx не могут их выдать ни при какой настройке.

Пример одного и того же места: панель а показывает (CTC) против Панель A показывает (e2e).

Требования движка e2e

Python ≥ 3.10 с установленным gigaam-mlx и ffmpeg в PATH:

uv venv ~/.dsh/venvs/gigaam-mlx --python 3.12
uv pip install --python ~/.dsh/venvs/gigaam-mlx/bin/python \
  "gigaam-mlx @ git+https://github.com/aystream/gigaam-mlx.git"

Путь ищется так: поле e2ePythonPath, иначе $GIGAAM_MLX_PYTHON, иначе /venvs/gigaam-mlx/bin/python. Веса модель качает сама в кэш Hugging Face.

Цена первого запроса. В свежем процессе MLX компилирует пайплайн: первый ответ ~1.7 с против 0.13 с прогретого, дальше 0.027 RTF. Поэтому idleTimeoutMs: 0 ставить не стоит: воркер должен переживать паузу между записями.

Почему реестр форкнут

Штатный configure() проверяет текущий язык против нового провайдера:

const id = patch.providerId ?? this.config.defaultProvider.get();
this.selectedProvider(id, patch.language ?? this.config.language.get());

Из-за этого смена распознавателя невозможна, когда сохранённый язык не входит в список нового провайдера. В настройках это выглядит как «выбрал — откатило», и выхода нет: выбрать русский можно только у провайдера, который русский уже поддерживает.

Фикс: голое переключение провайдера берёт язык, который новый провайдер принимает, — сначала сохранённый, иначе первый в его списке. Явно заданный язык по-прежнему проверяется и по-прежнему отвергается вслух.

Контракт сервиса не изменён: имя speechToText, схема конфига и все методы те же, поэтому штатные мост и UI работают против форка без изменений.

Проверка

npm test                              # реестр: переключение провайдера, 11 проверок
node test/provider.mjs      # провайдер: регистрация, prepare, расшифровка

У провайдера есть отрицательный контроль: тишина обязана дать пустой текст, иначе сломанная модель прошла бы как рабочая.

Живой замер движка:

node test/provider.mjs  ~/.dsh/models/gigaam-v3-ctc e2e    # или metal, onnx
node scripts/selftest.mjs  ~/.dsh/models/gigaam-v3-ctc onnx  # замер только Node-движков

Что дальше

RNNT вместо CTC в движке e2e. Сейчас по умолчанию ctc — он быстрее. rnnt заявлен точнее (~77× против ~330× realtime у автора на M2 Max), обе ветки с пунктуацией. Переключается конфигом e2eModel, без переустановки.

Память. По умолчанию воркер освобождается через 120 с простоя. idleTimeoutMs: 0 держит его загруженным постоянно — на ноутбуке этого стоит избегать.

Лицензия

MIT. Форк реестра — производная от @deepseek-ai/dsh-experimental-speech-to-text 0.1.7-rc.2. Веса модели не входят в поставку: провайдер тянет их сам по закреплённой ревизии.