habulaj commited on
Commit
b98dcb6
·
verified ·
1 Parent(s): f2593a4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +3 -155
app.py CHANGED
@@ -866,8 +866,8 @@ class GeminiSubtitleRequest(BaseModel):
866
  context: Optional[str] = "N/A"
867
  model: Optional[str] = "flash" # 'flash' or 'thinking'
868
 
869
- @app.post("/subtitle/gemini")
870
- async def generate_subtitle_gemini(request: GeminiSubtitleRequest):
871
  """
872
  Endpoint PRINCIPAL:
873
  1. Baixa e Processa áudio (Demucs opcional + Filtros FFmpeg)
@@ -907,7 +907,7 @@ async def generate_subtitle_gemini(request: GeminiSubtitleRequest):
907
  # 3. Montar Prompt
908
  processed_context = request.context if request.context else "N/A"
909
 
910
- prompt = f\"""
911
  Traduza essa legenda pro português do Brasil, corrija qualquer erro de formatação, pontuação e mantenha timestamps e os textos nos seus respectivos blocos de legenda.
912
 
913
  Deve traduzir exatamente o texto da legenda observando o contexto, não é pra migrar, por exemplo, textos de um bloco de legenda pra outro. Deve traduzir exatamente o texto de cada bloco de legenda, manter sempre as palavras, nunca retirar.
@@ -942,155 +942,3 @@ INSTRUÇÕES/CONTEXTO DO USUÁRIO: {processed_context}
942
  import traceback
943
  traceback.print_exc()
944
  raise HTTPException(status_code=500, detail=str(e))
945
-
946
- @app.get("/subtitle")
947
- async def generate_subtitle(
948
- file: str,
949
- context: Optional[str] = None,
950
- start: Optional[float] = None,
951
- end: Optional[float] = None,
952
- model: Optional[str] = "thinking",
953
- language: Optional[str] = None,
954
- temperature: Optional[float] = 0.4
955
- ):
956
- """
957
- Endpoint PRINCIPAL para gerar legendas traduzidas (PT-BR).
958
- Fluxo:
959
- 1. Gera SRT base com Groq + Filtro Netflix (via helper /subtitle/groq logic).
960
- 2. Envia SRT para Gemini traduzir para PT-BR mantendo formatação.
961
- """
962
- logs = []
963
- def log(msg):
964
- print(msg)
965
- logs.append(msg)
966
-
967
- if not chatbots:
968
- raise HTTPException(status_code=500, detail="Chatbot não inicializado")
969
-
970
- # Selecionar chatbot
971
- requested_model = model.lower() if model else "flash"
972
- if "thinking" in requested_model:
973
- selected_chatbot = chatbots.get('thinking', chatbots['default'])
974
- else:
975
- selected_chatbot = chatbots.get('flash', chatbots['default'])
976
-
977
- if not file:
978
- raise HTTPException(status_code=400, detail="Parâmetro 'file' é obrigatório")
979
-
980
- try:
981
- # 1. Gerar SRT Base (Groq)
982
- log(f"🎤 [Fase 1] Gerando SRT base com Groq...")
983
- srt_base, _, processed_audio_url = await get_groq_srt_base(file, language, temperature)
984
- log(f"✅ SRT Base gerado ({len(srt_base)} chars)")
985
-
986
- # 2. Traduzir com Gemini
987
- log(f"🧠 [Fase 2] Enviando para Gemini ({requested_model}) para tradução PT-BR (com contexto de vídeo)...")
988
-
989
- # Baixar arquivo para enviar ao Gemini
990
- log(f"⬇️ Baixando mídia para contexto...")
991
- response = download_file_with_retry(file)
992
- content_type = response.headers.get('content-type', '').lower()
993
-
994
- file_extension = '.mp4'
995
- media_type = 'video'
996
- if 'audio' in content_type:
997
- file_extension = '.mp3'
998
- media_type = 'audio'
999
-
1000
- temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=file_extension)
1001
- for chunk in response.iter_content(chunk_size=8192):
1002
- if chunk:
1003
- temp_file.write(chunk)
1004
- temp_file.close()
1005
- log(f"✅ Mídia baixada: {temp_file.name}")
1006
-
1007
- context_instruction = ""
1008
- if context:
1009
- context_instruction = f"\n6. **USER INSTRUCTIONS**: {context}\n"
1010
-
1011
- prompt = f"""Translate and Correct the SRT subtitles to Brazilian Portuguese (PT-BR).
1012
-
1013
- SOURCE MATERIAL: I have attached the video/audio file. Use it as the PRIMARY source of truth for context, speaker identification, and meaning.
1014
- INPUT SRT: I have provided a draft SRT generated by an automated transcription service.
1015
-
1016
- CRITICAL INSTRUCTIONS:
1017
- 1. **CORRECTION**: The input SRT is a draft. It may have wrong words or misinterpretations. **You MUST correct the text based on the actual audio.**
1018
- 2. **TIMESTAMPS**: The timestamps in the input SRT are generally correct. **Keep them as much as possible**, only adjust if they are clearly wrong / desynchronized.
1019
- 3. **FORMATTING**:
1020
- - Keep the visual structure (2 lines max).
1021
- - **DIALOGUES**: If two different people speak in the same block, separate them with a hyphen "- " at the start of each line.
1022
- * Example Input: "I did it. So did I."
1023
- * Example Output:
1024
- - Eu fiz isso.
1025
- - Eu também.
1026
- 4. **CONTEXT**: Translate naturally for a Brazilian audience. Prioritize clarity and meaning over literal translation. Make it readable and elegant.
1027
- 5. **PUNCTUATION**: Adjust punctuation to fit the context best.
1028
- 6. **OUTPUT**: Return ONLY the corrected and translated SRT content. No extra text.{context_instruction}
1029
-
1030
- DRAFT SRT:
1031
- {srt_base}
1032
- """
1033
-
1034
- # Helper function for retry logic
1035
- async def ask_with_retry(chatbot, prompt, media_file, media_type):
1036
- max_retries = 3
1037
- for attempt in range(max_retries):
1038
- # Passar video ou audio
1039
- kwargs = {}
1040
- if media_type == 'video':
1041
- kwargs['video'] = media_file
1042
- else:
1043
- kwargs['audio'] = media_file
1044
-
1045
- response = await chatbot.ask(prompt, **kwargs)
1046
- if response.get("error"):
1047
- content = response.get("content", "")
1048
- if "Failed to parse response body" in content and attempt < max_retries - 1:
1049
- log(f"⚠️ Erro de parsing (tentativa {attempt+1}/{max_retries}). Retentando...")
1050
- import asyncio
1051
- await asyncio.sleep(2)
1052
- continue
1053
- return response
1054
- return response
1055
-
1056
- response_gemini = await ask_with_retry(selected_chatbot, prompt, temp_file.name, media_type)
1057
-
1058
- # Limpar arquivo temporário
1059
- if os.path.exists(temp_file.name):
1060
- try:
1061
- os.unlink(temp_file.name)
1062
- except:
1063
- pass
1064
-
1065
- if response_gemini.get("error"):
1066
- raise HTTPException(
1067
- status_code=500,
1068
- detail=f"Erro no Gemini: {response_gemini.get('content', 'Erro desconhecido')}"
1069
- )
1070
-
1071
- srt_translated = response_gemini.get("content", "").strip()
1072
-
1073
- # Limpezas básicas no output do Gemini (caso ele devolva markdowns)
1074
- if "```srt" in srt_translated:
1075
- srt_translated = srt_translated.split("```srt")[1].split("```")[0].strip()
1076
- elif "```" in srt_translated:
1077
- srt_translated = srt_translated.split("```")[1].split("```")[0].strip()
1078
-
1079
- log(f"✅ Tradução concluída")
1080
-
1081
- # Retornar
1082
- return JSONResponse(
1083
- content={
1084
- "srt": srt_translated,
1085
- "success": True,
1086
- "processed_audio_url": processed_audio_url,
1087
- "logs": logs # Mantendo logs para debug se necessário
1088
- }
1089
- )
1090
-
1091
- except HTTPException:
1092
- raise
1093
- except Exception as e:
1094
- import traceback
1095
- traceback.print_exc()
1096
- raise HTTPException(status_code=500, detail=f"Erro ao gerar legendas: {str(e)}")
 
866
  context: Optional[str] = "N/A"
867
  model: Optional[str] = "flash" # 'flash' or 'thinking'
868
 
869
+ @app.post("/subtitle")
870
+ async def generate_subtitle(request: GeminiSubtitleRequest):
871
  """
872
  Endpoint PRINCIPAL:
873
  1. Baixa e Processa áudio (Demucs opcional + Filtros FFmpeg)
 
907
  # 3. Montar Prompt
908
  processed_context = request.context if request.context else "N/A"
909
 
910
+ prompt = f"""
911
  Traduza essa legenda pro português do Brasil, corrija qualquer erro de formatação, pontuação e mantenha timestamps e os textos nos seus respectivos blocos de legenda.
912
 
913
  Deve traduzir exatamente o texto da legenda observando o contexto, não é pra migrar, por exemplo, textos de um bloco de legenda pra outro. Deve traduzir exatamente o texto de cada bloco de legenda, manter sempre as palavras, nunca retirar.
 
942
  import traceback
943
  traceback.print_exc()
944
  raise HTTPException(status_code=500, detail=str(e))