Skip to content
MediaVideo generationMenu

Video generation

A video job in a conversation: queue position, progress with the time left, a poster frame revealed as it renders, then a compact player with the clip's length and resolution.

A clip waits in the queue, renders with time left, then plays. The video is recorded in your browser.

The demo clip is drawn on a canvas and recorded in your browser while the job renders, so the page ships no video file.

Installation

$ pnpm dlx shadcn@latest add https://chatcn.dev/r/video-generation.json

Usage

tsx
import { VideoGeneration } from "@/components/ui/chatcn/video-generation"

<VideoGeneration
  prompt={job.prompt}
  status={job.status}
  queuePosition={job.queuePosition}
  progress={job.progress}
  posterSrc={job.posterUrl}
  src={job.videoUrl}
  duration={6}
  resolution="1080p"
  fps={24}
  audio={false}
  onCancel={cancel}
/>

Pass etaMs when the provider gives one. Otherwise the time left is measured from how fast progress moves: it waits for enough signal, smooths the rate, and counts down between updates. While queued, etaMs reads as the expected wait. VideoPlayer is exported on its own for clips that are not generated.

Examples

Every state

Queued with an expected wait, generating with a poster, done, failed and content blocked.

Props

VideoGeneration

PropTypeNotes
promptstringShown with a copy button
status"queued" | "generating" | "done" | "failed" | "blocked"The player appears when done and src is set
progressnumber0 to 100
queuePositionnumber1 means next
etaMsnumberTime left, or the expected wait while queued
posterSrcstringRevealed while rendering, then the player's poster
srcstringThe finished clip
durationnumberSeconds. Also the fallback for files without one
resolutionstring | { width, height }"1080p" or a size
fps, audionumber, booleanShown in the summary line
aspectRatio"W:H" | numberDefaults to "16:9"
settingsReactNode[]Extra facts, such as the model
actionsReactNodeShown when done, for example Extend or Remix
onRetry, onCancel, onEditPrompt, onDownload() => void
autoPlay, loopbooleanPassed to the player

VideoPlayer

PropTypeNotes
src, posterstring
titlestringNames the player for screen readers
durationnumberUsed until the file reports its own
aspectRationumberDefault 16 / 9
autoPlay, loop, defaultMutedboolean

Keyboard

KeyAction
Space, KPlay or pause
← →Seek 5 s. Mirrored in RTL. On the scrubber, arrows step it
MMute or unmute
FFull screen

Accessibility

  • While rendering, the status line is a progressbar whose value text includes the time left.
  • The scrubber is a native range input with spoken times, for example 2 seconds of 6 seconds.
  • Controls stay visible while paused or focused, and every icon button has a label.
  • Status changes are announced once in a polite live region.

Motion

  • The poster frame uses the same scan reveal as image generation, so a still and a clip feel like one family.
  • The control bar fades in 150 ms and hides 2 s after the pointer stops while playing. Keyboard focus shows it instantly.
  • Play and pause swap with a 150 ms blur crossfade. The scrubber follows the playhead every frame, not four times a second.