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>
This commit is contained in:
2026-07-23 14:53:30 +02:00
parent c69dddd8f5
commit 66ecf55ea9
18 changed files with 780 additions and 0 deletions
+4
View File
@@ -0,0 +1,4 @@
# Files
- [Architektur-Übersicht](overview.md) - 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.
- [Source-Map](source-map.md) - Verzeichnisstruktur und Datei-Referenzen für whisper-local. Jede Datei mit ihrer Verantwortung.
+91
View File
@@ -0,0 +1,91 @@
---
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.
+108
View File
@@ -0,0 +1,108 @@
---
type: SourceMap
title: Source-Map
description: Verzeichnisstruktur und Datei-Referenzen für whisper-local. Jede Datei mit ihrer Verantwortung.
tags: [source-map, file-inventory]
---
# Source-Map
## Projekt-Root
| Datei | Beschreibung |
|---|---|
| `pyproject.toml` | Projekt-Metadaten, plattformabhängige Dependencies, Entry-Point `whisper-local` |
| `config.example.toml` | Konfigurations-Vorlage mit allen Sektionen und Defaults |
| `uv.lock` | Lock-File für reproduzierbare Installationen |
| `build.ps1` | Windows-Build-Skript: PyInstaller + versioniertes ZIP |
| `whisper_local.spec` | PyInstaller-Build-Konfiguration (DLLs, Datas, Hidden-Imports) |
| `README.md` | Nutzer-Dokumentation: Installation, System-Dependencies, Konfiguration |
| `CLAUDE.md` | Agent-Instruktionen: Entwicklungsumgebung, Architektur, Test-Konventionen |
| `AGENTS.md` | OpenWiki-Referenz für automatisierte Doku-Updates |
## `whisper_local/` — Hauptpaket
| Datei | Verantwortung |
|---|---|
| `__init__.py` | Paket-Marker |
| `__main__.py` | `App`-Klasse, `main()`-Entry-Point, Orchestrator für alle Module |
| `config.py` | `Config`-Dataclass, `load_config()`, `save_config()` — TOML-basiert |
| `recorder.py` | `Recorder`-Klasse — Audio-Aufnahme via `sounddevice.InputStream` |
| `transcriber.py` | `Transcriber`-Klasse — `faster_whisper.WhisperModel`, Modell-Cache-Logik |
### `whisper_local/hotkey/` — Hotkey-Listener
| Datei | Beschreibung |
|---|---|
| `__init__.py` | `HotkeyListener`-Protocol, `create_listener()`-Factory |
| `_evdev.py` | Linux: `EvdevHotkeyListener` — lauscht auf `/dev/input/event*` |
| `_pynput.py` | Windows: `PynputHotkeyListener` — pynput mit Key-Repeat-Unterdrückung |
### `whisper_local/inserter/` — Text-Einfügung
| Datei | Beschreibung |
|---|---|
| `__init__.py` | `Inserter`-Protocol, `create_inserter()`-Factory |
| `_wayland.py` | Linux: `WaylandInserter``wl-copy` + `ydotool key Ctrl+V`, Clipboard-Restaurierung |
| `_win32.py` | Windows: `Win32Inserter``win32clipboard` + pynput `Ctrl+V`, Clipboard-Restaurierung |
### `whisper_local/media/` — Medien-Steuerung
| Datei | Beschreibung |
|---|---|
| `__init__.py` | `MediaController`-Protocol, `create_media_controller()`-Factory |
| `_mpris.py` | Linux: `MprisController` — D-Bus MPRIS2, pausiert alle Playing-Sessions |
| `_smtc.py` | Windows: `SmtcController` — Windows SMTC via `winrt` |
| `_noop.py` | `NoopController` — No-Op-Fallback |
### `whisper_local/microphone/` — Mikrofon-Überwachung
| Datei | Beschreibung |
|---|---|
| `__init__.py` | `MicrophoneMonitor`-Protocol, `create_monitor()`-Factory |
| `_poll.py` | `PollMonitor` — Cross-Platform Polling via `sounddevice.query_devices()` |
| `_win32.py` | `Win32Monitor` — COM `IMMNotificationClient` mit Polling-Fallback |
### `whisper_local/tray/` — Tray-Icon und UI
| Datei | Beschreibung |
|---|---|
| `__init__.py` | `create_tray()`-Factory, `AppState`-Re-Export |
| `_tray.py` | `PystrayApp` (Tray-Icon, Menu, Zustand), `NoOpTray`, `AppState`-Enum |
| `_icon.py` | `create_icon()` — Pillow-basierte Mikrofon-Icon-Generierung je Zustand |
| `_settings.py` | `SettingsDialog` — Tkinter-Dialog für Hotkey, Mikrofon, Medien-Pause |
| `_download_progress.py` | `load_model_with_progress()` — Tkinter-Fortschrittsdialog für Modell-Download |
| `_notification.py` | `notify()` — notify-py Wrapper für Desktop-Benachrichtigungen |
| `_theme.py` | `apply_system_theme()` — sv-ttk + darkdetect |
| `_hotkey_record_pynput.py` | Windows: Hotkey-Aufzeichnung + `check_hotkey_conflict()` via Win32 `RegisterHotKey` |
| `_hotkey_record_evdev.py` | Linux: Hotkey-Aufzeichnung via evdev-Selector |
## `tests/` — Test-Suite
| Datei | Test-Bereich |
|---|---|
| `test_config.py` | Config laden/speichern, Defaults, TOML-Escaping |
| `test_recorder.py` | Recorder start/stop, min_duration-Filter |
| `test_transcriber.py` | Transcriber mit gemocktem WhisperModel |
| `test_hotkey.py` | EvdevHotkeyListener + PynputHotkeyListener, Key-Repeat-Unterdrückung |
| `test_inserter.py` | WaylandInserter + Win32Inserter, Clipboard-Restaurierung |
| `test_media_factory.py` | Factory-Dispatch für MediaController |
| `test_media_mpris.py` | MprisController pause/resume, Circuit-Breaker |
| `test_media_smtc.py` | SmtcController pause/resume, Circuit-Breaker |
| `test_microphone_monitor.py` | PollMonitor Geräte-Erkennung, Start-Check |
| `test_tray.py` | Tray-App, AppState, Icon-Generierung, Settings-Dialog |
| `test_download_progress.py` | Download-Fortschrittsdialog |
| `test_main.py` | App-Integration: Aufnahme-Zyklus, Config-Reload, Mikrofon-Callbacks |
## `docs/superpowers/` — Specs und Pläne
Design-Specs (`specs/`) und Implementierungspläne (`plans/`) für jede Feature-Entwicklung. Die Doku-Sprache ist Deutsch. Die Specs dokumentieren Architektur-Entscheidungen vor der Implementierung und sind wertvoll für das Verständnis historischer Design-Rationale.
## Weitere Verzeichnisse
| Pfad | Beschreibung |
|---|---|
| `systemd/` | `whisper-local.service` — systemd-User-Unit für Linux-Autostart |
| `.github/workflows/` | `openwiki-update.yml` — tägliche OpenWiki-Doku-Aktualisierung |
| `.claude/skills/bump-version/` | Claude-Code-Skill für SemVer-Versionsverwaltung via `uv version --bump` |
| `build/`, `dist/` | PyInstaller-Build-Artifacts (gitignored) |