vidscroll0.3.3

Automatic optimization

How vidscroll re-encodes slow-to-scrub videos in the browser, caches them, and what you can configure.

You can give ScrollVideo any MP4 or WebM, including one exported straight from an editor. If its keyframes are too far apart for smooth scrubbing (why that matters), vidscroll fixes the file in the visitor’s browser. This is on by default.

What happens

  1. Check the cacheIf this file was optimized on an earlier visit, that copy is used and nothing is downloaded.
  2. DownloadOtherwise the whole file is fetched, so its structure can be read.
  3. Check keyframesGaps of 0.5 s or less: the file is used as it is.
  4. Re-encodeOtherwise the browser's video encoder (WebCodecs) makes a copy with close keyframes.
  5. Swap and storeThe copy replaces the original at the same frame and is saved for next time.

What visitors see

While the re-encode runs, the original video is already on screen and can be scrolled. Scrolling forward plays it smoothly; scrolling backward is choppy until the new copy arrives. A small badge in the corner shows the progress. When the copy is ready, it takes over at exactly the frame on screen, so the switch isn’t visible.

In our tests, a 60-second 1080p clip took about 8 to 10 seconds to re-encode on a desktop computer and about 20 seconds on an Android phone. Shorter clips are proportionally faster.

To keep the loading overlay up until the smooth copy is ready instead, use wait:

Hero.tsx
<ScrollVideo src="/videos/hero.mp4" optimize={{ wait: true }} />

The re-encoded copy

PropertyValue
KeyframesOne every 0.25 s
ResolutionShort side at most 720 px (never enlarged)
Frame rateAt most 30 fps, or 15 fps for videos over two minutes
CodecH.264
AudioRemoved

The browser encoder favours speed over size: for the clip above, the copy it made was 18.6 MB, where the CLI produces 11.9 MB at the same resolution. That file lives only in the visitor’s browser, but it’s one more reason to prepare videos ahead of time for production.

Caching

The optimized copy is saved in the browser’s Cache Storage, so later visits load it straight away without downloading or re-encoding again. The cache entry is tied to:

  • the video’s URL,
  • the optimization settings, so changing maxResolution, maxFps or maxKeyframeGap creates a new copy,
  • the file’s identity, read from its ETag, Last-Modified or Content-Length header, so replacing the file on the server starts over.

Caching also needs a secure page (HTTPS or localhost), like WebCodecs itself.

Options

Pass an object to optimize to change the defaults, or false to turn optimization off:

Hero.tsx
<ScrollVideo src="/videos/hero.mp4" optimize={{ maxResolution: 1080, cache: true }} />
PropTypeDefaultDescription
maxKeyframeGapnumber0.5Largest keyframe gap, in seconds, that counts as fine. Files above it are re-encoded.
maxResolutionnumber720Short side of the re-encoded copy, in pixels. Never enlarges.
maxFpsnumber30Frame rate cap for the copy. 15 for videos over two minutes unless set.
cachebooleantrueSave the copy for later visits.
waitbooleanfalseKeep the loading overlay until the copy is ready, instead of showing the original meanwhile.

When it can’t run

In each of these cases vidscroll still shows the video, and says why in the browser console:

SituationWhat happens
The browser has no WebCodecsThe original is used; scrubbing is only as smooth as the file.
The re-encode failsThe original stays on screen.
The file is on another site without CORSvidscroll can’t read it, so it streams the file directly instead.
Several raw videos on one page in FirefoxFirefox may refuse to encode more than one at a time; the others keep their originals.
optimize={false}The file is used as is, with a warning if its keyframes are far apart.
fullPreload={false}The file is streamed directly: nothing is downloaded or re-encoded first.

When to rely on it

Automatic optimization is ideal while building, for content that changes often, and for videos you don’t control. For a production page with a fixed video, pre-encode it with the CLI: the file is smaller, every visitor gets smooth scrubbing on their first visit, and phones skip the work entirely.