CoolFace
Apppublic

Ani14/Video-agent

sourceHugging Faceupdated 1y agoView on Hugging Face
0likes
app.py333 linesDownload Raw Back to root
1"""2Gradio interface for WAN-VACE video generation3"""4import gradio as gr5import torch6 7# -----------------------------------------------------------------------------8# XPU shim for CPU‑only environments9#10# `diffusers` attempts to access `torch.xpu.empty_cache()` when cleaning up11# device memory. On CPU‑only builds of PyTorch (or builds without Intel12# extension support), the `xpu` attribute does not exist on the `torch`13# module. Defining a dummy `torch.xpu` prevents AttributeError during14# import.15# -----------------------------------------------------------------------------16if not hasattr(torch, "xpu"):17    class _DummyXPU:18        @staticmethod19        def empty_cache():20            return None21        @staticmethod22        def manual_seed(_seed: int):23            return None24        @staticmethod25        def is_available():26            return False27        @staticmethod28        def device_count():29            return 030        @staticmethod31        def current_device():32            return 033        @staticmethod34        def set_device(_idx: int):35            return None36    torch.xpu = _DummyXPU()  # type: ignore37import time38from typing import Optional39 40# Import the simple planner41from planning import plan_from_topic42 43from config import UI_CONFIG, DEFAULT_PARAMS, SERVER_CONFIG44from model_handler import model_handler45from utils import cleanup_temp_files46 47def load_model_interface(progress=gr.Progress()):48    """Interface function for loading the model"""49    def progress_callback(value, message):50        progress(value, desc=message)51    52    success, message = model_handler.load_model(progress_callback)53    54    if success:55        return (56            gr.update(visible=False),  # Hide load button57            gr.update(visible=True),   # Show generation interface58            gr.update(value=message, visible=True),  # Show success message59            gr.update(visible=False)   # Hide error message60        )61    else:62        return (63            gr.update(visible=True),   # Keep load button visible64            gr.update(visible=False),  # Keep generation interface hidden65            gr.update(visible=False),  # Hide success message66            gr.update(value=message, visible=True)   # Show error message67        )68 69def generate_video_interface(70    prompt: str,71    negative_prompt: str,72    width: int,73    height: int,74    num_frames: int,75    num_inference_steps: int,76    guidance_scale: float,77    seed: Optional[int],78    progress=gr.Progress()79):80    """Interface function for video generation"""81    82    def progress_callback(value, message):83        progress(value, desc=message)84    85    # Plan the prompt: treat the user input as a high‑level concept and let the86    # agent craft a refined prompt and recommended negative prompt.  If the user87    # supplies a negative prompt, it overrides the recommended negative prompt.88    plan = plan_from_topic(prompt)89    # Use the refined prompt from the plan90    effective_prompt = plan.prompt91    # If the user provided a negative prompt, use it; otherwise use the recommended one92    effective_negative = negative_prompt.strip() if negative_prompt and negative_prompt.strip() else plan.negative_prompt93 94    success, video_path, error_msg, gen_info = model_handler.generate_video(95        prompt=effective_prompt,96        negative_prompt=effective_negative,97        width=width,98        height=height,99        num_frames=num_frames,100        num_inference_steps=num_inference_steps,101        guidance_scale=guidance_scale,102        seed=seed,103        progress_callback=progress_callback104    )105    106    if success:107        return (108            gr.update(value=video_path, visible=True),  # Video output109            gr.update(value=gen_info, visible=True),    # Generation info110            gr.update(visible=False)                    # Hide error message111        )112    else:113        return (114            gr.update(value=None, visible=False),       # Hide video output115            gr.update(visible=False),                   # Hide generation info116            gr.update(value=error_msg, visible=True)    # Show error message117        )118 119def create_interface():120    """Create the Gradio interface"""121    122    with gr.Blocks(123        title=UI_CONFIG["title"],124        theme=UI_CONFIG["theme"]125    ) as demo:126        127        # Header128        gr.Markdown(f"# {UI_CONFIG['title']}")129        gr.Markdown(UI_CONFIG["description"])130        131        # Model loading section132        with gr.Row():133            with gr.Column():134                load_btn = gr.Button(135                    "🚀 Load Video Generation Model", 136                    variant="primary", 137                    size="lg"138                )139                load_success_msg = gr.Markdown(visible=False)140                load_error_msg = gr.Markdown(visible=False)141        142        # Main generation interface (initially hidden)143        with gr.Column(visible=False) as generation_interface:144            145            # Input section146            with gr.Row():147                with gr.Column(scale=2):148                    with gr.Group():149                        gr.Markdown("### 📝 Concept & Prompts")150                        # The user supplies a high‑level concept or topic.  The agent will151                        # refine this into a detailed prompt automatically.152                        prompt_input = gr.Textbox(153                            label="Video Concept",154                            placeholder="Describe the concept you want to generate, e.g. 'a pig in a winter forest'...",155                            lines=3,156                            value="a pig moving quickly in a beautiful winter scenery nature trees sunset tracking camera"157                        )158                        # Optional negative prompt: overrides the agent's recommended negative prompt.159                        negative_prompt_input = gr.Textbox(160                            label="Negative Prompt (Optional)",161                            placeholder="Things you don't want in the video; leave empty to use the agent's recommendation...",162                            lines=2,163                            value=""164                        )165                166                with gr.Column(scale=1):167                    with gr.Group():168                        gr.Markdown("### ⚙️ Generation Parameters")169                        170                        with gr.Row():171                            width_slider = gr.Slider(172                                label="Width",173                                minimum=64,174                                maximum=1920,175                                step=8,176                                value=DEFAULT_PARAMS["width"]177                            )178                            height_slider = gr.Slider(179                                label="Height",180                                minimum=64,181                                maximum=1080,182                                step=8,183                                value=DEFAULT_PARAMS["height"]184                            )185                        186                        num_frames_slider = gr.Slider(187                            label="Number of Frames",188                            minimum=1,189                            maximum=200,190                            step=1,191                            value=DEFAULT_PARAMS["num_frames"]192                        )193                        194                        inference_steps_slider = gr.Slider(195                            label="Inference Steps",196                            minimum=1,197                            maximum=100,198                            step=1,199                            value=DEFAULT_PARAMS["num_inference_steps"]200                        )201                        202                        guidance_scale_slider = gr.Slider(203                            label="Guidance Scale",204                            minimum=0.0,205                            maximum=20.0,206                            step=0.1,207                            value=DEFAULT_PARAMS["guidance_scale"]208                        )209                        210                        seed_input = gr.Number(211                            label="Seed (Optional)",212                            value=0,213                            precision=0214                        )215            216            # Generation button217            with gr.Row():218                generate_btn = gr.Button(219                    "🎬 Generate Video",220                    variant="primary",221                    size="lg"222                )223            224            # Output section225            with gr.Row():226                with gr.Column():227                    video_output = gr.Video(228                        label="Generated Video",229                        visible=False230                    )231                    232                    generation_info = gr.Markdown(233                        label="Generation Information",234                        visible=False235                    )236                    237                    generation_error = gr.Markdown(238                        visible=False239                    )240            241            # Additional controls242            with gr.Row():243                with gr.Column():244                    gr.Markdown("""245                    ### 💡 Tips:246                    - Enter a short **concept** (e.g. “a busy city street at dawn”). The agent will expand it into a detailed prompt.247                    - Adjust the **guidance scale**: higher values make the video adhere more closely to the refined prompt.248                    - Increasing **inference steps** improves quality at the cost of generation time.249                    - Use the optional **Negative Prompt** field only if you want to override the agent's recommended terms.250                    - Keep width and height multiples of 8 for optimal performance.251                    """)252                253                with gr.Column():254                    if torch.cuda.is_available():255                        gpu_info = f"🎮 GPU: {torch.cuda.get_device_name()}"256                    else:257                        gpu_info = "💻 Running on CPU"258                    259                    gr.Markdown(f"""260                    ### 🖥️ System Information:261                    {gpu_info}262                    263                    ### 📊 Model Information:264                    - **Model:** WAN‑VACE 1.3B (Q4_0 Quantized)265                    - **Text Encoder:** UMT5‑XXL266                    - **Scheduler:** UniPC Multistep267                    268                    ### 🤖 Agent Details:269                    - **Planning:** The agent automatically crafts a detailed prompt and a recommended negative prompt based on your concept.270                    - **Override:** Supply your own negative prompt to override the recommendation if desired.271                    """)272        273        # Event handlers274        load_btn.click(275            fn=load_model_interface,276            outputs=[277                load_btn,278                generation_interface,279                load_success_msg,280                load_error_msg281            ]282        )283        284        generate_btn.click(285            fn=generate_video_interface,286            inputs=[287                prompt_input,288                negative_prompt_input,289                width_slider,290                height_slider,291                num_frames_slider,292                inference_steps_slider,293                guidance_scale_slider,294                seed_input295            ],296            outputs=[297                video_output,298                generation_info,299                generation_error300            ]301        )302    303    return demo304 305def main():306    """Main function to launch the application"""307    print(f"🚀 Starting {UI_CONFIG['title']}...")308    print(f"🔧 Server configuration: {SERVER_CONFIG['host']}:{SERVER_CONFIG['port']}")309    310    # Check GPU availability311    if torch.cuda.is_available():312        print(f"🎮 GPU detected: {torch.cuda.get_device_name()}")313        print(f"💾 GPU Memory: {torch.cuda.get_device_properties(0).total_memory / 1024**3:.1f}GB")314    else:315        print("💻 Running on CPU (GPU recommended for better performance)")316    317    # Create interface and enable the event queue to support multiple users.  318    demo = create_interface()319    # Hugging Face Spaces expect `.queue()` to be called for handling request concurrency.  320    # Limiting concurrency_count to 1 helps prevent excessive memory usage on CPU-only hardware.321    demo = demo.queue()322 323    # Launch the interface.  324    demo.launch(325        server_name=SERVER_CONFIG["host"],326        server_port=SERVER_CONFIG["port"],327        share=SERVER_CONFIG["share"],328        show_error=True,329    )330 331if __name__ == "__main__":332    main()333