Spaces:
Runtime error
Runtime error
Download ui/shared/h3_ref2va_ui.py from Samuelsrmendozs/MiniMax-H3-e: direct link, hf CLI and curl.
- Browser
- Download file 18.4 kB
-
https://huggingface.co/spaces/Samuelsrmendozs/MiniMax-H3-e/resolve/main/ui/shared/h3_ref2va_ui.py
- Command line
-
hf download hf://spaces/Samuelsrmendozs/MiniMax-H3-e/ui/shared/h3_ref2va_ui.py
-
curl -L -o h3_ref2va_ui.py https://huggingface.co/spaces/Samuelsrmendozs/MiniMax-H3-e/resolve/main/ui/shared/h3_ref2va_ui.py
18.4 kB
| import gradio as gr | |
| from .h3_ref2va_logic import process_inputs, RESOLUTION_PRESETS | |
| from .ui_components import create_lora_settings_ui, create_h3_controlnet_ui, create_h3_guide_ui | |
| from comfy_integration.nodes import SAMPLER_CHOICES, SCHEDULER_CHOICES | |
| from core.generation_logic import generate_h3_video_wrapper | |
| UI_INFO = { | |
| "workflow_recipe": "h3_ref2va_recipe.yaml", | |
| "main_tab": "VideoGen", | |
| "sub_tab": "H3 REF2VA", | |
| "run_button_text": "🎬 Generate H3 Video" | |
| } | |
| MAX_REF_IMAGES = 9 | |
| MAX_REF_VIDEOS = 3 | |
| MAX_REF_AUDIOS = 3 | |
| def create_ui(): | |
| components = {} | |
| with gr.Column(): | |
| gr.Markdown("## MiniMax H3 Reference Video Generation") | |
| gr.Markdown("💡 **Tip:** Supports uploading up to 9 reference images, 3 reference videos with audio, and 3 reference audio files. Under the default ZeroGPU Duration (s) of 120s, tasks with 544p resolution, 20 steps, 5s duration, and 3 reference images pass successfully.") | |
| components['prompt'] = gr.Textbox(label="Prompt", lines=5) | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| with gr.Row(): | |
| components['resolution'] = gr.Radio( | |
| label="Resolution", | |
| choices=["544p", "768p", "1080p"], | |
| value="544p", | |
| interactive=True | |
| ) | |
| with gr.Row(): | |
| components['aspect_ratio'] = gr.Dropdown( | |
| label="Aspect Ratio", | |
| choices=list(RESOLUTION_PRESETS["544p"].keys()), | |
| value="16:9 (Landscape)", | |
| interactive=True | |
| ) | |
| with gr.Row(): | |
| components['width'] = gr.Number(label="Width", value=960, precision=0) | |
| components['height'] = gr.Number(label="Height", value=544, precision=0) | |
| with gr.Row(visible=False): | |
| components['sampler'] = gr.Dropdown( | |
| label="Sampler", | |
| choices=SAMPLER_CHOICES, | |
| value="res_multistep" if "res_multistep" in SAMPLER_CHOICES else (SAMPLER_CHOICES[0] if SAMPLER_CHOICES else "res_multistep"), | |
| interactive=True, | |
| visible=False | |
| ) | |
| components['scheduler'] = gr.Dropdown( | |
| label="Scheduler", | |
| choices=SCHEDULER_CHOICES, | |
| value="simple" if "simple" in SCHEDULER_CHOICES else (SCHEDULER_CHOICES[0] if SCHEDULER_CHOICES else "simple"), | |
| interactive=True, | |
| visible=False | |
| ) | |
| with gr.Row(visible=False): | |
| components['cfg_scale'] = gr.Slider( | |
| label="CFG Scale", | |
| minimum=1.0, | |
| maximum=20.0, | |
| step=0.1, | |
| value=1.0, | |
| interactive=True, | |
| visible=False | |
| ) | |
| with gr.Row(): | |
| components['steps'] = gr.Slider( | |
| label="Steps", | |
| minimum=1, | |
| maximum=50, | |
| step=1, | |
| value=20, | |
| interactive=True | |
| ) | |
| components['duration'] = gr.Slider( | |
| label="Duration (s)", | |
| minimum=0.2, | |
| maximum=15.0, | |
| step=0.1, | |
| value=5.0, | |
| interactive=True | |
| ) | |
| with gr.Row(): | |
| components['seed'] = gr.Number(label="Seed (-1 for random)", value=-1, precision=0) | |
| components['zero_gpu_duration'] = gr.Number( | |
| label="ZeroGPU Duration (s)", | |
| value=120, | |
| precision=0 | |
| ) | |
| with gr.Column(scale=1): | |
| components['output_video'] = gr.Video( | |
| label="Result Video", | |
| interactive=False, | |
| height=492 | |
| ) | |
| components.update(create_lora_settings_ui("h3_ref2va")) | |
| with gr.Accordion("Reference Image Settings", open=False): | |
| ref_image_groups = [] | |
| ref_image_inputs = [] | |
| with gr.Row(): | |
| for i in range(MAX_REF_IMAGES): | |
| with gr.Column(visible=(i < 1), min_width=160) as img_col: | |
| img_comp = gr.Image( | |
| type="pil", | |
| label=f"Ref Image {i+1}", | |
| sources=["upload"], | |
| height=160 | |
| ) | |
| ref_image_groups.append(img_col) | |
| ref_image_inputs.append(img_comp) | |
| components['ref_image_groups'] = ref_image_groups | |
| components['ref_image_inputs'] = ref_image_inputs | |
| components['ref_images'] = ref_image_inputs | |
| with gr.Row(): | |
| components['add_ref_button'] = gr.Button("✚ Add Reference Image") | |
| components['delete_ref_button'] = gr.Button("➖ Delete Reference Image", visible=True) | |
| components['ref_count_state'] = gr.State(1) | |
| with gr.Accordion("Reference Video Settings", open=False): | |
| ref_video_groups = [] | |
| ref_video_inputs = [] | |
| with gr.Row(): | |
| for i in range(MAX_REF_VIDEOS): | |
| with gr.Column(visible=(i < 1), min_width=200) as vid_col: | |
| vid_comp = gr.Video( | |
| label=f"Ref Video {i+1}", | |
| sources=["upload"], | |
| height=200 | |
| ) | |
| ref_video_groups.append(vid_col) | |
| ref_video_inputs.append(vid_comp) | |
| components['ref_video_groups'] = ref_video_groups | |
| components['ref_video_inputs'] = ref_video_inputs | |
| components['ref_videos'] = ref_video_inputs | |
| with gr.Row(): | |
| components['add_ref_video_button'] = gr.Button("✚ Add Reference Video") | |
| components['delete_ref_video_button'] = gr.Button("➖ Delete Reference Video", visible=True) | |
| components['ref_video_count_state'] = gr.State(1) | |
| with gr.Accordion("Reference Audio Settings", open=False): | |
| ref_audio_groups = [] | |
| ref_audio_inputs = [] | |
| with gr.Row(): | |
| for i in range(MAX_REF_AUDIOS): | |
| with gr.Column(visible=(i < 1), min_width=200) as aud_col: | |
| aud_comp = gr.Audio( | |
| label=f"Ref Audio {i+1}", | |
| sources=["upload"], | |
| type="filepath" | |
| ) | |
| ref_audio_groups.append(aud_col) | |
| ref_audio_inputs.append(aud_comp) | |
| components['ref_audio_groups'] = ref_audio_groups | |
| components['ref_audio_inputs'] = ref_audio_inputs | |
| components['ref_audios'] = ref_audio_inputs | |
| with gr.Row(): | |
| components['add_ref_audio_button'] = gr.Button("✚ Add Reference Audio") | |
| components['delete_ref_audio_button'] = gr.Button("➖ Delete Reference Audio", visible=True) | |
| components['ref_audio_count_state'] = gr.State(1) | |
| components.update(create_h3_guide_ui("h3_ref2va")) | |
| components.update(create_h3_controlnet_ui("h3_ref2va")) | |
| components['run_button'] = gr.Button(UI_INFO["run_button_text"], variant="primary", elem_classes=["run-shortcut"]) | |
| return components | |
| def create_event_handlers(components: dict, demo: gr.Blocks): | |
| def update_dimensions(resolution, aspect_ratio): | |
| w, h = RESOLUTION_PRESETS.get(resolution, {}).get(aspect_ratio, (960, 544)) | |
| return w, h | |
| components['resolution'].change( | |
| fn=update_dimensions, | |
| inputs=[components['resolution'], components['aspect_ratio']], | |
| outputs=[components['width'], components['height']], | |
| api_name=False | |
| ) | |
| components['aspect_ratio'].change( | |
| fn=update_dimensions, | |
| inputs=[components['resolution'], components['aspect_ratio']], | |
| outputs=[components['width'], components['height']], | |
| api_name=False | |
| ) | |
| ref_count_state = components['ref_count_state'] | |
| add_ref_btn = components['add_ref_button'] | |
| del_ref_btn = components['delete_ref_button'] | |
| ref_image_groups = components['ref_image_groups'] | |
| ref_image_inputs = components['ref_image_inputs'] | |
| def add_ref_row(count): | |
| count += 1 | |
| visibility_updates = tuple(gr.update(visible=i < count) for i in range(MAX_REF_IMAGES)) | |
| return (count, gr.update(visible=count < MAX_REF_IMAGES), gr.update(visible=count > 0)) + visibility_updates | |
| def delete_ref_row(count): | |
| count -= 1 | |
| image_clear_updates = [gr.update()] * MAX_REF_IMAGES | |
| if count >= 0: | |
| image_clear_updates[count] = None | |
| visibility_updates = tuple(gr.update(visible=i < count) for i in range(MAX_REF_IMAGES)) | |
| return (count, gr.update(visible=count < MAX_REF_IMAGES), gr.update(visible=count > 0)) + visibility_updates + tuple(image_clear_updates) | |
| add_ref_outputs = [ref_count_state, add_ref_btn, del_ref_btn] + ref_image_groups | |
| del_ref_outputs = [ref_count_state, add_ref_btn, del_ref_btn] + ref_image_groups + ref_image_inputs | |
| add_ref_btn.click( | |
| fn=add_ref_row, | |
| inputs=[ref_count_state], | |
| outputs=add_ref_outputs, | |
| show_progress=False, | |
| api_name=False | |
| ) | |
| del_ref_btn.click( | |
| fn=delete_ref_row, | |
| inputs=[ref_count_state], | |
| outputs=del_ref_outputs, | |
| show_progress=False, | |
| api_name=False | |
| ) | |
| ref_video_count_state = components['ref_video_count_state'] | |
| add_ref_vid_btn = components['add_ref_video_button'] | |
| del_ref_vid_btn = components['delete_ref_video_button'] | |
| ref_video_groups = components['ref_video_groups'] | |
| ref_video_inputs = components['ref_video_inputs'] | |
| def add_ref_video_row(count): | |
| count += 1 | |
| visibility_updates = tuple(gr.update(visible=i < count) for i in range(MAX_REF_VIDEOS)) | |
| return (count, gr.update(visible=count < MAX_REF_VIDEOS), gr.update(visible=count > 0)) + visibility_updates | |
| def delete_ref_video_row(count): | |
| count -= 1 | |
| video_clear_updates = [gr.update()] * MAX_REF_VIDEOS | |
| if count >= 0: | |
| video_clear_updates[count] = None | |
| visibility_updates = tuple(gr.update(visible=i < count) for i in range(MAX_REF_VIDEOS)) | |
| return (count, gr.update(visible=count < MAX_REF_VIDEOS), gr.update(visible=count > 0)) + visibility_updates + tuple(video_clear_updates) | |
| add_ref_vid_outputs = [ref_video_count_state, add_ref_vid_btn, del_ref_vid_btn] + ref_video_groups | |
| del_ref_vid_outputs = [ref_video_count_state, add_ref_vid_btn, del_ref_vid_btn] + ref_video_groups + ref_video_inputs | |
| add_ref_vid_btn.click( | |
| fn=add_ref_video_row, | |
| inputs=[ref_video_count_state], | |
| outputs=add_ref_vid_outputs, | |
| show_progress=False, | |
| api_name=False | |
| ) | |
| del_ref_vid_btn.click( | |
| fn=delete_ref_video_row, | |
| inputs=[ref_video_count_state], | |
| outputs=del_ref_vid_outputs, | |
| show_progress=False, | |
| api_name=False | |
| ) | |
| ref_audio_count_state = components['ref_audio_count_state'] | |
| add_ref_aud_btn = components['add_ref_audio_button'] | |
| del_ref_aud_btn = components['delete_ref_audio_button'] | |
| ref_audio_groups = components['ref_audio_groups'] | |
| ref_audio_inputs = components['ref_audio_inputs'] | |
| def add_ref_audio_row(count): | |
| count += 1 | |
| visibility_updates = tuple(gr.update(visible=i < count) for i in range(MAX_REF_AUDIOS)) | |
| return (count, gr.update(visible=count < MAX_REF_AUDIOS), gr.update(visible=count > 0)) + visibility_updates | |
| def delete_ref_audio_row(count): | |
| count -= 1 | |
| audio_clear_updates = [gr.update()] * MAX_REF_AUDIOS | |
| if count >= 0: | |
| audio_clear_updates[count] = None | |
| visibility_updates = tuple(gr.update(visible=i < count) for i in range(MAX_REF_AUDIOS)) | |
| return (count, gr.update(visible=count < MAX_REF_AUDIOS), gr.update(visible=count > 0)) + visibility_updates + tuple(audio_clear_updates) | |
| add_ref_aud_outputs = [ref_audio_count_state, add_ref_aud_btn, del_ref_aud_btn] + ref_audio_groups | |
| del_ref_aud_outputs = [ref_audio_count_state, add_ref_aud_btn, del_ref_aud_btn] + ref_audio_groups + ref_audio_inputs | |
| add_ref_aud_btn.click( | |
| fn=add_ref_audio_row, | |
| inputs=[ref_audio_count_state], | |
| outputs=add_ref_aud_outputs, | |
| show_progress=False, | |
| api_name=False | |
| ) | |
| del_ref_aud_btn.click( | |
| fn=delete_ref_audio_row, | |
| inputs=[ref_audio_count_state], | |
| outputs=del_ref_aud_outputs, | |
| show_progress=False, | |
| api_name=False | |
| ) | |
| lora_sources = components.get('lora_sources_h3_ref2va', []) | |
| lora_ids = components.get('lora_ids_h3_ref2va', []) | |
| lora_scales = components.get('lora_scales_h3_ref2va', []) | |
| cn_videos = components.get('h3_controlnet_videos_h3_ref2va', []) | |
| cn_types = components.get('h3_controlnet_types_h3_ref2va', []) | |
| cn_series = components.get('h3_controlnet_series_h3_ref2va', []) | |
| cn_strengths = components.get('h3_controlnet_strengths_h3_ref2va', []) | |
| cn_start_percents = components.get('h3_controlnet_start_percents_h3_ref2va', []) | |
| cn_end_percents = components.get('h3_controlnet_end_percents_h3_ref2va', []) | |
| cn_filepaths = components.get('h3_controlnet_filepaths_h3_ref2va', []) | |
| guide_images = components.get('h3_guide_images_h3_ref2va', []) | |
| guide_videos = components.get('h3_guide_videos_h3_ref2va', []) | |
| guide_audios = components.get('h3_guide_audios_h3_ref2va', []) | |
| guide_times = components.get('h3_guide_times_h3_ref2va', []) | |
| guide_frames = components.get('h3_guide_frames_h3_ref2va', []) | |
| inputs_list = [ | |
| components['prompt'], | |
| components['resolution'], | |
| components['aspect_ratio'], | |
| components['width'], | |
| components['height'], | |
| components['duration'], | |
| components['sampler'], | |
| components['scheduler'], | |
| components['steps'], | |
| components['cfg_scale'], | |
| components['seed'], | |
| components['zero_gpu_duration'] | |
| ] + ref_image_inputs + ref_video_inputs + ref_audio_inputs + lora_sources + lora_ids + lora_scales + cn_videos + cn_types + cn_series + cn_strengths + cn_start_percents + cn_end_percents + cn_filepaths + guide_images + guide_videos + guide_audios + guide_times + guide_frames | |
| def on_run_click(*args, progress=gr.Progress(track_tqdm=True)): | |
| prompt, resolution, aspect_ratio, width, height, duration, sampler, scheduler, steps, cfg_scale, seed, zero_gpu_duration = args[:12] | |
| idx = 12 | |
| imgs = list(args[idx : idx + len(ref_image_inputs)]) | |
| idx += len(ref_image_inputs) | |
| vids = list(args[idx : idx + len(ref_video_inputs)]) | |
| idx += len(ref_video_inputs) | |
| auds = list(args[idx : idx + len(ref_audio_inputs)]) | |
| idx += len(ref_audio_inputs) | |
| num_loras = len(lora_sources) | |
| l_sources = args[idx : idx + num_loras] | |
| l_ids = args[idx + num_loras : idx + 2*num_loras] | |
| l_scales = args[idx + 2*num_loras : idx + 3*num_loras] | |
| idx += 3 * num_loras | |
| num_cns = len(cn_videos) | |
| c_vids = args[idx : idx + num_cns] | |
| c_types = args[idx + num_cns : idx + 2*num_cns] | |
| c_series = args[idx + 2*num_cns : idx + 3*num_cns] | |
| c_strengths = args[idx + 3*num_cns : idx + 4*num_cns] | |
| c_starts = args[idx + 4*num_cns : idx + 5*num_cns] | |
| c_ends = args[idx + 5*num_cns : idx + 6*num_cns] | |
| c_fps = args[idx + 6*num_cns : idx + 7*num_cns] | |
| idx += 7 * num_cns | |
| num_guides = len(guide_images) | |
| g_imgs = args[idx : idx + num_guides] | |
| g_vids = args[idx + num_guides : idx + 2*num_guides] | |
| g_auds = args[idx + 2*num_guides : idx + 3*num_guides] | |
| g_times = args[idx + 3*num_guides : idx + 4*num_guides] | |
| g_frames = args[idx + 4*num_guides : idx + 5*num_guides] if guide_frames else [] | |
| ui_values = { | |
| 'prompt': prompt, | |
| 'resolution': resolution, | |
| 'aspect_ratio': aspect_ratio, | |
| 'width': width, | |
| 'height': height, | |
| 'duration': duration, | |
| 'sampler_name': sampler, | |
| 'scheduler': scheduler, | |
| 'steps': steps, | |
| 'cfg_scale': cfg_scale, | |
| 'seed': seed, | |
| 'zero_gpu_duration': zero_gpu_duration, | |
| 'batch_count': 1, | |
| 'ref_images': imgs, | |
| 'ref_videos': vids, | |
| 'ref_audios': auds, | |
| 'lora_sources_h3_ref2va': list(l_sources), | |
| 'lora_ids_h3_ref2va': list(l_ids), | |
| 'lora_scales_h3_ref2va': list(l_scales), | |
| 'h3_controlnet_videos_h3_ref2va': list(c_vids), | |
| 'h3_controlnet_types_h3_ref2va': list(c_types), | |
| 'h3_controlnet_series_h3_ref2va': list(c_series), | |
| 'h3_controlnet_strengths_h3_ref2va': list(c_strengths), | |
| 'h3_controlnet_start_percents_h3_ref2va': list(c_starts), | |
| 'h3_controlnet_end_percents_h3_ref2va': list(c_ends), | |
| 'h3_controlnet_filepaths_h3_ref2va': list(c_fps), | |
| 'h3_guide_images_h3_ref2va': list(g_imgs), | |
| 'h3_guide_videos_h3_ref2va': list(g_vids), | |
| 'h3_guide_audios_h3_ref2va': list(g_auds), | |
| 'h3_guide_times_h3_ref2va': list(g_times), | |
| 'h3_guide_frames_h3_ref2va': list(g_frames), | |
| } | |
| return generate_h3_video_wrapper(process_inputs, ui_values, progress=progress) | |
| components['run_button'].click( | |
| fn=on_run_click, | |
| inputs=inputs_list, | |
| outputs=[components['output_video']], | |
| api_name=False | |
| ) | |