macOS companion app

Sprach-Overlay

Lebenszyklus des Sprach-Overlays (macOS)

Zielgruppe: Mitwirkende an der macOS-App. Ziel: ein vorhersehbares Verhalten des Sprach-Overlays, wenn sich Aktivierungswort und Push-to-Talk überschneiden.

Verhalten

  • Wenn das Overlay aufgrund des Aktivierungsworts bereits sichtbar ist und die Person die Tastenkombination drückt, übernimmt die Tastenkombinationssitzung den vorhandenen Text, statt ihn zurückzusetzen. Das Overlay bleibt sichtbar, solange die Tastenkombination gedrückt gehalten wird. Beim Loslassen: senden, wenn Text nach dem Entfernen umgebender Leerzeichen vorhanden ist, andernfalls schließen.
  • Nur das Aktivierungswort führt bei Stille weiterhin zum automatischen Senden; Push-to-Talk sendet sofort beim Loslassen.

Implementierung

  • VoiceSessionCoordinator (apps/macos/Sources/OpenClaw/VoiceSessionCoordinator.swift) ist der alleinige Eigentümer der aktiven Sprachsitzung. Es handelt sich um einen @MainActor @Observable-Singleton, nicht um einen Actor. API: startSession, updatePartial, finalize, sendNow, dismiss, updateLevel, snapshot. Jede Sitzung enthält ein UUID-Token; Aufrufe mit einem veralteten oder nicht übereinstimmenden Token werden verworfen.
  • VoiceWakeOverlayController (VoiceWakeOverlayController+Session.swift) rendert das Overlay und leitet Benutzeraktionen (requestSend, dismiss) über das Sitzungstoken an den Koordinator zurück. Es verwaltet niemals selbst den Sitzungsstatus.
  • Push-to-Talk (VoicePushToTalk.begin()) übernimmt jeglichen sichtbaren Overlay-Text als adoptedPrefix (über VoiceSessionCoordinator.shared.snapshot()), sodass beim Drücken der Tastenkombination während der Anzeige des Aktivierungswort-Overlays der Text erhalten bleibt und neue Sprache angehängt wird. Beim Loslassen wartet es bis zu 1.5s auf ein endgültiges Transkript, bevor es auf den aktuellen Text zurückgreift.
  • Bei dismiss ruft das Overlay VoiceSessionCoordinator.overlayDidDismiss auf, wodurch VoiceWakeRuntime.refresh(state:) ausgelöst wird. So wird das Lauschen auf das Aktivierungswort nach dem manuellen Schließen über X, dem Schließen bei leerem Text und dem Schließen nach dem Senden jeweils fortgesetzt.
  • Einheitlicher Sendepfad: Wenn der Text nach dem Entfernen umgebender Leerzeichen leer ist, schließen; andernfalls spielt sendNow den Sendeton einmal ab, leitet den Text über VoiceWakeForwarder weiter und schließt anschließend das Overlay.

Protokollierung

Das Sprachsubsystem ist ai.openclaw; jede Komponente protokolliert unter ihrer eigenen Kategorie:

Kategorie Komponente
voicewake.coordinator VoiceSessionCoordinator
voicewake.overlay VoiceWakeOverlayController/VoiceWakeOverlay
voicewake.ptt Push-to-Talk-Tastenkombination und Aufnahme
voicewake.runtime Aktivierungswort-Laufzeit
voicewake.chime Wiedergabe des Signaltons
voicewake.sync Globale Einstellungssynchronisierung
voicewake.forward Transkriptweiterleitung
voicewake.meter Mikrofonpegelüberwachung

Checkliste zur Fehlerbehebung

  • Streamen Sie die Protokolle, während Sie ein hängen bleibendes Overlay reproduzieren:

    bash
    sudo log stream --predicate 'subsystem == "ai.openclaw" AND category CONTAINS "voicewake"' --level info --style compact
  • Vergewissern Sie sich, dass nur ein aktives Sitzungstoken vorhanden ist; veraltete Callbacks werden vom Koordinator verworfen.

  • Stellen Sie sicher, dass beim Loslassen von Push-to-Talk immer end() mit dem aktiven Token aufgerufen wird; wenn der Text leer ist, muss das Overlay ohne Signalton oder Senden geschlossen werden.

Verwandte Themen

Was this useful?
On this page

On this page