VoicePult/README.md
2026-10-03 11:07:47 +02:00

18 KiB
Raw Permalink Blame History

VoicePult

Ein lokales, responsives Audio-Patchpanel für Linux mit PipeWire-Pulse oder PulseAudio. Anwendungen werden auf virtuelle Kanäle gelegt. Jeder Kanal kann gleichzeitig auf einen gewählten Geräteausgang und in ein virtuelles Mikrofon spielen.

Automatische Einrichtung auf einem neuen Computer

Den gesamten VoicePult-Ordner auf den neuen Linux-Rechner kopieren und darin ausführen:

bash setup.sh

Alternativ bei gesetztem Ausführungsrecht: ./setup.sh. Als normalen Benutzer in der angemeldeten Desktop-Sitzung ausführen, nicht mit sudo. Das Setup fordert das sudo-Passwort selbst an, wenn Systempakete fehlen. Für Paketdownloads ist Internet erforderlich; VoicePult selbst arbeitet danach lokal.

Das Setup:

  1. Prüft Python ≥ 3.10, pactl, Browser und xdg-open; installiert fehlende Pakete über apt (Debian/Ubuntu/Mint), dnf (Fedora) oder pacman (Arch/Manjaro).
  2. Nutzt einen vorhandenen PulseAudio-/PipeWire-Server. Fehlt die Audio-Umgebung vollständig, installiert es PipeWire-Pulse und WirePlumber. Ein vorhandener Audiostack wird nicht ersetzt.
  3. Installiert eine eigenständige Programmkopie unter ~/.local/share/voicepult/app und einen Eintrag VoicePult im Anwendungsmenü.
  4. Richtet Autostart nach Benutzeranmeldung als systemd --user-Dienst ein; ohne erreichbare systemd-Benutzersitzung über einen XDG-Autostart-Eintrag.
  5. Startet VoicePult, prüft das virtuelle Eingabegerät VoicePult Mikrofon und öffnet die Oberfläche im Browser. Beim späteren Anmelden startet der Audioteil im Hintergrund, ohne ein Browserfenster zu öffnen.

Persönliche Einstellungen liegen bei dieser Installation in ~/.config/voicepult/config.json. Die Standardpfade berücksichtigen XDG_DATA_HOME, XDG_CONFIG_HOME und XDG_STATE_HOME. Die ursprüngliche Projektkopie darf nach der Installation verschoben werden. Einstellungen aus deren .voicepult-Ordner werden bewusst nicht importiert: Audiogeräte eines anderen Rechners passen nicht zur neuen Installation. Vorhandene Einstellungen der installierten Version bleiben bei erneutem Setup erhalten.

Nützliche Optionen:

./setup.sh --dry-run                         # Nur anzeigen, nichts ändern
./setup.sh --no-autostart                    # Installation ohne Anmeldestart
./setup.sh --no-open                         # Starten, ohne Browser zu öffnen
./setup.sh --no-start                        # Nur installieren, keine Dienste starten
./setup.sh --skip-packages --no-start        # Voraussetzungen extern bereitstellen

--no-start lässt den konfigurierten Autostart bestehen. Für eine reine Dateieinrichtung zusätzlich --no-autostart angeben. Die Optionen können kombiniert werden. Erneute Ausführung aktualisiert die Programmdateien; ein laufender verwalteter Dienst wird bei normalem Setup neu gestartet. Eine noch manuell gestartete Projektinstanz wird nicht ungefragt beendet; das Setup weist auf den nötigen Wechsel zur installierten Version hin.

Bei systemd-Installation:

systemctl --user status voicepult.service
journalctl --user -u voicepult.service -n 80
systemctl --user restart voicepult.service
systemctl --user stop voicepult.service
systemctl --user disable voicepult.service   # Autostart ausschalten

Ohne systemd liegen Servermeldungen in ~/.local/state/voicepult/server.log; der Autostart liegt in ~/.config/autostart/voicepult.desktop. Das Setup installiert keine Desktop-Umgebung und keine Hardwaretreiber. Ein funktionsfähiger Linux-Desktop wird vorausgesetzt; Windows/macOS werden nicht unterstützt. Bei Arch wird keine vollständige Systemaktualisierung ausgelöst. Falls die Paketdatenbank veraltet ist, das System regulär aktualisieren und das Setup erneut ausführen.

Die Installationslogik ist automatisiert mit isolierten Zielverzeichnissen, wiederholter Installation und Pfaden mit Leer-/Sonderzeichen getestet. Paketinstallationen auf frischen Distributions-VMs sind noch nicht getestet. Paketzuordnung nach den offiziellen Verzeichnissen: Ubuntu PipeWire-Pulse, Fedora PulseAudio-Werkzeuge, Fedora PipeWire, Arch PipeWire.

Direkt aus dem Projekt starten (ohne Installation)

Voraussetzungen: Python 3.10 oder neuer, pactl und ein laufender PipeWire-Pulse-/PulseAudio-Server in deiner normalen Desktop-Sitzung. Keine Python-/npm-Pakete erforderlich. Unter Debian/Ubuntu gehört pactl zu pulseaudio-utils.

./start.sh

Danach http://127.0.0.1:8765 im Browser öffnen. Nicht mit sudo starten: Audio läuft im Kontext deines angemeldeten Benutzers. Die App läuft, solange der Server läuft; das Browserfenster darf geschlossen werden. Beenden mit Strg+C im Serverterminal. Dabei werden zugeordnete Audiostreams zurückgeleitet und die eigenen virtuellen Geräte entfernt.

Anderer Port:

./start.sh --port 8766

Firefox auf Kopfhörer und Mikrofon

  1. Einen Kanal erstellen, beispielsweise Browser.
  2. In Firefox Audio abspielen, damit ein Stream erscheint. Bei Firefox den Kanal Browser auswählen.
  3. Am Kanal Kopfhörer und Mikrofon-Mix einschalten.
  4. Rechts als Ausgabegerät den Kopfhörer-Ausgang auswählen.
  5. In Discord, OBS, Firefox oder der Konferenz-App VoicePult Mikrofon als Eingabegerät auswählen. VoicePult zeigt unter dem Mikrofon-Mix an, welche laufenden Anwendungen das virtuelle Eingabegerät tatsächlich verwenden. Falls eine Anwendung ihre Geräteliste nicht aktualisiert, die Audioeinstellungen neu öffnen oder die Anwendung neu starten. „VoicePult_Mix“ ist der interne Misch-Ausgang; als App-Eingabe wird „VoicePult Mikrofon“ verwendet.
  6. Für die eigene Stimme rechts Stimme direkt in den Mix aktivieren und das echte Mikrofon auswählen.

Ein physisches Mikrofon ist ein Eingabegerät. Deshalb stellt VoicePult ein zusätzliches virtuelles Mikrofon bereit, in dem Anwendungs-Audio und optional deine Stimme zusammenlaufen. Gesprächspartner hören diesen Mix erst, wenn die Gesprächs-App dieses Eingabegerät verwendet. Die Gesprächs-App selbst sollte nicht in denselben Mikrofon-Mix geleitet werden, um Echos zu vermeiden. Rauschunterdrückung in Gesprächs-Apps kann Musik im Mix unterdrücken.

Live-Wellenform, Darkmode und Mehrfach-Routing

Oben rechts schaltet der Darkmode-Schieber das Erscheinungsbild um. Im Live-Panel wählst du den Mikrofon-Mix oder einen Kanal als Signal. Die Anzeige wertet echte PCM-Daten aus, zeigt Stereo-Wellenformen und RMS-Pegel in dBFS und markiert Vollaussteuerung. Wellenform vergrößern reicht von ×1 bis ×32 (anfangs ×8); dies verändert ausschließlich die Darstellung, nicht das Audiosignal oder den gemessenen Pegel. Mit Anzeige pausieren endet die Auswertung nach spätestens etwa zwei Sekunden ohne weitere Abrufe. Audiodaten bleiben nur kurz im Arbeitsspeicher und werden nicht als Aufnahme gespeichert.

Anwendungen und Dein Mikrofon besitzen jetzt Kanal-Checkboxen. Mehrere Häkchen senden dasselbe Signal gleichzeitig an mehrere Kanäle; Lautstärke, Stummschaltung und Ausgabeziele sind pro Kanal unabhängig. Ohne App-Häkchen erfolgt die Wiedergabe direkt auf dem Geräteausgang. Stimme direkt in den Mix ist ein zusätzlicher direkter Mikrofonweg. Wenn dieses Signal außerdem über einen Kanal in denselben Mix gelangt, wird es doppelt addiert. Den direkten Weg gegebenenfalls ausschalten.

Darkmode, Wellenform-Vergrößerung, ausgewähltes Signal, Pause, Kanalzuordnungen, Mikrofonwege, Geräte, Lautstärken und Stummschaltungen werden serverseitig gespeichert und nach Neustart wiederhergestellt. Die installierte Version verwendet ~/.config/voicepult/config.json. Alte Einzelkanal-Zuordnungen werden automatisch in die Mehrfachauswahl übernommen.

Zugriff von Handy und Tablet

./setup.sh --lan

Danach auf dem Rechner in VoicePult unten Handy & Tablet öffnen. Handy/Tablet mit demselben erreichbaren lokalen Netzwerk verbinden, die angezeigte IP-Adresse mit Port 8765 im Browser öffnen und den Zugangscode eingeben. Der Code bleibt bei Neustarts erhalten und wird auf dem Mobilgerät lokal gespeichert. Ohne Code sind im Netzwerk weder Status, Audiodaten noch Änderungen zugänglich. Auf dem Rechner selbst funktioniert der Zugriff über 127.0.0.1 weiterhin ohne Code.

Die Verbindung verwendet HTTP und ist für ein vertrauenswürdiges privates Netzwerk vorgesehen; keine Router-Portweiterleitung einrichten. Der Code ist keine TLS-Verschlüsselung. Audio bleibt auf dem Rechner; das Mobilgerät ist Fernbedienung und Pegelanzeige. Falls die Rechner-IP per DHCP wechselt, die neue Adresse unten in VoicePult verwenden. Gast-WLAN bzw. Client-Isolation kann Verbindungen zwischen Geräten verhindern. Eine aktive Rechner-Firewall muss TCP-Port 8765 aus dem lokalen Netz erlauben; das Setup verändert keine Firewall-Regeln.

--lan wird in der installierten Startkonfiguration gespeichert. Ohne Installation: ./start.sh --lan. Ohne LAN-Option ist die ursprüngliche Projektversion weiterhin nur unter 127.0.0.1 erreichbar. Die Netzwerkadresse wird beim Serverstart ermittelt.

Funktionen

  • Bis zu 16 virtuelle Kanäle erstellen, umbenennen und löschen.
  • Mehrere Anwendungen auf einem Kanal mischen.
  • Kopfhörer und Mikrofon-Mix je Kanal unabhängig schalten.
  • Lautstärke und Stummschaltung je Kanal; beide Ziele werden gemeinsam geregelt.
  • Physisches Mikrofon optional dem Mikrofon-Mix hinzufügen.
  • Audiostreams alle zwei Sekunden neu erkennen und gespeicherte App-Zuordnungen wieder anwenden.
  • Konfiguration lokal in .voicepult/config.json speichern und beim nächsten Start wiederherstellen.
  • Beim Entfernen einer Zuordnung oder eines Kanals auf den ursprünglichen Ausgang zurückschalten; wenn dieser nicht mehr verfügbar ist, einen verfügbaren Geräteausgang verwenden.
  • Nur eigene Audiomodule verwalten; Module nach einem unvorhergesehenen Prozessabbruch beim nächsten Start bereinigen.
  • Desktop-, Tablet- und Mobil-Layout; Tastaturbedienung und beschriftete Bedienelemente.

Neue Kanäle geben zunächst nur auf dem gewählten Geräteausgang aus. Das echte Mikrofon ist anfangs ausgeschaltet. Gespeicherte Mikrofon-Routen werden beim nächsten Start wiederhergestellt.

Grenzen und Fehlersuche

  • Ohne --lan ist der Server nur lokal erreichbar. Mit --lan ist die Oberfläche mit Zugangscode auch von Handy und Tablet erreichbar.
  • Die Anwendungserkennung verwendet die PulseAudio-Schnittstelle. Native JACK-/ALSA- oder ausschließlich native PipeWire-Streams sind nicht Bestandteil dieser ersten Version.
  • Alle Streams mit derselben Kombination aus Prozessname und Anwendungsname teilen sich eine Kanalauswahl; Firefox-Tabs sind keine separaten Anwendungen.
  • Ein Kanal hat zwei mögliche Ziele: einen gemeinsamen Geräteausgang und den gemeinsamen Mikrofon-Mix. Weitere Geräteausgänge pro Kanal werden noch nicht unterstützt.
  • Die Anzeige „Spielt Audio“ beruht auf dem Stream-Status; sie ist kein gemessener Pegel.
  • Loopbacks fordern 30 ms Pufferung an. Die tatsächliche Gesamtlatenz hängt von den Geräten und der Audiokonfiguration ab.
  • Wenn ein Gerät abgezogen wird, bleibt es ausgewählt und wird als nicht verfügbar angezeigt. Wähle ein anderes Gerät aus oder verbinde es erneut.
  • Wenn eine Anwendung fehlt, dort zuerst Audio starten. Die Oberfläche aktualisiert sich automatisch.
  • Bei „Audioserver nicht erreichbar“ pactl info in deiner Desktop-Sitzung prüfen.
  • Es läuft nur eine VoicePult-Instanz pro Benutzer. Der direkte Projektstart richtet keinen Autostart ein; setup.sh richtet ihn standardmäßig ein.

VoicePult speichert keine Audioaufnahmen und überträgt keine Daten an externe Dienste. Die Live-Anzeige verarbeitet kurze Audioblöcke im Arbeitsspeicher. Die HTTP-API prüft Host, bei LAN-Zugriff zusätzlich den Zugangscode und für Änderungen einen zufälligen Sitzungstoken; es gibt keine CORS-Freigabe.

Entwicklung und Tests

python3 -m unittest discover -s tests -p 'test_*.py' -v
node --check web/app.js

Optionaler Integrationstest bei laufender App:

python3 tests/live_smoke.py

Der Integrationstest benötigt paplay und parec sowie einen ungenutzten Mikrofon-Mix (alle Mikrofon-Routen und die eigene Stimme ausgeschaltet). Während des Tests keine Einstellungen ändern. Er erzeugt einen temporären Kanal, prüft ein künstliches Signal im virtuellen Mikrofon, Lautstärke, Stummschaltung, Anwendungszuordnung, neue Streams, Rückleitung und API-Zugriffsschutz. Das künstliche Tonsignal wird nicht auf den physischen Ausgang geleitet. Testkanäle werden im finally-Block entfernt. Keine Aufnahme des echten Mikrofons.

Aufbau

  • setup.sh: Paketprüfung und Einrichtung für neue Linux-Rechner.
  • scripts/install.py: Benutzerinstallation, Menüeintrag und Autostart.
  • scripts/launcher.py: Start und Browseröffnung der installierten Anwendung.
  • audio_meter.py: PCM-Wellenformen und Pegel, kurzlebige Audioauswertung.
  • lan_access.py: LAN-Zugangscode und Netzwerkadresse.
  • server.py: HTTP-Server, Konfiguration, Anwendungszuordnung und pactl-Anbindung; Python-Standardbibliothek.
  • web/: Oberfläche in HTML, CSS und JavaScript, ohne Build-Schritt oder externe Ressourcen.
  • tests/test_audio.py: automatisierte Tests ohne Audioserver.
  • tests/live_smoke.py: optionaler Test mit echtem Audioserver.
  • tests/test_setup.py: isolierte Installation, Updates, Autostart und Pfadbehandlung.

Signalfluss:

Firefox ─┐                    ┌─ Loopback → Kopfhörer / Geräteausgang
Musik ───┴→ Virtueller Kanal ─┤
                              └─ Loopback → Mix → VoicePult Mikrofon
Echtes Mikrofon (optional) ────────────────→ Mix

Gespeicherte Apps

Der Arbeitsbereich Gespeicherte Apps zeigt alle dauerhaft zugeordneten Anwendungen, auch wenn sie pausiert oder geschlossen sind. Über die Kanal-Checkboxen lässt sich die Mehrfachzuordnung jederzeit ändern. Bestehende Streams werden sofort verschoben; neue Streams erhalten automatisch die gespeicherten Ziele. Die Zuordnungen überstehen einen Neustart. Wird der letzte Kanal abgewählt, verschwindet die gespeicherte Zuordnung. Auf Handy und Tablet findest du den Arbeitsbereich über die Navigation oberhalb der Seite.

Zusätzliche virtuelle Mikrofone

Unter Ziele → Virtuelles Mikrofon hinzufügen lassen sich im laufenden Betrieb bis zu 16 zusätzliche Eingabegeräte anlegen, etwa „VoicePult OBS“ und „VoicePult Gespräch“. Wähle die gewünschten Mikrofone unter Weiterleiten an an jedem virtuellen Kanal. Ein Kanal kann mehrere Mikrofone gleichzeitig speisen; mehrere Kanäle können dasselbe Mikrofon speisen. Jedes Ziel hat eine eigene Lautstärke und Stummschaltung und ist in der Live-Anzeige auswählbar. Für deine Stimme leite dein echtes Mikrofon zunächst auf einen virtuellen Kanal und diesen auf die gewünschten Ziele.

Namen, Lautstärken und Verbindungen werden automatisch gespeichert und beim Start wiederhergestellt. Wähle das jeweilige Gerät in OBS, Element usw. als Eingabe; manche Apps müssen ihre Geräteliste erst neu laden. Beim Löschen eines Mikrofonziels werden nur dessen Verbindungen entfernt. Apps, die es verwendet haben, benötigen anschließend ein anderes Eingabegerät.

Geräuscharmes Umschalten

Zielverbindungen bleiben nach dem Ausschalten intern stumm bestehen. Beim nächsten Einschalten wird kein Loopback neu angelegt; eine kurze Lautstärkerampe blendet das Signal ein und aus. Neue PipeWire-Verbindungen starten stumm, bevor ihr Puffer gefüllt und das Signal eingeblendet wird. Die Stummschaltung von Kanälen und Mikrofonzielen verwendet ebenfalls eine kurze Rampe. Gelöschte Kanäle/Ziele und entfernte Geräteverbindungen werden weiterhin vollständig abgebaut.

Der Integrationstest python3 tests/live_quiet_routes.py prüft fünf Umschaltzyklen, konstante Modul-IDs, Signalspitzen und Stille im ausgeschalteten Zustand. Das Testsignal wird ausschließlich zwischen temporären virtuellen Geräten übertragen. Eine Prüfung der tatsächlichen Kopfhörer-Hardware ersetzt das nicht.

OpenDeck / Stream Deck

Die Integration unter integrations/opendeck/de.voicepult.control.sdPlugin steuert VoicePult über die lokale API. Sie benötigt Node.js ab Version 22 und keine zusätzlichen npm-Pakete. Eine Taste schaltet einen ganzen Kanal oder ein virtuelles Mikrofonziel stumm/an, ohne dessen Verbindungen zu löschen. Die Farben und die AN/AUS-Anzeige folgen dem tatsächlichen Zustand, auch bei Änderungen über die Website. Ist VoicePult nicht erreichbar, erscheint OFFLINE; fehlende Kanäle werden als FEHLT angezeigt.

Die Einrichtung erfolgt bewusst getrennt von der allgemeinen Installation, damit bestehende Stream-Deck-Profile erhalten bleiben:

python3 scripts/install_opendeck.py --device DEINE_GERAETE_ID
python3 scripts/install_opendeck.py --device DEINE_GERAETE_ID --apply

Der erste Aufruf zeigt nur die geplante Belegung. Der zweite sichert das Ausgangsprofil unter ~/.config/opendeck/voicepult-backups/, startet OpenDeck neu und verwendet eine freie Taste für einen VoicePult-Ordner (eigenes Profil mit Zurück-Taste). Ein vorhandenes VoicePult-Profil wird nicht überschrieben. Auf diesem Rechner liegt der Ordner im Default-Profil auf Taste 3, die Zurück-Taste auf Position 15. Enthalten sind Kopfhörer, Voice-Chats, Musik und das Mikrofonziel Discord.

Weitere Kanäle können in OpenDeck über die Aktion VoicePult → Kanal ein/aus auf freie Tasten gezogen und im Einstellungsfeld ausgewählt werden. Die Profilseite wird nicht automatisch mit neuen Kanälen überschrieben.