Voice Wake & Push-to-Talk

Modi

  • Wake-Word-Modus (Standard): Die Spracherkennung läuft permanent und wartet auf Trigger-Wörter (swabbleTriggerWords). Bei einem Treffer startet die Aufnahme, das Overlay zeigt den Text in Echtzeit an und sendet automatisch nach einer Sprechpause.
  • Push-to-Talk (Rechte Option-Taste halten): Halte die rechte Option-Taste gedrückt, um sofort aufzunehmen – ohne Trigger-Wort. Das Overlay erscheint während du die Taste hältst. Beim Loslassen wird der Text nach kurzer Verzögerung weitergeleitet, damit du ihn noch anpassen kannst.

Runtime-Verhalten (Wake-Word)

  • Die Spracherkennung läuft in VoiceWakeRuntime.
  • Der Trigger feuert nur, wenn zwischen dem Wake-Word und dem nächsten Wort eine deutliche Pause liegt (~0,55s Abstand). Das Overlay und der Signalton können schon in der Pause starten, bevor der eigentliche Befehl beginnt.
  • Stille-Fenster: 2,0s während des Sprechens, 5,0s wenn nur das Trigger-Wort erkannt wurde.
  • Harter Stopp: 120s, um endlose Sessions zu verhindern.
  • Debounce zwischen Sessions: 350ms.
  • Das Overlay wird über VoiceWakeOverlayController gesteuert und zeigt committed/volatile Text farblich unterschiedlich an.
  • Nach dem Senden startet die Erkennung sauber neu und wartet auf den nächsten Trigger.

Lifecycle-Invarianten

  • Wenn Voice Wake aktiviert ist und die Berechtigungen erteilt wurden, sollte die Wake-Word-Erkennung immer lauschen (außer während einer expliziten Push-to-Talk-Aufnahme).
  • Die Sichtbarkeit des Overlays (auch manuelles Schließen über den X-Button) darf niemals verhindern, dass die Erkennung wieder startet.

Sticky-Overlay-Fehlermodus (früher)

Früher konnte Voice Wake “tot” erscheinen, wenn das Overlay hängen blieb und du es manuell geschlossen hast. Der Neustart-Versuch der Runtime wurde durch die Overlay-Sichtbarkeit blockiert und kein weiterer Neustart wurde geplant.

Verbesserungen:

  • Der Neustart der Wake-Runtime wird nicht mehr durch die Overlay-Sichtbarkeit blockiert.
  • Das Schließen des Overlays triggert ein VoiceWakeRuntime.refresh(...) über den VoiceSessionCoordinator, sodass manuelles X-Schließen immer das Lauschen wieder aufnimmt.

Push-to-Talk-Details

  • Die Hotkey-Erkennung nutzt einen globalen .flagsChanged-Monitor für die rechte Option-Taste (keyCode 61 + .option). Wir beobachten nur Events (kein Swallowing).
  • Die Aufnahme-Pipeline läuft in VoicePushToTalk: startet Speech sofort, streamt Partial-Texte zum Overlay und ruft VoiceWakeForwarder beim Loslassen auf.
  • Wenn Push-to-Talk startet, pausieren wir die Wake-Word-Runtime, um konkurrierende Audio-Taps zu vermeiden. Sie startet automatisch nach dem Loslassen neu.
  • Berechtigungen: benötigt Mikrofon + Speech; für Event-Erkennung ist Accessibility/Input Monitoring nötig.
  • Externe Tastaturen: Manche geben die rechte Option-Taste nicht wie erwartet weiter – biete einen Fallback-Shortcut an, wenn User Probleme melden.

Benutzer-Einstellungen

  • Voice Wake-Toggle: aktiviert die Wake-Word-Runtime.
  • Cmd+Fn halten zum Sprechen: aktiviert den Push-to-Talk-Monitor. Deaktiviert auf macOS < 26.
  • Sprach- und Mikrofon-Auswahl, Live-Pegel-Anzeige, Trigger-Wort-Tabelle, Tester (nur lokal, leitet nicht weiter).
  • Die Mikrofon-Auswahl merkt sich die letzte Auswahl, wenn ein Gerät getrennt wird, zeigt einen Hinweis und fällt temporär auf das System-Standard-Mikrofon zurück, bis es wieder verfügbar ist.
  • Sounds: Signaltöne bei Trigger-Erkennung und beim Senden; Standard ist der macOS-Systemsound “Glass”. Du kannst für jedes Event eine beliebige NSSound-kompatible Datei wählen (z. B. MP3/WAV/AIFF) oder No Sound auswählen.

Weiterleitungs-Verhalten

  • Wenn Voice Wake aktiviert ist, werden Transkripte an den aktiven Gateway/Agent weitergeleitet (derselbe Local-vs-Remote-Modus wie im Rest der Mac-App).
  • Antworten werden an den zuletzt genutzten Main-Provider geliefert (WhatsApp/Telegram/Discord/WebChat). Bei Fehlern wird der Error geloggt und der Run bleibt über WebChat/Session-Logs sichtbar.

Weiterleitungs-Payload

  • VoiceWakeForwarder.prefixedTranscript(_:) stellt den Machine-Hint vor dem Senden voran. Wird von Wake-Word- und Push-to-Talk-Pfaden gemeinsam genutzt.

Schnelle Verifikation

  • Aktiviere Push-to-Talk, halte Cmd+Fn, sprich, lass los: Das Overlay sollte Partial-Texte zeigen und dann senden.
  • Während du die Taste hältst, sollten die Menüleisten-Ohren vergrößert bleiben (nutzt triggerVoiceEars(ttl:nil)); sie verschwinden nach dem Loslassen.