Clips Studio
Generate a short video clip through deliberate stages — brainstorm → draft cheaply → produce the
final at quality — using fal.ai. The moving-image sibling of image-studio. The point of the
staging is cost and control: video is the dearest thing on fal (roughly 10–100× a still), so you
lock the idea on a cheap model first, then spend on a quality model only once, on the agreed clip.
This skill generates files locally for the user to review and use. It never posts, publishes, or
sends anything as final collateral.
Scope and routing
Use this skill only when all of the following are true:
- The task is generative video — a clip from a prompt, animating a still, or a camera move over a
still — not slide/deck production, charting, dashboarding, or design-template automation.
- The user is comfortable with fal.ai egress and paid API usage.
- The local helper workflow is available, or the user is asking you to prepare the brief for it.
Do not use this skill for:
- Still images (use
image-studio), Canva-style templates, slide decks, data charts, dashboards,
flowcharts or diagrams.
- Confidential or sensitive image/document processing.
- Any host environment where a native video-generation tool is explicitly mandated.
Three modes — choose this first
Pick the one that matches what the user has and wants:
- Text-to-video (
generate) — a clip from a prompt, with no source image. Best for concept,
abstract/motion-graphic, brand-mood or b-roll-style clips with no still to start from. It
invents everything, so it is never the way to depict a real place, product or person —
animate a real photo for that.
- Animate a still (
animate) — bring an existing image to life: a product turning, people
interacting, a scene, foliage/water/light. The clip animates what is in the frame.
- Adding a new subject to an EMPTY scene (people to a room, product to a set) is a two-step job.
Video models animate what they see; they don't reliably invent believable new subjects. So
first add the subject to the still with
image-studio (an instruction edit), review it,
then animate the populated still here.
- Camera move (
camera) — extrapolate a camera motion over a still: a slow push-in, pan,
tilt, shallow orbit or pull-out (a "3D"/parallax feel; an interior "3D view"). The subject can be
static; the camera moves. This is the riskiest mode for honesty (it invents unseen geometry) —
keep moves gentle and read references/motion-honesty-guide.md first.
All three use the same staging below and the same scripts/falvid.py helper (generate / animate
/ camera).
Before you start — egress and preflight
Generating a clip sends the prompt (and for animate/camera, the start image you provide)
to fal.ai, a third-party US service, and the result clip is downloaded from its CDN. That is external
data egress.
Before any API call:
- Confirm the task is in scope.
- Confirm explicit user go-ahead for fal.ai egress and paid API usage before the first generation in
a session.
- Confirm explicit user go-ahead again before the costlier Stage-3 production run — quote the
estimated cost (video clips can be several dollars each).
- Check that
scripts/falvid.py exists, dependencies are installed, FAL_KEY is set, and the
working directory is writable.
- For
animate/camera, use only non-confidential images the user has rights to process through
fal.ai.
- Use the exact output paths printed by
falvid.py; do not infer filenames from examples.
Never feed confidential or sensitive imagery to fal.ai — e.g. a private person's photo, confidential
documents, or anything under NDA. If the user asks to animate something sensitive, stop and flag the
egress issue rather than uploading it.
Brainstorming in Stage 1 is pure chat and has no egress, so you can always draft the brief first and
confirm the send afterwards.
Setup needed: a fal.ai account with billing, and the FAL_KEY — either the environment variable,
or just saved in a text file in the working folder (any filename, e.g. fal key.txt). The helper
finds the key automatically — env var first, then any small text file in the working folder, then the
home dir — detecting it by content (a FAL_KEY=your-key line or the raw id:secret key), so don't
ask the user for a key before checking; only prompt if none is found. It uses the fal-client
package (pip install fal-client requests). If no key is found the helper fails with a clear message —
generation cannot proceed without it, but Stage 1 still works. (Keep any key file local; never commit it.)
Stage 1 — Brainstorm the brief (no API call)
A good clip starts from a precise brief, so invest here before spending. Interview the user and agree:
- The source — for
animate/camera, which still are we using? (For animate of an empty
scene, has the subject been added via image-studio yet?) For generate, there's no still — agree
the scene to describe. Keep any original in _workings/ untouched.
- The motion / subject — name the action, not a mood. "A nice product video" is vague; "the
bottle slowly rotates on a plinth, soft studio light sweeping across the label" is concrete. For
camera, name the move in cinematographic terms ("slow dolly push-in", "pan left", "shallow orbit").
- Length — default 5 seconds. Keep it short; cost scales with every second. 4–6s suits a
social/web loop.
- Aspect & orientation — anchor to the destination: 16:9 web/hero, 9:16 reel/story, 1:1 social.
For
animate/camera, match the output to the source's orientation and pass --aspect
explicitly (see the check below). For generate there's no source, so choose the target aspect.
- Audio — FLUX 3 generates audio by default (native, included free). The script sends
generate_audio=true for FLUX 3 models automatically — pass --no-audio to disable.
For non-FLUX-3 models (Kling, Seedance, Veo), audio is off by default — opt in with
--audio. So the brief must cover sound for FLUX 3, not just motion. Agree with the user:
- Ambient sound — what's naturally in the scene (rain patter, traffic, birds, machinery hum).
- Music — say "no music" if unwanted, or name the genre/feel ("soft ambient piano", "upbeat
electronic"). Each layer lands separately.
- Speech — a quoted line becomes speech only if a speaker is visible on camera. Without one
it renders as burned-in text. Quote the line, describe the speaker, and add "no on-screen text,
no subtitles" to prevent burned-in captions.
- Silence — if the user wants no audio at all, pass
--no-audio (FLUX 3) or simply don't pass
--audio (other models).
Aspect & orientation — check the source before you generate (applies to animate/camera).
Compare the source still's orientation to the intended video frame (usually 16:9 for web,
9:16 for reels). If they differ — e.g. a portrait or square phone shot for a 16:9 video —
don't just generate:
- First, ask the user for a properly-oriented photo — a landscape shot for a landscape clip, a
vertical shot for a vertical clip. A source that already matches the target frame is the cleanest,
most honest result.
- If the user wants to proceed with the mismatched source anyway, check in on which approach —
never decide it silently:
- (2) Pillarbox / letterbox — keep the source's orientation and place the clip inside the
target frame with side/top fill (bars, or a soft blur of the same shot). Honest — nothing is
invented; you just get bars. Usually a step in the user's video editor.
- (3) Generatively extend (outpaint) the still to the target aspect first, then animate —
full-bleed, but the model invents the surroundings that weren't photographed. Combo with
image-studio (an instruction edit at the target --aspect). Two musts before any video
spend: (a) ground the extension — ask the user for reference images of what's actually around
the subject so the model reconstructs the real context rather than inventing it; (b) confirm
the extended still with the user BEFORE animating — take corrections, re-edit, approve, then
animate. Illustrative only; never present it as the real setting.
- Never (1) force-crop to the target aspect — on a mismatched source the model centre-crops and
discards most of the subject (a tall building loses its top and bottom). It is off the table.
When the orientation does match, still pass --aspect to match the source so the helper doesn't
fall back to 16:9 and crop.
Save the agreed brief to _workings/ (for example _workings/brief_[slug].md) so the run is
auditable. Keep prompts free of confidential detail. This step replaces a cheap prototype for the
idea — confirm the brief (and the start image, for animate/camera) before the first paid call.
Prompting craft. Read references/video-prompting-techniques.md before the first generation in a
session — it covers grounding real subjects, audio layer control, multi-shot syntax, speech vs
burned-in text, and continuation/chaining. These techniques work across all fal.ai video models, not
just one. The short version: write plain prose (not keyword tags), ground anything with a real
checkable appearance, and specify what matters — what you leave out is the model's call.
Stage 2 — Draft cheaply
Render a draft on FLUX 3 Draft (cheap, HD only, native audio included) so you can react for a
fraction of the full cost — $0.06/s vs $0.17/s for the full render.
animate — default FLUX 3 Image-to-Video Draft
(blackforestlabs/flux-3/image-to-video/draft, ~$0.06/s → ~$0.30 for 5s, native audio):
python scripts/falvid.py animate \
--prompt "[the agreed motion, including audio description]" \
--image _workings/[source-still].png \
--duration 5 --aspect 16:9 \
--run-log _workings/run-log_[slug].md \
--out-dir _workings --name vid_[slug]_draft
generate (text-to-video) — default FLUX 3 Text-to-Video Draft
(blackforestlabs/flux-3/text-to-video/draft, ~$0.06/s → ~$0.30 for 5s, native audio):
python scripts/falvid.py generate \
--prompt "[the scene to create, including audio description]" \
--duration 5 --aspect 16:9 \
--out-dir _workings --name vid_[slug]_draft
camera — default Seedance 1.5 Pro (unchanged — strongest camera control); --move offers
gentle presets (push-in, pull-out, pan-left/right, tilt-up/down, orbit, crane-up), and
--static locks the camera entirely:
python scripts/falvid.py camera --move push-in \
--image _workings/[still].png --duration 5 --aspect 16:9 \
--out-dir _workings --name vid_[slug]_draft
Save the draft's seed — it's printed in the run log and cost log. You need it for Draft Enhance
(Stage 3) to re-render the same motion at full quality.
Watch the draft for motion problems — warping faces/hands (the hardest thing for every model; see
references/motion-honesty-guide.md), the camera drifting through walls, objects morphing, jittery
motion. On feedback, the first move is a better prompt, not a pricier model: tighten the action,
reduce the number of moving subjects, slow the camera, then re-draft. Loop cheaply until the motion is
right. Always use the exact saved paths printed by the helper.
Stage 3 — Produce the final
Once the motion is approved on the draft, confirm the go-ahead and the cost again — this is the
main spend. Put the estimate to the user explicitly, e.g. "final as a 5s FLUX 3 clip at 720p, native
audio, ~$0.85 — go ahead?"
Preferred: Draft Enhance (same seed + motion, full quality)
If you drafted on FLUX 3 Draft (Stage 2), the most efficient path to the final is Draft Enhance —
re-render the approved draft at full quality using its same seed, so the motion and composition
carry over exactly. You only pay the full-render cost (not another draft + full):
python scripts/falvid.py enhance \
--prompt "[the same prompt used for the draft]" \
--image _workings/[source-still].png \
--seed [the draft's seed from the run log] \
--duration 5 --resolution 1080p --aspect 16:9 \
--run-log _workings/run-log_[slug].md \
--out-dir . --name vid_[slug]_final
This is the default workflow when you drafted on FLUX 3 Draft. The seed locks the motion; the full
render adds fidelity, corrects artefacts, and upgrades to 1080p.
Alternative: full render from scratch
If you didn't draft on FLUX 3, or want a fresh render from the locked prompt:
animate / generate (people, product, general realism) → FLUX 3
(blackforestlabs/flux-3/image-to-video, or …/text-to-video) — best real-world
understanding, native audio included free; $0.17/s (720p) / $0.29/s (1080p). Up to 20s.
Leaner: Kling 3.0 Pro (fal-ai/kling-video/v3/pro/...). Premium: Veo 3.1
(fal-ai/veo3.1/image-to-video, $0.20/s no-audio / $0.40/s audio).
camera (camera move) → Seedance 1.5 Pro (fal-ai/bytedance/seedance/v1.5/pro/image-to-video)
is already the camera default — strongest camera control and a true camera_fixed lock; ~$0.26
for a 720p/5s clip. For a premium native 4K move, Kling v3 4K (fal-ai/kling-video/v3/4k/image-to-video).
python scripts/falvid.py animate \
--prompt "[the approved motion, including audio]" --image _workings/[source-still].png \
--model blackforestlabs/flux-3/image-to-video --duration 5 --resolution 1080p --aspect 16:9 \
--run-log _workings/run-log_[slug].md \
--out-dir . --name vid_[slug]_final
Save the finished clip at the work-folder root as vid_[slug]_final.mp4, or whatever exact filename
the helper prints. Tell the user the file path and remind them it is a draft clip for review — not
published material, and not a literal record of a real place, product or person.
The honesty line
A moving clip is more persuasive than a still, so the discipline scales with how real the subject
is (full detail in references/motion-honesty-guide.md):
- Don't fabricate facts about a real thing. Don't invent a feature, finish, view or capability a
real product/space doesn't have; don't imply an occupancy, clientele or popularity that isn't real.
Text-to-video invents everything → never use it to depict a real, identifiable subject;
animate a real photo instead.
- Camera moves invent geometry the camera never saw. A slow push-in or a locked camera invents
almost nothing; an aggressive orbit or fly-through hallucinates whole spaces. Prefer gentle moves,
prefer
--static where it works, and never present an extrapolated clip as a real walkthrough or a
faithful layout.
- People & likeness. Use generated, non-identifiable people for mood; never animate an
identifiable real person without consent, and never upload a private person's photo.
- When literal accuracy matters (a listing, a spec claim), a real shoot or a proper 3D capture is
the faithful gold standard — this is a fast first-pass marketing draft.
Model choices
The helper defaults to FLUX 3 for draft and full renders — best real-world understanding, native
audio included free, up to 20s clips, and a Draft Enhance workflow that re-renders the approved draft
at full quality with the same seed. Override with --model [endpoint-id]. The current verified endpoint
IDs, their role and approximate cost live in references/fal-video-models.md.
fal.ai's catalogue changes — if a model ID errors, check that reference and the fal.ai model gallery
rather than guessing. Anything marked (verify) there has not been confirmed against the live gallery
in this build (several text-to-video IDs/rates are (verify) — confirm before relying on the
cost). Stick with the proven defaults unless a result is genuinely unsatisfactory; the first fix is a
better prompt or a gentler move, not a model hunt.
The helper — scripts/falvid.py
One script, three generation subcommands plus costs. It reads FAL_KEY from the environment,
uploads any local --image to fal storage, calls the model via fal_client.subscribe (which polls
the async video queue and blocks until the clip is ready — this can take several minutes; don't
interrupt it), downloads the MP4 locally, and prints the saved path plus an estimated cost. Run
python scripts/falvid.py -h or python scripts/falvid.py [subcommand] -h for all options.
Key flags:
generate (text-to-video) — --prompt (required), --duration, --resolution, --aspect,
--audio, --seed, --model, --out-dir, --name. No --image.
animate — --prompt (required), --image (required), then --duration/--resolution/--aspect/
--audio/--seed/--model/--out-dir/--name.
camera — --move (gentle preset) and/or --prompt, --static (lock the camera), --image
(required), then the same flags.
enhance — FLUX 3 Draft Enhance: --prompt (required), --image (required), --seed (required,
from the draft's run log), --mode (generate or animate, default animate), then the same
flags. Re-renders the draft at full quality using the same seed — locks motion, upgrades fidelity.
costs — print the running cost tally for the session, with --reset to clear it.
recommend — the recommended default model per mode (generate/animate/camera), with live
pricing. Read-only, no spend.
search "term" — search the live fal catalogue (--category, --limit); each hit shown with
its live price, category and licence. Read-only. Find a model the defaults don't cover — then still
prefer the default unless it genuinely falls short.
--arg key=value / --arg-json '{...}' — escape hatch to pass a raw model parameter the flags
don't cover (e.g. --arg negative_prompt='blurry, distorted', --arg end_image_url=...).
--run-log _workings/run-log_[slug].md — append a human-readable markdown audit log.
--verbose — stream the model's own progress logs. Off by default.
The helper maps the start-image argument per model (image_url, or start_image_url for Kling v3),
casts --duration to the type each model wants, only sends generate_audio to models that accept it,
and applies camera_fixed for --static on Seedance (or adds a "static shot" instruction for models
without the parameter). If a call fails because the fal balance is exhausted, it prints clear guidance
rather than a raw stack trace. A worked end-to-end run is in examples/example-run.md.
Costs and balance
Video billing is messy — per-second (Kling, Veo) or per-clip/per-token (Seedance, Hailuo), and the
exact figure depends on output duration, fps, resolution and audio, which the API does not return.
So falvid.py leads with a verified-rate estimate from its registry (mirrors
references/fal-video-models.md) computed from the requested duration and clearly flagged as an estimate
(there is no live pricing-API lookup for video). The fal dashboard is the authoritative
charge. Each run is appended to ./_falvid-costs.jsonl; run python scripts/falvid.py costs for the
session breakdown. Quote the estimate before the final render and keep drafts cheap and short. Balance
is shown only if a fal Admin key is set in FAL_ADMIN_KEY; the normal FAL_KEY cannot read
billing (HTTP 403).
Principles
- Drafts, not advice — outputs are drafts for a person to review, not finished published material.
- Never invent — do not fabricate costs, model IDs, capabilities, or output paths. If uncertain,
say so. Don't fabricate facts about a real subject in a clip.
- Deterministic where it counts — cost tracking, file naming and model routing are deterministic;
the LLM handles creative judgment only.
- Honesty and calibration — flag uncertainty, don't overstate quality, show costs.
- Workspace hygiene — deliverables at the work-folder root; interim files in
_workings/;
superseded versions in _superseded/.
Data handling
Prompts and any start image sent to fal.ai leave the user's control to a third-party tool, so follow a
PII / data-egress rule: do not send confidential or sensitive content to fal.ai. Keep real source
and output files on the local machine. When in doubt, do not egress; ask the user first.
Pitfalls
- Match the source orientation — the models don't reliably inherit it; Seedance defaults to 16:9
and centre-crops a portrait/square still. Pass
--aspect to match (a 3:4 source → --aspect 3:4).
- Hands and fine object interaction break — holding/pouring/gripping is the hardest motion for
every model. Design it out (park object-handling subjects), don't pay a pricier model to fix it.
- Screens/TVs fabricate content — any "alive" cue makes the model cut/zoom the on-screen image;
keep screen motion out of the brief, or let a camera move mask it.
- Confirm before Stage 3 — that's the main spend; a 5s Veo clip with audio is ~$2.
- Use actual saved paths — examples are placeholders; use the paths printed by
falvid.py.
- Text-to-video is never for a real subject — it invents everything;
animate a real photo.
- Video is slow — a single clip can take several minutes; the helper blocks while fal renders it.
- Text-to-video rates are (verify) — sanity-check the first
generate cost on the dashboard.
Verification checklist
1---2name: clips-studio3description: Use when the user wants to "make a video/clip", "generate a video from text", "animate this image/photo", "create a marketing reel / social video / teaser", "do a 3D / parallax move", "pan/zoom/orbit a shot", or mentions fal.ai, Kling, Veo or Seedance for video. Staged fal.ai workflow — brainstorm, draft cheaply, produce the final at quality. Three modes: text-to-video, animate (still to motion), camera-move (push-in/pan/orbit). Not for still images (image-studio), slide decks, or charts. Honesty discipline: never depict real identifiable subjects via text-to-video.4license: MIT5---67# Clips Studio89Generate a short video clip through deliberate stages — **brainstorm → draft cheaply → produce the10final at quality** — using fal.ai. The moving-image sibling of `image-studio`. The point of the11staging is cost and control: video is the dearest thing on fal (roughly **10–100× a still**), so you12lock the idea on a cheap model first, then spend on a quality model only once, on the agreed clip.1314This skill **generates files locally** for the user to review and use. It never posts, publishes, or15sends anything as final collateral.1617## Scope and routing1819Use this skill only when all of the following are true:20211. The task is generative video — a clip from a prompt, animating a still, or a camera move over a22 still — not slide/deck production, charting, dashboarding, or design-template automation.232. The user is comfortable with fal.ai egress and paid API usage.243. The local helper workflow is available, or the user is asking you to prepare the brief for it.2526Do **not** use this skill for:2728- Still images (use `image-studio`), Canva-style templates, slide decks, data charts, dashboards,29 flowcharts or diagrams.30- Confidential or sensitive image/document processing.31- Any host environment where a native video-generation tool is explicitly mandated.3233## Three modes — choose this first3435Pick the one that matches what the user has and wants:3637- **Text-to-video** (`generate`) — a clip **from a prompt, with no source image**. Best for concept,38 abstract/motion-graphic, brand-mood or b-roll-style clips with no still to start from. It39 **invents everything**, so it is **never** the way to depict a *real* place, product or person —40 `animate` a real photo for that.41- **Animate a still** (`animate`) — bring an **existing image** to life: a product turning, people42 interacting, a scene, foliage/water/light. The clip animates **what is in the frame**.43 - **Adding a new subject to an EMPTY scene (people to a room, product to a set) is a two-step job.**44 Video models animate what they see; they don't reliably *invent* believable new subjects. So45 **first add the subject to the still** with `image-studio` (an instruction edit), review it,46 **then animate the populated still here.**47- **Camera move** (`camera`) — extrapolate a **camera motion** over a still: a slow push-in, pan,48 tilt, shallow orbit or pull-out (a "3D"/parallax feel; an interior "3D view"). The subject can be49 static; the *camera* moves. This is the riskiest mode for honesty (it invents unseen geometry) —50 keep moves **gentle** and read `references/motion-honesty-guide.md` first.5152All three use the same staging below and the same `scripts/falvid.py` helper (`generate` / `animate`53/ `camera`).5455## Before you start — egress and preflight5657Generating a clip sends the **prompt** (and for `animate`/`camera`, the **start image you provide**)58to fal.ai, a third-party US service, and the result clip is downloaded from its CDN. That is external59data egress.6061Before any API call:62631. Confirm the task is in scope.642. Confirm explicit user go-ahead for fal.ai egress and paid API usage before the first generation in65 a session.663. Confirm explicit user go-ahead again before the costlier Stage-3 production run — **quote the67 estimated cost** (video clips can be several dollars each).684. Check that `scripts/falvid.py` exists, dependencies are installed, `FAL_KEY` is set, and the69 working directory is writable.705. For `animate`/`camera`, use only non-confidential images the user has rights to process through71 fal.ai.726. Use the exact output paths printed by `falvid.py`; do **not** infer filenames from examples.7374Never feed confidential or sensitive imagery to fal.ai — e.g. a private person's photo, confidential75documents, or anything under NDA. If the user asks to animate something sensitive, stop and flag the76egress issue rather than uploading it.7778Brainstorming in Stage 1 is pure chat and has no egress, so you can always draft the brief first and79confirm the send afterwards.8081**Setup needed:** a fal.ai account with billing, and the `FAL_KEY` — either the environment variable,82**or just saved in a text file in the working folder** (any filename, e.g. `fal key.txt`). The helper83finds the key automatically — env var first, then any small text file in the working folder, then the84home dir — detecting it by content (a `FAL_KEY=your-key` line or the raw `id:secret` key), so **don't85ask the user for a key before checking**; only prompt if none is found. It uses the `fal-client`86package (`pip install fal-client requests`). If no key is found the helper fails with a clear message —87generation cannot proceed without it, but Stage 1 still works. (Keep any key file local; never commit it.)8889## Stage 1 — Brainstorm the brief (no API call)9091A good clip starts from a precise brief, so invest here before spending. Interview the user and agree:9293- **The source** — for `animate`/`camera`, which **still** are we using? (For `animate` of an empty94 scene, has the subject been added via `image-studio` yet?) For `generate`, there's no still — agree95 the scene to describe. Keep any original in `_workings/` untouched.96- **The motion / subject** — *name the action, not a mood.* "A nice product video" is vague; "the97 bottle slowly rotates on a plinth, soft studio light sweeping across the label" is concrete. For98 `camera`, name the move in cinematographic terms ("slow dolly push-in", "pan left", "shallow orbit").99- **Length** — default **5 seconds**. Keep it short; cost scales with every second. 4–6s suits a100 social/web loop.101- **Aspect & orientation** — anchor to the destination: 16:9 web/hero, 9:16 reel/story, 1:1 social.102 **For `animate`/`camera`, match the output to the source's orientation and pass `--aspect`103 explicitly** (see the check below). For `generate` there's no source, so choose the target aspect.104- **Audio** — FLUX 3 generates audio **by default** (native, included free). The script sends105 `generate_audio=true` for FLUX 3 models automatically — pass `--no-audio` to disable.106 For non-FLUX-3 models (Kling, Seedance, Veo), audio is **off by default** — opt in with107 `--audio`. So the brief must cover sound for FLUX 3, not just motion. Agree with the user:108 - **Ambient sound** — what's naturally in the scene (rain patter, traffic, birds, machinery hum).109 - **Music** — say "no music" if unwanted, or name the genre/feel ("soft ambient piano", "upbeat110 electronic"). Each layer lands separately.111 - **Speech** — a quoted line becomes speech **only if a speaker is visible on camera**. Without one112 it renders as burned-in text. Quote the line, describe the speaker, and add "no on-screen text,113 no subtitles" to prevent burned-in captions.114 - **Silence** — if the user wants no audio at all, pass `--no-audio` (FLUX 3) or simply don't pass115 `--audio` (other models).116117**Aspect & orientation — check the source before you generate** *(applies to `animate`/`camera`)*.118Compare the **source still's orientation** to the **intended video frame** (usually 16:9 for web,1199:16 for reels). If they differ — e.g. a **portrait or square phone shot** for a 16:9 video —120**don't just generate**:1211221. **First, ask the user for a properly-oriented photo** — a landscape shot for a landscape clip, a123 vertical shot for a vertical clip. A source that already matches the target frame is the cleanest,124 most honest result.1252. **If the user wants to proceed with the mismatched source anyway, check in on which approach** —126 never decide it silently:127 - **(2) Pillarbox / letterbox** — keep the source's orientation and place the clip inside the128 target frame with side/top fill (bars, or a soft blur of the same shot). **Honest — nothing is129 invented**; you just get bars. Usually a step in the user's video editor.130 - **(3) Generatively extend (outpaint) the still to the target aspect first, then animate** —131 full-bleed, but the model **invents the surroundings that weren't photographed**. Combo with132 `image-studio` (an instruction edit at the target `--aspect`). Two **musts** before any video133 spend: (a) **ground the extension** — ask the user for reference images of what's actually around134 the subject so the model *reconstructs* the real context rather than inventing it; (b) **confirm135 the extended still with the user BEFORE animating** — take corrections, re-edit, approve, *then*136 animate. Illustrative only; never present it as the real setting.1373. **Never (1) force-crop to the target aspect** — on a mismatched source the model centre-crops and138 discards most of the subject (a tall building loses its top and bottom). It is **off the table**.139140When the orientation **does** match, still pass `--aspect` to match the source so the helper doesn't141fall back to 16:9 and crop.142143Save the agreed brief to `_workings/` (for example `_workings/brief_[slug].md`) so the run is144auditable. Keep prompts free of confidential detail. **This step replaces a cheap prototype for the145idea — confirm the brief (and the start image, for `animate`/`camera`) before the first paid call.**146147**Prompting craft.** Read `references/video-prompting-techniques.md` before the first generation in a148session — it covers grounding real subjects, audio layer control, multi-shot syntax, speech vs149burned-in text, and continuation/chaining. These techniques work across all fal.ai video models, not150just one. The short version: write plain prose (not keyword tags), ground anything with a real151checkable appearance, and specify what matters — what you leave out is the model's call.152153## Stage 2 — Draft cheaply154155Render a draft on FLUX 3 Draft (cheap, HD only, native audio included) so you can react for a156fraction of the full cost — **$0.06/s** vs $0.17/s for the full render.157158- **`animate`** — default **FLUX 3 Image-to-Video Draft**159 (`blackforestlabs/flux-3/image-to-video/draft`, ~$0.06/s → ~$0.30 for 5s, native audio):160161 ```bash162 python scripts/falvid.py animate \163 --prompt "[the agreed motion, including audio description]" \164 --image _workings/[source-still].png \165 --duration 5 --aspect 16:9 \166 --run-log _workings/run-log_[slug].md \167 --out-dir _workings --name vid_[slug]_draft168 ```169170- **`generate`** (text-to-video) — default **FLUX 3 Text-to-Video Draft**171 (`blackforestlabs/flux-3/text-to-video/draft`, ~$0.06/s → ~$0.30 for 5s, native audio):172173 ```bash174 python scripts/falvid.py generate \175 --prompt "[the scene to create, including audio description]" \176 --duration 5 --aspect 16:9 \177 --out-dir _workings --name vid_[slug]_draft178 ```179180- **`camera`** — default **Seedance 1.5 Pro** (unchanged — strongest camera control); `--move` offers181 gentle presets (`push-in`, `pull-out`, `pan-left/right`, `tilt-up/down`, `orbit`, `crane-up`), and182 `--static` locks the camera entirely:183184 ```bash185 python scripts/falvid.py camera --move push-in \186 --image _workings/[still].png --duration 5 --aspect 16:9 \187 --out-dir _workings --name vid_[slug]_draft188 ```189190**Save the draft's seed** — it's printed in the run log and cost log. You need it for Draft Enhance191(Stage 3) to re-render the same motion at full quality.192193Watch the draft **for motion problems** — warping faces/hands (the hardest thing for every model; see194`references/motion-honesty-guide.md`), the camera drifting through walls, objects morphing, jittery195motion. On feedback, the **first move is a better prompt, not a pricier model**: tighten the action,196reduce the number of moving subjects, slow the camera, then re-draft. Loop cheaply until the motion is197right. Always use the exact saved paths printed by the helper.198199## Stage 3 — Produce the final200201Once the motion is approved on the draft, **confirm the go-ahead and the cost again** — this is the202main spend. Put the estimate to the user explicitly, e.g. *"final as a 5s FLUX 3 clip at 720p, native203audio, ~$0.85 — go ahead?"*204205### Preferred: Draft Enhance (same seed + motion, full quality)206207If you drafted on FLUX 3 Draft (Stage 2), the most efficient path to the final is **Draft Enhance** —208re-render the approved draft at full quality using its **same seed**, so the motion and composition209carry over exactly. You only pay the full-render cost (not another draft + full):210211```bash212python scripts/falvid.py enhance \213 --prompt "[the same prompt used for the draft]" \214 --image _workings/[source-still].png \215 --seed [the draft's seed from the run log] \216 --duration 5 --resolution 1080p --aspect 16:9 \217 --run-log _workings/run-log_[slug].md \218 --out-dir . --name vid_[slug]_final219```220221This is the default workflow when you drafted on FLUX 3 Draft. The seed locks the motion; the full222render adds fidelity, corrects artefacts, and upgrades to 1080p.223224### Alternative: full render from scratch225226If you didn't draft on FLUX 3, or want a fresh render from the locked prompt:227228- **`animate` / `generate` (people, product, general realism)** → **FLUX 3**229 (`blackforestlabs/flux-3/image-to-video`, or `…/text-to-video`) — best real-world230 understanding, native audio included free; $0.17/s (720p) / $0.29/s (1080p). Up to 20s.231 Leaner: **Kling 3.0 Pro** (`fal-ai/kling-video/v3/pro/...`). Premium: **Veo 3.1**232 (`fal-ai/veo3.1/image-to-video`, $0.20/s no-audio / $0.40/s audio).233234- **`camera` (camera move)** → **Seedance 1.5 Pro** (`fal-ai/bytedance/seedance/v1.5/pro/image-to-video`)235 is already the `camera` default — strongest camera control and a true `camera_fixed` lock; ~$0.26236 for a 720p/5s clip. For a premium native 4K move, **Kling v3 4K** (`fal-ai/kling-video/v3/4k/image-to-video`).237238```bash239python scripts/falvid.py animate \240 --prompt "[the approved motion, including audio]" --image _workings/[source-still].png \241 --model blackforestlabs/flux-3/image-to-video --duration 5 --resolution 1080p --aspect 16:9 \242 --run-log _workings/run-log_[slug].md \243 --out-dir . --name vid_[slug]_final244```245246Save the finished clip at the work-folder root as `vid_[slug]_final.mp4`, or whatever exact filename247the helper prints. Tell the user the file path and remind them it is a **draft clip for review** — not248published material, and not a literal record of a real place, product or person.249250## The honesty line251252A moving clip is more persuasive than a still, so the discipline scales with how *real* the subject253is (full detail in `references/motion-honesty-guide.md`):254255- **Don't fabricate facts about a real thing.** Don't invent a feature, finish, view or capability a256 real product/space doesn't have; don't imply an occupancy, clientele or popularity that isn't real.257 **Text-to-video invents everything** → never use it to depict a real, identifiable subject;258 `animate` a real photo instead.259- **Camera moves invent geometry the camera never saw.** A slow push-in or a locked camera invents260 almost nothing; an aggressive orbit or fly-through hallucinates whole spaces. Prefer gentle moves,261 prefer `--static` where it works, and never present an extrapolated clip as a real walkthrough or a262 faithful layout.263- **People & likeness.** Use generated, non-identifiable people for mood; never animate an264 identifiable real person without consent, and never upload a private person's photo.265- **When literal accuracy matters** (a listing, a spec claim), a real shoot or a proper 3D capture is266 the faithful gold standard — this is a fast first-pass marketing draft.267268## Model choices269270The helper defaults to **FLUX 3** for draft and full renders — best real-world understanding, native271audio included free, up to 20s clips, and a Draft Enhance workflow that re-renders the approved draft272at full quality with the same seed. Override with `--model [endpoint-id]`. The current verified endpoint273IDs, their role and approximate cost live in `references/fal-video-models.md`.274fal.ai's catalogue changes — if a model ID errors, check that reference and the fal.ai model gallery275rather than guessing. Anything marked *(verify)* there has not been confirmed against the live gallery276in this build (several **text-to-video** IDs/rates are *(verify)* — confirm before relying on the277cost). Stick with the proven defaults unless a result is genuinely unsatisfactory; the first fix is a278better prompt or a gentler move, not a model hunt.279280## The helper — `scripts/falvid.py`281282One script, three generation subcommands plus `costs`. It reads `FAL_KEY` from the environment,283uploads any local `--image` to fal storage, calls the model via `fal_client.subscribe` (**which polls284the async video queue and blocks until the clip is ready — this can take several minutes; don't285interrupt it**), downloads the MP4 locally, and prints the saved path plus an estimated cost. Run286`python scripts/falvid.py -h` or `python scripts/falvid.py [subcommand] -h` for all options.287288Key flags:289290- `generate` (text-to-video) — `--prompt` (required), `--duration`, `--resolution`, `--aspect`,291 `--audio`, `--seed`, `--model`, `--out-dir`, `--name`. **No `--image`.**292- `animate` — `--prompt` (required), `--image` (required), then `--duration`/`--resolution`/`--aspect`/293 `--audio`/`--seed`/`--model`/`--out-dir`/`--name`.294- `camera` — `--move` (gentle preset) and/or `--prompt`, `--static` (lock the camera), `--image`295 (required), then the same flags.296- `enhance` — FLUX 3 Draft Enhance: `--prompt` (required), `--image` (required), `--seed` (required,297 from the draft's run log), `--mode` (`generate` or `animate`, default `animate`), then the same298 flags. Re-renders the draft at full quality using the same seed — locks motion, upgrades fidelity.299- `costs` — print the running cost tally for the session, with `--reset` to clear it.300- `recommend` — the recommended default model per mode (generate/animate/camera), with **live301 pricing**. Read-only, no spend.302- `search "term"` — search the **live** fal catalogue (`--category`, `--limit`); each hit shown with303 its live price, category and licence. Read-only. Find a model the defaults don't cover — then still304 prefer the default unless it genuinely falls short.305- `--arg key=value` / `--arg-json '{...}'` — escape hatch to pass a raw model parameter the flags306 don't cover (e.g. `--arg negative_prompt='blurry, distorted'`, `--arg end_image_url=...`).307- `--run-log _workings/run-log_[slug].md` — append a human-readable markdown audit log.308- `--verbose` — stream the model's own progress logs. Off by default.309310The helper maps the start-image argument per model (`image_url`, or `start_image_url` for Kling v3),311casts `--duration` to the type each model wants, only sends `generate_audio` to models that accept it,312and applies `camera_fixed` for `--static` on Seedance (or adds a "static shot" instruction for models313without the parameter). If a call fails because the fal balance is exhausted, it prints clear guidance314rather than a raw stack trace. A worked end-to-end run is in `examples/example-run.md`.315316## Costs and balance317318Video billing is messy — per-second (Kling, Veo) or per-clip/per-token (Seedance, Hailuo), and the319exact figure depends on output duration, fps, resolution and audio, which the API does **not** return.320So `falvid.py` leads with a **verified-rate estimate** from its registry (mirrors321`references/fal-video-models.md`) computed from the requested duration and clearly flagged as an estimate322(there is no live pricing-API lookup for video). **The fal dashboard is the authoritative323charge.** Each run is appended to `./_falvid-costs.jsonl`; run `python scripts/falvid.py costs` for the324session breakdown. Quote the estimate before the final render and keep drafts cheap and short. Balance325is shown only if a fal **Admin** key is set in `FAL_ADMIN_KEY`; the normal `FAL_KEY` cannot read326billing (HTTP 403).327328## Principles329330- **Drafts, not advice** — outputs are drafts for a person to review, not finished published material.331- **Never invent** — do not fabricate costs, model IDs, capabilities, or output paths. If uncertain,332 say so. Don't fabricate facts about a real subject in a clip.333- **Deterministic where it counts** — cost tracking, file naming and model routing are deterministic;334 the LLM handles creative judgment only.335- **Honesty and calibration** — flag uncertainty, don't overstate quality, show costs.336- **Workspace hygiene** — deliverables at the work-folder root; interim files in `_workings/`;337 superseded versions in `_superseded/`.338339## Data handling340341Prompts and any start image sent to fal.ai leave the user's control to a third-party tool, so follow a342PII / data-egress rule: **do not send confidential or sensitive content** to fal.ai. Keep real source343and output files on the local machine. When in doubt, do not egress; ask the user first.344345## Pitfalls3463471. **Match the source orientation** — the models don't reliably inherit it; Seedance defaults to 16:9348 and centre-crops a portrait/square still. Pass `--aspect` to match (a 3:4 source → `--aspect 3:4`).3492. **Hands and fine object interaction break** — holding/pouring/gripping is the hardest motion for350 every model. Design it out (park object-handling subjects), don't pay a pricier model to fix it.3513. **Screens/TVs fabricate content** — any "alive" cue makes the model cut/zoom the on-screen image;352 keep screen motion out of the brief, or let a camera move mask it.3534. **Confirm before Stage 3** — that's the main spend; a 5s Veo clip with audio is ~$2.3545. **Use actual saved paths** — examples are placeholders; use the paths printed by `falvid.py`.3556. **Text-to-video is never for a real subject** — it invents everything; `animate` a real photo.3567. **Video is slow** — a single clip can take several minutes; the helper blocks while fal renders it.3578. **Text-to-video rates are *(verify)*** — sanity-check the first `generate` cost on the dashboard.358359## Verification checklist360361- [ ] Scope is video generation, not deck/chart/diagram/design-template work.362- [ ] User confirmed fal.ai egress and paid API usage before the first API call.363- [ ] Source orientation checked; `--aspect` passed to match (or the mismatch handled via pillarbox /364 grounded+confirmed outpaint — never a force-crop).365- [ ] Brief saved to `_workings/`; drafted cheaply and iterated before the quality render.366- [ ] Actual printed output paths were used, not inferred paths.367- [ ] User confirmed go-ahead and saw the cost estimate before Stage 3.368- [ ] Text-to-video was not used to depict a real, identifiable subject.369- [ ] Final clip saved at the work-folder root; user told the path and reminded it is a draft.370- [ ] `--run-log` used, or the JSONL cost log reviewed; cost summary printed via `falvid.py costs`.