multimodalart's picture
multimodalart HF Staff
Initial GreenWAM demo
a1833c8 verified
Raw History Blame Contribute Delete
9.97 kB
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: OpenMDW-1.1
import math
import re
from typing import List, Tuple
IMAGE_RES_SIZE_INFO: dict[str, dict[str, tuple[int, int]]] = {
# Our desired 256 resolution is the one below (commented).
# Desired: "256": {"1,1": (336, 336), "4,3": (384, 288), "3,4": (288, 384), "16,9": (448, 256), "9,16": (256, 448)},
"256": {
"1,1": (256, 256),
"4,3": (320, 256),
"3,4": (256, 320),
"16,9": (320, 192),
"9,16": (192, 320),
},
"480": {"1,1": (640, 640), "4,3": (736, 544), "3,4": (544, 736), "16,9": (832, 480), "9,16": (480, 832)},
# 704 resolutions are nicely divisible by 32
"704": {"1,1": (960, 960), "4,3": (1088, 832), "3,4": (832, 1088), "16,9": (1280, 704), "9,16": (704, 1280)},
"720": {"1,1": (960, 960), "4,3": (1104, 832), "3,4": (832, 1104), "16,9": (1280, 720), "9,16": (720, 1280)},
# 768 for arena.ai
"768": {"1,1": (1024, 1024), "4,3": (1184, 880), "3,4": (880, 1184), "16,9": (1360, 768), "9,16": (768, 1360)},
"1080": {"1,1": (1440, 1440), "4,3": (1664, 1248), "3,4": (1248, 1664), "16,9": (1920, 1080), "9,16": (1080, 1920)},
"1280": {"1,1": (1712, 1712), "4,3": (1968, 1472), "3,4": (1472, 1968), "16,9": (2272, 1280), "9,16": (1280, 2272)},
"2048": {
"1,1": (2728, 2728),
"4,3": (3160, 2368),
"3,4": (2368, 3160),
"16,9": (3640, 2048),
"9,16": (2048, 3640),
},
"gt_2048": {
"1,1": (5464, 5464),
"4,3": (6304, 4728),
"3,4": (4728, 6304),
"16,9": (7280, 4096),
"9,16": (4096, 7280),
},
}
VIDEO_RES_SIZE_INFO: dict[str, dict[str, tuple[int, int]]] = {
# Our desired 256 resolution is the one below (commented).
# Desired: "256": {"1,1": (336, 336), "4,3": (384, 288), "3,4": (288, 384), "16,9": (448, 256), "9,16": (256, 448)},
"256": {
"1,1": (256, 256),
"4,3": (320, 256),
"3,4": (256, 320),
"16,9": (320, 192),
"9,16": (192, 320),
},
# "2,3" (h/w=1.5, W:H=2:3): added for the BEHAVIOR-1K R1Pro concat_view composite
# (native 1080x720), so it snaps to an exact-aspect 512x768 canvas with no
# reflection padding. Scoped to the 480 tier that b1k trains at.
"480": {
"1,1": (640, 640),
"4,3": (736, 544),
"3,4": (544, 736),
"16,9": (832, 480),
"9,16": (480, 832),
"2,3": (512, 768),
},
# 704 resolutions are nicely divisible by 32
"704": {"1,1": (960, 960), "4,3": (1088, 832), "3,4": (832, 1088), "16,9": (1280, 704), "9,16": (704, 1280)},
"720": {"1,1": (960, 960), "4,3": (1104, 832), "3,4": (832, 1104), "16,9": (1280, 720), "9,16": (720, 1280)},
# 768 for arena.ai
"768": {"1,1": (1024, 1024), "4,3": (1184, 880), "3,4": (880, 1184), "16,9": (1360, 768), "9,16": (768, 1360)},
"1080": {"1,1": (1440, 1440), "4,3": (1664, 1248), "3,4": (1248, 1664), "16,9": (1920, 1080), "9,16": (1080, 1920)},
"1280": {"1,1": (1712, 1712), "4,3": (1968, 1472), "3,4": (1472, 1968), "16,9": (2272, 1280), "9,16": (1280, 2272)},
"2048": {
"1,1": (2728, 2728),
"4,3": (3160, 2368),
"3,4": (2368, 3160),
"16,9": (3640, 2048),
"9,16": (2048, 3640),
},
"gt_2048": {
"1,1": (5464, 5464),
"4,3": (6304, 4728),
"3,4": (4728, 6304),
"16,9": (7280, 4096),
"9,16": (4096, 7280),
},
}
def get_aspect_ratios_from_wdinfos(wdinfos: list[str]) -> list[str]:
aspect_ratios = []
for wdinfo in wdinfos:
aspect_ratio_match = re.search(r"aspect_ratio_(\d+_\d+)", wdinfo)
aspect_ratios.append(aspect_ratio_match.group(1))
return aspect_ratios
def get_wdinfos_w_aspect_ratio(wdinfos: list[str]) -> List[Tuple[str, str]]:
aspect_ratios = get_aspect_ratios_from_wdinfos(wdinfos)
# return a list of (wdinfo_path, aspect_ratio) pairs
return [(wdinfo, aspect_ratio.replace("_", ",")) for wdinfo, aspect_ratio in zip(wdinfos, aspect_ratios)]
def parse_frame_range_from_wdinfo(wdinfo: str) -> tuple[int, int | float] | None:
"""
Parse frame range from wdinfo path.
Args:
wdinfo: wdinfo path string containing a frames_X_Y pattern, where Y may be ``inf``
Returns:
Tuple of (min_frames, max_frames) if found, where max_frames is
``math.inf`` for unbounded ``frames_X_inf`` and ``frames_gt_X`` buckets.
``frames_gt_X`` is treated as starting at X. Returns None if no frame
range is present.
Example:
>>> parse_frame_range_from_wdinfo("wdinfo/v4/tv_drama/resolution_720/aspect_ratio_16_9/frames_300_400/wdinfo.json")
(300, 400)
>>> parse_frame_range_from_wdinfo("wdinfo/v4/tv_drama/resolution_720/aspect_ratio_16_9/frames_3700_inf/wdinfo.json")
(3700, inf)
"""
match = re.search(r"frames_(\d+)_(\d+|inf)(?!\w)", wdinfo)
if match:
max_frames = math.inf if match.group(2) == "inf" else int(match.group(2))
return (int(match.group(1)), max_frames)
match = re.search(r"frames_gt_(\d+)", wdinfo)
if match:
# Wdinfo generation uses frames_gt_X for the bucket that starts at X, so treat it as >= X.
return (int(match.group(1)), math.inf)
return None
def normalize_skip_frame_ranges(
skip_frame_range: str | list[str] | None,
) -> set[tuple[int, int | float]]:
"""Normalize ``skip_frame_range`` into a set of (min_frames, max_frames) buckets.
Args:
skip_frame_range: A single bucket string like ``"300_400"`` or ``"3700_inf"``,
a list of such strings, or None. Each string identifies the frame-range
bucket (e.g. ``frames_300_400``) that should be skipped.
Returns:
Set of (min_frames, max_frames) tuples to skip. An ``inf`` upper bound is
represented by ``math.inf``. Empty if ``skip_frame_range`` is None.
"""
if skip_frame_range is None:
return set()
if isinstance(skip_frame_range, str):
skip_frame_range = [skip_frame_range]
skip_buckets: set[tuple[int, int | float]] = set()
for bucket in skip_frame_range:
match = re.fullmatch(r"(\d+)_(\d+|inf)", bucket.strip())
if match is None:
raise ValueError(
f"Invalid skip_frame_range entry {bucket!r}. "
"Expected the form '<min>_<max>', e.g. '300_400' or '3700_inf'."
)
max_frames = math.inf if match.group(2) == "inf" else int(match.group(2))
skip_buckets.add((int(match.group(1)), max_frames))
return skip_buckets
def filter_wdinfos_by_frame_range(
wdinfos: list[str],
min_frames: int | None = None,
max_frames: int | None = None,
skip_frame_range: str | list[str] | None = None,
) -> list[str]:
"""
Filter wdinfo files based on frame range.
The frame range in wdinfo path (e.g., frames_300_400) represents videos
with frames between those values. This function filters wdinfo files
based on the wdinfo's upper bound (wdinfo_max):
- min_frames is EXCLUSIVE: wdinfo_max must be > min_frames
- max_frames is INCLUSIVE: wdinfo_max must be <= max_frames
- an ``inf`` upper bound is treated as infinity and excluded by any finite max_frames
Additionally, any wdinfo whose frame-range bucket matches an entry in
``skip_frame_range`` is excluded.
Args:
wdinfos: List of wdinfo paths
min_frames: Minimum number of frames (exclusive). If None, no lower bound.
max_frames: Maximum number of frames (inclusive). If None, no upper bound.
skip_frame_range: Frame-range bucket(s) to exclude, e.g. ``"300_400"`` to
drop the ``frames_300_400`` bucket or ``"3700_inf"`` to drop the
``frames_3700_inf`` bucket. Accepts a single string or a list of strings.
If None, no bucket is skipped.
Returns:
Filtered list of wdinfo paths
Example:
>>> wdinfos = [
... "wdinfo/frames_400_500/wdinfo.json",
... "wdinfo/frames_500_600/wdinfo.json",
... "wdinfo/frames_600_700/wdinfo.json",
... ]
>>> filter_wdinfos_by_frame_range(wdinfos, min_frames=500, max_frames=600)
['wdinfo/frames_500_600/wdinfo.json']
# frames_400_500 excluded because wdinfo_max (500) <= min_frames (500)
# frames_500_600 included because wdinfo_max (600) > min_frames (500) AND <= max_frames (600)
# frames_600_700 excluded because wdinfo_max (700) > max_frames (600)
>>> filter_wdinfos_by_frame_range(wdinfos, skip_frame_range="500_600")
['wdinfo/frames_400_500/wdinfo.json', 'wdinfo/frames_600_700/wdinfo.json']
# frames_500_600 excluded because its bucket matches skip_frame_range
"""
skip_buckets = normalize_skip_frame_ranges(skip_frame_range)
if min_frames is None and max_frames is None and not skip_buckets:
return wdinfos
filtered = []
for wdinfo in wdinfos:
frame_range = parse_frame_range_from_wdinfo(wdinfo)
if frame_range is None:
# If no frame range in path, include by default
filtered.append(wdinfo)
continue
wdinfo_min, wdinfo_max = frame_range
# Skip explicitly excluded buckets (matched on the full (min, max) bucket).
if (wdinfo_min, wdinfo_max) in skip_buckets:
continue
# Filter based on wdinfo's upper bound (wdinfo_max):
# - min_frames is exclusive: wdinfo_max must be > min_frames
# - max_frames is inclusive: wdinfo_max must be <= max_frames
include = True
if min_frames is not None and wdinfo_max <= min_frames:
include = False
if max_frames is not None and wdinfo_max > max_frames:
include = False
if include:
filtered.append(wdinfo)
return filtered