> ## Documentation Index
> Fetch the complete documentation index at: https://docs2.openclaw.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Голосовое наложение

# Жизненный цикл голосового оверлея (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 theme={"theme":{"light":"min-light","dark":"min-dark"}}
  sudo log stream --predicate 'subsystem == "ai.openclaw" AND category CONTAINS "voicewake"' --level info --style compact
  ```

* Убедитесь, что активен только один токен сеанса; устаревшие обратные вызовы отбрасываются координатором.

* Убедитесь, что при отпускании клавиши функции «нажми и говори» всегда вызывается `end()` с активным токеном; если текст пуст, ожидается закрытие без звукового сигнала и отправки.

## Связанные материалы

* [Приложение для macOS](https://docs2.openclaw.ai/ru/platforms/macos.md)
* [Голосовая активация (macOS)](https://docs2.openclaw.ai/ru/platforms/mac/voicewake.md)
* [Режим разговора](https://docs2.openclaw.ai/ru/nodes/talk.md)
