Skip to content
Back to skills

Vse Python

ASecurity

Build and inspect Video Sequence Editor timelines from Python: SequenceEditor.strips vs the removed .sequences, new_effect length vs frame_end, strip transforms, and the 5.2 COLOR strip width/height bake from scene resolution. Use when the user scripts the sequencer, hits AttributeError on sequence_editor.sequences in 5.x or a TypeError on new_effect keyword arguments, or renders COLOR strips that ignore transform scale after a resolution change. Targets 5.2 LTS with 4.5 LTS fallback.

  • 16 stars
  • 0 votes
  • 0 copies
  • 4 views
  • Added September 23, 2026
developmentpythongogitapi

Works with

  • api

Security analysis

A100/100

Scanned October 5, 2026

npx -y skills add TMHSDigital/Blender-Developer-Tools --skill vse-python --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Vse Python?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Vse Python
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tmhsdigital-vse-python/badge)](https://www.skillsdirectory.com/skills/tmhsdigital-vse-python)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: vse-python
description: "Build and inspect Video Sequence Editor timelines from Python: SequenceEditor.strips vs the removed .sequences, new_effect length vs frame_end, strip transforms, and the 5.2 COLOR strip width/height bake from scene resolution. Use when the user scripts the sequencer, hits AttributeError on sequence_editor.sequences in 5.x or a TypeError on new_effect keyword arguments, or renders COLOR strips that ignore transform scale after a resolution change. Targets 5.2 LTS with 4.5 LTS fallback."
standards-version: 1.10.0
---

# Video Sequence Editor in Python

## Trigger

Use this skill when the user:

- Builds or inspects a VSE / sequencer timeline from a script
- Mentions `sequence_editor`, `strips`, `sequences`, `new_effect`, COLOR strips, or `StripTransform`
- Hits `AttributeError: 'SequenceEditor' object has no attribute 'sequences'` on 5.x
- Hits `TypeError` on `new_effect` kwargs (`frame_end` vs `length`)
- Renders a sequencer composite whose COLOR cells ignore `transform.scale_*` after a resolution change

## High-level shape

```python
import bpy

scene = bpy.context.scene
se = scene.sequence_editor or scene.sequence_editor_create()
coll = se.strips if hasattr(se, "strips") else se.sequences

if bpy.app.version >= (5, 0, 0):
    strip = coll.new_effect(
        name="A", type="COLOR", channel=1,
        frame_start=1, length=10,
    )
else:
    strip = coll.new_effect(
        name="A", type="COLOR", channel=1,
        frame_start=1, frame_end=11,
    )
strip.color = (0.85, 0.10, 0.22)
```

Branch on the `bpy.app.version` tuple for known API boundaries (such as the 5.2 COLOR strip `width`/`height` bake), never on `bpy.app.version_string`. Pick the `.strips` vs `.sequences` accessor with `hasattr`, not version: an empty `bpy_prop_collection` is falsy, so `se.strips or se.sequences` silently falls through to the legacy accessor on an empty timeline.

## Accessor: `.strips` vs `.sequences`

| | 4.5 LTS | 5.1 / 5.2+ |
| --- | --- | --- |
| Canonical collection | `.strips` (`.sequences` is a bridge to the same strips) | `.strips` only |
| `.sequences` | Present, same contents as `.strips` | `AttributeError` |

```python
def strips_coll(se):
    return se.strips if hasattr(se, "strips") else se.sequences
```

Do not write `se.sequences` in new code. On 5.x it is gone; on 4.5 `.strips` already exists.

## `new_effect` end kwarg

`strips.new_effect(...)` ends a strip with **one** accepted end argument. The other raises `TypeError`.

```python
span = (1, 33)  # end-exclusive [start, end)

if bpy.app.version >= (5, 0, 0):
    strip = coll.new_effect(
        name="A", type="COLOR", channel=1,
        frame_start=span[0], length=span[1] - span[0],
    )
else:
    strip = coll.new_effect(
        name="A", type="COLOR", channel=1,
        frame_start=span[0], frame_end=span[1],
    )
```

Timeline bounds: `frame_final_start` / `frame_final_end` / `frame_final_duration` on 4.5. On 5.x those names are deprecated aliases (removal announced for 6.0); canonical accessors are `left_handle` / `right_handle` / `duration`. Scene strips take four args — `new_scene(name, scene, channel, frame_start)` — with no `length` / `frame_end` kwarg on either version.

The `TRANSFORM` effect type is removed on 5.x. Place strips with per-strip `strip.transform` (`StripTransform`) on both versions. Effect inputs are `input_1` / `input_2` (creation kwargs `input1` / `input2`).

## COLOR strip intrinsic size (5.2)

4.5 LTS and 5.1 COLOR strips have **no** intrinsic size. `transform.scale_*` is a fraction of the **output frame**. Creating at factory resolution then rendering a tiny buffer is fine.

5.2 and later bake readonly `width` / `height` from **scene render resolution at `new_effect` time**. Scale and offset are then in that **media** space, not a later output size. Set scene resolution **before** building strips.

This split is **not** in the 5.2 `python_api` release notes. Witnessed by [`examples/vse-cut-list/`](https://github.com/TMHSDigital/Blender-Developer-Tools/tree/main/examples/vse-cut-list) `--check-pixels`.

```python
width, height = 96, 54
scene.render.resolution_x = width
scene.render.resolution_y = height

se = scene.sequence_editor or scene.sequence_editor_create()
coll = se.strips if hasattr(se, "strips") else se.sequences

if bpy.app.version >= (5, 0, 0):
    strip = coll.new_effect(
        name="A", type="COLOR", channel=1,
        frame_start=1, length=10,
    )
else:
    strip = coll.new_effect(
        name="A", type="COLOR", channel=1,
        frame_start=1, frame_end=11,
    )

if bpy.app.version >= (5, 2, 0):
    # 5.2+: readonly width/height baked at new_effect from scene.render
    assert (strip.width, strip.height) == (width, height)
    # strip.width = 64  # TypeError — readonly
else:
    # 4.5 / 5.1: no intrinsic size; hasattr(strip, "width") is False
    pass

strip.transform.scale_x = 0.36
strip.transform.scale_y = 0.36
```

Creating at factory 1920×1080 then dropping the scene to 96×54 for a check render makes a 0.36-scaled COLOR cell larger than the output. On 5.2 the long-runner covers the frame; pixel samples read the wrong strip.

A lone COLOR strip **does** honor `transform.scale_*` on 5.2. The break is media size vs a later output size, not "transform is ignored."

## Common AI mistakes

1. **`sequence_editor.sequences` on 5.x.** `AttributeError`. Use `.strips` (with `hasattr` only as a 4.5 bridge).

2. **Wrong `new_effect` end kwarg.** `frame_end=` on 5.x and `length=` on 4.5 both raise `TypeError`.

3. **Creating COLOR strips, then changing render size** (the 5.2 trap):

   ```python
   a = coll.new_effect(...)          # bakes 1920×1080 on 5.2
   scene.render.resolution_x = 96    # output changed; media size did not
   ```

   Set `scene.render.resolution_*` **before** `new_effect`.

4. **`se.strips or se.sequences`.** An empty collection is falsy, so this falls through to `.sequences` on a fresh editor.

5. **`TRANSFORM` effect type on 5.x.** Gone. Use `strip.transform`.

6. **Scene strip pointing at its own scene.** Feedback loop; renders transparent. Source a **separate** scene.

7. **Effect strips consume their inputs** only when stacked on a channel **above** those inputs. Below, the inputs keep compositing independently. A `GAMMA_CROSS` asked to outlast its inputs' overlap is silently clamped to the overlap.

## See also

- Example [`examples/vse-cut-list/`](https://github.com/TMHSDigital/Blender-Developer-Tools/tree/main/examples/vse-cut-list) — accessor rename, `new_effect` kwargs, save/reload, and the 5.2 COLOR size bake (`--check-pixels` asserts `A.width, A.height == render size` on 5.2+).
- Example [`examples/vse-gamma-cross/`](https://github.com/TMHSDigital/Blender-Developer-Tools/tree/main/examples/vse-gamma-cross) — `GAMMA_CROSS` blend curve.
- Audit log: [`docs/technical-audit.md`](https://github.com/TMHSDigital/Blender-Developer-Tools/blob/main/docs/technical-audit.md) § Findings the release notes did not list.

<!-- examples:begin (generated by scripts/build_examples_index.py from examples/skills.json; do not edit) -->
## Runnable examples

Each example runs headless, asserts the contract, and exits non-zero when it breaks. Run one with `blender --background --python <script> --`; pass a falsifier flag to watch the check fail.

- [`vse-cut-list`](https://github.com/TMHSDigital/Blender-Developer-Tools/tree/main/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_*. Falsify: `--swap-inputs` (exit 7).
- [`vse-gamma-cross`](https://github.com/TMHSDigital/Blender-Developer-Tools/tree/main/examples/vse-gamma-cross): The GAMMA_CROSS fade is not the naive linear mix: it blends in a gamma-0.5 space, so the mid-cross dips below the sRGB lerp. Falsify: `--swap-inputs` (exit 4).
- [`vse-linear-modifiers`](https://github.com/TMHSDigital/Blender-Developer-Tools/tree/main/examples/vse-linear-modifiers): Pathology witness for the 5.2 removal of `Strip.use_linear_modifiers`. Falsify: `--assume-present` (exit 4).

<!-- examples:end -->

## References

- `bpy.types.SequenceEditor`: https://docs.blender.org/api/current/bpy.types.SequenceEditor.html
- `bpy.types.Strip` (5.x name of `Sequence`): https://docs.blender.org/api/current/bpy.types.Strip.html
- 4.5 LTS `Sequence`: https://docs.blender.org/api/4.5/bpy.types.Sequence.html
- 4.5 LTS `SequenceEditor`: https://docs.blender.org/api/4.5/bpy.types.SequenceEditor.html
- 5.1 `SequenceEditor`: https://docs.blender.org/api/5.1/bpy.types.SequenceEditor.html

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.