Seedance Video Studio
Turn raw material into a finished short video. This skill covers the whole path: reading
the material, researching the right visual reference, writing a prompt that actually earns
a good render, driving the Volcengine Ark Seedance API, and pulling the finished MP4 back
to disk.
It also carries working knowledge of film language - the shot grammar behind why one
camera move lands and another one does not - so a request like "make it feel like a
Wong Kar-wai film" becomes something a model can actually render, rather than a
compliment that goes nowhere.
It works in two modes, and the second one matters because it means the skill is useful
even before anyone has an API key.
| Mode | Requires | What happens |
|---|---|---|
| Generate | ARK_API_KEY |
Writes the prompt, submits the job, polls it, downloads the MP4 |
| Prompt-only | Nothing | Writes the prompt and hands it over for the user to paste into 即梦 or any other platform |
Step 1 - Decide which mode you are in
Check the environment before promising anything:
python3 scripts/video_studio.py doctor
doctor reports the Python version, whether ARK_API_KEY is set, and whether the
endpoint authenticates. Exit code 0 means generation is available. Non-zero means fall
back to prompt-only mode, or help the user get a key.
If there is no key, do not stall the task. Produce the prompt, then tell the user in one
sentence what to set to unlock generation.
Three tools ship with this skill:
| Script | Job |
|---|---|
scripts/video_studio.py |
submit, poll and download generation jobs |
scripts/image_prep.py |
vet and prepare input images; first/last frame compatibility scoring |
scripts/trend_scout.py |
collect public sources and report prompt / topic intelligence |
Step 2 - Understand the material
Work out what the user actually handed over before writing a single word of prompt:
- Text only - the idea is theirs; your job is to make it concrete and visual
- Image only - read the image and propose a direction; this is where the most value is created
- Image + text - reconcile them; if they conflict, say so rather than silently picking one
- First + last frame - the motion between them is the whole story; describe the journey, not the endpoints
- Reference images - the user wants a style or subject carried over, not the image animated
Step 3 - Anchor to references
Skip only when the request is already fully specified and simple. Run this loop whenever
the user names a film, a director, a style, a mood, or a genre - or says anything like
"make it look like X" or "I want it to feel premium".
R1 - Research
Use web_search. Query patterns that actually return usable material:
| Goal | Query patterns |
|---|---|
| A specific film or director | <film> 镜头语言 分析, <director> 摄影风格 |
| A genre's visual grammar | <genre> 电影摄影 构图 光影 |
| A mood | 经典 <mood> 镜头 案例, <mood> commercial cinematography breakdown |
| A technique | 长镜头 运镜 手法 案例, <technique> shot analysis |
Collect two to four references. Record concrete techniques, not impressions.
"The lighting felt moody" is useless. "Low-key lighting, one hard side light, cold
grade" is usable.
R2 - Deconstruct
Break each reference into the eight variables from
references/cinematography.md: shot size, angle, movement,
composition, focal length, lighting, color, editing rhythm.
Then name the mechanism - what specifically makes it work? The push-in that compresses
distance? The negative space that isolates? The warm-cool split that adds depth? Write the
mechanism down. Impressions cannot become prompts; mechanisms can.
R3 - Translate
Map the mechanism onto what a generative model can actually execute. This is where most
attempts fail - film references assume long takes and permanently consistent actors,
neither of which holds here. Read section 10 of
references/cinematography.md before translating.
The three hard gaps: 3-5 second stable clip length, no inherent cross-shot consistency,
and fragile complex motion.
R4 - Exceed
Apply one of the four moves from references/shot-library.md:
| Move | What it does |
|---|---|
| Combine | Stack techniques from two different traditions so neither stays predictable |
| Invert | Reverse a classic technique's expected payoff - a push-in aimed at nothing |
| Layer | Add one small detail the reference never had - footprints that are absent |
| Distill | Strip every decorative element, leave one clean strike |
Then ask: can the viewer tell this is copied? If yes, it failed. Rewrite.
Copyright boundary
Learn the technique; do not reproduce the frame.
- Technique is free. Camera movement, lighting approach, composition logic and color
strategy are not protected - study and reuse them freely. - Specific protected expression is not. Recreating a distinctive copyrighted
character, a branded product, a recognizable shot-for-shot sequence, or a real person's
likeness is off limits. Decline those. - Naming a film as a style reference is normal and fine. Rendering that film's actual
footage, characters, or logo is not. - When in doubt, name the mechanism instead of the film:
低饱和冷调 + 极慢推镜 + 大面积负空间
beats做成和银翼杀手一样.
What "exceed" can and cannot mean
Be straight with the user rather than overselling it.
Can exceed a film reference on: single-shot visual density (light, texture and grade
dialed in precisely); speed and cost (minutes, not a shoot day); combinations no real
production would attempt.
Cannot exceed on: narrative complexity inside one shot (3-5s, one idea per shot);
cross-shot continuity without deliberate constraints; complex multi-subject staging.
So "exceed" means a stronger shot, assembled into a sequence - not out-directing a
director inside a single 5-second clip. Say it plainly. A user who understands the
boundary gets a better result than one who was promised cinema and handed a clip.
Step 4 - Write the prompt
The prompt must be in Chinese. Seedance is tuned for Chinese. The conversation with
the user can be in any language; the prompt that goes into the API is always Chinese.
A prompt that renders well has four layers, roughly in this order:
- Subject and action - who or what, doing what, where
- Camera work - shot scale, movement, speed. Pull terms from
references/prompt-cookbook.md; do not invent vocabulary - Light and texture - time of day, light source, color grade, material feel
- Rhythm and mood - pacing, emotional beat, what the viewer should feel at the cut
Keep it tight. A 5-second clip cannot carry eight ideas. Pick one subject, one camera
move, one emotional beat.
For ready-made shot structures, start from a template in
references/shot-library.md instead of a blank page. Each
one gives the intent, a fill-in-the-blanks Chinese prompt, and a way to push past the
original.
The quality gate
Before submitting, run the prompt through this filter. If it fails, rewrite - do not
generate and hope.
- Is anything surprising in it? Frame-accurate renderings of the obvious are forgettable.
- Is there a change? Even in five seconds there should be an A to B, not a static slice of life.
- Would you describe it to a friend? If not, it is not interesting enough yet.
Iterate two or three times here. A rewrite costs nothing; a render costs money and a
minute of waiting.
Step 5 - Submit and retrieve
# Text to video
python3 scripts/video_studio.py create \
-p "清晨的深圳湾,一只白鹭掠过水面,晨雾未散,镜头缓慢横移跟随" \
--ratio 16:9 --duration 5 --wait --download ~/Videos
# Image to video (adaptive ratio keeps the source shape)
python3 scripts/video_studio.py create \
-p "镜头缓慢推近,画面中的人物微微转头看向窗外,光线从冷转暖" \
-i photo.jpg --ratio adaptive --duration 5 --wait --download ~/Videos
# First and last frame - run check-pair first, see the dedicated section below
python3 scripts/video_studio.py create \
-p "花苞紧闭、花瓣收拢,随时间缓缓绽开、颜色由浅粉渐深,最后完全盛开,镜头极缓慢推近,晨光暖色调" \
--image bud.jpg --last-frame bloom.jpg --ratio adaptive --duration 6 --wait --download ~/Videos
# Reference images carry style across
python3 scripts/video_studio.py create \
-p "保持参考图的青绿山水笔触风格,画中的舟缓缓顺流而下" \
--ref-images ref1.jpg ref2.jpg --wait --download ~/Videos
# Inspect the request without spending a call
python3 scripts/video_studio.py create -p "..." --dry-run
Always pass --wait --download <dir> for interactive work. Submitting without --wait
returns a task id that has to be polled separately, which is only useful for batching.
Job management
python3 scripts/video_studio.py status <task_id> # inspect one job
python3 scripts/video_studio.py wait <task_id> --download ./out
python3 scripts/video_studio.py list --status succeeded
python3 scripts/video_studio.py delete <task_id> # cancel or remove
python3 scripts/video_studio.py models # model table and defaults
Add --json to any command for machine-readable output. Add --dry-run to create to
inspect the exact payload - it never sends credentials or media to the network.
First / last frame workflow
This mode fails more often than any other, and nearly always for a reason that was
visible before submitting anything. Two checks come first:
# 1. Can these two frames survive being interpolated?
python3 scripts/image_prep.py check-pair first.jpg last.jpg
# 2. If the geometry disagrees, normalise it before submitting
python3 scripts/image_prep.py pair-fit first.jpg last.jpg --ratio 16:9 --out-dir ./frames
check-pair returns a 0-100 compatibility score and a suggested duration. Treat anything
below 55 as a signal to fix the frames rather than to hope harder. pair-fit repairs
geometry; it cannot repair content that is too far apart - that needs a new frame or two
separate shots.
Then write the prompt as start -> path -> end. Describing only the two endpoints
leaves the model to invent the middle, and that is where drift and morphing come from.
The last frame is a guide, not a pixel lock. Expect the final frame to approach your
target in composition, subject and mood - not to match it exactly. When you need
frame-exact continuity, make it two shots and cut them together.
Full guidance, mid-motion verbs, a duration table and worked examples:
references/frame-transition.md.
Setup
Only needed for generate mode. Prompt-only mode works with no setup at all.
- Create an API key at the Volcengine Ark console.
- Export it - never paste a key into a file that gets shared:
# macOS / Linux / Git Bash
export ARK_API_KEY="your-key-here"
# Windows PowerShell
$env:ARK_API_KEY = "your-key-here"
- Confirm:
python3 scripts/video_studio.py doctor
Interpreter name. Examples throughout use python3. On Windows the interpreter is
normally python - substitute it if python3 is not recognised.
Optional environment variables: ARK_MODEL (override the default model), ARK_BASE_URL
(custom endpoint), ARK_TIMEOUT (HTTP timeout in seconds, default 60).
video_studio.py and trend_scout.py use only the Python standard library, so they run
on a bare Python 3.8 or newer. image_prep.py does its checks with the standard library
alone, and unlocks cropping and frame normalisation when Pillow is present:
python3 -m pip install pillow # optional - unlocks crop / fit / pair-fit
Model selection
Default is doubao-seedance-2-0-260128 (Seedance 2.0). If the account is not enabled for
it, fall back rather than failing:
| Situation | Use |
|---|---|
| Default, multimodal, multi-shot | doubao-seedance-2-0-260128 |
| 2.0 unavailable, need native audio | doubao-seedance-1-5-pro-251215 |
| Need precise frame counts or last frame | doubao-seedance-1-0-pro-250528 |
| Latency matters more than peak quality | doubao-seedance-1-0-pro-fast-251015 |
| Reference-image heavy image-to-video | doubao-seedance-1-0-lite-i2v-250428 |
Run python3 scripts/video_studio.py models for the live table. A 403 usually means the
model is not enabled on that account - switch models before assuming the key is broken.
Resolution defaults to quality
--resolution defaults to the highest setting the chosen model supports, capped at
1080p. Leaving it unset does not hand the decision to the model - it hands it to the
platform default, which is typically 720p or lower.
That silent downgrade is the most common reason a well-written prompt comes back looking
soft. Pass -r 720p when you want faster, cheaper renders. Reach for -r 2k
deliberately, never by default.
Platform limits
The script checks these before submitting, so violations surface as clear local errors
instead of opaque API rejections.
| Input | Limit |
|---|---|
| Images | up to 9, each under 30 MB, jpeg/png/webp/bmp/tiff/gif |
| Video reference | up to 3, total 2-15s, each under 50 MB, mp4/mov |
| Audio reference | up to 3, total 15s, each under 15 MB, mp3/wav |
| Mixed total | 12 files |
| Duration | 4-15s on 2.0, 4-12s on 1.x; -1 lets the model decide |
Local files are inlined as base64, so nothing needs to be hosted publicly.
Content safety red lines
These are platform policy, not preferences. Refuse and explain rather than attempting
and getting the account flagged.
- No real, identifiable people's faces submitted as material, and no prompt that
recreates a specific real person's likeness. - No sexualized content involving minors. Refuse outright, in every framing.
- No content that defames, harasses, or impersonates a real individual.
- No deepfake-style swaps of real people into scenarios they did not participate in.
- Flag anything that looks like it is heading toward fraud, defamation, or non-consensual
intimate imagery, and decline.
When a request trips a red line, say which line and offer a legitimate alternative
direction - a generic subject, an illustrated style, a stock-like composition. Do not
just refuse and stop.
Troubleshooting
Run doctor first; it isolates most failures. Then match the message:
| Symptom | Cause | Fix |
|---|---|---|
ARK_API_KEY is not set |
Env var missing in this shell | Export it; note that Windows PowerShell and Git Bash use different syntax |
| HTTP 401 | Key malformed, revoked, or truncated | Re-issue the key; check for a trailing newline |
| HTTP 403 | Model not enabled for this account or region | Switch model, or enable it in the Ark console |
| HTTP 400 | Bad parameter for this model | Check duration/resolution against the model row; try --dry-run |
| HTTP 429 | Rate limit or exhausted quota | Wait and retry, or check account balance |
Job stuck in running |
Generation genuinely takes 30-180s | Keep waiting; raise --interval if polling is noisy |
| Download produced 0 bytes | URL expired between poll and fetch | Re-run wait <task_id> --download <dir> promptly |
Generation typically takes 30 to 180 seconds depending on resolution and model. Polling
every 15 seconds is a reasonable default.
Trend Scout - batch collection and analysis
scripts/trend_scout.py collects public content and turns it into prompt intelligence.
Reach for it when the user wants to know what is currently working, as opposed to
generating one specific clip.
Two layers, answering different questions:
| Layer | Source | Answers |
|---|---|---|
| Generation | AI video communities that publish prompts alongside results | How should the prompt be written |
| Topic | Public ranking / metadata endpoints | What subject is worth making |
A finding worth remembering. Ranking feeds carry titles and blurbs, not shot
descriptions. A real run against 55,000 characters of Bilibili ranking data matched
shot-language terminology 3 times - a density of 0.05 per 1000 characters. The report
states this up front, because pretending otherwise wastes the user's time. Ranking data
informs what to make; it never tells you how to write the prompt.
python3 scripts/trend_scout.py sources # built-in sources + blocklist
python3 scripts/trend_scout.py check <url> # is this URL fetchable?
python3 scripts/trend_scout.py scout --urls urls.txt --out report.md --delay 3
python3 scripts/trend_scout.py scout --seed --out report.md
python3 scripts/trend_scout.py analyze --input .trend_scout --out report.md
The output is a report, never an automatic edit. Trend data is noisy and a bad merge
would pollute every future prompt. The user reviews the report and decides what - if
anything - goes into prompt-cookbook.md.
Compliance posture
State this plainly to the user; do not soften it.
- The script refuses known-prohibited domains (Douyin, Kuaishou, Xiaohongshu, Weibo,
TikTok, Instagram, Facebook, Zhihu) and says why, rather than attempting and failing. - It respects robots.txt, rate-limits per domain, caps pages per domain, and stops a
domain immediately on 403 / 429. - It never bypasses a captcha, login wall, signature, or paywall, and never sends
credentials. - This is not a scraper for the platforms the user probably has in mind. When asked
to scrape Douyin or Xiaohongshu, explain that the risk is legal rather than merely
technical - unfair-competition law, and potentially criminal-code exposure for
circumventing technical measures - then route them to official open APIs or licensed
data services. - When platform-scale analysis is genuinely needed, point at the licensed data
connectors available in this environment (FastMoss, Tec-Do and similar) rather than
attempting a custom crawler.
Reference material
Read in this order when the task is creative; jump straight to the API doc when it is
mechanical.
| File | Layer | Read when |
|---|---|---|
| references/frame-transition.md | Mode guide - first/last frame mechanics, start-path-end templates, duration table | Any first/last frame job, before writing the prompt |
| references/cinematography.md | Grammar - the eight variables of a shot, and the three hard gaps between film and generation | Deciding how a shot should be built |
| references/shot-library.md | Patterns - 14 shot archetypes with fill-in Chinese prompt templates, plus four moves to exceed them | Starting a shot, or asked to imitate a reference |
| references/prompt-cookbook.md | Vocabulary - shot scale, movement, lighting, texture and style terms | Choosing the exact word |
| references/api-reference.md | Mechanics - parameters, model table, error codes, job states | Debugging a request or extending the script |
The creative references are written in Chinese, because the prompt vocabulary they exist
to supply is Chinese. The mechanism descriptions stay readable regardless of what
language the conversation is in.