Adjust MiniMah h3 sizing for videos to downscale to match
This commit is contained in:
parent
70b1089359
commit
151ad0e959
|
|
@ -1330,7 +1330,7 @@ class MinimaxH3Ref2VAModel(MinimaxH3Model):
|
|||
blocks = [(1, h, w, 0) for h, w in ref_shapes]
|
||||
audio_rows = []
|
||||
self._append_video_ref_blocks(
|
||||
batch, all_rows, audio_rows, blocks, device, dtype
|
||||
batch, all_rows, audio_rows, blocks, device, dtype, target_h, target_w
|
||||
)
|
||||
if not all_rows:
|
||||
return None, None, (), ()
|
||||
|
|
@ -1364,8 +1364,10 @@ class MinimaxH3Ref2VAModel(MinimaxH3Model):
|
|||
n = packing.align_num_frames_down(max(len(frames), 5))
|
||||
frames = frames[:n]
|
||||
h0, w0 = frames[0].shape[:2]
|
||||
# ComfyUI reference-video sizing (independent of the sample canvas)
|
||||
ph, pw = packing.reference_video_pixel_size(w0, h0)
|
||||
# match the sample canvas's pixel area, own aspect kept
|
||||
ph, pw = packing.reference_video_pixel_size(
|
||||
w0, h0, gen_config.height, gen_config.width
|
||||
)
|
||||
pixels = torch.from_numpy(np.stack(frames)).float() / 255.0 * 2.0 - 1.0
|
||||
pixels = pixels.permute(3, 0, 1, 2)[None] # (1, 3, T, H, W)
|
||||
pixels = (
|
||||
|
|
@ -1405,10 +1407,11 @@ class MinimaxH3Ref2VAModel(MinimaxH3Model):
|
|||
return {"latent": latents[0].float(), "audio_rows": audio_rows}
|
||||
|
||||
def _append_video_ref_blocks(
|
||||
self, batch, all_rows, audio_rows, blocks, device, dtype
|
||||
self, batch, all_rows, audio_rows, blocks, device, dtype, target_h, target_w
|
||||
):
|
||||
# control videos get dataset-identical treatment (frame count, fps,
|
||||
# bucket) and one VAE encode, disk-cached next to the video; the
|
||||
# control videos get the dataset's temporal treatment (frame count,
|
||||
# fps), are area-matched to the target, and get one VAE encode
|
||||
# disk-cached next to the video; the
|
||||
# resulting latents become multi-frame reference blocks packed after
|
||||
# the image references
|
||||
paths_per_item = getattr(batch, "control_video_paths_list", None)
|
||||
|
|
@ -1425,7 +1428,7 @@ class MinimaxH3Ref2VAModel(MinimaxH3Model):
|
|||
auds = []
|
||||
for per_item in paths_per_item:
|
||||
entry = load_ref_video_latent(
|
||||
self, per_item[ref_idx], batch.dataset_config
|
||||
self, per_item[ref_idx], batch.dataset_config, target_h, target_w
|
||||
)
|
||||
lats.append(entry["latent"].to(device, torch.float32))
|
||||
auds.append(entry.get("audio_rows"))
|
||||
|
|
|
|||
|
|
@ -124,16 +124,17 @@ def reference_pixel_size(
|
|||
return height, width
|
||||
|
||||
|
||||
def reference_video_pixel_size(ref_width: int, ref_height: int) -> Tuple[int, int]:
|
||||
"""Reference VIDEO sizing (ComfyUI): the 768-short-edge canvas with the
|
||||
768*1344 area cap, or the native size (rounded to /32) when the source is
|
||||
smaller than that canvas. Returns (height, width)."""
|
||||
ch, cw = resolve_canvas_size(ref_width, ref_height)
|
||||
if ref_width * ref_height < cw * ch:
|
||||
m = CANVAS_MULTIPLE
|
||||
cw = max(m, round(ref_width / m) * m)
|
||||
ch = max(m, round(ref_height / m) * m)
|
||||
return ch, cw
|
||||
def reference_video_pixel_size(
|
||||
ref_width: int, ref_height: int, target_height: int, target_width: int
|
||||
) -> Tuple[int, int]:
|
||||
"""Reference VIDEO sizing: match the TARGET's pixel area with the ref's own
|
||||
aspect kept (same aspect -> exactly the target size; other aspects -> the
|
||||
same pixel budget on the /32 grid). Returns (height, width)."""
|
||||
scale = math.sqrt((target_height * target_width) / float(ref_width * ref_height))
|
||||
m = CANVAS_MULTIPLE
|
||||
height = max(m, round(ref_height * scale / m) * m)
|
||||
width = max(m, round(ref_width * scale / m) * m)
|
||||
return height, width
|
||||
|
||||
|
||||
def prepare_reference_image(
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
"""Reference-video latents for ref2va, without dataloader machinery.
|
||||
|
||||
A control VIDEO gets the dataset's temporal treatment — num_frames /
|
||||
auto_frame_count, fps — and ComfyUI's reference sizing (768-short-edge canvas
|
||||
or native when smaller, aspect kept), then a single VAE encode whose
|
||||
auto_frame_count, fps — and is area-matched to the target (own aspect kept, /32
|
||||
grid), then a single VAE encode whose
|
||||
result is cached next to the video in ``_latent_cache/`` (keyed like normal
|
||||
latent caches: file signature + the config values that shape the latent).
|
||||
Everything is deterministic (even frame spread, no random start) so the cache
|
||||
|
|
@ -112,7 +112,9 @@ def _cache_path(path: str, hash_dict: dict) -> str:
|
|||
|
||||
|
||||
@torch.no_grad()
|
||||
def load_ref_video_latent(model, path: str, dataset_config) -> dict:
|
||||
def load_ref_video_latent(
|
||||
model, path: str, dataset_config, target_height: int, target_width: int
|
||||
) -> dict:
|
||||
"""Returns {"latent": (C, T, h, w) cpu tensor, "num_frames": int},
|
||||
encoding + disk-caching on first use. ``model`` is the MinimaxH3 model
|
||||
(used for the VAE, audio encode and the frame-count snapper)."""
|
||||
|
|
@ -145,7 +147,10 @@ def load_ref_video_latent(model, path: str, dataset_config) -> dict:
|
|||
)
|
||||
hash_dict = {
|
||||
"signature": get_quick_signature_string(path),
|
||||
"ref_sizing": "comfy_canvas",
|
||||
"ref_sizing": "match_target_area",
|
||||
"target_area": int(target_height * target_width)
|
||||
if target_height and target_width
|
||||
else 0,
|
||||
"num_frames": num_frames,
|
||||
"fps": dataset_config.fps,
|
||||
"trim_tail": trim_tail,
|
||||
|
|
@ -164,9 +169,10 @@ def load_ref_video_latent(model, path: str, dataset_config) -> dict:
|
|||
mem_cache[path] = entry
|
||||
return entry
|
||||
|
||||
# ComfyUI reference-video sizing: 768-short-edge canvas (768*1344 area
|
||||
# cap) or native size when smaller; aspect-preserving resize, no crop
|
||||
out_h, out_w = reference_video_pixel_size(src_w, src_h)
|
||||
# match the target's pixel area (the dataset bucket the target trains at)
|
||||
# with the ref's own aspect: same aspect -> identical size; aspect-
|
||||
# preserving resize, no crop
|
||||
out_h, out_w = reference_video_pixel_size(src_w, src_h, target_height, target_width)
|
||||
|
||||
indices = ref_frame_indices(
|
||||
total, src_fps, num_frames, dataset_config.fps, trim_tail
|
||||
|
|
|
|||
|
|
@ -922,7 +922,7 @@ export const modelArchs: ModelArch[] = [
|
|||
<div className="space-y-2">
|
||||
<p>
|
||||
Reference-to-video: control images condition the output as subject/style references (never as a first frame).
|
||||
Reference images keep their aspect and scale down (never up) to the target's pixel area; reference videos use the 768-short-edge canvas (or native size if smaller). Each rides into the packed
|
||||
References keep their own aspect and are matched to the target's pixel area (images scale down only, never up; a same-aspect video reference is exactly the target size). Each rides into the packed
|
||||
sequence as a reference block, and is also shown to the Qwen3-VL conditioner as a{' '}
|
||||
<code><Picture i></code> vision block. Training references come from the dataset control path(s);
|
||||
sampling uses the sample ctrl images — always as references. Image references only for now (no reference
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
VERSION = "0.12.22"
|
||||
VERSION = "0.12.23"
|
||||
|
|
|
|||
Loading…
Reference in New Issue