Skip to content

cmux-next: video backgrounds fade in and free their decoder when out of sight - #21720

Merged
teamleaderleo merged 3 commits into
feat-cmux-nextfrom
leo/next-video-playback
Oct 18, 2026
Merged

teamleaderleo merged 3 commits into
feat-cmux-nextfrom
leo/next-video-playback

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 18, 2026 •

Copy link
Copy Markdown
Collaborator

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 (Motion fade token fadeIn) 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. BackdropVideoPlayers now 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 AVQueuePlayer and 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.
  • 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. BackdropImageStore already 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 for releaseAfter, 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


View with [code]smith Autofix with [code]smith
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 AVQueuePlayer and, 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.

Written for commit 7175953. Summary will update on new commits.

View guided diff Turn on auto-fix

…of sight

The first frame now fades in over the poster instead of cutting. A video no
one can see (hidden, minimized, covered, screens asleep) for a minute drops
its items, freeing the decoder and frame buffers, and resumes at the frame it
held when seen again. A video held for Low Power Mode or Reduce Motion is
still on screen and keeps its frame.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration
  • Configuration used: Repository: manaflow-ai/cmux/.coderabbit.yaml
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: e64807c0-c0a7-4afd-ab4a-fa2e153aec4f

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

Receipt for 7175953 (this PR's head; a new push replaces it)

  • Visual review: HQ feed card · gallery before/after runs
  • Checks: this head
  • App of this head (app.zip, kept 1 day): gh workflow run reload-build.yml -R manaflow-ai/cmux --ref feat-cmux-next -f tag=pr21720 -f ref=leo/next-video-playback -f platform=macos -f backend_mode=local

@github-actions

github-actions Bot commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

Not verified: macOS jobs did not run: compile and app tests were skipped on 7175953042; ci-status is green without them.

CI passes on 7175953042 (run 39142268173 attempt 1).
macOS jobs did not run: compile and app tests were skipped: Fast static checks skipped (the macos job needs both to succeed). Re-run CI once they pass, before merging.

Written by scripts/ci/classify_failures.py (ci-failure-attribution.yml); signatures are its SIGNATURES table. A machine verdict is the runner's fault, not this PR's; yours means the failing file is one this PR changes, also red on main that main's latest full suite fails the same way, seen on other PRs that it failed on another pull request's run lately.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Bead cx-mt09g created for this PR by the cmux coordinator.

@blacksmith-sh

blacksmith-sh Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

Found 2 test failures on Blacksmith runners:

Failures

Test View Logs
/tmp/tmp6rwounrd/summary-fail.json (live):/summary-fail.json (live): View Logs
/tmp/tmpz5yyvxdb/summary-missing.json (live):/summary-missing.json (live): View Logs

Fix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

teamleaderleo and others added 2 commits October 18, 2026 15:34
… ready

Review fixes: the seek after a decoder release waits for the new item to be
ready (a seek sent before then can be dropped or undone by the looper) and uses
zero tolerance both ways, not the next keyframe. The players take their clock,
so the release deadline test steps a manual clock; the restore test checks the
time it came back at.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…me test holds still

Re-review fixes: the entry is stored before the readiness observation, so an
item already ready (reported inline) seeks and clears its pending restore
instead of leaving it set. The resume test restores while held in Low Power,
so a restart from 0 cannot reach the mark by playing; it checks 0.95-1.05 s.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@teamleaderleo
teamleaderleo merged commit 8114fe4 into feat-cmux-next Oct 18, 2026
129 of 139 checks passed
@teamleaderleo
teamleaderleo deleted the leo/next-video-playback branch October 18, 2026 21:17
teamleaderleo added a commit that referenced this pull request Oct 19, 2026
The batch Swift run failed aVideoNoOneCanSeeGivesBackItsDecoderAndPicksUpWhereItWas
(from #21720): AVPlayerLooper inserts items once the asset's duration loads, so
checking them right after attaching raced it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant