Video

Renders a playing video. Layout and child positioning are inherited from Rect: a Video lays out its children exactly like a Rect, with a playing video frame painted in place of the fill. The video's audio track is automatically scheduled alongside the picture.

0.0s / 4.0s

Usage

import { createScene, Video } from 'motion-script';

export default createScene(function* (stage) {
  stage.add(
    <Video
      src="./assets/clip.mp4"
      fit="fill"
      width={1280}
      height={720}
      cornerRadius={0}
    />
  );
});

Props

Source & fit

PropTypeDefaultDescription
srcstringPath to the video file
fit'fill' | 'fit' | 'tile' | 'stretch''fill'How the video frame fills the node's bounds. 'fill' covers + crops (centered), 'fit' letterboxes, 'tile' repeats, 'stretch' distorts to fill.
cropInsets0Window onto the source frame, in fractions of its own size, applied before fit
zoomnumber1Magnification on top of the fitted scale
anchorAnchor'center'The point held fixed as zoom scales, and the alignment when the frame doesn't cover
matrixImageMatrixRaw frame→shape matrix; bypasses crop/fit/zoom/anchor and the bounds
filtersMediaFilter[] | FilterChain[]Visual filters applied to the rendered frame

crop, zoom and anchor behave exactly as they do on Image — same pipeline, same units, same caveats under 'tile'.

Playback

PropTypeDefaultDescription
playingbooleantrueWhether playback advances with the node's clock
timestampnumber | nullExplicit source time in seconds. Omit it and the picture is timed from the moment this node appeared; set it to drive the playhead yourself, or null to hand it back
trimStartnumberStarting point within the source file in seconds
trimEndnumberEnding point within the source file in seconds
speednumber1Playback-rate multiplier (affects both picture and audio)
loop'forward' | 'reverse' | 'none'Loop behaviour
durationnumberLength of one loop cycle in seconds. Defaults to the trimmed clip length

Audio

PropTypeDefaultDescription
volumenumber1Audio volume in [0, 1]
mutedbooleanfalseSilence the audio track without affecting the picture
audioFiltersAudioFilter[]Audio filters applied to the video's sound track (a single filter, an array, or an AudioFilterChain)

Layout & appearance

PropTypeDefaultDescription
cornerRadiusnumber | CornerRadiusProps0Corner radius (clips the frame)
cornerStyle'rounded' | 'angled' | CornerStyleProps'rounded'Corner shape

Playback timing

The frame shown is worked out as the node paints, from how long the node has existed — a Video added 3s into a scene opens on its first frame, not 3s in. Nothing advances it per frame, so a given frame renders the same whether you scrubbed to it, exported it, or played into it.

timestamp overrides that: set it and the node shows exactly that source time. It is the time-remap knob — tween it to scrub the clip, or pair it with playing: false to hold a single frame. Set it to null to hand the playhead back to the clock (set() merges a partial, so undefined won't clear it). A paused clip with no timestamp sits on its first frame (trimStart).

Animating

Animate standard node props (opacity, scale, cornerRadius, etc.) with .to(). For playback control, set timestamp and playing:

import { createScene, Video, createRef, easeInOut, wait } from 'motion-script';

export default createScene(function* (stage) {
  const clip = createRef<Video>();

  stage.add(
    <Video
      ref={clip}
      src="./assets/clip.mp4"
      fit="fill"
      width={960}
      height={540}
      cornerRadius={24}
      opacity={0}
    />
  );

  // Fade in
  yield* clip().to({ opacity: 1, cornerRadius: 0 }, 0.8, easeInOut);

  // Freeze on the frame 3s into the clip
  yield* wait(3);
  clip().set({ playing: false, timestamp: 3 });

  // Scrub it by hand while frozen
  yield* clip().to({ timestamp: 8 }, 2, easeInOut);

  // Hand the playhead back to the clock, which never stopped — so it resumes
  // where an unpaused clip would be
  clip().set({ playing: true, timestamp: null });
});

Trim and loop

<Video
  src="./assets/clip.mp4"
  trimStart={2.5}
  trimEnd={8.0}
  loop="forward"
  width={640}
  height={360}
/>

Speed change

<Video src="./assets/clip.mp4" speed={0.5} width={640} height={360} />

Notes

  • Video extends Rect, so children can be placed on top of the video frame (for subtitles, overlays, etc.).
  • Set muted: true to suppress audio while keeping the picture, which is useful when compositing multiple video layers.
  • playing: false freezes both picture and sound; add a timestamp to choose which frame it holds.
  • loop: 'reverse' plays the clip backward when it reaches the end.
  • See Audio Filters for the full list of audio filters.
  • See Image Filters for the full list of visual filters that can be applied to the frame.