Video gen
Battle-tested skills for AI agents that do real work
npx -y skills add buildoak/fieldwork-skills --skill video-genAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 15 stars15 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Video generation via fal.ai -- from quick one-off clips to multi-scene productions with keyframes, state tracking, and assembly. 10+ models including Kling 3.0, Veo 3.1, Sora 2, LTX-2.3. Two modes: light (fire-and-forget) and project (structured pipeline with gates).
SKILL.md
22.9 KB, as published. Nobody here has run it
video-gen
Video generation and multi-scene production via fal.ai. Two modes: light (fire-and-forget) and project (interactive pipeline with gates).
Scripts: ./scripts/generate.py, ./scripts/preview.py, ./scripts/project_init.py, ./scripts/project_state.py, ./scripts/decompose.py, ./scripts/keyframe.py, ./scripts/clip.py, ./scripts/assemble.py, ./scripts/character_sheet.py
Output dir: ./output/
Setup
export FAL_KEY="your-fal-ai-key"
- Claude Code: copy this skill folder into
.claude/skills/video-gen/ - Codex CLI: append this SKILL.md content to your project's root
AGENTS.md
For the full installation walkthrough (prerequisites, API keys, verification, troubleshooting), see references/installation-guide.md.
Credential management
Three tiers for managing the FAL_KEY environment variable:
- Vault skill (recommended): If you have a vault or secret-management skill, store the key there and export it before running scripts. Example:
export FAL_KEY=$(vault get FAL_KEY) - Custom secret manager: Use your team's preferred secret manager (1Password CLI, AWS Secrets Manager, etc.)
- Plain export:
export FAL_KEY='your-fal-ai-key'in your shell profile
For project mode (keyframes + character sheets): also need image-gen peer skill.
Staying Updated
This skill ships with an UPDATES.md changelog and UPDATE-GUIDE.md for your AI agent.
After installing, tell your agent: "Check UPDATES.md in the video-gen skill for any new features or changes."
When updating, tell your agent: "Read UPDATE-GUIDE.md and apply the latest changes from UPDATES.md."
Follow UPDATE-GUIDE.md so customized local files are diffed before any overwrite.
Decision Tree
Need video?
├── Quick one-off clip? ─────────── Light Mode (generate.py)
│ Single prompt, single output, no state
│
└── Multi-scene story/production? ── Project Mode
├── New project? ─────────────── project_init.py → G0
├── Existing project? ────────── project_state.py --status
└── Resume at gate? ──────────── Check state, pick up where left off
Quick Reference
Light Mode
# Generate with default model (ltx-2.3)
python ./scripts/generate.py \
--prompt "A red fox running through snow" \
--output ./output/
# Generate with specific model and settings
python ./scripts/generate.py \
--prompt "Tokyo skyline at sunset with dramatic clouds" \
--model kling-v3 \
--mode t2v \
--duration 10 \
--resolution 1080p \
--aspect 16:9
# Image-to-video generation
python ./scripts/generate.py \
--prompt "The character starts walking forward" \
--mode i2v \
--image ./path/to/keyframe.png \
--model veo-3
# Quick preview (uses LTX fast, cheapest)
python ./scripts/preview.py \
--prompt "Test scene" \
--mode t2v
Project Mode
# Initialize new project
python ./scripts/project_init.py \
--name noir-detective \
--scenes 5 \
--output-dir ./projects \
--style "cinematic, moody, film noir" \
--tier standard \
--logline "A detective investigates in a cyberpunk city"
# Check project status
python ./scripts/project_state.py --project ./projects/noir-detective
# Generate keyframe for scene
python ./scripts/keyframe.py \
--project ./projects/noir-detective \
--scene 1 \
--style-keywords "cinematic, moody"
# Generate video clip for scene
python ./scripts/clip.py \
--project ./projects/noir-detective \
--scene 1 \
--model kling-v3 \
--duration 8
# Assemble final video
python ./scripts/assemble.py \
--clips-dir ./projects/noir-detective/scenes \
--output ./projects/noir-detective/output/final.mp4
Light Mode
Model Selection
What do you need?
├── Fast drafts + budget? ──────────── ltx-2.3 (fast) $0.04/s
├── Cinematic quality? ─────────────── kling-v3 $0.168/s
├── Dialogue/lip sync? ─────────────── veo-3 $0.20-0.40/s
├── Long clips (>10s)? ─────────────── sora-2 (up to 25s)
├── Budget with audio? ─────────────── wan $0.05-0.10/s
├── Anime/stylized? ────────────────── hailuo $0.045-0.08/s
└── Physics accuracy? ──────────────── cosmos $0.20/video
| Use Case | Model | Cost/5s | Why |
|---|---|---|---|
| Fast drafts | ltx-2.3 | $0.20 | Open source, 4K capable, fastest iteration |
| Cinematic | kling-v3 | $0.84 | Multi-shot narratives, character consistency |
| Dialogue/lip sync | veo-3 | $2.00 | Best-in-class audio sync, natural performances |
| Long clips | sora-2 | $2.50 | Up to 25s duration, complex scenes |
| Budget with audio | wan | $0.50 | Cheapest audio option, social media |
| Anime/stylized | hailuo | $0.40 | Anime support, micro-expressions |
| Physics | cosmos | $0.20 | RL-trained on physics, simulation-accurate |
Script Reference: generate.py
| Flag | Default | Description |
|---|---|---|
--model | ltx-2.3 | Model alias: ltx-2.3, kling-v3, veo-3, sora-2, wan, hailuo, cosmos, pixverse, grok |
--mode | t2v | t2v (text-to-video) or i2v (image-to-video) |
--prompt | required | Video description |
--image | none | Source image path or URL (required for i2v) |
--duration | 8 | Duration in seconds |
--resolution | 1080p | 720p, 1080p, 1440p, 4k |
--aspect | 16:9 | 16:9, 9:16, 1:1 |
--fps | 24 | Frames per second |
--seed | none | Reproducibility seed |
--output | ./output/ | Output directory or file path |
--no-preview | false | Skip macOS QuickLook preview |
--no-audio | false | Disable audio generation |
--quality | standard | fast, standard, pro |
--dry-run | false | Cost estimate only, no API call |
--timeout | 300 | Queue timeout in seconds |
--negative-prompt | none | What to exclude from generation |
--json | false | Output JSON only (suppress stderr logs) |
Script Reference: preview.py
# Preview existing video file
python ./scripts/preview.py /path/to/video.mp4
# Generate and preview (uses LTX fast, $0.04/s)
python ./scripts/preview.py \
--prompt "Quick test scene" \
--mode t2v \
[--image path] \
[--output path]
Output JSON Contract
{
"success": true,
"file": "/abs/path/to/20260308-143052-t2v-red-fox-snow.mp4",
"model": "ltx-2.3",
"mode": "t2v",
"duration_sec": 8,
"resolution": "1080p",
"cost_usd": 0.32,
"seed": 42,
"fal_request_id": "abc123"
}
Duration Constraints
| Model | Valid Durations | Notes |
|---|---|---|
| LTX-2.3 | 2, 4, 6, 8, 10s | Fixed increments only |
| Kling V3/2.6 | 5, 10s | Two options only |
| Veo 3.1 | 5-8s | Any value in range |
| Sora 2 | 5-20s (std), 5-25s (pro) | Any value in range |
| Hailuo | 4-6s | Any value in range |
| Wan | 3-5s | Any value in range |
| Cosmos | 5-9s | Any value in range |
Cost Quick Reference
| Model | Video Only | With Audio | 4K Available |
|---|---|---|---|
ltx-2.3 (fast) | $0.04/s | $0.04/s | Yes ($0.16/s) |
ltx-2.3 (std) | $0.06/s | $0.06/s | Yes ($0.24/s) |
wan | $0.05/s | $0.10/s | No |
hailuo | $0.045/s | N/A | No |
kling-v3 | $0.168/s | $0.336/s | No |
veo-3 (fast) | $0.10/s | $0.15/s | No |
veo-3 (std) | $0.20/s | $0.40/s | No |
sora-2 (720p) | $0.30/s | included | No |
sora-2 (1080p) | $0.50/s | included | No |
Project Mode
Gate Pipeline (G0-G5)
| Gate | Stage | What | Scripts | JSON Output |
|---|---|---|---|---|
| G0 | Project Setup | Initialize project structure, manifest, state | project_init.py | project_dir, manifest, state paths |
| G1 | Shot Prompts | Story decomposition into scene prompts | decompose.py | LLM prompt for story breakdown |
| G2 | Reference Images | Generate keyframe images per scene | keyframe.py | keyframe image paths, costs |
| G3 | Sequence Review | Review and lock shot sequence | project_state.py --lock-sequence | sequence lock confirmation |
| G4 | Video Generation | Generate video clips per scene | clip.py | video clip paths, costs |
| G5 | Assembly | Combine clips into final video | assemble.py | final video path, metadata |
Detailed Gate Instructions
G0 - Project Setup: Use project_init.py to create project folder with scenes/, characters/, audio/, output/ subdirectories, manifest.md template, and state.json tracking file. Define style, tier, budget, aspect ratio.
G1 - Shot Prompts: Use decompose.py to generate LLM prompt for story decomposition. Coordinator runs this against LLM to get scene-by-scene breakdown. Update state.json with scene prompts.
G2 - Reference Images: Run keyframe.py for each scene to generate keyframe images. These anchor the visual style and serve as I2V inputs. Requires image-gen peer skill.
G3 - Sequence Review: Use project_state.py --lock-sequence to freeze the shot sequence. No more scene additions/deletions after this gate. Review keyframes before locking.
G4 - Video Generation: Run clip.py for each scene to generate video clips using keyframes as I2V input. Outputs shot_NN.mp4 files in scenes/NN-name/ directories.
G5 - Assembly: Use assemble.py to discover clips and combine them with ffmpeg. Supports crossfades, audio overlay, and story.json metadata for timing.
Script Reference: project_init.py
| Flag | Default | Description |
|---|---|---|
--name | required | Project name (kebab-case) |
--scenes | required | Number of scenes (int >= 1) |
--output-dir | required | Parent directory for project |
--aspect | 16:9 | 16:9, 9:16, 1:1 |
--style | cinematic | Style keywords (comma-separated) |
--tier | standard | budget, standard, premium, ultra |
--logline | none | One-line story description |
--budget | 50.0 | Max spend in USD |
Script Reference: project_state.py
# Display status table
python ./scripts/project_state.py --project /path/to/project
# Update gate status
python ./scripts/project_state.py \
--project /path \
--scene 1 \
--gate prompt \
--status locked \
--path scenes/01-intro/prompt.md
# Add new scene
python ./scripts/project_state.py \
--project /path \
--add-scene \
--scene-name climax \
--scene-number 6
# Lock sequence (G3)
python ./scripts/project_state.py --project /path --lock-sequence
# Invalidate downstream gates
python ./scripts/project_state.py \
--project /path \
--scene 1 \
--invalidate prompt
Script Reference: decompose.py
| Flag | Default | Description |
|---|---|---|
--idea | required | Story concept description |
--style | required | Visual style keywords |
--aspect-ratio | 16:9 | Video aspect ratio |
--duration | 30 | Total target duration (seconds) |
--tier | standard | Generation tier |
--output | none | Save LLM prompt to file |
Script Reference: keyframe.py
| Flag | Default | Description |
|---|---|---|
--project | required | Project directory path |
--scene | required | Scene number |
--style-keywords | none | Override style keywords |
--model | from tier | Image generation model |
--no-state-update | false | Don't update state.json |
Script Reference: clip.py
| Flag | Default | Description |
|---|---|---|
--project | required | Project directory path |
--scene | required | Scene number |
--model | from tier | Video generation model |
--duration | 6 | Clip duration in seconds |
--quality | standard | fast, standard, pro |
--bridge | false | Use temporal bridging |
--seed | none | Reproducibility seed |
--no-state-update | false | Don't update state.json |
Script Reference: assemble.py
| Flag | Default | Description |
|---|---|---|
--clips-dir | required | Directory containing scene clips |
--output | required | Output video file path |
--story | none | story.json for timing metadata |
--audio | none | Voiceover track path |
--music | none | Background music path |
--crossfade | 0.5 | Crossfade duration between clips |
Script Reference: character_sheet.py
| Flag | Default | Description |
|---|---|---|
--character-json | required | Characters definition file |
--character-id | required | Character ID from JSON |
--output-dir | required | Output directory for images |
--views | front,profile,three_quarter | Comma-separated view list |
--tier | standard | Image generation tier |
File Structure
project-name/
├── manifest.md # Human-readable project summary
├── state.json # Machine state tracking (G0-G5)
├── story.json # Scene decomposition (G1 output)
├── characters.json # Character definitions
├── scenes/
│ ├── 01-intro/
│ │ ├── prompt.md # Scene description
│ │ ├── keyframe.png # Reference image (G2)
│ │ └── shot_01.mp4 # Generated clip (G4)
│ ├── 02-conflict/
│ │ ├── prompt.md
│ │ ├── keyframe.png
│ │ └── shot_02.mp4
│ └── ...
├── characters/ # Character reference sheets
│ ├── detective-front.png
│ ├── detective-profile.png
│ └── ...
├── audio/ # Voiceover and music
└── output/ # Final assembled videos
└── final.mp4
Token Efficiency Rules
- Coordinator context management: Load only current gate's requirements, not full project history
- Scene isolation: Each scene script operates independently with minimal cross-references
- State checkpoints: Use
state.jsonas single source of truth, not file system scanning - Selective loading: Scripts load only required JSON sections, not entire project state
Going Back / Cascade Rules
- Upstream change: Invalidates all downstream gates automatically
- Prompt change (G1): Invalidates G2 (keyframes), G4 (clips), G5 (assembly)
- Keyframe change (G2): Invalidates G4 (clips), G5 (assembly)
- Sequence lock (G3): Prevents scene additions/deletions, allows content changes
- Clip regeneration (G4): Invalidates G5 (assembly) only
Style Control (3 Layers)
- Project tier: Maps to default models (budget→ltx-2.3, standard→kling-v3, premium→kling-v3, ultra→veo-3)
- Project style keywords: Applied to all keyframes and clips automatically
- Per-scene overrides:
--style-keywordsflag on keyframe.py/clip.py for scene-specific variations
Dependencies
Required for Light Mode
- Python 3.10+
requestslibrary:pip install requests- fal.ai API key (
FAL_KEYenvironment variable)
Required for Project Mode (additional)
ffmpeg+ffprobe(video assembly): install via system package managerimage-genpeer skill (keyframes + character sheets)
Image-gen Peer Resolution
Scripts resolve image generation dependency in this order:
- Environment override:
IMAGE_GEN_SCRIPT=/path/to/generate.py(explicit path) - Auto-discovery:
../image-gen/scripts/generate.py(peer skill in fieldwork layout) - Actionable error: "Image generation requires the image-gen skill. Install it as a peer skill or set IMAGE_GEN_SCRIPT env var."
Anti-Patterns
| Anti-pattern | Why it fails | Do this instead |
|---|---|---|
Using produce.py when interactive mode is appropriate | Skips human review gates, produces lower quality | Use project mode (G0-G5 pipeline) for quality work |
| Skipping style checkpoint on first keyframe | Inconsistent visual style across scenes | Review and approve keyframe style before generating remaining scenes |
| Generating video before locking prompts and images | Wasted generation costs on changing requirements | Complete G1-G3 (prompts, keyframes, sequence lock) before G4 |
| Hardcoding model without considering budget | Cost overruns, especially with Sora/Veo | Use --dry-run first, choose model based on budget and use case |
| Generating clips out of order | Breaks temporal bridging between scenes | Generate clips sequentially: scene 1, 2, 3... |
| Loading full prompts into coordinator context | Token waste, context overflow | Load only current gate requirements, use state.json for coordination |
Using --duration 4 with LTX | API validation error (LTX minimum is 6s) | Use --duration 6 or higher for LTX model |
Forgetting --image flag for i2v mode | Generation fails with validation error | Always provide --image path/URL for image-to-video |
| Using Kling for 15s clips | Model constraint violation (max 10s) | Use Sora 2 for clips longer than 10s |
Skipping --lock-sequence before G4 | Scene changes invalidate expensive video generation | Lock sequence at G3 before generating any videos |
Error Handling
| Error | Cause | Fix |
|---|---|---|
| FAL_KEY not set | Missing API credential | export FAL_KEY='your-fal-ai-key' |
| Image-gen not found | Missing peer skill dependency | Install image-gen skill or set IMAGE_GEN_SCRIPT env var |
| ffmpeg not found | Missing video assembly dependency | Install ffmpeg: brew install ffmpeg (macOS) or apt install ffmpeg (Linux) |
| Duration validation failure | Invalid duration for model | Check duration constraints table, use valid values |
| HTTP 429: Rate limit | Too many requests | Wait 30s and retry, or switch to different model |
| HTTP 402: No credits | fal.ai account balance | Top up fal.ai account balance |
| API timeout | Model overloaded or network issue | Increase --timeout or try --quality fast variant |
| No video URL in result | Malformed API response | Check fal.ai status, try different model |
| Downloaded file is empty | Network interruption during download | Retry generation, check network stability |
| Model not available | Model endpoint changed or deprecated | Check references/models.md for current endpoints |
| Invalid aspect ratio | Unsupported ratio for model | Use 16:9, 9:16, or 1:1 (universally supported) |
| Project directory exists | Name collision | Choose different --name or remove existing directory |
| Sequence already locked | Trying to add scenes after G3 | Use project_state.py --unlock-sequence or work with existing scenes |
| Clip discovery failed | Assembly can't find generated clips | Check clip naming pattern shot_NN.mp4 in scenes/*/ directories |
Bundled Resources Index
| Path | What | When to Load |
|---|---|---|
./scripts/generate.py | Core video generation script | Every light mode generation task |
./scripts/preview.py | Quick preview wrapper (LTX fast) | Quick tests and iteration |
./scripts/project_init.py | Project structure initialization | Starting new multi-scene project (G0) |
./scripts/project_state.py | State management and status display | Managing project gates, checking progress |
./scripts/decompose.py | Story decomposition LLM prompt | Breaking story into scenes (G1) |
./scripts/keyframe.py | Keyframe image generation | Creating visual references (G2) |
./scripts/clip.py | Scene video generation | Generating video clips (G4) |
./scripts/assemble.py | Final video assembly via ffmpeg | Combining clips into final video (G5) |
./scripts/character_sheet.py | Multi-view character reference sheets | Character consistency across scenes |
./references/models.md | Complete model catalog with capabilities and pricing | Model selection and optimization |
./references/model-kling.md | Kling 3.0 detailed reference card | Kling-specific generation parameters |
./references/model-veo.md | Veo 3.1 detailed reference card | Veo-specific features and audio capabilities |
./references/model-sora.md | Sora 2 detailed reference card | Sora-specific parameters and remix features |
./references/model-ltx.md | LTX-2.3 detailed reference card | LTX-specific modes and 4K capabilities |
./references/model-wan.md | Wan 2.5/2.6 detailed reference card | Wan-specific features and budget optimization |
./references/model-hailuo.md | Hailuo-02 detailed reference card | Hailuo anime/stylization capabilities |
./references/fal-api.md | fal.ai queue API reference | API integration and debugging |
./references/pricing.md | Cost per model per second with scenarios | Budget planning and cost optimization |
./references/prompt-guide.md | Video prompt engineering best practices | Writing effective video prompts |
./references/camera-vocabulary.md | Camera movement and angle terminology | Cinematic prompt construction |
./references/style-keywords.md | Visual style keyword reference | Style consistency across scenes |
./references/story-schema.md | JSON schema for story.json structure | Story decomposition validation |
./references/scene-schema.md | JSON schema for scene objects | Scene data structure validation |
./references/shot-schema.md | JSON schema for shot objects | Shot-level metadata validation |
./references/character-schema.md | JSON schema for character objects | Character definition validation |
./references/consistency-guide.md | Visual consistency techniques across scenes | Multi-scene project quality |
./references/cost-reference.md | Cost estimation for project mode workflows | Project budget planning |
./references/model-selection.md | Model selection guide for project mode | Choosing optimal models per scene |
./references/prompt-assembly.md | How prompts are assembled from components | Understanding prompt construction |
./prompts/enhance-animated.md | LLM prompt template for animation enhancement | Animated content optimization |
./prompts/enhance-cinematic.md | LLM prompt template for cinematic enhancement | Film-quality content optimization |
./prompts/enhance.md | General LLM prompt enhancement template | General prompt improvement |
./prompts/decompose.md | LLM prompt template for story decomposition | Story-to-scenes breakdown |