Das macht man doch nicht, Trakt

Das macht man doch nicht, Trakt

Auf hnz.io werden gerade keine zuletzt gesehenen Serien mehr importiert. Und es liegt diesmal nicht an mir! Wirklich!Diesmal jedenfalls nicht. Trakt hat meiner kleinen Anbindung schlicht den Stecker gezogen.

Ich finde es völlig in Ordnung, wenn ein Dienst versucht, Geld zu verdienen. Im Gegenteil: Bei vielen Projekten drücke ich sogar die Daumen, dass sie ein tragfähiges Geschäftsmodell finden. Server, Entwicklung und Support bezahlen sich nicht von freundlichen Gedanken. Ich weiß allerdings auch, wie oft genau an diesem Punkt die Enshittification beginnt: Ein Dienst wird erst nützlich, dann unverzichtbar und schließlich Stück für Stück schlechter oder geschlossener.

Monetarisierung allein ist noch keine Enshittification. Heimliche Verschlechterung kommt ihr aber schon ziemlich nahe.

Vorübergehend, aber ohne Vorwarnung

Noch im Februar erklärte Trakt im eigenen Forum, die öffentliche API sei kostenlos und auch ihre kommerzielle Nutzung nicht grundsätzlich eingeschränkt. Anfang August sah die Welt plötzlich anders aus. Kostenlose Konten konnten keine neuen API-Anwendungen mehr anlegen. Bei einigen verschwanden sogar bestehende Anwendungen, die zuvor funktioniert hatten. Wer eine neue App anlegen wollte, bekam stattdessen den Hinweis auf Trakt VIP.

Ganz abgeschaltet hat Trakt seine API also nicht. Der Zugang für kostenlose Entwicklerkonten wurde eingeschränkt und mein Serienimport ist dabei auf der Strecke geblieben. Trakt selbst bezeichnet das als vorübergehende Maßnahme, um Missbrauch zu verhindern. Das kann ein nachvollziehbarer Grund sein. Nur gab es offenbar weder eine vorherige Ankündigung noch einen Zeitplan und nicht einmal eine brauchbare Erklärung für die Menschen, deren Anwendungen plötzlich verschwunden waren.

Das ist der Teil, der mich ärgert. <dass Trakt Geld verdienen möchte: schön und gut. Dass ein Dienst seine Regeln ändert: Schon häufiger erlebt, komme ich mit klar. Aber dass ich die Änderung erst bemerke, weil auf meiner Website nichts mehr ankommt, das ist etwas Blöde.

Und dann war auch der RSS-Feed weg

Als Ausweichroute hätte mir sogar der Verlauf als RSS-Feed gereicht, hatte ich so designt. Wenn die API down ist, war das mein Fallback. Aber wenn ich die Seite jetzt ansurfe, begrüßt mich ein nicht ganz so freundlicher 404-Fehler. Seite nicht gefunden. Und das offenbar nicht nur bei kostenlosen Konten. Selbst Menschen mit laufendem VIP-Abo berichten von plötzlich nicht mehr funktionierenden RSS-Feeds. Eine offizielle Ankündigung dazu habe ich nicht gefunden.

Die API ohne Vorwarnung einschränken und gleichzeitig den RSS-Ausgang zumauern: Das macht man doch nicht. Trakt.

Zum Glück gibt es Ryot nicht bei Cloudron

Zum Glück bietet Cloudron Ryot nicht als fertige App an. Das meine ich nur halb ironisch. Sonst hätte ich vermutlich längst einen Abend, eine Nacht und den darauffolgenden Vormittag damit verbracht, meinen eigenen Medien-Tracker aufzusetzen.

Ryot steht für „Roll Your Own Tracker“ und ist genau die Sorte Projekt, bei der ich gefährlich schnell schwach werde. Die freie, selbst hostbare Anwendung verwaltet nicht nur Filme und Serien, sondern auch Bücher, Spiele, Musik, Podcasts und sogar Trainingseinheiten. Sie kann Daten unter anderem aus Trakt übernehmen, lässt sich mit Jellyfin, Plex, Kodi oder Emby verbinden und bringt Statistiken sowie eine eigene API mit. Die Daten liegen dabei auf dem eigenen Server.

Allerdings ist Ryot kein kleiner Schalter, den ich in Cloudron umlege. Die Installation läuft regulär über Docker, braucht PostgreSQL und je nach Medienart weitere Zugangsschlüssel, etwa für TMDB. Das wäre machbar. Und genau deshalb gefährlich. Ich möchte gerade eigentlich nur wieder drei Serien auf meiner Website anzeigen und nicht aus Versehen eine neue Infrastruktur betreiben.

Erst einmal Simkl

Wahrscheinlich lande ich deshalb vorerst bei Simkl. Der Dienst kann den Trakt-Export als ZIP-Datei übernehmen, einschließlich Verlauf, Merkliste und Bewertungen. Außerdem gibt es eine öffentliche API, über die ich den Serienimport für hnz.io neu bauen kann. Das klingt nach dem deutlich kürzeren Weg.

Natürlich ziehe ich damit erst einmal nur von einem fremden Dienst zum nächsten. Das ist keine große digitale Unabhängigkeitserklärung. Es ist eine pragmatische Lösung, während ich mir in Ruhe anschaue, was dauerhaft funktioniert und wie gut ich meine Daten dort wieder herausbekomme.

Bis dahin gibt es auf hnz.io keinen Serienimport. Ich arbeite dran, da soll sich ZUkunfts-Flo drum kümmern. Und Gegenwarts-Flo ärgert sich leise weiter, dass Trakt nicht nur die Tür abgeschlossen, sondern auch noch den RSS-Fallback zugeschraubt hat.

Was ich stattdessen vorziehe

Viel wichtiger als der Serienimport, ist die neue Blockroll, die ich hier als nächstes ausrollen will. Frank hat drüben bei rivva geschrieben, warum das wichtig ist.. Und Felix hat das Plugin von Christian Pfefferle gleich schon mal für Kirby quasi in Nullzeit angepasst und auf Github veröffentlicht. Danke dir! Und wenn dass dann bei mir ausgerollt ist und funktioniert, dann kümmere ich mich um mein neues, altes Medientracking.

DaVinci Resolve unter Fedora: läuft. Nur nicht einfach so.

DaVinci Resolve unter Fedora: läuft. Nur nicht einfach so.

DaVinci Resolve gibt es für Linux. D astimmt erst mal alles dran. Nur einfach es tatsächlich zum Laufen zu bringen, war es nicht.

Ich wollte meine MKV-Aufnahmen aus OBS unter Fedora schneiden. Kein exotisches Kameramaterial, keine Kinoproduktion, keine acht verschiedenen RAW-Formate. Einfach Aufnahmen aus meinem Stream, dazu eine getrennte Facecam und später automatisch erzeugte Untertitel. Auf dem Papier ist das ein ziemlich überschaubarer Wunsch.

Mein Stand dabei: Fedora 44, eine Nvidia RTX 2070 Super und Resolve als Flatpak. AutoSubs lief bei der Einrichtung zunächst in Version 3.6.2. Bei anderen Versionen können Pfade und einzelne Schritte inzwischen anders aussehen.

In der Praxis musste ich erst Resolve in ein Flatpak verpacken, meine Videos in ein anderes Format umrechnen, Verzeichnisse durch eine Sandbox reichen und am Ende Steam davon überzeugen, einen Port freizugeben, den AutoSubs für sich beanspruchte.

Jetzt läuft es. Und wenn ich mir den Weg dorthin anschaue, ist das entweder eine Erfolgsgeschichte für Linux oder ein ziemlich gutes Beispiel dafür, wie unterschiedlich Menschen das Wort „läuft“ verwenden.

Resolve in eine passende Schachtel packen

Blackmagic Design bietet Resolve zwar für Linux an, richtet sich dabei aber offiziell an eine recht fest umrissene Umgebung. Fedora gehört nicht dazu. Ich hätte nun anfangen können, Bibliotheken auf meinem System passend zu biegen. Das war mir für eine große proprietäre Anwendung allerdings zu heikel.

Meine Lösung wurde resolve-flatpak von pobthebuilder. Das Projekt nimmt den offiziellen Installer von Blackmagic Design und baut daraus ein Flatpak. Resolve landet damit in einer eigenen Umgebung und verteilt seine Erwartungen nicht quer über mein Fedora-System.

Das Projekt beschreibt den grundsätzlichen Bau so:

git clone https://github.com/pobthebuilder/resolve-flatpak.git --recursive
cd resolve-flatpak

flatpak-builder \
  --install-deps-from=flathub \
  --force-clean \
  --repo=.repo \
  .build-dir \
  com.blackmagic.Resolve.yaml

flatpak --user remote-add --no-gpg-verify resolve-repo .repo
flatpak --user install resolve-repo com.blackmagic.Resolve

In meiner Installation heißt die Anwendung com.blackmagic.Resolve. Nicht com.blackmagic.ResolveStudio. Diese kleine Unterscheidung hat mich später beschäftigt, als ich mit remote-info nach einem Update suchen wollte und nur die Meldung bekam, das lokale Repository habe keine Summary-Datei. Denn: Mein resolve-repo war schlicht kein gewöhnlicher Flatpak-Server, sondern das lokale Ergebnis meines eigenen Builds. Ein Update kommt deshalb nicht automatisch über flatpak update. Ich muss das Git-Repository aktualisieren, Resolve neu bauen und die vorhandene Installation ersetzen:

git pull

flatpak-builder \
  --install-deps-from=flathub \
  --force-clean \
  --repo=.repo \
  .build-dir \
  com.blackmagic.Resolve.yaml

flatpak --user install --reinstall resolve-repo com.blackmagic.Resolve

Das ist mehr Arbeit als ein Klick im Software-Center. Dafür weiß ich ziemlich genau, woher das Paket kommt und was bei einem Update passiert. Ich finde diesen Tausch in Ordnung.

Resolve startete danach. Damit war ungefähr die Hälfte des Problems gelöst.

Eigentlich müsste alles laufen... Eigentlich.

Meine OBS-Aufnahme sah technisch vollkommen normal aus: H.264 Main, yuv420p, 30 Bilder pro Sekunde und AAC-Ton mit 48 Kilohertz. Genau die Art von Datei, die auf ziemlich jedem Gerät abgespielt wird, das nicht gerade eine Digitaluhr ist.

Resolve Free unter Linux hat bei H.264 und AAC allerdings eigene Vorstellungen. In der offiziellen Liste der unterstützten Formate für Resolve 19 ist H.264 unter Rocky Linux der Studio-Version mit Nvidia-Grafik vorbehalten. AAC wird dort gar nicht unterstützt. Fedora ist nicht Rocky Linux, aber an der entscheidenden Stelle half mir dieser Unterschied nicht: Mein Material ließ sich nicht so verwenden, wie es aus OBS kam.

Zuerst hoffte ich, ein einfaches Remuxing würde reichen. Dabei wird nur der Behälter gewechselt, ohne Bild und Ton neu zu codieren. Das wäre schnell gewesen und hätte keine zusätzliche Generation erzeugt. Aber ein H.264-Video mit AAC-Ton bleibt auch danach ein H.264-Video mit AAC-Ton.

Die funktionierende Lösung war deshalb FFmpeg und ein Schnittformat, mit dem Resolve unter Linux zuverlässig arbeiten konnte: DNxHR SQ in einer MOV-Datei, dazu unkomprimierter PCM-Ton.

ffmpeg -hide_banner -y \
  -i "$input" \
  -map 0:v:0 \
  -map 0:a? \
  -c:v dnxhd \
  -profile:v dnxhr_sq \
  -pix_fmt yuv422p \
  -c:a pcm_s16le \
  -f mov \
  "$output"

Das Video wird dabei deutlich größer. Sehr deutlich. Dafür kann Resolve es öffnen, flüssig bearbeiten und samt Ton wiedergeben. DNxHR LB und zusätzliche MOV-Metadaten hatte ich ebenfalls ausprobiert. In meinem Ablauf machten sie Probleme. DNxHR SQ mit PCM funktionierte.

Also blieb es dabei.

Aus dem einzelnen Befehl wurde später ein kleines Skript. Es beobachtet einen Eingangsordner mit inotifywait, nimmt neue MKV-Dateien und legt die umgerechneten MOV-Dateien in einem Resolve-Ordner ab. Dafür braucht es unter Fedora neben FFmpeg die inotify-tools:

sudo dnf install ffmpeg inotify-tools

Das ist zusätzlicher Speicherbedarf und ein weiterer Verarbeitungsschritt. Aber es ist auch eine klare Grenze zwischen Aufnahme und Schnitt: OBS produziert sichere MKV-Dateien, das Skript übersetzt sie automatisch und Resolve bekommt genau das Material, mit dem es umgehen kann.

Nicht elegant im Sinne von „Ich werfe jede Datei hinein und alles funktioniert“. Und leider auch nicht angenehm im Sinne von „Ich muss nicht mehr darüber nachdenken“.

Mein Videoschnitt ist eine Konvertierungsstrecke

Die Skripte nehmen mir die Befehle ab. Das Warten, die großen Zwischendateien und die zusätzlichen Arbeitsschritte bleiben.

Bei einem längeren Video sieht mein Ablauf inzwischen so aus: Ich lade die Aufzeichnung von Twitch herunter, weil ich natürlich immer vergesse, rechtzeitig meine lokale Aufnahme zu starten. Dann konvertiere ich sie in ein Format, das Resolve unter Linux zuverlässig verarbeitet. Genauso wie die Files, die OBS produziert. Ich schneide das Video und exportiere es. Anschließend konvertiere ich den Export noch einmal, damit daraus eine vernünftig große Datei wird, die ich bei YouTube hochladen kann.

Das Video wird also vor dem Schnitt übersetzt und danach wieder zurückübersetzt. Dazwischen liegt die eigentliche Arbeit, wegen der ich Resolve überhaupt geöffnet habe.

Bei Social-Media-Clips ist es nicht besser. Die Videos sind zwar kürzer, aber der Ablauf bleibt: schneiden, exportieren, erneut konvertieren. Ohne den letzten Schritt sind die Dateien für ein paar Sekunden oder Minuten Video erstaunlich unhandlich. Mit dem Schritt sind sie gut zu speichern und hochzuladen. Nur muss ich ihn eben jedes Mal machen.

Das funktioniert inzwischen zuverlässig. Der Workflow steht. Aber ein funktionierender Workflow ist nicht automatisch ein guter Workflow. Ich habe aus einem Kompatibilitätsproblem eine kleine Produktionsstraße gebaut. Sie rattert ordentlich vor sich hin, nur möchte ich eigentlich Videos schneiden und nicht hauptberuflich Dateiformate ineinander umfüllen.

Die Sandbox macht ihren Job

Das Flatpak löste meine Bibliotheksprobleme, brachte aber seine eigene Grenze mit. Eine Anwendung in einer Sandbox darf nicht einfach überall auf meine Dateien zugreifen. Das ist grundsätzlich gut. Beim Videoschnitt fällt es nur sofort auf, wenn das Rohmaterial außerhalb der freigegebenen Verzeichnisse liegt.

Einen Ordner kann ich Resolve gezielt mit Schreibzugriff freigeben:

flatpak override --user \
  --filesystem=~/Streaming/Rohmaterial:rw \
  com.blackmagic.Resolve

Anschließend lässt sich das Verzeichnis in Resolve unter Preferences, System und Media Storage eintragen. Ich gebe damit nicht pauschal mein gesamtes Home-Verzeichnis frei, sondern nur den Ort, an dem Resolve tatsächlich arbeiten soll.

Genau für solche Grenzen mag ich Flatpak. Bis ein Plugin auftaucht, das fest davon ausgeht, Resolve liege unter /opt/resolve und könne selbstverständlich auf /usr/lib zugreifen.

AutoSubs trifft auf zwei verschiedene Welten

Für meine Social-Media-Clips wollte ich AutoSubs verwenden. Das Projekt transkribiert lokal und kann die Untertitel direkt als gestaltete Clips in eine Resolve-Timeline schreiben. Unter Fedora kam AutoSubs 3.6.2 bei mir als RPM auf das System. Resolve lief aber im Flatpak.

Damit lebten beide zunächst nebeneinander her.

Das RPM legte sein Lua-Skript hier ab:

/opt/resolve/Fusion/Scripts/Utility/AutoSubs.lua

Die benötigten Ressourcen lagen unter anderem hier:

/usr/lib/autosubs/resources

Resolve im Flatpak konnte mit diesen Orten nichts anfangen. Der erste deutliche Hinweis war:

Could not find the AutoSubs app resources

Mein erster Versuch bestand darin, die Verzeichnisse per Flatpak-Override freizugeben. Das reichte nicht. Innerhalb eines Flatpaks ist /usr Teil der eigenen Laufzeitumgebung. Ein Verzeichnis vom Host lässt sich dort nicht so einhängen, wie ich es zunächst erwartet hatte.

Funktioniert hat ein anderer Weg: Ich habe das Lua-Skript in den Script-Ordner von Resolve innerhalb des Flatpak-Datenbereichs kopiert. Auch die AutoSubs-Ressourcen liegen nun innerhalb dieses Bereichs. Den fest eingetragenen Ressourcenpfad im Lua-Skript habe ich entsprechend angepasst.

Die entscheidenden Orte lagen damit nicht mehr unter /opt und /usr, sondern unterhalb von:

~/.var/app/com.blackmagic.Resolve/

Das ist kein besonders schöner Installationsweg. Er macht aber sichtbar, was hier eigentlich passiert: Das native RPM weiß nichts von der Flatpak-Installation, und das Flatpak weiß nichts von den Dateien des RPM. Ich musste die Brücke selbst bauen.

AutoSubs tauchte danach unter Workspace und Scripts in Resolve auf. Später fehlten noch Teile des Caption-Templates. Auch das war am Ende kein geheimnisvoller Resolve-Fehler, sondern eine unvollständige Ressourcenkette. Lua-Skript, Module, Bilder, Schriften und Fusion-Template müssen gemeinsam in der Umgebung liegen, die Resolve tatsächlich sieht. Nur die Startdatei zu kopieren genügt nicht.

Steam und der Untertitelserver

Als dann alles richtig aussah, meldete AutoSubs trotzdem:

Failed to send Exit via socket

Die Resolve-Integration von AutoSubs startet innerhalb von Resolve einen kleinen Lua-Server. Die AutoSubs-Oberfläche spricht ihn über 127.0.0.1 auf Port 56002 an.

Also habe ich nachgesehen, wer diesen Port benutzte:

ss -tanp | grep 56002

Die Antwort war Steam.

Nicht Resolve. Nicht AutoSubs. Steam hatte zufällig eine lokale Verbindung mit genau diesem Port aufgebaut. Wahrscheinlich war das kein dauerhaft reservierter Port, sondern schlicht Pech bei der automatischen Vergabe. Für AutoSubs war er trotzdem belegt.

Die Lösung war entsprechend unspektakulär:

steam -shutdown
pkill -f /usr/bin/autosubs

Danach habe ich AutoSubs einmal neu gestartet. Es funktionierte.

Es läuft, weil ich die Übergänge kontrolliere

Resolve unter Fedora zum Laufen zu bringen war bei mir nicht die eine Installation mit dem einen geheimen Befehl. Es waren vier Übergänge, die nicht zusammenpassten:

  1. Der offizielle Linux-Installer erwartete eine andere Distribution. Das Flatpak gab ihm eine passende Umgebung.
  2. OBS und Twitch liefern Material, das Resolve Free unter Linux nicht so verarbeitet, wie ich es brauche. Vor dem Schnitt übersetzt FFmpeg es in DNxHR SQ und PCM. Nach dem Export folgt die Übersetzung zurück in ein handliches Format für YouTube und Social Media.
  3. AutoSubs wurde nativ installiert. Skript und Ressourcen mussten in den Datenbereich des Resolve-Flatpaks.
  4. Die Verbindung lief über einen lokalen Port. Steam saß zufällig darauf.

Keines dieser Probleme war für sich besonders dramatisch. Zusammen erzeugten sie aber dieses typische Linux-Gefühl: Das Programm ist installiert, das Fenster geht auf und trotzdem beginnt die eigentliche Einrichtung erst jetzt.

Ich würde diesen Weg nicht allen empfehlen. Wer einfach nur Videos schneiden möchte, hat wenig davon, Dateiformate, Sandboxes und lokale Socket-Verbindungen kennenzulernen. Ich mag an meiner Lösung trotzdem, dass ich sie inzwischen verstehe. Meine Aufnahmen bleiben im offenen OBS-Workflow, die Untertitel entstehen lokal und die notwendigen Übersetzungen übernehmen kleine Skripte.

Nur unsichtbar werden die Übersetzungen dadurch nicht. Jede längere Twitch-Aufzeichnung läuft vor und nach dem Schnitt durch FFmpeg. Jeder kleine Social-Media-Clip wird erst exportiert und anschließend noch einmal auf eine handliche Größe gebracht. Die Skripte verhindern, dass ich jedes Mal Befehle zusammensuchen muss. Zeit, Speicherplatz und einen zusätzlichen Schritt kosten sie trotzdem.

Resolve läuft unter Fedora. Ich kann so arbeiten, das am Ende was rauskommt. Es nervt jetzt nur zuverlässig.

Ein Kabelplan, den ich starten kann

Ein Kabelplan, den ich starten kann

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.

@hnz.io
Angepinnt auf rivva.de

Ich freu mich total! Ein Text von mir ist aktuell auf rivva.de angepinnt. Ich habe keine Ahnung, was das genau bedeutet, aber es ist bestimmt was Tolles! Wenn ihr rivva.de noch nicht kennt: Das ist mein täglicher Aggregator um zu schauen, was so in der deutschen Blog-Szene los ist. Realisiert wird das dankenswerterweise von Frank, den ihr gerne auch unterstützen könnt. Wenn man sich da die Zahlen von Leuten, die etwas Spenden bei Steady so anschaut, dann sind die Zeiten einer "Blogosphäre" oder der "Netzgemeinde" lange her. Schade.

Also: Lasst mal einen Groschen springen. Lohnt sich wirklich und ist meines Wissens im deutschsprachigen Raum einzigartig. Danke.