Skip to content

Repository files navigation

🎙️ go-radio-streamer

Go Version License: MIT Platform

🇬🇧 English

Go service that takes an internet radio stream (MP3), decodes/resamples it via FFmpeg, and sends it as AES67-style RTP multicast (L24/48000/2) with Web UI, REST API, MQTT control, ICY metadata, and SAP/SDP announcement.

🚀 Installation

# Dependencies
sudo apt-get install -y ffmpeg    # Debian/Ubuntu / Raspberry Pi OS
brew install ffmpeg               # macOS

# Build
cd go-radio-streamer
CGO_ENABLED=0 go build -o radio-streamer ./cmd

# Run
./radio-streamer

Server URL: http://localhost:8080

Raspberry Pi guide: RASPBERRY_PI_SETUP.md

🔌 API Quickstart

curl -sS http://localhost:8080/api/stations
curl -sS -X POST http://localhost:8080/api/play -H 'Content-Type: application/json' -d '{"station":1}'
curl -sS -X POST http://localhost:8080/api/stop
curl -sS http://localhost:8080/api/status
curl -sS http://localhost:8080/api/stream.sdp

📡 MQTT Topics

  • Control: gostreamer/play, gostreamer/stop
  • Status: gostreamer/current, gostreamer/heartbeat

📄 License

MIT (LICENSE)


🇨🇭 Deutsch

Go-Service, der einen Internet-Radiostream (MP3) per FFmpeg dekodiert/resampelt und als AES67-ähnlichen RTP-Multicast (L24/48000/2) mit Web-UI, REST-API, MQTT-Steuerung, ICY-Metadaten und SAP/SDP-Announcement sendet.

🚀 Installation

Voraussetzungen

  • Go (aktuell mit Go 1.26.x gebaut)
  • FFmpeg in PATH
  • MQTT optional (ohne mqtt.conf läuft HTTP/Web trotzdem)

FFmpeg installieren

# Debian/Ubuntu / Raspberry Pi OS
sudo apt-get update
sudo apt-get install -y ffmpeg

# macOS
brew install ffmpeg

Projekt bauen & starten

cd go-radio-streamer
CGO_ENABLED=0 go build -o radio-streamer ./cmd
./radio-streamer

Server läuft dann auf http://localhost:8080.

Raspberry Pi

Vollständige Anleitung mit Pi 5 Optimierungen: RASPBERRY_PI_SETUP.md

Docker (alternativ)

docker run -d --name radio-streamer --network host \
  -v $(pwd)/stations.txt:/app/stations.txt \
  -v $(pwd)/streamer.conf:/app/streamer.conf \
  silly82/go-radio-streamer:latest

⚙️ Konfiguration

Die App liest drei Dateien aus dem Projekt-Root.

stations.txt

1. SRF-1 https://stream.srg-ssr.ch/m/rsrp1/mp3_128
2. SRF-2 https://stream.srg-ssr.ch/m/rsrp2/mp3_128

Hinweise:

  • Erstes Token muss <nummer>. sein
  • Zweites Token ist Stationsname (ein Token)
  • Rest ist URL

mqtt.conf (optional)

broker=tcp://192.168.188.62:1883
user=your_user
pass=your_password

streamer.conf (optional, ab v2.0)

# Multicast address for RTP streaming and SAP announcements
multicast_address=239.69.250.171:5004

# PTP reference clock (optional)
# ptp_ref_clock=IEEE1588-2008:AA-BB-CC-DD-EE-FF-00-00:0

# Network optimisations (Pi 5)
bind_interface=eth0
ttl=1
udp_buffer_size=4194304

Fehlende Optionen nutzen Defaults:

  • multicast_address: 239.69.250.171:5004
  • bind_interface: leer (default route)
  • ttl: 32
  • udp_buffer_size: 1048576 (1 MiB)
  • ptp_ref_clock: leer (verwendet localmac)

✨ Features

Streaming

  • RTP Multicast auf konfigurierbarer Adresse (Default 239.69.250.171:5004)
  • Audioformat: L24/48000/2 (Payload Type 97)
  • Stabiler Senderwechsel über POST /api/play (kontrollierter Stop/Start)
  • Stabilitätsorientiertes Tuning (ptime=40, Prebuffer, Silence bei Underrun)

Network Stack (Optimiert für Raspberry Pi 5)

  • Interface-Binding – Multicast zwingend über bestimmtes Interface (bind_interface)
  • Konfigurierbarer TTL – für Subnet-Only oder geroutete Netze
  • Konfigurierbare Socket-Buffer – Pi 5 Gigabit Ethernet: bis 4 MiB Sendbuffer
  • Multicast Loopback deaktiviert – kein selbst-Empfang
  • SO_REUSEPORT – schnelle Neustarts

Web Interface

  • HTML Station Selection UI
  • Play/Stop Controls
  • Status Display (Artist/Track from ICY metadata)
  • Auto-Refresh alle 5 Sekunden

REST API

  • GET /api/stations
  • POST /api/play
  • POST /api/stop
  • GET /api/status
  • GET /api/stream.sdp

MQTT Integration

  • Broker Connection (optional, ohne läuft HTTP/Web trotzdem)
  • Topic Subscription (gostreamer/play, gostreamer/stop)
  • Status Publishing (gostreamer/current, gostreamer/heartbeat)

SAP / Discovery

  • SDP Announcement via SAP auf 239.255.255.255:9875
  • Intervall: 30 Sekunden
  • SAP Delete-Announcement beim Stop

🌐 Web UI

Aufrufen:

http://localhost:8080/

Funktionen:

  • Start/Stop
  • Senderwechsel ohne separaten Stop (Backend macht atomaren Switch)
  • Anzeige von aktiver Station + artist/track

🔌 REST API

GET /api/stations

curl -sS http://localhost:8080/api/stations

POST /api/play

curl -sS -X POST http://localhost:8080/api/play \
  -H 'Content-Type: application/json' \
  -d '{"station":1}'

POST /api/stop

curl -sS -X POST http://localhost:8080/api/stop

GET /api/status

curl -sS http://localhost:8080/api/status

Beispielantwort:

{
  "running": true,
  "station": "SRF-1",
  "artist": "...",
  "track": "...",
  "meta_updated": 1774982390
}

GET /api/stream.sdp

curl -sS http://localhost:8080/api/stream.sdp

Query-Parameter:

  • ip (Default aus multicast_address)
  • port (Default aus multicast_address)
  • pt (Default 97)
  • ptime (Default 40)
  • ptp (Default: konfigurierte ptp_ref_clock oder localmac)
  • originip (Default: auto-detected local IP)

📡 MQTT

Subscribe (Control)

  • gostreamer/play (Payload: z. B. 1)
  • gostreamer/stop (Payload optional)

Publish (Status)

  • gostreamer/current (JSON)
  • gostreamer/heartbeat (JSON, alle 30s)

Beispiele:

# subscribe
mosquitto_sub -h 192.168.188.62 -u your_user -P your_password -t 'gostreamer/#'

# play station 1
mosquitto_pub -h 192.168.188.62 -u your_user -P your_password -t 'gostreamer/play' -m '1'

# stop
mosquitto_pub -h 192.168.188.62 -u your_user -P your_password -t 'gostreamer/stop' -m ''

🧠 Technische Hinweise

  • FFmpeg-Output: pcm_s24be (s24be raw)
  • RTP-Clock: 48 kHz
  • Grösserer UDP-Write-Buffer für glatteres Senden (konfigurierbar)
  • Fokus auf Kontinuität statt ultra-niedriger Latenz
  • sync.RWMutex für thread-sicheren Metadaten-Zugriff
  • Alte go-mp3-Codepfade entfernt (nur FFmpeg-basiert)

PTP / Clock

Der SDP enthält standardmässig a=ts-refclk:localmac=…. Wenn dein AES67-Hardware-Receiver PTP erzwingt, einfach ptp_ref_clock in der streamer.conf auf die Clock-ID des PTP-Grandmasters setzen (z.B. Powersoft Nota/Mezzo in ArmoníaPlus zum GM bestimmen → Clock-ID ins Config → SDP annonciert die PTP-ID → Receiver akzeptiert). Der Pi braucht kein eigenes Hardware-PTP.

Detailierte Anleitung: RASPBERRY_PI_SETUP.md.


🛠️ Troubleshooting

API antwortet nicht

ps aux | grep radio-streamer
curl -sS http://localhost:8080/api/status

Kein Audio am Receiver

  1. RTP-Verkehr prüfen:
tcpdump -ni eth0 udp and port 5004
  1. SDP prüfen:
curl -sS http://localhost:8080/api/stream.sdp
  1. Empfänger muss L24/48000/2, PT 97 erwarten.

Audio knackt/stottert

  • udp_buffer_size erhöhen (auf Pi 5: 4194304)
  • bind_interface=eth0 setzen (WLAN meiden)
  • Defaults sind stabilitätsorientiert (ptime=40, Prebuffer, Silence bei Underrun)
  • Receiver-Jitterbuffer erhöhen
  • Host-/Netzlast und Paketverlust prüfen

"No PTP clock" Fehler

  • Hardware-Receiver erwartet PTP Grandmaster im Netz
  • Lösung: Empfänger zum PTP-GM machen, Clock-ID in streamer.conf setzen (siehe RASPBERRY_PI_SETUP.md)
  • Software-Receiver (ffplay, VLC) ignorieren das → für Tests erstmal nutzen

FFmpeg fehlt

ffmpeg -version
sudo apt install -y ffmpeg

MQTT nicht verfügbar

  • Server startet trotzdem (HTTP/Web-only)
  • MQTT wird aktiviert, sobald gültige mqtt.conf vorhanden ist

👨‍💻 Entwicklung

cd go-radio-streamer
go test -v ./...
CGO_ENABLED=0 go build -o radio-streamer ./cmd

Aktuelle Testabdeckung: 13 Tests (config 6, streamer 5, aes67 3)


📄 Lizenz

Dieses Projekt steht unter der MIT-Lizenz. Details siehe LICENSE.


🗂️ Projektlayout

go-radio-streamer/
├── RASPBERRY_PI_SETUP.md       # Pi Setup Guide (Pi 4 + Pi 5)
├── cmd/main.go                 # Entry point
├── internal/
│   ├── api/handlers.go         # REST API endpoints
│   ├── config/config.go        # Config parsing (stations, MQTT, streamer)
│   ├── mqtt/mqtt.go            # MQTT client
│   ├── streamer/
│   │   ├── metadata.go         # ICY metadata parser
│   │   ├── streamer.go         # Core: FFmpeg → RTP multicast
│   │   └── streamer_test.go
│   └── web/                    # Web UI (static HTML)
├── pkg/aes67/
│   ├── sap.go                  # SAP announcements
│   ├── sdp.go                  # SDP builder
│   └── sdp_test.go
├── stations.txt                # Station list (example)
├── streamer.conf               # Streamer config (multicast, network, PTP)
├── mqtt.conf                   # MQTT credentials (example)
├── go.mod
└── README.md

Stand: Juli 2026 · go-radio-streamer v2.0

About

Go radio streamer with AES67-style RTP multicast, Web UI, REST API, MQTT control, metadata, and SAP/SDP discovery.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages