--- type: Workflow title: Aufnahme-Zyklus (Push-to-Talk) description: "Der Kern-Workflow von whisper-local: Hotkey drücken → Audio aufnehmen → Medien pausieren → Hotkey loslassen → transkribieren → Text einfügen → Medien fortsetzen. Sowie Mikrofon-Überwachung und Config-Reload." tags: [workflow, push-to-talk, recording, transcription, media-pause, microphone-monitor] --- # Aufnahme-Zyklus (Push-to-Talk) Der zentrale Workflow wird durch die `App`-Klasse in [`__main__.py`](../../whisper_local/__main__.py) orchestriert. Die beiden Callbacks `on_press` und `on_release` bilden den vollständigen Zyklus. ## Push-to-Talk-Flow ``` Hotkey gedrückt (on_press) 1. Tray.set_state(RECORDING) — Icon wird rot 2. await media.pause() — alle Playing-Sessions pausieren 3. recorder.start() — sounddevice.InputStream öffnet Hotkey losgelassen (on_release) 1. recorder.stop() — Stream schließen, Audio-Array zurück 2. await media.resume() — pausierte Sessions fortsetzen (im finally-Block) 3. Wenn audio == None → Tray WAITING, return 4. Tray.set_state(TRANSCRIBING) — Icon wird gelb 5. transcriber.transcribe(audio) — faster-whisper transkribiert lokal 6. await inserter.insert(text) — Text ins aktive Textfeld einfügen 7. Tray.set_state(WAITING) — Icon wird grau ``` ### Mindestdauer-Filter `Recorder.stop()` verwirft Aufnahmen kürzer als `min_duration` (Standard: 0,5 s). In diesem Fall gibt `stop()` `None` zurück und der Zyklus wird abgebrochen — keine Transkription, kein Einfügen. Das verhindert versehentliche Trigger bei kurzen Hotkey-Berührungen. ### Text-Einfügung mit Clipboard-Restaurierung Beide Inserter-Backends (Wayland und Win32) folgen demselben Muster: 1. Alten Clipboard-Inhalt sichern. 2. Transkribierten Text ins Clipboard setzen. 3. `Ctrl+V` simulieren (ydotool unter Wayland, pynput unter Windows). 4. Kurz warten (`PASTE_DELAY = 0.2s`). 5. Alten Clipboard-Inhalt wiederherstellen (im `finally`-Block). Dadurch bleibt der bisherige Clipboard-Inhalt des Nutzers erhalten. Details siehe [Plattform-Abstraktionen → Inserter](../domain/platform-abstractions.md#inserter). ## Medien-Pause während Aufnahme Wenn `pause_media_during_recording = true` (Standard), pausiert der [MediaController](../domain/platform-abstractions.md#mediacontroller) alle aktiv wiedergebenden Sessions bei Aufnahmestart und setzt nur diejenigen fort, die er selbst pausiert hat. Der Circuit-Breaker deaktiviert die Funktion dauerhaft, wenn D-Bus (Linux) oder SMTC (Windows) nicht verfügbar ist. ## Mikrofon-Überwachung Der `MicrophoneMonitor` läuft als Hintergrund-Task und überwacht Audio-Geräte-Änderungen: - **Gerät entfernt**: Wenn das konfigurierte Mikrofon getrennt wird, wechselt `App._on_configured_microphone_missing` auf das Standard-Gerät, zeigt eine Desktop-Benachrichtigung via [notify-py](../../whisper_local/tray/_notification.py) und setzt eine Tray-Warnung (`set_warning("Mikrofon nicht gefunden")`). - **Gerät hinzugefügt**: Wenn das konfigurierte Mikrofon wieder verfügbar wird, stellt `App._on_microphone_added` es wieder her, benachrichtigt den Nutzer und entfernt die Tray-Warnung. - **Start-Check**: Beim Start meldet `PollMonitor` sofort, wenn das konfigurierte Gerät nicht gefunden wird. Windows verwendet `IMMNotificationClient` (COM Core Audio API) für Event-basierte Benachrichtigungen mit automatischem Polling-Fallback. Linux verwendet den `PollMonitor` (2,5 s Intervall). Details siehe [Plattform-Abstraktionen → Mikrofon-Monitor](../domain/platform-abstractions.md#mikrofon-monitor). ## Config-Reload zur Laufzeit `App._on_config_reload` wird vom [Einstellungs-Dialog](../../whisper_local/tray/_settings.py) aufgerufen und tauscht alle dynamischen Komponenten ohne Neustart aus: 1. Neue Config übernehmen. 2. Recorder neu instanziieren (neues Mikrofon/Sample-Rate). 3. Mikrofon-Monitor stoppen und neu starten. 4. Tray-Warnung zurücksetzen. 5. Alten Media-Controller fortsetzen, neuen erstellen. 6. Hotkey-Listener stoppen und neu starten (`_restart_hotkey`). Der Hotkey-Restart benötigt ein kurzes `await asyncio.sleep(0.1)` zwischen Stop und Start, um den alten Listener sauber abzubauen.