VoiceClips commited on
Commit
4db023e
·
verified ·
1 Parent(s): e55539f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +8 -17
app.py CHANGED
@@ -9,8 +9,9 @@ import json
9
  import shutil
10
  from typing import Optional
11
 
12
- # Google API Kararlı Sürüm Zorlaması (Beta Devri Bitti!)
13
- os.environ["GEMINI_API_VERSION"] = "v1"
 
14
 
15
  app = FastAPI(title="VoiceClips heavy video processor (Wav2Lip + FFmpeg)")
16
 
@@ -330,7 +331,6 @@ def run_simulation_pipeline(job: TranslationJob, supabase_url: str, supabase_ano
330
  time.sleep(1)
331
 
332
  # Target Lang Mock URL selector
333
- # To make it feel premium, we can point to a high quality public MP4 file
334
  mock_output_video = "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerEscapes.mp4"
335
 
336
  print(f"[{video_id}] Simulation complete. Updating database to completed.")
@@ -374,8 +374,7 @@ def run_production_pipeline(job: TranslationJob, gemini_key: str, elevenlabs_key
374
  print(f"[{video_id}] Standardizing downloaded video to MP4 format...")
375
  cmd_standardize = [
376
  "ffmpeg", "-y", "-i", downloaded_video_path,
377
- "-c:v", "libx264", "-pix_fmt", "yuv420p", "-r", "25",
378
- "-c:a", "aac", "-ar", "16000", "-ac", "1",
379
  input_video_path
380
  ]
381
  subprocess.run(cmd_standardize, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
@@ -394,7 +393,9 @@ def run_production_pipeline(job: TranslationJob, gemini_key: str, elevenlabs_key
394
  with open(extracted_audio_path, "rb") as audio_file:
395
  audio_data = base64.b64encode(audio_file.read()).decode("utf-8")
396
 
397
- gemini_url = f"https://generativelanguage.googleapis.com/v1/models/gemini-2.0-flash:generateContent?key={gemini_key}"
 
 
398
 
399
  if job.has_captions:
400
  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."
@@ -436,7 +437,6 @@ def run_production_pipeline(job: TranslationJob, gemini_key: str, elevenlabs_key
436
 
437
  # 4. Synthesize voice cloning using ElevenLabs API
438
  print(f"[{video_id}] Calling ElevenLabs TTS Voice Cloning with tone '{job.voice_tone}'...")
439
- # We can use the default standard voice (e.g. Rachel: 21m00Tcm4TlvDq8ikWAM)
440
  voice_id = "21m00Tcm4TlvDq8ikWAM"
441
  elevenlabs_url = f"https://api.elevenlabs.io/v1/text-to-speech/{voice_id}"
442
 
@@ -445,7 +445,6 @@ def run_production_pipeline(job: TranslationJob, gemini_key: str, elevenlabs_key
445
  "Content-Type": "application/json"
446
  }
447
 
448
- # Optional stability configurations based on voice tone
449
  stability = 0.5
450
  similarity_boost = 0.75
451
  if job.voice_tone == 'excited':
@@ -488,7 +487,6 @@ def run_production_pipeline(job: TranslationJob, gemini_key: str, elevenlabs_key
488
  "--outfile", f"../{lipsync_output_path}"
489
  ]
490
 
491
- # Execute in the Wav2Lip directory to resolve relative imports
492
  result = subprocess.run(cmd_lipsync, cwd="Wav2Lip", capture_output=True, text=True)
493
  if result.returncode != 0:
494
  print(f"Wav2Lip stdout: {result.stdout}")
@@ -510,8 +508,6 @@ def run_production_pipeline(job: TranslationJob, gemini_key: str, elevenlabs_key
510
  )
511
 
512
  if job.has_lip_sync:
513
- # Lip-synced video already has the synthesized audio merged inside it.
514
- # So we map audio track from the same file (0:a)
515
  cmd_merge = [
516
  "ffmpeg", "-y", "-i", video_src_for_subtitles,
517
  "-vf", f"subtitles={srt_file_path}:force_style='{style_str}'",
@@ -520,7 +516,6 @@ def run_production_pipeline(job: TranslationJob, gemini_key: str, elevenlabs_key
520
  output_video_path
521
  ]
522
  else:
523
- # Map audio from input 1 (synthesized audio path)
524
  cmd_merge = [
525
  "ffmpeg", "-y", "-i", video_src_for_subtitles, "-i", synthesized_audio_path,
526
  "-vf", f"subtitles={srt_file_path}:force_style='{style_str}'",
@@ -542,7 +537,6 @@ def run_production_pipeline(job: TranslationJob, gemini_key: str, elevenlabs_key
542
  ]
543
  subprocess.run(cmd_merge, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
544
 
545
- # Normalize Supabase base URL (remove trailing slash and rest/v1 path if present)
546
  base_url = supabase_url.rstrip("/")
547
  if base_url.endswith("/rest/v1"):
548
  base_url = base_url[:-8].rstrip("/")
@@ -558,13 +552,11 @@ def run_production_pipeline(job: TranslationJob, gemini_key: str, elevenlabs_key
558
  "Content-Type": "video/mp4"
559
  }
560
  upload_res = requests.post(storage_upload_url, headers=upload_headers, data=out_file)
561
- # If exists, we can try to PUT (overwrite)
562
  if upload_res.status_code == 400 and "AlreadyExists" in upload_res.text:
563
  upload_res = requests.put(storage_upload_url, headers=upload_headers, data=out_file)
564
 
565
  upload_res.raise_for_status()
566
 
567
- # Get public url
568
  public_video_url = f"{base_url}/storage/v1/object/public/videos/{video_id}_translated.mp4"
569
  print(f"[{video_id}] Video successfully uploaded. Public URL: {public_video_url}")
570
 
@@ -591,6 +583,5 @@ def process_video(job: TranslationJob, background_tasks: BackgroundTasks):
591
 
592
  if __name__ == "__main__":
593
  import uvicorn
594
- # Make sure we load local variables before starting
595
  load_env_local()
596
- uvicorn.run(app, host="0.0.0.0", port=7860)
 
9
  import shutil
10
  from typing import Optional
11
 
12
+ # 🎯 DÜZELTME 1: Google API için v1beta sürümünü zorunlu kılıyoruz.
13
+ # Gemini 2.0 Flash modeli faturalı (Paid) hesaplarda bile sadece v1beta otoyolunda çalışır.
14
+ os.environ["GEMINI_API_VERSION"] = "v1beta"
15
 
16
  app = FastAPI(title="VoiceClips heavy video processor (Wav2Lip + FFmpeg)")
17
 
 
331
  time.sleep(1)
332
 
333
  # Target Lang Mock URL selector
 
334
  mock_output_video = "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerEscapes.mp4"
335
 
336
  print(f"[{video_id}] Simulation complete. Updating database to completed.")
 
374
  print(f"[{video_id}] Standardizing downloaded video to MP4 format...")
375
  cmd_standardize = [
376
  "ffmpeg", "-y", "-i", downloaded_video_path,
377
+ "25", "-c:a", "aac", "-ar", "16000", "-ac", "1",
 
378
  input_video_path
379
  ]
380
  subprocess.run(cmd_standardize, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
 
393
  with open(extracted_audio_path, "rb") as audio_file:
394
  audio_data = base64.b64encode(audio_file.read()).decode("utf-8")
395
 
396
+ # 🎯 DÜZELTME 2: Endpoint URL'ini tam olarak v1beta'ya yönlendiriyoruz.
397
+ # Artık hem faturalı bakiyemiz devrede hem de model jilet gibi adreste bulunacak!
398
+ gemini_url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key={gemini_key}"
399
 
400
  if job.has_captions:
401
  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."
 
437
 
438
  # 4. Synthesize voice cloning using ElevenLabs API
439
  print(f"[{video_id}] Calling ElevenLabs TTS Voice Cloning with tone '{job.voice_tone}'...")
 
440
  voice_id = "21m00Tcm4TlvDq8ikWAM"
441
  elevenlabs_url = f"https://api.elevenlabs.io/v1/text-to-speech/{voice_id}"
442
 
 
445
  "Content-Type": "application/json"
446
  }
447
 
 
448
  stability = 0.5
449
  similarity_boost = 0.75
450
  if job.voice_tone == 'excited':
 
487
  "--outfile", f"../{lipsync_output_path}"
488
  ]
489
 
 
490
  result = subprocess.run(cmd_lipsync, cwd="Wav2Lip", capture_output=True, text=True)
491
  if result.returncode != 0:
492
  print(f"Wav2Lip stdout: {result.stdout}")
 
508
  )
509
 
510
  if job.has_lip_sync:
 
 
511
  cmd_merge = [
512
  "ffmpeg", "-y", "-i", video_src_for_subtitles,
513
  "-vf", f"subtitles={srt_file_path}:force_style='{style_str}'",
 
516
  output_video_path
517
  ]
518
  else:
 
519
  cmd_merge = [
520
  "ffmpeg", "-y", "-i", video_src_for_subtitles, "-i", synthesized_audio_path,
521
  "-vf", f"subtitles={srt_file_path}:force_style='{style_str}'",
 
537
  ]
538
  subprocess.run(cmd_merge, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
539
 
 
540
  base_url = supabase_url.rstrip("/")
541
  if base_url.endswith("/rest/v1"):
542
  base_url = base_url[:-8].rstrip("/")
 
552
  "Content-Type": "video/mp4"
553
  }
554
  upload_res = requests.post(storage_upload_url, headers=upload_headers, data=out_file)
 
555
  if upload_res.status_code == 400 and "AlreadyExists" in upload_res.text:
556
  upload_res = requests.put(storage_upload_url, headers=upload_headers, data=out_file)
557
 
558
  upload_res.raise_for_status()
559
 
 
560
  public_video_url = f"{base_url}/storage/v1/object/public/videos/{video_id}_translated.mp4"
561
  print(f"[{video_id}] Video successfully uploaded. Public URL: {public_video_url}")
562
 
 
583
 
584
  if __name__ == "__main__":
585
  import uvicorn
 
586
  load_env_local()
587
+ uvicorn.run(app, host="0.0.0.0", port=7860)