From 60156de67a0d711c0b45348de5462efea2db4201 Mon Sep 17 00:00:00 2001 From: digital-garbage <133010426+digital-garbage@users.noreply.github.com> Date: Tue, 13 Oct 2026 04:31:03 +0300 Subject: [PATCH] feat: more cut variants, only the phrases the MiniMax-H3 guide approves (camera/shot cuts, transitions, changes, switches) Co-Authored-By: Claude Haiku 5.5 --- modules/conditioning/shot_camera/engine.py | 12 ++++++++++-- .../shot_camera/tests/test_cut_openers.py | 14 ++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 modules/conditioning/shot_camera/tests/test_cut_openers.py diff --git a/modules/conditioning/shot_camera/engine.py b/modules/conditioning/shot_camera/engine.py index c91c5ba8..d86c3b62 100644 --- a/modules/conditioning/shot_camera/engine.py +++ b/modules/conditioning/shot_camera/engine.py @@ -601,8 +601,16 @@ def add_camera_moves(text, seed=None, chance=1.0, prior=None, choices=None, arms # a view and a focus. Never inside one shortcut. Nothing in a prompt knows the video's # length, so the caller hands it in (seconds). STAMP = re.compile(r"\b\d\d:\d\d\.\d{3}\b") -CUT_OPENERS = ("the camera cuts to a new angle", "the shot transitions to the next moment", - "the shot changes to a new view", "the shot switches to what follows") +# The official MiniMax-H3 guide (docs/VIDEO_PROMPT_WRITING_GUIDE_base_en.md) approves these ordinary cut phrases. +# Dissolve, fade and wipe are for when the user asks for them, never default. +# Each cut says what is new: a new angle, place, subject, viewpoint, state or moment. Only these four verbs. +CUT_OPENERS = ("the camera cuts to a new angle", "the camera cuts to a closer view", + "the shot cuts to a new angle", "the shot cuts to a new location", "the shot cuts to a later moment", + "the shot transitions to the next moment", "the shot transitions to a new location", + "the shot transitions to a new point of view", + "the shot changes to a new view", "the shot changes to a different subject", + "the shot changes to a new state of the scene", + "the shot switches to what follows", "the shot switches to a wider view") LEAD_CUT = re.compile(r"^\s*(?:the\s+)?(?:camera|shot)\s+(?:cuts|transitions|changes|switches)\s+to\b", re.I) MIN_SHOT_SECONDS = 2 diff --git a/modules/conditioning/shot_camera/tests/test_cut_openers.py b/modules/conditioning/shot_camera/tests/test_cut_openers.py new file mode 100644 index 00000000..eebc6d9e --- /dev/null +++ b/modules/conditioning/shot_camera/tests/test_cut_openers.py @@ -0,0 +1,14 @@ +"""Every cut opener is a hard cut that reads as a cut, never as a camera move.""" + +import re + +from .. import engine + + +def test_every_opener_is_a_hard_cut_and_no_opener_reads_as_a_camera_move(): + for opener in engine.CUT_OPENERS: + assert not engine.CAMERA.search(opener), opener + assert not any(w in opener for w in ("dissolve", "fade", "wipe")), opener + assert engine.CUT.search(opener), opener + assert re.search(r"\b(?:cuts|transitions|changes|switches) to\b", opener), opener +