Fast_deploy / ComfyUI-MiniMaxH3-Context-Loop /tests /_masked_bridge_unit_test.py
dzmdd's picture
Upload folder using huggingface_hub (part 2)
bc50ea0 verified
Raw History Blame Contribute Delete
5.94 kB
#!/usr/bin/env python3
"""CPU regression for the two-ended H3 AV bridge target and masks."""
import importlib.util
import os
import sys
import types
import torch
import torch.nn.functional as functional
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
PACKAGE = "h3_bridge_test_pkg"
class NestedTensor:
def __init__(self, parts):
self.parts = tuple(parts)
def unbind(self):
return self.parts
def _install_stubs():
package = types.ModuleType(PACKAGE)
package.__path__ = [ROOT]
sys.modules[PACKAGE] = package
comfy = types.ModuleType("comfy")
comfy.__path__ = []
nested = types.ModuleType("comfy.nested_tensor")
nested.NestedTensor = NestedTensor
comfy.nested_tensor = nested
sys.modules["comfy"] = comfy
sys.modules["comfy.nested_tensor"] = nested
nodes = types.ModuleType("%s.nodes" % PACKAGE)
nodes.FPS = 24
nodes.AUDIO_HZ = 40
frame_per_token = (1, 4, 4, 4, 4)
nodes._pixel_frames = lambda count: sum(
frame_per_token[index % 5] for index in range(int(count)))
def resize(images, width, height, _crop):
work = images[..., :3].movedim(-1, 1)
work = functional.interpolate(
work, size=(height, width), mode="bilinear", align_corners=False)
return work.movedim(1, -1)
nodes._resize = resize
sys.modules[nodes.__name__] = nodes
support = types.ModuleType("%s.masking_support" % PACKAGE)
support.require_h3_mask_support = lambda _purpose: None
sys.modules[support.__name__] = support
return nodes
def _load_bridge():
spec = importlib.util.spec_from_file_location(
"%s.masked_bridge" % PACKAGE,
os.path.join(ROOT, "masked_bridge.py"))
module = importlib.util.module_from_spec(spec)
sys.modules[spec.name] = module
spec.loader.exec_module(module)
return module
class VideoVAE:
def encode(self, frames):
count = int(frames.shape[0])
steps = 2 if count <= 5 else ((count - 5) // 17) * 5 + 2
value = float(frames.mean())
return torch.full((1, 24, steps, 2, 4), value)
class AudioVAE:
audio_sample_rate = 32000
def encode(self, audio):
steps = round(int(audio.shape[1]) / self.audio_sample_rate * 40)
return torch.full((1, 32, 2, steps), float(audio.mean()))
def main():
nodes = _install_stubs()
bridge = _load_bridge()
assert nodes._pixel_frames(57) == 192
target_video = torch.zeros((1, 24, 57, 2, 4))
target_audio = torch.zeros((1, 32, 2, 320))
target = {"samples": NestedTensor((target_video, target_audio))}
start_frames = torch.full((100, 32, 64, 3), 0.2)
end_frames = torch.full((100, 32, 64, 3), 0.8)
start_audio = {
"waveform": torch.full(
(1, 2, round(100 / 24 * 32000)), 0.3),
"sample_rate": 32000,
}
end_audio = {
"waveform": torch.full(
(1, 2, round(100 / 24 * 32000)), 0.7),
"sample_rate": 32000,
}
input_types = bridge.MiniMaxH3ContexMaskedAVBridge.INPUT_TYPES()
assert "start_audio" not in input_types["required"]
assert "end_audio" not in input_types["required"]
assert {"start_audio", "end_audio"} <= set(input_types["optional"])
output, middle, protected = (
bridge.MiniMaxH3ContexMaskedAVBridge().prepare(
target,
VideoVAE(),
AudioVAE(),
start_frames,
start_audio,
end_frames,
end_audio,
24.0,
24.0,
39,
"disabled",
))
assert middle == 114
assert protected == 39
video, audio = output["samples"].unbind()
video_mask, audio_mask = output["noise_mask"].unbind()
assert torch.allclose(
video[:, :, :12], torch.full_like(video[:, :, :12], 0.2))
assert not torch.count_nonzero(video[:, :, 12:-12])
assert torch.allclose(
video[:, :, -12:], torch.full_like(video[:, :, -12:], 0.8))
assert torch.allclose(
audio[..., :65], torch.full_like(audio[..., :65], 0.3))
assert not torch.count_nonzero(audio[..., 65:-65])
assert torch.allclose(
audio[..., -65:], torch.full_like(audio[..., -65:], 0.7))
assert not torch.count_nonzero(video_mask[:, :, :12])
assert torch.all(video_mask[:, :, 12:-12] == 1)
assert not torch.count_nonzero(video_mask[:, :, -12:])
assert not torch.count_nonzero(audio_mask[..., :65])
assert torch.all(audio_mask[..., 65:-65] == 1)
assert not torch.count_nonzero(audio_mask[..., -65:])
assert not torch.count_nonzero(target_video)
assert not torch.count_nonzero(target_audio)
generated_start, _, _ = (
bridge.MiniMaxH3ContexMaskedAVBridge().prepare(
target, VideoVAE(), AudioVAE(), start_frames, None,
end_frames, end_audio, 24.0, 24.0, 39, "disabled"))
_generated_video, generated_audio = generated_start["samples"].unbind()
_generated_video_mask, generated_audio_mask = (
generated_start["noise_mask"].unbind())
assert not torch.count_nonzero(generated_audio[..., :65])
assert torch.all(generated_audio_mask[..., :65] == 1)
assert torch.allclose(
generated_audio[..., -65:],
torch.full_like(generated_audio[..., -65:], 0.7))
assert not torch.count_nonzero(generated_audio_mask[..., -65:])
try:
bridge.MiniMaxH3ContexMaskedAVBridge().prepare(
target, VideoVAE(), AudioVAE(), start_frames, start_audio,
end_frames, end_audio, 24.0, 24.0, 40, "disabled")
except ValueError as exc:
assert "exact H3 video run" in str(exc)
else:
raise AssertionError("a 40-frame bridge endpoint must be rejected")
print(
"masked bridge: 192 target frames, 39+39 protected, 114 generated; "
"12 video and optional 65-step audio windows protected independently")
if __name__ == "__main__":
main()