Skip to content

perf(preview): stop decoding pictures the hidden media elements never show - #976

Merged
EtienneLescot merged 1 commit into
mainfrom
perf/preview-idle-decoders
Oct 2, 2026
Merged

EtienneLescot merged 1 commit into
mainfrom
perf/preview-idle-decoders

Conversation

@EtienneLescot

@EtienneLescot EtienneLescot commented Oct 2, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

The native compositor draws every pixel of the preview, yet Chromium kept decoding the recording beside it, on the decode engine the compositor's own decoders need.

  • Screen: the hidden <video> plays only as the playback clock, and the <audio> on the same mp4 only for its sound, but both decoded every frame of the picture. The editor window now enables the AudioVideoTracks Blink feature, and both elements deselect their video track once their metadata is in (dropVideoTrack).
  • Exception: a recording without sound keeps its picture. With neither track selected the element has nothing left to keep time with: measured, its clock races to the end.
  • Camera: WebcamOverlay is now read for the camera's size only and never played. That retires the playback clock VirtualPreview published for it (playback-clock.ts).

Measured in a hidden Electron 41.2.1 window, 1080p60 take, decode engine of Chromium's GPU process (RTX 4070 Ti):

element playing decode engine frames decoded clock ×1 / ×2 / seek
<video> 6.7 % 516 in ~8.5 s ok
<video>, video track deselected 0.0 % 0 ok, readyState 4
<audio> on the same mp4 6.6 % — ok
<audio>, video track deselected 0.0 % — ok

Related issue

None: comes out of a preview-fluidity investigation. Independent of the shared-texture transport PR.

Type of change

  • Bug fix
  • Feature
  • Enhancement
  • Documentation
  • Refactor / maintenance
  • Performance
  • Security

Release impact

  • Patch
  • Minor
  • Major / breaking change
  • No release note needed

Desktop impact

  • Windows
  • macOS
  • Linux
  • Installer / packaging
  • Not platform-specific

Screenshots / video

No visual change: the elements involved are hidden.

Testing

  • npx vitest --run: full suite green (298 files). New VirtualPreview.tracks.test.ts (4) and a WebcamOverlay test that the camera is never played.
  • tsc --noEmit (app and tests), Biome, npm run docs:check.
  • The bench above, one run per element.
  • In the editor (dev build on Windows, an 8.2 s 1080p take with its webcam): during playback Chromium's GPU process decoded nothing (0.0 % on the decode engine), while the compositor's own decoders ran in the main process (6-9 %). Mid-playback, the clock <video> (muted) and the sound <audio> (not muted) were both playing at 2.80 s with readyState 4 and their video track deselected, the imported voiceover track was playing, and the camera <video> stayed paused. Seeks and the 1.8× speed region played through as before.
  • Electron's dev console flags enableBlinkFeatures (security checklist): AudioVideoTracks only exposes the media track lists, and the warning does not show in packaged builds.

🤖 Generated with Claude Code

… show

The native compositor draws every pixel of the preview, yet Chromium kept
decoding the recording beside it. The screen <video> plays only as the
playback clock and the <audio> on the same mp4 only for its sound, but both
decoded every frame of the picture: measured on a 1080p60 take, ~6.7 % of an
RTX 4070 Ti's decode engine apiece, on the engine the compositor's own
decoders need. The camera <video> decoded and seeked the whole webcam
recording for pixels CSS hid.

The editor window enables the AudioVideoTracks Blink feature, and both
elements deselect their video track once their metadata is in: zero frames
decoded, with the clock, playbackRate and seeks unchanged. A recording
without sound keeps its picture, since with neither track selected the
element has nothing left to keep time with and races to its end.

The camera element is now read for its size only and never played, which
retires the playback clock VirtualPreview published for it.
@coderabbitai

coderabbitai Bot commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: c6e1a616-40d2-40e9-8fde-10364477cecd

📥 Commits

Reviewing files that changed from the base of the PR and between bbeb37f and e127431.

📒 Files selected for processing (10)
  • electron/windows.ts
  • src/components/ai-edition/NewEditorShell.module.css
  • src/components/ai-edition/PreviewCanvas.tsx
  • src/components/ai-edition/VirtualPreview.tracks.test.ts
  • src/components/ai-edition/VirtualPreview.tsx
  • src/components/ai-edition/WebcamOverlay.test.tsx
  • src/components/ai-edition/WebcamOverlay.tsx
  • src/lib/ai-edition/timeline/playback-clock.test.ts
  • src/lib/ai-edition/timeline/playback-clock.ts
  • technical-documentation/architecture/preview.md
💤 Files with no reviewable changes (2)
  • src/lib/ai-edition/timeline/playback-clock.test.ts
  • src/lib/ai-edition/timeline/playback-clock.ts

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 6 remain after this review.


📝 Walkthrough

Walkthrough

The preview enables Chromium media track support and drops video tracks after metadata loads when audio and video tracks are available. The shared playback clock is removed. WebcamOverlay now reads camera dimensions without playing its video.

Changes

Preview media handling

Layer / File(s) Summary
Screen media tracks and clock removal
electron/windows.ts, src/components/ai-edition/VirtualPreview.tsx, src/components/ai-edition/VirtualPreview.tracks.test.ts, src/components/ai-edition/PreviewCanvas.tsx, src/lib/ai-edition/timeline/playback-clock.ts, src/lib/ai-edition/timeline/playback-clock.test.ts, technical-documentation/architecture/preview.md, src/components/ai-edition/NewEditorShell.module.css
The editor window enables Chromium’s AudioVideoTracks feature. VirtualPreview deselects video tracks on metadata load when both audio and video track lists are present. The shared playback-clock API and its publication from VirtualPreview are removed. Tests cover the track helper’s return values and track selection.
Webcam metadata and preview wiring
src/components/ai-edition/WebcamOverlay.tsx, src/components/ai-edition/WebcamOverlay.test.tsx, src/components/ai-edition/PreviewCanvas.tsx, src/components/ai-edition/NewEditorShell.module.css
WebcamOverlay takes clips and current time, then renders a muted video preloaded for metadata for visible camera tracks. It records positive native dimensions without playing the video. PreviewCanvas removes the former playback and layout props, and the test checks that the video is not played.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Other

Sequence Diagram(s)

sequenceDiagram
  participant PreviewCanvas
  participant VirtualPreview
  participant ScreenMedia
  participant WebcamOverlay
  participant CameraVideo
  PreviewCanvas->>VirtualPreview: Render clips and current time
  VirtualPreview->>ScreenMedia: Load screen media
  ScreenMedia-->>VirtualPreview: Report metadata loaded
  VirtualPreview->>ScreenMedia: Deselect video tracks when audio and video tracks exist
  PreviewCanvas->>WebcamOverlay: Render clips and current time
  WebcamOverlay->>CameraVideo: Render muted video with metadata preload
  CameraVideo-->>WebcamOverlay: Report native dimensions
Loading

Merge Risk: ⚪ Minimal · up to e1274

No demonstrated preview regression remains to block merging after normal checks. The Electron playback check is still useful for confirming the track behavior in-app.

Security Architecture Review

Security architecture risk: 🔵 Low · up to e1274

The change is limited to preview playback and media metadata. No expanded data access or privilege was demonstrated, but real-media timing and recovery behavior remain partly unverified.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The demonstrated exposure remains media processing within the editor renderer for existing recording and camera sources. The new feature exposes track-selection controls to that renderer, but the inspected changes do not grant new filesystem, credential, or native-command authority.

Trust Boundaries and Controls

  • observed — Webcam metadata loading remains gated by the resolved camera track's visibility and source path. The existing URL converter accepts HTTP, HTTPS, blob, and data URLs as well as local paths; it is not an allowlist. This behavior predates the PR, and upstream source-path provenance and validation were not established by the focused inspection.

Resilience and Maintainability Implications

  • inferred — Camera-source switching remounts the metadata element by source path. A late callback writes dimensions under its captured source key, while PreviewCanvas reads the active camera's key, limiting cross-source dimension contamination. Entries are dimensions rather than media content; component-level eviction was absent before and remains absent, and a document-unload eviction caller was not verified.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 8 functions across 6 files. (2 skipped: 2… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly and concisely describes the main performance change: preventing hidden media elements from decoding video frames they do not display.
Description check ✅ Passed The description includes the required summary, issue context, change type, release impact, desktop impact, screenshots note, and detailed testing results. It is complete and directly related to the pu…
Full details: Docstring Coverage

Explanation

Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 8 functions across 6 files. (2 skipped: 2 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


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.

@EtienneLescot
EtienneLescot merged commit e73097c into main Oct 2, 2026
21 checks passed
@EtienneLescot
EtienneLescot deleted the perf/preview-idle-decoders branch October 2, 2026 08:52
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