Files
knowledge-base/decisions/2026-05-05-mac-dictation-groq-hammerspoon.md
dttb 265d99b378 Mac dictation: Hammerspoon + Groq Whisper решение
- decisions/2026-05-05-mac-dictation-groq-hammerspoon.md: полный план,
  грабли с раскладкой, fallback на whisper-cpp, восстановление на новом Mac
- notes/ru-geoblocked-services.md: реестр CDN с RU-блоком
  (cdn.spokenly, dl.wisprflow и пр.) + принципы обхода
- snippets/mac-dictation/: рабочая версия скриптов и init.lua

Триггер — одиночный Fn, Groq cloud first → tiny local fallback,
вставка через hs.eventtap.event keycode 9 (минует ru-keymap warnings).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 16:27:17 +03:00

73 lines
6.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 2026-05-05 — Mac dictation: Hammerspoon + Groq Whisper
## Контекст
Олег на Intel MacBook Pro (i9-9880H, 2019), нужна голосовая диктовка для русского. Все современные приложения (superwhisper PRO, VoiceInk, Spokenly Parakeet) либо требуют Apple Silicon, либо платную PRO-лицензию ($150-250). Бесплатный free-tier у superwhisper исчерпан и валидируется на их сервере (см. [feedback_superwhisper_no_license](../../.claude/projects/-Users-ai-knowledge-base/memory/feedback_superwhisper_no_license.md)).
## Решение
Свой скрипт + Hammerspoon + Groq Whisper API:
- **Hammerspoon** ловит глобальный hotkey `⌘⇧D`
- **Bash скрипт** toggle-режим: первый запуск → ffmpeg запись с микрофона; второй → стоп → POST в Groq → текст в `/tmp/groq-dictate.last`
- **Lua callback** в Hammerspoon читает файл, кладёт в pasteboard, нажимает Cmd+V через `hs.eventtap.keyStroke`
- **Groq Whisper-large-v3-turbo** — бесплатно ~14400 запросов/день, 0.5с на 4-сек запись, RU IP не блочится
## Файлы
- `~/bin/groq-dictate.sh` — скрипт записи + Groq POST + **fallback на whisper-cpp** + write to `/tmp/groq-dictate.last`
- `~/bin/dictation-doctor.sh` — health-check всех компонентов (Hammerspoon / TCC / зависимости / Groq / mic / Fn-key); запускать когда «не работает»
- `~/.hammerspoon/init.lua` — Fn (одиночное нажатие) trigger через eventtap, paste через `hs.eventtap.keyStroke`
- `~/.cache/whisper-cpp/ggml-tiny-q5_1.bin` — 31MB локальная модель для offline fallback
- Groq API key — в `reference_groq_api.md` private memory
## Финальный hotkey
**Fn (Globe) одиночное нажатие** — toggle (старт/стоп). Срабатывает быстрее ⌘⇧D, освобождает руки. Apple Dictation на двойное Fn остаётся (если не отключить «Нажатие клавиши Fn» в System Settings → Keyboard).
## Критические грабли (и фиксы)
1. **Hammerspoon Accessibility кеширует статус** — после Enable в System Settings нужен **`killall Hammerspoon && open -a Hammerspoon`**, иначе Hammerspoon продолжает показывать WARNING и hotkey не работает.
2. **`hs.hotkey.bind({"cmd","shift"}, "d", ...)`** на русской раскладке выдаёт warning `key 'd' not found in active keymap; using ANSI-standard US keyboard layout as fallback, returning '2'`. Решение: **биндить по числовому keycode**`hs.hotkey.bind({"cmd","shift"}, 2, ...)` (2 = физическая клавиша D). Так работает на любой раскладке.
3. **`osascript -e 'tell application "System Events" to keystroke "v" using command down'`** на русской раскладке вместо Cmd+V вставляет UTF-8 байты текста как символы → получается мусор типа `—В—ь—А—∞—ь—В?` для строки «Ты меня слышишь?». Решение: **никогда не использовать `keystroke` для paste**. Использовать `hs.eventtap.keyStroke({"cmd"}, "v")` напрямую из Lua (отправляет настоящий low-level KeyDown event).
4. **Toggle через PID-файл**`/tmp/groq-dictate.pid`. Если процесс упал/убит — удалить руками. Скрипт устойчив: `kill -INT` корректно закрывает .wav, ждёт до 0.5с дописать заголовок.
5. **ffmpeg avfoundation `:0`** = default mic. Если нужен другой — `ffmpeg -f avfoundation -list_devices true -i ""`.
## Стоимость
- Hammerspoon бесплатный
- Groq бесплатный (14400 req/day, ~120 минут диктовки в день — намного больше нужного)
- Итого: 0₽
## Альтернативы которые НЕ подошли
- **superwhisper** — free tier 530 сек, потом сервер бракует
- **VoiceInk** — официально Apple Silicon only, на Intel CPU крутит большую модель часами
- **Spokenly** — `cdn.spokenly.app` блокирует RU IP (3.8 KB/s), Parakeet требует Neural Engine
- **Wispr Flow** — `dl.wisprflow.com` блокирует RU IP, плюс $144/год Pro для регулярного использования
- **MacWhisper** — $59 lifetime + не пробовали (всё уже работало бесплатно)
- **OpenWhispr** — 273MB dmg в GitHub, не докачался
## Связано
- [RU-заблокированные сервисы](../notes/ru-geoblocked-services.md)
- [Groq API](../../.claude/projects/-Users-ai-knowledge-base/memory/reference_groq_api.md)
- [Superwhisper — нет PRO](../../.claude/projects/-Users-ai-knowledge-base/memory/feedback_superwhisper_no_license.md)
## Воспроизведение на новом Mac
```bash
brew install --cask hammerspoon
brew install whisper-cpp jq ffmpeg
mkdir -p ~/bin ~/.hammerspoon ~/.cache/whisper-cpp
# скопировать ~/bin/groq-dictate.sh + ~/bin/dictation-doctor.sh → chmod +x
# скопировать ~/.hammerspoon/init.lua
# скачать локальную fallback-модель (31 MB, GitHub не блочит RU)
curl -sSL -o ~/.cache/whisper-cpp/ggml-tiny-q5_1.bin \
"https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-tiny-q5_1.bin?download=true"
open -a Hammerspoon
# Hammerspoon Preferences → Enable Accessibility → System Settings → включить
killall Hammerspoon && open -a Hammerspoon # ОБЯЗАТЕЛЬНО после grant — кеш
# System Settings → Клавиатура → Нажатие клавиши Fn → "Действие не требуется"
~/bin/dictation-doctor.sh # должно быть всё зелёное
```
Готово. **Fn → говори → Fn** — текст вставится в активное окно.