An art project of mine; showing 30 second video clips of calm places & moments I've enjoyed being in.
stream.place/byjp.me
video
streaming
art
1#!/bin/bash
2
3[[ -z "$RTMP_URL" ]] && echo "RTMP_URL is required" >&2 && exit 1
4[[ -z "$STREAM_KEY" ]] && echo "STREAM_KEY is required" >&2 && exit 1
5
6HISTORY_SIZE=5
7RETRY_DELAY=1
8MAX_RETRY_DELAY=30
9
10pick_video() {
11 local all_videos=()
12 for f in *.ts; do
13 [[ -f "$f" ]] || continue
14 all_videos+=("$f")
15 done
16
17 [[ ${#all_videos[@]} -eq 0 ]] && return 1
18
19 local available=()
20 for v in "${all_videos[@]}"; do
21 local in_history=0
22 for h in "${history[@]}"; do
23 [[ "$v" == "$h" ]] && in_history=1 && break
24 done
25 [[ $in_history -eq 0 ]] && available+=("$v")
26 done
27
28 [[ ${#available[@]} -eq 0 ]] && available=("${all_videos[@]}")
29
30 echo "${available[$((RANDOM % ${#available[@]}))]}"
31}
32
33# Outer loop: reconnect on disconnect
34while true; do
35 echo "Connecting to $RTMP_URL..." >&2
36 declare -a history=()
37
38 # Inner loop: pick and stream videos, piped into ffmpeg
39 while true; do
40 video=$(pick_video)
41 if [[ -z "$video" ]]; then
42 echo "No .ts files found, waiting..." >&2
43 sleep 5
44 continue
45 fi
46
47 history+=("$video")
48 (( ${#history[@]} > HISTORY_SIZE )) && history=("${history[@]:1}")
49
50 echo "Playing: $video" >&2
51 cat "$video"
52 done | ffmpeg -loglevel error -re -fflags +genpts -i pipe:0 -c copy -f flv "$RTMP_URL/$STREAM_KEY"
53
54 echo "Stream disconnected, reconnecting in ${RETRY_DELAY}s..." >&2
55 sleep "$RETRY_DELAY"
56
57 RETRY_DELAY=$(( RETRY_DELAY * 2 ))
58 (( RETRY_DELAY > MAX_RETRY_DELAY )) && RETRY_DELAY=$MAX_RETRY_DELAY
59done