···11+#!/bin/bash
22+#
33+# Validates all .ts files in the current directory have a video stream.
44+# Run this before streaming to catch bad encodes.
55+66+bad=0
77+88+for f in *.ts; do
99+ [[ -f "$f" ]] || continue
1010+1111+ if ! ffprobe -v error -select_streams v:0 \
1212+ -show_entries stream=codec_type -of csv=p=0 "$f" 2>/dev/null \
1313+ | grep -q video; then
1414+ echo "INVALID: $f" >&2
1515+ bad=$((bad + 1))
1616+ fi
1717+done
1818+1919+if [[ $bad -gt 0 ]]; then
2020+ echo "$bad invalid file(s) found" >&2
2121+ exit 1
2222+fi
2323+2424+echo "All files valid"
+34-16
stream.sh
···44[[ -z "$STREAM_KEY" ]] && echo "STREAM_KEY is required" >&2 && exit 1
5566HISTORY_SIZE=5
77-declare -a history=()
77+RETRY_DELAY=1
88+MAX_RETRY_DELAY=30
99+1010+pick_video() {
1111+ local all_videos=()
1212+ for f in *.ts; do
1313+ [[ -f "$f" ]] || continue
1414+ all_videos+=("$f")
1515+ done
81699-CURRENT_VIDEO_TRACKER=$(mktemp)
1010-trap 'echo "Last playing: $(cat "$CURRENT_VIDEO_TRACKER")" >&2; rm -f "$CURRENT_VIDEO_TRACKER"' EXIT
1717+ [[ ${#all_videos[@]} -eq 0 ]] && return 1
11181212-pick_video() {
1313- local all_videos=(*.ts)
1419 local available=()
1515-1616- # Filter out recently played videos
1720 for v in "${all_videos[@]}"; do
1821 local in_history=0
1922 for h in "${history[@]}"; do
···2225 [[ $in_history -eq 0 ]] && available+=("$v")
2326 done
24272525- # If fewer videos than history size, use all
2628 [[ ${#available[@]} -eq 0 ]] && available=("${all_videos[@]}")
27292828- # Pick random from available
2930 echo "${available[$((RANDOM % ${#available[@]}))]}"
3031}
31323333+# Outer loop: reconnect on disconnect
3234while true; do
3333- video=$(pick_video)
3535+ echo "Connecting to $RTMP_URL..." >&2
3636+ declare -a history=()
34373535- # Update history (add new, keep last HISTORY_SIZE)
3636- history+=("$video")
3737- (( ${#history[@]} > HISTORY_SIZE )) && history=("${history[@]:1}")
3838+ # Inner loop: pick and stream videos, piped into ffmpeg
3939+ while true; do
4040+ video=$(pick_video)
4141+ if [[ -z "$video" ]]; then
4242+ echo "No .ts files found, waiting..." >&2
4343+ sleep 5
4444+ continue
4545+ fi
4646+4747+ history+=("$video")
4848+ (( ${#history[@]} > HISTORY_SIZE )) && history=("${history[@]:1}")
4949+5050+ echo "Playing: $video" >&2
5151+ cat "$video"
5252+ done | ffmpeg -loglevel error -re -fflags +genpts -i pipe:0 -c copy -f flv "$RTMP_URL/$STREAM_KEY"
38533939- echo "$video" > "$CURRENT_VIDEO_TRACKER"
4040- cat "$video"
4141-done | ffmpeg -loglevel error -re -fflags +genpts -i pipe:0 -c copy -f flv "$RTMP_URL/$STREAM_KEY"
5454+ echo "Stream disconnected, reconnecting in ${RETRY_DELAY}s..." >&2
5555+ sleep "$RETRY_DELAY"
5656+5757+ RETRY_DELAY=$(( RETRY_DELAY * 2 ))
5858+ (( RETRY_DELAY > MAX_RETRY_DELAY )) && RETRY_DELAY=$MAX_RETRY_DELAY
5959+done