File size: 3,108 Bytes
e3a745a
 
bb1b5ea
e3a745a
 
 
245fbeb
a365794
e3a745a
 
 
 
245fbeb
bb1b5ea
 
 
 
 
 
 
245fbeb
 
 
 
 
 
 
bb1b5ea
245fbeb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bb1b5ea
e3a745a
 
 
245fbeb
 
 
 
bb1b5ea
e3a745a
 
 
 
 
 
 
 
 
 
 
 
 
bb1b5ea
e3a745a
 
 
 
 
245fbeb
 
e3a745a
 
 
 
 
 
 
 
 
 
 
 
 
 
bb1b5ea
245fbeb
e3a745a
bb1b5ea
e3a745a
bb1b5ea
e3a745a
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
"""
AIBRUH/ditto — Amanda's talking head engine.
SadTalker ZeroGPU A100: portrait image + audio → MP4 talking head video.
"""
import gradio as gr
import spaces
import os, sys, subprocess

SADTALKER = "/tmp/SadTalker"
CKPT = f"{SADTALKER}/checkpoints"

def _setup():
    # Clone SadTalker source if not already present
    if not os.path.exists(SADTALKER):
        subprocess.run(
            ["git", "clone", "--depth=1",
             "https://github.com/OpenTalker/SadTalker.git", SADTALKER],
            check=True,
        )

    # Install ALL SadTalker dependencies in one shot from their own requirements file
    req_file = os.path.join(SADTALKER, "requirements.txt")
    if os.path.exists(req_file):
        subprocess.run(
            [sys.executable, "-m", "pip", "install", "-q", "-r", req_file],
            check=False,
        )

    # numpy 2.x removed VisibleDeprecationWarning — patch it now (before any SadTalker import)
    import numpy as np
    if not hasattr(np, "VisibleDeprecationWarning"):
        np.VisibleDeprecationWarning = DeprecationWarning  # type: ignore[attr-defined]

    # Download SadTalker checkpoints if not present
    if not os.path.exists(f"{CKPT}/SadTalker_V0.0.2_256.safetensors"):
        os.makedirs(CKPT, exist_ok=True)
        from huggingface_hub import snapshot_download
        snapshot_download(
            repo_id="vinthony/SadTalker-V002rc",
            local_dir=CKPT,
            ignore_patterns=["*.md", "*.txt"],
        )

    if SADTALKER not in sys.path:
        sys.path.insert(0, SADTALKER)


_setup()

# numpy patch must also run at module level for the import below
import numpy as np  # noqa: E402
if not hasattr(np, "VisibleDeprecationWarning"):
    np.VisibleDeprecationWarning = DeprecationWarning  # type: ignore[attr-defined]

from src.gradio_demo import SadTalker as _ST  # noqa: E402

_sad: _ST | None = None

def _load():
    global _sad
    if _sad is None:
        _sad = _ST(CKPT, f"{SADTALKER}/config", lazy_load=True)
    return _sad


@spaces.GPU
def infer(source_image: str, driven_audio: str):
    """Portrait image + WAV audio → talking head MP4."""
    st = _load()
    result = st.test(
        source_image=source_image,
        driven_audio=driven_audio,
        preprocess="crop",
        still_mode=True,
        use_enhancer=False,
        batch_size=1,
        size=256,
        pose_style=0,
        exp_scale=1.0,
        use_ref_video=False,
        ref_video=None,
        ref_info="pose",
        use_idle_mode=False,
        length_of_audio=0,
        use_blink=True,
    )
    return result


with gr.Blocks(title="AIBRUH/ditto · Amanda Engine") as demo:
    gr.Markdown("## AIBRUH/ditto · Amanda Talking Head Engine")
    with gr.Row():
        img_in = gr.Image(type="filepath", label="Source Portrait (JPG/PNG)")
        aud_in = gr.Audio(type="filepath", label="Driving Audio (WAV)")
    btn = gr.Button("Generate Talking Head", variant="primary")
    vid_out = gr.Video(label="Amanda Speaking")
    btn.click(fn=infer, inputs=[img_in, aud_in], outputs=vid_out, api_name="infer")

demo.launch()