Мне нужен был голосовой ввод. Не встроенная в ОС диктовка, не облачный API — а простая и главное локальная штука: зажал клавишу, сказал, отпустил, текст появился в активном окне.
Готовых решений, которые бы устроили, сходу не нашёл. Сделал свое. Может, кому будет полезно.
Микрофон → Whisper (локально) → LLM-трансформация (опционально) → вставка в активное окно
Whisper транскрибирует. Ollama (у меня gemma3:12b) обрабатывает результат — что именно делает LLM, целиком определяется промптом. Дефолтный убирает слова-паразиты, расставляет пунктуацию, поправляет регистр. Но через кастомный промпт можно переформатировать текст в email, перевести на другой язык, привести к стилю документации — короче, как настроите. Оба шага работают локально. LLM-трансформацию можно отключить, тогда вставляется сырой текст от Whisper.
Рассчитано на GPU. Один самодостаточный скрипт на платформу.
|
Платформа |
Whisper-бэкенд |
GPU |
|---|---|---|
|
Windows / Linux |
faster-whisper |
NVIDIA CUDA |
|
macOS |
mlx-whisper |
Apple Silicon (Metal) |
Два скрипта вместо одного — осознанное решение. Разным платформам нужны разные бэкенды Whisper, разные механизмы вставки, разные аудио-особенности. Каждый скрипт — самодостаточный, ~400–560 строк, читается за 10 минут. Идея в том чтобы, просмотрев один файл + список зависимостей, можно было валидировать код, который слушает ваш микрофон.
Пребуфер. Если начать запись по нажатию клавиши, первое слово часто теряется — человек начинает говорить раньше, чем палец дожимает кнопку, микрофон не сразу оживает и так далее. Поэтому микрофон пишет в кольцевой буфер постоянно (последние 0.5 секунды), и при старте записи этот буфер подклеивается в начало. Первое слово не обрезается.
Буфер обмена. Вставка текста через Ctrl+V / Cmd+V требует положить текст в буфер обмена. Но там может быть что-то важное. Поэтому есть три политики: restore (вернуть старое содержимое после вставки), clear, preserve. По умолчанию — restore.
Горячая клавиша. По умолчанию Alt (Windows/Linux) или Option (macOS). Дефолты удобны, но могут конфликтовать — стоит переназначить на что-то вроде Pause или комбинацию. У меня стоит Pause. Push-to-talk: зажал — говоришь — отпустил — текст пошёл на транскрипцию.
На NVIDIA GPU 16GB (large-v3 + gemma3:12b) и Apple Silicon M3 16GB (large-v3-turbo + qwen2.5:14b) — результаты схожие:
|
Этап |
Время |
|---|---|
|
Whisper |
1–3 с |
|
LLM-трансформация |
1–3 с |
|
Итого |
2–6 с |
Большие пассажи подольше, но всё ещё юзабельно.
В основном — для набора сообщений в чатах и AI-ассистентах (Cursor, ChatGPT, Slack). Фокус на текстовое поле, зажал клавишу, сказал, отпустил — текст вставился, Enter отправился. Настройка KEYS_AFTER_PASTE позволяет отправить любую клавишу после вставки (или не отправлять ничего).
git clone https://github.com/sancau/whisper-ptt.git cd whisper-ptt python -m venv venv source venv/bin/activate pip install -r requirements-cuda.txt # или requirements-apple-silicon.txt cp .env.example-cuda .env # или .env.example-apple-silicon python whisper_ptt_cuda.py # или whisper_ptt_apple_silicon.py
Для преобладания русского языка (в эпизодами английского) у меня в .env настроено вот так:
WHISPER_PTT_WHISPER_LANGUAGE=ru WHISPER_PTT_WHISPER_INITIAL_PROMPT=Russian speech with possible English tech terms.
GitHub: https://github.com/sancau/whisper-ptt
Лицензия: MIT
Источник


