record_live.py runs the whole chain alone: headless browser only to learn the
entry id (it appears at runtime; static HTML has none when nothing is live),
then plain Python mints a fresh master playlist, then ffmpeg records.
No password needed. Firefox session cookies run to late November, well past
any kickoff, so the job authenticates from the stored session.
Three failures found by testing against a live feed rather than at kickoff:
- yt-dlp's native HLS downloader fetches variant playlists with Python and
gets 403/404 on path-token URLs. Forced --downloader ffmpeg; this is
required, not a preference.
- ffmpeg 4.3.1 has no -reconnect_on_network_error. Removed here and in
catcher.py, which had the same unsupported flag.
- A master playlist outlives its stream: after a match ends the master is
still served while its variants 404. So a found master does not mean a live
stream, and a downloader that dies immediately means "not up yet" rather
than "failed". It now retries until the wait window expires.
Untested: the actual segment download for an audio-only stream, because
nothing is live right now. Video was verified working on 29 Aug.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kyt7QHQvLJtQRuiY4wAqKB
Verified end to end against a live match: 1080p H.264/AAC MPEG-TS at
~5.2 Mbit/s, recorded while the browser played the same stream.
Components:
- tampermonkey sniffer hooks fetch/XHR at document-start, captures the
manifest URL verbatim and POSTs it to the local catcher. v0.4 also traces
the API chain to find which call mints the token.
- catcher receives the URL and launches yt-dlp. Dedupes on the Kaltura asset
id and checks downloader liveness, so a mid-match page reload is both safe
and the recovery path for a dead downloader.
- creds stores secrets in the OS vault rather than a gitignored file, and
refuses to run on a backend that does not encrypt.
Protocol notes are in the README: the stream uses a two-stage token chain
(a ~25s hdnts token for the master playlist, a ~24h hdntl token for media),
concurrency is unrestricted, and the live window is ~30s with no DVR.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kyt7QHQvLJtQRuiY4wAqKB