cmux-next: video backgrounds fade in and free their decoder when out of sight
Merged
TE
18d ago+186+186+012345678901234567890123456789-16-16-01234567890123456789
Phase 2 of the backgrounds plan (briefs/next-backgrounds-plan.md): video background playback.
What changes
- Fade in. A video's first frame fades in over its poster (
Motionfade tokenfadeIn) instead of cutting from the still. Frames that stop, such as a released decoder, still hide at once, which leaves the poster underneath. - Free the decoder when nobody can see the video.
BackdropVideoPlayersnow tracks which windows could be seen at all (BackdropVideoView.canBeSeen): on screen, not minimized or app-hidden, not covered by other windows, screens awake, session active.- When no window showing a video could be seen for
releaseAfter(60 s), the shared player:- saves its time
- disables looping
- drops its items, which frees the hardware decoder and its frame buffers
- When a window can be seen again, it rebuilds the looper on the same
AVQueuePlayerand seeks to the saved frame, so the windows' layers keep their player. - The deadline starts when the last viewer goes out of sight. Updates while hidden don't push it back.
- When no window showing a video could be seen for
- Videos paused but still on screen keep their decoder. That covers Low Power Mode, a hot Mac, and Reduce Motion or animations off. Their frame never drops to the poster in front of someone.
- Not needed: poster caching.
BackdropImageStorealready snapshots a video's first frame on first decode, so launches reuse it. I've dropped that item from the plan.
Tests
In CmuxNextAppTests/VideoWallpaperTests:
aVideoNoOneCanSeeGivesBackItsDecoderAndPicksUpWhereItWas: a video held for Low Power keeps its items. A hidden one releases them, comes back on the same player when seen, and plays.theDecoderGoesOnlyAfterTheDeadline: the release waits forreleaseAfter, and updates while hidden don't reset it.
Verification
- Not built locally: this lane has no Mac. Swift compile and tests are left to this PR's CI.
lint-ios-package-conventions.sh: clean.- CmuxNextApp source lines are unchanged (84323).
- Not dogfooded. To try it with a
dev-build: pick a video background, hide cmux for over a minute, then show it again. The video should come back at the same frame and fade in.
WINDOW
None.
Changelog
Changed: Video backgrounds fade in, and stop using video memory while no one can see them.
🤖 Generated with Claude Code
Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
Video backgrounds in cmux-next now fade in over their poster and free their hardware decoder when no one can see them.
- The first frame fades in over the poster instead of cutting; a frame that stops (a released decoder) goes away at once, leaving the poster below.
- When no window showing a video can be seen (hidden, minimized, covered, screens asleep, or the session inactive) for
releaseAfter(60 s), the shared player saves its position, drops its items, and frees the decoder and its frame buffers. - When a window is seen again, the player rebuilds the looper on the same
AVQueuePlayerand, once the new item is ready, seeks to the saved frame with zero tolerance, so layers keep their player and the video resumes at the exact frame it held. - The release deadline starts when the last viewer goes out of sight; updates while hidden don't push it back, and it is timed by an injectable clock.
- Videos paused on screen (Low Power Mode, a hot Mac, Reduce Motion) keep their decoder so their frame never drops to the poster.