habulaj commited on
Commit
b2555d5
·
verified ·
1 Parent(s): a7c1d7c

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +89 -29
main.py CHANGED
@@ -264,6 +264,9 @@ async def run_process_url(request: ProcessUrlRequest, record_id: int):
264
  print("Gemini client is not initialized")
265
  return
266
 
 
 
 
267
  temp_file = None
268
  cropped_file_path = None
269
  cropped_video_path = None
@@ -342,13 +345,14 @@ async def run_process_url(request: ProcessUrlRequest, record_id: int):
342
  if chunk:
343
  temp_file.write(chunk)
344
  temp_file.close()
 
345
 
346
  video_path_to_analyze = temp_file.name
347
- files_to_send = [video_path_to_analyze]
348
 
349
  # 3. Crop
350
  if is_image:
351
- print("✂️ Processando imagem: detectando e cortando...")
352
  try:
353
  cropped_file_path = detect_and_crop_image(video_path_to_analyze)
354
  if cropped_file_path and os.path.exists(cropped_file_path):
@@ -356,18 +360,43 @@ async def run_process_url(request: ProcessUrlRequest, record_id: int):
356
  except Exception as e:
357
  print(f"⚠️ Erro ao cortar imagem: {e}")
358
  else:
359
- print("✂️ Processando vídeo: detectando e cortando bordas...")
360
  try:
361
  cropped_video_path = tempfile.NamedTemporaryFile(delete=False, suffix=".mp4").name
362
- crop_success = detect_and_crop_video(video_path_to_analyze, cropped_video_path, text_cut=request.text_cut)
363
- if crop_success and os.path.exists(cropped_video_path):
 
 
 
 
 
 
 
 
 
364
  files_to_send.append(cropped_video_path)
365
- print("✅ Vídeo cortado adicionado como segundo anexo")
 
 
 
 
 
 
 
 
 
 
 
 
 
366
  else:
367
  cropped_video_path = None
368
  except Exception as e:
369
  cropped_video_path = None
370
- print(f"⚠️ Erro ao cortar vídeo: {e}")
 
 
 
371
 
372
  # 4. Montar contextos
373
  contexto_add = f"\n{context}" if context else ""
@@ -395,8 +424,9 @@ async def run_process_url(request: ProcessUrlRequest, record_id: int):
395
 
396
  # 5. Gerar com Gemini
397
  model_obj = get_gemini_model("flash")
398
- print(f"🧠 Enviando para Gemini (flash) [{agent_name}] process-url...")
399
  response_gemini = await client.generate_content(prompt, files=files_to_send, model=model_obj)
 
400
 
401
  titles_data = extract_json_from_text(response_gemini.text)
402
  if not titles_data:
@@ -451,9 +481,9 @@ async def run_process_url(request: ProcessUrlRequest, record_id: int):
451
  screenshot_url = upload_resp.json().get("url", "")
452
 
453
  if screenshot_url:
454
- # Upload vídeo cortado
455
- if video_for_export != temp_file.name:
456
- print("☁️ Enviando vídeo cortado para recurve-save...")
457
  with open(video_for_export, "rb") as vf:
458
  vid_upload_resp = requests.post(
459
  "https://habulaj-recurve-save.hf.space/upload",
@@ -463,9 +493,10 @@ async def run_process_url(request: ProcessUrlRequest, record_id: int):
463
  )
464
  vid_upload_resp.raise_for_status()
465
  exported_cropped_video_url = vid_upload_resp.json().get("url", "")
466
-
467
  export_video_url = exported_cropped_video_url if exported_cropped_video_url else video_url
468
-
 
469
  import cv2
470
  cap = cv2.VideoCapture(video_for_export)
471
  crop_w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) if cap.isOpened() else 1080
@@ -486,7 +517,7 @@ async def run_process_url(request: ProcessUrlRequest, record_id: int):
486
  # Legendas
487
  needs_legenda = result_data.get("legenda", False)
488
  if needs_legenda:
489
- print("🎙️ Gerando legendas (Groq + Gemini)...")
490
  try:
491
  srt_raw, _, _, _ = await get_groq_srt_base(
492
  export_video_url, language="en", temperature=0.4, has_bg_music=False
@@ -709,8 +740,10 @@ async def process_account_endpoint(account: str):
709
  publish_res = await safe_call_publish(account)
710
  return {"status": "ok", "message": "Nenhuma postagem pendente para ser processada.", "publish_result": publish_res}
711
 
 
712
  record = records[0]
713
  record_id = record.get("id")
 
714
  video_url = record.get("ig_post_url")
715
  context = record.get("ig_caption", "")
716
  comments = record.get("comments") # Se existir no banco, pode ser uma lista
@@ -758,12 +791,13 @@ async def process_account_endpoint(account: str):
758
  for chunk in response.iter_content(chunk_size=1024*1024):
759
  if chunk: temp_file.write(chunk)
760
  temp_file.close()
 
761
 
762
  video_path_to_analyze = temp_file.name
763
- files_to_send = [video_path_to_analyze]
764
 
765
  if 'image' in content_type:
766
- print(f"✂️ Processando imagem: detectando e cortando...")
767
  try:
768
  cropped_file_path = detect_and_crop_image(video_path_to_analyze)
769
  if cropped_file_path and os.path.exists(cropped_file_path):
@@ -772,19 +806,44 @@ async def process_account_endpoint(account: str):
772
  print(f"⚠️ Erro ao cortar imagem: {e}")
773
  else:
774
  # Vídeo: detectar e cortar bordas estáticas
775
- print(f"✂️ Processando vídeo: detectando e cortando bordas...")
776
  try:
777
  cropped_video_path = tempfile.NamedTemporaryFile(delete=False, suffix='.mp4').name
778
- crop_success = detect_and_crop_video(video_path_to_analyze, cropped_video_path)
779
- if crop_success and os.path.exists(cropped_video_path):
 
 
 
 
 
 
 
 
 
780
  files_to_send.append(cropped_video_path)
781
- print(f"✅ Vídeo cortado adicionado como segundo anexo para o Gemini")
 
 
 
 
 
 
 
 
 
 
 
 
 
782
  else:
783
  cropped_video_path = None
784
- print(f"⚠️ Crop de vídeo não gerou resultado, seguindo com original apenas")
785
  except Exception as e:
786
  cropped_video_path = None
787
  print(f"⚠️ Erro ao cortar vídeo: {e}")
 
 
 
788
  contexto_add = f"\n{context}" if context else ""
789
  comentarios_add = ""
790
  if comments:
@@ -813,10 +872,11 @@ async def process_account_endpoint(account: str):
813
  )
814
  model_name = record.get("model", "flash") # Tenta pegar do banco, senão flash
815
  model_obj = get_gemini_model(model_name)
816
- print(f"🧠 Enviando para Gemini ({model_name}) para processamento...")
817
 
818
- # Envio do prompt + arquivos (original e opcionalmente cortado) pro Gemini
819
  response_gemini = await client.generate_content(prompt, files=files_to_send, model=model_obj)
 
820
 
821
  titles_data = extract_json_from_text(response_gemini.text)
822
  if not titles_data:
@@ -868,10 +928,9 @@ async def process_account_endpoint(account: str):
868
  screenshot_url = upload_resp.json().get("url", "")
869
 
870
  if screenshot_url:
871
- # 3. Upload do vídeo cortado para recurve-save
872
- cropped_video_url = None
873
- if video_for_export != temp_file.name:
874
- print("☁️ Enviando vídeo cortado para recurve-save...")
875
  with open(video_for_export, 'rb') as vf:
876
  vid_upload_resp = requests.post(
877
  "https://habulaj-recurve-save.hf.space/upload",
@@ -881,12 +940,13 @@ async def process_account_endpoint(account: str):
881
  )
882
  vid_upload_resp.raise_for_status()
883
  cropped_video_url = vid_upload_resp.json().get("url", "")
884
- print(f"✅ Vídeo cortado enviado: {cropped_video_url}")
885
 
886
  # URL do vídeo para o export: cortado se disponível, senão original
887
  export_video_url = cropped_video_url if cropped_video_url else video_url
 
888
 
889
  # 4. Obter dimensões do vídeo para cálculo horizontal/vertical
 
890
  import cv2
891
  cap = cv2.VideoCapture(video_for_export)
892
  crop_w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) if cap.isOpened() else 1080
@@ -920,7 +980,7 @@ async def process_account_endpoint(account: str):
920
  needs_legenda = result_data.get("legenda", False)
921
  srt_for_export = None
922
  if needs_legenda:
923
- print("🎙️ Gerando legendas (Groq + Gemini)...")
924
  try:
925
  # Transcricao via Groq usando o arquivo local
926
  import urllib.request as _urlreq
 
264
  print("Gemini client is not initialized")
265
  return
266
 
267
+ t_start = time.time()
268
+ print(f"🚀 [0.0s] Inciando process-url em background para Record: {record_id}")
269
+
270
  temp_file = None
271
  cropped_file_path = None
272
  cropped_video_path = None
 
345
  if chunk:
346
  temp_file.write(chunk)
347
  temp_file.close()
348
+ print(f"📥 [{time.time()-t_start:.1f}s] Download concluído.")
349
 
350
  video_path_to_analyze = temp_file.name
351
+ files_to_send = [] # Ordem: [cropped, original]
352
 
353
  # 3. Crop
354
  if is_image:
355
+ print(f"✂️ [{time.time()-t_start:.1f}s] Processando imagem: detectando e cortando...")
356
  try:
357
  cropped_file_path = detect_and_crop_image(video_path_to_analyze)
358
  if cropped_file_path and os.path.exists(cropped_file_path):
 
360
  except Exception as e:
361
  print(f"⚠️ Erro ao cortar imagem: {e}")
362
  else:
363
+ print(f"✂️ [{time.time()-t_start:.1f}s] Processando vídeo: detectando e cortando bordas...")
364
  try:
365
  cropped_video_path = tempfile.NamedTemporaryFile(delete=False, suffix=".mp4").name
366
+ crop_status = detect_and_crop_video(video_path_to_analyze, cropped_video_path, text_cut=request.text_cut)
367
+
368
+ if crop_status == "aborted_area_too_small":
369
+ print(f"🚫 [{time.time()-t_start:.1f}s] Crop abortado: área de texto no centro. Negando filtro.")
370
+ requests.patch(f"{supabase_url}/rest/v1/posts?id=eq.{record_id}", headers=headers, json={
371
+ "approved_filter": False,
372
+ "result": {"error": "Rejeitado: Região útil de texto insuficiente para crop seguro (texto centralizado)."}
373
+ })
374
+ return # Para o processamento aqui
375
+
376
+ if crop_status == "success" and os.path.exists(cropped_video_path):
377
  files_to_send.append(cropped_video_path)
378
+ print(f"✅ [{time.time()-t_start:.1f}s] Vídeo cortado com sucesso.")
379
+
380
+ # Upload antecipado para recurve-save (Performance)
381
+ print(f"☁️ [{time.time()-t_start:.1f}s] Enviando vídeo cortado antecipadamente para recurve-save...")
382
+ with open(cropped_video_path, "rb") as vf:
383
+ vid_upload_resp = requests.post(
384
+ "https://habulaj-recurve-save.hf.space/upload",
385
+ files={"files": ("cropped_video.mp4", vf, "video/mp4")},
386
+ data={"long_duration": "yes"},
387
+ timeout=120,
388
+ )
389
+ vid_upload_resp.raise_for_status()
390
+ exported_cropped_video_url = vid_upload_resp.json().get("url", "")
391
+ print(f"✅ [{time.time()-t_start:.1f}s] URL do vídeo cortado: {exported_cropped_video_url}")
392
  else:
393
  cropped_video_path = None
394
  except Exception as e:
395
  cropped_video_path = None
396
+ print(f"⚠️ Erro no processo de crop: {e}")
397
+
398
+ # Adiciona o vídeo original (sempre em segundo se houver crop)
399
+ files_to_send.append(video_path_to_analyze)
400
 
401
  # 4. Montar contextos
402
  contexto_add = f"\n{context}" if context else ""
 
424
 
425
  # 5. Gerar com Gemini
426
  model_obj = get_gemini_model("flash")
427
+ print(f"🧠 [{time.time()-t_start:.1f}s] Enviando para Gemini (flash) [{agent_name}] process-url...")
428
  response_gemini = await client.generate_content(prompt, files=files_to_send, model=model_obj)
429
+ print(f"✨ [{time.time()-t_start:.1f}s] Resposta do Gemini recebida.")
430
 
431
  titles_data = extract_json_from_text(response_gemini.text)
432
  if not titles_data:
 
481
  screenshot_url = upload_resp.json().get("url", "")
482
 
483
  if screenshot_url:
484
+ # 3. Upload do vídeo cortado para recurve-save (Se ainda não foi feito)
485
+ if (video_for_export != temp_file.name) and not exported_cropped_video_url:
486
+ print(f"☁️ [{time.time()-t_start:.1f}s] Enviando vídeo cortado para recurve-save...")
487
  with open(video_for_export, "rb") as vf:
488
  vid_upload_resp = requests.post(
489
  "https://habulaj-recurve-save.hf.space/upload",
 
493
  )
494
  vid_upload_resp.raise_for_status()
495
  exported_cropped_video_url = vid_upload_resp.json().get("url", "")
496
+
497
  export_video_url = exported_cropped_video_url if exported_cropped_video_url else video_url
498
+
499
+ print(f"📏 [{time.time()-t_start:.1f}s] Preparando export...")
500
  import cv2
501
  cap = cv2.VideoCapture(video_for_export)
502
  crop_w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) if cap.isOpened() else 1080
 
517
  # Legendas
518
  needs_legenda = result_data.get("legenda", False)
519
  if needs_legenda:
520
+ print(f"🎙️ [{time.time()-t_start:.1f}s] Gerando legendas (Groq + Gemini)...")
521
  try:
522
  srt_raw, _, _, _ = await get_groq_srt_base(
523
  export_video_url, language="en", temperature=0.4, has_bg_music=False
 
740
  publish_res = await safe_call_publish(account)
741
  return {"status": "ok", "message": "Nenhuma postagem pendente para ser processada.", "publish_result": publish_res}
742
 
743
+ t_start = time.time()
744
  record = records[0]
745
  record_id = record.get("id")
746
+ print(f"🚀 [0.0s] Inciando processamento da conta '{account}' para Record: {record_id}")
747
  video_url = record.get("ig_post_url")
748
  context = record.get("ig_caption", "")
749
  comments = record.get("comments") # Se existir no banco, pode ser uma lista
 
791
  for chunk in response.iter_content(chunk_size=1024*1024):
792
  if chunk: temp_file.write(chunk)
793
  temp_file.close()
794
+ print(f"📥 [{time.time()-t_start:.1f}s] Download concluído.")
795
 
796
  video_path_to_analyze = temp_file.name
797
+ files_to_send = [] # Ordem: [cropped, original]
798
 
799
  if 'image' in content_type:
800
+ print(f"✂️ [{time.time()-t_start:.1f}s] Processando imagem: detectando e cortando...")
801
  try:
802
  cropped_file_path = detect_and_crop_image(video_path_to_analyze)
803
  if cropped_file_path and os.path.exists(cropped_file_path):
 
806
  print(f"⚠️ Erro ao cortar imagem: {e}")
807
  else:
808
  # Vídeo: detectar e cortar bordas estáticas
809
+ print(f"✂️ [{time.time()-t_start:.1f}s] Processando vídeo: detectando e cortando bordas...")
810
  try:
811
  cropped_video_path = tempfile.NamedTemporaryFile(delete=False, suffix='.mp4').name
812
+ crop_status = detect_and_crop_video(video_path_to_analyze, cropped_video_path)
813
+
814
+ if crop_status == "aborted_area_too_small":
815
+ print(f"🚫 [{time.time()-t_start:.1f}s] Crop abortado: área de texto no centro. Negando filtro.")
816
+ requests.patch(f"{supabase_url}/rest/v1/posts?id=eq.{record_id}", headers=headers, json={
817
+ "approved_filter": False,
818
+ "result": {"error": "Rejeitado: Região útil de texto insuficiente para crop seguro (texto centralizado)."}
819
+ })
820
+ return {"status": "rejected", "message": "Postagem rejeitada por crop insuficiente."}
821
+
822
+ if crop_status == "success" and os.path.exists(cropped_video_path):
823
  files_to_send.append(cropped_video_path)
824
+ print(f"✅ [{time.perf_counter()-t_start:.1f}s] Vídeo cortado com sucesso.")
825
+
826
+ # Upload antecipado para recurve-save (Performance)
827
+ print(f"☁️ [{time.time()-t_start:.1f}s] Enviando vídeo cortado antecipadamente para recurve-save...")
828
+ with open(cropped_video_path, 'rb') as vf:
829
+ vid_upload_resp = requests.post(
830
+ "https://habulaj-recurve-save.hf.space/upload",
831
+ files={'files': ('cropped_video.mp4', vf, 'video/mp4')},
832
+ data={'long_duration': 'yes'},
833
+ timeout=120
834
+ )
835
+ vid_upload_resp.raise_for_status()
836
+ cropped_video_url = vid_upload_resp.json().get("url", "")
837
+ print(f"✅ [{time.time()-t_start:.1f}s] URL do vídeo cortado: {cropped_video_url}")
838
  else:
839
  cropped_video_path = None
840
+ print(f"⚠️ [{time.time()-t_start:.1f}s] Crop de vídeo não gerou resultado, seguindo com original apenas")
841
  except Exception as e:
842
  cropped_video_path = None
843
  print(f"⚠️ Erro ao cortar vídeo: {e}")
844
+
845
+ # Adiciona o vídeo original (sempre em segundo se houver crop)
846
+ files_to_send.append(video_path_to_analyze)
847
  contexto_add = f"\n{context}" if context else ""
848
  comentarios_add = ""
849
  if comments:
 
872
  )
873
  model_name = record.get("model", "flash") # Tenta pegar do banco, senão flash
874
  model_obj = get_gemini_model(model_name)
875
+ print(f"🧠 [{time.time()-t_start:.1f}s] Enviando para Gemini ({model_name}) para processamento...")
876
 
877
+ # Envio do prompt + arquivos (cortado e original) pro Gemini
878
  response_gemini = await client.generate_content(prompt, files=files_to_send, model=model_obj)
879
+ print(f"✨ [{time.time()-t_start:.1f}s] Resposta do Gemini recebida.")
880
 
881
  titles_data = extract_json_from_text(response_gemini.text)
882
  if not titles_data:
 
928
  screenshot_url = upload_resp.json().get("url", "")
929
 
930
  if screenshot_url:
931
+ # 3. Upload do vídeo cortado para recurve-save (Se ainda não foi feito)
932
+ if (video_for_export != temp_file.name) and not cropped_video_url:
933
+ print(f"☁️ [{time.time()-t_start:.1f}s] Enviando vídeo cortado para recurve-save...")
 
934
  with open(video_for_export, 'rb') as vf:
935
  vid_upload_resp = requests.post(
936
  "https://habulaj-recurve-save.hf.space/upload",
 
940
  )
941
  vid_upload_resp.raise_for_status()
942
  cropped_video_url = vid_upload_resp.json().get("url", "")
 
943
 
944
  # URL do vídeo para o export: cortado se disponível, senão original
945
  export_video_url = cropped_video_url if cropped_video_url else video_url
946
+ print(f"✅ [{time.time()-t_start:.1f}s] Vídeo para export: {export_video_url}")
947
 
948
  # 4. Obter dimensões do vídeo para cálculo horizontal/vertical
949
+ print(f"📏 [{time.time()-t_start:.1f}s] Preparando export...")
950
  import cv2
951
  cap = cv2.VideoCapture(video_for_export)
952
  crop_w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) if cap.isOpened() else 1080
 
980
  needs_legenda = result_data.get("legenda", False)
981
  srt_for_export = None
982
  if needs_legenda:
983
+ print(f"🎙️ [{time.time()-t_start:.1f}s] Gerando legendas (Groq + Gemini)...")
984
  try:
985
  # Transcricao via Groq usando o arquivo local
986
  import urllib.request as _urlreq