From f513d485a9914fca54248c5f8feda23148ab2cde Mon Sep 17 00:00:00 2001 From: digital-garbage <133010426+digital-garbage@users.noreply.github.com> Date: Sun, 21 Jun 2026 18:05:35 +0300 Subject: [PATCH] opencut_ui: surface score_slider (FreeSliders) in Engine Settings The Chain Sampler's Guidance section already exposes embed_guidance via the sampler-knob path; add its score-space sibling the same way. Two new knobs in SAMPLER_KNOBS (score_slider bool, score_slider_strength eta 0-3, dependsOn the toggle) listed in the chain_guid section beside embed_guidance. Flows through the existing sampler_inputs path (setSamplerInput -> _run_sampler_inputs -> builder -> Chain Sampler node); refinement_key_input is already wired, so no backend change. BachVid + KV-Lock need no UI (automatic, ride the refinement key). Test: score_slider sampler_inputs pass through _run_sampler_inputs untouched. Co-Authored-By: Claude Opus 4.8 --- movie_editor/frontend/engine_settings.js | 4 +++- movie_editor/tests/test_server.py | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/movie_editor/frontend/engine_settings.js b/movie_editor/frontend/engine_settings.js index f2ac0908..cb1d651c 100644 --- a/movie_editor/frontend/engine_settings.js +++ b/movie_editor/frontend/engine_settings.js @@ -189,6 +189,8 @@ { name: "embed_guidance", label: "Embed guidance", kind: "bool", default: false }, { name: "embed_guidance_source", label: "Embed mode", kind: "combo", choices: ["relative", "absolute"], default: "relative", dependsOn: "embed_guidance" }, { name: "embed_guidance_strength", label: "Embed strength", kind: "float", default: 0.02, min: 0.005, max: 0.1, step: 0.005, dependsOn: "embed_guidance" }, + { name: "score_slider", label: "Score slider", kind: "bool", default: false }, + { name: "score_slider_strength", label: "Slider strength (eta)", kind: "float", default: 1.0, min: 0, max: 3, step: 0.25, dependsOn: "score_slider" }, { name: "decode_noise_scale", label: "Decode noise scale", kind: "float", default: 0.0, min: 0, max: 1, step: 0.01 }, { name: "decode_timestep", label: "Decode timestep", kind: "float", default: 0.05, min: 0, max: 1, step: 0.01 }, { name: "decode_tile_size", label: "Decode tile size", kind: "int", default: 0, min: 0, max: 4096, step: 64 }, @@ -332,7 +334,7 @@ { id: "chain_auto", title: "Auto continuity", defaultOpen: true, knobs: [] }, { id: "chain_timing", title: "Timing", defaultOpen: false, knobs: ["frame_overlap", "transition_duration", "use_same_seed"] }, { id: "chain_cont", title: "Manual continuity", defaultOpen: false, knobs: ["carry_i2v_guides"] }, - { id: "chain_guid", title: "Guidance", defaultOpen: false, knobs: ["cfg", "embed_guidance", "embed_guidance_source", "embed_guidance_strength"] }, + { id: "chain_guid", title: "Guidance", defaultOpen: false, knobs: ["cfg", "embed_guidance", "embed_guidance_source", "embed_guidance_strength", "score_slider", "score_slider_strength"] }, { id: "chain_dec", title: "Decode", defaultOpen: false, knobs: ["decode_noise_scale", "decode_timestep", "decode_tile_size"] }, { id: "chain_exp", title: "Experimental", defaultOpen: false, knobs: ["mid_scene_guide", "mid_scene_guide_strength"] }, ]; diff --git a/movie_editor/tests/test_server.py b/movie_editor/tests/test_server.py index fde7b429..68841dce 100644 --- a/movie_editor/tests/test_server.py +++ b/movie_editor/tests/test_server.py @@ -185,6 +185,21 @@ def test_studio_inputs_skips_custom_conditioning(): assert _run_studio_inputs(p, p.scenes) == {} +def test_score_slider_sampler_inputs_pass_through(): + # FreeSliders score_slider is a plain sampler knob (like embed_guidance): the editor + # sets it in sampler_inputs and _run_sampler_inputs must carry it through untouched + # so builder.py can stamp it onto the Chain Sampler node. + full = _project( + scenes=[{"id": "s1", "text": "a"}, {"id": "s2", "text": "b", "source": {"type": "carry"}}], + sampler_inputs={"score_slider": True, "score_slider_strength": 2.0, + "embed_guidance_source": "relative"}, + ) + samp = _run_sampler_inputs(full, 2, full=full) + assert samp["score_slider"] is True + assert samp["score_slider_strength"] == 2.0 + assert samp["embed_guidance_source"] == "relative" + + def test_shortcut_seed_uses_sampler_inputs(): p = _project([], sampler_inputs={"seed": 4242}) assert _shortcut_seed(p) == 4242