Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
|
@@ -412,13 +412,10 @@ def run_production_pipeline(job: TranslationJob, gemini_key: str, elevenlabs_key
|
|
| 412 |
run_ffmpeg_command(cmd_extract, "Audio Extraction")
|
| 413 |
|
| 414 |
# 3. Request Transcription & Translation from Gemini 2.5 Flash
|
| 415 |
-
print(f"[{video_id}] Calling Gemini
|
| 416 |
with open(extracted_audio_path, "rb") as audio_file:
|
| 417 |
audio_data = base64.b64encode(audio_file.read()).decode("utf-8")
|
| 418 |
|
| 419 |
-
# 🎯 DÜZELTME 3: Endpoint URL'i v1beta olarak bırakıldı, faturalı bakiye ile limitsiz akacak!
|
| 420 |
-
gemini_url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key={gemini_key}"
|
| 421 |
-
|
| 422 |
if job.has_captions:
|
| 423 |
gemini_prompt = f"Transcribe the following audio, translate it accurately to '{job.target_lang}', and output the result in SRT subtitle format. Keep each caption line short (max 4-5 words) and ensure the timing is aligned with the audio. Output ONLY the raw SRT text, no extra markdown formatting, tags, or explanations."
|
| 424 |
else:
|
|
@@ -441,9 +438,45 @@ def run_production_pipeline(job: TranslationJob, gemini_key: str, elevenlabs_key
|
|
| 441 |
}
|
| 442 |
]
|
| 443 |
}
|
| 444 |
-
|
| 445 |
-
|
| 446 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 447 |
|
| 448 |
gemini_output = gemini_data["candidates"][0]["content"]["parts"][0]["text"].strip()
|
| 449 |
|
|
@@ -670,10 +703,10 @@ def run_production_pipeline(job: TranslationJob, gemini_key: str, elevenlabs_key
|
|
| 670 |
}
|
| 671 |
upload_res = requests.post(storage_upload_url, headers=upload_headers, data=out_file)
|
| 672 |
# If exists, we can try to PUT (overwrite)
|
| 673 |
-
|
| 674 |
upload_res = requests.put(storage_upload_url, headers=upload_headers, data=out_file)
|
| 675 |
-
|
| 676 |
-
|
| 677 |
|
| 678 |
# Get public url
|
| 679 |
public_video_url = f"{base_url}/storage/v1/object/public/videos/{video_id}_translated.mp4"
|
|
|
|
| 412 |
run_ffmpeg_command(cmd_extract, "Audio Extraction")
|
| 413 |
|
| 414 |
# 3. Request Transcription & Translation from Gemini 2.5 Flash
|
| 415 |
+
print(f"[{video_id}] Calling Gemini for transcription/translation to '{job.target_lang}'...")
|
| 416 |
with open(extracted_audio_path, "rb") as audio_file:
|
| 417 |
audio_data = base64.b64encode(audio_file.read()).decode("utf-8")
|
| 418 |
|
|
|
|
|
|
|
|
|
|
| 419 |
if job.has_captions:
|
| 420 |
gemini_prompt = f"Transcribe the following audio, translate it accurately to '{job.target_lang}', and output the result in SRT subtitle format. Keep each caption line short (max 4-5 words) and ensure the timing is aligned with the audio. Output ONLY the raw SRT text, no extra markdown formatting, tags, or explanations."
|
| 421 |
else:
|
|
|
|
| 438 |
}
|
| 439 |
]
|
| 440 |
}
|
| 441 |
+
|
| 442 |
+
# Retry logic: try gemini-2.5-flash up to 3 times (503/429/500 are transient),
|
| 443 |
+
# then fall back to gemini-2.0-flash-exp if it keeps failing.
|
| 444 |
+
GEMINI_MODELS = [
|
| 445 |
+
"gemini-2.5-flash", # Primary: best quality
|
| 446 |
+
"gemini-2.0-flash-exp", # Fallback: still very capable
|
| 447 |
+
]
|
| 448 |
+
RETRY_DELAYS = [5, 15, 30] # seconds between retries per model
|
| 449 |
+
|
| 450 |
+
gemini_data = None
|
| 451 |
+
last_error = None
|
| 452 |
+
|
| 453 |
+
for model_name in GEMINI_MODELS:
|
| 454 |
+
gemini_url = f"https://generativelanguage.googleapis.com/v1beta/models/{model_name}:generateContent?key={gemini_key}"
|
| 455 |
+
print(f"[{video_id}] Trying Gemini model: {model_name}")
|
| 456 |
+
|
| 457 |
+
for attempt, delay in enumerate(RETRY_DELAYS, start=1):
|
| 458 |
+
try:
|
| 459 |
+
gemini_res = requests.post(gemini_url, json=gemini_payload, timeout=300)
|
| 460 |
+
if gemini_res.status_code in (503, 429, 500):
|
| 461 |
+
last_error = f"HTTP {gemini_res.status_code}"
|
| 462 |
+
print(f"[{video_id}] Gemini {model_name} attempt {attempt} returned {gemini_res.status_code}. Retrying in {delay}s...")
|
| 463 |
+
time.sleep(delay)
|
| 464 |
+
continue
|
| 465 |
+
gemini_res.raise_for_status()
|
| 466 |
+
gemini_data = gemini_res.json()
|
| 467 |
+
print(f"[{video_id}] Gemini {model_name} responded successfully on attempt {attempt}.")
|
| 468 |
+
break # success
|
| 469 |
+
except Exception as e:
|
| 470 |
+
last_error = str(e)
|
| 471 |
+
print(f"[{video_id}] Gemini {model_name} attempt {attempt} failed: {e}. Retrying in {delay}s...")
|
| 472 |
+
time.sleep(delay)
|
| 473 |
+
|
| 474 |
+
if gemini_data:
|
| 475 |
+
break # got a response, no need to try next model
|
| 476 |
+
print(f"[{video_id}] All retries exhausted for {model_name}, trying next model...")
|
| 477 |
+
|
| 478 |
+
if not gemini_data:
|
| 479 |
+
raise Exception(f"Gemini API failed after all retries and model fallbacks. Last error: {last_error}")
|
| 480 |
|
| 481 |
gemini_output = gemini_data["candidates"][0]["content"]["parts"][0]["text"].strip()
|
| 482 |
|
|
|
|
| 703 |
}
|
| 704 |
upload_res = requests.post(storage_upload_url, headers=upload_headers, data=out_file)
|
| 705 |
# If exists, we can try to PUT (overwrite)
|
| 706 |
+
if upload_res.status_code == 400 and "AlreadyExists" in upload_res.text:
|
| 707 |
upload_res = requests.put(storage_upload_url, headers=upload_headers, data=out_file)
|
| 708 |
+
|
| 709 |
+
upload_res.raise_for_status()
|
| 710 |
|
| 711 |
# Get public url
|
| 712 |
public_video_url = f"{base_url}/storage/v1/object/public/videos/{video_id}_translated.mp4"
|