Voice Wake и Push-to-Talk

Режимы

  • Режим Wake-word (по умолчанию): всегда включенный распознаватель речи ждет триггерных токенов (swabbleTriggerWords). При совпадении он начинает захват, показывает оверлей с частичным текстом и автоматически отправляет после тишины.
  • Push-to-talk (удержание правой клавиши Option): удерживайте правую клавишу Option для немедленного захвата — триггер не нужен. Оверлей появляется при удержании; отпускание завершает и пересылает после короткой задержки, чтобы вы могли настроить текст.

Поведение runtime (wake-word)

  • Распознаватель речи находится в VoiceWakeRuntime.
  • Триггер срабатывает только при наличии значимой паузы между wake word и следующим словом (~0,55 с разрыв). Оверлей/chime могут начаться на паузе даже до начала команды.
  • Окна тишины: 2,0 с при течении речи, 5,0 с, если услышан только триггер.
  • Жесткая остановка: 120 с для предотвращения неконтролируемых сеансов.
  • Дебаунс между сеансами: 350 мс.
  • Оверлей управляется через VoiceWakeOverlayController с зафиксированной/волатильной окраской.
  • После отправки распознаватель перезапускается чисто, чтобы слушать следующий триггер.

Инварианты жизненного цикла

  • Если Voice Wake включен и разрешения предоставлены, распознаватель wake-word должен слушать (кроме явного захвата push-to-talk).
  • Видимость оверлея (включая ручное закрытие через кнопку X) никогда не должна препятствовать возобновлению распознавателя.

Режим отказа зависшего оверлея (предыдущий)

Ранее, если оверлей застревал видимым и вы закрывали его вручную, Voice Wake мог казаться "мертвым", потому что попытка перезапуска runtime могла быть заблокирована видимостью оверлея, и последующий перезапуск не планировался.

Укрепление:

  • Перезапуск wake runtime больше не блокируется видимостью оверлея.
  • Завершение закрытия оверлея вызывает VoiceWakeRuntime.refresh(...) через VoiceSessionCoordinator, поэтому ручное закрытие X всегда возобновляет прослушивание.

Специфика Push-to-talk

  • Обнаружение горячей клавиши использует глобальный монитор .flagsChanged для правой клавиши Option (keyCode 61 + .option). Мы только наблюдаем события (без поглощения).
  • Конвейер захвата находится в VoicePushToTalk: немедленно запускает речь, передает partials в оверлей и вызывает VoiceWakeForwarder при отпускании.
  • Когда начинается push-to-talk, мы приостанавливаем wake-word runtime, чтобы избежать конкурирующих аудио-захватов; он автоматически перезапускается после отпускания.
  • Разрешения: требуется Microphone + Speech; просмотр событий требует утверждения Accessibility/Input Monitoring.
  • Внешние клавиатуры: некоторые могут не предоставлять правую клавишу Option, как ожидается — предложите резервную комбинацию клавиш, если пользователи сообщают о пропусках.

Пользовательские настройки

  • Переключатель Voice Wake: включает wake-word runtime.
  • Удерживайте Cmd+Fn для разговора: включает монитор push-to-talk. Отключено на macOS < 26.
  • Выборщики языка и микрофона, живой измеритель уровня, таблица триггерных слов, тестер (только локально; не пересылает).
  • Выбор микрофона сохраняет последний выбор, если устройство отключается, показывает подсказку об отключении и временно возвращается к системному по умолчанию, пока оно не вернется.
  • Звуки: chimes при обнаружении триггера и при отправке; по умолчанию системный звук macOS "Glass". Вы можете выбрать любой файл, загружаемый NSSound (например, MP3/WAV/AIFF) для каждого события или выбрать Без звука.

Поведение пересылки

  • Когда Voice Wake включен, транскрипты пересылаются активному шлюзу/агенту (тот же локальный или удаленный режим, используемый остальной частью приложения mac).
  • Ответы доставляются последнему использованному основному провайдеру (WhatsApp/Telegram/Discord/WebChat). Если доставка не удается, ошибка регистрируется, и выполнение все еще видно через логи WebChat/сеанса.

Полезная нагрузка пересылки

  • VoiceWakeForwarder.prefixedTranscript(_:) добавляет подсказку машины перед отправкой. Общий между путями wake-word и push-to-talk.

Быстрая проверка

  • Включите push-to-talk, удерживайте Cmd+Fn, говорите, отпустите: оверлей должен показать partials, затем отправить.
  • При удержании уши в строке меню должны оставаться увеличенными (использует triggerVoiceEars(ttl:nil)); они опускаются после отпускания.