zengxianyu
upload submodules
8573fa5
import sys
sys.path.insert(0, "ComfyUI")
import os
import torch
import gc
import gradio as gr
from wan22_style import VideoProcessor
from huggingface_hub import hf_hub_download
import cv2
import shutil
import os
def convert_video_for_gradio(video_path):
"""
Convert video to web-compatible format for Gradio display.
This fixes the 'video not playable' issue with OpenCV-generated videos.
"""
if video_path is None:
return None
try:
# Create output in a Gradio-friendly location
output_dir = "video"
os.makedirs(output_dir, exist_ok=True)
base_name = os.path.splitext(os.path.basename(video_path))[0]
converted_path = os.path.join(output_dir, f"{base_name}_gradio_compatible.mp4")
# Read the original video
cap = cv2.VideoCapture(video_path)
if not cap.isOpened():
print(f"Could not open video: {video_path}")
return video_path # Return original if can't process
# Get video properties
fps = cap.get(cv2.CAP_PROP_FPS)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
# Try different codecs in order of preference
codecs_to_try = ['mp4v', 'XVID', 'MJPG', 'X264']
out = None
for codec in codecs_to_try:
try:
fourcc = cv2.VideoWriter_fourcc(*codec)
out = cv2.VideoWriter(converted_path, fourcc, fps, (width, height))
if out.isOpened():
print(f"Using codec: {codec}")
break
else:
out.release()
out = None
except:
continue
if out is None or not out.isOpened():
print("No suitable codec found, copying original file")
shutil.copy2(video_path, converted_path)
return converted_path
# Read and write frames
while True:
ret, frame = cap.read()
if not ret:
break
out.write(frame)
# Clean up
cap.release()
out.release()
print(f"Video converted for Gradio: {converted_path}")
return converted_path
except Exception as e:
print(f"Error converting video: {e}")
# Fallback: just copy the original file
try:
output_dir = "video"
os.makedirs(output_dir, exist_ok=True)
base_name = os.path.splitext(os.path.basename(video_path))[0]
fallback_path = os.path.join(output_dir, f"{base_name}_fallback.mp4")
shutil.copy2(video_path, fallback_path)
return fallback_path
except:
return video_path # Return original if all else fails
def video_output_wrapper(func):
"""
Wrapper function that automatically converts video outputs to Gradio-compatible format.
Use this to wrap any function that returns a video path.
"""
def wrapper(*args, **kwargs):
# Call the original function
result = func(*args, **kwargs)
# If result is a video path, convert it for Gradio
if result is not None and isinstance(result, str) and result.endswith(('.mp4', '.avi', '.mov', '.mkv')):
print(f"Converting output video for Gradio: {result}")
converted_path = convert_video_for_gradio(result)
return converted_path
return result
return wrapper
#@video_output_wrapper
#def generate_image(*args, **kwargs):
# """
# Example function that would return a video path.
# Replace this with your actual video processing function.
# """
# # This is just a placeholder - replace with your actual processing
# return "video/processed_rgbfast.mp4"
video_processor = VideoProcessor()
@video_output_wrapper
def process_video_wrapper(structure_video, prompt_video, prompt_negative, structure_option, prompt_style, num_frames, fps, seed):
result = video_processor._process_single_video(
video_file_path=structure_video,
output_prefix="video/gradio_output",
positive_prompt=prompt_video,
negative_prompt=prompt_negative,
preprocess_option=structure_option,
flux_positive_prompt=prompt_style,
num_frames=int(num_frames),
fps=int(fps),
seed=int(seed)
)
return result
if __name__ == "__main__":
#hf_hub_download(repo_id="Comfy-Org/Lumina_Image_2.0_Repackaged", filename="split_files/vae/ae.safetensors",local_dir="temp")
#os.system("mv temp/split_files/vae/ae.safetensors ComfyUI/models/vae/ae.safetensors")
#hf_hub_download(repo_id="Comfy-Org/Wan_2.1_ComfyUI_repackaged", filename="split_files/vae/wan_2.1_vae.safetensors",local_dir="temp")
#os.system("mv temp/split_files/vae/wan_2.1_vae.safetensors ComfyUI/models/vae/wan_2.1_vae.safetensors")
#hf_hub_download(repo_id="openai/clip-vit-large-patch14", filename="model.safetensors",local_dir="temp")
#os.system("mv temp/model.safetensors ComfyUI/models/clip/clip-vit-large-patch14.safetensors")
#hf_hub_download(repo_id="comfyanonymous/flux_text_encoders", filename="t5xxl_fp8_e4m3fn_scaled.safetensors",local_dir="temp")
#os.system("mv temp/t5xxl_fp8_e4m3fn_scaled.safetensors ComfyUI/models/clip/t5xxl_fp8_e4m3fn_scaled.safetensors")
#hf_hub_download(repo_id="QuantStack/Wan2.2-Fun-A14B-Control-GGUF", filename="HighNoise/Wan2.2-Fun-A14B-Control_HighNoise-Q8_0.gguf",local_dir="temp")
#os.system("mv temp/HighNoise/Wan2.2-Fun-A14B-Control_HighNoise-Q8_0.gguf ComfyUI/models/unet/Wan2.2-Fun-A14B-Control_HighNoise-Q8_0.gguf")
#hf_hub_download(repo_id="QuantStack/Wan2.2-Fun-A14B-Control-GGUF", filename="LowNoise/Wan2.2-Fun-A14B-Control_LowNoise-Q8_0.gguf",local_dir="temp")
#os.system("mv temp/LowNoise/Wan2.2-Fun-A14B-Control_LowNoise-Q8_0.gguf ComfyUI/models/unet/Wan2.2-Fun-A14B-Control_LowNoise-Q8_0.gguf")
#hf_hub_download(repo_id="QuantStack/FLUX.1-Kontext-dev-GGUF", filename="flux1-kontext-dev-Q8_0.gguf",local_dir="temp")
#os.system("mv temp/flux1-kontext-dev-Q8_0.gguf ComfyUI/models/unet/flux1-kontext-dev-Q8_0.gguf")
# Start your Gradio app
with gr.Blocks() as app:
# Add a title
gr.Markdown("# Video Style Shaping with Flux and WAN2.2")
gr.Markdown("## Click the convert button if getting the not playable error")
with gr.Row():
with gr.Column():
# Add an input
prompt_style = gr.Textbox(label="Style Prompt for Flux", placeholder="Enter your prompt here...")
prompt_video = gr.Textbox(label="Content Prompt for WAN Video", placeholder="Enter your prompt here...")
# Add a `Row` to include the groups side by side
with gr.Row():
# First group includes structure image and depth strength
with gr.Group():
structure_video = gr.Video(label="Structure Video (quality: 720 x 1280, decent quality: 480 x 832)")
convert_btn = gr.Button("Convert Video for Gradio", size="sm")
structure_option = gr.Radio(label="Preprocessing Option", choices=["Intensity", "Canny", "None"], value="Intensity")
# Advanced Settings Section (collapsible)
with gr.Accordion("⚙️ Advanced Settings", open=False):
with gr.Row():
with gr.Column():
# Video generation parameters
num_frames = gr.Slider(
label="Number of Frames",
minimum=17,
maximum=121,
value=81,
step=1,
info="Number of frames to generate"
)
fps = gr.Slider(
label="FPS",
minimum=8,
maximum=30,
value=16,
step=1,
info="Frames per second"
)
seed = gr.Number(
label="Seed",
value=-1,
precision=0,
info="Random seed (-1 for random)"
)
prompt_negative = gr.Textbox(
label="Negative Prompt for WAN Video",
value="色调艳丽,过曝,静态,细节模糊不清,字幕,风格,作品,画作,画面,静止,整体发灰,最差质量,低质量,JPEG压缩残留,丑陋的,CG, game, cartoon, anime, render, 渲染,游戏,卡通",
lines=4
)
# The generate button
generate_btn = gr.Button("Generate")
with gr.Column():
# The output video
output_video = gr.Video(label="Generated Video")
# Convert video button (manual only to avoid infinite loops)
convert_btn.click(
fn=convert_video_for_gradio,
inputs=[structure_video],
outputs=[structure_video]
)
# When clicking the button, it will trigger the `generate_image` function, with the respective inputs
# and the output an image
generate_btn.click(
fn=process_video_wrapper,
inputs=[
structure_video,
prompt_video,
prompt_negative,
structure_option,
prompt_style,
num_frames,
fps,
seed,
],
outputs=[output_video]
)
app.launch(share=True)