Skip to main content
This page provides complete context for AI agents (Claude, GPT, Cursor, etc.) to help users create videos with varg. If you’re a human, you might prefer the Quickstart guide.

What is varg?

varg is a JSX-based AI video generation platform. Users write React-like code to describe video compositions, and varg handles AI generation (images, video, voice, music) and final video rendering. Everything goes through one API (api.varg.ai), one API key. For the best agent experience, install the varg skill which includes 10 reference docs, setup scripts, and auto-update:
npx -y skills add vargHQ/skills --all --copy -y

Required Environment

# .env file — only VARG_API_KEY is needed
VARG_API_KEY=varg_xxx
Get a key at app.varg.ai. This single key provides access to all AI providers (images, video, speech, music, lipsync) through the varg API.
If the user doesn’t have a key, you can drive the OTP login flow with curl. See Authentication for the agent-driven login flow.

Two Rendering Modes

You haveModeHow
Just curlCloud RenderSubmit TSX via POST https://api.varg.ai/v2/render
bun + ffmpegLocal RenderWrite TSX files, run bunx vargai render file.tsx

Minimal Working Example (Local Render)

/** @jsxImportSource vargai */
import { Render, Clip, Image, Video } from "vargai/react"
import { createVarg } from "vargai/ai"

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

const image = Image({
  model: varg.imageModel("nano-banana-pro"),
  prompt: "cute cat, big eyes, Pixar style",
  aspectRatio: "9:16",
})

export default (
  <Render width={1080} height={1920}>
    <Clip duration={5}>
      <Video
        prompt={{ text: "cat waves hello", images: [image] }}
        model={varg.videoModel("kling-v3")}
      />
    </Clip>
  </Render>
)
Render: bunx vargai render video.tsx --verbose

Minimal Working Example (Cloud Render)

# Submit — returns a job (202): {"id": "job_xxx", "status": "queued", ...}
curl -s -X POST https://api.varg.ai/v2/render \
  -H "Authorization: Bearer $VARG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"code": "const img = Image({ model: fal.imageModel(\"nano_banana_pro\"), prompt: \"cute cat\", aspectRatio: \"9:16\" });\nexport default (<Render width={1080} height={1920}><Clip duration={5}><Video prompt={{ text: \"cat waves hello\", images: [img] }} model={fal.videoModel(\"kling_v3\")} /></Clip></Render>);"}'

# Poll until status=completed, then read .output.outputs[0].url
curl -s https://api.varg.ai/v2/jobs/job_xxx \
  -H "Authorization: Bearer $VARG_API_KEY"
Cloud render uses fal.*Model() syntax — globals are auto-injected. Local render uses varg.*Model() via createVarg().

All Components

ComponentTypePurposeKey Props
<Render>JSXRoot containerwidth, height, fps
<Clip>JSXTime segmentduration, transition
Image()FunctionGenerate AI imagemodel, prompt, aspectRatio, zoom
Video()FunctionGenerate AI videomodel, prompt, duration
Speech()FunctionText-to-speechmodel, voice, children
<Music>JSXBackground musicmodel, prompt, volume, duration
<Captions>JSXSubtitlessrc, style, color, withAudio
<Title>JSXText overlayposition, color, start, end
<Subtitle>JSXSubtitle textbackgroundColor
<Overlay>JSXPositioned layerleft, top, width, height
<Split>JSXSide-by-sidedirection
<Grid>JSXGrid layoutcolumns
<Slider>JSXBefore/after revealdirection
<Swipe>JSXCard stackdirection, interval
<TalkingHead>JSXAnimated charactercharacter, voice, model
<Packshot>JSXEnd card with CTAbackground, logo, cta
Critical: Image(), Video(), Speech() are function calls that return references. <Music>, <Captions>, <Title> are JSX components. Never write <Image prompt="..." />.

All AI Models

Image Models

ModelCode (varg API)Best ForCredits
Nano Banana Provarg.imageModel("nano-banana-pro")Versatile, fast5
Nano Banana Editvarg.imageModel("nano-banana-pro/edit")Image editing5
Flux Schnellvarg.imageModel("flux-schnell")Fast generation5
Flux Provarg.imageModel("flux-pro")High quality25
Recraft V3varg.imageModel("recraft-v3")Graphic design15
Soulvarg.imageModel("soul")Character consistency15
Background Removervarg.imageModel("background-remover")Remove backgrounds5

Video Models

ModelCode (varg API)DurationBest ForCredits
Kling V3varg.videoModel("kling-v3")3-15s (int)Best quality150
Seedance 2varg.videoModel("seedance_2")4-15s or autoExcellent quality (ByteDance), exact per-second billing160 (5s@720p)
Seedance 2 Minivarg.videoModel("seedance_2_mini")4-15s (int)Budget ByteDance, cheapest tier74 (5s@720p)
Seedance 2 Less Restrictionvarg.videoModel("seedance_2_less_restriction")4-15s (int)Permissive content review, explicit opt-in116 (5s@720p)
Kling V2.6varg.videoModel("kling-v2.6")5 or 10sQuality100
Wan 2.5varg.videoModel("wan-2.5")3-10sCharacters75
Minimaxvarg.videoModel("minimax")5-10sAlternative75

Lipsync Models

ModelCode (varg API)Best ForCredits
Sync V2 Provarg.videoModel("sync-v2-pro")Lip sync100
Sync V2varg.videoModel("sync-v2")Lip sync (fast)75

Audio Models

ModelCode (varg API)Best ForCredits
Eleven V3varg.speechModel("eleven_v3")Best TTS25
Eleven Multilingual V2varg.speechModel("eleven_multilingual_v2")Multi-language20
Eleven Flash V2.5varg.speechModel("eleven_flash_v2_5")Fast TTS15
Music V1varg.musicModel()Background music25

Voices

VoiceGenderStyle
rachelFemaleCalm, warm
bellaFemaleSoft, gentle
domiFemaleConfident
elliFemaleYoung, cheerful
adamMaleDeep, warm
joshMaleYoung, energetic
samMaleRaspy
antoniMaleCalm
arnoldMaleAuthoritative

Import Statement (Local Render)

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

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

Common Patterns

Character Consistency

// Create character ONCE, reuse everywhere
const character = Image({
  model: varg.imageModel("nano-banana-pro"),
  prompt: "woman, brown hair, green eyes, professional attire",
  aspectRatio: "9:16",
})

// Same character in different scenes
<Video prompt={{ text: "character waves", images: [character] }} model={varg.videoModel("kling-v3")} />
<Video prompt={{ text: "character smiles", images: [character] }} model={varg.videoModel("kling-v3")} />

Transitions Between Clips

<Clip duration={3} transition={{ name: "fade", duration: 0.5 }}>
<Clip duration={3} transition={{ name: "crossfade", duration: 0.5 }}>
<Clip duration={3} transition={{ name: "wipeleft", duration: 0.5 }}>
<Clip duration={3} transition={{ name: "cube", duration: 0.8 }}>
<Clip duration={3} transition={{ name: "pixelize", duration: 0.5 }}>

Caption Styles

<Captions src={voiceover} style="tiktok" withAudio />    // Word-by-word highlight
<Captions src={voiceover} style="karaoke" withAudio />   // Fill left-to-right
<Captions src={voiceover} style="bounce" withAudio />    // Words bounce in
<Captions src={voiceover} style="typewriter" withAudio /> // Typing effect

Zoom Effects

<Image prompt="landscape" zoom="in" />   // Zoom in (Ken Burns)
<Image prompt="landscape" zoom="out" />  // Zoom out
<Image prompt="landscape" zoom="left" /> // Pan left
<Image prompt="landscape" zoom="right" />// Pan right

Aspect Ratios

RatioResolutionPlatform
9:161080x1920TikTok, Reels, Shorts
16:91920x1080YouTube, Twitter
1:11080x1080Instagram Feed

Template: Simple Slideshow

/** @jsxImportSource vargai */
import { Render, Clip, Image, Music } from "vargai/react"
import { createVarg } from "vargai/ai"

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

const SCENES = ["sunset over ocean", "mountain peaks at dawn", "city lights at night"]

export default (
  <Render width={1080} height={1920}>
    <Music prompt="chill ambient lofi" model={varg.musicModel()} volume={0.3} duration={12} />
    {SCENES.map((prompt, i) => (
      <Clip key={i} duration={4} transition={{ name: "fade", duration: 0.5 }}>
        <Image prompt={prompt} model={varg.imageModel("nano-banana-pro")} aspectRatio="9:16" zoom="in" />
      </Clip>
    ))}
  </Render>
)

Template: Talking Character

/** @jsxImportSource vargai */
import { Render, Clip, Image, Video, Speech, Music, Captions } from "vargai/react"
import { createVarg } from "vargai/ai"

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

const character = Image({
  model: varg.imageModel("nano-banana-pro"),
  prompt: "friendly tech influencer, casual style, ring light, 9:16",
  aspectRatio: "9:16",
})

const voiceover = Speech({
  model: varg.speechModel("eleven_v3"),
  voice: "rachel",
  children: "Hey everyone! Today I want to show you something amazing.",
})

const animated = Video({
  model: varg.videoModel("kling-v3"),
  prompt: { text: "person speaking naturally, subtle head movements", images: [character] },
  duration: 5,
})

const lipsynced = Video({
  model: varg.videoModel("sync-v2-pro"),
  prompt: { video: animated, audio: voiceover },
})

export default (
  <Render width={1080} height={1920}>
    <Music prompt="upbeat tech podcast intro" model={varg.musicModel()} volume={0.15} duration={8} />
    <Clip duration={5}>{lipsynced}</Clip>
    <Captions src={voiceover} style="tiktok" color="#ffffff" withAudio />
  </Render>
)

Template: Before/After Transformation

/** @jsxImportSource vargai */
import { Render, Clip, Image, Video, Split, Title } from "vargai/react"
import { createVarg } from "vargai/ai"

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

const CHARACTER = "woman in her 30s, brown hair"

const before = Image({
  model: varg.imageModel("nano-banana-pro"),
  prompt: `${CHARACTER}, tired expression, loose clothing`,
  aspectRatio: "9:16",
})

const after = Image({
  model: varg.imageModel("nano-banana-pro/edit"),
  prompt: { text: `${CHARACTER}, fit and confident, athletic wear, same person transformed`, images: [before] },
  aspectRatio: "9:16",
})

const beforeVid = Video({
  model: varg.videoModel("kling-v3"),
  prompt: { text: "person sighs, looks down sadly", images: [before] },
  duration: 5,
})

const afterVid = Video({
  model: varg.videoModel("kling-v3"),
  prompt: { text: "person smiles confidently, proud posture", images: [after] },
  duration: 5,
})

export default (
  <Render width={2160} height={1920}>
    <Clip duration={5}>
      <Split direction="horizontal">
        {beforeVid}
        {afterVid}
      </Split>
      <Title position="top" color="#ffffff">My 3-Month Transformation</Title>
    </Clip>
  </Render>
)

Media Processing (FFmpeg)

Cloud-hosted FFmpeg for video manipulation — no local install needed. One endpoint (POST /v2/ffmpeg), the operation is selected by the model field. All operations return a job — poll GET /v2/jobs/{id} until completed.

Probe

Inspect a video or audio file — returns metadata synchronously (not a job).
curl -s -X POST https://api.varg.ai/v2/files/probe \
  -H "Authorization: Bearer $VARG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://s3.varg.ai/files/acc_x/my-video.mp4"}'
Returns: { url, media_type, width, height, duration_ms, duration, metadata }

Trim

Cut a segment. Provide start + either end or duration. Set precise: true for frame-accurate cuts.
curl -s -X POST https://api.varg.ai/v2/ffmpeg \
  -H "Authorization: Bearer $VARG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "rendi_ffmpeg_trim", "url": "https://s3.varg.ai/files/acc_x/my-video.mp4", "start": 5, "end": 15}'

Resize

Scale to new dimensions. At least one of width/height required. Fit modes: cover (default, crop overflow), contain (letterbox), stretch.
curl -s -X POST https://api.varg.ai/v2/ffmpeg \
  -H "Authorization: Bearer $VARG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "rendi_ffmpeg_resize", "url": "https://s3.varg.ai/files/acc_x/my-video.mp4", "width": 1080, "height": 1920, "fit": "cover"}'

Slice

Split a video into segments. Modes: every (interval), at (timestamps), count (equal parts), ranges (explicit ranges).
curl -s -X POST https://api.varg.ai/v2/ffmpeg \
  -H "Authorization: Bearer $VARG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "rendi_ffmpeg_slice", "video_url": "https://s3.varg.ai/files/acc_x/my-video.mp4", "every": 15, "thumbnails": true}'

Custom FFmpeg Command

Run any FFmpeg command. Use {{in_N}}/{{out_N}} placeholders mapped through input_files/output_files.
curl -s -X POST https://api.varg.ai/v2/ffmpeg \
  -H "Authorization: Bearer $VARG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "rendi_ffmpeg",
    "command": "-i {{in_1}} -vf eq=brightness=0.1 -c:a copy {{out_1}}",
    "input_files": {"in_1": "https://s3.varg.ai/files/acc_x/my-video.mp4"},
    "output_files": {"out_1": "brightened.mp4"}
  }'
All FFmpeg operations cost ~6 credits per call. Outputs land in output.outputs[] on the completed job.

Common Errors and Solutions

ErrorCauseSolution
VARG_API_KEY not foundMissing API keyGet one at app.varg.ai or bunx vargai login
402 Insufficient BalanceNo creditsAdd credits at app.varg.ai or bunx vargai topup
Rate limit exceededToo many requestsWait, or upgrade plan
Video generation failedContent policy or bad promptSimplify prompt, check content
Duration must be integerkling-v3 needs integer secondsUse duration: 5 not duration: 4.5
kling-v2.5 only 5 or 10Duration constraintUse exactly 5 or 10 for kling-v2.5
Lipsync failedPoor quality inputUse close-up face shots, clear audio
Cache miss on re-renderProps changedKeep unchanged prompts exactly the same

CLI Commands

bunx vargai login                           # Sign in, get API key
bunx vargai balance                         # Check credit balance
bunx vargai topup                           # Add credits
bunx vargai render video.tsx --preview      # Free preview
bunx vargai render video.tsx --verbose      # Full render
bunx vargai render video.tsx --no-cache     # Skip cache

Cost Reference

1 credit = 1 cent. Cache hits are always free.
ActionModelCredits
Imagegrok_imagine_image4
Imageflux_dev / flux_pro68
Imagenano_banana_268
Imagenano_banana_pro126
Video 5ssora_2105
Video 5swan_2.5158
Video 5skling_v3221
Video 5sseedance_2_mini (cheapest Seedance tier)74
Video 5sseedance_2 via piapi:seedance-2 (advanced route pin)105
Video 5sseedance_2 (canonical, fal route, 720p)160
Video 5sseedance_2 with duration: "auto" (reserves worst case)479
Speecheleven_turbo_v2_5105
Musicmusic_v179
Lipsyncsync_v253
Lipsyncsync_v2_pro84
FFmpeg (any op)rendi_ffmpeg*6
Typical 3-clip video: $2-5. Discover models and routes (no auth): GET https://api.varg.ai/v2/models (filter with ?tool=video). Live price catalog (no auth): GET https://api.varg.ai/v2/pricing. Price any request without running it: POST https://api.varg.ai/v2/estimate — the response includes resolved_model_key, the exact route the request would run on.

File Structure

project/
├── .env              # VARG_API_KEY=varg_xxx
├── package.json
├── output/           # Generated videos
├── .cache/ai/        # Cached AI generations
└── videos/
    └── my-video.tsx  # Video composition

Tips for Best Results

  1. One API key: Use VARG_API_KEY with createVarg() — no need for individual provider keys
  2. Character consistency: Use soul for characters, or generate once with nano-banana-pro and reference in all scenes
  3. Video quality: kling-v3 for best quality, wan-2.5 for characters
  4. Lipsync: Works best with frontal face, clear audio, 5-10 second clips
  5. Caching: Same props = instant $0. Even slightly different prompt = full regeneration
  6. Music volume: Keep at 0.1-0.3 for background, voices at 1.0
  7. Duration: kling-v3 needs integer 3-15s. kling-v2.5 needs exactly 5 or 10. seedance_2 accepts integer 4-15 (fal routes also accept “auto”).