Я печатаю быстро. Где-то 90 слов в минуту, если верить тестам. Но есть ситуации, когда клавиатура просто мешает. Длинное описание бага с контекстом на три абзаца. Диктовка мыслей, пока идёшь за кофе. Объяснение задачи Claude Code, когда проще рассказать голосом, чем формулировать текстом. На macOS и Windows голосовой ввод давно встроен в систему. На Linux всё сложнее — готовых решений уровня «нажал кнопку и диктуешь» здесь нет. Точнее, не было.
В этой статье разберём проект voice-setup — готовую конфигурацию для локального распознавания речи на GPU. Whisper для STT, Kokoro для озвучки ответов, VoiceMode MCP для интеграции с Claude Code. Всё крутится в Docker, ничего не уходит в облако.
Зачем вообще локальный STT
Облачные сервисы распознавания речи работают отлично. Google Speech-to-Text, OpenAI Whisper API, Deepgram — выбирай на вкус. Проблема в другом.
Во-первых, приватность. Каждый фрагмент аудио улетает на чужой сервер. Если вы диктуете описание внутренней архитектуры или обсуждаете рабочие задачи, это может быть неприемлемо. Во-вторых, задержка. Даже при хорошем интернете сетевой round-trip добавляет 200–500 мс поверх самого распознавания. Для коротких команд это заметно. И в-третьих, деньги. Whisper API стоит $0.006 за минуту — немного, но при активном использовании набегает. Локальный Whisper на вашей видеокарте — это ноль рублей навсегда.
Проект voice-setup решает все три проблемы разом: ставит Whisper и Kokoro TTS в Docker-контейнеры с GPU-ускорением, подключает их к Claude Code через MCP-протокол, а бонусом даёт универсальный скрипт для голосового ввода в любое приложение на Linux.
Что внутри
Архитектура простая. Два Docker-контейнера с GPU-доступом, один MCP-сервер на Python, клиент в виде Claude Code.
Whisper STT слушает на порту 2022 и предоставляет OpenAI-совместимый API. Kokoro TTS — на порту 8880, тоже OpenAI-совместимый. VoiceMode MCP связывает микрофон с Claude Code: вы говорите «послушай», дожидаетесь сигнала, произносите задачу — Claude получает распознанный текст и работает с ним как с обычным промптом.
Kokoro — open-weight модель с 82 миллионами параметров. Занимает примерно 1 ГБ VRAM. Лицензия Apache 2.0, качество озвучки на уровне коммерческих решений (модель заняла первое место в HuggingFace TTS Arena для single-speaker). Если озвучка ответов не нужна — контейнер с Kokoro можно просто не запускать.
Требования к железу
Для работы нужна видеокарта NVIDIA с поддержкой CUDA. Модель Whisper large-v3 занимает около 3 ГБ VRAM, Kokoro — около 1 ГБ. На карте с 12 ГБ (RTX 4070 SUPER, например) остаётся ещё 8 ГБ для всего остального — Ollama, inference других моделей, что угодно.
Если VRAM мало, можно выбрать модель полегче:
| Модель | VRAM | Латентность | Качество распознавания русского |
|---|---|---|---|
| faster-whisper-tiny | ~1 ГБ | мгновенно | слабое |
| faster-whisper-small | ~2 ГБ | очень быстро | среднее |
| faster-whisper-medium | ~5 ГБ | быстро | хорошее |
| faster-whisper-large-v3 | ~10 ГБ | 300–500 мс | отличное |
Для русского языка я бы не рекомендовал опускаться ниже medium. Tiny и small сносно работают с английским, но на русском начинают путать окончания, глотать предлоги и выдавать кашу на длинных предложениях. Large-v3 стоит по умолчанию — и это правильный выбор, если карта тянет.
Немного цифр для контекста: оригинальный Whisper large-v3 от OpenAI показывает WER (Word Error Rate) около 9.84% на русском по датасету Common Voice 17.0. Существует дообученная версия antony66/whisper-large-v3-russian, которая снижает WER до 6.39%. Проект voice-setup использует стандартную large-v3, но при желании модель можно заменить одной строкой в docker-compose.yml.
Установка
Минимальный путь — клонировать репозиторий и запустить скрипт:
git clone https://gitlab.com/avtobys/voice-setup.git
cd voice-setup
chmod +x setup.sh
./setup.sh
Скрипт поставит системные зависимости (ffmpeg, portaudio, pulseaudio), установит uv (менеджер пакетов для Python от Astral), поднимет Docker-контейнеры и настроит VoiceMode MCP. Первый запуск скачает модель large-v3 — это примерно 3 ГБ, так что на медленном интернете придётся подождать.
После установки нужно прописать переменные окружения. В репозитории есть файл bashrc-snippet.sh — его содержимое добавляется в ~/.bashrc:
export STT_BASE_URL="http://127.0.0.1:2022/v1"
export VOICEMODE_STT_BASE_URLS="http://127.0.0.1:2022/v1"
export TTS_BASE_URL="http://127.0.0.1:8880/v1"
export VOICEMODE_TTS_BASE_URLS="http://127.0.0.1:8880/v1"
export VOICEMODE_VOICES="af_sky"
Проверить, что всё работает:
curl http://localhost:2022/v1/models # Whisper
curl http://localhost:8880/v1/models # Kokoro
Если оба отвечают — готово. Дальше в Claude Code пишете «послушай» или «listen», говорите задачу, и Claude работает с ней.
Голосовой ввод без Claude Code: скрипт на хоткей
Самая практичная часть проекта — это даже не интеграция с Claude Code, а простой bash-скрипт для голосового ввода в любое приложение. Первое нажатие хоткея начинает запись, второе — останавливает, распознаёт и вставляет текст в активное окно через xdotool.
#!/bin/bash
PIDFILE=/tmp/rec.pid
WAVFILE=/tmp/rec.wav
if [ -f "$PIDFILE" ]; then
kill $(cat $PIDFILE)
rm $PIDFILE
notify-send "🎤 STT" "Распознаю..." -t 1500
sleep 0.2
TEXT=$(curl -s http://localhost:2022/v1/audio/transcriptions \
-F file=@$WAVFILE \
-F "model=Systran/faster-whisper-large-v3" \
-F language=ru \
| jq -r .text | tr -d '\n')
xdotool type --clearmodifiers --delay 20 "$TEXT "
notify-send "✅ STT" "$TEXT" -t 3000
else
arecord -f cd -t wav $WAVFILE &
echo $! > $PIDFILE
notify-send "🔴 STT" "Запись..." -t 6000
fi
Сохраняете как ~/.local/bin/stt, делаете chmod +x, назначаете на хоткей (Super+V, Ctrl+Alt+S — что удобнее). Дальше это работает везде: в браузере, в IDE, в мессенджере, в терминале. Зависимости минимальные: arecord, curl, jq, xdotool, notify-send.
Я повесил это на Super+V и за неделю привык настолько, что теперь без этого хоткея чувствую себя как без буфера обмена. Особенно удобно для длинных сообщений в Telegram и описаний тикетов в Jira — ситуации, где печатать лень, а надиктовать за 30 секунд нормально.
Нормализация текста через Ollama
Whisper распознаёт хорошо, но не идеально. Бывают лишние запятые, неправильные окончания, слипшиеся слова. Если на машине уже крутится Ollama (а у кого из нас она не крутится), можно прогонять распознанный текст через локальную LLM для исправления.
В проекте есть расширенная версия скрипта, которая делает именно это. Штука в том, что скрипт определяет активное окно и передаёт его название в промпт. LLM получает контекст: если диктуешь в терминал — она не будет «исправлять» команды, если в редактор кода — учтёт техническую лексику.
# Контекст активного окна
WID=$(xdotool getactivewindow)
WINDOW_NAME=$(xdotool getwindowname $WID 2>/dev/null || echo "unknown")
PROCESS=$(ps -p $(xdotool getwindowpid $WID) -o comm= 2>/dev/null || echo "unknown")
# Нормализация через Ollama
PAYLOAD=$(jq -n \
--arg text "$TEXT" \
--arg window "$WINDOW_NAME" \
--arg process "$PROCESS" \
'{model: "qwen3.5:4b", stream: false, think: false,
prompt: "Исправь опечатки и ошибки распознавания речи в тексте.
Пользователь вводит текст в программе \($process) (окно: \($window)).
Верни ТОЛЬКО исправленный текст.\nТекст: \($text)"}')
Qwen 3.5 4B справляется за доли секунды. Суммарная задержка от окончания записи до появления текста — около секунды на RTX 4070 SUPER (Whisper ~400 мс + Ollama ~300 мс + накладные расходы). Для диктовки в чат или описание задачи это вполне комфортно.
А что с нативным голосовым вводом в Claude Code?
Справедливый вопрос. В марте 2026 Anthropic добавила в Claude Code встроенный голосовой режим: зажимаете пробел, говорите, отпускаете — текст попадает в промпт. Казалось бы, зачем городить огород с Docker и MCP?
Разница в scope. Нативный /voice в Claude Code — это голосовой ввод только внутри Claude Code. Проект voice-setup даёт голосовой ввод везде в системе. Плюс полная приватность — аудио не покидает вашу машину. Плюс возможность использовать дообученные модели Whisper (например, ту самую whisper-large-v3-russian с WER 6.39%). Плюс нормализация через Ollama с учётом контекста окна.
Если вам нужен голосовой ввод только для Claude Code и приватность не критична — встроенный /voice проще в установке и не требует GPU. Если нужен универсальный голосовой ввод по всей системе с полным контролем — voice-setup.
Грабли и нюансы
Несколько вещей, на которые стоит обратить внимание.
PulseAudio vs PipeWire. Если у вас PipeWire (а в 2026 году он стоит почти везде), убедитесь, что установлен pipewire-pulse — прослойка совместимости с PulseAudio. Docker-контейнер Whisper ожидает PulseAudio для доступа к микрофону.
Холодный старт. Первый запрос к Whisper после старта контейнера обрабатывается дольше — модель загружается в GPU. Последующие запросы идут за 300–500 мс.
xdotool и Wayland. Скрипт с xdotool type работает только в X11. Если у вас Wayland, нужен wtype или ydotool. В проекте пока только X11-версия.
Кодировка при xdotool type. Если вставляемый текст содержит кириллицу, а раскладка клавиатуры в момент вставки английская — текст может превратиться в мусор. Простое решение: переключить раскладку перед вставкой или использовать xclip/xsel для вставки через буфер обмена вместо эмуляции набора.
Проект живёт на GitLab. Клонируете, запускаете setup.sh, вешаете скрипт на хоткей — и получаете голосовой ввод по всей системе за один вечер. Whisper large-v3 на GPU распознаёт русскую речь с WER около 10% из коробки, с дообученной моделью — около 6%. Kokoro TTS озвучивает ответы Claude Code, если это нужно. Ollama подчищает ошибки распознавания с учётом контекста.
Из зависимостей — NVIDIA GPU от 6 ГБ VRAM, Docker с nvidia-container-toolkit и пара минут на настройку. По соотношению «усилия / результат» это одна из лучших оптимизаций рабочего процесса, которые я делал за последний год.