
    j3                        d Z ddlZddlZddlZddlmZ ddlZddlmZ ddl	m
Z
mZ ddlmZ ddlmZmZ ddlmZ d	Z ej*                  d
d      Z ee      j0                  dz  Z ee      j0                  dz  Z ee      j0                  dz  ZdZdZdedefdZde defdZ!de"fdZ#	 	 	 	 	 	 d#de"de"de"dede$de"de"de"de$de$d e%d!e"fd"Z&y)$u.   Pipeline principal de processamento de vídeo.    N)Path)transcrever_audio)buscar_videosbaixar_video)gerar_videos_seedance)cortar_segmentosmontar_video_final)obter_musica_para_videozl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PEXELS_API_KEYPEXELS_API_KEY_PLACEHOLDERtempoutputmusicg      @   	segmentosreturnc                    | sg S g }| d   d   | d   d   | d   d   d}| dd D ]P  }|d   |d   z
  t         k  r|d   |d<   |dxx   d|d   z   z  cc<   1|j                  |       |d   |d   |d   d}R |j                  |       t        |      t        kD  r=t        |      t        z  }t	        t              D cg c]  }|t        ||z            }}|S c c}w )	z
    Agrupa segmentos do Whisper em janelas de ~JANELA_SEG segundos.
    Retorna [{"inicio": float, "fim": float, "texto": str}, ...].
    r   iniciofimtexto)r   r   r      N )
JANELA_SEGappendlenMAX_JANELASrangeint)r   janelasatualsegstepis         4/opt/mia/workspace/video_editor/backend/processor.py_construir_janelasr%      s
   
 	G |H-il56IT]^_T`ahTijE} XJx(Z7u:E%L'NcCL00NNN5!"8}SZ#g,WEX NN5 7|k!7|k)383EFa73q4x=)FFN Gs   =Ctranscricaoc                    | j                  dg       }t        |      }|sg S t        j                  t              }dj                  d t        |      D              }d| d}	 |j                  j                  ddd	|d
g      }|j                  d   j                  }t        j                  d|t        j                        }|st        d|dd         g S t        j                   |j#                               }	|	j                  dg       }
g }|
D ]  }	 t%        |j                  dd            dz
  }|j                  d      xs dj'                         }|dk  s|t)        |      k\  rY|r|j+                         dk(  ro||   }|j-                  t/        |d         t/        |d         |d        |S # t0        $ r Y w xY w# t0        $ r}t        d|        g cY d}~S d}~ww xY w)u   
    Para cada janela de ~7s da transcrição, gera uma query visual em inglês via Claude.
    Retorna lista alinhada: [{"inicio": float, "fim": float, "query": str}, ...].
    r   )api_key
c           	   3   t   K   | ]0  \  }}|d z    d|d   dd|d   dd|d   j                           2 yw)	r   z. [r   z.1fzs - r   zs] r   N)strip).0r#   js      r$   	<genexpr>z&analisar_para_broll.<locals>.<genexpr>H   sR      Aq Q3%s1X;s#4%~S79I9I9K8LMs   68u%  Você está ajudando a editar um Reel para Instagram. Para cada trecho de fala numerado abaixo, sugira UMA query de busca em inglês (3-5 palavras visuais concretas) para encontrar um vídeo no Pexels que ILUSTRE visualmente o conceito específico falado naquele trecho.

Regras:
- Sempre em inglês
- 3 a 5 palavras concretas e visuais (ex: "person typing laptop", "city skyline sunset", "team meeting office")
- NÃO repita a mesma query
- Se o trecho for muito genérico/conectivo (sem conceito visual claro), retorne "skip" como query

Trechos:
u   

Retorne APENAS um JSON válido neste formato (sem texto antes ou depois):
{
  "brolls": [
    {"n": 1, "query": "person typing laptop"},
    {"n": 2, "query": "skip"},
    ...
  ]
}zclaude-haiku-4-5i  user)rolecontent)model
max_tokensmessagesr   z\{.*\}z[claude] Resposta sem JSON: N   brollsnr   query skipr   r   )r   r   r8   z'[claude] Erro ao analisar para b-roll: )getr%   	anthropic	AnthropicANTHROPIC_KEYjoin	enumerater4   creater1   textresearchDOTALLprintjsonloadsgroupr   r+   r   lowerr   float	Exception)r&   r   r   clientbloco_janelaspromptresprB   matchdataitemsoutitidxr8   r-   es                    r$   analisar_para_brollrX   ;   s   
 R0I +G	  7F II g& M
	  	F(#%%$%&9: & 

 ||A##		)T29950ds=>Izz%++-(2&  	B"&&a.)A-.B5577cS\1 7CL

#AhK0 5?" 	  
    7s;<	sb   $A4G <G AF7*G +F7 G 2F73G 7	G G GG 	G)G$G)$G)c                  &   t         j                         syt        t         j                  d            t        t         j                  d            z   t        t         j                  d            z   } | syddl}t        |j                  |             S )uQ   Retorna o caminho de uma música aleatória do diretório music/, ou '' se vazio.r9   *.mp3z*.m4az*.aacr   N)	MUSIC_DIRexistslistglobrandomstrchoice)musicasr_   s     r$   escolher_musicarc      sk    9>>'*+d9>>'3J.KKdS\SaSabiSjNkkGv}}W%&&    job_id
video_pathmodousar_musicaestilo_legendatamanho_legendamusica_path_diretousar_legenda
usar_brollvolume_musicabroll_fontec                 	   |xs dj                         dk(  rd}
|xs dj                         }|dvrd}	  || ddd       |d	k(  r'|r%t        d
t        |       d       t        |||       }|	xs |
}dg d}|r@ || ddd       t        d| d       t	        |      }t        dt        |d                 nt        d        || ddd       g }|
r || ddd       t        |      }t        d| d|D cg c]  }|d   |d   |d   f c}        |dk(  rv || d d!d"t        |       d#       	 t        || t        d$%      }|D ]   }|j                  |d&   |d   |d   d'       " 	 t        d*t        |       d+t        |              n || d,d-d.       t        |      D ]  \  }}|j                  dd      }|st        |d/0      }d}|d)d/ D ]K  }t        t        |  d1|d2d3z        }t        |d4   |      }|s.|j                  ||d   |d   d'       d5} n d6|d7z    d+t        |       d8| |rdnd9z   } || d,t        d-|d:z  z   d;      |        t        d<t        |              nt        d=        || dd-d>        || d?d@dA       t        t         |  dBz        }d}|r&|r5t#        |      j%                         r|} || d?d;dC       t        dD|        n || d?d;dE       	 t'        |j                  dFd      |       xs d}|rt        dH|        ng } t(        j%                         rnt(        j+                         D ]3  }!|!j-                         s| j/                  |!j1                  dI             5 | j/                  t(        j1                  dI             | r,dJd)l}"t        |"j5                  |             }t        dK|        |	r|nd}#t7        |||||#| |||L	       t#        |      j%                         st9        dM       || dNdOdP|       y)c c}w # t        $ r}t        d(|        g }Y d)}~d)}~ww xY w# t        $ r}t        dG|        d}Y d)}~Yd)}~ww xY w# t        $ rF}t        dQ|  d8|        dJd)l}$|$j=                           || dRdJdSt        |              Y d)}~y)d)}~ww xY w)Tu  
    Pipeline completo (toggles independentes):
    1. Corta segmentos (modo live)
    2. Transcrição Whisper (sempre, pra alimentar B-roll/legenda quando ativos)
    3. Análise Claude para b-roll (se usar_broll)
    4. Download b-roll Pexels OU geração via Seedance (se usar_broll)
    5. Montagem final com FFmpeg (legenda/música/B-roll condicionais)

    Args extras:
        usar_legenda: se False, pula queima de legenda no vídeo final.
        usar_broll:   se False, pula análise/download.
        usar_musica:  se False, output sem música.
        broll_fonte:  "pexels" (default, gratuito) | "seedance" (IA, pago)
                      "none" é tratado como usar_broll=False.
    r9   noneFpexels>   rr   seedancefila   u   Preparando vídeo...livez[proc] Cortando z segmentos...)r   r   transcrevendo   u   Transcrevendo áudio com IA...z[proc] Transcrevendo z...u$   [proc] Transcrição OK. Segmentos: r   u3   [proc] Transcrição pulada (legenda + b-roll off).
preparandou(   Preparando vídeo (sem transcrição)...
analisando   u*   Analisando conteúdo para buscar B-roll...z[proc] B-rolls alinhados (z): r   r   r8   rs   gerando_broll(   zGerando z' cena(s) com IA (pode levar 1-2 min)...720p)termosre   temp_dir
resolutionpath)r   r   r   z*[proc] Seedance falhou catastroficamente: Nz![proc] B-rolls Seedance gerados: /baixando_broll-   u   Buscando vídeos de apoio...   )
quantidade_broll_02dz.mp4urlTzB-roll r   z: z (sem resultado)   <   z [proc] B-rolls Pexels baixados: z([proc] B-roll pulado (usar_broll=False).zPulando B-roll...montandoA   u   Montando vídeo final...z
_final.mp4zAplicando trilha selecionada...u(   [proc] Música escolhida pelo usuário: u%   Buscando trilha sonora automática...r   z[proc] ccMixter falhou: u'   [proc] Música automática (ccMixter): rZ   r   u!   [proc] Música local (fallback): )	video_principalclips_brollr&   musica_pathri   re   output_pathrj   rn   u.   Arquivo de saída não foi gerado pelo FFmpeg.	concluidod   u   Pronto! Seu Reel está pronto.z[proc] ERRO no job errozErro no processamento: )rJ   rF   r   _cortar_segmentosr   rX   r   TEMP_DIRr   rL   r@   r;   r   r`   r   min
OUTPUT_DIRr   r\   r
   r[   iterdiris_dirextendr^   r_   ra   r	   RuntimeError	traceback	print_exc)%re   rf   rg   r   rh   ri   callback_statusrj   rk   rl   rm   rn   ro   precisa_transcricaor&   r   r   tclips_seedancecrW   r#   termor8   videosbaixadovdestok
status_msgr   r   musicas_locaissubr_   estilo_efetivor   s%                                        r$   processar_videor      s   > 	r  "f,
*(113K00OO+AB6>i$S^$4MBC*:y&IJ +8j "4FOR9YZ)*S9:+J7K8[=U9V8WXYGIFL"6`a FL"6bc(5F.{m3CIJaq{AeHaj9JKM N j(ORs6{m+RS%%:%%!)#)	&N , #**$%fI&'k#$U8,  9#k:J9K1SQW[MZ[  (8">\] )& 1 _HAu!IIgr2E  *5Q?F#G#BQZ 
""8#wd.K#KL)!E(D9'..(,*//',U|0 
 '+G!
" $+1Q3%qVRw!GQX2^p!qJ#F,<c"q1u*b>QS]^%_( 8[9I8JKL<>FL"6IJ 	
B0JK*&'<<= !d+=&>&E&E&G0
B8YZ@NO
B8_`%"9+//'SU:VX^"_"eceK CK=QR &(N '')#,#4#4#6 IC"zz| . 5 5chhw6G HI '--innW.EF%%&)&--*G&H A+OP ,8R&###)#+'
	
 K '')OPPS2RT_`Y K, ! %FqcJK"$K%d ! %4QC89"$K%L  O#F82aS12-DSVH+MNN	Os   CQ5 7P"&Q5 38P' +BQ5 C0Q5 4 Q AQ5 #B>Q5 "Q5 '	Q0Q Q5 QQ5 	Q2Q-'Q5 -Q22Q5 5	S><R??S)medioNTT   rr   )'__doc__rG   osrC   pathlibr   r<   whisper_utilsr   pexels_utilsr   r   seedance_utilsr   ffmpeg_utilsr   r   r	   music_utilsr
   r>   getenv
PEXELS_KEY__file__parentr   r   r[   r   r   r]   r%   dictrX   r`   rc   boolr   r    rd   r$   <module>r      sd   4  	 	   + 4 0 R /~RYY')EF
>  6)(^""X-
N!!G+	 
$ 4 <IT Id IX' '& #"sOsOsO sO 	sO
 sO sO sO sO sO sO sO sOrd   