fix: share buffered Cast HLS input and select streams

This commit is contained in:
2026-10-13 22:47:07 +02:00
parent b0636c5af7
commit ad4b2da5c8
6 changed files with 362 additions and 63 deletions
+3 -1
View File
@@ -217,7 +217,7 @@ The Mac serves session-only capability URLs over HTTP. Keep it awake and connect
Local files, resolved Miruro HLS and YouTube's combined/separate video/audio inputs are delivered as six-second HLS segments. Compatible, independently decodable H.264/AAC is remuxed; other supported inputs use VideoToolbox H.264 (including its platform software fallback) and stereo AAC. Output targets at most **1920×1080 at 30 fps**, H.264 Main/High level 4.1 or lower, with preserved display aspect ratio. Recorded segments are generated on demand, including distant seeks; there is no full-movie download or preprocessing step. Live output keeps eight segments (about 48 seconds) and is not seekable. Audio-only sources are supported.
Recorded delivery retains already-probed upstream inputs and caches eight completed segments (at most 256 MiB). Repeated, HEAD and range requests reuse cached bytes; uncached segments seek the retained inputs rather than reopening and probing both streams. Uncached generation is serialized to keep FFmpeg input ownership simple. GOP preroll, transcoding and receiver buffering can still make a fresh Cast seek slower than local playback.
Recorded network delivery uses the native player's bounded compressed-packet buffer: up to 128 MiB shared between inputs, targeting sixty seconds ahead and thirty seconds behind (byte pressure can shorten retention). Combined HLS supplies video/audio from one selected-stream reader; unused quality variants are disabled. Sequential and nearby seeks reuse packets, including decoder/AAC preroll; true cache misses seek upstream once. Nearby forward requests wait for existing read-ahead instead of cancelling and restarting its fetch. Eight completed output segments are also cached (at most 256 MiB), so repeated, HEAD and range requests reuse encoded bytes. Uncached generation is serialized; GOP preroll, transcoding, provider slowness and receiver buffering can still delay a fresh Cast seek.
Miruro retains its HTTP(S)-only, same-origin media and no-redirect policy. Public YouTube HLS can cross CDN origins, but supplied headers never follow it to another origin. All Cast media redirects are rejected. WebVTT is fetched with each track's own headers and the existing bounded, same-origin subtitle redirect policy, then served with CORS. Private upstream addresses and headers are not sent to the receiver or included in errors.
@@ -225,6 +225,8 @@ The Cast channel accepts the selected receiver's self-signed TLS certificate: en
`make check-cast` exercises a real self-signed TLS loopback receiver, decoded relay output for all three source paths, header/origin isolation, recorded seeking, VOD/live audio continuity, anamorphic video, capability expiry, controlled protocol deadlines/live pacing, and complete player handoff/back-to-Mac recovery. Regression checks cover slow/asynchronous launch, stale volume feedback, native slider tracking and split-stream seek work: repeated segments add no upstream requests, and indexed distant/adjacent seeks add no origin-zero reprobes. A production-paced live HLS smoke also decoded A/V across a segment boundary and shut down. **YouTube Cast playback has been observed on a physical receiver; these fixes, receiver captions and perceived A/V synchronization still need human verification.**
Authenticated multi-variant HLS regressions gate upstream responses and verify no unused-quality downloads or duplicate retained-media reads, nearby rewinds, distant cache misses, decoded A/V positions and AAC continuity, and cancellation while upstream remains blocked. Native network playback checks cover the shared reader's existing callers.
## Resume playback
Reopening a local video, YouTube video or resolved Miruro episode automatically resumes its saved position, including after quitting and relaunching the app. Local files use their resolved file paths; YouTube uses the canonical video webpage URL; Miruro uses its opaque media ID and episode number. Newly resolved addresses therefore share progress without saving CDN tokens as identity. The app does not automatically reopen the last video on launch.