Голосовое пробуждение и Push-to-Talk
Режимы
- Режим по ключевому слову (по умолчанию): постоянно активный распознаватель речи ждёт триггерные токены (
swabbleTriggerWords). При совпадении начинается захват, показывается оверлей с частичным текстом и выполняется автoотправка после паузы. - Push-to-talk (удержание правой Option): удерживайте правую клавишу Option для немедленного захвата — без триггера. Оверлей отображается во время удержания; отпускание завершает ввод и отправляет его с короткой задержкой, чтобы вы могли подправить текст.
Поведение во время выполнения (по ключевому слову)
- Распознаватель речи работает в
VoiceWakeRuntime. - Триггер срабатывает только при наличии осмысленной паузы между ключевым словом и следующим словом (~0,55 с). Оверлей/звонок могут стартовать на паузе ещё до начала команды.
- Окна тишины: 2,0 с при непрерывной речи, 5,0 с если было услышано только ключевое слово.
- Жёсткая остановка: 120 с для предотвращения «убегающих» сессий.
- Дебаунс между сессиями: 350 мс.
- Оверлей управляется через
VoiceWakeOverlayControllerс окраской «зафиксировано/временно». - После отправки распознаватель корректно перезапускается и снова слушает следующий триггер.
Инварианты жизненного цикла
- Если голосовое пробуждение включено и разрешения выданы, распознаватель ключевого слова должен слушать (кроме явного захвата push-to-talk).
- Видимость оверлея (включая ручное закрытие кнопкой X) никогда не должна мешать возобновлению работы распознавателя.
Режим отказа «липкого» оверлея (ранее)
Ранее, если оверлей застревал видимым и вы закрывали его вручную, голосовое пробуждение могло выглядеть «мертвым», потому что попытка перезапуска в рантайме могла блокироваться видимостью оверлея и повторный перезапуск не планировался. Усложнение:- Перезапуск рантайма голосового пробуждения больше не блокируется видимостью оверлея.
- Завершение закрытия оверлея инициирует
VoiceWakeRuntime.refresh(...)черезVoiceSessionCoordinator, поэтому ручное закрытие X всегда возобновляет прослушивание.
Особенности push-to-talk
- Детектирование хоткея использует глобальный монитор
.flagsChangedдля правой Option (keyCode 61+.option). Мы только наблюдаем события (без перехвата). - Конвейер захвата находится в
VoicePushToTalk: немедленно запускает Speech, стримит частичные результаты в оверлей и вызываетVoiceWakeForwarderпри отпускании. - При старте push-to-talk мы приостанавливаем рантайм по ключевому слову, чтобы избежать конкурирующих аудиотапов; после отпускания он автоматически перезапускается.
- Разрешения: требуются Microphone + Speech; для получения событий нужны права Accessibility/Input Monitoring.
- Внешние клавиатуры: некоторые могут не корректно экспонировать правую Option — предложите запасное сочетание, если пользователи сообщают о пропусках.
Пользовательские настройки
- Переключатель Voice Wake: включает рантайм по ключевому слову.
- Удерживать Cmd+Fn для разговора: включает монитор push-to-talk. Отключено на macOS < 26.
- Выбор языка и микрофона, индикатор уровня в реальном времени, таблица триггерных слов, тестер (только локально; без пересылки).
- Выбор микрофона сохраняет последнюю настройку при отключении устройства, показывает подсказку об отключении и временно откатывается к системному по умолчанию, пока устройство не вернётся.
- Звуки: звонки при обнаружении триггера и при отправке; по умолчанию используется системный звук macOS «Glass». Можно выбрать любой файл, загружаемый через
NSSound(например, MP3/WAV/AIFF) для каждого события или выбрать No Sound.
Поведение пересылки
- Когда голосовое пробуждение включено, транскрипты пересылаются активному gateway/агенту (тот же локальный или удалённый режим, что и у остального приложения для macOS).
- Ответы доставляются в последний использованный основной провайдер (WhatsApp/Telegram/Discord/WebChat). Если доставка не удалась, ошибка логируется, а запуск всё равно виден через WebChat/логи сеанса.
Полезная нагрузка пересылки
VoiceWakeForwarder.prefixedTranscript(_:)добавляет подсказку о машине перед отправкой. Используется совместно путями по ключевому слову и push-to-talk.
Быстрая проверка
- Включите push-to-talk, удерживайте Cmd+Fn, говорите, отпустите: оверлей должен показать частичные результаты и затем отправить.
- Во время удержания «уши» в строке меню должны оставаться увеличенными (используется
triggerVoiceEars(ttl:nil)); после отпускания они уменьшаются.