Ich streame unter Fedora. OBS läuft, die Kamera läuft, das Mikrofon funktioniert und auch das Stream Deck tut, was es soll. Das war alles deutlich unspektakulärer, als ich vorher gedacht hatte.

Dann kam der Ton.

Mikrofon, Discord, Spiel, Firebot und die Geräusche vom Stream Deck sollen schließlich nicht nur irgendwie hörbar sein. Sie sollen an den richtigen Stellen hörbar sein. Und an den falschen bitte ausdrücklich nicht.

Ausgerechnet dieses Audiorouting ist inzwischen einer der Teile meines Setups, die mir unter Fedora am besten gefallen. Nicht, weil alles auf Anhieb funktioniert hätte. Das wäre gelogen. Sondern weil ich jetzt ein Skript habe, in dem ziemlich genau steht, was wohin geht.

Kein zusätzliches virtuelles Mischpult mit vielen Knöpfen und einer Konfiguration, an die ich mich drei Monate später nicht mehr erinnere. Ich habe einen Kabelplan, den ich starten kann.

Wer eigentlich was hören darf

Der Stream soll mein Mikrofon hören, die Leute im Discord, Firebot, das Spiel und die Sounds, die ich über das Stream Deck einspiele.

Discord soll dagegen nur meine von OBS bearbeitete Stimme und ausgewählte Sounds vom Stream Deck bekommen. Nicht den Spielton. Nicht Firebot. Und vor allem nicht den Discord-Chat selbst. Sonst hören sich dort alle mit leichter Verzögerung noch einmal.

Ich selbst möchte über den Kopfhörer natürlich mitbekommen, was gerade passiert. Nur meine eigene Stimme möchte ich nicht zeitversetzt hören. Das macht mich innerhalb weniger Sätze vollständig sprechunfähig.

Für diese Trennung legt mein Skript in PipeWire mehrere virtuelle Ausgänge an. Technisch heißen die Dinger Sinks. Das Wort hilft mir beim Verständnis allerdings nur bedingt. Für mich sind das eher beschriftete Räume: Ein Programm wird in den passenden Raum geschickt, OBS nimmt den Raum als eigene Quelle auf und das Skript entscheidet, wer außerdem zuhören darf.

  • discord_sink enthält die Stimmen aus Discord. In OBS heißt diese Quelle Discord-Sound. Ich höre sie auf dem Kopfhörer, Discord selbst bekommt sie aber nicht zurück.
  • firebot_sounds sammelt die Sounds aus Firebot und dem Browser. In OBS landen sie als Firebot-Sounds, auf meinem Kopfhörer ebenfalls, in Discord nicht.
  • soundboard_sounds enthält die Sounds vom Stream Deck. OBS nimmt sie als Soundboard auf, ich höre sie und Discord bekommt eine leisere Kopie.
  • game_audio ist für Spiel- und Systemton zuständig. In OBS heißt die Quelle Game-Sound. Ich höre sie, Discord nicht.
  • discord_micmix mischt meine bearbeitete Stimme mit der leiseren Soundboard-Kopie. Diesen Mix höre weder ich noch OBS. Er geht nur an Discord.

Discords Ausgabe landet also in OBS und auf meinem Kopfhörer, aber niemals wieder in Discord. Firebot und der Spielton bleiben ebenfalls draußen. Nur das Soundboard bekommt einen zusätzlichen Weg in Richtung Sprachkanal.

Meine Stimme nimmt noch einen kleinen Umweg. Das echte Mikrofon landet zuerst in OBS, wird dort gefiltert, komprimiert und begrenzt und anschließend über das Audio-Monitoring in discord_micmix geschickt.

Normalerweise bedeutet Monitoring, dass man sich selbst auf dem Kopfhörer hört. Genau das möchte ich wegen der Verzögerung nicht. Als Monitoring-Gerät ist in OBS deshalb nicht mein Kopfhörer ausgewählt, sondern DiscordMicMix. OBS überwacht meine Stimme gewissermaßen in Richtung Discord. Bei mir kommt diese Spur nicht noch einmal an.

Dadurch hören Stream und Discord dieselbe bearbeitete Stimme. Das rohe Mikrofon bleibt aus dem Discord-Mix heraus. Würde ich beides verbinden, kämen meine unbearbeitete und meine bearbeitete Stimme gleichzeitig an. Lauter wäre das vermutlich. Besser eher nicht.

Ton da. Discord hört nichts.

Ganz geradlinig bin ich zu diesem Aufbau nicht gekommen.

Zwischendurch sah alles richtig aus. Der Mix enthielt Ton, die Verbindungen waren vorhanden und Discord nahm angeblich das passende Gerät auf. Im Mikrofontest war trotzdem nichts zu hören.

Mit pw-play habe ich deshalb testweise direkt etwas in den vorgesehenen Audioweg geschickt. Diese Wiedergabe erkannte Discord plötzlich als Mikrofon. Der Ton war also da und der Weg grundsätzlich offen. Discord behandelte nur den Monitor des virtuellen Ausgangs nicht so, wie ich es brauchte.

Aus discord_micmix.monitor wurde deshalb über eine Remap-Quelle ein richtiges virtuelles Eingabegerät: discord_microphone. In der Oberfläche heißt es erfreulich eindeutig Discord-Mikrofon.

Das war der Punkt, an dem aus einem scheinbar richtigen Aufbau ein tatsächlich funktionierender wurde.

Vorher lagen ein Nachmittag mit Gerätenamen, Stream-IDs, ziemlich vielen Ausgaben von pactl list und dem leisen Verdacht, alles kaputtrepariert zu haben.

Danach hatte ich eine Lösung, die ich vollständig lesen konnte.

Was mein Skript erledigt

Das Skript heißt streaming-audio.sh und liegt bei mir in ~/bin.

Einmalig richte ich damit die virtuellen Audiogeräte ein:

~/bin/streaming-audio.sh install

Vor dem Stream starte ich OBS, Discord und das Soundboard. Anschließend setze ich das Routing:

~/bin/streaming-audio.sh route

Das Skript prüft und erledigt dabei unter anderem:

  • fehlende virtuelle Audiogeräte anlegen
  • game_audio als Standardausgang für neu gestartete Spiele setzen
  • bereits laufende Programme anhand ihrer Namen auf die passenden Ausgänge verschieben
  • die virtuellen Ausgänge mit meinem Kopfhörer verbinden
  • alte oder doppelte Verbindungen aus früheren Versuchen entfernen
  • das OBS-Mikrofon mit 115 Prozent in den Discord-Mix schicken
  • das Soundboard mit 75 Prozent zusätzlich in diesen Mix legen
  • das virtuelle Discord-Mikrofon anlegen und als Systemmikrofon setzen
  • einen bereits laufenden Discord-Aufnahmestrom auf dieses Mikrofon verschieben

Die 75 Prozent gelten nur für die Kopie des Soundboards, die in Discord ankommt. Im Stream und auf meinem Kopfhörer bleibt der Pegel unverändert. Ich kann einen Sound für die Leute im Sprachchat also leiser machen, ohne ihn gleichzeitig für den Stream verändern zu müssen.

Wenn etwas nicht dort landet, wo ich es erwarte, hilft:

~/bin/streaming-audio.sh status

Damit sehe ich die Standardgeräte, die virtuellen Ausgänge, laufende Wiedergabe- und Aufnahmeströme und die relevanten PipeWire-Verbindungen.

Nach dem Stream kann ich außerdem wieder mein echtes Mikrofon als normales Systemmikrofon setzen:

~/bin/streaming-audio.sh restore-mic

In Discord musste ich Discord-Mikrofon einmal als Eingabegerät auswählen. Seitdem stellt das Skript den Aufbau bei jedem route-Durchlauf wieder her und verschiebt auch einen bereits laufenden Discord-Stream auf das richtige Gerät.

Discord merkt sich die Auswahl. Jedenfalls bislang. Software liest solche Sätze bekanntlich gern als Herausforderung.

Das Feintuning bleibt in OBS

Das Skript kümmert sich um die Wege. Wie die einzelnen Quellen klingen, stelle ich weiterhin in OBS ein.

Unter Einstellungen → Audio → Erweitert ist bei mir DiscordMicMix als Audiomonitoring-Gerät ausgewählt.

In den Erweiterten Audioeigenschaften gilt:

  • Mikrofon: Monitor und Ausgabe
  • Discord-Sound: Monitoring aus
  • Firebot-Sounds: Monitoring aus
  • Game-Sound: Monitoring aus
  • Soundboard: Monitoring aus

Nur mein Mikrofon darf über das OBS-Monitoring in den Discord-Mix. Die zusätzliche Verbindung für das Soundboard legt das Skript direkt in PipeWire an.

Für mein Mikrofon nutze ich als Ausgangspunkt die Audiofilter von OBS:

  1. Rauschunterdrückung
  2. bei Bedarf einen Expander statt eines harten Noise Gates
  3. einen Kompressor mit ungefähr −28 dB Threshold, 3:1 Ratio, 8 ms Attack, 150 ms Release und 6 dB Ausgangsverstärkung
  4. einen Limiter bei ungefähr −5 dB und 80 ms Release

Beim normalen Sprechen liegt mein Signal grob zwischen −18 und −12 dB. Wenn ich lauter werde, darf es Richtung −10 bis −6 dB gehen. Die Kopie meiner Stimme wird auf dem Weg zu Discord zusätzlich auf 115 Prozent gesetzt. Das verändert nur den Pegel in Discord, nicht den im Stream.

Auch Discord-Sound wird in OBS etwas eingefangen. Dort sitzt zunächst ein leichter Kompressor mit ungefähr −20 dB Threshold, 2,5:1 Ratio, 10 ms Attack, 150 ms Release und 2 dB Ausgangsverstärkung.

Dahinter folgt ein zweiter, sehr zurückhaltender Kompressor mit meinem Mikrofon als Sidechain-Quelle. Sobald ich spreche, wird Discord um ungefähr zwei oder drei Dezibel abgesenkt. Das reicht für etwas mehr Verständlichkeit, ohne dass das Gespräch hörbar verschwindet. Ein Limiter bei ungefähr −8 dB fängt Spitzen ab.

Mein Ziel ist, dass Discord ungefähr zwischen −16 und −10 dB liegt und meine Stimme etwas darüber bleibt. Das sind meine Werte für mein Mikrofon, meinen Abstand und meine Stimme. Wer den Aufbau übernimmt, wird an dieser Stelle selbst hören, aufnehmen und nachstellen müssen.

Die Technik an der richtigen Stelle

Natürlich lässt sich ein vergleichbares Setup auch unter Windows bauen. Dort hatte ich dafür virtuelle Audiokabel, Mischpulte und zusätzliche Programme. Unter Fedora ist meine Lösung nicht weniger technisch. Eher im Gegenteil.

Die Technik sitzt für mich jetzt nur an einer angenehmeren Stelle.

Mein Audiorouting besteht aus Text. Ich kann es sichern, verändern, vergleichen und nach einem Neustart wieder anwenden. Wenn ich wissen möchte, weshalb Discord das Soundboard hört, gibt es dafür eine konkrete Verbindung. Wenn Firebot nicht im Sprachkanal landen soll, existiert dieser Weg einfach nicht.

Das Skript kann keine schlechte Mikrofonposition ausgleichen und auch nicht entscheiden, ob eine Stimme angenehm laut ist. Dafür ist weiterhin OBS zuständig. Es stellt aber reproduzierbar die Verkabelung her.

OBS läuft. Das Stream Deck läuft. Und das vermeintlich komplizierteste Stück meiner Streaming-Einrichtung ist inzwischen der Teil, den ich am liebsten mag.

Ich habe keinen Zustand in einem virtuellen Mischpult mehr, den ich mir merken muss.

Ich habe einen Kabelplan, den ich starten kann.

Kommentar schreiben

Mit dem Absenden stimmst du zu, dass die eingegebenen Daten gespeichert und in Form eines Kommentars dargestellt werden dürfen.