1. Doel
End-to-end setup voor:
- GoPro RTMP → RPi4
- Omzetten naar HLS (low-latency)
- Host HLS lokaal op RPi4
- Sync naar TransIP subsite
- Remote cleanup van oude TS-segmenten
Opmerking: Race conditions / mogelijke hikken van de videostream zijn besproken in de sync- en cleanup scripts.
2. Vereisten
- FFmpeg
- inotify-tools
- rsync
- SSH key-based login naar TransIP
- systemd
3. HLS conversie op RPi4
Systemd unit: hls-stream.service
[Unit] Description=GoPro RTMP to HLS After=network-online.target Wants=network-online.target [Service] User=pi4 Group=www-data WorkingDirectory=/var/www/html/hls/gopro ExecStartPre=/bin/mkdir -p /var/www/html/hls/gopro ExecStartPre=/bin/chown pi4:www-data /var/www/html/hls/gopro #ExecStartPre=/bin/bash -c 'rm -f *.ts *.m3u8' # map leegmaken bij echte start (voorkomt sequence conflicts) ExecStartPre=/bin/bash -c 'rm -f /var/www/html/hls/gopro/*.ts /var/www/html/hls/gopro/*.m3u8' ExecStart=/usr/bin/ffmpeg -loglevel warning -fflags +genpts+discardcorrupt -probesize 500000 -analyzeduration 1000000 -i rtmp://127.0.0.1:1935/gopro/live -map 0:v:0 -c:v copy -an -f hls -hls_time 2 -hls_list_size 30 -hls_flags delete_segments+independent_segments+program_date_time+temp_file -hls_segment_type mpegts -hls_segment_filename segment_%%05d.ts stream.m3u8 Restart=always RestartSec=2 StartLimitIntervalSec=0 KillSignal=SIGINT TimeoutStopSec=5 LimitNOFILE=65535 StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target
4. HLS sync naar TransIP
Watcher script: hls_to_transip.sh
#!/bin/bash
set -u
LOCAL_DIR="/var/www/html/hls/gopro"
REMOTE="transip-hls"
REMOTE_DIR="subsites/stream.auslese.nl"
# Simpele rsync met SSH-config (die werkt al bewezen)
echo "$(date '+%F %T') Starting HLS rsync sync loop..."
# Eenmalig remote dir
ssh -F /home/pi4/.ssh/config "$REMOTE" "mkdir -p ~/\"$REMOTE_DIR\""
while true; do
echo "$(date '+%F %T') Syncing..."
if rsync -az --delete --timeout=5 \
-e "ssh -F /home/pi4/.ssh/config" \
"$LOCAL_DIR/" "$REMOTE:$REMOTE_DIR/" ; then
echo "$(date '+%F %T') Sync OK"
else
echo "$(date '+%F %T') RSYNC ERROR - retrying..." >&2
fi
sleep 0.5
done
Systemd service: hls-to-transip.service
[Unit] Description=HLS sync to TransIP (rsync + inotify) After=network-online.target Wants=network-online.target [Service] Type=simple User=pi4 Group=www-data # Zorg dat paden bestaan WorkingDirectory=/var/www/html/hls/gopro ExecStart=/usr/local/bin/hls_to_transip.sh # Altijd blijven draaien Restart=always RestartSec=2 StartLimitIntervalSec=0 # Nette shutdown (Ctrl+C simulatie) KillSignal=SIGINT TimeoutStopSec=5 # Logging StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target
6. Best Practices
- Activeren:
- Test eerst handmatig:
/usr/local/bin/hls_cleanup_remote.sh - Monitor logs:
journalctl -u hls-stream.service -f - Pas
SAFETY_AGEaan bij langere HLS windows - SSH keys moeten passwordless werken
- Voor meerdere streams: aparte directories + systemd units
sudo systemctl daemon-reloadsudo systemctl enable servicename.service of ~servicename.timersudo systemctl start servicename.service of ~servicename.timer7. Workflow overzicht
- GoPro → RTMP server op RPi4
- FFmpeg converteert → HLS (segment_XXXXX.ts + stream.m3u8)
hls_to_transip.shsync → remote TransIP folderhls_cleanup_remote.shverwijdert oude segments, playlist-aware- Race conditions / mogelijke hikken van de videostream zijn verwerkt in de scripts
- Alle processen draaien via systemd services en timer