Audio Ingest Rework
Hinweis zum Stand (2026-04-07)
Dieses Dokument beschreibt das Zielbild. Der aktuelle Ist-Stand in Phase 1 ist:
- shared ingest runtime + unified source factory sind implementiert
stdin, http-raw, icecast Adapter sind implementiert
- Icecast Decoder-Layer + ffmpeg fallback sind implementiert
- native Decoder
mp3 / oggvorbis / aac sind noch Platzhalter
- funktionaler Decode-Pfad heute: ffmpeg fallback
Ziel
fm-rds-tx soll mittelfristig mehrere Audio-Ingest-Pfade sauber unterstützen, ohne den bestehenden ffmpeg-Pfad kaputt zu machen.
Einordnung des Phase-1-Ergebnisses
Mit Phase 1 wurde die Audio-Zuführung erstmals als eigenständiges Subsystem vor den bestehenden TX-/DSP-Pfad gezogen.
Die bestehende Sendekette bleibt weitgehend unangetastet; neue Ingest-Quellen laufen stattdessen über eine gemeinsame Runtime-Schicht, die Lifecycle, Formatwandlung und Basistelemetrie bündelt und weiterhin in den bestehenden audio.StreamSource einspeist.
Konkret umfasst dieser Stand:
- gemeinsame Ingest-Runtime
- zentrale Source-Auswahl für
stdin, http-raw und icecast
- Umstellung von
/audio/stream auf den Ingest-Pfad
- Runtime-/Source-Stats im Control-Plane-Output
- Icecast-Adapter mit Reconnect-/Decoder-Policy
- Decoder-Layer mit explizitem Fallback-Pfad
Wichtig ist die ehrliche Abgrenzung:
Die Decoder-Architektur ist vorhanden, aber native Decoder für mp3, oggvorbis und aac sind aktuell noch Platzhalter. Praktisch funktionsfähig ist der Icecast-Pfad derzeit vor allem über den expliziten ffmpeg-Fallback. Das ist für Phase 1 akzeptabel, weil die strukturelle Trennung jetzt sauber steht und spätere native Decoder nicht mehr die Runtime-Architektur verbiegen müssen.
Warum das ein sinnvoller Abschluss von Phase 1 ist
Phase 1 hatte nicht das Ziel, sämtliche Transport- und Codecvarianten produktionsreif abzuschliessen. Ziel war vielmehr, die bisher punktuellen Audio-Eingänge in ein gemeinsames, erweiterbares Modell zu überführen. Genau das ist erreicht:
- die TX-Schicht kennt keine Source-Familien mehr direkt
- HTTP- und CLI-Ingest hängen nicht mehr als Sonderfälle im Startcode
- Icecast ist als echter Source-Typ modelliert
- Decoder-Fallback ist explizit statt implizit
- die Control Plane kann Ingest-Zustand sichtbar machen
Nächster sinnvoller Schritt
Der nächste Block ist nicht noch mehr Runtime-Umbau, sondern gezielte inhaltliche Vervollständigung:
- echte native Decoder für MP3 und Ogg/Vorbis
- danach AAC/ADTS, sofern Bibliothekslage und Streaming-Verhalten sauber genug sind
- erst danach zusätzliche Familien wie AoIP/SRT in die gemeinsame Runtime ziehen
Die strategische Richtung ist daher nicht „ffmpeg sofort ersetzen“, sondern:
- bestehenden
ffmpeg-Pfad als universellen Fallback behalten
- native Ingest-Familien daneben aufbauen
- alle Pfade auf eine gemeinsame interne PCM-/Audio-Source-Abstraktion führen
- neue native Pfade schrittweise produktionsreif machen
Leitprinzipien
- Kein Big-Bang-Rewrite – Bestehendes bleibt lauffähig.
- Native Pfade zuerst dort, wo sie klaren Mehrwert bringen.
- Go-Libraries bevorzugen – Decoder/Protocol-Handling einkaufen statt neu erfinden.
- Ein gemeinsames Ingest-Modell – unabhängig von Quelle oder Protokoll.
- Control Plane / Runtime / Telemetrie von Decoder-Details trennen.
Zielbild: drei Ingest-Familien
1. FFmpeg Family
Bestehender universeller Adapter.
Rolle:
- Fallback
- Legacy-Kompatibilität
- exotische oder seltene Formate
- schneller pragmatischer Pfad für Quellen, die nativ noch nicht unterstützt werden
Wichtig:
- bleibt vorerst erhalten
- wird nicht „rausoptimiert“, sondern architektonisch nachrangig
- sollte in der Runtime als eigener Ingest-Typ sichtbar sein
2. AoIP Family
Für professionelle / broadcast-nahe Audioquellen.
Ziel-Protokolle / Modi:
- RTP multicast
- AES67-lite
- SDP
- SAP
- später: NMOS IS-04 / IS-05
- später: SRT framed PCM
Basis:
Rolle:
- deterministische LAN-Audiozuführung
- Broadcast-/AoIP-Umgebungen
- spätere professionelle Discovery/Activation
3. Streaming Family
Für klassische Internet-/HTTP-/Radio-Streamingquellen.
Ziel-Protokolle / Modi:
- HTTP audio streams
- Icecast / Shoutcast
- ICY metadata
- MP3
- AAC / HE-AAC (je nach verfügbarer Lib)
- später ggf. Opus
Rolle:
- Webradio / Online-Streams
- Metadatenübernahme
- native Alternative zu
ffmpeg für die häufigsten Streaming-Fälle
Wichtig:
Diese Familie sollte nicht in aoiprxkit gepresst werden. AoIP und Streaming sind konzeptionell verschieden genug, dass getrennte Package-Bereiche sinnvoll sind.
Gemeinsame interne Abstraktion
Alle Ingest-Familien sollen auf dieselbe interne PCM-Einspeisung münden.
Ziel
Unabhängig davon, ob Samples von:
ffmpeg
- RTP/AES67
- Icecast/MP3
- SRT framed PCM
kommen, soll der Rest der Sende-/RDS-/Runtime-Logik immer dieselbe Audioquelle sehen.
Grobe Zielverantwortung
Eine Quelle soll idealerweise liefern können:
- PCM-Samples
- Sample-Rate
- Kanalzahl
- Source-Label / Source-Type
- Laufzeitstatus / Health
- Basisstatistiken
- optional Metadaten (z. B. ICY title)
Wichtige Designregel
Decoder/Protocol-Layer und Sender-Runtime nicht vermischen.
Das Ingest-System soll:
- Audio empfangen / decodieren / normieren
- Health / Stats liefern
- Audio in die bestehende Audio-Pipeline schieben
Die Sender-Runtime soll:
- Quellen starten/stoppen
- aktive Quelle verwalten
- Fehler/Fallback/Status darstellen
- UI/Control-Plane bedienen
Einordnung von aoiprxkit
Was aoiprxkit heute schon gut abdeckt
- RTP multicast RX
- L24-Decoding
- Jitter/Reorder
- statische SDP-Auswertung
- SAP-Listener
- Stream-Finder per SDP
s= Name
- Basis-Stats
- Live-Metering
- NMOS-/SRT-Grundgerüst
Was aoiprxkit heute noch nicht vollständig als Produkt ist
- keine voll integrierte
fm-rds-tx-Runtime-Anbindung
- SRT-Pfad eher Scaffold als fertig produktionsreif
- NMOS eher vorbereitend als vollständig integriert
- noch kein gemeinsames Source-Management mit anderen Ingest-Familien
Konsequenz
aoiprxkit ist integrationswürdig, aber aktuell noch eher ein Modul/Baukasten als direktes Hauptsystem.
Empfohlene Package-/Modul-Richtung in fm-rds-tx
Dies ist ein Zielbild, kein harter Sofort-Umbau.
Kandidaten
internal/audioingest
- gemeinsame Interfaces / gemeinsame Typen / gemeinsame Runtime-Adapter
internal/audioingest/ffmpeg
- bestehender ffmpeg-basierter Pfad
internal/audioingest/aoip
- Adapter zwischen
aoiprxkit und fm-rds-tx
internal/audioingest/streaming
- HTTP/Icecast/Shoutcast/ICY + Decoder-Libs
Optional später:
internal/audioingest/shared
- Resampling, channel mapping, sample normalization, metadata structs
Konfigurationszielbild
Die Runtime sollte einen expliziten Ingest-Typ kennen.
Beispielhaft:
input:
kind: ffmpeg | aoip-rtp | aoip-sap | aoip-srt | stream-http
Später können pro Familie Unterstrukturen folgen.
Beispielhaft:
input:
kind: aoip-rtp
aoip:
multicastGroup: 239.69.0.1
port: 5004
payloadType: 97
sampleRateHz: 48000
channels: 2
oder
input:
kind: stream-http
streaming:
url: https://example.org/live.mp3
icyMeta: true
Runtime-Zielbild
Die Runtime sollte Quellen einheitlich behandeln können:
- initialisieren
- starten
- stoppen
- Status abfragen
- Health/Stats lesen
- Audio in denselben bestehenden Ringbuffer / Audio-Input-Pfad drücken
Telemetrie / UI
Die Control Plane sollte mittelfristig ingest-bezogen sichtbar machen:
- aktiver Ingest-Typ
- Source-Label
- Transport / Codec / Sample-Rate / Channels
- Fehlerzustand
- Puffer-/Jitter-/Underrun-relevante Daten
- optional Metadata (z. B. StreamTitle)
Wichtig ist hier eine Trennung zwischen:
- Audio ingest health
- TX/runtime health
Empfohlene Umsetzungsreihenfolge
Phase 1 – Architektur sauberziehen
- gemeinsames Ingest-Zielbild festziehen
- bestehende Audio-Input-Andockpunkte in
fm-rds-tx dokumentieren
- entscheiden, welche internen Interfaces nötig sind
Phase 2 – AoIP MVP
aoiprxkit nicht blind verschieben, sondern zuerst als Adapter anbinden
- erster nativer Ingest-Modus: statischer RTP/AES67-lite Pfad
- PCM-Frames in bestehende Audio-Pipeline einspeisen
- Runtime-/Health-/Status sichtbar machen
Phase 3 – SDP / SAP Discovery
- statische SDP-Unterstützung
- optional SAP Listener + Session-Auswahl
- Discovery klar von Audio-Transport trennen
Phase 4 – Streaming MVP
- neuer nativer HTTP/Icecast/Shoutcast-Pfad
- bewährte Go-Libs für Decoder und ICY nutzen
- erstes Ziel: häufige Webradio-Fälle ohne
ffmpeg
Phase 5 – Vereinheitlichung / Telemetrie
- gemeinsame Ingest-Stats
- gemeinsame Statusmodelle
- UI/Control-Plane-Integration
- Quellwechsel / Fehlermeldungen / Health States
Phase 6 – Erweiterte Pfade
- SRT sauber produktionsfähig machen
- NMOS weiter integrieren
- später ggf. Opus / weitere Streaming-Codecs
Was explizit vermieden werden soll
ffmpeg sofort herausreissen
- AoIP und Web-Streaming in denselben unscharfen Package-Topf werfen
- Decoder / Demux / Protocol-Layer unnötig selbst neu bauen
- Discovery-Logik eng mit der PCM-Pipeline verheiraten
- UI bauen, bevor Runtime-Modelle sauber stehen
Erste konkrete Bauschritte ab jetzt
- bestehenden Audio-Input-Pfad in
fm-rds-tx analysieren
- kleinste gemeinsame Ingest-Abstraktion definieren
aoiprxkit-RTP als ersten nativen Adapter integrieren
- danach Streaming-Familie planen und anbinden
Kurzfazit
ffmpeg bleibt vorerst als nützlicher Universalpfad erhalten.
Die Zukunft liegt aber in zwei nativen Familien:
- AoIP für professionelle/broadcast-nahe Zuführung
- Streaming für HTTP/Icecast/Shoutcast/ICY + Standardcodecs
Beide sollen sauber über eine gemeinsame interne Audio-Ingest-Schicht in fm-rds-tx zusammenlaufen.