Video generation
A clip rendering frame by frame, then playable with a scrubber once it is ready.
Loading preview…
Install
- 1
Run this command in your Tailwind CSS project. It adds
components/ai/video-generation.tsxand installs its dependencies.$ npx shadcn@latest add https://gradientdeck.com/ai-components/r/video-generation.json
Usage & API
Example
import { VideoGeneration } from "@/components/ai/video-generation"
<VideoGeneration
prompt="…"
rendered={1}
time={1}
onTimeChange={() => {}}
playing={true}
onPlayingChange={() => {}}
/>Props VideoGeneration
| Prop | Type & description | Required |
|---|---|---|
prompt | string | Required |
frames | numberNumber of frames shown in the strip. | Optional |
rendered | numberHow many frames have rendered so far. Equal to `frames` when the clip is ready. | Required |
time | numberPlayback position, 0–1 | Required |
onTimeChange | (time: number) => void | Required |
playing | boolean | Required |
onPlayingChange | (playing: boolean) => void | Required |
duration | numberClip length in seconds | Optional |
seed | number | Optional |
Dependencies
- React
- Tailwind CSS
- motion
- lucide-react
Implementation notes
Frame strip is the only variant. The preview area is an image role. While rendering, its label is the frame count. When ready, the label is Generated clip plus the prompt. The overlay play control is separate from the transport play control. Both restart from the beginning if time is already at 1, then set playing. The seek track ignores pointers until ready, and its accessible value is the clock time. The frame buttons say Jump to frame N and do nothing until the clip is ready, when they set time from the frame index. The header always shows the duration you passed and the literal 24 fps. The demo uses eight frames and six seconds, starts with none of them ready, and fills the strip before it will play. There is no mute, no speed control, and no fullscreen button.
Choosing a layout
Use it when a clip is the result and the wait should show frames accumulating instead of a single percent on a still. The strip makes a partial render look like a film, and the same strip becomes the scrubber once the job finishes, so you do not swap components at the end. Eight frames in a 21:9 card fit a short shot. If your job has a different frame count, pass frames and keep rendered in range. The scene art is a stand-in. A production player would put real frame images in that grid, but this file draws Scene for every cell from the seed and the frame index.
Use the Audio player when the result is a waveform and a voice or music clip rather than pictures over time. Image generation is the still-image wait, with blur, noise, scan, or a grid, and it never grows a transport. This card has no download button and no regenerate button. If those actions matter during the render, they are not here. It is also the wrong player for an arbitrary uploaded video with chapters, captions, or a volume control. None of those controls exist on the row.
When do play and seek turn on?
When rendered is greater than or equal to frames. Before that, the transport button is disabled, the seek slider is aria-disabled and not tabbable, frame buttons are disabled, and the preview shows the rendering line instead of a play icon. Passing a lower rendered count returns the card to that waiting state.
Is the clip a real video element?
No. The preview and every thumbnail draw an SVG scene whose composition shifts with time. Playing is a boolean you toggle, and the demo advances time with requestAnimationFrame. There is no src, no captions track, and no volume. Duration only formats the clock and the header.