VSE Cut List

examples/vse-cut-list/

The sequencer API rename from 4.5 LTS to 5.x — strips (never .sequences), new_effect ending in length= vs frame_end=, and left_handle/right_handle/duration replacing the deprecated frame_final_*. A deterministic cut list — color programs, a clamped GAMMA_CROSS, a scene strip, a text strip — asserted before and after save/reload.

Rendered headless by the example itself. Select it to enlarge.

witnesses Each side hard-fails the other's spelling: TypeError on the wrong end kwarg, AttributeError on .sequences. The cross clamps to the source overlap, effect strips consume their inputs only when stacked above them, and a same-scene scene strip renders transparent.

tags sequencer rendering

runs on 4.5 LTS · 5.1 · 5.2 LTS

blender --background --python examples/vse-cut-list/vse_cut_list.py --

falsify it Breaks the contract on purpose and must exit 7

blender --background --python examples/vse-cut-list/vse_cut_list.py -- --swap-inputs

A runnable example that witnesses the sequencer API rename between Blender 4.5 LTS and 5.x — the single most common way AI-generated VSE code dies on a modern Blender. Every tutorial-era snippet does scene.sequence_editor.sequences.new_effect(..., frame_end=...); on 5.x that path is gone twice over (sequences removed, frame_end kwarg rejected), and on 4.5 the modern spelling (strips, length=) is already the only one the new collection accepts.

What it witnesses: a deterministic cut list — three color programs A/B/C, a GAMMA_CROSS fed by a dedicated source pair T1/T2, a scene strip, and a text strip — asserted against closed-form spans on each version's canonical accessors, then re-asserted after a save/reload round-trip:

What each check catches on failure:

Hazards discovered while authoring (all witnessed by the checks above):

Version divergence: the whole example is the divergence — gated on the bpy.app.version tuple (>= (5, 0, 0)), never on version_string ("4.5.11 LTS" is not bare semver). Each side asserts its own canonical contract plus the other side's removal/bridge state. Measured values are identical on 4.5.11 and 5.1.2, including the pixel witness. 5.2 LTS COLOR strips bake readonly width/height from the scene render resolution at new_effect time (4.5/5.1 have no intrinsic size — scale is a fraction of the output frame). The pixel check sets 96×54 before building the cut list; creating at factory 1920×1080 then rendering 96×54 makes 0.36-scaled cells larger than the output, C covers the frame, and TL samples amber (0.949, 0.62, 0.102) instead of crimson.

Render: the program wall is the sequencer output at frame 29 (mid cross) — crimson A, teal B, amber long-runner C, and the 50/50 cross blend, over the Stage scene strip showing the dark studio. An off-by-one in end-exclusive span math drops its cell to the dark stage; the caption strip carries the closed form. The hero presents that authentic frame on a reference monitor in a dark-studio editing bay — the pixels on the screen are the genuine sequencer output (evidence); only the bay around them is staged (presentation). Rendered locally with EEVEE (GPU host); the checks and --check-pixels need no GPU (Cycles CPU).

In front of the monitor, a tilted timeline console makes the same cut list physical: one lane per channel (A, B, C, TXT, GC), each strip a coloured block spanning its [left_handle, right_handle) read back through the same strip_span accessor the check asserts, with raised handle notches at both ends, a frame ruler, and the playhead at frame 29. The GC block ramps from its input_1 colour to its input_2 colour, so the wiring reads too. The console is laid out from the strips, never from constants — a span that drifted would move its block. The monitor's neck is seated into the monitor back and its foot sits on the walnut desk top; none of the bay touches the sequencer frame or any check.

The still builds the cut list at the 1280×720 render resolution. 5.2 COLOR strips bake width/height from the render resolution at new_effect time (the same trap --check-pixels documents), and the previous still built at the factory 1920×1080 and rendered at 1280×720, which pushed every mosaic cell off its crosshair slot.

Framing measurement#

The gallery still renders from the dedicated Bay scene (camera BayCam), not bpy.context.scene — a framing measurement with examples/gallery_framing.py must be handed that (scene, camera) pair explicitly.

Run#

# Cheap correctness check (no render) — the CI check:
blender --background --python vse_cut_list.py --

# Falsifier: GC T2 -> T1. Must exit non-zero (wiring). `--check-pixels` is a
# second witness, not this falsifier.
blender --background --python vse_cut_list.py -- --swap-inputs

# Compositing witness on a tiny render (Cycles CPU, CI-safe):
blender --background --python vse_cut_list.py -- --check-pixels --engine cycles

# Also render the still (EEVEE on a GPU host; --engine cycles on GPU-less):
blender --background --python vse_cut_list.py -- --output vse.png

Exit codes#

Per-script sequential checks. 9 is a valid check code; there is no rule against it. 10 is also the shared framing helper.

CodeMeaning
0Success
1Uncaught exception (FATAL wrapper)
2argparse / usage
3.sequences accessor contract for this Blender
4Wrong-era new_effect end kwarg or TRANSFORM type did not TypeError
5Strip span or channel off closed form
6frame_final_* deprecation bridge for this Blender
7GC wiring or strip .type enum (--swap-inputs lands here)
8Scene strip span or Stage source
9Mosaic transform, compositing defaults, text body, or strip color
10Gallery framing violation (--output only; gallery_framing)
12--check-pixels compositing contract
13Save/reload round-trip re-assert failed
14--output produced no file

The blender-smoke workflow runs the check and the pixel witness on Blender 5.2 LTS and 4.5 LTS (5.1 on the weekly cron, the needs-5.1 PR label, or manual dispatch). Smoke does not pass --output. Its catalog falsifier is --swap-inputs (expects exit 7).

Source

examples/vse-cut-list/vse_cut_list.py View the script on GitHub →
A monitor on a walnut desk showing crimson, teal, amber and cross-blend cells, above a tilted timeline console laying out the same strips as coloured blocks under a playhead.