RPi4 GoPro HLS Streaming Runbook

1. Doel

End-to-end setup voor:

Opmerking: Race conditions / mogelijke hikken van de videostream zijn besproken in de sync- en cleanup scripts.

2. Vereisten

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

7. Workflow overzicht

  1. GoPro → RTMP server op RPi4
  2. FFmpeg converteert → HLS (segment_XXXXX.ts + stream.m3u8)
  3. hls_to_transip.sh sync → remote TransIP folder
  4. hls_cleanup_remote.sh verwijdert oude segments, playlist-aware
  5. Race conditions / mogelijke hikken van de videostream zijn verwerkt in de scripts
  6. Alle processen draaien via systemd services en timer