File size: 9,229 Bytes
0b909d1
 
 
 
 
 
 
 
 
 
 
 
 
 
cfe7995
 
 
 
 
 
 
 
0b909d1
 
 
 
 
 
 
 
 
 
 
 
 
 
cfe7995
 
 
0b909d1
cfe7995
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0b909d1
cfe7995
0b909d1
cfe7995
0b909d1
cfe7995
 
 
 
 
 
 
 
 
 
0b909d1
cfe7995
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0b909d1
 
 
cfe7995
0b909d1
 
 
 
 
 
cfe7995
0b909d1
55bc200
 
cfe7995
55bc200
cfe7995
 
55bc200
 
 
 
0b909d1
cfe7995
55bc200
 
cfe7995
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0b909d1
 
 
 
cfe7995
0b909d1
 
 
 
 
cfe7995
0b909d1
 
 
 
 
cfe7995
0b909d1
 
 
 
 
cfe7995
0b909d1
 
 
 
cfe7995
0b909d1
 
cfe7995
 
0b909d1
 
 
cfe7995
0b909d1
 
 
cfe7995
55bc200
 
 
 
 
 
 
cfe7995
55bc200
 
 
cfe7995
55bc200
1bbd1d4
7b7aba3
55bc200
 
658070f
55bc200
0b909d1
 
 
 
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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
# app.py
import os
import oss2
import sys
import uuid
import shutil
import time
import gradio as gr
import requests

import dashscope
from dashscope.utils.oss_utils import check_and_upload_local

DASHSCOPE_API_KEY = os.getenv("DASHSCOPE_API_KEY")

# چک کردن وجود API Key
if not DASHSCOPE_API_KEY:
    print("⚠️ هشدار: DASHSCOPE_API_KEY تنظیم نشده است!")
    print("برای استفاده از برنامه، لطفاً API Key را تنظیم کنید.")
    DASHSCOPE_API_KEY = None
else:
    dashscope.api_key = DASHSCOPE_API_KEY


class WanAnimateApp:
    def __init__(self, url, get_url):
        self.url = url
        self.get_url = get_url

    def predict(
        self, 
        ref_img,
        video,
        model_id,
        model,
    ):
        # چک کردن API Key قبل از شروع
        if not DASHSCOPE_API_KEY:
            return None, "خطا: DASHSCOPE_API_KEY تنظیم نشده است. لطفاً متغیر محیطی را تنظیم کنید."
        
        try:
            # آپلود فایل‌ها به OSS
            _, image_url = check_and_upload_local(model_id, ref_img, DASHSCOPE_API_KEY)
            _, video_url = check_and_upload_local(model_id, video, DASHSCOPE_API_KEY)

            # آماده‌سازی درخواست
            payload = {
                "model": model_id,
                "input": {
                    "image_url": image_url,
                    "video_url": video_url
                },
                "parameters": {
                    "check_image": True,
                    "mode": model,
                }
            }
            
            # تنظیم هدرها
            headers = {
                "X-DashScope-Async": "enable",
                "X-DashScope-OssResourceResolve": "enable",
                "Authorization": f"Bearer {DASHSCOPE_API_KEY}",
                "Content-Type": "application/json"
            }
            
            # ارسال درخواست اولیه
            url = self.url
            response = requests.post(url, json=payload, headers=headers)
            
            # چک کردن موفقیت درخواست
            if response.status_code != 200:
                return None, f"خطا در درخواست: {response.status_code}: {response.text}"
            
            # دریافت task ID
            result = response.json()
            task_id = result.get("output", {}).get("task_id")
            if not task_id:
                return None, "خطا: دریافت task ID انجام نشد"
            
            # پولینگ برای نتایج
            get_url = f"{self.get_url}/{task_id}"
            headers = {
                "Authorization": f"Bearer {DASHSCOPE_API_KEY}",
                "Content-Type": "application/json"
            }
            
            while True:
                response = requests.get(get_url, headers=headers)
                if response.status_code != 200:
                    return None, f"خطا در دریافت وضعیت: {response.status_code}: {response.text}"
                
                result = response.json()
                print(result)
                task_status = result.get("output", {}).get("task_status")
                
                if task_status == "SUCCEEDED":
                    video_url = result["output"]["results"]["video_url"]
                    return video_url, "موفق ✓"
                elif task_status == "FAILED":
                    error_msg = result.get("output", {}).get("message", "خطای ناشناخته")
                    code_msg = result.get("output", {}).get("code", "کد ناشناخته")
                    return None, f"تسک ناموفق: {error_msg} کد: {code_msg} TaskId: {task_id}"
                else:
                    # تسک در حال اجراست
                    time.sleep(5)
        
        except Exception as e:
            return None, f"خطا: {str(e)}"

def start_app():
    import argparse
    parser = argparse.ArgumentParser(description="Wan2.2-Animate ابزار تولید ویدیو")
    args = parser.parse_args()
    
    url = "https://dashscope.aliyuncs.com/api/v1/services/aigc/image2video/video-synthesis/"
    get_url = f"https://dashscope.aliyuncs.com/api/v1/tasks/"
    app = WanAnimateApp(url=url, get_url=get_url)

    with gr.Blocks(title="Wan2.2-Animate تولید ویدیو") as demo:
        gr.HTML("""
            <div style="padding: 2rem; text-align: center; max-width: 1200px; margin: 0 auto; font-family: Arial, sans-serif;">
                <h1 style="font-size: 2.5rem; font-weight: bold; margin-bottom: 0.5rem; color: #333;">
                    Wan2.2-Animate: Unified Character Animation and Replacement
                </h1>
                <h3 style="font-size: 2rem; font-weight: bold; margin-bottom: 0.5rem; color: #333;">
                    Wan2.2-Animate: مدل یکپارچه انیمیشن کاراکتر و جایگزینی شخصیت ویدیو
                </h3>
                <div style="font-size: 1.25rem; margin-bottom: 1.5rem; color: #555;">
                    Tongyi Lab, Alibaba
                </div>
            </div>
        """)
        
        gr.HTML("""
            <details>
                <summary>‼️ راهنمای استفاده</summary>
                
                <h4>دو حالت پشتیبانی می‌شود:</h4>
                <ul>
                    <li><strong>Move Mode</strong>: حرکت دادن کاراکتر تصویر ورودی با حرکات از ویدیو ورودی</li>
                    <li><strong>Mix Mode</strong>: جایگزینی کاراکتر ویدیو ورودی با کاراکتر از تصویر ورودی</li>
                </ul>
                
                <h4>محدودیت‌های ورودی:</h4>
                <ul>
                    <li>حجم فایل ویدیو: کمتر از 200MB</li>
                    <li>رزولوشن ویدیو: حداقل ضلع بیشتر از 200، حداکثر ضلع کمتر از 2048</li>
                    <li>مدت ویدیو: 2 تا 30 ثانیه</li>
                    <li>نسبت تصویر: 1:3 تا 3:1</li>
                    <li>فرمت ویدیو: mp4, avi, mov</li>
                    <li>حجم تصویر: کمتر از 5MB</li>
                    <li>رزولوشن تصویر: حداقل ضلع بیشتر از 200، حداکثر ضلع کمتر از 4096</li>
                    <li>فرمت تصویر: jpg, png, jpeg, webp, bmp</li>
                </ul>
                
                <h4>کیفیت استنتاج:</h4>
                <ul>
                    <li><strong>wan-pro</strong>: 25fps, 720p</li>
                    <li><strong>wan-std</strong>: 15fps, 720p</li>
                </ul>
            </details>
        """)

        with gr.Row():
            with gr.Column():    
                ref_img = gr.Image(
                    label="تصویر مرجع (Reference Image)",
                    type="filepath",
                    sources=["upload"],
                )
                
                video = gr.Video(
                    label="ویدیوی الگو (Template Video)",
                    sources=["upload"],
                )
                
                with gr.Row():
                    model_id = gr.Dropdown(
                        label="حالت (Mode)",
                        choices=["wan2.2-animate-move", "wan2.2-animate-mix"],
                        value="wan2.2-animate-move",
                    )

                    model = gr.Dropdown(
                        label="کیفیت استنتاج (Inference Quality)",
                        choices=["wan-pro", "wan-std"],
                        value="wan-pro",
                    )

                run_button = gr.Button("تولید ویدیو (Generate Video)")

            with gr.Column():
                output_video = gr.Video(label="ویدیوی خروجی (Output Video)")
                output_status = gr.Textbox(label="وضعیت (Status)")
        
        run_button.click(
            fn=app.predict,
            inputs=[ref_img, video, model_id, model],
            outputs=[output_video, output_status],
        )

        # مثال‌ها بدون کش
        example_data = [
            ['./examples/mov/1/1.jpeg', './examples/mov/1/1.mp4', 'wan2.2-animate-move', 'wan-pro'],
            ['./examples/mov/2/2.jpeg', './examples/mov/2/2.mp4', 'wan2.2-animate-move', 'wan-pro'],
            ['./examples/mix/1/1.jpeg', './examples/mix/1/1.mp4', 'wan2.2-animate-mix', 'wan-pro'],
            ['./examples/mix/2/2.jpeg', './examples/mix/2/2.mp4', 'wan2.2-animate-mix', 'wan-pro']
        ]

        if example_data and os.path.exists('./examples'):
            gr.Examples(
                examples=example_data,
                inputs=[ref_img, video, model_id, model],
                # outputs و fn و cache_examples را حذف کنید
            )
    
    demo.queue(default_concurrency_limit=100)
    demo.launch(
        server_name="0.0.0.0",
        server_port=7860
    )


if __name__ == "__main__":
    start_app()