Harden H3 detail-pass cleanup

This commit is contained in:
2026-09-03 07:18:13 +00:00
parent ab6ba86d76
commit 769257513b
2 changed files with 133 additions and 27 deletions
+32 -27
View File
@@ -6461,36 +6461,41 @@ class H3LongVideos:
raise
refined_out = out
detail_pass = _coerce_bool_flag(detail_pass)
if detail_pass:
detail_latent = _latent_with_replaced_samples(latent, out)
try:
detail_start = time.perf_counter()
(refined_out,) = nodes.common_ksampler(
if detail_pass:
detail_latent = _latent_with_replaced_samples(latent, out)
try:
detail_start = time.perf_counter()
(refined_out,) = nodes.common_ksampler(
model, seed, int(detail_steps), cfg, detail_sampler_name, detail_scheduler,
positive, negative, detail_latent, denoise=float(detail_denoise))
timing["detail_sample"] += time.perf_counter() - detail_start
except Exception as e:
if _is_oom(e):
e._h3_stage = "sampling"
raise
refined_out = _video_only_refined_latent(out, refined_out)
# Keep a CPU copy of the sampled latent BEFORE decoding, for the `latent`
# output. Latents are ~1000x smaller than the frames they decode to (a
# 1344x768 124f shot is ~1.5MB against ~1.5GB), so carrying one per shot for
# the whole chain is free. Detached and moved off the card immediately, for
# the same reason the decoded frames are.
decode_video_start = time.perf_counter()
shot_latent = _copy_sample_latent(refined_out)
video = _decode_video(vae, refined_out, tiled, free_first=model,
tile_t=decode_tile_frames, tile_xy=decode_tile_size)
timing["decode_video"] += time.perf_counter() - decode_video_start
decode_audio_start = time.perf_counter()
audio = _decode_audio(audio_vae, out)
timing["decode_audio"] += time.perf_counter() - decode_audio_start
cleanup_start = time.perf_counter()
del out, refined_out, positive, latent
_deep_cleanup()
timing["cleanup"] += time.perf_counter() - cleanup_start
except Exception as e:
if _is_oom(e):
e._h3_stage = "sampling"
raise
refined_out = _video_only_refined_latent(out, refined_out)
del detail_latent
# Keep a CPU copy of the sampled latent BEFORE decoding, for the `latent`
# output. Latents are ~1000x smaller than the frames they decode to (a
# 1344x768 124f shot is ~1.5MB against ~1.5GB), so carrying one per shot for
# the whole chain is free. Detached and moved off the card immediately, for
# the same reason the decoded frames are.
decode_video_start = time.perf_counter()
shot_latent = _copy_sample_latent(refined_out)
decode_audio_start = time.perf_counter()
audio = _decode_audio(audio_vae, out)
timing["decode_audio"] += time.perf_counter() - decode_audio_start
# Audio is much smaller than the video decode. Drop the first-pass
# conditioning before the VAE work so the optional detail pass does not
# keep both sampled latents resident across the heaviest allocation.
del out, positive, latent
video = _decode_video(vae, refined_out, tiled, free_first=model,
tile_t=decode_tile_frames, tile_xy=decode_tile_size)
timing["decode_video"] += time.perf_counter() - decode_video_start
cleanup_start = time.perf_counter()
del refined_out
_deep_cleanup()
timing["cleanup"] += time.perf_counter() - cleanup_start
if timing_sink is not None:
timing["total"] = sum(timing.values())
timing_sink.append(timing)