# 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:
1. echte native Decoder für MP3 und Ogg/Vorbis
2. danach AAC/ADTS, sofern Bibliothekslage und Streaming-Verhalten sauber genug sind
3. 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
1. **Kein Big-Bang-Rewrite** – Bestehendes bleibt lauffähig.
2. **Native Pfade zuerst dort, wo sie klaren Mehrwert bringen**.
3. **Go-Libraries bevorzugen** – Decoder/Protocol-Handling einkaufen statt neu erfinden.
4. **Ein gemeinsames Ingest-Modell** – unabhängig von Quelle oder Protokoll.
5. **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:**
- `aoiprxkit`

**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:

```yaml
input:
  kind: ffmpeg | aoip-rtp | aoip-sap | aoip-srt | stream-http
```

Später können pro Familie Unterstrukturen folgen.

Beispielhaft:

```yaml
input:
  kind: aoip-rtp
  aoip:
    multicastGroup: 239.69.0.1
    port: 5004
    payloadType: 97
    sampleRateHz: 48000
    channels: 2
```

oder

```yaml
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
1. bestehenden Audio-Input-Pfad in `fm-rds-tx` analysieren
2. kleinste gemeinsame Ingest-Abstraktion definieren
3. `aoiprxkit`-RTP als ersten nativen Adapter integrieren
4. 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.
