跪拜 Guibai
← All articles
Frontend

Double Buffering Video Switches: No More Black Frames Between Clips

By Mh ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Front-end teams building video carousels, product sliders, or animated backgrounds can eliminate black frames between clips for under twenty lines of code and one extra video element, without pulling in a player library. The same double-buffer idea generalizes to any stack where an element both renders and loads.

Summary

Video carousels, product showcases, and background animations often flash black or freeze mid-switch because one video element is forced to both display the current frame and load the next source. Once loading starts, the old frame disappears, but the new clip still needs to download and decode before its first frame can render. That gap is the stutter.

Double buffering splits those tasks across two stacked video elements. The visible video keeps playing while a hidden second video loads the next source. The swap happens when the hidden video fires its `loadeddata` event, meaning its first frame is ready for rendering. Toggling a single boolean flips a CSS class that hides one video and shows the other in the same render, and `visibility: hidden` is used instead of `v-if` so neither element gets destroyed.

The technique does not make downloads faster or files smaller; it only stops the wait from showing as an empty screen. Core logic stays under twenty lines with Vue reactivity and native video elements. The pattern leaves room for fade transitions via opacity, error handling on the background video, and preloading on hover, and it comes with known limits: first load still needs a poster, two elements add decoding overhead on mobile, and large composition differences between clips cause a visible jump regardless of the swap.

Takeaways
— A single video element cannot simultaneously display the current frame and load the next source without a visible gap.
— Double buffering uses two stacked video elements: one stays visible and playing, the other loads the new source invisibly.
— The swap is triggered by the background video's `loadeddata` event, which fires when the first frame is renderable.
— `loadeddata` is more appropriate than `loadedmetadata` as a swap signal because metadata can exist without a renderable frame.
— Toggle visibility between the two videos with a boolean that drives a CSS class using `visibility: hidden`, not `v-if`, to avoid destroying and recreating elements.
— Reassigning the `loadeddata` handler on each click ensures only the last requested clip loads during rapid clicking.
— The core logic is fewer than twenty lines, using Vue's reactivity and native video elements, with no player library required.
— Double buffering does not reduce download time or file size; it only prevents the wait from appearing as an empty screen.
— The first load still has no old frame to show, so a poster image is the fallback.
Conclusions

Double buffering trades one extra video element's decoding cost for perceived smoothness, a trade-off that pays off on desktop but needs scrutiny on high-resolution mobile playback.

Choosing `loadeddata` over `loadedmetadata` is the detail that makes the swap seamless; relying on metadata alone would swap before any frame is drawable, reintroducing the black flash.

Using `visibility: hidden` instead of `v-if` keeps element state intact and avoids remount cost, a pattern that applies to any frequently toggled media element.

The technique is honest about its limits: it hides loading latency instead of reducing it, and it doesn't fix visual jumps when clips have very different compositions.

Concepts & terms
Double buffering (video)
A technique that uses two video elements so one continues displaying current content while the other loads the next source; they swap visibility only when the new frame is ready.
loadeddata event
A browser event fired on a media element when the current playback position has data that can be rendered, meaning the first frame is available for display.
loadedmetadata event
A browser event fired when a media element's dimensions and duration are known, but not necessarily that any frame is renderable.
From the discussion
Featured comments
卷土的土

Keeping the old frame when loading fails is very practical.

See top comments, translated →
Source: juejin.cn ↗ Google Translate ↗ Backup ↗