0.4.0 Beta 15 - Episode handoffs, paused Dolby Vision, and playback recovery
Install this over any earlier Apple build. Beta 15 brings together the Apple playback work tested in local builds 248–250, plus a new guard for next episodes starting several seconds into the video. Apple build 251. All Beta 14 changes are retained; no earlier executable or release package has been substituted.
This is an Apple-only update for Apple TV, iPhone, iPad, and Apple Silicon Mac. Android remains on the signed Beta 14 packages described below.
What's fixed
Next episodes no longer accept an unexpected multi-second opening as a normal start. A device diagnostic showed a fresh episode committing at 4.046 seconds despite a zero resume point and auto-skip being off. The new check intercepts that first position before it can update the episode identity or watch progress, and makes one precise return to the opening on the already-running player. It does not restart the stream or change your pause state. Genuine resume points, live streams, and your own seeks stay in charge. If the correction cannot reach the opening, the app reports a source failure instead of quietly skipping ahead or repeatedly rewinding. This targets the observed next-episode handoff; the separate native decoder failure still needs device verification.
Next-episode preloading can retain the whole requested warm prefix. The preloader requested the first 32 MiB but its response-size validator could reject that same valid response. The limit now matches the request. This removes a specific reason prepared streams were discarded and had to start cold; it is not a promise that every Usenet source can prepare instantly on every server.
Changing or recovering a source no longer introduces its own hidden Pause. An implementation pause used while rejecting or retiring a source could survive an in-place player replacement, leaving the new source frozen despite having data. That synthetic pause is removed. An actual viewer pause is still preserved, but is bound only after the replacement is accepted. A failed retiring engine's paused flag does not get mistaken for your choice. Rejected replacements retain the current load's state.
A paused Dolby Vision stream can recover an expired local HLS playlist without skipping the episode or immediately falling back. The device trace identified a real conflict: while paused, the bounded local producer stopped adding segments, and AVFoundation eventually rejected the unchanged growing playlist. One failure callback previously bypassed the existing paused-recovery path. It now keeps same-mount recovery evidence and waits for Play. Duplicate failure callbacks coalesce, and existing position, track-selection and DV restoration stay attached to the current item. No fake segments or unbounded producer buffer have been added.
A producer finishing while you are paused does not mean you finished watching. Recovery now distinguishes the producer's final playlist from the viewer's actual position. A retained position inside that finished playlist can resume; a real end remains an end, and an invalid or evicted position remains a source error. Retry budgets only re-arm after sustained real playback, not seek jumps or paused ticks, preventing repeated item-replacement loops.
A stream ending early cannot casually mark the episode watched and play the next one. Both Apple playback surfaces now compare a decoder's EOF against load-owned position and known duration. An EOF far before the ending enters same-episode source recovery instead of completion handling. Recovery uses observed playback position, not an optimistic scrub target or old resume floor. Duplicate EOF callbacks cannot spend the recovery budget twice. True endings, live playback, trailers and unknown-duration sources keep their existing semantics. This addresses the premature-completion code gap examined alongside issue #223.
Replacement items do not inherit the previous item's completion evidence. AVPlayer can recover a physical item while retaining the logical playback request. Completion evidence now also follows the physical item generation, so an old early-EOF rejection cannot prevent the recovered item from genuinely finishing later. Retired callbacks cannot finish a newer episode.
Apple TV's short backward/forward seeks receive the same refill protection as a scrub. A relative seek outside the buffered window previously missed the existing refill hold and bounded recovery watchdog. It now uses that protection while retaining relative seek semantics and your latest Pause/Play choice. In-buffer seeks do not unnecessarily invoke the cold-refill path.
Continue Watching keeps the episode you actually opened when it needs to show Details. Local CW navigation on Apple TV and iPhone now carries the exact episode ID and resume point into the detail page. An episode with a zero resume point is still a valid selection; it does not fall back to an unwatched special such as S0E1. After you successfully play a newer episode, that newer local receipt supersedes the older navigation hint. If a partial episode list does not yet contain the exact target, the hero waits rather than inventing a different episode.
The phone's resume offset must belong to its selected episode. The detail hero no longer applies an offset from one episode to a different selected episode. This matches the existing episode-identity check on Apple TV.
Up from the first episode returns to the selected season. On Apple TV, that move now explicitly reveals and focuses the current season chip instead of jumping to the hero or making you navigate back down from Play. Down from the first episode still moves to the second; deeper episode rows retain their normal navigation.
Supported native AVPlayer WebVTT subtitles can follow the in-player appearance settings. Their timed text can now use the existing VortX subtitle overlay, so outline, shaded and box styles are app-controlled. The native renderer is suppressed before supported text is displayed, and cues replace rather than accumulate. Seeks, subtitle changes, item replacements and close clear or fence stale cues. Unsupported or bitmap captions remain native; Picture in Picture and AirPlay retain native captions. This does not change the device's system caption settings or claim styling support for every subtitle format.
Diagnostics preserve useful decoder failure reasons without exporting raw decoder traffic. Probe-enabled release builds now retain bounded, allowlisted VideoToolbox failure categories, including bad frame status, no-output callbacks, session/format failure and waiting for a keyframe. Signed stream links, request headers and arbitrary log text are excluded. This helps distinguish a native decoding failure from an output-frame drop or an empty network cache.
Android
There is no new Android APK in Beta 15. The current Full/MPV and Play/Media3 packages remain in Beta 14, version code 237. Both variants include phone and Android TV interfaces. Their existing fixes are retained; this Apple release does not claim new Android playback or parity work.
The separately recorded Android rapid-title-selection race and Android update-feed correction remain open. Use the matching Beta 14 APK directly while that feed still serves the older entry.
Verification and remaining limits
The Apple completion, Continue Watching target, focus, resume/seek, source handoff, subtitle and diagnostic policies have executable regression coverage. Independent source review accompanies the changes; the release workflow builds and verifies fresh Apple packages, engine pins, signing/provenance and update feeds before publication.
The fresh-origin recovery was also exercised against the exact bundled GPL playback libraries with VideoToolbox, GPU-next/MoltenVK and AVFoundation audio. A controlled 4.046-second initial position returned to zero while playing and while paused, without changing the pause state. The matching source itself contains timestamps starting at zero.
These are specific repairs, not a claim that every playback problem is solved. The physical Apple TV's initial hardware-decoder failure has not been reproduced on the Mac, and broader active-play DV stalls, provider-specific buffering and sustained NNTP throughput still need live-device testing. This release does not force software decoding, remove Dolby Vision, or disguise a failed source as a completed episode. The broader Android parity and phone/Mac redesign work is not bundled into this playback cut.
Please test
- Let a series advance automatically and use the next-episode button. Confirm the opening is shown, the selected episode is correct, and watch progress belongs to that episode.
- Pause a DV/AVPlayer title long enough for the local producer to stop filling, then resume. Confirm it stays paused until Play and recovers the same episode and selections.
- Seek backward and forward both inside and outside the buffered window, including while paused.
- Open Family Guy or another series from CW. If Details opens, confirm it targets the current episode instead of an unwatched special. From the first episode, press Up once to reach the season selector.
- With supported built-in AVPlayer text subtitles, compare outline and box appearance. Include the subtitle format and a diagnostic if it remains native or ignores styling.
Install
Apple TV. Use VortX-tvOS-v0.4.0-beta.15-ci.ipa for Full or VortX-tvOS-lite-v0.4.0-beta.15-ci.ipa for Lite. Install the same variant you normally use through your signing service.
iPhone and iPad. Use VortX-iOS-v0.4.0-beta.15-ci.ipa. Apple sideloading instructions and the VortX install feed are available for supported installers.
Mac. Download VortX-macOS-v0.4.0-beta.15-ci.dmg, drag VortX into Applications, and use System Settings > Privacy & Security > Open Anyway if needed. This is the Apple Silicon package, ad-hoc signed rather than notarized. Mac installation guide.
Check SHA256SUMS-ci.txt; the immutable tag, source commit, and protected release workflow provide provenance for the published Apple files. This beta is deliberately promoted to Latest; Apple update and install feeds are verified as part of publication.