#!/bin/bash # Persistent multi-camera capture with zero-gap segmentation # Condenses each completed segment automatically # Usage: ipcam-record.sh [cameras.conf] CONF="${1:-$(dirname "$0")/ipcam-cameras.conf}" DIR="$HOME/Downloads/ipcam" SEGMENT=600 PIDFILE="$DIR/.capture.pids" CONDENSE="$(dirname "$0")/ipcam-condense.sh" MERGE="$(dirname "$0")/ipcam-merge.sh" mkdir -p "$DIR" cleanup() { if [ -f "$PIDFILE" ]; then while read pid; do kill "$pid" 2>/dev/null done < "$PIDFILE" rm "$PIDFILE" fi exit 0 } trap cleanup INT TERM > "$PIDFILE" # launch one ffmpeg per camera while read -r name url; do [ -z "$name" ] && continue [[ "$name" == \#* ]] && continue ( while true; do ffmpeg -loglevel error \ -vaapi_device /dev/dri/renderD128 \ -i "$url" \ -vf "drawtext=text='%{localtime\:%Y-%m-%d %T %Z}':fontsize=28:fontcolor=white:borderw=2:bordercolor=black:x=24:y=h-48,format=nv12,hwupload" \ -c:v h264_vaapi -qp 18 \ -f segment \ -segment_time "$SEGMENT" \ -segment_format matroska \ -reset_timestamps 1 \ -strftime 1 \ -segment_list pipe:1 \ -segment_list_type flat \ "$DIR/${name}_%Y%m%d_%H%M%S.mkv" \ /dev/null | while read -r completed; do [ -z "$completed" ] && continue # segment_list outputs bare filename, add dir f="$DIR/$completed" [ -f "$f" ] || continue echo "segment complete: $completed, condensing..." bash "$CONDENSE" "$f" && bash "$MERGE" done # if ffmpeg dies (camera offline), retry after 5s sleep 5 done ) & echo $! >> "$PIDFILE" echo "started capture: $name ($url) pid=$!" done < "$CONF" echo "all cameras started, waiting..." wait