diff --git a/README.md b/README.md index 0a9df81..a9c9b82 100644 --- a/README.md +++ b/README.md @@ -109,3 +109,18 @@ do not use it to conclude a token is dead. yt-dlp reads cookies from a running Firefox. Chrome/Edge lock their cookie DB while running (yt-dlp issue 7271), and an unattended job cannot close the browser to read them. + +### The stream never ends + +After full time the feed switches to a static league slate and keeps serving +indefinitely at full CBR bitrate (~4.7 Mbit/s to encode a still image). There +is no `#EXT-X-ENDLIST`, so ffmpeg never finishes, and there is no stall to +detect either -- from the downloader's point of view it is a healthy live +stream forever. + +**A hard duration cap is therefore the only stop condition.** `catcher.py` +passes `ffmpeg_o:-t $DURATION_MIN*60`. Do not remove it; without it an +unattended run fills the disk with a logo. + +Observed: 116 min recorded for a 23:00 kickoff, still going at 01:04 and only +stopped manually. Budget ~3.5-4 GB per copy per match at 40 MB/min. diff --git a/endwatch.sh b/endwatch.sh new file mode 100644 index 0000000..54cc7c7 --- /dev/null +++ b/endwatch.sh @@ -0,0 +1,54 @@ +#!/usr/bin/env bash +# Watch a live recording until its downloaders exit, and record HOW they ended. +# +# The question this answers: when the stream stops, does ffmpeg finish cleanly +# on #EXT-X-ENDLIST, or does it hang until something kills it? Unattended +# recording depends on the answer -- a job that never exits needs a hard cap. +set -u +cd "$(dirname "$0")" +LOG=logs/endwatch.log +mkdir -p logs + +say() { echo "[$(date '+%H:%M:%S')] $*" | tee -a "$LOG"; } + +say "endwatch start" +LAST_TOTAL=0 +STALL=0 + +while true; do + N=$(tasklist //FI "IMAGENAME eq ffmpeg.exe" 2>/dev/null | grep -c ffmpeg.exe) + TOTAL=0 + for f in recordings/*; do + [ -f "$f" ] && TOTAL=$(( TOTAL + $(stat -c%s "$f") )) + done + MB=$(( TOTAL / 1048576 )) + GROW=$(( (TOTAL - LAST_TOTAL) / 1024 )) + + if [ "$TOTAL" -eq "$LAST_TOTAL" ]; then + STALL=$(( STALL + 1 )) + else + STALL=0 + fi + LAST_TOTAL=$TOTAL + + say "ffmpeg=$N total=${MB}MB grew=${GROW}KB stalled_ticks=$STALL" + + if [ "$N" -eq 0 ]; then + say "ALL DOWNLOADERS EXITED -- stream ended and ffmpeg finished on its own" + break + fi + if [ "$STALL" -ge 10 ]; then + say "STALLED: files not growing for ~5min but ffmpeg still alive" + say " -> it does NOT self-terminate cleanly; unattended runs need a hard cap" + break + fi + sleep 30 +done + +say "final state:" +for f in recordings/*; do + [ -f "$f" ] || continue + D=$(ffprobe -v error -show_entries format=duration -of csv=p=0 "$f" 2>/dev/null) + say " $(basename "$f") $(( $(stat -c%s "$f") / 1048576 ))MB duration=${D:-unknown}s" +done +say "endwatch done"