Skip to main content

Import

/** @jsxImportSource vargai */
import { 
  Render, Clip, 
  Image, Video, Speech, Music,
  Title, Subtitle, Captions,
  Overlay, Split, Slider, Swipe, Grid,
  TalkingHead, Packshot
} from "vargai/react"
import { createVarg } from "vargai/ai"

const varg = createVarg({ apiKey: process.env.VARG_API_KEY! })

Quick Reference

ComponentPurposeKey Props
<Render>Root containerwidth, height, fps
<Clip>Time segmentduration, transition
<Image>AI or static imageprompt, src, zoom
<Video>AI or source videoprompt, src, volume
<Speech>Text-to-speechvoice, children
<Music>Background musicprompt, volume, loop
<Title>Text overlayposition, color
<Captions>Auto-generated subssrc, style
<Overlay>Positioned layerleft, top, width, height
<Split>Side-by-sidedirection

Container Components

Render

Root container for video composition. Required for all videos.
<Render width={1080} height={1920} fps={30}>
  {/* clips and media */}
</Render>
PropTypeDefaultDescription
widthnumber1080Video width in pixels
heightnumber1920Video height in pixels
fpsnumber30Frames per second
Common resolutions:
PlatformResolutionAspect Ratio
TikTok/Reels/Shorts1080x19209:16
YouTube1920x108016:9
Instagram Feed1080x10801:1

Clip

Time segment container. Clips play sequentially.
<Clip duration={3} transition={{ name: "fade", duration: 0.5 }}>
  <Video src="scene.mp4" />
</Clip>
PropTypeDefaultDescription
durationnumberRequiredDuration in seconds
transitionobjectundefinedTransition to next clip
cutFromnumber0Start time offset
cutTonumberundefinedEnd time offset
Transition options:
transition={{ name: "fade", duration: 0.5 }}
transition={{ name: "crossfade", duration: 0.5 }}
transition={{ name: "wipeleft", duration: 0.5 }}
transition={{ name: "wiperight", duration: 0.5 }}
transition={{ name: "slideup", duration: 0.5 }}
transition={{ name: "slidedown", duration: 0.5 }}
transition={{ name: "cube", duration: 0.8 }}
transition={{ name: "pixelize", duration: 0.5 }}
67 GL-transitions available.

Media Components

Image

AI-generated or static image.
// AI generation
const cat = Image({
  prompt: "cute orange cat, Pixar style",
  model: varg.imageModel("nano-banana-pro"),
  aspectRatio: "9:16",
})

// In composition with zoom
<Clip duration={3}>
  <Image src={cat} zoom="in" />
</Clip>

// Static image
<Clip duration={3}>
  <Image src="media/photo.jpg" zoom="out" />
</Clip>
Element function props:
PropTypeDefaultDescription
promptstringRequiredImage description
modelImageModelvarg.imageModel("nano-banana-pro")AI model
aspectRatiostring"1:1"Output ratio
Component props:
PropTypeDefaultDescription
srcstring or ImageRefRequiredImage source or reference
zoom"in" "out" "left" "right"undefinedKen Burns effect
resize"cover" or "contain""cover"Resize mode

Video

AI-generated or source video.
// Image-to-video
const character = Image({ prompt: "robot character" })

<Clip duration={5}>
  <Video
    prompt={{ text: "robot waves hello", images: [character] }}
    model={varg.videoModel("kling-v3")}
  />
</Clip>

// Text-to-video
<Clip duration={5}>
  <Video
    prompt="ocean waves crashing on beach"
    model={varg.videoModel("kling-v3")}
  />
</Clip>

// Source video
<Clip duration={5}>
  <Video src="media/clip.mp4" volume={0.5} />
</Clip>

// Lipsync (video + audio)
const animatedVideo = Video({ prompt: { ... } });
const voiceover = Speech({ ... });

<Video
  prompt={{ video: animatedVideo, audio: voiceover }}
  model={varg.videoModel("sync-v2-pro")}
/>
PropTypeDefaultDescription
promptstring or object-Generation prompt
srcstring-Source video path
modelVideoModelvarg.videoModel("kling-v3")AI model
volumenumber1Audio volume (0-1)
cutFromnumber0Start trim
cutTonumber-End trim
Prompt formats:
// Text only
prompt="waves on beach"

// Image-to-video
prompt={{ text: "waves crash", images: [imageRef] }}

// Lipsync
prompt={{ video: videoRef, audio: speechRef }}

Speech

Text-to-speech voiceover.
const voiceover = Speech({
  model: varg.speechModel("eleven_v3"),
  voice: "rachel",
  children: "Hello everyone! Welcome to my video.",
})

// Use in composition
<Captions src={voiceover} style="tiktok" />
PropTypeDefaultDescription
childrenstringRequiredText to speak
modelSpeechModelvarg.speechModel("eleven_v3")TTS model
voicestring"rachel"Voice name or ID
volumenumber1Audio volume
Available voices: rachel, adam, bella, josh, sam, antoni, elli, arnold, domi

Music

Background music generation.
<Render>
  <Music 
    prompt="upbeat electronic pop, energetic" 
    model={varg.musicModel()} 
    volume={0.2}
    loop
  />
  
  <Clip duration={5}>...</Clip>
  <Clip duration={5}>...</Clip>
</Render>
PropTypeDefaultDescription
promptstring-Music description
srcstring-Source audio file
modelMusicModelvarg.musicModel()Generation model
volumenumber1Audio volume (0.1-0.3 for background)
loopbooleanfalseLoop audio
duckingnumberundefinedLower volume during speech

Text Components

Title

Text overlay on video.
<Clip duration={5}>
  <Video src="scene.mp4" />
  <Title position="top" color="#ffffff">My Video Title</Title>
</Clip>
PropTypeDefaultDescription
childrenstringRequiredTitle text
position"top" "center" "bottom""center"Position
colorstring"#ffffff"Text color
startnumber0Start time
endnumber-End time

Captions

Auto-generated subtitles from speech.
const voiceover = Speech({ children: "Hello everyone!" });

<Render>
  <Clip duration={5}>
    <Video src="talking.mp4" />
  </Clip>
  <Captions src={voiceover} style="tiktok" color="#ffffff" />
</Render>
PropTypeDefaultDescription
srcSpeechRefRequiredSpeech reference for timing
srtstring-Custom SRT file
stylestring"tiktok"Caption animation style
colorstring"#ffffff"Text color
activeColorstring-Active word color
Caption styles:
StyleDescription
tiktokWord-by-word highlight
karaokeFill left-to-right
bounceWords bounce in
typewriterTyping effect

Layout Components

Overlay

Positioned layer on top of content.
<Clip duration={5}>
  <Video src="background.mp4" />
  <Overlay left={50} top={100} width={200} height={200}>
    <Image src="logo.png" />
  </Overlay>
</Clip>
PropTypeDefaultDescription
leftnumber0X position
topnumber0Y position
widthnumber-Width
heightnumber-Height
keepAudiobooleantrueKeep overlay audio

Split

Side-by-side layout.
<Clip duration={5}>
  <Split direction="horizontal">
    <Video src="left.mp4" />
    <Video src="right.mp4" />
  </Split>
</Clip>
PropTypeDefaultDescription
direction"horizontal" or "vertical""horizontal"Split direction

SplitLayout

Before/after comparison layout.
<Clip duration={5}>
  <SplitLayout 
    direction="horizontal" 
    left={beforeVideo} 
    right={afterVideo} 
  />
</Clip>

Grid

Grid layout for multiple items.
<Clip duration={5}>
  <Grid columns={2}>
    <Video src="1.mp4" />
    <Video src="2.mp4" />
    <Video src="3.mp4" />
    <Video src="4.mp4" />
  </Grid>
</Clip>
PropTypeDefaultDescription
columnsnumber2Number of columns

Slider

Before/after reveal slider.
<Clip duration={5}>
  <Slider direction="horizontal">
    <Image src="before.jpg" />
    <Image src="after.jpg" />
  </Slider>
</Clip>

Swipe

Tinder-style card swipe.
<Clip duration={10}>
  <Swipe direction="horizontal" interval={2}>
    <Image src="card1.jpg" />
    <Image src="card2.jpg" />
    <Image src="card3.jpg" />
  </Swipe>
</Clip>
PropTypeDefaultDescription
direction"horizontal" or "vertical""horizontal"Swipe direction
intervalnumber2Seconds per card

Special Components

TalkingHead

Complete talking character with automatic lipsync.
const character = Image({ prompt: "friendly presenter" });

<Clip duration={10}>
  <TalkingHead
    character={character}
    voice="rachel"
    model={varg.videoModel("kling-v3")}
    lipsyncModel={varg.videoModel("sync-v2-pro")}
  >
    Hello everyone! Welcome to my channel.
  </TalkingHead>
</Clip>
PropTypeDefaultDescription
characterImageRefRequiredCharacter image
childrenstringRequiredScript text
voicestring"rachel"Voice name
modelVideoModel-Animation model
lipsyncModelVideoModel-Lipsync model

Packshot

End card with call-to-action.
<Clip duration={3}>
  <Packshot
    background="#000000"
    logo="media/logo.png"
    cta="Subscribe Now!"
    blinkCta
  />
</Clip>
PropTypeDefaultDescription
backgroundstring"#000000"Background color
logostring-Logo image path
ctastring-Call-to-action text
blinkCtabooleanfalseAnimate CTA

FFmpeg processing

Slice

Split a video into segments with automatic first-frame extraction. Returns an array of segments, each with a video URL, full-resolution first frame (JPEG), and 480px thumbnail (WebP).
import { Slice } from "vargai/react";
import { createVarg } from "@vargai/gateway";

const varg = createVarg({ apiKey: process.env.VARG_API_KEY! });

// Split every 15 seconds
const { segments } = await Slice({ src: "https://example.com/video.mp4", every: 15 });

for (const seg of segments) {
  console.log(seg.url);         // segment video URL
  console.log(seg.first_frame); // full-res JPEG of first frame
  console.log(seg.thumbnail);   // 480px WebP thumbnail
  console.log(seg.start, seg.end, seg.duration);
}
Four split modes are available:
// Split every N seconds
await Slice({ src: video, every: 10 });

// Split at specific timestamps
await Slice({ src: video, at: [5, 15, 30] });

// Split into N equal parts
await Slice({ src: video, count: 4 });

// Split at explicit ranges
await Slice({ src: video, ranges: [{ start: 0, end: 10 }, { start: 20, end: 30 }] });
Element function props
PropTypeDefaultDescription
srcstring | File | VargElement-Source video (URL, File, or element)
codec"copy" | "reencode""copy"copy for fast keyframe-aligned cuts, reencode for frame-accurate
everynumber-Split every N seconds
atnumber[]-Split at specific timestamps
countnumber-Split into N equal parts
rangesArray<{start, end}>-Explicit time ranges
Exactly one of every, at, count, or ranges must be provided. Segment properties Each segment in the returned array has:
PropertyTypeDescription
urlstringCDN URL of the segment video
fileFileFile object for the segment
durationnumberSegment duration in seconds
indexnumber0-based segment index
startnumberStart time in the source video (seconds)
endnumberEnd time in the source video (seconds)
first_framestringFull-resolution first frame (JPEG)
thumbnailstring480px-wide thumbnail (WebP)