Files
info 66ecf55ea9 docs: OpenWiki-Dokumentation und Auto-Update-Workflow hinzufügen
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>
2026-07-23 14:53:30 +02:00

92 lines
5.3 KiB
Markdown

---
type: Architecture
title: Architektur-Übersicht
description: 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.
tags: [architecture, factory-pattern, protocol, asyncio, platform-dispatch]
---
# Architektur-Übersicht
## Kernprinzip
whisper-local ist plattformübergreifend (Linux + Windows) gebaut. Jede plattformabhängige Funktionalität folgt demselben Muster:
1. **`typing.Protocol`-Interface** im Paket-`__init__.py` — keine abstrakte Basisklasse, stattdessen structural subtyping.
2. **Plattformspezifische Backends** in `_linux.py` / `_win32.py` Untermodulen.
3. **Factory-Funktion** (`create_*()`) im Paket-`__init__.py` dispatcht zur Laufzeit auf `sys.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`](../../whisper_local/__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_threadsafe` in den asyncio-Loop gebridged.
- **pystray** läuft in einem Daemon-Thread; Menu-Callbacks rufen `_on_settings` / `_quit` auf, 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](../domain/platform-abstractions.md).
## 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 um `sys.platform`-Check erweitern.
- **Neues Whisper-Modell**: `config.toml``[whisper]` `model` ändern. Modelle werden von HuggingFace heruntergeladen.
- **Neue Tray-Funktionalität**: Menu in `_tray.py` erweitern, Callback in `App` verdrahten.