Chapter 6 of 9. Prerequisite: Motion transfer. You can put a registered character through borrowed choreography now. This chapter stops the ground under that character changing between shots: one scene plate, passed as an image reference into every render, is the whole trick.
No video model holds a persistent 3D world. Every task you submit to the create-task endpoint is stateless: the model that rendered your arena in beat 1 retains nothing of it when beat 2 renders ten seconds later. Ask for the same location twice by prompt alone and you get two locations that rhyme.
Films never solved this either. A physical set is a handful of fragments and the edit implies the whole. That method ports directly: you do not build a space, you build a spliceable scene map of fragments. The operating rule fits on one line. You never have to show the whole space; you only have to never contradict it.
No persistent world: why chaining and camera locks cannot save you
Two obvious fixes fail before the real one works.
Frame-chaining. Chapter 2's long-form pattern loops return_last_frame into the next render's first_frame. In a text-only 1.x pipeline that runs. In this pipeline it is illegal: the moment a request carries a character asset or a motion reference, adding first-frame or last-frame content returns HTTP 400 with
first/last frame content cannot be mixed with reference media content
The API treats first/last-frame image-to-video and reference media (the reference_image / reference_video inputs documented in the Seedance 2.0 series tutorial) as mutually exclusive modes. So shot-to-shot frame-chaining is unavailable to any pipeline that uses registered characters. Even where chaining is legal, every link inherits the last link's drift, and the environment mutates a little more per generation.
Camera locks. The camera_fixed body parameter on the create-task API is rejected whenever any reference media is present:
HTTP 400 "camera_fixed is not supported for dreamina-seedance-2-0 in r2v, must be empty"
In an asset pipeline reference media is always present, so camera consistency is a post-production problem, never a render-time parameter.
What remains is a set of hard limits to design around rather than fight:
- Trustworthy footage tops out around 5 to 8 seconds per clip. 2.0 renders up to 15 seconds, but plan your cut before the drift arrives.
- There is no coherent mega-wide. The model cannot paint a whole consistent city; it can paint a plate-sized fragment of one.
- Conflicting references get averaged. Keep every reference in a request inside one lighting and palette family.
- Camera-move prompts are unreliable. Fake camera moves on the plate in the edit instead.
- Text and signage warp. Add titles in the edit, never in the render.
Seedance 2.0 accepts four input modalities, "text, image, audio, and video", per the official launch announcement. The scene primitive exploits the image modality for a job the marketing never mentions: pinning the world.
A consistent environment across shots: the single-render proof
The receipt is one 480p render. The content array held two registered character assets as Image 1 and Image 2, a raw anime/CGI choreography reference as Video 1, and a scene plate of a ruined colosseum as the third image, with the prompt ending "in the environment of @Image3." The raw reference passed moderation with no line-art step, confirming chapter 5's rule cuts both ways: line-art is for real-person footage, and animated or CGI references sail through untouched.
The output was unmistakably the plate's colosseum: the tiers, the cracked sandstone, the sun position, the shadow direction. Both actors were lit to match. The model does not paste the plate behind the action as a backdrop; it relights the whole shot to agree with the plate.
Then the sequence-scale proof. The first full movie was five beats of 7 seconds each, every beat an independent create-task submission, the same plate cited in all five. The devlog line: "The arena LOCKED across all 5 independent renders". Scene consistency via a shared plate had only been proven for one shot before that run; this is the proof that makes multi-shot films viable. Total render spend for the whole five-beat movie was about $2.50. For calibration, a 5-second 480p render with an image reference present bills at roughly $0.35 on the 2.0 rate card (see ModelArk pricing for the current per-model formulas).
That is the scene primitive in full. The plate is the world. Every beat renders independently against it, and the lock survives because each render re-derives the environment from the same pixels.
The plate in the request: roles, order, and citation by index
A scene plate needs no registration. Character faces went through Virtual Portrait Asset registration in chapter 4 because raw face uploads trip moderation. A plate has no faces, so no moderation gate and no registration step: pass it straight in as an image_url item, either a hosted URL or a base64 data URI. Images accept base64; reference videos do not, as chapter 5's InvalidParameter: reference_video must be provided as a web url rejection established.
Here is a real beat request, genericised, in the shape the video generation tutorial documents:
{
"model": "dreamina-seedance-2-0-260128",
"content": [
{
"type": "text",
"text": "New Eyes is @Image1, Ellie is @Image2, in the environment of @Image3. New Eyes drives Ellie screen-right across the arena floor with a flurry of punches, dust kicking up at their feet. Cracked sandstone tiers behind, low sun from screen-left, long hard shadows. Static medium two-shot. Motion follows @Video1."
},
{ "type": "image_url", "image_url": { "url": "asset://<your-asset-id>" }, "role": "reference_image" },
{ "type": "image_url", "image_url": { "url": "asset://<your-asset-id>" }, "role": "reference_image" },
{ "type": "image_url", "image_url": { "url": "data:image/png;base64,<plate-bytes>" }, "role": "reference_image" },
{ "type": "video_url", "video_url": { "url": "https://<your-public-host>/beat-03.mp4" }, "role": "reference_video" }
],
"resolution": "480p",
"ratio": "16:9",
"duration": 7,
"watermark": false
}
Submit it against the ap-southeast-1 base URL from the ModelArk overview:
curl -sS "https://ark.ap-southeast.bytepluses.com/api/v3/contents/generations/tasks" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY" \
-d @beat-03.json
The response is immediate and tiny:
{ "id": "cgt-<task-id>" }
Poll the retrieve endpoint at GET /contents/generations/tasks/{id} until the status leaves queued/running. The full state set is queued, running, succeeded, failed, expired, plus cancelled, which the docs note applies only to tasks still queued: "Only tasks in the queued state can be canceled". On success the payload carries a signed MP4 URL:
{
"id": "cgt-<task-id>",
"status": "succeeded",
"content": { "video_url": "https://<signed-mp4-url>" }
}
Because the account cap on an individual plan is 3 concurrent non-4K generations, submitting five beats at once parks two of them in queued rather than failing them; BytePlus's burst-traffic guidance covers what happens past the harder limits, where the API answers 429.
Now the rule that decides whether your citations point at the right pixels. @Image3 means the third item of type image_url in the content array, counted from 1 in array order. @Video1 means the first video_url item. Asset ids never enter into it; referencing by id is unsupported.
The input budget on a 2.0 request is text plus up to 9 images, 3 videos and 3 audios, per the Seedance 2.0 series tutorial. The plate costs one image slot per render. With two characters and a plate you have six image slots left for props before the budget bites.
Scene maps replace worlds: five to nine plates and a bible
One plate locks one angle of one location. A film needs coverage, so the unit of world-building is not a plate but a scene map: 5 to 9 anchor plates, a consistency bible, a beat list, and transition rules. As a data structure:
scene: ruined-colosseum
axis_of_action: "attacker screen-left, defender screen-right; the 180 line runs along the arena's long axis"
bible:
- "cracked sandstone tiers, three visible"
- "low afternoon sun from screen-left, long hard shadows"
- "dust haze at ground level"
anchors:
- id: master
file: plate-01-master-wide.png # generated first; the style seed for every other plate
- id: floor-east
file: plate-02-floor-east.png
- id: wall-breach
file: plate-03-wall-breach.png
beats:
- id: b3
anchor: floor-east
action: "flurry drive, screen-left to screen-right"
transitions:
- "every scale jump is a hard cut"
- "cross the 180 line only through the master wide"
Authoring rules, in order:
- Generate the master plate first. It is the style seed; every other anchor derives from it, so its palette and light become the scene's palette and light.
- Keep every anchor in the master's lighting family. Conflicting references get averaged, and an averaged environment is a broken lock.
- Decide the axis of action before generating anything. The 180 line is a promise to the audience; cross it only through a neutral anchor such as the master wide.
- Reuse plates with pans and pushes in post. A slow push on a still plate reads as a camera move and costs nothing; a prompted camera move costs a render and often fails.
- Repeat the bible tokens in every prompt. "Cracked sandstone, low sun screen-left" appears in beat 3's prompt above because it appears in every beat's prompt.
Cut, never traverse: transition rules that survive independent renders
Never ask the model to traverse the space. A character walking from the east wall to the tiers in one shot forces the model to invent everything between two anchors, and it will contradict both. Cut instead. Every relocation and every scale jump is a hard cut to a beat rendered against a different anchor.
The proof of how far this goes is a kick through a wall built from four fragments that never share a frame:
- Launch
Render the kick against the interior anchor. The target leaves frame toward the wall. Cut at the moment of exit, before any contact.
- Impact frame
1 to 3 frames of white flash and dust, built in the edit. Nothing is rendered. This is where the contact lives, and it is never shown.
- Burst-out
Render the far side against the wall-breach anchor: body and debris travelling away from a hole that was always there in the plate.
- Landing and settle
Render the landing against the same anchor, then drop one delayed rubble chunk into frame in post. The late chunk sells the mass.
The escalation ladder from wall to building to city runs on the same grammar plus two scale cheats: slow is big, so drop the action's tempo as the scale rises; and reaction shots carry scale, so a face watching the far-off collapse reads bigger than the collapse ever renders.
Verify a lock the same way every time. Pull a contact sheet from each beat and compare geometry, sun direction and shadow direction across renders:
ffmpeg -i beat-03.mp4 -vf "fps=2,scale=420:-1,tile=4x3" beat-03-sheet.png
Why a plate per beat, not a chained world?
The call
Every beat renders as an independent task against the same scene plate. Continuity lives in the reference, and the edit implies the space.
Rejected
What it costs
You author 5 to 9 anchor plates and a consistency bible before the first beat renders, and every scale jump needs a cut you planned in advance.
Revisit when
If a future model ships a persistent scene or world-state API, chaining becomes worth re-testing.
What's next
The world is locked; the acting inside it is still rough. The five-beat movie above held its arena perfectly and still read as a rough cut, and its roughness at the cuts was later fixed entirely in the edit with no re-render. The acting problem is different: a later full-fight pass rendered every shot off one constant generic prompt and looked it. The fix was a directed prompt per beat, and that before/after is the sharpest quality jump in this whole course. That is the next chapter.
Lock your own world with one plate
Build a minimal scene map for a location of your own: generate a master plate, derive two more anchors in the same lighting family, write a three-line consistency bible, then render two independent beats against the same anchor plate and prove the environment locked.
Expected behaviour
- A scene-map file with a master plate, at least two derived anchors, a three-line bible, and a declared axis of action
- Every anchor shares the master's lighting and palette family, so no reference gets averaged against another
- Two independent create-task requests that pass the same plate as a reference_image and cite it by array index in the prompt
- Neither request pairs the plate with first_frame or last_frame content, so neither returns the mixing 400
- A contact sheet per render showing matching geometry, sun direction and shadow direction in both clips
PROVE IT Place the two contact sheets side by side and point at three matching environment features across the independent renders: one geometry feature, the light direction, and one bible token visibly honoured in both.
Your five-beat sequence renders each beat as an independent task. What keeps the environment consistent across the shots?
Two character assets occupy the first two image slots of the production content array. Which citation names the beat's scene anchor plate?
Your storyboard wants the fighter to cross the arena from the east wall to the tiers in a single shot. What does the chapter say to do instead, and why?
Show answer
Cut, never traverse. No model holds a persistent 3D world, so a traversal forces it to invent everything between two anchors and contradict both. Render the east-wall beat against its anchor plate, hard-cut, then render the tiers beat against its own anchor, crossing the 180 line only through a neutral anchor if the axis flips. The edit implies the space; you never show the whole arena, you only never contradict it.
↺ re-read: “Cut, never traverse: transition rules that survive independent renders”