habulaj commited on
Commit
e1f06ee
·
verified ·
1 Parent(s): f31c5cd

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +197 -208
main.py CHANGED
@@ -11,10 +11,6 @@ import time
11
  import json
12
  import subprocess
13
  import asyncio
14
- import logging
15
-
16
- logging.basicConfig(level=logging.INFO, format='%(levelname)s:\t %(message)s')
17
- logger = logging.getLogger(__name__)
18
 
19
  from gemini_webapi import GeminiClient
20
  from gemini_webapi.constants import Model
@@ -30,200 +26,16 @@ app.mount("/static", StaticFiles(directory="static"), name="static")
30
  Secure_1PSID = os.getenv("GEMINI_SECURE_1PSID", "PRIVATE")
31
  Secure_1PSIDTS = os.getenv("GEMINI_SECURE_1PSIDTS", "PRIVATE")
32
 
33
- subtitle_gem = None
34
- elements_gem = None
35
 
36
  @app.on_event("startup")
37
  async def startup_event():
38
- global client, subtitle_gem, elements_gem
39
- logger.info("Iniciando cliente do Gemini em plano de fundo...")
40
  client = GeminiClient(Secure_1PSID, Secure_1PSIDTS, proxy=None)
41
-
42
- # Extende o tempo máximo que a biblioteca aguarda por uma resposta "pensante" do modelo
43
- client.watchdog_timeout = 180
44
-
45
  # auto_refresh=True fará com que o token __Secure-1PSIDTS seja renovado automaticamente
46
  await client.init(timeout=180, auto_close=False, close_delay=300, auto_refresh=True)
47
- logger.info("Cliente Gemini-API inicializado com sucesso!")
48
-
49
- # Configurar o Gemini Gem (System Prompt) para a tradução de legendas
50
- try:
51
- await client.fetch_gems()
52
- gem_name = "API Subtitle Translator v1"
53
- gem_prompt = """Você é um tradutor especialista de legendas para PORTUGUÊS DO BRASIL (pt-BR).
54
- Sua função é receber uma legenda base gerada por IA (frequentemente imprecisa em pontuação e separação) e traduzi-la perfeitamente pro português, analisando o contexto geral e o áudio do vídeo fornecido.
55
-
56
- REGRAS ESTILÍSTICAS E DE TRADUÇÃO:
57
- 1. Traduza exatamente o texto da legenda observando o contexto. Mantenha as palavras nos seus respectivos blocos, evite juntar blocos indevidamente ou omitir informações.
58
- 2. Não adicione nenhum texto antes ou depois da resposta. Responda EXCLUSIVAMENTE o conteúdo `.srt` válido numérico.
59
- 3. Se verificar pelo áudio que alguém está gritando ou falando muito alto, ESCREVA EM MAIÚSCULO. Adapte gírias e sotaques para deixá-lo fluído em pt-BR.
60
- 4. MÚSICA E LETRAS: Se houver música/canto (que deve reter seu sentido), VOCÊ DEVE LEGENDAR A LETRA colocando o símbolo ♪ no início e fim da frase. Pesquise a letra/tradução oficial na internet para garantir precisão.
61
-
62
- TIMING, TIMESTAMPS E CONFLITOS:
63
- - Use a lista fornecida de "TIMESTAMPS POR PALAVRA (WORD-LEVEL)" como a DICA FINAL ABSOLUTA de timing.
64
- - Se a legenda base Whisper colocou uma palavra no bloco 4, mas o word-level deixa claro que o áudio dessa palavra foi falado de fato no tempo correspondente ao bloco 5, MOVA a tradução para o bloco 5. Alinhe sua saída perfeitamente ao som utilizando-o como referência fina.
65
-
66
- EXEMPLOS DE FORMATAÇÃO:
67
-
68
- Original recebido:
69
- 1
70
- 00:00:01,000 --> 00:00:04,000
71
- hey what are you doing here i thought you left already
72
- 2
73
- 00:00:04,500 --> 00:00:07,200
74
- yeah i was going to but then i realized i forgot my keys
75
-
76
- Sua resposta (TRADUZIDO):
77
- 1
78
- 00:00:01,000 --> 00:00:04,000
79
- Ué, o que você tá fazendo aqui? Não era pra você já ter ido embora?
80
-
81
- 2
82
- 00:00:04,500 --> 00:00:07,200
83
- Eu ia, mas aí percebi que esqueci minhas chaves.
84
- """
85
- existing_gem = None
86
- for g in client.gems:
87
- if g.name == gem_name:
88
- existing_gem = g
89
- break
90
-
91
- if existing_gem:
92
- subtitle_gem = existing_gem
93
- logger.info(f"✨ Gem '{gem_name}' encontrado e carregado na conta.")
94
- else:
95
- subtitle_gem = await client.create_gem(name=gem_name, prompt=gem_prompt, description="Gem otimizado para legenda SRT em pt-BR")
96
- logger.info(f"✨ Gem '{gem_name}' criado com sucesso na conta.")
97
-
98
-
99
- # Configurar o Gemini Gem (System Prompt) para a Geração de Elementos
100
- gem_elements_name = "API Instagram Elements Creator v1"
101
- gem_elements_prompt = """IDIOMA: Todo o conteúdo gerado (título, descrição) DEVE ser em PORTUGUÊS DO BRASIL. Mesmo que o vídeo esteja em outro idioma, a saída final deve ser inteiramente em pt-BR.
102
-
103
- Crie um título e uma descrição analisando o vídeo, o contexto e os comentários fornecidos. Corrija qualquer informação imprecisa, utilize técnicas modernas que prendem o leitor a ler até o final.
104
- A legenda deve ser compatível e do tamanho de uma legenda do Instagram.
105
- A descrição deve ser sem tópicos, apenas descrição limpa e direta, sem conclusões parecendo IA e sem enrolação ou redundâncias.
106
- Quero informações concretas e factuais, não pensamentos, opiniões ou imaginações.
107
- Não seja redundante, cada frase precisa adicionar informação nova.
108
- LEMBRE-SE: Como os comentários são feitos por humanos reais, você DEVE olhar para eles e usá-los como inspiração, se necessário, para gerar títulos com uma pegada MUITO mais humanizada, baseando-se nas reações reais.
109
- Se inspire rigorosamente no modo de escrita dos exemplos fornecidos.
110
-
111
- ESTILO DE ESCRITA OBRIGATÓRIO:
112
-
113
- - Tom semiformal que mistura precisão técnica com fluidez conversacional
114
- - Use conectivos naturais como aliás, na verdade, por exemplo, definitivamente, etc, para criar ritmo
115
- - Palavras-chave em MAIÚSCULA para ênfase quando fizer sentido
116
- - Informações diretas, sem rodeios, cada frase deve acrescentar um dado novo
117
- - NUNCA termine com frases que pareçam conclusões de IA
118
- - Evite palavras como consolidou, definiu, simboliza especialmente no final
119
- - Termine a descrição sempre com um FATO CONCRETO como número, prêmio, data ou detalhe técnico relevante
120
- - NUNCA use travessões em nenhuma parte do texto
121
- - NUNCA faça perguntas retóricas ou diretas ao final da descrição
122
- - NUNCA utilize termos como "O vídeo resgata", "O vídeo mostra", etc... a descrição deve ser sempre direta.
123
-
124
- LEGENDA:
125
- - Define se o vídeo precisa de legendas (se há fala importante que precisa ser traduzida ou transcrita).
126
- - Responda com true se houver diálogo/fala crucial.
127
- - Responda com false se for apenas visual, música de fundo ou fala irrelevante.
128
-
129
- TÍTULOS E EMOJIS:
130
-
131
- - O público primário é Geração Z, portanto o tom pode ser descontraído quando o contexto permitir
132
- - O uso de “Quando” no início do título é UMA OPÇÃO ESTILÍSTICA recomendada, não obrigatória
133
- - Varie estruturas de título, podendo usar afirmações diretas, contrastes, dados impactantes ou frases curtas
134
- - Emojis são opcionais e devem ser usados apenas quando reforçam a emoção do contexto
135
- - Não use emojis em todos os títulos
136
- - O título só deve ter UM emoji, NUNCA DOIS.
137
- - Outros emojis podem ser usados conforme o contexto, como 🥹, 😭, 🔥, etc. Se for utilizado o coração, SEMPRE deve ser coração sem ser o vermelho ou branco... dependendo do contexto.
138
- - MUITO IMPORTANTE: Mantenha as quebras de linha na descrição utilizando `\\n\\n` no JSON para separar os parágrafos, assim o texto não fica tudo numa única linha.
139
-
140
- EXEMPLOS (saída esperada em JSON):
141
-
142
- [
143
- {
144
- "title": "É incrível como ele era vulnerável e emotivo antes de perder qualquer traço de humanidade 💀",
145
- "description": "No episódio 3 da 1ª temporada de Breaking Bad (...And the Bag's in the River), Walter White reconstrói um prato quebrado e descobre que falta um único estilhaço. Ele percebe que Krazy-8, o traficante mantido em seu porão, escondeu a peça pontiaguda para usá-la como arma. Walt estava decidido a libertar o prisioneiro, mas a prova física da traição o forçou a estrangular o traficante pra sobreviver.\\n\\nFoi nesse momento que o docente de química compreendeu que a empatia seria sua condenação. Morria, naquele instante, o mestre de escola, e surgia a lógica inflexível de Heisenberg 🔥",
146
- "legenda": false
147
- },
148
- {
149
- "title": "Imagina escrever uma música do próprio livro e vê-la ganhar vida em live-action 🥹",
150
- "description": "Jogos Vorazes deu vida a \\"The Hanging Tree\\", de Suzanne Collins, depois que a canção apareceu pela primeira vez em seu livro Mockingjay. Na Parte 1 de Mockingjay, no Distrito 12, o que começa como uma lembrança solene do pai de Katniss transforma-se em um grito de mobilização para que os distritos se oponham à Capital. Enquanto Snow manipula a mente de Peeta no silêncio do Distrito 13, a canção deixa muito claro que o poder de uma ideia é a única coisa que o medo não consegue deter. Até porque, nada representa uma ameaça maior para um tirano do que um povo que não tem mais nada a perder 🎯",
151
- "legenda": true
152
- },
153
- {
154
- "title": "Normal People foi tão bom porque o Paul Mescal definitivamente não tava atuando 🥹",
155
- "description": "🥹 Paul Mescal era um ator de teatro praticamente desconhecido até ser escalado como Connell Waldron em Normal People. A adaptação do best-seller de Sally Rooney rendeu a Mescal o BAFTA de Melhor Ator e uma indicação ao Emmy, que claramente consolidou sua química com Daisy Edgar-Jones como uma das mais realistas da televisão recente.\\n\\nA produção utilizou uma coordenadora de intimidade para garantir que as cenas de vulnerabilidade fossem autênticas, focando mais na linguagem corporal e no silêncio do que em diálogos expositivos. Filmada na Irlanda e na Itália, a série apresenta com precisão técnica a transição da vida escolar em Sligo para a universidade no Trinity College, evitando os clichês estéticos típicos de romances juvenis e concentrando-se no naturalismo das atuações.",
156
- "legenda": true
157
- },
158
- {
159
- "title": "O exato momento em que Carl supera seu luto de décadas 🥺",
160
- "description": "🍇 O broche que Carl entrega a Russell é uma tampa de refrigerante de uva (Grape Soda) original dos anos 30, o mesmo objeto que Ellie deu a Carl quando eles se conheceram na infância.\\n\\nNo final de Up: Altas Aventuras (2009), Russell, com 8 anos, lida com a falta do pai durante a cerimônia de formatura dos Exploradores da Natureza. Carl Fredricksen sobe ao palco e entrega ao garoto a \\"Insígnia Ellie\\", a mais alta distinção que ele tem. Isso representa o momento preciso em que Carl supera seu luto de décadas, transferindo o legado de aventura para Russell e assumindo o papel de figura paterna para o garoto.\\n\\nDirigido por Pete Docter, o longa fez história ao ser a primeira animação a abrir o Festival de Cannes e venceu os Oscars de Melhor Filme de Animação e Melhor Trilha Sonora.",
161
- "legenda": true
162
- },
163
- {
164
- "title": "“Ei, olha só... meu turno acabou de terminar” 😭",
165
- "description": "No filme \\"Atração Perigosa\\" (2010), o diretor Ben Affleck definitivamente enfatizou o realismo tático quando apresentou a cultura criminosa de Charlestown, Boston. Nessa cena, por exemplo, imediatamente após o assalto ao banco em North End, o policial interpretado por Jack Walsh opta por desconsiderar a gangue liderada por Doug MacRay, que está equipada com fuzis automáticos e usando as conhecidas máscaras de freira. A escolha do oficial é uma das reações mais pragmáticas do gênero policial... a autopreservação diante de uma desvantagem letal evidente. O filme, aliás, inspirado no livro \\"Prince of Thieves\\", rendeu a Jeremy Renner uma indicação ao Oscar de Melhor Ator Coadjuvante por sua atuação como o instável James Coughlin.",
166
- "legenda": false
167
- },
168
- {
169
- "title": "Quando um \\"Eu te odeio\\" carrega mais amor que um \\"Eu te amo\\" 😝",
170
- "description": "No episódio \\"Fun Run\\" (4x01), Jim finge um pedido de casamento apenas para amarrar o cadarço, arrancando esse \\"eu te odeio\\" de Pam. O momento marca o MELHOR INÍCIO de temporada da série, quando o casal finalmente assume o namoro após três anos de tensão e o famoso beijo no \\"Casino Night\\" 🥹. A naturalidade da cena é, na verdade, fruto de um processo rigoroso de escalação... Greg Daniels, o showrunner, realizou inúmeros testes de química cruzada até que John Krasinski e Jenna Fischer se encontrassem. No dia do teste final, antes mesmo de começarem, Fischer perguntou a Krasinski se ele seria o Jim, e ele respondeu: \\"Você é minha Pam\\". A produção de The Office escolheu um estilo de romance \\"slow burn\\", no qual o afeto se desenvolvia em silêncio, por meio de olhares e piadas internas, evitando o melodrama típico das sitcoms dos anos 2000.",
171
- "legenda": true
172
- },
173
- {
174
- "title": "Dominic Monaghan simplesmente enganou Elijah Wood por 10 minutos e o resultado foi esse 😭",
175
- "description": "Durante a turnê de divulgação de O Retorno do Rei em 2004, Dominic Monaghan, intérprete do hobbit Merry, assumiu o papel de um jornalista alemão fictício chamado Hans Jensen para entrevistar seu colega de elenco Elijah Wood. Monaghan estava em uma sala diferente com um modulador de voz, o que permitiu que ele fizesse perguntas cada vez mais absurdas enquanto Elijah, em um estúdio em Nova York, tentava manter o profissionalismo. O ponto alto da pegadinha ocorre quando Monaghan questiona Elijah repetidamente sobre o uso de perucas, gerando uma crise de riso incontrolável no ator ao perceber a bizarrice da situação. Curiosamente, a ironia técnica do momento reside no fato de que todos os atores principais de O Senhor dos Anéis utilizaram perucas durante os dezoito meses de filmagem na Nova Zelândia para garantir a continuidade visual dos personagens. O registro completo dessa entrevista foi incluído oficialmente como um easter egg nos extras do DVD da Versão Estendida de O Senhor dos Anéis: O Retorno do Rei.",
176
- "legenda": true
177
- },
178
- {
179
- "title": "Loucura como o Justin Bieber já demonstrava um senso rítmico absurdo aos 2 anos de idade 😵",
180
- "description": "Justin Bieber tinha somente dois anos quando sua mãe, Pattie Mallette, gravou este vídeo caseiro na cozinha de sua residência em Stratford, Ontário. A habilidade dele em manter o tempo rítmico e realizar viradas rápidas usando apenas as mãos e uma superfície improvisada impressiona pela coordenação motora avançada para sua idade.\\n\\nJustin aprendeu a tocar bateria de forma autodidata antes de passar para o piano e o violão, instrumentos que ele dominou antes de ser descoberto no YouTube em 2007. O artista, vale ressaltar, tocou bateria profissionalmente em várias turnês internacionais, evidenciando que a base percussiva foi o fundamento de sua formação musical.\\n\\nEsse registro particular tornou-se uma das cenas mais icônicas do seu documentário \\"Never Say Never\\", que arrecadou 99 milhões de dólares em todo o mundo.",
181
- "legenda": true
182
- },
183
- {
184
- "title": "Quando o James Franco foi apresentar o Oscar e a avó dele resolveu flertar com o Mark Wahlberg 😭",
185
- "description": "A fim de atrair um público mais jovem, a 83ª edição do Academy Awards, realizada em 2011, escalou James Franco e Anne Hathaway como apresentadores. Franco fez uma apresentação espontânea de sua avó, Mitsue \\"Mitzie\\" Verne, que se encontrava na plateia. Quando pegou o microfone, ela direcionou sua atenção a Mark Wahlberg, referindo-se a ele pelo apelido de sua carreira inicial, \\"Marky Mark\\". A interação rompeu o protocolo oficial da premiação e provocou uma reação autêntica de Wahlberg, que riu ao ser apontado diante das câmeras.\\n\\nA tentativa da Academia de modernizar o evento por meio de interações não roteirizadas entre os convidados da primeira fila e os apresentadores foi um dos principais destaques da edição do Oscar.\\n\\nMitzie Verne, aliás, era uma personalidade reconhecida no cenário artístico de Cleveland, cidade onde estabeleceu a Verne Interactive Collective Gallery em 1953.",
186
- "legenda": true
187
- },
188
- {
189
- "title": "O mano é inocente demais pra esse mundo tão cruel 😭",
190
- "description": "Estátuas vivas são artistas de rua que utilizam técnicas rigorosas de controle da respiração e relaxamento muscular para se manterem imóveis por períodos que variam de 30 a 60 minutos. Por exemplo, o artista Donald Eleanor usa maquiagem metálica e figurinos rígidos para fazer parecer que é um objeto inanimado em locais públicos. Quando o pedestre interage ou oferece uma gratificação, o performer rompe a imobilidade com movimentos fluidos e robóticos, criando um contraste visual instantâneo. Essa atividade requer meses de treinamento para evitar o reflexo automático de piscar ou responder a distrações externas, como sons e mudanças climáticas.\\n\\nA técnica de \\"locking\\", por exemplo, permite que o ator fixe as articulações em ângulos determinados, mantendo uma postura estável e sem oscilações.",
191
- "legenda": false
192
- },
193
- {
194
- "title": "Os bastidores de Jumanji sendo mais engraçados que o próprio filme 😭",
195
- "description": "Durante as filmagens de Jumanji: Bem-Vindo à Selva (2017) no Havaí, a produção precisou ser interrompida porque Jack Black se recusou a continuar gravando antes de terminar sua refeição. Kevin Hart registrou o momento em que o colega de elenco, ainda caracterizado como o professor Sheldon Oberon, ignora a pressão do cronograma para finalizar um prato de arroz.\\n\\nDwayne Johnson, o The Rock, aliás, aparece no vídeo sendo transportado por uma plataforma móvel enquanto Kevin Hart ironiza o \\"nível de Hollywood\\" do set. A química entre o quarteto principal foi fundamental para o sucesso do longa, que utilizou locações reais como a Reserva Kualoa para criar o ambiente imersivo do jogo.\\n\\nO filme arrecadou 962 milhões de dólares globalmente, tornando-se a maior bilheteria da Sony Pictures nos Estados Unidos até o lançamento de Homem-Aranha: Sem Volta para Casa.",
196
- "legenda": true
197
- },
198
- {
199
- "title": "O mano genuinamente se sentiu violado 😭",
200
- "description": "Ele estava sob efeito de sedativos pesados após um procedimento cirúrgico quando este registro foi feito em uma unidade hospitalar. O homem apresenta um estado de desorientação típica do despertar anestésico, que afeta temporariamente as funções cognitivas e a percepção de realidade do paciente. Nas imagens, ele tenta vestir sua própria camiseta enquanto interage com a equipe de enfermagem de forma confusa e cômica.\\n\\nA sedação consciente, técnica comum em procedimentos ambulatoriais, utiliza medicamentos que induzem ao relaxamento profundo e, frequentemente, causam amnésia retrógrada.",
201
- "legenda": true
202
- }
203
- ]
204
-
205
- INSTRUÇÕES FINAIS:
206
-
207
- Mande apenas o JSON na resposta. Verifique se o JSON é válido. Responda em uma lista de objetos, mesmo que seja apenas um item.
208
-
209
- NUNCA adicione perguntas, sugestões ou qualquer texto adicional após o JSON.
210
- Se o contexto enviado pelo usuário não for verdadeiro ou estiver impreciso, ignore completamente. Gere uma legenda para o Instagram correta e factual, inspirada nos exemplos acima. NUNCA cite ou mencione a imprecisão do contexto original (ex: não escreva "Justin Bieber não teve o carro quebrado em 2018 como sugere a legenda do vídeo"). Simplesmente apresente a informação correta de forma natural.
211
- """
212
- existing_elem_gem = None
213
- for g in client.gems:
214
- if g.name == gem_elements_name:
215
- existing_elem_gem = g
216
- break
217
-
218
- if existing_elem_gem:
219
- elements_gem = existing_elem_gem
220
- logger.info(f"✨ Gem '{gem_elements_name}' encontrado e carregado na conta.")
221
- else:
222
- elements_gem = await client.create_gem(name=gem_elements_name, prompt=gem_elements_prompt, description="Gem focado na criação de elementos nativos pro Instagram (pt-BR)")
223
- logger.info(f"✨ Gem '{gem_elements_name}' criado com sucesso na conta.")
224
-
225
- except Exception as e:
226
- logger.error(f"⚠️ Aviso: Não foi possivel carregar/criar Gems. Erro: {e}")
227
 
228
  @app.get("/")
229
  def root():
@@ -439,22 +251,125 @@ async def generate_elements_endpoint(request: GenerateElementsRequest):
439
  comentarios_add += f"- {text} ({c.get('like_count', 0)} curtidas)\n"
440
 
441
  prompt = f"""
442
- Por favor, gere os elementos (título, descrição, legenda) com base nas instruções de perfil rígidas do sistema. Aqui estão as informações adicionais providenciadas para esse vídeo específico:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
443
 
444
- ------------------------------------
445
- Contexto Adicional (seja factual, não dependa 100% disso): {contexto_add}
 
 
 
 
 
 
 
 
446
  {comentarios_add}
447
- ------------------------------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
448
  """
449
  model_obj = get_gemini_model(request.model)
450
- logger.info(f"🧠 Enviando para Gemini ({request.model})...")
451
 
452
  # Envio do prompt + arquivo (vídeo) pro Gemini
453
- kwargs = {"model": model_obj, "files": [video_path_to_analyze]}
454
- if elements_gem:
455
- kwargs["gem"] = elements_gem
456
-
457
- response_gemini = await client.generate_content(prompt, **kwargs)
458
 
459
  titles_data = extract_json_from_text(response_gemini.text)
460
  if not titles_data:
@@ -578,6 +493,85 @@ async def generate_subtitle(request: GeminiSubtitleRequest):
578
  contexto_final = request.context if request.context and request.context.strip() != "N/A" else default_context
579
 
580
  prompt = f"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
581
  INSTRUÇÕES/CONTEXTO DO USUÁRIO (OPCIONAL): {contexto_final}
582
 
583
  --- LEGENDA BASE (WHISPER) ---
@@ -587,12 +581,7 @@ INSTRUÇÕES/CONTEXTO DO USUÁRIO (OPCIONAL): {contexto_final}
587
  {word_level_text}
588
  """
589
  model_obj = get_gemini_model(request.model)
590
-
591
- kwargs = {"model": model_obj, "files": [processed_audio_path]}
592
- if subtitle_gem:
593
- kwargs["gem"] = subtitle_gem
594
-
595
- response_gemini = await client.generate_content(prompt, **kwargs)
596
  cleaned_srt = clean_and_validate_srt(response_gemini.text)
597
 
598
  if request.time_start and request.time_start > 0:
 
11
  import json
12
  import subprocess
13
  import asyncio
 
 
 
 
14
 
15
  from gemini_webapi import GeminiClient
16
  from gemini_webapi.constants import Model
 
26
  Secure_1PSID = os.getenv("GEMINI_SECURE_1PSID", "PRIVATE")
27
  Secure_1PSIDTS = os.getenv("GEMINI_SECURE_1PSIDTS", "PRIVATE")
28
 
29
+ client = None
 
30
 
31
  @app.on_event("startup")
32
  async def startup_event():
33
+ global client
34
+ print("Iniciando cliente do Gemini em plano de fundo...")
35
  client = GeminiClient(Secure_1PSID, Secure_1PSIDTS, proxy=None)
 
 
 
 
36
  # auto_refresh=True fará com que o token __Secure-1PSIDTS seja renovado automaticamente
37
  await client.init(timeout=180, auto_close=False, close_delay=300, auto_refresh=True)
38
+ print("Cliente Gemini-API inicializado com sucesso!")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
 
40
  @app.get("/")
41
  def root():
 
251
  comentarios_add += f"- {text} ({c.get('like_count', 0)} curtidas)\n"
252
 
253
  prompt = f"""
254
+ IDIOMA: Todo o conteúdo gerado (título, descrição) DEVE ser em PORTUGUÊS DO BRASIL. Mesmo que o vídeo esteja em outro idioma, a saída final deve ser inteiramente em pt-BR.
255
+
256
+ Crie um título e uma descrição analisando o vídeo, o contexto e os comentários fornecidos. Corrija qualquer informação imprecisa, utilize técnicas modernas que prendem o leitor a ler até o final.
257
+ A legenda deve ser compatível e do tamanho de uma legenda do Instagram.
258
+ A descrição deve ser sem tópicos, apenas descrição limpa e direta, sem conclusões parecendo IA e sem enrolação ou redundâncias.
259
+ Quero informações concretas e factuais, não pensamentos, opiniões ou imaginações.
260
+ Não seja redundante, cada frase precisa adicionar informação nova.
261
+ LEMBRE-SE: Como os comentários são feitos por humanos reais, você DEVE olhar para eles e usá-los como inspiração, se necessário, para gerar títulos com uma pegada MUITO mais humanizada, baseando-se nas reações reais.
262
+ Se inspire rigorosamente no modo de escrita dos exemplos fornecidos.
263
+
264
+ ESTILO DE ESCRITA OBRIGATÓRIO:
265
+
266
+ - Tom semiformal que mistura precisão técnica com fluidez conversacional
267
+ - Use conectivos naturais como aliás, na verdade, por exemplo, definitivamente, etc, para criar ritmo
268
+ - Palavras-chave em MAIÚSCULA para ênfase quando fizer sentido
269
+ - Informações diretas, sem rodeios, cada frase deve acrescentar um dado novo
270
+ - NUNCA termine com frases que pareçam conclusões de IA
271
+ - Evite palavras como consolidou, definiu, simboliza especialmente no final
272
+ - Termine a descrição sempre com um FATO CONCRETO como número, prêmio, data ou detalhe técnico relevante
273
+ - NUNCA use travessões em nenhuma parte do texto
274
+ - NUNCA faça perguntas retóricas ou diretas ao final da descrição
275
+ - NUNCA utilize termos como "O vídeo resgata", "O vídeo mostra", etc... a descrição deve ser sempre direta.
276
+
277
+ LEGENDA:
278
+ - Define se o vídeo precisa de legendas (se há fala importante que precisa ser traduzida ou transcrita).
279
+ - Responda com true se houver diálogo/fala crucial.
280
+ - Responda com false se for apenas visual, música de fundo ou fala irrelevante.
281
+
282
+ TÍTULOS E EMOJIS:
283
 
284
+ - O público primário é Geração Z, portanto o tom pode ser descontraído quando o contexto permitir
285
+ - O uso de “Quando” no início do título é UMA OPÇÃO ESTILÍSTICA recomendada, não obrigatória
286
+ - Varie estruturas de título, podendo usar afirmações diretas, contrastes, dados impactantes ou frases curtas
287
+ - Emojis são opcionais e devem ser usados apenas quando reforçam a emoção do contexto
288
+ - Não use emojis em todos os títulos
289
+ - O título só deve ter UM emoji, NUNCA DOIS.
290
+ - Outros emojis podem ser usados conforme o contexto, como 🥹, 😭, 🔥, etc. Se for utilizado o coração, SEMPRE deve ser coração sem ser o vermelho ou branco... dependendo do contexto.
291
+ - MUITO IMPORTANTE: Mantenha as quebras de linha na descrição utilizando `\\n\\n` no JSON para separar os parágrafos, assim o texto não fica tudo numa única linha.
292
+
293
+ Contexto que pode ajudar: {contexto_add}
294
  {comentarios_add}
295
+
296
+ EXEMPLOS (saída esperada em JSON):
297
+
298
+ [
299
+ {{
300
+ "title": "É incrível como ele era vulnerável e emotivo antes de perder qualquer traço de humanidade 💀",
301
+ "description": "No episódio 3 da 1ª temporada de Breaking Bad (...And the Bag's in the River), Walter White reconstrói um prato quebrado e descobre que falta um único estilhaço. Ele percebe que Krazy-8, o traficante mantido em seu porão, escondeu a peça pontiaguda para usá-la como arma. Walt estava decidido a libertar o prisioneiro, mas a prova física da traição o forçou a estrangular o traficante pra sobreviver.\\n\\nFoi nesse momento que o docente de química compreendeu que a empatia seria sua condenação. Morria, naquele instante, o mestre de escola, e surgia a lógica inflexível de Heisenberg 🔥",
302
+ "legenda": false
303
+ }},
304
+ {{
305
+ "title": "Imagina escrever uma música do próprio livro e vê-la ganhar vida em live-action 🥹",
306
+ "description": "Jogos Vorazes deu vida a \\"The Hanging Tree\\", de Suzanne Collins, depois que a canção apareceu pela primeira vez em seu livro Mockingjay. Na Parte 1 de Mockingjay, no Distrito 12, o que começa como uma lembrança solene do pai de Katniss transforma-se em um grito de mobilização para que os distritos se oponham à Capital. Enquanto Snow manipula a mente de Peeta no silêncio do Distrito 13, a canção deixa muito claro que o poder de uma ideia é a única coisa que o medo não consegue deter. Até porque, nada representa uma ameaça maior para um tirano do que um povo que não tem mais nada a perder 🎯",
307
+ "legenda": true
308
+ }},
309
+ {{
310
+ "title": "Normal People foi tão bom porque o Paul Mescal definitivamente não tava atuando 🥹",
311
+ "description": "🥹 Paul Mescal era um ator de teatro praticamente desconhecido até ser escalado como Connell Waldron em Normal People. A adaptação do best-seller de Sally Rooney rendeu a Mescal o BAFTA de Melhor Ator e uma indicação ao Emmy, que claramente consolidou sua química com Daisy Edgar-Jones como uma das mais realistas da televisão recente.\\n\\nA produção utilizou uma coordenadora de intimidade para garantir que as cenas de vulnerabilidade fossem autênticas, focando mais na linguagem corporal e no silêncio do que em diálogos expositivos. Filmada na Irlanda e na Itália, a série apresenta com precisão técnica a transição da vida escolar em Sligo para a universidade no Trinity College, evitando os clichês estéticos típicos de romances juvenis e concentrando-se no naturalismo das atuações.",
312
+ "legenda": true
313
+ }},
314
+ {{
315
+ "title": "O exato momento em que Carl supera seu luto de décadas 🥺",
316
+ "description": "🍇 O broche que Carl entrega a Russell é uma tampa de refrigerante de uva (Grape Soda) original dos anos 30, o mesmo objeto que Ellie deu a Carl quando eles se conheceram na infância.\\n\\nNo final de Up: Altas Aventuras (2009), Russell, com 8 anos, lida com a falta do pai durante a cerimônia de formatura dos Exploradores da Natureza. Carl Fredricksen sobe ao palco e entrega ao garoto a \\"Insígnia Ellie\\", a mais alta distinção que ele tem. Isso representa o momento preciso em que Carl supera seu luto de décadas, transferindo o legado de aventura para Russell e assumindo o papel de figura paterna para o garoto.\\n\\nDirigido por Pete Docter, o longa fez história ao ser a primeira animação a abrir o Festival de Cannes e venceu os Oscars de Melhor Filme de Animação e Melhor Trilha Sonora.",
317
+ "legenda": true
318
+ }},
319
+ {{
320
+ "title": "“Ei, olha só... meu turno acabou de terminar” 😭",
321
+ "description": "No filme \\"Atração Perigosa\\" (2010), o diretor Ben Affleck definitivamente enfatizou o realismo tático quando apresentou a cultura criminosa de Charlestown, Boston. Nessa cena, por exemplo, imediatamente após o assalto ao banco em North End, o policial interpretado por Jack Walsh opta por desconsiderar a gangue liderada por Doug MacRay, que está equipada com fuzis automáticos e usando as conhecidas máscaras de freira. A escolha do oficial é uma das reações mais pragmáticas do gênero policial... a autopreservação diante de uma desvantagem letal evidente. O filme, aliás, inspirado no livro \\"Prince of Thieves\\", rendeu a Jeremy Renner uma indicação ao Oscar de Melhor Ator Coadjuvante por sua atuação como o instável James Coughlin.",
322
+ "legenda": false
323
+ }},
324
+ {{
325
+ "title": "Quando um \\"Eu te odeio\\" carrega mais amor que um \\"Eu te amo\\" 😝",
326
+ "description": "No episódio \\"Fun Run\\" (4x01), Jim finge um pedido de casamento apenas para amarrar o cadarço, arrancando esse \\"eu te odeio\\" de Pam. O momento marca o MELHOR INÍCIO de temporada da série, quando o casal finalmente assume o namoro após três anos de tensão e o famoso beijo no \\"Casino Night\\" 🥹. A naturalidade da cena é, na verdade, fruto de um processo rigoroso de escalação... Greg Daniels, o showrunner, realizou inúmeros testes de química cruzada até que John Krasinski e Jenna Fischer se encontrassem. No dia do teste final, antes mesmo de começarem, Fischer perguntou a Krasinski se ele seria o Jim, e ele respondeu: \\"Você é minha Pam\\". A produção de The Office escolheu um estilo de romance \\"slow burn\\", no qual o afeto se desenvolvia em silêncio, por meio de olhares e piadas internas, evitando o melodrama típico das sitcoms dos anos 2000.",
327
+ "legenda": true
328
+ }},
329
+ {{
330
+ "title": "Dominic Monaghan simplesmente enganou Elijah Wood por 10 minutos e o resultado foi esse 😭",
331
+ "description": "Durante a turnê de divulgação de O Retorno do Rei em 2004, Dominic Monaghan, intérprete do hobbit Merry, assumiu o papel de um jornalista alemão fictício chamado Hans Jensen para entrevistar seu colega de elenco Elijah Wood. Monaghan estava em uma sala diferente com um modulador de voz, o que permitiu que ele fizesse perguntas cada vez mais absurdas enquanto Elijah, em um estúdio em Nova York, tentava manter o profissionalismo. O ponto alto da pegadinha ocorre quando Monaghan questiona Elijah repetidamente sobre o uso de perucas, gerando uma crise de riso incontrolável no ator ao perceber a bizarrice da situação. Curiosamente, a ironia técnica do momento reside no fato de que todos os atores principais de O Senhor dos Anéis utilizaram perucas durante os dezoito meses de filmagem na Nova Zelândia para garantir a continuidade visual dos personagens. O registro completo dessa entrevista foi incluído oficialmente como um easter egg nos extras do DVD da Versão Estendida de O Senhor dos Anéis: O Retorno do Rei.",
332
+ "legenda": true
333
+ }},
334
+ {{
335
+ "title": "Loucura como o Justin Bieber já demonstrava um senso rítmico absurdo aos 2 anos de idade 😵",
336
+ "description": "Justin Bieber tinha somente dois anos quando sua mãe, Pattie Mallette, gravou este vídeo caseiro na cozinha de sua residência em Stratford, Ontário. A habilidade dele em manter o tempo rítmico e realizar viradas rápidas usando apenas as mãos e uma superfície improvisada impressiona pela coordenação motora avançada para sua idade.\\n\\nJustin aprendeu a tocar bateria de forma autodidata antes de passar para o piano e o violão, instrumentos que ele dominou antes de ser descoberto no YouTube em 2007. O artista, vale ressaltar, tocou bateria profissionalmente em várias turnês internacionais, evidenciando que a base percussiva foi o fundamento de sua formação musical.\\n\\nEsse registro particular tornou-se uma das cenas mais icônicas do seu documentário \\"Never Say Never\\", que arrecadou 99 milhões de dólares em todo o mundo.",
337
+ "legenda": true
338
+ }},
339
+ {{
340
+ "title": "Quando o James Franco foi apresentar o Oscar e a avó dele resolveu flertar com o Mark Wahlberg 😭",
341
+ "description": "A fim de atrair um público mais jovem, a 83ª edição do Academy Awards, realizada em 2011, escalou James Franco e Anne Hathaway como apresentadores. Franco fez uma apresentação espontânea de sua avó, Mitsue \\"Mitzie\\" Verne, que se encontrava na plateia. Quando pegou o microfone, ela direcionou sua atenção a Mark Wahlberg, referindo-se a ele pelo apelido de sua carreira inicial, \\"Marky Mark\\". A interação rompeu o protocolo oficial da premiação e provocou uma reação autêntica de Wahlberg, que riu ao ser apontado diante das câmeras.\\n\\nA tentativa da Academia de modernizar o evento por meio de interações não roteirizadas entre os convidados da primeira fila e os apresentadores foi um dos principais destaques da edição do Oscar.\\n\\nMitzie Verne, aliás, era uma personalidade reconhecida no cenário artístico de Cleveland, cidade onde estabeleceu a Verne Interactive Collective Gallery em 1953.",
342
+ "legenda": true
343
+ }},
344
+ {{
345
+ "title": "O mano é inocente demais pra esse mundo tão cruel 😭",
346
+ "description": "Estátuas vivas são artistas de rua que utilizam técnicas rigorosas de controle da respiração e relaxamento muscular para se manterem imóveis por períodos que variam de 30 a 60 minutos. Por exemplo, o artista Donald Eleanor usa maquiagem metálica e figurinos rígidos para fazer parecer que é um objeto inanimado em locais públicos. Quando o pedestre interage ou oferece uma gratificação, o performer rompe a imobilidade com movimentos fluidos e robóticos, criando um contraste visual instantâneo. Essa atividade requer meses de treinamento para evitar o reflexo automático de piscar ou responder a distrações externas, como sons e mudanças climáticas.\\n\\nA técnica de \\"locking\\", por exemplo, permite que o ator fixe as articulações em ângulos determinados, mantendo uma postura estável e sem oscilações.",
347
+ "legenda": false
348
+ }},
349
+ {{
350
+ "title": "Os bastidores de Jumanji sendo mais engraçados que o próprio filme 😭",
351
+ "description": "Durante as filmagens de Jumanji: Bem-Vindo à Selva (2017) no Havaí, a produção precisou ser interrompida porque Jack Black se recusou a continuar gravando antes de terminar sua refeição. Kevin Hart registrou o momento em que o colega de elenco, ainda caracterizado como o professor Sheldon Oberon, ignora a pressão do cronograma para finalizar um prato de arroz.\\n\\nDwayne Johnson, o The Rock, aliás, aparece no vídeo sendo transportado por uma plataforma móvel enquanto Kevin Hart ironiza o \\"nível de Hollywood\\" do set. A química entre o quarteto principal foi fundamental para o sucesso do longa, que utilizou locações reais como a Reserva Kualoa para criar o ambiente imersivo do jogo.\\n\\nO filme arrecadou 962 milhões de dólares globalmente, tornando-se a maior bilheteria da Sony Pictures nos Estados Unidos até o lançamento de Homem-Aranha: Sem Volta para Casa.",
352
+ "legenda": true
353
+ }},
354
+ {{
355
+ "title": "O mano genuinamente se sentiu violado 😭",
356
+ "description": "Ele estava sob efeito de sedativos pesados após um procedimento cirúrgico quando este registro foi feito em uma unidade hospitalar. O homem apresenta um estado de desorientação típica do despertar anestésico, que afeta temporariamente as funções cognitivas e a percepção de realidade do paciente. Nas imagens, ele tenta vestir sua própria camiseta enquanto interage com a equipe de enfermagem de forma confusa e cômica.\\n\\nA sedação consciente, técnica comum em procedimentos ambulatoriais, utiliza medicamentos que induzem ao relaxamento profundo e, frequentemente, causam amnésia retrógrada.",
357
+ "legenda": true
358
+ }}
359
+ ]
360
+
361
+ INSTRUÇÕES FINAIS:
362
+
363
+ Mande apenas o JSON na resposta. Verifique se o JSON é válido. Responda em uma lista de objetos, mesmo que seja apenas um item.
364
+
365
+ NUNCA adicione perguntas, sugestões ou qualquer texto adicional após o JSON.
366
+ Se o contexto enviado pelo usuário não for verdadeiro ou estiver impreciso, ignore completamente. Gere uma legenda para o Instagram correta e factual, inspirada nos exemplos acima. NUNCA cite ou mencione a imprecisão do contexto original (ex: não escreva "Justin Bieber não teve o carro quebrado em 2018 como sugere a legenda do vídeo"). Simplesmente apresente a informação correta de forma natural.
367
  """
368
  model_obj = get_gemini_model(request.model)
369
+ print(f"🧠 Enviando para Gemini ({request.model})...")
370
 
371
  # Envio do prompt + arquivo (vídeo) pro Gemini
372
+ response_gemini = await client.generate_content(prompt, files=[video_path_to_analyze], model=model_obj)
 
 
 
 
373
 
374
  titles_data = extract_json_from_text(response_gemini.text)
375
  if not titles_data:
 
493
  contexto_final = request.context if request.context and request.context.strip() != "N/A" else default_context
494
 
495
  prompt = f"""
496
+ IDIOMA: A legenda traduzida DEVE ser inteiramente em PORTUGUÊS DO BRASIL (pt-BR). Independente do idioma original do vídeo.
497
+
498
+ 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.
499
+ 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.
500
+ Mande o SRT completo, sem textos adicionais na resposta, apenas o SRT traduzido. Também analise o áudio anexado pra ver se algo foi legendado incorretamente ou errado, ou se algo não for legendado. Se não for, inclua, sem mudar o timestamp já existente. A legenda acima é uma base gerada pelo Whisper que precisa ser analisada e traduzida, não o resultado final.
501
+ A legenda deve ser totalmente traduzida corretamente analisando o contexto e a entonação de falar. Se alguém estiver gritando, ESCREVA MAIÚSCULO! etc... Adapte gírias e qualquer coisa do tipo. Não deve ser literal a tradução, deve se adaptar.
502
+
503
+ TIMING E TIMESTAMPS:
504
+ - Abaixo da legenda base (SRT), você receberá também os TIMESTAMPS POR PALAVRA (word-level) gerados pelo Whisper.
505
+ - Esses timestamps indicam o início e fim exato de cada palavra falada no áudio.
506
+ - USE esses timestamps para verificar se os blocos de legenda estão sincronizados corretamente.
507
+ - Se perceber que uma palavra está no bloco errado (começa depois do timestamp do bloco seguinte, por exemplo), MOVA-A para o bloco correto.
508
+ - Se precisar criar novos blocos ou ajustar timestamps, baseie-se nos timestamps word-level para garantir precisão.
509
+ - Os timestamps por palavra são a fonte de verdade para saber QUANDO cada palavra é falada.
510
+
511
+ MÚSICA E LETRAS:
512
+ - Se houver música/canto no vídeo, VOCÊ DEVE LEGENDAR A LETRA.
513
+ - Adicione o símbolo ♪ no início e no final de cada frase cantada. Ex: ♪ Hello, it's me ♪
514
+ - PESQUISE NA INTERNET a letra correta da música e sua tradução oficial/mais aceita para garantir que está correto. Tente identificar a música pelo áudio se não souber.
515
+ - Mantenha a sincronia com o áudio.
516
+
517
+ EXEMPLO:
518
+
519
+ (Original): 1
520
+ 00:00:01,000 --> 00:00:04,000
521
+ hey what are you doing here i thought you left already
522
+
523
+ 2
524
+ 00:00:04,500 --> 00:00:07,200
525
+ yeah i was going to but then i realized i forgot my keys
526
+
527
+ 3
528
+ 00:00:07,900 --> 00:00:10,500
529
+ you always forget something man this is crazy
530
+
531
+ 4
532
+ 00:00:11,000 --> 00:00:14,000
533
+ relax it's not a big deal stop acting like that
534
+
535
+ 5
536
+ 00:00:14,500 --> 00:00:17,800
537
+ i am not acting you said you would be on time
538
+
539
+ 6
540
+ 00:00:18,000 --> 00:00:21,500
541
+ okay okay i'm sorry can we just go now
542
+
543
+ 7
544
+ 00:00:22,000 --> 00:00:25,000
545
+ fine but if we are late again it's on you
546
+
547
+ (Traduzido, como você deveria traduzir): 1
548
+ 00:00:01,000 --> 00:00:04,000
549
+ Ué, o que você tá fazendo aqui? Não era pra você já ter ido embora?
550
+
551
+ 2
552
+ 00:00:04,500 --> 00:00:07,200
553
+ Eu ia, mas aí percebi que esqueci minhas chaves.
554
+
555
+ 3
556
+ 00:00:07,900 --> 00:00:10,500
557
+ Cara, você SEMPRE esquece alguma coisa, isso é surreal!
558
+
559
+ 4
560
+ 00:00:11,000 --> 00:00:14,000
561
+ Ah, relaxa! Não é o fim do mundo, para de drama.
562
+
563
+ 5
564
+ 00:00:14,500 --> 00:00:17,800
565
+ Não é drama! Você falou que ia chegar no horário!
566
+
567
+ 6
568
+ 00:00:18,000 --> 00:00:21,500
569
+ Tá, tá... foi mal. Bora logo?
570
+
571
+ 7
572
+ 00:00:22,000 --> 00:00:25,000
573
+ Tá bom. Mas se a gente se atrasar de novo, a culpa é SUA!
574
+
575
  INSTRUÇÕES/CONTEXTO DO USUÁRIO (OPCIONAL): {contexto_final}
576
 
577
  --- LEGENDA BASE (WHISPER) ---
 
581
  {word_level_text}
582
  """
583
  model_obj = get_gemini_model(request.model)
584
+ response_gemini = await client.generate_content(prompt, files=[processed_audio_path], model=model_obj)
 
 
 
 
 
585
  cleaned_srt = clean_and_validate_srt(response_gemini.text)
586
 
587
  if request.time_start and request.time_start > 0: