Architektur und Ausführungsmodell

Die persistente Sitzung und der CLI-Client, der Steuer-Socket, der Whisper-Backend-Adapter und die Kaskade der Texteinfügung.

Eine persistente Sitzung, ein Client, der mit ihr spricht

whispskrid ohne Steuerargument gestartet startet eine persistente Sitzung im Vordergrund: Sie lädt die Konfiguration, lädt das Whisper-Modell einmal, öffnet das Aufnahmegerät, startet den Tasten-Listener und den Steuer-Socket und wartet dann.

TastendruckAudioaufnahmeWhisper-TranskriptionEinfüge-KaskadeSteuer-Socket
Der Weg von der Stimme zum Text: Die Aufnahme beginnt beim Drücken, endet beim Loslassen, und der gesamte Puffer geht in einem einzigen Durchgang an den Backend-Adapter. Der Steuer-Socket ist kein Schritt auf diesem Weg – er ist der Seitenkanal, über den ein Desktop-Kurzbefehl die laufende Sitzung steuert.

Ein CTranslate2-Modell braucht je nach Größe und Maschine in der Größenordnung von einer bis mehreren Sekunden zum Laden. Es bei jedem Diktat neu zu laden würde Push-to-Talk unbrauchbar machen: Das ist der Grund für den persistenten Prozess.

whispskrid mit einem Steuerargument gestartet (--dictate, --status, --stop…) handelt als Client: Es verbindet sich mit dem Socket der laufenden Sitzung, sendet einen einzeiligen Befehl, gibt die Antwort aus und beendet sich mit einem Rückgabecode, der OK oder ERR widerspiegelt. Gibt es keine Sitzung, sagt es das und beendet sich mit einem Fehler.

Zwei Wege, ein Diktat auszulösen

Derselbe interne Zustand der persistenten Sitzung wird von einem lokalen Tasten-Listener und vom Steuer-Socket gesteuert.

  • Lokaler Kurzbefehl-Listener (pynput) – er beobachtet den X-Server. pynput unterscheidet Drücken von Loslassen, daher ist die Semantik „ich spreche, solange ich halte" auf diesem Weg nativ. Unter Wayland sieht er nur Fenster, die über XWayland laufen, nie ein natives Wayland-Fenster; es ist ein Best-Effort-Komfort. Standardtaste: rechte Umschalttaste (shift_r), überschreibbar über hotkeys.push_to_talk.
  • CLI-Unterbefehle über den Socket – ein universeller Weg, unabhängig vom Sitzungstyp. Ein Desktop-Kurzbefehl überträgt kein „Taste gehalten / Taste losgelassen", daher funktioniert dieser Weg als Umschalter. --dictate startet die Aufnahme, --dictate-stop beendet sie und fügt ein, --toggle macht je nach Zustand das eine oder andere, --cancel verwirft die laufende Aufnahme ohne Einfügen.

Eine per Taste gestartete Aufnahme kann mit --cancel abgebrochen werden und umgekehrt.

Dauer-Schutzvorkehrung

Die einzige automatische Schutzvorkehrung ist capture.max_seconds (Standard 300).

Bleibt die Taste darüber hinaus gehalten, stoppt die Aufnahme von selbst, das Aufgenommene wird normal transkribiert und eingefügt, und eine Warnung wird protokolliert. Das ist kein Komfort-Timer – es ist Schutz gegen eine hängende Taste oder einen endlos wachsenden Audiopuffer. Automatische Stille-Abschaltung (VAD) bleibt später als Option möglich; der Schlüssel vad.enabled ist im Schema reserviert, aber in v1.0.1 nicht implementiert.

Der Backend-Adapter

Ein Modul backend/ stellt eine schmale Schnittstelle bereit – load, transcribe(audio, language), info – damit eine zweite Engine später hinzugefügt werden kann, ohne den Rest anzufassen.

faster-whisper (CTranslate2) ist die einzige in v1.0.1 ausgelieferte Implementierung; der Schlüssel backend.name ist reserviert, akzeptiert aber nur diesen Wert. whisper.cpp wird als zweites Backend erwogen, später.

Der Adapter instanziiert WhisperModel mit device (auto: CPU oder CUDA), compute_type (auto: int8 auf der CPU, float16 auf CUDA) und download_root auf das verwaltete Modellverzeichnis gerichtet. transcribe() wird mit beam_size (Standard 5), der erzwungenen Sprache oder None und ohne VAD-Filter aufgerufen; es fügt die zurückgegebenen Segmente zusammen und trimmt den Text.

Modellverwaltung

Modelle liegen in einem verwalteten Verzeichnis – /usr/share/whispskrid/whisper-models/ und ~/.local/share/whispskrid/whisper-models/ für eine Paketinstallation, whisper-models/ im Wurzelverzeichnis des Repositorys für eine Quellinstallation.

Das Auflösen eines Kurznamens (base) durchläuft diese Orte der Reihe nach. Der Standard-Hugging-Face-Cache von faster-whisper ist nur ein letzter Ausweg: Das Werkzeug muss offline starten, sobald das Modell vorhanden ist. whispskrid --download-model [NAME] lädt das angeforderte Modell in das Benutzerverzeichnis, prüft, dass es lädt, und beendet sich; das postinst des Pakets bietet diesen Download beim ersten Start an, wenn kein Modell vorhanden ist.

Texteinfügung: ein Einfügen über die Zwischenablage, mit Engine-Kaskade

Sobald der Text transkribiert und nachbearbeitet ist, legt die Einfügeschicht ihn in die Zwischenablage und simuliert ein Einfügen. Die Engine wird einmal beim Start gewählt.

WegWerkzeugeBedingung
Zuerstydotool + wl-clipboardEingabe auf Treiberebene (/dev/uinput) über den Daemon ydotoold; Keycodes hängen vom Tastaturlayout ab; verlangt Mitgliedschaft in der Gruppe input.
Sonstxdotool + xclipStandardweg. Die Fensterklassen-Erkennung (Terminal-Einfüge-Kombination) gibt es nur hier — ydotool kennt kein Zielfenster.
Andernfallsdegradierter ModusKein Tastendruck wird gesendet; der transkribierte Text bleibt für den Rest der Sitzung im Terminal.

Die Tipp-Engine braucht ein Zwischenablage-Werkzeug an ihrer Seite: wl-clipboard unter Wayland – auch beim Rückfall ydotool erforderlich – und xclip unter X11. Das Debian-Paket zieht wl-clipboard und empfiehlt xclip; eine Quellinstallation fügt sie selbst hinzu. Ohne sie erreicht der transkribierte Text nie die Zwischenablage und das Einfügen setzt wieder das ein, was zuletzt von Hand kopiert wurde.

Der vorherige Inhalt der Zwischenablage wird zurückgelesen und nach dem Einfügen wiederhergestellt (regelbar über clipboard.restore, standardmäßig an). Nicht-textueller Inhalt – ein Bild, Dateien – bleibt unangetastet. Unter Wayland mit einer GTK-Anwendung kann die Wiederherstellung dem Lesen der Zwischenablage durch das Fenster vorauseilen; clipboard.defer_restore verschiebt die Wiederherstellung ans Ende der Sitzung, damit das Einfügen nie den alten Inhalt aufgreift.

Funktioniert keine für die aktuelle Sitzung geeignete Engine, stürzt das Werkzeug nicht ab und gibt nichts stillschweigend auf: Es geht in den degradierten Modus. Der transkribierte Text erscheint weiter im Terminal und automatisches Tippen wird für den Rest der Sitzung deaktiviert, statt es – erfolglos – bei jedem Diktat erneut zu versuchen. Einige Fenster verweigern das Einfügen ebenfalls – bestimmte Java-Anwendungen, geschützte Felder; beim ersten solchen Fall geht das Werkzeug auf dieselbe Weise in den degradierten Modus.

Der Steuer-Socket

Eine laufende Sitzung öffnet einen privaten Unix-Socket unter $XDG_RUNTIME_DIR/whispskrid.sock (Modus 0600). Derselbe Befehl mit --dictate, --dictate-stop, --toggle, --cancel, --status oder --stop verbindet sich mit diesem Socket, statt eine zweite Sitzung zu starten.

Das ist es, was Desktop-Kurzbefehle unter Wayland überall funktionieren lässt, auch für native Wayland-Fenster, die der pynput-Listener nie sieht. Das Protokoll besteht aus Textzeilen, ein Befehl pro Zeile, Antwort mit OK oder ERR vorangestellt; ein unbekannter Befehl antwortet ERR unknown-command. Es gibt kein sleep / wake: WhispSkrid hat keinen Ruhezustand.

Es läuft nur eine Sitzung pro Benutzer gleichzeitig; ein durch einen Absturz zurückgelassener Socket wird erkannt und beim nächsten Start ersetzt.

Sprache der Oberfläche und Sprache des Diktats

Das sind zwei getrennte Einstellungen.

Sprache der Oberfläche

Die Zeichenketten des Werkzeugs selbst laufen durch die GNU-gettext-Kette – .po-Kataloge zu .mo kompiliert, aus dem Python-Quellcode extrahiert. Vier Sprachen: Englisch, Französisch, Deutsch, Spanisch.

Sprache des Diktats

-l fr erzwingt die für diese Sitzung an Whisper übergebene Sprache; ohne Argument default_language, dann Whispers Autoerkennung. Keine Konfiguration je Sprache über diese Wahl hinaus.

Whisper setzt Zeichensetzung und Satz-Großschreibung selbst. Die Nachbearbeitung von WhispSkrid beschränkt sich auf das Entfernen von Rand-Leerraum und einen erzwungenen Großbuchstaben beim ersten Zeichen des eingefügten Textes. Keine Ersetzungstabelle, keine Regeln je Sprache.

Siehe das Projekt-Repository für den Code und Guides für den Einstieg.