CoolFace
Apppublic

durgappc/infinitetalk

sourceHugging Faceapache-2.0updated 8mo agoView on Hugging Face
0likes
app.py279 linesDownload Raw Back to root
1import os2import random3import logging4from typing import Any5 6import torch7import gradio as gr8from PIL import Image9 10from utils.model_loader import ModelManager11from utils.gpu_manager import gpu_manager12 13import wan14from wan.utils.utils import cache_image, cache_video, is_video15from wan.utils.multitalk_utils import save_video_ffmpeg16 17 18# =========================19# HOTFIX: Gradio /api_info crash20# =========================21# Fixes: TypeError: argument of type 'bool' is not iterable22# Caused by gradio_client trying to interpret JSON Schema nodes that can be booleans23try:24    import gradio_client.utils as gcu25 26    _old_json_schema_to_python_type = gcu._json_schema_to_python_type27 28    def _json_schema_to_python_type_patched(schema: Any, defs=None):29        if isinstance(schema, bool):30            return "Any"31        return _old_json_schema_to_python_type(schema, defs)32 33    gcu._json_schema_to_python_type = _json_schema_to_python_type_patched34except Exception as e:35    print("gradio_client patch skipped:", e)36 37 38# =========================39# Logging40# =========================41logging.basicConfig(level=logging.INFO)42logger = logging.getLogger(__name__)43 44 45# =========================46# Globals47# =========================48model_manager: ModelManager | None = None49models_loaded = False50 51 52def initialize_models(progress=gr.Progress()):53    """Download/prepare model assets on first use."""54    global model_manager, models_loaded55 56    if models_loaded:57        return58 59    try:60        progress(0.1, desc="Initializing model manager...")61        model_manager = ModelManager()62 63        progress(0.3, desc="Downloading models (first time only)...")64 65        # Pre-download assets (actual heavy loading happens on first inference)66        model_manager.get_wan_model_path()67        model_manager.get_infinitetalk_weights_path()68        model_manager.get_wav2vec_model_path()69 70        models_loaded = True71        progress(1.0, desc="Models ready!")72        logger.info("Models initialized successfully")73 74    except Exception as e:75        logger.exception("Error initializing models")76        raise gr.Error(f"Failed to initialize models: {str(e)}")77 78 79def _set_seed(seed: int) -> int:80    """Set deterministic seeds and return the final seed used."""81    if seed == -1:82        seed = random.randint(0, 99_999_999)83 84    torch.manual_seed(seed)85    if torch.cuda.is_available():86        torch.cuda.manual_seed(seed)87 88    return seed89 90 91def generate_video(92    image_or_video,93    audio_file,94    resolution="480p",95    steps=40,96    audio_guide_scale=3.0,97    seed=-1,98    progress=gr.Progress(),99):100    """101    Generate a talking video from an image OR dub an existing video.102 103    Note: This is a simplified pipeline example. Your real pipeline may use104    wan_pipeline + diffusion steps etc. This version just stitches frames + audio.105    """106    try:107        if not torch.cuda.is_available():108            raise gr.Error("⚠️ GPU not available. This Space requires GPU hardware to generate videos.")109 110        # Ensure models are prepared111        if not models_loaded:112            initialize_models(progress)113 114        progress(0.1, desc="Processing audio...")115 116        progress(0.2, desc="Loading models...")117        # Load models (kept for parity with your structure)118        size = f"infinitetalk-{resolution.replace('p', '')}"119        wan_pipeline = model_manager.load_wan_model(size=size, device="cuda")  # noqa: F841120 121        progress(0.3, desc="Processing input...")122 123        # Decide whether the input is a video or image124        if is_video(image_or_video):125            logger.info("Processing video dubbing input...")126            input_frames = cache_video(image_or_video)127        else:128            logger.info("Processing image-to-video input...")129            input_image = Image.open(image_or_video).convert("RGB")130            input_frames = [input_image]131 132        progress(0.4, desc="Generating video...")133 134        seed = _set_seed(int(seed))135        output_path = f"/tmp/output_{seed}.mp4"136 137        # Simplified output save (frames + audio)138        save_video_ffmpeg(139            input_frames,140            output_path,141            audio_file,142            high_quality_save=False,143        )144 145        progress(1.0, desc="Complete!")146        return output_path147 148    except Exception as e:149        logger.exception("Error generating video")150        gpu_manager.cleanup()151        raise gr.Error(f"Generation failed: {str(e)}")152 153 154def create_interface():155    """Create Gradio UI."""156    with gr.Blocks(title="InfiniteTalk - Talking Video Generator") as demo:157        gr.Markdown(158            """159# 🎬 InfiniteTalk - Talking Video Generator160 161Generate realistic talking head videos with accurate lip-sync from images or dub existing videos with new audio!162 163**Note**: First generation may take a few minutes while models download. Subsequent generations are faster.164"""165        )166 167        with gr.Tabs():168            # Tab 1: Image-to-Video169            with gr.Tab("📸 Image-to-Video"):170                gr.Markdown("Transform a static portrait into a talking video")171 172                with gr.Row():173                    with gr.Column():174                        image_input = gr.Image(175                            type="filepath",176                            label="Upload Portrait Image (clear face visibility recommended)",177                        )178                        audio_input = gr.Audio(179                            type="filepath",180                            label="Upload Audio (MP3, WAV, or FLAC)",181                        )182 183                        with gr.Accordion("Advanced Settings", open=False):184                            resolution = gr.Radio(185                                choices=["480p", "720p"],186                                value="480p",187                                label="Resolution (480p faster, 720p higher quality)",188                            )189                            steps = gr.Slider(190                                minimum=20,191                                maximum=50,192                                value=40,193                                step=1,194                                label="Diffusion Steps (more = higher quality but slower)",195                            )196                            audio_scale = gr.Slider(197                                minimum=1.0,198                                maximum=5.0,199                                value=3.0,200                                step=0.5,201                                label="Audio Guide Scale (2–4 recommended)",202                            )203                            seed = gr.Number(value=-1, label="Seed (-1 for random)")204 205                        generate_btn = gr.Button("🎬 Generate Video", variant="primary", size="lg")206 207                    with gr.Column():208                        output_video = gr.Video(label="Generated Video")209                        gr.Markdown("**💡 Tip**: Use a high-quality portrait image with clear facial features.")210 211                generate_btn.click(212                    fn=generate_video,213                    inputs=[image_input, audio_input, resolution, steps, audio_scale, seed],214                    outputs=output_video,215                )216 217            # Tab 2: Video Dubbing218            with gr.Tab("🎥 Video Dubbing"):219                gr.Markdown("Dub an existing video with new audio while maintaining natural movements")220 221                with gr.Row():222                    with gr.Column():223                        video_input = gr.Video(label="Upload Video (with visible face)")224                        audio_input_v2v = gr.Audio(225                            type="filepath",226                            label="Upload New Audio (MP3, WAV, or FLAC)",227                        )228 229                        with gr.Accordion("Advanced Settings", open=False):230                            resolution_v2v = gr.Radio(231                                choices=["480p", "720p"],232                                value="480p",233                                label="Resolution",234                            )235                            steps_v2v = gr.Slider(236                                minimum=20,237                                maximum=50,238                                value=40,239                                step=1,240                                label="Diffusion Steps",241                            )242                            audio_scale_v2v = gr.Slider(243                                minimum=1.0,244                                maximum=5.0,245                                value=3.0,246                                step=0.5,247                                label="Audio Guide Scale",248                            )249                            seed_v2v = gr.Number(value=-1, label="Seed")250 251                        generate_btn_v2v = gr.Button("🎬 Generate Dubbed Video", variant="primary", size="lg")252 253                    with gr.Column():254                        output_video_v2v = gr.Video(label="Dubbed Video")255                        gr.Markdown("**💡 Tip**: Use a video with consistent face visibility.")256 257                generate_btn_v2v.click(258                    fn=generate_video,259                    inputs=[video_input, audio_input_v2v, resolution_v2v, steps_v2v, audio_scale_v2v, seed_v2v],260                    outputs=output_video_v2v,261                )262 263        gr.Markdown(264            """265---266### About267Powered by InfiniteTalk (Apache 2.0)268 269⚠️ **Note**: This Space requires GPU hardware to generate videos.270"""271        )272 273    return demo274 275 276if __name__ == "__main__":277    demo = create_interface()278    demo.launch()279