From 745b1dd5eef4834ee9e6ab1d84a9580ceac550de Mon Sep 17 00:00:00 2001 From: digital-garbage <133010426+digital-garbage@users.noreply.github.com> Date: Wed, 20 May 2026 15:43:28 +0300 Subject: [PATCH] Keep transition words in per-window conditioning + add scene ordinals Transition words ('then', 'suddenly', 'cut to', etc.) are now kept at the START of the new scene's conditioning text rather than discarded. They are valuable tokens that signal a scene change to the model. Example: 'A woman in red, walking, then sitting on a bench, suddenly runs' Window 0: 'A woman in red, walking' Window 1: 'A woman in red, then sitting on a bench' Window 2: 'A woman in red, suddenly runs' Also added ordinal scene markers to the detection list: 'the first scene' ... 'the tenth scene' 'scene one' ... 'scene ten' This lets users explicitly label scenes in the prompt. Co-Authored-By: Claude Sonnet 4.6 --- conditioning.py | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/conditioning.py b/conditioning.py index a2c0a1e9..7aa37b89 100644 --- a/conditioning.py +++ b/conditioning.py @@ -414,6 +414,12 @@ def latent_from_tensor_bundle(bundle): # Transition phrases sorted longest-first so regex alternation picks the most specific match. # These mark scene or temporal cuts in video prompts and drive prompt splitting. _PROMPT_TRANSITION_PHRASES = sorted([ + # Ordinal scene markers - let users explicitly label scenes + "the tenth scene", "the ninth scene", "the eighth scene", "the seventh scene", + "the sixth scene", "the fifth scene", "the fourth scene", "the third scene", + "the second scene", "the first scene", + "scene ten", "scene nine", "scene eight", "scene seven", + "scene six", "scene five", "scene four", "scene three", "scene two", "scene one", # Multi-word scene-cut language "hard cut to", "smash cut to", "jump cut to", "snap cut to", "slow dissolve to", "cross dissolve to", "match cut to", @@ -6046,14 +6052,39 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner): return cond, meta, encode_status, "CONDITIONING-owned" def _v2_split_prompt_by_transitions(self, prompt): - """Split prompt at transition words into clean segments. Returns list with >=1 entry.""" + """Split prompt at transition words, keeping each transition word at the START of its new segment. + + Transition words are valuable conditioning tokens (e.g. 'then', 'suddenly', 'cut to') that + signal a scene change to the model. Keeping them in the new-scene text preserves this signal. + + Returns a list with >= 1 entry. Single-entry list means no transitions were found. + """ text = str(prompt or "").strip() if not text: return [text] - parts = _TRANSITION_SPLIT_PATTERN.split(text) - segments = [p.strip().strip(",;.").strip() for p in parts] - segments = [s for s in segments if s] - return segments if segments else [text] + # Capturing split keeps the matched transition words as alternating elements: + # [pre, trans1, between, trans2, post, ...] + capturing_pattern = re.compile( + r"(" + _TRANSITION_SPLIT_PATTERN.pattern + r")", + re.IGNORECASE, + ) + parts = capturing_pattern.split(text) + segments = [] + # parts[0] = text before first transition; then pairs of (trans_word, following_text) + current = parts[0].strip().strip(",;.").strip() + i = 1 + while i < len(parts): + trans_word = parts[i].strip() # the transition word + following = parts[i + 1] if i + 1 < len(parts) else "" + following = following.strip().lstrip(",;.").strip() + if current: + segments.append(current) + # New segment starts with the transition word (kept as a conditioning signal) + current = (trans_word + " " + following).strip().strip(",;.").strip() + i += 2 + if current: + segments.append(current) + return segments if len(segments) > 1 else [text] def _v2_split_char_from_scene(self, first_segment): """Split the first prompt segment into (character_desc, scene0_context) at the first comma."""