fix: separate Cast launch readiness, preserve volume intent and reuse seek inputs

This commit is contained in:
2026-10-13 21:40:19 +02:00
parent 697158aa02
commit b9e63cd760
8 changed files with 365 additions and 55 deletions
+5 -1
View File
@@ -211,15 +211,19 @@ Open media, then choose the **Cast** icon in the titlebar (or compact controls),
Terebi pauses local output before transferring the acknowledged position and play/pause intent to Google's Default Media Receiver. The existing controls, keyboard shortcuts and macOS media commands control remote playback, seeking, volume/mute and resolved-source subtitles. **Play on This Mac** restores receiver-confirmed position and intent; local volume is preserved independently. Connection/load failures return to local playback with an error. Opening another source ends casting and opens it locally. Frame stepping and YouTube quality changes are local-only; automatic quality is suspended while casting.
TLS connection establishment has a twelve-second deadline; cold receiver launch has a separate thirty-second deadline and accepts validated asynchronous readiness without waiting for the original launch acknowledgement. Volume controls retain the latest requested value until its acknowledgement, ignore older feedback, and do not reposition the native slider during a drag. External TV volume changes still update idle controls.
The Mac serves session-only capability URLs over HTTP. Keep it awake and connected, and allow incoming connections through its firewall. The relay exposes only the chosen media and subtitle resources, never arbitrary filesystem paths or a general URL proxy. Disconnect, replacement and quit cancel delivery and invalidate the listening endpoint.
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.
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.
The Cast channel accepts the selected receiver's self-signed TLS certificate: encryption on a trusted LAN, **not** Google device authentication or public-CA receiver identity verification. Discovery and receiver control trust the selected LAN endpoint. Native media decoding has a 4096×2160-pixel budget, individual FFmpeg allocations are capped at 128 MiB after Cast initialization, and each outgoing segment is capped at 32 MiB. Recorded inputs longer than fourteen days are rejected.
`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. A production-paced live HLS smoke also decoded A/V across a segment boundary and shut down. **Physical Cast playback, receiver captions and perceived A/V synchronization remain human verification; the TODO stays open until that check.**
`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.**
## Resume playback