Spaces:
Paused
Paused
Update main.py
Browse files
main.py
CHANGED
|
@@ -2274,7 +2274,6 @@ def local_merge_videos(base_video_bytes, new_clip_bytes):
|
|
| 2274 |
|
| 2275 |
async def helper_generate_image_for_video(prompt, action_name, width, height):
|
| 2276 |
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"}
|
| 2277 |
-
# تلاش برای ساخت تصویر تا ۳ بار در صورت برخورد با محدودیت
|
| 2278 |
for attempt in range(3):
|
| 2279 |
try:
|
| 2280 |
payload = {"prompt": prompt, "width": width, "height": height, "action_name": action_name}
|
|
@@ -2285,7 +2284,7 @@ async def helper_generate_image_for_video(prompt, action_name, width, height):
|
|
| 2285 |
run_id = data.get("run_id")
|
| 2286 |
if run_id:
|
| 2287 |
waited = 0
|
| 2288 |
-
while waited < 100:
|
| 2289 |
await asyncio.sleep(5)
|
| 2290 |
waited += 5
|
| 2291 |
try:
|
|
@@ -2301,58 +2300,6 @@ async def helper_generate_image_for_video(prompt, action_name, width, height):
|
|
| 2301 |
await asyncio.sleep(5)
|
| 2302 |
return None
|
| 2303 |
|
| 2304 |
-
async def helper_optimize_video_prompt(image_bytes, user_prompt):
|
| 2305 |
-
if not GEMINI_KEYS:
|
| 2306 |
-
return None
|
| 2307 |
-
|
| 2308 |
-
master_prompt = """You are an expert AI Animation Planner. Your absolute highest priority is to faithfully and creatively execute the user's specific request based on the provided image.
|
| 2309 |
-
|
| 2310 |
-
1. If the user prompt is empty or generic (like "animate this"), add subtle, high-quality, believable cinematic motion (e.g., slow zoom, water flowing, wind in hair).
|
| 2311 |
-
2. If the user gives specific directions, focus ENTIRELY on executing that command perfectly. If the action is not visible in-frame, use cinematic camera movements to reveal it.
|
| 2312 |
-
3. You must output ONLY a highly detailed, descriptive animation prompt in ENGLISH. Do not translate literally; ENHANCE the prompt for a text-to-video AI model.
|
| 2313 |
-
4. MUST Include keywords at the end: cinematic, photorealistic, high detail, smooth motion, 8k.
|
| 2314 |
-
|
| 2315 |
-
CRITICAL RULE: DO NOT say "Here is the prompt" or give any conversational explanations. DO NOT output JSON. Output ONLY the raw English animation prompt text and NOTHING ELSE."""
|
| 2316 |
-
|
| 2317 |
-
prompt_for_ai = user_prompt if user_prompt else "لطفاً این تصویر را به یک ویدیوی سینمایی بسیار جذاب و واقعگرایانه متحرک کن."
|
| 2318 |
-
combined_prompt = f"{master_prompt}\n\nUser request: {prompt_for_ai}"
|
| 2319 |
-
|
| 2320 |
-
base64_data = base64.b64encode(image_bytes).decode('utf-8')
|
| 2321 |
-
mime_type = "image/jpeg"
|
| 2322 |
-
|
| 2323 |
-
for attempt in range(2):
|
| 2324 |
-
keys_to_try = get_next_gemini_keys(50)
|
| 2325 |
-
async with aiohttp.ClientSession() as session:
|
| 2326 |
-
for key in keys_to_try:
|
| 2327 |
-
url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key={key}"
|
| 2328 |
-
payload = {
|
| 2329 |
-
"contents": [{
|
| 2330 |
-
"parts": [
|
| 2331 |
-
{"text": combined_prompt},
|
| 2332 |
-
{"inlineData": {"mimeType": mime_type, "data": base64_data}}
|
| 2333 |
-
]
|
| 2334 |
-
}],
|
| 2335 |
-
"generationConfig": {"temperature": 0.7, "maxOutputTokens": 1024}
|
| 2336 |
-
}
|
| 2337 |
-
try:
|
| 2338 |
-
async with session.post(url, json=payload, timeout=20) as response:
|
| 2339 |
-
if response.status == 200:
|
| 2340 |
-
data = await response.json()
|
| 2341 |
-
try:
|
| 2342 |
-
enhanced_prompt = data["candidates"][0]["content"]["parts"][0]["text"]
|
| 2343 |
-
enhanced_prompt = enhanced_prompt.replace("```text", "").replace("```", "").replace("```json", "").strip()
|
| 2344 |
-
|
| 2345 |
-
if "پردازش متوقف شد" in enhanced_prompt or "سهمیه سرور موقتاً پر شده" in enhanced_prompt:
|
| 2346 |
-
continue
|
| 2347 |
-
|
| 2348 |
-
return enhanced_prompt
|
| 2349 |
-
except (KeyError, IndexError):
|
| 2350 |
-
continue
|
| 2351 |
-
except Exception:
|
| 2352 |
-
continue
|
| 2353 |
-
await asyncio.sleep(2)
|
| 2354 |
-
return None
|
| 2355 |
-
|
| 2356 |
async def process_video_generation(client, chat_id, video_type, prompt, duration_int, image_bytes, txt_model_action=None, width=1024, height=1024):
|
| 2357 |
str_chat_id = str(chat_id).replace("`", "").replace("'", "").replace('"', "").strip()
|
| 2358 |
creds = get_user_credits(str_chat_id)
|
|
@@ -2374,12 +2321,63 @@ async def process_video_generation(client, chat_id, video_type, prompt, duration
|
|
| 2374 |
|
| 2375 |
current_image_bytes = await asyncio.to_thread(force_jpeg, current_image_bytes)
|
| 2376 |
|
| 2377 |
-
# پرامپت
|
| 2378 |
-
proc_msg = await update_status_msg(client, chat_id, proc_msg, "🧠 در حال درک تصویر و بهین
|
| 2379 |
-
eng_prompt = await helper_optimize_video_prompt(current_image_bytes, prompt)
|
| 2380 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2381 |
if eng_prompt:
|
| 2382 |
-
|
|
|
|
| 2383 |
await asyncio.sleep(3)
|
| 2384 |
else:
|
| 2385 |
try:
|
|
@@ -2388,18 +2386,27 @@ async def process_video_generation(client, chat_id, video_type, prompt, duration
|
|
| 2388 |
except:
|
| 2389 |
eng_prompt = "cinematic motion, photorealistic, high detail, smooth animation, 8k"
|
| 2390 |
|
| 2391 |
-
op_name = "متحرکسازی تصاویر" if video_type == "animate" else "ساخت ویدیو"
|
| 2392 |
-
proc_msg = await update_status_msg(client, chat_id, proc_msg, f"🎬 عملیات {op_name} آغاز شد.\n⏱ زمان نهایی: {duration_int} ثانیه")
|
| 2393 |
-
|
| 2394 |
for loop_idx in range(loops_needed):
|
| 2395 |
new_clip_bytes = None
|
| 2396 |
-
step_text_base = f"🎬 بخش {loop_idx + 1} از {loops_needed}"
|
| 2397 |
|
| 2398 |
-
# تلاش مجدد تا ۳ بار برای هر رندر ۵ ثانیهای
|
| 2399 |
for attempt in range(3):
|
| 2400 |
run_id = str(uuid.uuid4())
|
| 2401 |
-
|
| 2402 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2403 |
|
| 2404 |
input_filename = f"{run_id}_input.jpg"
|
| 2405 |
with open(f"static/images/{input_filename}", "wb") as f:
|
|
@@ -2407,8 +2414,6 @@ async def process_video_generation(client, chat_id, video_type, prompt, duration
|
|
| 2407 |
|
| 2408 |
image_public_url = f"{RUBIKA_SPACE_URL}/static/images/{input_filename}"
|
| 2409 |
|
| 2410 |
-
dispatch_url = f"https://api.github.com/repos/{GITHUB_USER}/{GITHUB_REPO}/dispatches"
|
| 2411 |
-
dispatch_headers = {"Accept": "application/vnd.github.v3+json", "Authorization": f"token {GITHUB_TOKEN}"}
|
| 2412 |
dispatch_payload = {
|
| 2413 |
"event_type": "generate-video",
|
| 2414 |
"client_payload": {
|
|
@@ -2423,15 +2428,18 @@ async def process_video_generation(client, chat_id, video_type, prompt, duration
|
|
| 2423 |
try:
|
| 2424 |
resp = await asyncio.to_thread(requests.post, dispatch_url, headers=dispatch_headers, json=dispatch_payload, timeout=20)
|
| 2425 |
if resp.status_code != 204:
|
| 2426 |
-
proc_msg = await update_status_msg(client, chat_id, proc_msg, f"❌ خطای گیتهاب در پذیرش دستور: {resp.text}")
|
| 2427 |
await asyncio.sleep(4)
|
| 2428 |
continue
|
| 2429 |
-
except Exception
|
| 2430 |
-
proc_msg = await update_status_msg(client, chat_id, proc_msg, f"❌ خطای اتصال به اکشن: {str(e)[:50]}")
|
| 2431 |
await asyncio.sleep(4)
|
| 2432 |
continue
|
| 2433 |
|
| 2434 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2435 |
|
| 2436 |
waited = 0
|
| 2437 |
while waited < 180: # انتظار تا 180 ثانیه (3 دقیقه)
|
|
@@ -2455,33 +2463,32 @@ async def process_video_generation(client, chat_id, video_type, prompt, duration
|
|
| 2455 |
if new_clip_bytes:
|
| 2456 |
break
|
| 2457 |
else:
|
| 2458 |
-
proc_msg = await update_status_msg(client, chat_id, proc_msg, step_text + "⚠️ محدودیت زمانی در رندر یا خطای ترافیک. ایجاد درخواست و اکشن جدید...")
|
| 2459 |
await asyncio.sleep(5)
|
| 2460 |
|
| 2461 |
if not new_clip_bytes:
|
| 2462 |
-
return await update_status_msg(client, chat_id, proc_msg, "❌
|
| 2463 |
|
| 2464 |
if base_video_bytes is not None:
|
| 2465 |
-
proc_msg = await update_status_msg(client, chat_id, proc_msg,
|
| 2466 |
base_video_bytes = await asyncio.to_thread(local_merge_videos, base_video_bytes, new_clip_bytes)
|
| 2467 |
else:
|
| 2468 |
base_video_bytes = new_clip_bytes
|
| 2469 |
|
| 2470 |
if loop_idx < loops_needed - 1:
|
| 2471 |
current_secs = (loop_idx + 1) * 5
|
| 2472 |
-
proc_msg = await update_status_msg(client, chat_id, proc_msg,
|
| 2473 |
current_image_bytes = await asyncio.to_thread(helper_extract_last_frame, base_video_bytes)
|
| 2474 |
if not current_image_bytes:
|
| 2475 |
await update_status_msg(client, chat_id, proc_msg, "⚠️ استخراج فریم با مشکل مواجه شد. عملیات در همین نقطه پایان یافت.")
|
| 2476 |
break
|
| 2477 |
|
| 2478 |
-
proc_msg = await update_status_msg(client, chat_id, proc_msg, "🚀 ویدیو کاملاً آماده شد! در حال آپلود سریع...")
|
| 2479 |
|
| 2480 |
try:
|
| 2481 |
file_name = f"video_{uuid.uuid4().hex}.mp4"
|
| 2482 |
await asyncio.to_thread(sync_write_file, file_name, base_video_bytes)
|
| 2483 |
|
| 2484 |
-
caption_text = f"🎞 ویدیو شما با موفقیت آماده شد!\n⏱ زمان: {duration_int} ثانیه\n✨ پرامپت
|
| 2485 |
upload_result = False
|
| 2486 |
|
| 2487 |
for up_att in range(3):
|
|
|
|
| 2274 |
|
| 2275 |
async def helper_generate_image_for_video(prompt, action_name, width, height):
|
| 2276 |
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"}
|
|
|
|
| 2277 |
for attempt in range(3):
|
| 2278 |
try:
|
| 2279 |
payload = {"prompt": prompt, "width": width, "height": height, "action_name": action_name}
|
|
|
|
| 2284 |
run_id = data.get("run_id")
|
| 2285 |
if run_id:
|
| 2286 |
waited = 0
|
| 2287 |
+
while waited < 100:
|
| 2288 |
await asyncio.sleep(5)
|
| 2289 |
waited += 5
|
| 2290 |
try:
|
|
|
|
| 2300 |
await asyncio.sleep(5)
|
| 2301 |
return None
|
| 2302 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2303 |
async def process_video_generation(client, chat_id, video_type, prompt, duration_int, image_bytes, txt_model_action=None, width=1024, height=1024):
|
| 2304 |
str_chat_id = str(chat_id).replace("`", "").replace("'", "").replace('"', "").strip()
|
| 2305 |
creds = get_user_credits(str_chat_id)
|
|
|
|
| 2321 |
|
| 2322 |
current_image_bytes = await asyncio.to_thread(force_jpeg, current_image_bytes)
|
| 2323 |
|
| 2324 |
+
# 🧠 استفاده از Gemma 4 از طریق گیتهاب برای بهینهسازی پرامپت
|
| 2325 |
+
proc_msg = await update_status_msg(client, chat_id, proc_msg, "🧠 در حال درک تصویر و نگارش بهترین سناریو برای ویدیو توسط هوش مصنوعی...")
|
|
|
|
| 2326 |
|
| 2327 |
+
master_prompt = """You are an expert AI Animation Planner. Your absolute highest priority is to faithfully and creatively execute the user's specific request based on the provided image.
|
| 2328 |
+
|
| 2329 |
+
1. If the user prompt is empty or generic (like "animate this"), add subtle, high-quality, believable cinematic motion (e.g., slow zoom, water flowing, wind in hair).
|
| 2330 |
+
2. If the user gives specific directions, focus ENTIRELY on executing that command perfectly. If the action is not visible in-frame, use cinematic camera movements to reveal it.
|
| 2331 |
+
3. You must output ONLY a highly detailed, descriptive animation prompt in ENGLISH. Do not translate literally; ENHANCE the prompt for a text-to-video AI model.
|
| 2332 |
+
4. MUST Include keywords at the end: cinematic, photorealistic, high detail, smooth motion, 8k.
|
| 2333 |
+
|
| 2334 |
+
CRITICAL RULE: DO NOT say "Here is the prompt" or give any conversational explanations. DO NOT output JSON. Output ONLY the raw English animation prompt text and NOTHING ELSE."""
|
| 2335 |
+
|
| 2336 |
+
prompt_for_ai = prompt if prompt else "لطفاً این تصویر را به یک ویدیوی سینمایی بسیار جذاب و واقعگرایانه متحرک کن."
|
| 2337 |
+
combined_prompt = f"{master_prompt}\n\nUser request: {prompt_for_ai}"
|
| 2338 |
+
|
| 2339 |
+
gemma_run_id = f"gemma_{uuid.uuid4().hex[:8]}"
|
| 2340 |
+
gemma_filename = f"{gemma_run_id}.jpg"
|
| 2341 |
+
with open(f"static/images/{gemma_filename}", "wb") as f:
|
| 2342 |
+
f.write(current_image_bytes)
|
| 2343 |
+
gemma_image_url = f"{RUBIKA_SPACE_URL}/static/images/{gemma_filename}"
|
| 2344 |
+
|
| 2345 |
+
dispatch_url = f"https://api.github.com/repos/{GITHUB_USER}/{GITHUB_REPO}/dispatches"
|
| 2346 |
+
dispatch_headers = {"Accept": "application/vnd.github.v3+json", "Authorization": f"token {GITHUB_TOKEN}"}
|
| 2347 |
+
gemma_payload = {
|
| 2348 |
+
"event_type": "chat-gemma",
|
| 2349 |
+
"client_payload": {
|
| 2350 |
+
"prompt": combined_prompt,
|
| 2351 |
+
"file_url": gemma_image_url,
|
| 2352 |
+
"file_mime": "image/jpeg",
|
| 2353 |
+
"run_id": gemma_run_id,
|
| 2354 |
+
"space_url": RUBIKA_SPACE_URL
|
| 2355 |
+
}
|
| 2356 |
+
}
|
| 2357 |
+
|
| 2358 |
+
eng_prompt = None
|
| 2359 |
+
try:
|
| 2360 |
+
resp = await asyncio.to_thread(requests.post, dispatch_url, headers=dispatch_headers, json=gemma_payload, timeout=20)
|
| 2361 |
+
if resp.status_code == 204:
|
| 2362 |
+
waited = 0
|
| 2363 |
+
while waited < 90:
|
| 2364 |
+
txt_path = f"static/images/{gemma_run_id}.txt"
|
| 2365 |
+
if os.path.exists(txt_path):
|
| 2366 |
+
with open(txt_path, "r", encoding="utf-8") as f:
|
| 2367 |
+
eng_prompt = f.read().strip()
|
| 2368 |
+
os.remove(txt_path)
|
| 2369 |
+
break
|
| 2370 |
+
await asyncio.sleep(3)
|
| 2371 |
+
waited += 3
|
| 2372 |
+
except Exception as e:
|
| 2373 |
+
print("Gemma action error:", e)
|
| 2374 |
+
|
| 2375 |
+
try: os.remove(f"static/images/{gemma_filename}")
|
| 2376 |
+
except: pass
|
| 2377 |
+
|
| 2378 |
if eng_prompt:
|
| 2379 |
+
eng_prompt = eng_prompt.replace("```text", "").replace("```", "").replace("```json", "").strip()
|
| 2380 |
+
proc_msg = await update_status_msg(client, chat_id, proc_msg, f"✅ سناریوی ویدیوی شما بهینهسازی شد:\n\n`{eng_prompt}`")
|
| 2381 |
await asyncio.sleep(3)
|
| 2382 |
else:
|
| 2383 |
try:
|
|
|
|
| 2386 |
except:
|
| 2387 |
eng_prompt = "cinematic motion, photorealistic, high detail, smooth animation, 8k"
|
| 2388 |
|
|
|
|
|
|
|
|
|
|
| 2389 |
for loop_idx in range(loops_needed):
|
| 2390 |
new_clip_bytes = None
|
|
|
|
| 2391 |
|
|
|
|
| 2392 |
for attempt in range(3):
|
| 2393 |
run_id = str(uuid.uuid4())
|
| 2394 |
+
|
| 2395 |
+
# مدیریت هوشمند پیامهای نمایشی بدون اصطلاحات فنی
|
| 2396 |
+
if loops_needed == 1:
|
| 2397 |
+
if attempt == 0:
|
| 2398 |
+
msg_txt = "🎬 در حال ارسال درخواست به سرورهای قدرتمند رندر ویدیو..."
|
| 2399 |
+
else:
|
| 2400 |
+
msg_txt = "⚠️ به دلیل شلوغی سرور، در حال تلاش مجدد با یک مسیر آزادتر..."
|
| 2401 |
+
else:
|
| 2402 |
+
start_sec = loop_idx * 5
|
| 2403 |
+
end_sec = (loop_idx + 1) * 5
|
| 2404 |
+
if attempt == 0:
|
| 2405 |
+
msg_txt = f"🎬 در حال رندر ثانیههای {start_sec} تا {end_sec} از ویدیو..."
|
| 2406 |
+
else:
|
| 2407 |
+
msg_txt = f"⚠️ تلاش مجدد برای رندر ثانیههای {start_sec} تا {end_sec}..."
|
| 2408 |
+
|
| 2409 |
+
proc_msg = await update_status_msg(client, chat_id, proc_msg, msg_txt)
|
| 2410 |
|
| 2411 |
input_filename = f"{run_id}_input.jpg"
|
| 2412 |
with open(f"static/images/{input_filename}", "wb") as f:
|
|
|
|
| 2414 |
|
| 2415 |
image_public_url = f"{RUBIKA_SPACE_URL}/static/images/{input_filename}"
|
| 2416 |
|
|
|
|
|
|
|
| 2417 |
dispatch_payload = {
|
| 2418 |
"event_type": "generate-video",
|
| 2419 |
"client_payload": {
|
|
|
|
| 2428 |
try:
|
| 2429 |
resp = await asyncio.to_thread(requests.post, dispatch_url, headers=dispatch_headers, json=dispatch_payload, timeout=20)
|
| 2430 |
if resp.status_code != 204:
|
|
|
|
| 2431 |
await asyncio.sleep(4)
|
| 2432 |
continue
|
| 2433 |
+
except Exception:
|
|
|
|
| 2434 |
await asyncio.sleep(4)
|
| 2435 |
continue
|
| 2436 |
|
| 2437 |
+
if loops_needed == 1:
|
| 2438 |
+
wait_msg = "⏳ هوش مصنوعی در حال ساخت ویدیوی شماست.\n(این فرآیند معمولاً بین ۲ تا ۴ دقیقه زمان میبرد. لطفاً صبور باشید...)"
|
| 2439 |
+
else:
|
| 2440 |
+
wait_msg = "⏳ هوش مصنوعی در حال پردازش و رندر این بخش میباشد...\n(ممکن است چند دقیقه زمان ببرد)"
|
| 2441 |
+
|
| 2442 |
+
proc_msg = await update_status_msg(client, chat_id, proc_msg, wait_msg)
|
| 2443 |
|
| 2444 |
waited = 0
|
| 2445 |
while waited < 180: # انتظار تا 180 ثانیه (3 دقیقه)
|
|
|
|
| 2463 |
if new_clip_bytes:
|
| 2464 |
break
|
| 2465 |
else:
|
|
|
|
| 2466 |
await asyncio.sleep(5)
|
| 2467 |
|
| 2468 |
if not new_clip_bytes:
|
| 2469 |
+
return await update_status_msg(client, chat_id, proc_msg, "❌ متاسفانه به دلیل ترافیک سنگین سرورهای رندر، عملیات متوقف شد. لطفاً کمی بعد مجدداً تلاش کنید.")
|
| 2470 |
|
| 2471 |
if base_video_bytes is not None:
|
| 2472 |
+
proc_msg = await update_status_msg(client, chat_id, proc_msg, "🔄 در حال متصل کردن ویدیوهای ساخته شده به یکدیگر...")
|
| 2473 |
base_video_bytes = await asyncio.to_thread(local_merge_videos, base_video_bytes, new_clip_bytes)
|
| 2474 |
else:
|
| 2475 |
base_video_bytes = new_clip_bytes
|
| 2476 |
|
| 2477 |
if loop_idx < loops_needed - 1:
|
| 2478 |
current_secs = (loop_idx + 1) * 5
|
| 2479 |
+
proc_msg = await update_status_msg(client, chat_id, proc_msg, f"✅ {current_secs} ثانیه از ویدیو ساخته شد!\n📸 در حال آمادهسازی برای ساخت ثانیههای بعدی...")
|
| 2480 |
current_image_bytes = await asyncio.to_thread(helper_extract_last_frame, base_video_bytes)
|
| 2481 |
if not current_image_bytes:
|
| 2482 |
await update_status_msg(client, chat_id, proc_msg, "⚠️ استخراج فریم با مشکل مواجه شد. عملیات در همین نقطه پایان یافت.")
|
| 2483 |
break
|
| 2484 |
|
| 2485 |
+
proc_msg = await update_status_msg(client, chat_id, proc_msg, "🚀 ویدیو کاملاً آماده شد! در حال آپلود سریع در سرور روبیکا...")
|
| 2486 |
|
| 2487 |
try:
|
| 2488 |
file_name = f"video_{uuid.uuid4().hex}.mp4"
|
| 2489 |
await asyncio.to_thread(sync_write_file, file_name, base_video_bytes)
|
| 2490 |
|
| 2491 |
+
caption_text = f"🎞 ویدیو شما با موفقیت آماده شد!\n⏱ زمان: {duration_int} ثانیه\n✨ پرامپت بهینه شده:\n{eng_prompt}"
|
| 2492 |
upload_result = False
|
| 2493 |
|
| 2494 |
for up_att in range(3):
|