File size: 4,894 Bytes
c139bcf
 
9e7a994
4ea23c0
 
 
 
1f6e6f1
4ea23c0
3be93ed
6536113
 
4ea23c0
6536113
 
4ea23c0
 
6536113
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4ea23c0
6536113
4ea23c0
6536113
4ea23c0
 
 
9e7a994
4ea23c0
9e7a994
4ea23c0
 
6536113
 
c139bcf
 
4ea23c0
c139bcf
4ea23c0
6536113
4ea23c0
6536113
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4ea23c0
6536113
4ea23c0
6536113
4ea23c0
 
 
 
 
6536113
4ea23c0
 
 
 
 
 
6536113
 
 
 
 
 
 
 
 
 
 
4ea23c0
6536113
c139bcf
6536113
c139bcf
4ea23c0
 
 
 
6536113
4ea23c0
3ae4fdd
6536113
3ae4fdd
 
9e7a994
4ea23c0
3ae4fdd
 
4ea23c0
9e7a994
6536113
3ae4fdd
4ea23c0
 
 
6536113
3ae4fdd
 
4ea23c0
3ae4fdd
c139bcf
4ea23c0
 
6536113
 
 
4ea23c0
 
3be93ed
4ea23c0
42f1e7f
9e7a994
3be93ed
 
9e7a994
 
 
c139bcf
 
4ea23c0
 
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
import gradio as gr
import os
import tempfile
import shutil
import torch
import numpy as np
from PIL import Image

print("Loading OVI model...")

device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"Device: {device}")

model = None
tokenizer = None

try:
    from transformers import AutoTokenizer
    from huggingface_hub import hf_hub_download, snapshot_download
    import sys

    # Download full repo
    repo_path = snapshot_download("chetwinlow1/Ovi")
    sys.path.insert(0, repo_path)

    # Try importing model directly from repo
    try:
        from modeling_ovi import OviModel
        from processing_ovi import OviProcessor

        processor = OviProcessor.from_pretrained("chetwinlow1/Ovi")
        model = OviModel.from_pretrained(
            "chetwinlow1/Ovi",
            torch_dtype=torch.float16 if device == "cuda" else torch.float32,
        ).to(device)
        model.eval()
        print("βœ… OVI loaded via custom classes!")

    except ImportError:
        # Fallback - try pipeline
        from transformers import pipeline
        pipe = pipeline(
            "image-to-video",
            model="chetwinlow1/Ovi",
            device=0 if device == "cuda" else -1,
        )
        model = pipe
        processor = None
        print("βœ… OVI loaded via pipeline!")

except Exception as e:
    print(f"❌ Model error: {e}")
    model = None
    processor = None


def generate_video(image, prompt):
    if image is None:
        raise gr.Error("Please upload an image!")
    if not prompt or prompt.strip() == "":
        raise gr.Error("Please enter a text prompt!")
    if model is None:
        raise gr.Error("Model not loaded!")

    try:
        if isinstance(image, str):
            pil_image = Image.open(image).convert("RGB")
        else:
            pil_image = Image.fromarray(image).convert("RGB")

        output_path = tempfile.NamedTemporaryFile(suffix=".mp4", delete=False).name

        if processor is not None:
            # Custom processor path
            inputs = processor(
                text=prompt,
                images=pil_image,
                return_tensors="pt"
            ).to(device)
            with torch.no_grad():
                outputs = model.generate(**inputs)
        else:
            # Pipeline path
            outputs = model(pil_image, prompt)

        # Save video
        if hasattr(outputs, 'video'):
            video_frames = outputs.video[0].cpu().numpy()
            import cv2
            h, w = video_frames.shape[1:3]
            writer = cv2.VideoWriter(
                output_path,
                cv2.VideoWriter_fourcc(*'mp4v'),
                24, (w, h)
            )
            for frame in video_frames:
                frame_bgr = cv2.cvtColor(
                    (frame * 255).astype(np.uint8),
                    cv2.COLOR_RGB2BGR
                )
                writer.write(frame_bgr)
            writer.release()
        elif isinstance(outputs, str) and os.path.exists(outputs):
            shutil.copy(outputs, output_path)
        elif isinstance(outputs, list) and len(outputs) > 0:
            out = outputs[0]
            if isinstance(out, str) and os.path.exists(out):
                shutil.copy(out, output_path)
            elif hasattr(out, 'get'):
                v = out.get('video') or out.get('path')
                if v:
                    shutil.copy(v, output_path)

        return output_path

    except Exception as e:
        raise gr.Error(f"Error: {str(e)}")


with gr.Blocks(theme=gr.themes.Soft()) as demo:
    gr.Markdown("""
# 🎬 OVI β€” Talking Avatar Generator
**Free & Open Source** | No login required
""")
    with gr.Row():
        with gr.Column():
            image_input = gr.Image(
                label="πŸ“Έ Upload Image",
                type="filepath",
                height=300,
            )
            prompt_input = gr.Textbox(
                label="πŸ’¬ Text Prompt",
                lines=3,
                placeholder="A person speaks. <S>Hello world!<E> <AUDCAP>Clear voice<ENDAUDCAP>",
            )
            generate_btn = gr.Button("🎬 Generate Video", variant="primary", size="lg")
            clear_btn = gr.Button("πŸ—‘οΈ Clear", variant="secondary")

        with gr.Column():
            video_output = gr.Video(
                label="πŸŽ₯ Generated Video",
                height=300,
                autoplay=True,
            )

    gr.Markdown("""
### πŸ’‘ Tips:
- `<S>speech here<E>` β€” what avatar says
- `<AUDCAP>voice style<ENDAUDCAP>` β€” voice description
""")

    generate_btn.click(
        fn=generate_video,
        inputs=[image_input, prompt_input],
        outputs=[video_output],
    )
    clear_btn.click(
        fn=lambda: (None, "", None),
        outputs=[image_input, prompt_input, video_output],
    )

if __name__ == "__main__":
    demo.launch(show_api=True)