Skip to content

fix(playback): mask flashes between files - #21

Merged
FengZeng merged 3 commits into
FengZeng:mainfrom
cjohnsto-nz:agent/fix-playback-transition-flashes
Aug 7, 2026
Merged

fix(playback): mask flashes between files#21
FengZeng merged 3 commits into
FengZeng:mainfrom
cjohnsto-nz:agent/fix-playback-transition-flashes

Conversation

@cjohnsto-nz

@cjohnsto-nz cjohnsto-nz commented Aug 2, 2026

Copy link
Copy Markdown

Summary

  • keep the native window host opaque black on Windows and Linux while making only the WebView transparent
  • add a theme-independent black WebView mask while MPV changes files
  • cover initial playback, manual previous/next navigation, natural EOF, and backend-driven automatic navigation
  • release the mask after playback restart, with race protection and a bounded fallback for hidden or throttled WebViews
  • clear the mask when a file fails before playback restart

Root cause

During a source transition, MPV's native render target can be absent or briefly contain its default or unpainted frame. Because the UI WebView is transparent during playback, that native transition can appear as a transparent or white flash. The source-loading flag cannot safely delimit this interval because it ends when MPV accepts the load command, before the first frame is necessarily presented.

The native host now provides a permanent black backing surface, and the WebView supplies a short black mask across the remaining render-target transition.

Platform safety

  • the mask is implemented with Vue and standard WebView APIs and is shared across platforms
  • native background handling is restricted to Windows and Linux; existing macOS window and vibrancy behavior is unchanged
  • MPV decoding, playback options, and render-target lifecycle are unchanged

Validation

  • pnpm build against current upstream main
  • six-file diff confirmed as exactly one commit ahead of upstream
  • stable patch ID matched the requested source commit
  • the same patch was previously validated with the Windows NSIS release packager

@cjohnsto-nz

Copy link
Copy Markdown
Author

@FengZeng this is a bit of a weird one.
On Windows at least, the entire app goes transparent between video files.
I tried several different mechanisms to address this. All of them exposed a secondary issue: mpv seems to display white frames at the very start and very end of playback.

To address this, I effectively added a "curtain" between the UI webview and the mpv layer while files are changing.
This solved the issue on Windows, but I haven't been able to test on other platforms.
Interested in your thoughts. Was the transparency intentional?

@FengZeng

FengZeng commented Aug 3, 2026

Copy link
Copy Markdown
Owner

Thanks for looking into this. The transparency was not intentional, it is indeed a bug. It can briefly occur when stopping playback or switching to the previous/next video.

The root cause is that transparency is enabled globally in tauri.conf.json. When playback stops, there is a short interval before the WebView becomes opaque again, during which the desktop is visible through the window. A similar gap occurs when switching files: until mpv starts rendering the next video frame, there is no opaque layer behind the transparent WebView.

Your approach of disabling transparent in tauri.conf.json and then enabling WebView transparency in app_bootstrap.rs is a very good idea:

window
    .as_ref()
    .set_background_color(Some(
        tauri::utils::config::Color(0, 0, 0, 0),
    ))?;

This should provide better visual stability because only the WebView needs to support transparency; the native window itself does not need to be globally transparent.

I also investigated why this approach exposes a white rectangle while switching or stopping playback. A simplified way to think about the rendering stack is as three layers:

  1. The native Windows window
  2. The mpv rendering layer
  3. The WebView UI layer

The native window is initially created using the default size from tauri.conf.json, for example 1280×720, and its initial background is white. The application then restores the window to its previously saved size. When the restored size is larger, the newly exposed area appears to be filled with black, while the original 1280×720 area remains white.

When playback stops or changes files, the mpv layer is temporarily removed or hidden. If the WebView is transparent at that moment, the native window background becomes visible. This is why the result looks like a white rectangle matching the initial configured window size, surrounded by black. It remains visible until either the WebView becomes opaque again or mpv renders the next video over it.

I think the cleanest solution is to paint the native window background using the current application theme's background color. That would make the transition visually seamless even when both the mpv layer and the WebView are temporarily transparent. It would also prevent differently colored edges from appearing while the user drags or resizes the window.

@FengZeng

FengZeng commented Aug 3, 2026

Copy link
Copy Markdown
Owner

@cjohnsto-nz I pushed a follow-up commit to your PR that implements native window background painting for windows only. Could you review it and check whether the transition behavior looks better now?

@FengZeng

FengZeng commented Aug 7, 2026

Copy link
Copy Markdown
Owner

The rendering logic on linux is different, so this issue doesn't occur there. The linux logic has been restored.

@FengZeng
FengZeng marked this pull request as ready for review August 7, 2026 12:35
@FengZeng
FengZeng merged commit 6b02fc2 into FengZeng:main Aug 7, 2026
4 checks passed
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.

3 participants