The cinematic trailer for this game runs 80.9 seconds. It opens on a storm over a mountain range and pushes down through the cloud to a fortified gate carved into the rock. Near the end the camera looks almost straight up at a stone giant lit with gold runework, with dwarves and goblins reduced to specks along the bottom of the frame, weapons lowered. All nine factions appear in between.
The finished file is eighteen pieces glued together: twelve generated shots, four narration cards, a title and an opening sting. Every one of those twelve shots came back from the video model at exactly eight seconds, because eight seconds is the only length it will produce.

Adam asked for a trailer. Not a pipeline, not a model, not a shot list: a trailer, in a list of other things he wanted, at a point where the game had enough in it to be worth showing. Everything below is the shape that request takes once you find out that the video model on the other end has exactly one duration.
Veo is Google's video generation model, and it does the thing the name suggests: you give it a paragraph describing a shot, optionally a still image to start from, and it returns a short video clip. There is no timeline, no camera rig and no way to adjust a take — you describe, you wait a few minutes, you accept or you ask again. Runway and OpenAI's Sora are the obvious alternatives.
The constraint that shapes everything below is that Veo generates clips of exactly eight seconds. Ask the same endpoint for four, six or seven and the request comes back rejected. Every shot is therefore generated at eight seconds and cut down afterwards, which turns out to be the cheaper mistake to make.
The model can move a picture, it cannot invent your dwarves
The obvious approach is text to video, and it does not work for a game with nine factions that each have a settled look. Ask for a dwarf and you get a dwarf, but not this game's dwarf, and there is no prompt long enough to fix that reliably across a whole storyboard.
So the pipeline runs in two stages. Stage one asks Gemini for a single wide still, with the game's own splash paintings attached to the request as reference images. Stage two hands that approved still to Veo as the first frame of a clip. The video model is then only being asked to move something that is already correct, rather than to invent the characters.
The storyboard holds fourteen shots, twelve of which made the final cut. Across all fourteen, 21 distinct splash paintings are used as references, plus exactly one character portrait, on the shot that needs a named hero's face to be right.

That is Thane Borin, and he is in the trailer because a shot with a named character in it has a much narrower definition of correct than a shot of an army.
A shot, then, is a handful of paintings and two pieces of writing. The first describes the frame, and the second describes only what moves in it.
keyframe: A charging wedge of goblin warg-riders bursts out of a misty
fog-drowned forest straight toward the viewer. Small wiry green goblins in
scavenged iron armour and open-faced helms, riding huge shaggy wolves with
burning orange eyes and bared fangs, brandishing torches and crude spears.
Mud and shallow water explode from the wolves' paws. Low ground-level angle.
motion: The warg riders charge full-tilt at the camera, wolves bounding through
shallow water with mud and spray exploding outward, torches streaming fire,
goblins howling and levelling spears as they close on the lens.Two habits in those motion prompts are worth taking. Every one of them bans music inside the clip, because a single score is laid over the whole cut at the end and a clip that brought its own would fight it. And every one restates the faction's face design even though the seed image already shows it, because faces drift off-model during animation, with goblins in particular sliding towards cartoon. The negative prompt carries the same defensive posture, listing orc, warcraft, cartoon eyes, big round glossy eyes, googly eyes, cute and chibi.
The recipe, without our nouns
If your project has an established visual identity of any kind, characters, a mascot, a product, a house style, this transfers directly and it is four steps.
- Pick the reference art you already own for the shot: the two or three existing images that between them fix the designs the shot needs. Not a description of them. The images.
- Ask an image model for one still, attaching those as image parts, with prompt text that says explicitly to match the designs and palette of the attached references.
- Look at the still and reject it if it is wrong. This is the cheap gate. A still costs a fraction of a video generation, and it is the only point where a design error is cheap to catch.
- Pass the approved still to the video model as the first frame, with a prompt describing only motion. Restate the identity constraints anyway, because they drift during animation, and put the failure modes you keep seeing into the negative prompt as nouns rather than as adjectives.
The reason this works is not a trick. A video model asked to animate an image is solving a much smaller problem than one asked to invent a scene. The identity question has moved into a still-image step, where you can judge it in a second, and the video model has been left with motion, which is what it is actually good at. The cost is one extra call per shot.
Generation runs one clip at a time, deliberately. Veo's quota is metered per minute and per day at once, so parallel requests burn the daily allowance on rate-limit rejections without finishing any sooner. Rate limits are the only failure worth retrying, backing off from 30 seconds and doubling to a four minute ceiling, and each job is polled every 10 seconds until it reports done.
Eight seconds in, four to seven seconds out
The per-shot durations in the storyboard are edit lengths, not generation lengths. They run 4, 6 and 7 seconds. Every clip on disk is 8 seconds at 1920 by 1080 and 24 frames per second.
The trim happens at assembly, and it is a plain cap on output duration with no seek, so the opening seconds are kept and the rest is thrown away. A four second shot discards half of what it paid for.
That waste is a decision rather than an oversight. A tail is trimmable at assembly, while a tail you did not generate is not recoverable. Regenerating a shot because the edit later wanted an extra second and a half costs another full call and returns a different take, so every shot is generated at the maximum the API allows and cut down afterwards. The eight second limit stops being a constraint on the trailer and becomes a constraint on the cost per second of usable footage.
Every junction between clips is a half second dissolve, and the arithmetic there
is the part that catches people out. ffmpeg's crossfade takes an offset
measured on the growing output timeline rather than on the incoming clip, so it
has to accumulate: each segment advances the offset by its own length minus one
dissolve. Eighteen segments summing to 89.4 seconds, minus seventeen half second
overlaps, gives 80.9, which is exactly what the finished file reports. If your
assembled video comes out longer than that arithmetic predicts, the offset is
being computed per clip instead of cumulatively, which is the default mistake.
The transitions are their own clips
An earlier version used Veo's ability to condition a clip on both a first and a last frame, baking the transition into the tail of every shot. It worked, and it was thrown away, because a tail with a transition baked into it is no longer usable as footage. It spent the full eight seconds of every shot to buy a junction, and that only became obvious once enough shots existed to cut together.
What shipped instead is nine standalone transition clips, generated the same way, each with its own keyframe plate: forge sparks, black smoke, warp gas, falling leaves and so on. At assembly one is cut from 8 seconds down to 3, faded in and out over 0.9 seconds, shifted so it straddles the junction, and laid over the crossfade. They appear only where a clip meets another clip, never where a title card is involved.
Mixing audio that arrived at random levels
Each generated clip brings its own sound with it, and the levels are not comparable. Loudness here is measured in LUFS, the broadcast standard for how loud something actually sounds to a person rather than how large its peaks are, which is why two clips can share a peak level and still be wildly different in perceived volume. Lower is quieter, and the numbers are negative by convention.
Mean loudness across the generated set landed anywhere between -18 and -30 LUFS, with peaks right up against the ceiling. So every clip is normalised to a common -24 LUFS before anything is mixed, which is what makes the mix levels a decision rather than a per-clip accident. Music sits well under a plain clip and lower again under narration, with effects and voice above both. The sum goes through a limiter before a final loudness pass at -15 LUFS, so a busy moment with music, voice and several overlapping effect tails cannot clip. The score under all of it is one of the nine faction soundtracks.
One ffmpeg detail here is worth publishing on its own. Its loudness filter
resamples to 192 kHz internally, and without an explicit resample back to 48 kHz
afterwards, the AAC encoder writes an off-spec sample rate that web players and
store pages will not take.
The other trailer, stepped one frame at a time
There are two trailers and they share nothing. The cinematic one is generated. The gameplay one is captured out of the running game, and it has the harder problem, because a real-time renderer cannot hand you frames at a constant rate while a screenshot is being taken. Something always stalls, and a stall in a capture is a stutter in the finished video.
The answer is to stop the game loop entirely and drive it by hand. The capture page starts a real match but never starts its clock. For each frame of video it advances the simulation to the tick that frame lands on, moves the camera to its keyframed position, and renders exactly once. The simulation runs at 20 ticks per second while capture runs at 24 or 30 frames per second, so most frames land between ticks, and the fractional remainder is passed through to the render so a captured frame interpolates exactly as it would in live play. The render clock is pinned to one frame's worth of time, so animations advance by precisely one capture frame no matter how long the screenshot actually took.
Each shot is a scene description: a map seed, cheats to apply, pre-placed buildings, spawn groups, orders scheduled by tick, and a camera track. The cheats are load-bearing rather than decorative, which is one of the reasons the cheat system is development infrastructure as much as a player feature.
A scene can also be captured twice from cold and compared frame by frame. That check does not demand identical frames, because water ripple phase, cloud seeding and billboard animation phase are render-side randomness that varies per run while the simulation itself is seed-deterministic. It falls back to an image similarity score with a pass floor of 22 dB, on the reasoning that shader phase noise sits around 24 dB and a staged action drifting apart tanks the score. That distinction between a deterministic simulation and a non-deterministic renderer is the same one the determinism checker has to make.
What the next cut needs
The structural work is done and it is reusable. A storyboard is a list of shots, a shot is a few reference paintings plus a motion sentence, and assembly turns a directory of clips into a finished file in one command. What that leaves is the part only Adam can do, which is deciding which dozen moments of this game are worth showing to a player who has never seen it. The pipeline will render whatever that answer turns out to be, in eight second pieces, and cut them down afterwards.





