From 293dbd11d5f7e596baa7fd8306730f5953a55e33 Mon Sep 17 00:00:00 2001 From: digital-garbage <133010426+digital-garbage@users.noreply.github.com> Date: Wed, 1 Jul 2026 17:02:13 +0300 Subject: [PATCH] distilled flow: port quality_sharpness unsharp mask from Hybrid Euler 2S MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The free video-only unsharp-on-x0 sharpening (temporal high-pass between consecutive denoised predictions, no extra model eval) only existed on Hybrid Euler 2S. Distilled Flow — the recommended sampler for this pipeline (deterministic, clean audio) — had no equivalent, so the "quality phase" of the actual production sampler had no sharpening path at all. Ports the same _apply_quality_sharpness call into sample_funpack_distilled_flow, gated to the existing final-correction (Heun) steps. Threaded through FunPackDistilledFlowSampler's INPUT_TYPES/get_sampler, Studio's _build_one_sampler, and the Editor's sampler_panel.js Distilled Flow section — verified live end-to-end (UI -> studio_settings JSON -> backend build call). --- conditioning.py | 1 + movie_editor/frontend/sampler_panel.js | 6 +++++- samplers.py | 20 ++++++++++++++++++-- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/conditioning.py b/conditioning.py index 4e839523..ba1cb550 100644 --- a/conditioning.py +++ b/conditioning.py @@ -14674,6 +14674,7 @@ class FunPackStudio: mg_strength=float(dc.get("mg_strength", 0.5)), mg_decay=float(dc.get("mg_decay", 0.5)), mg_sigma_threshold=float(dc.get("mg_sigma_threshold", 0.975)), + quality_sharpness=float(dc.get("quality_sharpness", 0.0)), sigmas=sigmas_raw, ) elif sampler_type == "KSampler": diff --git a/movie_editor/frontend/sampler_panel.js b/movie_editor/frontend/sampler_panel.js index 4a139202..b246138d 100644 --- a/movie_editor/frontend/sampler_panel.js +++ b/movie_editor/frontend/sampler_panel.js @@ -25,7 +25,7 @@ function defaultDistilled() { return { - order: 2, final_correction_steps: 1, ab2_ramp: false, + order: 2, final_correction_steps: 1, ab2_ramp: false, quality_sharpness: 0.0, normalize_strength: 0.0, normalize_start_sigma: 0.9, s_noise: 0.0, velocity_bias_mode: "off", velocity_bias_strength: 0.0, velocity_bias_source: "mean", velocity_refinement_key: "default", @@ -251,6 +251,10 @@ row(container, "final correction steps", intCtrl(dc.final_correction_steps, 0, 3, dk + "-dfcs", (v) => { dc.final_correction_steps = v; save(); })); + row(container, "quality sharpness", + numCtrl(dc.quality_sharpness, 0, 1, 0.01, dk + "-dqs", + (v) => { dc.quality_sharpness = v; save(); })); + hint(container, "Free unsharp mask on the final-correction steps only (needs final correction steps > 0). 0 = off, 0.2-0.4 typical."); row(container, "s_noise", numCtrl(dc.s_noise, 0, 0.5, 0.01, dk + "-dsn", (v) => { dc.s_noise = v; save(); })); diff --git a/samplers.py b/samplers.py index 5caa12e9..830e2ccb 100644 --- a/samplers.py +++ b/samplers.py @@ -1695,7 +1695,8 @@ def sample_funpack_distilled_flow(model, x, sigmas, extra_args=None, callback=No rescue_prompt_sig=None, alg_enabled=False, alg_strength=2.0, alg_sigma_threshold=0.975, alg_guide_tail_frames=0, - mg_enabled=False, mg_strength=0.5, mg_decay=0.5, mg_sigma_threshold=0.975): + mg_enabled=False, mg_strength=0.5, mg_decay=0.5, mg_sigma_threshold=0.975, + quality_sharpness=0.0): """ ODE sampler for distilled few-step video models (e.g. LTX2.3 distilled LoRA). @@ -1729,6 +1730,9 @@ def sample_funpack_distilled_flow(model, x, sigmas, extra_args=None, callback=No the complementary window to ALG's blur, which only acts above its threshold. The EMA itself accumulates every step (free) so it has real history by the time it starts being applied; only the application is gated. Audio is never touched (video-only). + - Optional quality_sharpness: temporal-average unsharp on the x0 prediction, applied only + during the final Heun-correction steps (same mechanism as the Hybrid Euler 2S sampler's + quality-phase sharpening, ported here). Free (no extra model eval), video-only. """ extra_args = {} if extra_args is None else extra_args seed = extra_args.get("seed", None) @@ -1837,6 +1841,11 @@ def sample_funpack_distilled_flow(model, x, sigmas, extra_args=None, callback=No source=velocity_bias_source, ), denoised, video_mask) + # Restore high-frequency detail during the final Heun-correction steps (free, + # video-only) — same unsharp mechanism as the Hybrid Euler 2S sampler. + if i >= correction_start_idx: + denoised = _video_only(_apply_quality_sharpness(denoised, prev_denoised, quality_sharpness), denoised, video_mask) + # Video-only latent normalization (opt-in, anti-overbake) — stacks on top of the ODE. denoised = _normalize_video_denoised( denoised, video_mask, sigma, ref_scale, normalize_strength, normalize_start_sigma, @@ -2013,6 +2022,11 @@ class FunPackDistilledFlowSampler: "default": 0.975, "min": 0.5, "max": 0.999, "step": 0.005, "tooltip": "Momentum guidance applies while sigma is BELOW this value (the opposite window from alg_sigma_threshold) — defaults to the same boundary as ALG for a clean handoff. Only used when mg_enabled.", }), + # Appended last on purpose, same rule as ab2_ramp above. + "quality_sharpness": ("FLOAT", { + "default": 0.0, "min": 0.0, "max": 1.0, "step": 0.01, + "tooltip": "Restores fine detail via temporal-average unsharp on the x0 prediction, applied only during the final Heun-correction steps (final_correction_steps > 0 required to have any effect). 0 disables. 0.2-0.4 typical. Free (no extra model eval), video-only.", + }), } } @@ -2036,7 +2050,8 @@ class FunPackDistilledFlowSampler: rescue_prompt_sig=None, sigmas=None, ab2_ramp=False, normalize_strength=0.0, normalize_start_sigma=0.9, alg_enabled=False, alg_strength=2.0, alg_sigma_threshold=0.975, - mg_enabled=False, mg_strength=0.5, mg_decay=0.5, mg_sigma_threshold=0.975): + mg_enabled=False, mg_strength=0.5, mg_decay=0.5, mg_sigma_threshold=0.975, + quality_sharpness=0.0): prepared_sigmas = sigmas.detach().clone() if isinstance(sigmas, torch.Tensor) else sigmas sampler = comfy.samplers.KSAMPLER( sample_funpack_distilled_flow, @@ -2062,6 +2077,7 @@ class FunPackDistilledFlowSampler: "mg_strength": mg_strength, "mg_decay": mg_decay, "mg_sigma_threshold": mg_sigma_threshold, + "quality_sharpness": quality_sharpness, } ) return (sampler, prepared_sigmas)