Commit Graph

2 Commits

Author SHA1 Message Date
Mikkeli Matlock 847fe1e13f Choose the feed, not just the rendition
The live page can expose two entries for one match, an audio feed and a video
feed, and discovery returned whichever manifest loaded first. That race came
out differently twice on the same night: at 21:11 the page served the video
entry, at 22:30 the audio one. The scheduled run recorded audio against a video
pass, and nothing looked wrong -- it fails by producing a complete, playable,
healthy recording of the wrong thing.

--prefer cannot rescue that; it picks a rendition inside one master, after the
entry is already chosen. So add --feed, which chooses between entries:

  video (default)  prefer a video feed, fall back to audio
  audio            the reverse
  any              first discovered, the old behaviour
  both             record every feed in parallel
  --entry <id>     skip discovery and pin one

find_manifest now returns every entry it sees and keeps watching 15s past the
first hit, rather than returning on it. Each candidate is classified by the
codecs in its master, never by entry id -- ids name a feed, but relying on that
would bake in an observation that has already been wrong once.

A preference is not a filter. Non-preferred feeds stay on the list, because a
feed you hold no pass for resolves a master fine and only 403s later on the
segments; the recorder falls through to the next candidate when a download dies
immediately, so a wrong guess costs seconds rather than the match.

Output files are tagged -video / -audio, which matters once --feed both writes
two at once.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fr1fLMnVGNAKH5L2BmhMxn
2026-09-26 22:33:34 +09:00
Mikkeli Matlock 21113bd6ba Capture Bristol Rovers video pass streams for personal time-shifting
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
2026-08-29 23:57:05 +09:00