Fügt generierte OpenWiki-Docs (Architektur, Domain, Betrieb, Tests, Workflows) sowie den GitHub-Actions-Workflow zur automatischen Aktualisierung hinzu. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
5.3 KiB
type, title, description, tags
| type | title | description | tags | |||||
|---|---|---|---|---|---|---|---|---|
| Architecture | Architektur-Übersicht | whisper-local verwendet ein Factory-Pattern mit typing.Protocol-Interfaces für plattformübergreifende Abstraktion. Die App-Klasse orchestriert alle Module über einen asyncio-Event-Loop. |
|
Architektur-Übersicht
Kernprinzip
whisper-local ist plattformübergreifend (Linux + Windows) gebaut. Jede plattformabhängige Funktionalität folgt demselben Muster:
typing.Protocol-Interface im Paket-__init__.py— keine abstrakte Basisklasse, stattdessen structural subtyping.- Plattformspezifische Backends in
_linux.py/_win32.pyUntermodulen. - Factory-Funktion (
create_*()) im Paket-__init__.pydispatcht zur Laufzeit aufsys.platform.
Dieses Muster wird konsequent für Hotkey, Inserter, Media-Controller und Mikrofon-Monitor angewendet. Die Factory-Funktion ist die einzige Stelle, an der Plattform-Logik zentralisiert ist — alle Backends implementieren dasselbe Protocol.
Module und Abhängigkeiten
App (__main__.py)
├── Config (config.py) — TOML-Konfiguration, Dataclass
├── Recorder (recorder.py) — Audio-Aufnahme via sounddevice
├── Transcriber (transcriber.py) — faster-whisper Transkription
├── HotkeyListener (hotkey/) — Systemweiter Hotkey-Listener
│ ├── _evdev.py (Linux)
│ └── _pynput.py (Windows)
├── Inserter (inserter/) — Text-Einfügung ins aktive Fenster
│ ├── _wayland.py (Linux)
│ └── _win32.py (Windows)
├── MediaController (media/) — Medien pausieren/während Aufnahme
│ ├── _mpris.py (Linux, D-Bus)
│ ├── _smtc.py (Windows, SMTC)
│ └── _noop.py (Fallback)
├── MicrophoneMonitor (microphone/) — Geräte-Überwachung
│ ├── _win32.py (Windows, COM)
│ └── _poll.py (Cross-Platform Fallback)
└── Tray (tray/) — Tray-Icon, Settings, Notifications
├── _tray.py — PystrayApp + AppState
├── _icon.py — Pillow-Icon-Generierung
├── _settings.py — Tkinter-Einstellungs-Dialog
├── _download_progress.py — Modell-Download-Fortschritt
├── _notification.py — notify-py Wrapper
├── _theme.py — sv-ttk System-Theme
├── _hotkey_record_pynput.py — Windows Hotkey-Aufzeichnung
└── _hotkey_record_evdev.py — Linux Hotkey-Aufzeichnung
App-Klasse — Der Orchestrator
Die App-Klasse in __main__.py ist der zentrale Orchestrator. Sie instanziiert alle Module im Konstruktor, verdrahtet Callbacks und betreibt den asyncio-Event-Loop.
Schlüsselfluss:
on_press→ Tray auf RECORDING setzen, Medien pausieren, Aufnahme starten.on_release→ Aufnahme stoppen, Medien fortsetzen, transkribieren, Text einfügen, Tray auf WAITING._on_config_reload→ Recorder, Monitor, Media und Hotkey zur Laufzeit austauschen — kein Neustart nötig.
Threading-Modell
- asyncio-Loop läuft im Main-Thread und verwaltet Hotkey-Listener, Mikrofon-Monitor und Media-Controller.
- pynput (Windows) betreibt einen eigenen Thread; Callbacks werden via
call_soon_threadsafein den asyncio-Loop gebridged. - pystray läuft in einem Daemon-Thread; Menu-Callbacks rufen
_on_settings/_quitauf, die wiederum thread-safe in den Loop delegieren. - Tkinter-Dialoge (Settings, Download-Fortschritt) laufen in eigenen Daemon-Threads.
Hotkey-Namen im evdev-Format
Key-Namen folgen einheitlich dem evdev-Format (KEY_F12, KEY_LEFTSHIFT, …) — auch unter Windows. Das pynput-Backend übersetzt intern via _evdev_to_pynput_key(). Dies stellt konsistente Konfiguration über Plattformen hinweg sicher.
Factory-Dispatch-Übersicht
| Modul | Factory | Linux-Backend | Windows-Backend | Fallback |
|---|---|---|---|---|
| Hotkey | create_listener() |
EvdevHotkeyListener |
PynputHotkeyListener |
— |
| Inserter | create_inserter() |
WaylandInserter |
Win32Inserter |
— |
| Media | create_media_controller() |
MprisController |
SmtcController |
NoopController |
| Mikrofon | create_monitor() |
PollMonitor |
Win32Monitor |
PollMonitor (in _win32.py bei COM-Fehler) |
| Tray | create_tray() |
PystrayApp |
PystrayApp |
NoOpTray |
Details zu den einzelnen Backends siehe Plattform-Abstraktionen.
Circuit-Breaker-Muster
MprisController und SmtcController implementieren einen Circuit-Breaker: Wenn die D-Bus- bzw. SMTC-Verbindung fehlschlägt (_bus_broken / _broken), wird der Controller dauerhaft deaktiviert und weitere pause()/resume()-Aufrufe sind No-Ops. Dies verhindert wiederholte Fehler-Logs bei nicht verfügbarer Infrastruktur.
Erweiterungspunkte
- Neue Plattform hinzufügen: Neue
_<platform>.py-Datei im jeweiligen Paket, Protocol implementieren, Factory-Funktion umsys.platform-Check erweitern. - Neues Whisper-Modell:
config.toml→[whisper]modeländern. Modelle werden von HuggingFace heruntergeladen. - Neue Tray-Funktionalität: Menu in
_tray.pyerweitern, Callback inAppverdrahten.