Knit UI
GitHub

Playground

Loading playground…

true
Playground
<Video
  source="https://media.w3.org/2010/05/sintel/trailer.mp4"
  contentFit="contain"
  size="md"
  controls
  autoHide
  loop={false}
  muted={false}
  aspectRatio={1.7777777777777777}
/>

Examples

Basic

Loading example…

BasicSourceStorybook

Auto Play Muted

Loading example…

Auto Play MutedSourceStorybook

Content Fit Cover

Loading example…

Content Fit CoverSourceStorybook

Sizes

Control sizing across the shared kit scale — the chrome's buttons, icons, and scrubber all step together off the canonical controlMetrics/icon ladders (the same scale Button/ActionIcon use), not a media-local copy.

Loading example…

SizesSourceStorybook

Native Platform Controls

Loading example…

Native Platform ControlsSourceStorybook

Custom Control Bar

Compose a custom control bar from the exported parts.

Loading example…

Custom Control BarSourceStorybook

Captions

Loading example…

CaptionsSourceStorybook

Custom Styled Captions

Because captions ride the kit overlay (not the platform's built-in subtitle renderer), their typography is fully stylable via the captions / captionText style slots — font, size, color, weight, background.

Loading example…

Custom Styled CaptionsSourceStorybook

Keyboard Shortcuts

Keyboard shortcuts (focus the player first): Space/k play·pause, ←/→ seek, ↑/↓ volume, m mute, f fullscreen, p PiP, 0–9 jump, </> speed.

Loading example…

Keyboard ShortcutsSourceStorybook

Persistent Controls

Always-visible controls (no auto-hide).

Loading example…

Persistent ControlsSourceStorybook

Styles

Per-slot styles overrides (Pillar B).

Loading example…

StylesSourceStorybook

Swap Source

Two players sharing nothing but the contract — swap the source at runtime.

Loading example…

Swap SourceSourceStorybook

Two Players

Two players sharing ONE shared video engine (the default singleton). The single <video> teleports into whichever player you press play on; the other shows its poster and pauses. Returning to the first resumes from where you left off — and there is only ever ONE <video> element in the DOM.

Loading example…

Two PlayersSourceStorybook

Now Playing

Now-playing / lock-screen controls with a cover preview. nowPlaying folds the title/artist/artwork into the source metadata and flips expo-video's showNowPlayingNotification + staysActiveInBackground, so the OS shows a media notification with the artwork as the cover and playback keeps going in the background. Native-only — surfacing it on a device build also needs the expo-video config plugin's supportsBackgroundPlayback: true. (No-op on web; the story still renders a normal player there.)

Loading example…

Now PlayingSourceStorybook

Props

PropTypeDefaultDescription
source requiredstring | number | VideoSourceObject | nullhttps://media.w3.org/2010/05/sintel/trailer.mp4The media to play.
allowsPictureInPictureboolean | undefined—Allow Picture-in-Picture. Default `true`.
artiststring | undefined—Now-playing artist / secondary text under the title.
artworkstring | undefined—Now-playing artwork (cover) image URL.
aspectRationumber | undefined—Fixed aspect ratio for the frame (e.g. `16 / 9`).
autoHidenumber | boolean | undefinedtrueAuto-hide the chrome during playback. `true` uses the default delay, `false` keeps it always visible, a number sets the delay in ms.
autoPlayboolean | undefined—Begin playback as soon as the source is ready.
contentFitVideoContentFit | undefined
contain · cover · fill
containHow the frame is scaled in the container. Default `'contain'`.
controlsReactNodetrueThe control chrome. `true` (default) renders the built-in control bar; `false` renders no chrome; a node renders custom chrome inside the context (compose `Video.*` parts).
controlsOffsetnumber | SpaceTokens | undefined—Inset of the control bar from the frame edges.
doubleClickToFullscreenboolean | undefined—Web: double-click/tap the video to toggle fullscreen. Default `true`.
getController((controller: VideoController) => void) | undefined—Receives the controller once ready.
heightnumber | Animated.AnimatedNode | GetThemeValueForKey<"height"> | null | undefined——
idstring | undefined—Stable identity for the shared-engine registry. Defaults to a generated id (each `<Video>` is its own player); pass an explicit `id` to make two mounts address the SAME shared-engine slot.
keyboardboolean | undefined—Enable keyboard shortcuts (space, arrows, m, f, …). Default `true`.
labelstring | undefined—Accessible label for the player region. Default `"Video player"`.
loopboolean | undefinedfalseReplay automatically on end.
mutedboolean | undefinedfalseStart muted (required by browsers for unattended autoplay).
nativeControlsboolean | undefined—Use the platform's own native controls instead of the kit chrome.
nowPlayingboolean | VideoMetadata | undefined—Enable the OS now-playing notification + lock-screen controls (native; no-op on web). `true` derives the displayed metadata from `title`/`artist`/`artwork`; an object supplies it explicitly. Surfacing it on a device build also requires the `expo-video` config plugin's `supportsBackgroundPlayback: true`.
onEnded(() => void) | undefined——
onError((error: VideoError) => void) | undefined——
onPlayingChange((playing: boolean) => void) | undefined——
onReady(() => void) | undefined—Fired once the player first becomes ready to play.
onStatusChange((status: VideoStatus, error: VideoError | null) => void) | undefined——
onTimeUpdate((currentTime: number) => void) | undefined——
playbackRatenumber | undefined—Initial playback rate.
posterstring | undefined—Poster image shown before playback (placeholder while the player is idle).
showBigPlayButtonboolean | undefined—Show the centered big play button while paused. Default `true`.
size system"xxs" | "xs" | "sm" | "md" | "lg" | "xl" | "xxl" | undefined
xxs · xs · sm · md · lg · xl · xxl
mdControl sizing scale. Default `'md'`.
styles systemSlotStyles<VideoStyles> | undefined—Per-slot style overrides.
testIDstring | undefined——
textTracksVideoTextTrack[] | undefined—External (sidecar) caption files. The controller fetches, parses, and renders them with the kit's own overlay on every platform.
timeUpdateIntervalnumber | undefined—Seconds the controller waits between `timeUpdate` emissions (native).
titlestring | undefined—Now-playing title (used for the OS lock-screen / now-playing notification).
updateIntervalnumber | undefined—Status / `timeUpdate` interval, ms (native). The unified name.
volumenumber | undefined—Initial volume, 0..1.
widthnumber | GetThemeValueForKey<"width"> | Animated.AnimatedNode | null | undefined—Frame style props (width/height/borderRadius…).

Style slots

Every part of Video can be styled through the styles prop. Explicit props on the component always win over slot styles.

SlotTargets
bigPlay—
buffering—
captionsThe caption cue bubble (background, radius, padding, position offset).
captionTextThe caption cue text (fontFamily, fontSize, color, fontWeight, …).
controlBar—
root—
scrim—
surface—

Edit this page on GitHub