Issue Examples¶
A minimal reproduction + outcome + fix for each entry in Known Issues, so every one is concrete. Numbers match that page.
#1 — Odd downsample_factor → 0-byte mp4¶
use_fast_output(engine="workbench", downsample_factor=6) # 1280 // 6 = 213 (odd width)
with bare_scene as shot:
shot.add(brian("A")); shot.camera("static"); shot.clip(1/24)
libx264/yuv420p encode aborts —
"Error while opening encoder — incorrect parameters such as … width or height" — leaving a
0-byte .mp4 (libx264 needs even dimensions).
Fix / workaround: use a factor that divides evenly — 1, 2, 4, 5, 8. (Code fix: add
-vf "scale=ceil(iw/2)*2:ceil(ih/2)*2" to the proxy ffmpeg call.)
#2 — Edit output root is a hardcoded absolute path¶
What happens: breaks if the repo moves or runs elsewhere. Workaround: pass it explicitly —
Edit("my_cut", output_root="…/edits").
#3 — pan / jitter / zoom not in the public camera API¶
What happens: these exist in dsl/camera.py but aren't wired into shot.camera()'s dispatch —
only reachable via the low-level comparison scripts (render_camera_compare*.py).
#4 — arc accepts only 90° or 180°¶
Fix / workaround: use arc=90 or arc=180 (the math would interpolate any angle; the guard is
artificial).
#5 — say() clip length follows the animation, not the speech¶
hero.say("Hi.") # ~1 s of speech …
# … but the shot is ~6.5 s — the length of the 'talking' animation
shot.clip(2.0) to trim,
or say(line, action_name="idle") for a shorter hold.
#6 — move_to(action="running") progressively collapses¶
What happens: the pose degrades over the clip — lean → crouch → near-horizontal → collapsed
on the ground (a longer clip is worse). Only running is affected.
A frame (left) and the full 8-second run (right) — it degrades and never recovers:
Workaround: for run-travel use jogging / sprint / fast_run (all fine).
#7 — perform(duration=N) ignored for in-place actions¶
hero.actor.perform("idle", duration=20) # ask for 20 frames …
# … frame_end is still ~121 (the full native idle plays)
duration is
discarded (in-place actions only — locomotion length comes from travel distance).
Workaround: bound the shot with shot.clip(seconds).
#8 — edit.music() BGM comes out near-inaudible¶
What happens: add_bgm mixes with amix, which halves each input, so a low volume BGM
vanishes (quiet ambient tracks especially). Workaround: raise volume to compensate —
0.6–0.8 for present tracks, higher for quiet ambient ones. (Code fix: amix=…:normalize=0.)
Generation & realism limitations¶
A different class from the bugs above — quality and reasoning gaps seen across full generated movies (the Known Issues table, #12–#19). These mostly have no one-line fix; each is shown here on a real rendered shot. Numbers match the Known Issues table.
#12 — TTS voice doesn't match the character¶
A character's voice comes from its rig entry in assets/character_descriptions.json. Cast a rig
whose voice is the wrong gender/tone for the role and the spoken line doesn't match the
character on screen. The frame, and the clip (▶ play with sound):
Workaround (historical): cast a rig whose voice fit the role, or edit the voice field.
✅ Resolved — voice split from the rig
The voice/rig split (dsl/voices.py + the new gender/default_voice schema) fixes this:
every character carries a gender, every voice is gender-tagged, and all 36 pairings are now
gender-matched. james (Marcus's rig) was repinned marin → echo, so the clip above is the
"before". Cast voices explicitly — define once at the top, then reuse in every shot:
# ── top of the film / scene module: import + cast once ─────────────
from dsl.actors import james, megan
from dsl.voices import echo, nova # gender-matched voices
marcus = james("Marcus", voice=echo) # male rig + male voice
nina = megan("Nina", voice=nova) # female rig + female voice
# ── then just use them in any shot ─────────────────────────────────
with BRIDGE.Canal_Bridge2_Middle.E2 as s:
s.block(face_to_face(), nina, marcus)
marcus.say("You get on that plane knowing this.", action_name="talking")
Or override inline for a one-off (voice by singleton or string name, plus a delivery note):
#13 — actors clip through set geometry¶
There is no collision between actors and the set. A blocking offset or walk path can drive a character straight through a post, fence, or prop. Two instances:
Bridge — Sam walks through the wooden post :
Rooftop — the approach path crosses the wall:
Workaround: none in-engine. Place anchors/blocking with clearance from geometry, and frame around contact points.
#14 — animations read as awkward¶
On most rigs the in-place gesture actions look stiff or subtly wrong — by observation 80–90% of them feel "off". Locomotion is the most reliable; gestures are the weakest. Two examples:
sizeup — the pose hunches awkwardly:
considers — the gesture snaps stiffly:
Mitigation: it's a retarget/asset-quality limit, not a code bug — favour the cleaner-reading actions, keep gesture holds short, and let camera + edit sell the beat.
#15 — blocking is flat and not varied¶
The blocking primitives are purely geometric, so staging often reads as unrealistic. Two examples:
Crowd — figures line up at one depth and overlap into each other:
Two-hander — the pair is awkardly faced for the realistic scenarios:
Mitigation: Can have some more realistion blockin and positioning
#16 — camera & subject get obstructed¶
The camera solve doesn't test line-of-sight, so set geometry can land between the lens and the subject — sometimes hiding the actor entirely. Two instances:
Fence — the confession push-in sits inside the fence posts, fully blocking Marcus (even though the shot asked for his "clear, unobstructed angle"):
Wall — a wall drops in front of the lens and hides the standing actor:
Mitigation: choose camera points/angles with a clear sightline to the subject; nudge
theta/phi/R until the view is unobstructed.
#17 — weak spatial reasoning¶
Understanding statement. Occlusion and 3-D space are genuinely hard to reason about from a script alone — even a human director can't reliably predict what the lens will see without looking. The generator inherits this: it can't "see" the set, so obstruction (#16), clipping (#13) and awkward staging (#15) all trace back here. The practical fix is iterative — render, look, nudge.
#18 — sparse anchors confuse relative positioning¶
Understanding statement. A set exposes only a handful of named anchor points, so when a shot needs a position relative to another actor (trailing/following, "just behind", "off to the side"), there are too few hooks and the placement gets imprecise. Denser anchors — or explicit relative offsets — reduce the guesswork.
#19 — gesture animations don't auto-loop to fill a duration¶
Understanding statement. Repeating an animation = call it again (for perform/act); and for
say() you can't loop the gesture — you split the line so each chunk re-triggers it.
Locomotion anims are the only ones that auto-repeat (to fill a to=/duration); gestures just
hold their last frame.
# from movie_samples/home_game/s24.py — a ~20 s confession.
# Split the speech into sentences so the "talking" gesture RE-TRIGGERS on each;
# one long say() would play the gesture ONCE and then freeze for the rest.
marcus.say("You were nine when I became your whole world, and I had no clue what I was doing.", action_name="talking")
marcus.say("I just never wanted you to see me scared, so I never let you see me anything.", action_name="talking")
marcus.say("But you get on that plane tomorrow knowing this: every early practice, every night I waited up.", action_name="talking")
marcus.say("I'd do all of it again. You're the best thing I ever made, Dev.", action_name="talking")