Vize

Scrubber Preview

Headless seek-bar preview: sprite, WebVTT, or captured video thumbnails with hover time.

Package @vizejs/ui/scrubber-preview
Maturity stable
Own the source vize lib pull scrubber-preview
Requires context, controllable-state
Aliases scrubber preview, video thumbnail, seek preview, storyboard, trick play, thumbnail track
Covers WebVTT thumbnail tracks (JW Player / Video.js convention), Media Fragments URI xywh, Vidstack slider thumbnails, HTMLVideoElement + canvas frame capture

Usage

import { ScrubberPreview, ScrubberPreviewRoot, ScrubberPreviewThumbnail, ScrubberPreviewTime, ScrubberPreviewTrack } from "@vizejs/ui/scrubber-preview";

Or copy the source into your project with vize lib pull scrubber-preview (see Source Distribution).

API

ScrubberPreview

Source: src/families/media/scrubber-preview/scrubber-preview-root.vue

Props

Prop Type Default Description
duration (required) number required Media duration in seconds.
time number | null undefined Controlled preview time (v-model:time). null hides the preview; undefined is uncontrolled.
dir ScrubberPreviewDirection "ltr" Reading direction; RTL tracks map the right edge to time zero.
disabled boolean false Stop previewing and seeking.
sprite ScrubberPreviewSprite undefined Sprite-sheet thumbnails. Takes precedence over thumbnails and videoSrc.
thumbnails string | readonly ScrubberPreviewCue[] undefined WebVTT thumbnails track text, or pre-parsed cues. Takes precedence over videoSrc.
thumbnailsBaseUrl string undefined Base URL that relative image URLs in VTT text resolve against.
videoSrc string undefined Video URL used to capture frames on the fly in the browser (same-origin or CORS-enabled).
captureWidth number 160 Width of captured frames in pixels.
captureInterval number 1 Captured frames are shared across this many seconds (cache granularity).
cacheSize number 40 Maximum captured frames kept; older object URLs are revoked.

Events

Event Payload Description
update:time [time: number | null] Fired when the preview time requests a new controlled value.
seek [time: number, nativeEvent: Event] Fired when the user releases a click or scrub on the track.

Slots

Slot Slot props Description
default ScrubberPreviewSlotState Track, thumbnail, and time parts. Receives the preview state.

Exposed

Member Type Description
active —
duration —
element Readonly<ShallowRef<HTMLElement | null>> Template ref to the rendered root element.
ratio —
setTime —
time —

ScrubberPreviewRoot

Source: src/families/media/scrubber-preview/scrubber-preview-root.vue

Props

Prop Type Default Description
duration (required) number required Media duration in seconds.
time number | null undefined Controlled preview time (v-model:time). null hides the preview; undefined is uncontrolled.
dir ScrubberPreviewDirection "ltr" Reading direction; RTL tracks map the right edge to time zero.
disabled boolean false Stop previewing and seeking.
sprite ScrubberPreviewSprite undefined Sprite-sheet thumbnails. Takes precedence over thumbnails and videoSrc.
thumbnails string | readonly ScrubberPreviewCue[] undefined WebVTT thumbnails track text, or pre-parsed cues. Takes precedence over videoSrc.
thumbnailsBaseUrl string undefined Base URL that relative image URLs in VTT text resolve against.
videoSrc string undefined Video URL used to capture frames on the fly in the browser (same-origin or CORS-enabled).
captureWidth number 160 Width of captured frames in pixels.
captureInterval number 1 Captured frames are shared across this many seconds (cache granularity).
cacheSize number 40 Maximum captured frames kept; older object URLs are revoked.

Events

Event Payload Description
update:time [time: number | null] Fired when the preview time requests a new controlled value.
seek [time: number, nativeEvent: Event] Fired when the user releases a click or scrub on the track.

Slots

Slot Slot props Description
default ScrubberPreviewSlotState Track, thumbnail, and time parts. Receives the preview state.

Exposed

Member Type Description
time number | null Previewed time in seconds, or null while no preview is shown.
ratio number | null Previewed position 0..1 along the track, or null.
active boolean Whether a preview is shown.
duration number Media duration in seconds.
element HTMLDivElement | null Rendered root element.
setTime (time: number | null) => boolean Show a preview for a time (e.g. while a seek slider has keyboard focus), or hide it.

ScrubberPreviewThumbnail

Source: src/families/media/scrubber-preview/scrubber-preview-thumbnail.vue

Events

Event Payload Description
error [error: ScrubberPreviewError] Fired when a thumbnail cannot be produced.

Slots

Slot Slot props Description
default ScrubberPreviewThumbnailSlotState Custom thumbnail rendering. Defaults to an <img> for captured frames; sprite and VTT frames are published as custom properties for CSS backgrounds.

Exposed

Member Type Description
kind ScrubberPreviewKind Source of preview images.
status ScrubberPreviewStatus Availability of the current frame.
frame ScrubberPreviewFrame | null Resolved frame, or null.
time number | null Previewed time in seconds, or null.
error ScrubberPreviewErrorCode | null Failure code after an error, or null.
element HTMLDivElement | null Rendered thumbnail element.

ScrubberPreviewTime

Source: src/families/media/scrubber-preview/scrubber-preview-time.vue

Props

Prop Type Default Description
format (seconds: number) => string undefined Custom formatter. Defaults to m:ss, or h:mm:ss for media of an hour or longer.

Slots

Slot Slot props Description
default ScrubberPreviewTimeSlotState Custom time rendering. Receives the previewed time and its formatted text.

Exposed

Member Type Description
time number | null Previewed time in seconds, or null.
text string Formatted time, e.g. "1:05" or "1:02:03"; empty while inactive.
element HTMLSpanElement | null Rendered time element.

ScrubberPreviewTrack

Source: src/families/media/scrubber-preview/scrubber-preview-track.vue

Slots

Slot Slot props Description
default ScrubberPreviewSlotState Track contents, typically the consumer's seek bar. Receives the preview state.

Exposed

Member Type Description
element HTMLDivElement | null Rendered track element.
scrubbing boolean Whether a pointer is scrubbing (pressed) on the track.

Behavior

Normative state x input -> outcome table for scrubber-preview-root.vue, scrubber-preview-track.vue, scrubber-preview-thumbnail.vue, and scrubber-preview-time.vue (@vizejs/ui/scrubber-preview). Every row is proven by the named test.

The preview is a visual affordance layered on the consumer's seek control: the track maps pointer positions to a preview time, the thumbnail resolves a frame for that time, and the time part shows it. All parts are aria-hidden; keyboard users hear the seek slider's own value text, and setTime() lets a focused slider drive the same preview. Frame sources, in precedence order, are a sprite sheet, a WebVTT thumbnails track, or frames captured on the fly from a hidden client-only <video>.

ID State Input Outcome Evidence
SP1 idle render root is idle with ratio 0; thumbnail is hidden and decorative; time text is empty renders an idle preview with hidden, decorative thumbnail and time parts
SP2 mouse hover pointerenter / move / leave the pointer position maps to a time and ratio (--vize-ui-scrubber-preview-ratio); leaving hides the preview; update:time reports each hovering the track previews the time under the pointer and leaving hides it
SP3 press on track pointerdown, move, up / cancel / touch pressing captures the pointer and keeps the preview while outside; release emits seek(time, event); cancel never seeks; touch hides on lift; RTL maps the right edge to zero; secondary buttons are ignored clicking or scrubbing the track emits seek on release; touch hides on lift
SP4 controlled / disabled time prop, setTime(), disabled a controlled time wins and clamps to the duration; setTime() shows or hides the preview and reports changes; disabled roots neither preview nor seek controlled time, setTime, and disabled roots
SP5 sprite preview time the frame's sheet URL and offset/size are published as custom properties; unsafe sheet URLs render nothing and report error sprite thumbnails publish background geometry for the previewed frame
SP6 WebVTT preview time cues (text or parsed) resolve relative to thumbnailsBaseUrl; regions become offsets; slots receive the frame; gaps are idle WebVTT thumbnails resolve cues and expose frames to slots
SP7 capture preview time a client-only hidden video captures one frame per captureInterval slot into an LRU cache of object URLs; evicted and unmounted frames are revoked; the default slot renders an <img alt=""> captured thumbnails are generated once per interval, cached, and revoked
SP8 capture busy rapid time changes only the latest pending slot is captured after the current one; intermediate requests are skipped rapid capture requests keep only the latest pending frame
SP9 capture failure seek error / unsafe videoSrc the thumbnail reports error with a typed ScrubberPreviewError; unsafe video URLs disable capture (kind="none") capture failures surface typed errors
SP10 captureVideoFrame call waits for metadata, clamps and seeks, scales to the requested width keeping aspect, and encodes a Blob or data URL captureVideoFrame waits for metadata, seeks, scales, and encodes
SP11 captureVideoFrame failure no 2D context is …_UNSUPPORTED, draw failures are …_CAPTURE_FAILED, cross-origin encoding is …_TAINTED, empty encodes are …_CAPTURE_FAILED captureVideoFrame reports unsupported, tainted, and failed encodes
SP12 missing provider setup parts fail closed with the shared context diagnostic compound parts require a matching root provider
SP13 VTT parser text cues with #xywh= (optionally pixel:) regions parse; malformed cues are skipped; URLs resolve against a base parses WebVTT thumbnail cues with sprite regions and resolves relative URLs
SP14 cue lookup time binary search finds the covering cue with an exclusive end; gaps return nothing finds the cue covering a time by binary search
SP15 sprite math time frames fill rows then sheets, clamp to frameCount, and invalid geometry throws a typed RangeError maps times to sprite frames across rows and sheets
SP16 helpers pointer, quantize, format ratios clamp and mirror for RTL; times snap to capture slots; times format as m:ss or h:mm:ss maps pointers to ratios, quantizes times, and formats durations
SP17 frame cache get / set / clear least-recently-used entries are evicted and every released URL is reported the frame cache evicts least-recently-used URLs
SP18 SSR isolated requests markup is byte-identical, never renders the capture <video> or an <img>, and renders sprite geometry for a controlled time renders byte-identical scrubber preview markup across isolated SSR requests
SP19 SSR / hydration hydrate server markup hydrates without warnings or node replacement hydrates scrubber preview markup without warnings or node replacement
SP20 types compile kinds, statuses, and error codes are closed; captureVideoFrame returns Blob or string by output scrubber-preview.types.test-d.ts

Captured thumbnails need a same-origin video or CORS headers (the capture video sets crossorigin="anonymous"); otherwise canvases are tainted and capture reports …_TAINTED.