[Frontend] Add ComfyUI FastH3 node, fix t2va aspect ratio and dropped audio (#7456)

Signed-off-by: princepride <wangzhipeng628@gmail.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
汪志鹏andClaude Opus 5 authored and GitHub committed 2026-09-14 11:22:05 +08:00
1 parent db40ed3a31
commit e8f45fcd89
13 files changed
+823 -23

No files matched your search

@@ -24,6 +24,7 @@ import requests
import torch
from comfy_api.input import AudioInput, VideoInput
from comfyui_vllm_omni.nodes import (
VLLMOmniFastH3Deployment,
VLLMOmniGenerateImage,
VLLMOmniGenerateVideo,
VLLMOmniTTS,
@@ -78,6 +79,7 @@ class SamplingKind(str, Enum):
TTS_DIFFUSION_SINGLE = "tts_diffusion_single"
VIDEO_NONE = "video_none"
VIDEO_DIFFUSION_SINGLE = "video_diffusion_single"
VIDEO_FASTH3 = "video_fasth3"
VIDEO_REF2VA_IMAGE_AUDIO = "video_ref2va_image_audio"
VIDEO_REF2VA_MULTI_VIDEO = "video_ref2va_multi_video"
@@ -89,6 +91,9 @@ VIDEO_WIDTH = 32
VIDEO_HEIGHT = 32
VIDEO_FPS = 8
VIDEO_NUM_FRAMES = 5
VIDEO_DURATION = VIDEO_NUM_FRAMES / VIDEO_FPS # 0.625 s at the generic 8 fps
# FastH3 pins 24 fps, so the same duration is a different frame count there.
VIDEO_FASTH3_NUM_FRAMES = round(VIDEO_DURATION * 24)
DIFFUSION_SINGLE_SAMPLING_PARAMS = DiffusionSamplingParams(
{
"n": 2,
@@ -394,6 +399,24 @@ def _build_mock_outputs(outputs: Iterable[OmniRequestOutput], sampling_case: Sam
LORA_PARAMS,
)
_assert_model_param_values(received_sampling_params_list[0], VIDEO_MODEL_PARAMS)
elif sampling_case.kind is SamplingKind.VIDEO_FASTH3:
assert len(received_sampling_params_list) == 1
received = received_sampling_params_list[0]
_assert_sampling_param_values(
received,
{
"width": VIDEO_WIDTH,
"height": VIDEO_HEIGHT,
"num_frames": VIDEO_FASTH3_NUM_FRAMES,
"fps": 24,
"num_inference_steps": 4,
},
)
assert received.lora_request is None
# t2va is refused without an explicit ratio; 32x32 derives "1:1".
_assert_model_param_values(received, {"task": "t2va", "aspect_ratio": "1:1"})
assert "flow_shift" not in received.extra_args
assert "audio_flow_shift" not in received.extra_args
elif sampling_case.kind is SamplingKind.VIDEO_REF2VA_IMAGE_AUDIO:
assert len(received_sampling_params_list) == 1
assert isinstance(prompt, dict)
@@ -861,7 +884,7 @@ async def test_video_generation_node(api_server: str, model: str, image_input: b
"width": VIDEO_WIDTH,
"height": VIDEO_HEIGHT,
"fps": VIDEO_FPS,
"num_frames": VIDEO_NUM_FRAMES,
"duration": VIDEO_DURATION,
"model_params": VIDEO_MODEL_PARAMS,
}
if image_input:
@@ -878,6 +901,67 @@ async def test_video_generation_node(api_server: str, model: str, image_input: b
assert isinstance(result[0], VideoInput)
@pytest.mark.asyncio
@pytest.mark.parametrize(
"server_case,deployment_model",
[
pytest.param(
ServerCase(
served_model="MiniMaxAI/MiniMax-H3",
stage_list=["diffusion"],
stage_configs=[{"stage_type": "diffusion", "final_output": True, "final_output_type": "video"}],
outputs=[_build_diffusion_video_output()],
),
"MiniMaxAI/MiniMax-H3",
id="canonical_model_name",
),
pytest.param(
ServerCase(
served_model="fasth3",
stage_list=["diffusion"],
stage_configs=[{"stage_type": "diffusion", "final_output": True, "final_output_type": "video"}],
outputs=[_build_diffusion_video_output()],
),
"fasth3",
# A --served-model-name alias lookup_model_spec cannot resolve to H3. The
# request must still be built by the H3 params builder, or it goes out
# without the aspect_ratio (and task) a t2va request is refused without.
id="served_model_alias",
),
],
indirect=["server_case"],
)
@pytest.mark.parametrize(
"sampling_case",
[SamplingCase(kind=SamplingKind.VIDEO_FASTH3, sampling_params=DIFFUSION_VIDEO_SINGLE_SAMPLING_PARAMS)],
indirect=True,
)
async def test_fast_h3_deployment_node(api_server: str, sampling_case: SamplingCase, deployment_model: str):
deployment_node = VLLMOmniFastH3Deployment()
(deployment,) = deployment_node.get_deployment(
url=api_server,
model=deployment_model,
)
result = await VLLMOmniGenerateVideo().generate(
url="http://ignored.invalid/v1",
model="ignored-model",
prompt="A singer performs on a neon-lit stage.",
negative_prompt="",
width=VIDEO_WIDTH,
height=VIDEO_HEIGHT,
fps=VIDEO_FPS,
duration=VIDEO_DURATION,
sampling_params=sampling_case.sampling_params,
model_params=H3_MODEL_PARAMS,
fast_h3=deployment,
)
assert isinstance(result, tuple)
assert len(result) == 1
assert isinstance(result[0], VideoInput)
@pytest.mark.asyncio
@pytest.mark.parametrize(
"server_case,sampling_case,ref_mode",
@@ -944,7 +1028,7 @@ async def test_video_generation_node_minimax_h3_ref2va(
width=VIDEO_WIDTH,
height=VIDEO_HEIGHT,
fps=VIDEO_FPS,
num_frames=VIDEO_NUM_FRAMES,
duration=VIDEO_DURATION,
references=references,
model_params=H3_MODEL_PARAMS,
)