macOS companion app

Голосове накладання

Життєвий цикл голосового накладання (macOS)

Аудиторія: розробники застосунку для macOS. Мета: забезпечити передбачувану поведінку голосового накладання, коли активація за ключовим словом і режим «натисни й говори» перекриваються.

Поведінка

  • Якщо накладання вже відображається після активації за ключовим словом і користувач натискає гарячу клавішу, сеанс гарячої клавіші приймає наявний текст замість його скидання. Накладання залишається відкритим, доки гарячу клавішу утримують. Після відпускання: надіслати, якщо після обрізання пробілів текст не порожній, інакше закрити.
  • Активація лише за ключовим словом, як і раніше, автоматично надсилає текст після настання тиші; режим «натисни й говори» надсилає його відразу після відпускання клавіші.

Реалізація

  • VoiceSessionCoordinator (apps/macos/Sources/OpenClaw/VoiceSessionCoordinator.swift) — єдиний власник активного голосового сеансу. Це одноелементний об’єкт @MainActor @Observable, а не актор. API: startSession, updatePartial, finalize, sendNow, dismiss, updateLevel, snapshot. Кожен сеанс містить токен UUID; виклики із застарілим або невідповідним токеном відкидаються.
  • VoiceWakeOverlayController (VoiceWakeOverlayController+Session.swift) відтворює накладання та передає дії користувача (requestSend, dismiss) назад через координатор за допомогою токена сеансу. Він ніколи сам не володіє станом сеансу.
  • Режим «натисни й говори» (VoicePushToTalk.begin()) приймає весь текст видимого накладання як adoptedPrefix (через VoiceSessionCoordinator.shared.snapshot()), тому натискання гарячої клавіші під час відображення накладання активації за ключовим словом зберігає текст і додає до нього нове мовлення. Після відпускання він очікує остаточну транскрипцію до 1,5 с, а потім використовує поточний текст як резервний варіант.
  • Під час dismiss накладання викликає VoiceSessionCoordinator.overlayDidDismiss, що запускає VoiceWakeRuntime.refresh(state:), тому ручне закриття кнопкою X, закриття через порожній текст і закриття після надсилання відновлюють прослуховування ключового слова.
  • Уніфікований шлях надсилання: якщо після обрізання пробілів текст порожній, закрити; інакше sendNow один раз відтворює сигнал надсилання, пересилає дані через VoiceWakeForwarder, а потім закриває накладання.

Журналювання

Підсистема голосових функцій — ai.openclaw; кожен компонент записує журнали у власній категорії:

Категорія Компонент
voicewake.coordinator VoiceSessionCoordinator
voicewake.overlay VoiceWakeOverlayController/VoiceWakeOverlay
voicewake.ptt Гаряча клавіша та захоплення в режимі «натисни й говори»
voicewake.runtime Середовище виконання активації за ключовим словом
voicewake.chime Відтворення звукового сигналу
voicewake.sync Синхронізація глобальних налаштувань
voicewake.forward Пересилання транскрипції
voicewake.meter Монітор рівня мікрофона

Контрольний список налагодження

  • Транслюйте журнали під час відтворення проблеми із завислим накладанням:

    bash
    sudo log stream --predicate 'subsystem == "ai.openclaw" AND category CONTAINS "voicewake"' --level info --style compact
  • Переконайтеся, що активний лише один токен сеансу; застарілі зворотні виклики відкидаються координатором.

  • Переконайтеся, що відпускання клавіші режиму «натисни й говори» завжди викликає end() з активним токеном; якщо текст порожній, очікуйте закриття без звукового сигналу та надсилання.

Пов’язані матеріали

Was this useful?
On this page

On this page