From 22607b0c1434a2bc468b1f482ae2fd7754247364 Mon Sep 17 00:00:00 2001 From: digital-garbage <133010426+digital-garbage@users.noreply.github.com> Date: Mon, 3 Aug 2026 20:04:20 +0300 Subject: [PATCH] refactor: core widget baseline is a values-only file, keyed by core id MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The editor seeded its fixed core nodes from a saved graph dump. Replaced with a small file holding just the widget values the builder consumes — no free text, nothing user-typed, since every text field a run needs arrives from the project at generate time. Graph output verified identical against live object_info. Co-Authored-By: Claude Opus 5 --- .gitignore | 3 + movie_editor/backend/builder.py | 29 ++++---- .../backend/reference/core_widgets.json | 74 +++++++++++++++++++ movie_editor/server.py | 2 +- 4 files changed, 92 insertions(+), 16 deletions(-) create mode 100644 movie_editor/backend/reference/core_widgets.json diff --git a/.gitignore b/.gitignore index 1da88e3f..144b93e8 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,6 @@ refinements/ # Large local research docs *.pdf + +# Never track saved ComfyUI workflow dumps — they carry whatever was typed in the graph. +movie_editor/backend/reference/*.workflow.json diff --git a/movie_editor/backend/builder.py b/movie_editor/backend/builder.py index af0f7a7a..7fb384a3 100644 --- a/movie_editor/backend/builder.py +++ b/movie_editor/backend/builder.py @@ -48,13 +48,6 @@ CORE: dict[str, str] = { "f2i": "LTXFloatToInt", } -# reference-workflow node id per core node (to seed widget values from the user's -# real settings). Missing -> bare object_info / param defaults. -REF_ID: dict[str, int] = { - "studio": 5299, "cond": 5147, "sampler": 5333, "concat": 4528, "separate": 4845, - "audiodec": 5021, "normaudio": 5314, "vhs": 5019, "saveref": 5328, "keyloader": 5303, - "pos": 5012, "neg": 5256, "frames": 4988, "fps": 4989, "f2i": 5145, -} # core internal links: core_id -> {input_name: (src_core_id, output_index)} CORE_LINKS: dict[str, dict[str, tuple[str, int]]] = { @@ -314,19 +307,25 @@ def _widget_choices(node_def: Optional[dict]) -> dict: return out -# ── reference workflow ──────────────────────────────────────────────────────── +# ── core widget baseline ────────────────────────────────────────────────────── def load_reference() -> dict: + """Baseline widget values for the fixed core nodes, keyed by core id — the tuned + settings (sigma schedules, sampler config, container format) the editor starts from + before per-run params are applied. + + Values only: no prompt text, and nothing user-typed. Every text field the run needs + arrives from the project at generate time, so none of it belongs in a checked-in file. + A missing/unreadable file just means each core node falls back to its object_info + defaults. + """ try: - return json.loads((config.REFERENCE_DIR / "montage.workflow.json").read_text()) + data = json.loads((config.REFERENCE_DIR / "core_widgets.json").read_text()) + return data if isinstance(data, dict) else {} except Exception: return {} -def _ref_widgets(ref: dict) -> dict[int, Any]: - return {n.get("id"): n.get("widgets_values") for n in (ref.get("nodes") or [])} - - # ── graph assembly ──────────────────────────────────────────────────────────── def _output_index(node_def: Optional[dict], out_name: str) -> int: @@ -352,7 +351,7 @@ def build(object_info: dict, models_config: dict, params: dict, media: dict | No # build (including the closures below), so every reference downstream is family-aware. family = family_of(models_config) CORE, CORE_LINKS, OPEN_PORTS = family_core(family) - ref_wv = _ref_widgets(load_reference()) + ref_wv = load_reference() graph: dict[str, dict] = {} # `blocking` is the subset of problems that should stop generation (required inputs). report: dict[str, list] = {"wired": [], "auto_wired": [], "ambiguous": [], "unsatisfied": [], "blocking": []} @@ -375,7 +374,7 @@ def build(object_info: dict, models_config: dict, params: dict, media: dict | No for cid, cls in CORE.items(): nd = object_info.get(cls) inputs = _widget_defaults(nd) - inputs.update(extract_widgets(nd, ref_wv.get(REF_ID.get(cid)))) + inputs.update(extract_widgets(nd, ref_wv.get(cid))) for inp, (src, idx) in CORE_LINKS.get(cid, {}).items(): inputs[inp] = [src, idx] protected_edges.add((cid, inp)) diff --git a/movie_editor/backend/reference/core_widgets.json b/movie_editor/backend/reference/core_widgets.json new file mode 100644 index 00000000..86414d74 --- /dev/null +++ b/movie_editor/backend/reference/core_widgets.json @@ -0,0 +1,74 @@ +{ + "cond": [ + 25 + ], + "f2i": [ + 0 + ], + "fps": [ + 30 + ], + "frames": [ + 241, + "fixed" + ], + "keyloader": [ + "tf", + "tf", + true, + "", + "", + "" + ], + "neg": [ + "underwater, diving, slow motion, still image, bad quality, subtitles, text, watermark, overlay, pc game, yelling, console game, childish, ugly, text, blur, logo, wordmark, static, low quality, noise, white noise, bleep, censoring, censor, bleeping, beep, beeping, newscast, interview, podcast, chinese, mutant, horror, 70's, film grain, comedy, stand-up " + ], + "normaudio": [ + -30 + ], + "pos": [ + "" + ], + "sampler": [ + 898993421681879, + "randomize", + 97, + 16, + 1, + 8, + false, + true, + false, + 0.25, + true, + 0.01, + 0, + 0, + 0.025, + 0.05, + "relative" + ], + "saveref": [ + "my_style_v1" + ], + "studio": [ + "Wrong details|loved", + "{\"refinement_key\":\"\",\"overrides\":{\"refinement_key\":false,\"feedback_prompt\":false,\"user_intent_prompt\":false,\"negative_prompt\":false},\"scene_builder\":{\"mode\":\"Pass-through\",\"scene\":\"-None-\",\"scene_name\":\"\",\"aliases\":\"\",\"scene_positive\":\"\",\"scene_negative\":\"\"},\"refiner\":{\"mode\":\"Refine\",\"advisor_mode\":\"Off\",\"advisor_thinking\":false,\"prompt_repair\":false,\"im_feeling_lucky\":false,\"reset_session\":false,\"feedback_prompt\":\"\",\"user_intent_prompt_override\":\"\",\"negative_prompt\":\"\",\"temporal_style\":\"accelerate\",\"split_by_transitions\":true,\"split_transition_placement\":\"start\",\"reference_injection\":false,\"vision_conditioning\":false,\"value_guidance\":true,\"steer_mode\":\"both\",\"absolute_strength\":0.3,\"latent_value_guidance\":true,\"transition_contrast\":1.5,\"batch_variants\":1,\"batch_mode\":\"Interactive Guessing\",\"batch_learning\":true,\"guess_mode\":false,\"guess_direction\":\"up\",\"guess_range\":1.2,\"guess_freeze_seed\":false},\"advisor_llm\":{\"enabled\":false,\"model_path\":\"huihui-ai/Huihui-Qwen3-8B-abliterated-v2\",\"dtype\":\"bfloat16\"},\"loras\":[],\"loras_config\":{\"mode\":\"ltx2\",\"per_block\":false},\"samplers\":{\"high\":{\"type\":\"Normalizing\",\"sigmas\":\"1.0, 0.99375, 0.9875, 0.98125, 0.975, 0.909375, 0.725, 0.421875, 0.0\",\"hybrid\":{\"eta\":1,\"eta_final\":1,\"normalize_strength\":1,\"normalize_start_sigma\":0.9,\"s_noise\":1,\"high_quality_pct\":0.5,\"correction_blend\":0.25,\"quality_sharpness\":0.3,\"motion_pulse_mode\":\"off\",\"motion_pulse_start_pct\":0.5,\"motion_pulse_count\":4,\"motion_pulse_spacing_pct\":0.22,\"motion_pulse_strength\":0.85,\"velocity_bias_mode\":\"capture\",\"velocity_bias_strength\":0.1,\"velocity_bias_source\":\"mean\",\"velocity_refinement_key\":\"\",\"rescue_mode\":false,\"rescue_threshold\":0.7,\"rescue_strength\":0.15,\"velocity_aspect_bucket\":\"any\",\"variability\":0},\"distilled\":{\"order\":1,\"final_correction_steps\":3,\"ab2_ramp\":false,\"normalize_strength\":0.5,\"normalize_start_sigma\":0.9,\"s_noise\":0,\"velocity_bias_mode\":\"capture\",\"velocity_bias_strength\":0.1,\"velocity_bias_source\":\"mean\",\"velocity_refinement_key\":\"\",\"rescue_mode\":false,\"rescue_threshold\":0.15,\"rescue_strength\":0.2},\"normalizing\":{\"normalize_strength\":0.5,\"normalize_start_sigma\":0.9,\"velocity_bias_mode\":\"capture_and_apply\",\"velocity_bias_strength\":0.1,\"velocity_bias_source\":\"mean\",\"velocity_refinement_key\":\"\",\"rescue_mode\":false,\"rescue_threshold\":0.15,\"rescue_strength\":0.2},\"ksampler_name\":\"ddim\"},\"low\":{\"type\":\"Distilled Flow\",\"sigmas\":\"0.909375, 0.725, 0.421875, 0.0\",\"hybrid\":{\"eta\":1,\"eta_final\":1,\"normalize_strength\":0,\"normalize_start_sigma\":0.9,\"s_noise\":1,\"high_quality_pct\":0.35,\"correction_blend\":1,\"quality_sharpness\":0,\"motion_pulse_mode\":\"off\",\"motion_pulse_start_pct\":0.3,\"motion_pulse_count\":2,\"motion_pulse_spacing_pct\":0.22,\"motion_pulse_strength\":0.85,\"velocity_bias_mode\":\"off\",\"velocity_bias_strength\":0,\"velocity_bias_source\":\"mean\",\"velocity_refinement_key\":\"default\",\"rescue_mode\":false,\"rescue_threshold\":0.15,\"rescue_strength\":0.2,\"velocity_aspect_bucket\":\"any\"},\"distilled\":{\"order\":1,\"final_correction_steps\":1,\"ab2_ramp\":false,\"normalize_strength\":0,\"normalize_start_sigma\":0.9,\"s_noise\":0,\"velocity_bias_mode\":\"off\",\"velocity_bias_strength\":0,\"velocity_bias_source\":\"mean\",\"velocity_refinement_key\":\"default\",\"rescue_mode\":false,\"rescue_threshold\":0.15,\"rescue_strength\":0.2},\"normalizing\":{\"normalize_strength\":0.5,\"normalize_start_sigma\":0.9,\"velocity_bias_mode\":\"off\",\"velocity_bias_strength\":0,\"velocity_bias_source\":\"mean\",\"velocity_refinement_key\":\"default\",\"rescue_mode\":false,\"rescue_threshold\":0.15,\"rescue_strength\":0.2},\"ksampler_name\":\"euler\"}}}", + "[]", + null, + "funpack_studio_open", + "funpack_studio_open", + "funpack_studio_batch" + ], + "vhs": { + "crf": 22, + "filename_prefix": "result_%date:MM-dd_hh-mm-ss%", + "format": "video/h265-mp4", + "frame_rate": 30, + "loop_count": 0, + "pingpong": false, + "pix_fmt": "yuv420p", + "save_metadata": false, + "save_output": false + } +} diff --git a/movie_editor/server.py b/movie_editor/server.py index f1f422e8..7e0b616e 100644 --- a/movie_editor/server.py +++ b/movie_editor/server.py @@ -1235,7 +1235,7 @@ if web is not None and PromptServer is not None: "ok": True, "comfy_url": config.comfy_base_url(), "template_exists": config.TEMPLATE_PATH.is_file(), - "reference_loaded": bool(builder.load_reference().get("nodes")), + "reference_loaded": bool(builder.load_reference()), "configured_slots": len(nodes.load_models().get("slots", [])), })