Ë
    ’ßjtŽ  ã                   óÒ  — U d Z ddlZddlZddlZddlZddlZddlZddlmZmZ ddl	m
Z
 ddlmZ ddlmZmZmZmZ ddlmZ ddlmZ dae
e   ed	<   dae
e   ed
<   defd„Zdefd„Zdefd„Zdefd„Zdededefd„Z 	 	 dUde!dede
e   de
e"   dejF                  f
d„Z$dede%fd„Z&dddddœZ'd ede(fd!„Z)d ede(fd"„Z*d#d$d%œd&ed'ed(ed)ed*edefd+„Z+d,d-œded(ed.ed/e(de%f
d0„Z,d1ede
e   fd2„Z-d3ed4ede
e   fd5„Z.d6eddfd7„Z/d8eded4ede
e   fd9„Z0d8eded4ede
e   fd:„Z1d;ed4ede
e   fd<„Z2d=d>d?d@dAdBœZ3dCdDdEdFdGdBœZ4dHdIdJddKœdLed(edMe%dNedOe%dPeddfdQ„Z5dRed(ede(fdS„Z6deddfdT„Z7y)Vuí  
GOLS - AI Avatar Video Generation Pipeline
==========================================
Runs as a FastAPI BackgroundTask (no Celery needed).

Pipeline stages (executed in order):
  1. TTS           - script -> voice.mp3   (OpenAI TTS -> gTTS -> pyttsx3 -> silence)
  2. Base / Liveness - image|video + audio -> base.mp4
                       â€¢ image + GPU models OFF -> FFmpeg "liveness" (Ken-Burns
                         motion + subtle head sway) so the avatar looks alive
                       â€¢ video source -> looped/clipped to audio length
  3. Face animation (LivePortrait / SadTalker)  - run if model installed
  4. Lip sync (Wav2Lip)                          - run if model installed
  5. Face enhancement (CodeFormer / GFPGAN)      - run if model installed
  6. Watermark (logo overlay, opacity/position)  - if enabled in settings
  7. Thumbnail + save to outputs/ + record in videos.json

GPU-only stages (3-5) are *actually invoked* now (previously TODO stubs). Each
runner is guarded: if the model directory / entrypoint is missing or the run
fails, the pipeline logs it and falls back to the previous stage's output so a
video is always produced. On a machine with the models installed and a CUDA GPU,
they execute and chain their outputs.
é    N)ÚdatetimeÚtimezone)ÚOptional)Úcfg)Úprojects_storeÚavatars_storeÚvideos_storeÚsettings_store)Úlog)Úopenai_serviceÚ_FFMPEGÚ_FFPROBEÚreturnc                  ó   — t         rt         S t        j                  xs dj                  «       } | rk| dk7  rft        j
                  j                  | «      r| a t         S | j                  d«      r| n| dz   }t        j
                  j                  |«      r|a t         S t        j                  d«      }|r|a t         S ddddt        j
                  j                  t        j                  j                  dd«      dd	d
«      t        j
                  j                  t        j                  j                  dd«      dd	d
«      g}|D ]A  }t        j
                  j                  |«      sŒ#|a t        j                  d|«       t         c S  t        d«      ‚)NÚ Úffmpegú.exezC:\ffmpeg\bin\ffmpeg.exez&C:\Program Files\ffmpeg\bin\ffmpeg.exez,C:\Program Files (x86)\ffmpeg\bin\ffmpeg.exezC:\tools\ffmpeg\bin\ffmpeg.exeÚUSERPROFILEÚbinz
ffmpeg.exeÚLOCALAPPDATAz[pipeline] Found ffmpeg at: %sa  ffmpeg not found!

FIX (Windows):
  1. Download from https://www.gyan.dev/ffmpeg/builds/
  2. Extract to C:\ffmpeg\
  3. Add C:\ffmpeg\bin to PATH, OR set FFMPEG_PATH in backend/.env
FIX (macOS):  brew install ffmpeg
FIX (Linux):  sudo apt install ffmpeg
Then restart the app.)r   r   ÚFFMPEG_PATHÚstripÚosÚpathÚisfileÚendswithÚshutilÚwhichÚjoinÚenvironÚgetr   ÚinfoÚRuntimeError)Úenv_pathÚexeÚfoundÚ	win_pathsÚps        úm/Users/priyanka/Documents/AI_Agent_Assessment/ai-video-generator-gols-v2-new/backend/app/services/pipeline.pyÚ_find_ffmpegr*   -   s9  € åÜˆÜ—‘Ò% 2×,Ñ,Ó.€HÙ�H Ò(Ü�7‰7�>‰>˜(Ô#ØˆGÜˆNØ"×+Ñ+¨FÔ3‰h¸ÀFÑ9JˆÜ�7‰7�>‰>˜#ÔØˆGÜˆNÜ�L‰L˜Ó"€EÙØˆÜˆà#Ø1Ø7Ø)Ü
�‰�‰”R—Z‘Z—^‘^ M°2Ó6¸À%ÈÓVÜ
�‰�‰”R—Z‘Z—^‘^ N°BÓ7¸À5È,ÓWð€Ió ˆÜ�7‰7�>‰>˜!ÕØˆGÜ�H‰HÐ5°qÔ9ÜŠNð	 ô
 ð	 ó	ð 	ó    c                  ód  — t         rt         S t        «       } t        j                  j	                  t        j                  j                  | «      d«      }t        j                  dk(  r|dz  }t        j                  j                  |«      r|a t         S t        j                  d«      xs da t         S )NÚffprobeÚwin32r   )r   r*   r   r   r   ÚdirnameÚsysÚplatformr   r   r   )Úffmpeg_pathr-   s     r)   Ú_find_ffprober3   W   s~   € åÜˆÜ“.€KÜ�g‰g�l‰lœ2Ÿ7™7Ÿ?™?¨;Ó7¸ÓC€GÜ
‡|�|�wÒØ�6ÑˆÜ	‡w�w‡~�~�gÔØˆô €Oô —<‘< 	Ó*Ò7¨iˆÜ€Or+   c                  ód   — t        j                  t        j                  «      j	                  «       S ©N)r   Únowr   ÚutcÚ	isoformat© r+   r)   Ú_nowr:   g   s   € Ü�<‰<œŸ™Ó%×/Ñ/Ó1Ð1r+   Ú
project_idc                 ó0   — t        j                  | |«       y r5   )r   Úupdate)r;   Úfieldss     r)   Ú_setr?   k   s   € Ü×Ñ˜* fÕ-r+   ÚstageÚexcc                 óp   — |› d|› �}t        j                  d| |«       t        | d||t        «       ¬«       y )Nz: z[pipeline] %s FAILED - %sÚfailed)ÚstatusÚerrorr@   Ú
updated_at)r   rE   r?   r:   )r;   r@   rA   Úmsgs       r)   Ú_errrH   o   s5   € ØˆG�2�c�UÐ
€CÜ‡I�IÐ)¨:°sÔ;Üˆ˜H¨C°uÌËÖPr+   ÚcmdÚlabelÚcwdÚtimeoutc           	      ó
  — t        j                  d|dj                  d„ | D «       «      «       t        j                  | dddd||¬«      }|j
                  dk7  r*t        |› d	|j
                  › d
|j                  dd › �«      ‚|S )zERun a subprocess; raise RuntimeError with a clean message on failure.z[pipeline] %s: %sÚ c              3   ó2   K  — | ]  }t        |«      –— Œ y ­wr5   )Ústr)Ú.0Úcs     r)   Ú	<genexpr>z_run.<locals>.<genexpr>x   s   è ø€ Ð2GÁ3¸a´3°q·6Á3ùs   ‚Túutf-8Úreplace)Úcapture_outputÚtextÚencodingÚerrorsrK   rL   r   z failed (exit z):
iDýÿÿN)r   Údebugr   Ú
subprocessÚrunÚ
returncoder#   Ústderr)rI   rJ   rK   rL   Úresults        r)   Ú_runr`   u   sˆ   € ô ‡I�IÐ! 5¨#¯(©(Ñ2GÁ3Ó2GÓ*GÔHÜ�^‰^Ø˜D t°gÀiØ˜ô€Fð ×Ñ˜AÒÜ˜e˜W N°6×3DÑ3DÐ2EÀTÈ&Ï-É-ÐX\ÐX]ÐJ^ÐI_Ð`ÓaÐaØ€Mr+   Ú
audio_pathc           
      óÀ   — t        «       }	 t        j                  |dddddd| gdddd	¬
«      }t        |j                  j                  «       «      S # t        $ r Y yw xY w)Nú-vrE   z-show_entrieszformat=durationz-ofz"default=noprint_wrappers=1:nokey=1TrT   rU   )rV   rW   rX   rY   g      $@)r3   r[   r\   ÚfloatÚstdoutr   Ú	Exception)ra   r-   Úprobes      r)   Ú_audio_durationrh   ‚   sk   € Ü‹o€GðÜ—‘Ø�d˜G _Ð6GØÐ8¸*ðFà d°WÀYô
ˆô
 �U—\‘\×'Ñ'Ó)Ó*Ð*øÜò Ùðús   ŒAA Á	AÁAz854:480z1280:720ú	1920:1080z	3840:2160)Ú480pÚ720pÚ1080pÚ4kr   c                 óf   — t         j                  j                  | «      d   j                  «       dv S )Né   )ú.jpgz.jpegz.pngz.webpz.bmp©r   r   ÚsplitextÚlower©r   s    r)   Ú	_is_imageru   ’   s+   € Ü�7‰7×Ñ˜DÓ! !Ñ$×*Ñ*Ó,Ð0ZÐZÐZr+   c                 óf   — t         j                  j                  | «      d   j                  «       dv S )Nro   )ú.mp4z.aviz.movz.mkvz.webmrq   rt   s    r)   Ú	_is_videorx   –   s+   € Ü�7‰7×Ñ˜DÓ! !Ñ$×*Ñ*Ó,Ð0YÐYÐYr+   ÚfemaleÚnatural©ÚgenderÚemotionÚscriptÚlangÚout_pathr|   r}   c                óÀ  — t        j                  «       rP	 | }	 t        j                  | ||¬«      }t        j                  |||||¬«      rt	        j                  d|||«       ynt	        j
                  d«       	 d	d
lm	} d} || ||v r|nd¬«      }	|	j                  |«       t	        j                  d||«       y# t        $ r }t	        j
                  d|«       Y d}~Œ¯d}~ww xY w# t        $ r }t	        j
                  d|«       Y d}~Œ’d}~ww xY w# t        $ r }t	        j
                  d|«       Y d}~nd}~ww xY wt        j                  dk(  �rt        j                  d«      �r	 dddddddddddœ
}
|
j                  |xs dj!                  «       d«      \  }}|xs dj!                  «       dk(  r|n|}|j#                  d d!«      }t%        dd"|d#|d$| gd%«       t%        t'        «       d&d'|d(d)|gd*«       t(        j*                  j-                  |«      rt)        j.                  |«       t	        j                  d+||«       y# t        $ r }t	        j
                  d,|«       Y d}~nd}~ww xY w	 d	dl}|j3                  «       }|j5                  d-d.«       	 |j7                  d/«      }|xs dj!                  «       dk(  rdnd0}|D ]b  }t9        |d1d«      › d2t9        |d3d«      › �j!                  «       }||v s|dk(  rd4|v s|d0k(  sŒAd5|v sŒF|j5                  d6|j:                  «        n n# t        $ r Y nw xY w|j#                  d d7«      }|j=                  | |«       |j?                  «        t%        t'        «       d&d'||gd8«       t(        j*                  j-                  |«      rt)        j.                  |«       t	        j                  d9|«       y:# t        $ r }t	        j
                  d;|«       Y d}~nd}~ww xY wtA        d<tC        tE        | «      d=z  d>«      «      }t%        t'        «       d&d?d@d'dAdBtG        |«      |g	dC«       t	        j
                  dD|«       yE)FzKGenerate voice audio. Returns the engine used: openai|gtts|pyttsx3|silence.)Úlanguager}   z+[pipeline] speech optimisation skipped (%s)N)r|   r‚   r}   z,[pipeline] TTS done via OpenAI (%s/%s) -> %sÚopenaiz7[pipeline] OpenAI TTS failed (%s), falling back to gTTSu„   [pipeline] OpenAI TTS unavailable (no key or 'openai' package not installed). Falling back to gTTS â€” run: pip install openai httpxr   )ÚgTTS)ÚenÚhiÚmrÚtaÚteÚknÚmlÚguÚbnÚpaÚurÚesÚfrÚdeÚjaÚzhÚarÚptÚruÚitr…   )rW   r   z'[pipeline] TTS done via gTTS (%s) -> %sÚgttsz2[pipeline] gTTS failed (%s), trying macOS 'say'...ÚdarwinÚsay)ÚSamanthaÚAlex)ÚLekharž   )ÚAmelieÚThomas)ÚAnnaÚMarkus)ÚMonicaÚJorge)ÚAliceÚLuca)ÚKyokoÚOtoya)ÚTingtingr©   )ÚLucianaÚFelipe)ÚMilenaÚYuri)
r…   r†   r‘   r’   r�   r˜   r“   r”   r–   r—   r   ry   z.mp3z	_say.aiffrc   ú-oz--z	macos-sayú-yú-iú-b:aÚ160kzsay->mp3z,[pipeline] TTS done via macOS say (%s) -> %sz3[pipeline] macOS say failed (%s), trying pyttsx3...Úrateé    ÚvoicesÚmaleÚnamerN   ÚidÚziraÚdavidÚvoicez_tmp.wavzpyttsx3->mp3z%[pipeline] TTS done via pyttsx3 -> %sÚpyttsx3z9[pipeline] pyttsx3 failed (%s), using silence fallback...é   é   éx   ú-fÚlavfizanullsrc=r=44100:cl=monoú-tzsilence-fallbacku²   [pipeline] NO VOICE: all TTS engines failed â€” produced SILENT audio (%ds). Install openai (pip install openai httpx) and set OPENAI_API_KEY, or ensure internet access for gTTS.Úsilence)$ÚaiÚ
is_enabledÚoptimize_for_speechrf   r   ÚwarningÚsynthesize_speechr"   r™   r„   Úsaver0   r1   r   r   r!   rs   rU   r`   r*   r   r   ÚexistsÚremover¼   ÚinitÚsetPropertyÚgetPropertyÚgetattrr¸   Úsave_to_fileÚ
runAndWaitÚmaxÚminÚlenrP   )r~   r   r€   r|   r}   ÚspokenÚer„   Ú	supportedÚttsÚ	mac_voiceÚfemr¶   ÚvÚaiffr¼   Úenginerµ   ÚwantÚmetaÚwav_tmpÚdurations                         r)   Ú	stage_ttsrâ   �   s&  € ô 
‡}�}„ð	VØˆFðNÜ×/Ñ/°ÀÈwÔW�ô ×#Ñ# F¨H¸VØ-1¸7õDä—‘ÐGÈÐQUÐW_Ô`ØðDô 	�‰ð Yô 	Zð	MÝðQˆ	á˜¨T°YÑ->¡TÀDÔIˆØ�‰�ÔÜ�‰Ð:¸DÀ(ÔKØøô) ò NÜ—‘ÐIÈ1×MÑMûðNûô ò 	VÜ�K‰KÐQÐST×UÑUûð	Vûô ò MÜ�‰ÐHÈ!×LÑLûðMúô ‡|�|�xÓ¤F§L¡L°Õ$7ð	Rð +Ð2DØ*Ð2DØ)Ð1BØ(Ð0HØ+Ð3EñˆIð "Ÿ™ t¢|¨t×&:Ñ&:Ó&<Ð>RÓS‰IˆC�Øš "×+Ñ+Ó-°Ò9‘¸tˆAØ×#Ñ# F¨KÓ8ˆDÜ�%˜˜q $¨¨d°FÐ;¸[ÔIÜ”,“. $¨¨d°F¸FÀHÐMÈzÔZÜ�w‰w�~‰~˜dÔ#Ü—	‘	˜$”Ü�H‰HÐCÀQÈÔQØøÜò 	RÜ�K‰KÐMÈq×QÑQûð	RúðTÛØ—‘“ˆØ×Ñ˜6 3Ô'ð
	Ø×'Ñ'¨Ó1ˆFØ &¢¨"×3Ñ3Ó5¸ÒA‘8ÀvˆDÛ�Ü! ! F¨2Ó.Ð/¨q´¸¸4ÀÓ1CÐ0DÐE×KÑKÓM�Ø˜4‘< D¨HÒ$4¸À4¹Ø˜F“N w°$¢Ø×&Ñ& w°·±Ô5Ùð ùô ò 	Ùð	úà×"Ñ" 6¨:Ó6ˆØ×Ñ˜F GÔ,Ø×ÑÔÜŒl‹n˜d D¨'°8Ð<¸nÔMÜ�7‰7�>‰>˜'Ô"Ü�I‰I�gÔÜ�‰Ð8¸(ÔCØøÜò TÜ�‰ÐOÐQR×SÑSûðTúô �1”cœ#˜f›+¨Ñ+¨SÓ1Ó2€HÜŒ,‹.˜$  g¨tÐ5OØ
”�H“˜xð
)Ø*<ô>ä‡K�Kð ,à-5ô7ð s»   –C( ™B< ±2C( Á;A D Â<	C%ÃC ÃC( Ã C%Ã%C( Ã(	DÃ1DÄDÄ	D=ÄD8Ä8D=Å+CI É	I/ÉI*É*I/É3&O ÊA.L. Ì	L. ÌL. Ì-O Ì.	L:Ì7O Ì9L:Ì:BO Ï	O>ÏO9Ï9O>T©ÚlivenessÚ
resolutionrä   c                ó®  — t         j                  |d«      }|j                  d«      \  }}t        «       }t	        |«      }	d}
d|› d|› d|› d�}| rQt
        j                  j                  | «      r2t        | «      r'|ddd	d
| d
|dt        |	«      d|ddddddddddddd|g}�n| rát
        j                  j                  | «      rÂt        | «      r·|r�d}d|
dz  › d�}d|
dz  › d �}d!|› d|› d"|› d|› d#|› d|› d$|› d%|› d&|› d'|› d(|› d)|
› d*�}g |‘d‘d+‘d,‘d
‘| ‘d
‘|‘d‘t        |	«      ‘d-‘t        |
«      ‘d.‘|‘d/‘d0‘d/‘d1‘d‘d‘d‘d‘d‘d2‘d‘d‘d‘d‘d‘d‘d‘|‘}nR|dd+d,d
| d
|dt        |	«      d|dddddddddddd|g}n-|dd3d4d
d5|› d(|› d6|
› �d
|dt        |	«      dd7dddddddddddd|g}t        |d8«       t        j                  d9|	||«       |	S ):a
  
    Build the base MP4 from an image or video + audio. Returns duration (s).
    For image sources with `liveness` enabled, applies a Ken-Burns zoom plus a
    gentle sinusoidal pan ("head sway") so the avatar is not a frozen frame even
    without GPU models.
    ri   Ú:é   zscale=z*:force_original_aspect_ratio=decrease,pad=z):(ow-iw)/2:(oh-ih)/2:black,format=yuv420pr¯   z-stream_loopz-1r°   rÂ   ú-vfú-c:vÚlibx264ú-presetÚfastú-crfÚ23ú-c:aÚaacr±   r²   ú	-shortestú	-movflagsú
+faststartzmin(1.0+0.0006*on,1.05)ziw/2-(iw/zoom/2)+sin(on/g       @z)*(iw*0.006)zih/2-(ih/zoom/2)+cos(on/gÍÌÌÌÌÌ@z)*(ih*0.005)z[0:v]scale=z+:force_original_aspect_ratio=increase,crop=z&,boxblur=26:3,setsar=1[bg];[0:v]scale=zU:force_original_aspect_ratio=decrease[fg];[bg][fg]overlay=(W-w)/2:(H-h)/2,zoompan=z='z':x='z':y='z':d=1:s=Úxz:fps=z,format=yuv420p[v]z-loopÚ1z-rz-filter_complexz-mapz[v]z1:aÚ20rÀ   rÁ   zcolor=c=black:s=z:r=zformat=yuv420pz
make-videoz8[pipeline] Base video created (%.1fs, liveness=%s) -> %s)ÚRES_MAPr!   Úsplitr*   rh   r   r   rÊ   rx   rP   ru   r`   r   r"   )Úsource_pathra   r€   rå   rä   Úvf_scaleÚwÚhr   rá   ÚfpsÚpadrI   Úzoomrõ   ÚyÚfcs                    r)   Ústage_make_videor  ý   sf  € ô �{‰{˜: {Ó3€HØ�>‰>˜#Ó�D€A€qÜ‹^€FÜ˜zÓ*€HØ
€Cà�H�:ð Ø��A�a�SÐAðC€Cñ ”r—w‘w—~‘~ kÔ2´yÀÔ7Mà�D˜.¨$°°kÀ4ÈØ”#�h“- ¨Ø�I˜y¨&°&¸$Ø�E˜6 6¨;¸À\ÐS[ð	
Šñ 
œŸ™Ÿ™¨Ô4¼À;Ô9OÙð
 -ˆDØ*¨3¨s©7¨)°<Ð@ˆAØ*¨3¨s©7¨)°<Ð@ˆAà˜a˜S  ! ð %Ø�s˜!˜A˜3ð Ø˜S  ! ð %à"˜V 5¨¨¨5°°°8¸A¸3¸aÀ¸sÀ%ÈÀuð M$ð	%ð ðØðØðØ%ðØ'*ðØ,0ðØ2=ðØ?CðØEOðàðä˜(“mðà%)ðä+.¨s«8ðð "ðð $&ðð (.ðð 05ðð 7=ðð ?Dðð ð	ð "ð	ð $-ð	ð /5ð	ð 7=ð	ð ?Cð	ð
 ðð
 ðð
  &ðð
 (.ðð
 0;ðð ðð *ðð ,4ð‰Cð ˜˜g s¨D°+¸tÀZØ”c˜(“m U¨CØ˜	 9¨f°f¸dØ˜˜v v¨{¸LÈ(ð	‰Cð �D˜$ ¨Ð1AÀ!ÀÀAÀaÀSÈÈCÈ5Ð/QØ�*˜d¤C¨£M°5Ð:JØ�I˜y¨&°&¸$Ø�E˜6 6¨;¸Àhð	
ˆô 	ˆˆlÔÜ‡H�HÐGØ�x ô+à€Or+   Ú	model_dirc                 ó˜   — |D ]E  }t         j                  j                  | |«      }t         j                  j                  |«      sŒC|c S  y r5   )r   r   r   r   )r  ÚnamesÚnr(   s       r)   Ú_entrypointr  F  s:   € ÛˆÜ�G‰G�L‰L˜ AÓ&ˆÜ�7‰7�>‰>˜!ÕØŠHð ð r+   Úsource_imageÚwork_dirc           
      ó`  — t         j                  }|r!t        j                  j	                  |«      r| syt        |g d¢«      }t        j                  j                  |dd«      }|rt        j                  j                  |«      st        j                  d«       yt        j                  j                  |d«      }	 t        t         j                  |d| d|d	|gd
|d¬«       t        j                  j                  |«      r|S dS # t        $ r }t        j                  d|«       Y d}~yd}~ww xY w)zÞ
    LivePortrait / SadTalker: animate a still portrait into a moving base clip.
    Requires a driving template video at <LIVEPORTRAIT_PATH>/assets/driving.mp4.
    Returns animated (silent) mp4 path or None to skip.
    N)úinference.pyzdemo.pyzrun.pyÚassetszdriving.mp4uL   [pipeline] LivePortrait present but no entrypoint/driving asset â€” skippingzanimated.mp4z-sz-dr®   Úliveportraité  ©rK   rL   u4   [pipeline] LivePortrait failed (%s) â€” falling back)r   ÚLIVEPORTRAIT_PATHr   r   Úisdirr  r   r   r   r"   r`   ÚMODELS_PYTHONrf   rÇ   )r	  r
  Úmdirr~   ÚdrivingÚoutrÖ   s          r)   Úrun_liveportraitr  N  sì   € ô × Ñ €DÙ”R—W‘W—]‘] 4Ô(©\ØÜ˜ÒDÓE€FÜ�g‰g�l‰l˜4 ¨=Ó9€GÙœŸ™Ÿ™¨Ô0Ü�‰Ð_Ô`ØÜ
�'‰'�,‰,�x Ó
0€CðÜŒc×Ñ ¨¨|¸TÀ7Ø�CðØ(¨d¸Dõ	Bä—g‘g—n‘n SÔ)ˆsÐ3¨tÐ3øÜò Ü�‰ÐJÈAÔNÜûðús   Â<AD ÄD Ä	D-ÄD(Ä(D-r  c                 óŒ  ‡— ddl }t        j                  j                  | d«      }	 t        j                  j	                  |«      ret        |d¬«      j                  «       }|j                  dd|«      }||k7  r2t        |dd¬«      j                  |«       t        j                  d	«       |j                  d«      }ddddddœŠt        j                  | «      D ]­  \  }}}	d|v rŒ|	D ]�  }
|
j                  d«      sŒt        j                  j                  ||
«      }	 t        |d¬«      j                  «       }|j                  ˆfd„|«      }||k7  r3t        |dd¬«      j                  |«       t        j                  d|«       ŒŸ Œ¯ y# t        $ r!}t        j                  d
|«       Y d}~�Œd}~ww xY w# t        $ r Y ŒÛw xY w)ug  
    Make the (2019-era) Wav2Lip source run on modern librosa / numpy WITHOUT any
    manual edits. Idempotent: safe to run before every invocation.

      â€¢ librosa.filters.mel(sr, n_fft, ...)  -> keyword args  (librosa >= 0.10)
      â€¢ deprecated numpy aliases np.float/np.int/np.bool/np.object/np.complex
        -> python builtins (numpy >= 1.24)
    r   Nzaudio.pyrT   )rX   z=librosa\.filters\.mel\(\s*hp\.sample_rate\s*,\s*hp\.n_fft\s*,z6librosa.filters.mel(sr=hp.sample_rate, n_fft=hp.n_fft,rü   z<[pipeline] patched Wav2Lip audio.py mel() for modern librosaz([pipeline] could not patch audio.py (%s)z5\bnp\.(float|int|bool|object|complex)\b(?!\d|_|\s*\()rd   ÚintÚboolÚobjectÚcomplex)rd   r  r  r  r  z.gitz.pyc                 ó,   •— ‰| j                  d«         S )Nro   )Úgroup)ÚmÚrepls    €r)   Ú<lambda>z'_patch_wav2lip_source.<locals>.<lambda>�  s   ø€ ¨¨Q¯W©W°Q«ZÒ(8r+   z&[pipeline] patched numpy aliases in %s)Úrer   r   r   r   ÚopenÚreadÚsubÚwriter   r"   rf   rÇ   ÚcompileÚwalkr   )r  r"  Úaudio_pyÚsrcÚnewrÖ   ÚaliasÚrootÚ_dÚfilesÚfr(   Úsr  r   s                 @r)   Ú_patch_wav2lip_sourcer2  f  s�  ø€ ó ä�w‰w�|‰|˜D *Ó-€HðCÜ�7‰7�>‰>˜(Ô#Ü�x¨'Ô2×7Ñ7Ó9ˆCØ—&‘&ØPØHØóˆCð
 �cŠzÜ�X˜s¨WÔ5×;Ñ;¸CÔ@Ü—‘ÐWÔXð
 �J‰JÐOÓP€EØ U°FØ¨9ñ6€DäŸ7™7 4ž=‰ˆˆb�%Ø�T‰>ØÛˆAØ—:‘:˜eÔ$ØÜ—‘—‘˜T 1Ó%ˆAðÜ˜ WÔ-×2Ñ2Ó4�Ø—I‘IÓ8¸!Ó<�Ø˜’6Ü˜˜C¨'Ô2×8Ñ8¸Ô;Ü—H‘HÐEÀqÔIøñ ñ )øô ò CÜ�‰Ð>À×BÒBûðCûô( ò Ùðús+   §BF
 ÄA(F7Æ
	F4ÆF/Æ/F4Æ7	GÇGÚface_video_or_imagec                 ó¢  — t         j                  }|rt        j                  j	                  |«      syt        |ddg«      }t        t        j                  j                  |d«      ddg«      xs t        |ddg«      }|r|st        j                  d«       yt         j                  rt        |«       t        j                  j                  |d«      }	 t        t         j                  |d	|d
| d|d|ddddddddgd|d¬«       t        j                  j                  |«      r|S dS # t        $ r }t        j                  d|«       Y d}~yd}~ww xY w)zDWav2Lip: apply accurate lip-sync of `audio` onto `face` video/image.Nr  zwav2lip_inference.pyÚcheckpointszwav2lip_gan.pthzwav2lip.pthuI   [pipeline] Wav2Lip present but missing entrypoint/checkpoint â€” skippingzlipsync.mp4z--checkpoint_pathz--facez--audioz	--outfilez
--nosmoothz--resize_factorrö   z--padsÚ0Ú10Úwav2lipé  r  u/   [pipeline] Wav2Lip failed (%s) â€” falling back)r   ÚWAV2LIP_PATHr   r   r  r  r   r   r"   ÚWAV2LIP_AUTOPATCHr2  r`   r  r   rf   rÇ   )r3  ra   r
  r  r~   Úckptr  rÖ   s           r)   Úrun_wav2lipr=  •  s8  € ä×Ñ€DÙ”R—W‘W—]‘] 4Ô(ØÜ˜ Ð0FÐGÓH€FÜ”r—w‘w—|‘| D¨-Ó8Ø)¨=Ð9ó;ò Aä�tÐ/°Ð?Ó@ð 	ñ ™Ü�‰Ð\Ô]ØÜ
×ÒÜ˜dÔ#Ü
�'‰'�,‰,�x Ó
/€Cð
ô 	Œc×Ñ Ð)<¸dØÐ+¨Y¸
Ø˜3 Ð.?ÀØ˜˜T 3¨ð-ð /8¸TÈ4õ	Qô —g‘g—n‘n SÔ)ˆsÐ3¨tÐ3øÜò Ü�‰ÐEÀqÔIÜûðús   ÃAD% Ä#D% Ä%	EÄ.E	Å	Ec           
      óê  — t         j                  }|rt        j                  j	                  |«      sy	 ddl}t        t        |dd«      xr |j                  j                  «       «      }|st        j                  d«       yt        |dg«      xs+ t        t        j                  j                  |d«      dg«      }|st        j                  d«       yt        j                  j                  |d	«      }	 t        t         j                   |d
| d|d|gd|d¬«       t        j                  j#                  |«      r|S t        j$                  |«      D ]c  \  }}	}
|
D ]X  }|j'                  «       j)                  d«      sŒ#d|j'                  «       v sŒ6t        j                  j                  ||«      c c S  Œe y# t        $ r d}Y �Œ[w xY w# t        $ r }t        j*                  d|«       Y d}~yd}~ww xY w)z×
    MuseTalk lip-sync (higher quality than Wav2Lip). Requires an NVIDIA CUDA GPU
    and the MuseTalk repo + weights at MUSETALK_PATH. Skips gracefully otherwise
    (e.g. on macOS, where CUDA is unavailable).
    Nr   ÚcudaFuF   [pipeline] MuseTalk present but no CUDA GPU â€” skipping (use Wav2Lip)r  Úscriptsu:   [pipeline] MuseTalk present but no entrypoint â€” skippingzmusetalk.mp4z--video_pathz--audio_pathz--result_dirÚmusetalkr9  r  rw   Úmuseu0   [pipeline] MuseTalk failed (%s) â€” falling back)r   ÚMUSETALK_PATHr   r   r  Útorchr  rÏ   r?  Úis_availablerf   r   r"   r  r   r`   r  r   r(  rs   r   rÇ   )r3  ra   r
  r  rD  Úhas_cudar~   r  Úrr.  r/  r0  rÖ   s                r)   Úrun_musetalkrH  ±  s¡  € ô ×Ñ€DÙ”R—W‘W—]‘] 4Ô(ØðÛÜœ  v¨tÓ4ÒR¸¿¹×9PÑ9PÓ9RÓSˆñ Ü�‰ÐYÔZØÜ˜ Ð/Ó0ò EÜ”B—G‘G—L‘L  yÓ1°NÐ3CÓDð áÜ�‰ÐMÔNØÜ
�'‰'�,‰,�x Ó
0€CðÜŒc×Ñ ¨Ð9LØ˜j¨.¸(ðDà˜T¨4õ	1ô �7‰7�>‰>˜#ÔØˆJÜŸG™G HÖ-‰LˆAˆr�5Û�Ø—7‘7“9×%Ñ% fÕ-°&¸A¿G¹G»IÒ2EÜŸ7™7Ÿ<™<¨¨1Ó-Ô-ñ ð .ð øô+ ò Ø‹ðûô, ò Ü�‰ÐFÈÔJÜûðúsC   ´6F7 Ã5AG	 Ä;A G	 Å<G	 Æ#G	 Æ3G	 Æ7GÇGÇ		G2ÇG-Ç-G2Úin_videoc                 óš  — t         j                  }|rt        j                  j	                  |«      syt        |ddg«      }|st        j                  d«       yt        j                  j                  |d«      }t        j                  |d¬«       	 t        t         j                  |d| d	|d
dddg
d|d¬«       t        j                  |«      D ]P  \  }}}|D ]E  }|j                  «       j                  d«      sŒ#t        j                  j                  ||«      c c S  ŒR y# t        $ r }	t        j                   d|	«       Y d}	~	yd}	~	ww xY w)z>CodeFormer / GFPGAN: per-frame face restoration & enhancement.Nzinference_codeformer.pyr  uA   [pipeline] CodeFormer present but missing entrypoint â€” skippingÚcf_outT©Úexist_okr°   r®   z--bg_upsamplerÚNonez-wz0.7Ú
codeformerr  r  rw   u2   [pipeline] CodeFormer failed (%s) â€” falling back)r   ÚCODEFORMER_PATHr   r   r  r  r   r"   r   Úmakedirsr`   r  r(  rs   r   rf   rÇ   )
rI  r
  r  r~   Úout_dirr-  r.  r/  r0  rÖ   s
             r)   Úrun_codeformerrS  Ù  s  € ä×Ñ€DÙ”R—W‘W—]‘] 4Ô(ØÜ˜Ð 9¸>ÐJÓK€FÙÜ�‰ÐTÔUØÜ�g‰g�l‰l˜8 XÓ.€GÜ‡K�K� $Õ'ðÜŒc×Ñ ¨¨x¸¸wØ ¨¨eð5Ø6BØ˜tõ	%ô  "Ÿw™w wÖ/‰OˆD�"�eÛ�Ø—7‘7“9×%Ñ% fÕ-ÜŸ7™7Ÿ<™<¨¨aÓ0Ô0ñ ð  0ð øÜò Ü�‰ÐHÈ!ÔLÜûðús%   ÂA'D! Ã9#D! ÄD! Ä!	E
Ä*EÅE
z20:20z	W-w-20:20z	20:H-h-20zW-w-20:H-h-20z(W-w)/2:(H-h)/2)ztop-leftz	top-rightzbottom-leftúbottom-rightÚcenterzx=m:y=mzx=w-tw-m:y=mzx=m:y=h-th-mzx=w-tw-m:y=h-th-mzx=(w-tw)/2:y=(h-th)/2gÍÌÌÌÌÌÜ?rT  g{®GázÄ?)ÚopacityÚpositionÚscalerW   Úin_pathrV  rW  rX  rW   c                ó  — t        «       }t        dt        dt        |«      «      «      }|xs t        j
                  xs dj                  «       }|j                  dd«      j                  dd«      j                  dd«      }	d}
d	}t        j                  |t        d
   «      j                  d|
«      }d|	› d|› d|› dt        d|dz   «      d›d|› �
}|dd| d|› d�dddddddddd |g}t        |d!«       t        j                  d"|	|||«       y#)$zè
    Burn a clean semi-transparent TEXT watermark (HeyGen-style), e.g. "GOLS",
    into every video. Font size scales with the video height; a soft shadow keeps
    it readable on any background. Re-encodes video, copies audio.
    gš™™™™™©?g      ð?ÚGOLSÚ\r   rç   Ú'zh*0.03zh*0.045rT  r  zdrawtext=text='z':fontsize=z:fontcolor=white@z:shadowcolor=black@g333333Ã?z.2fz:shadowx=2:shadowy=2:box=0:r¯   r°   ré   z,format=yuv420prð   Úcopyrê   rë   rì   rí   rî   r÷   ró   rô   zwatermark-textz:[pipeline] Text watermark '%s' applied (op=%.2f, %s) -> %sN)r*   rÒ   rÓ   rd   r   ÚWATERMARK_TEXTr   rU   Ú	_TEXT_POSr!   r`   r   r"   )rY  r€   rV  rW  rX  rW   r   ÚopÚwm_textÚsafeÚmarginÚfontsizeÚposÚdrawtextrI   s                  r)   Ústage_watermarkrh    s6  € ô ‹^€FÜ	ˆT”3�sœE '›NÓ+Ó	,€BØÒ3”s×)Ñ)Ò3¨V×:Ñ:Ó<€Gà�?‰?˜4 Ó$×,Ñ,¨S°"Ó5×=Ñ=¸cÀ2ÓF€Dà€FØ€HÜ
�-‰-˜¤)¨NÑ";Ó
<×
DÑ
DÀSÈ&Ó
Q€Cð ˜$˜ð  Ø�:Ð.¨r¨dð 3Ü   b¨4¡iÓ0°Ð5ð 6Ø�ð	ð ð �4˜˜w¨°(°¸?Ð/KØ�6˜6 9¨i¸ÀÈØ˜ hð0€Cô 	ˆÐÔÜ‡H�HÐIØ�2�x õ+r+   Ú
video_pathc                 óà   — t        «       }	 t        |dddd| dddddd	|gd
«       t        j                  j	                  |«      S # t
        $ r }t        j                  d|«       Y d }~yd }~ww xY w)Nr¯   z-ssrö   r°   z	-frames:vré   zscale=640:-2z-q:vÚ3Ú	thumbnailz+[pipeline] thumbnail generation failed (%s)F)r*   r`   r   r   r   rf   r   rÇ   )ri  r€   r   rÖ   s       r)   Ústage_thumbnailrm  +  so   € Ü‹^€FðÜˆf�d˜E 3¨¨j¸+ÀsØ�^ V¨S°(ð<Ø=Hô	Jä�w‰w�~‰~˜hÓ'Ð'øÜò Ü�‰ÐAÀ1ÔEÜûðús   Œ7A Á	A-ÁA(Á(A-c                 óx  — t        j                  d| «       d }	 t        «       }t        j                  d|«       t        j                  | «      }|sQt        j
                  d| «       	 |r7t        j                  j                  |«      r	 t        j                  |«       y y y t        j                  |j	                  dd«      «      xs i }|j	                  dd«      }|j	                  dd	«      }|j	                  d
d«      }|j	                  d«      xs |j	                  d«      xs d}|j	                  dd«      }	t        j                  d¬«      d   }
|
r|
d   ni }|j	                  dd«      }|j	                  dt        j                   «      }|j	                  dt        j"                  «      }t%        t'        j(                  «       «      d d }t        j                  j+                  t        j,                  d|› �«      }t        j.                  |d¬«       t        j                  j+                  |d«      }t        j                  j+                  |d«      }t        j                  j+                  |d«      }|j	                  d«      }d }|rƒt        j                  j+                  t        j0                  t        j                  j3                  |«      «      }t        j                  j                  |«      r|}nt        j4                  d |«       t7        | d!d"d#d$d ¬%«       t9        |||||	¬&«      }d }|d'k(  rd(}t7        | d)d*||¬+«       t7        | d,d-d.¬/«       t;        ||||t        j<                  ¬0«      }t7        | d1d2¬3«       |}|rzt?        |«      rot7        | d4d5d6¬/«       tA        ||«      }|rRt        j                  j+                  |d7«      }	 tC        |d8d9|d9|d:d;d<d=d>d?d@|gdA«       |}t        j                  dB«       |j	                  dC«      xs dDjE                  «       }||k7  r|n|xs |}t7        | dEdF|› dG�dH¬/«       d }|dIk(  r¡ddJl#m$} t        j                  j+                  |dK«      } |r^t?        |«      rS|jK                  ||| |||¬L«      \  }!}"|!r| }n~t        j4                  dM|"«       t7        | dN|"› �¬O«       tM        |||«      }nJt7        | dP¬O«       tM        |||«      }n/|dQk(  rtO        |||«      xs tM        |||«      }ntM        |||«      }|r|}t        j                  dR|«       nt        j                  dS«       |j	                  dTd«      rot7        | dTdUdV¬/«       tQ        ||«      }#|#rRt        j                  j+                  |dW«      }$	 tC        |d8d9|#d9|d:d;d<d=d>d?d@|$gdX«       |$}t        j                  dY«       t7        | ddZd[¬/«       |}%|ri	 tS        ||||¬\«       t        j                  jU                  |«      r%t        j                  jW                  |«      d]kD  r|}%nt        j4                  d^«       d`|› da�}'t        j                  j+                  t        j,                  |'«      }(t        jX                  |%|(«       d`|› db�})t        j                  j+                  t        j,                  |)«      }*t[        |(|*«      }+t]        t        j                  jW                  |(«      dcz  dd«      },t        j                  de|(|,«       t_        j`                  |j	                  dfdg«      | |j	                  d«      |'|+r|)nd dht]        |d«      ||||||,|ddiœ«      }-t_        jb                  |-dj   dk|-dj   › dl�dk|-dj   › dm�|+r	dk|-dj   › dn�nd doœ«       t7        | dhdpdqdrdk|-dj   › dl�dk|-dj   › dm�|-dj   t]        |d«      te        «       ¬s«
       t        j                  dt| |-dj   «       |r7t        j                  j                  |«      r	 t        j                  |«       y y y # t        $ r Y y w xY w# t        $ r |}Y �ŒZw xY w# t        $ r |#}Y �Œ¡w xY w# t        $ r!}&t        j4                  d_|&«       Y d }&~&�Œ9d }&~&ww xY w# t        $ rJ}.t        j
                  dutg        jh                  «       «       tk        | tm        |.dvdw«      |.«       Y d }.~.Œèd }.~.ww xY w# t        $ r Y y w xY w# |rFt        j                  j                  |«      r&	 t        j                  |«       w # t        $ r Y w w xY ww w xY w)xNz[pipeline] START %sz[pipeline] Using ffmpeg: %sz[pipeline] Project %s not foundÚ	avatar_idr   r~   zHello, this is your AI avatar.r‚   r…   rå   rl   Úvoice_genderry   r}   rz   ro   )Úper_pageÚitemsr   Ú	watermarkFÚwatermark_opacityÚwatermark_positioné   Ú_job_TrL  z	voice.mp3zbase.mp4zwatermarked.mp4Ú
source_urlz$[pipeline] Source file not found: %sÚ
processingrØ   zGenerating voice...é
   )rD   r@   Ústage_labelÚprogressrE   r{   rÃ   zžNo voice was generated (silent audio). Install OpenAI (pip install openai httpx) with OPENAI_API_KEY set, or ensure internet access for gTTS, then regenerate.Útts_doneé   )r@   r|  Úvoice_engine_usedÚvoice_warningÚvideozCreating base video...é(   )r@   r{  r|  rã   Ú
video_doneé:   )r@   r|  Ú	animationz Face animation (LivePortrait)...é@   zanimated_av.mp4r¯   r°   rê   r^  rð   rñ   rò   ró   rô   zmux-animatedz)[pipeline] LivePortrait animation appliedÚ
lip_enginer8  Úlipsyncz
Lip sync (z)...éJ   Údid)Údid_servicezdid.mp4)Úscript_textr|   r‚   z[pipeline] D-ID failed: %szD-ID: )Ú	did_errorz)D-ID needs an image source (not a video).rA  z"[pipeline] Lip-sync applied via %suG   [pipeline] No lip-sync engine produced output â€” using living portraitÚenhancez Face enhancement (CodeFormer)...éT   zenhanced_av.mp4zmux-enhancedz)[pipeline] CodeFormer enhancement appliedzFinalising video...é\   )rV  rW  iè  u>   [pipeline] watermark produced no file â€” using un-watermarkedu?   [pipeline] watermark failed (%s) â€” using un-watermarked videoÚavatar_rw   rp   i   é   z,[pipeline] Final video saved -> %s (%.2f MB)ÚtitlezAvatar VideoÚ	completed)r“  r;   ro  Úfilenamerl  rD   Úduration_secrå   r‚   rp  r  r€  Úfile_size_mbrs  Údownload_urlr¸   z/api/videos/z	/downloadz/streamz
/thumbnail)r˜  Ú
stream_urlÚthumbnail_urlÚdoneÚCompleteéd   )	rD   r@   r{  r|  Ú
output_urlr™  Úvideo_idr–  Úcompleted_atz[pipeline] DONE %s -> video %sz[pipeline] EXCEPTION:
%sr@   Úpipeline)7r   r"   r*   r   r!   rE   r   r   rÊ   r   Úrmtreerf   r   r
   Úlistr   ÚWATERMARK_OPACITYÚWATERMARK_POSITIONrP   ÚuuidÚuuid4r   Ú
OUTPUT_DIRrQ  Ú
UPLOAD_DIRÚbasenamerÇ   r?   râ   r  ÚENABLE_LIVENESSru   r  r`   rs   Úapp.servicesr‹  Úgenerate_talkr=  rH  rS  rh  r   ÚgetsizeÚcopy2rm  Úroundr	   Úcreater=   r:   Ú	tracebackÚ
format_excrH   rÏ   )/r;   r
  Ú
ffmpeg_exeÚprojectÚavatarr~   r   Úresr|   r}   ÚslistÚsettingsÚuse_wmÚ
wm_opacityÚwm_positionÚjob_idra   Úbase_mp4Úwm_mp4rx  rú   Ú	candidateÚ
tts_enginer€  rá   ÚcurrentÚanimatedÚmuxedr‡  Úlip_facerˆ  r‹  Údid_outÚokÚdetailÚenhancedÚcf_avÚfinal_sourcerÖ   r•  Ú	final_outÚ
thumb_nameÚ
thumb_pathÚ	has_thumbr—  r�  rA   s/                                                  r)   Úrun_pipelinerÐ  9  s†  € Ü‡H�HÐ" JÔ/Ø€HðAÜ!“^ˆ
Ü�‰Ð.°
Ô;ä ×$Ñ$ ZÓ0ˆÙÜ�I‰IÐ7¸ÔDØñl œŸ™Ÿ™ xÔ0ðÜ—‘˜hÕ'ð 1ˆ8ôi ×"Ñ" 7§;¡;¨{¸BÓ#?Ó@ÒFÀBˆØ—‘˜XÐ'GÓHˆØ�{‰{˜: tÓ,ˆØ�k‰k˜,¨Ó0ˆØ—‘˜^Ó,ÒV°·
±
¸>Ó0JÒVÈhˆØ—+‘+˜i¨Ó3ˆä×#Ñ#¨QÔ/°Ñ8ˆÙ$�5˜’8¨"ˆØ—‘˜k¨5Ó1ˆØ—\‘\Ð"5´s×7LÑ7LÓMˆ
Ø—l‘lÐ#7¼×9OÑ9OÓPˆä”T—Z‘Z“\Ó" 2 AÐ&ˆÜ—7‘7—<‘<¤§¡°%¸°xÐ0@ÓAˆÜ
�‰�H tÕ,ä—W‘W—\‘\ (¨KÓ8ˆ
Ü—7‘7—<‘< ¨*Ó5ˆÜ—‘—‘˜hÐ(9Ó:ˆà—Z‘Z Ó-ˆ
ØˆÙÜŸ™Ÿ™¤S§^¡^´R·W±W×5EÑ5EÀjÓ5QÓRˆIÜ�w‰w�~‰~˜iÔ(Ø'‘ä—‘ÐBÀIÔNô 	ˆZ °EØ.¸À4õ	Iä˜v t¨ZÀÐPWÔXˆ
ØˆØ˜Ò"ðQˆMô 	ˆZ˜z°BÈ*Ø(õ	*ô 	ˆZ˜wÐ4LÐWYÕZÜ# K°¸XÀsÜ-0×-@Ñ-@ôBˆäˆZ˜|°bÕ9Øˆñ œ9 [Ô1Ü� ;Ø?È"õNä'¨°XÓ>ˆHÙÜŸ™Ÿ™ XÐ/@ÓA�ð'Ü˜* d¨D°(¸DÀ*Ø  &¨&°%¸Ø% |°Uð<à=KôMð $�Gô —‘ÐDÔEð —j‘j Ó.Ò;°)×BÑBÓDˆ
Ø%¨Ò1‘7¸Ò8OÀxˆÜˆZ˜yØ% j \°Ð6Àõ	Eàˆà˜ÒÝ0Ü—g‘g—l‘l 8¨YÓ7ˆGÙœy¨Ô5Ø(×6Ñ6Ø ¨WØ &¨vÀð 7ó F‘
��Fñ Ø%‘Gô —K‘KÐ <¸fÔEÜ˜°¸°xÐ/@ÕAÜ)¨(°JÀÓI‘Gä�ZÐ+VÕWÜ% h°
¸HÓE‘Ø˜:Ò%Ü" 8¨Z¸ÓBò BÜ! (¨J¸ÓAñ ô " (¨J¸ÓAˆGáØˆGÜ�H‰HÐ9¸:ÕFä�H‰HÐ^Ô_ð �:‰:�i Ô&Ü� 9Ø?È"õNä% g¨xÓ8ˆHÙÜŸ™Ÿ™ XÐ/@ÓA�ð'Ü˜* d¨D°(¸DÀ*Ø  &¨&°%¸Ø% |°Uð<à=KôMð $�Gô —‘ÐDÔEô 	ˆZ˜{Ð8MÐXZÕ[ØˆÙðbÜ ¨¸Ø)4õ6ä—7‘7—>‘> &Ô)¬b¯g©g¯o©o¸fÓ.EÈÒ.LØ#)‘Lä—K‘KÐ `Ôað
 ˜V˜H DÐ)ˆÜ—G‘G—L‘L¤§¡°Ó:ˆ	Ü�‰�\ 9Ô-à˜v˜h dÐ+ˆ
Ü—W‘W—\‘\¤#§.¡.°*Ó=ˆ
Ü# I¨zÓ:ˆ	äœRŸW™WŸ_™_¨YÓ7¸)ÑCÀQÓGˆÜ�‰Ð?ÀÈLÔYä×#Ñ#Ø—[‘[ ¨.Ó9Ø$Ø Ÿ™ [Ó1Ø Ù'0™°dØ!Ü! (¨AÓ.ØØØ"Ø!+Ø*Ø(ØØñ%
ó ˆô" 	×Ñ˜E $™KØ*¨5°©;¨-°yÐAØ(¨¨t©¨°WÐ=ÙGP˜|¨E°$©K¨=¸
ÑCÐVZñ*
ô 	ô 	ˆZ °6ÀzØ¨°U¸4±[°MÀÐ&KØ& u¨T¡{ m°7Ð;Ø˜D‘k´°hÀÓ0BÜ›&õ		"ô
 	�‰Ð1°:¸uÀT¹{ÔKñ œŸ™Ÿ™ xÔ0ðÜ—‘˜hÕ'ð 1ˆ8øô ò Ùðûôu !ò 'Ø&“Gð'ûôn !ò 'Ø&“Gð'ûô ò bÜ—‘Ð]Ð_`×aÒaûðbûôZ ò AÜ�	‰	Ð-¬y×/CÑ/CÓ/EÔFÜˆZœ  g¨zÓ:¸C×@Ñ@ûðAûô ò Ùðûñ œŸ™Ÿ™ xÔ0ðÜ—‘˜hÕ'øÜò Ùðúð 1ˆ8úsï   šAb
 Â
`* Â"L.b
 Ï`9 Ï-F.b
 Öa Ö8(b
 ×!A(a Ù	F'b
 àc  à*	`6à5`6à9aáb
 áaáb
 áaáb
 áaáb
 á	bá&bá<b
 âbâb
 â
	câA cãc/ ãcãc/ ã 	c,ã+c,ã/"d9äd(ä'd9ä(	d4ä1d9ä3d4ä4d9)NN)8Ú__doc__r   r   r[   r0   r²  r¦  r   r   Útypingr   Ú
app.configr   Úapp.repository.storer   r   r	   r
   Úapp.utils.loggerr   r¬  r   rÄ   r   rP   Ú__annotations__r   r*   r3   r:   r?   rf   rH   r£  r  ÚCompletedProcessr`   rd   rh   rø   r  ru   rx   râ   r  r  r  r2  r=  rH  rS  Ú
_POSITIONSr`  rh  rm  rÐ  r9   r+   r)   Ú<module>rÙ     s  ðòó0 
Û Û Û 
Û Û ß 'Ý å ß \Ó \Ý  Ý -ð €ˆ�#‰Ó Ø€ˆ(�3‰-Ó ð'�có 'ðT�só ð 2ˆcó 2ð.�Só .ðQ�Sð Q ð Q¨9ó Qð 6:Ø"&ñ
ˆdð 
˜3ð 
 X¨c¡]ð 
Ø˜3‘-ð
Ø+5×+FÑ+Fó
ð
 ð 
¨ó 
ð  j¸;ÈkÑ
Z€ð[�Cð [˜Dó [ðZ�Cð Z˜Dó Zð %°YòZ�cð Z ð Z°ð ZØðZØ/2ðZØCFóZðB ;?òC¨cð C¸Sð CØ!$ðCØ37ðCØCHóCðR˜3ð ¨(°3©-ó ð 3ð °#ð ¸(À3¹-ó ð0, ð ,¨ó ,ð^ Sð °cð ÀSð ÈXÐVYÉ]ó ð8% cð %°sð %Àcð %ÈhÐWZÉmó %ðP˜Sð ¨Cð °H¸S±Mó ð: ØØØ#Ø%ñ€
ð Ø"Ø"Ø'Ø+ñ€	ð &*¸>Ø#'°Tò+˜Sð +¨Cð +Ø"ð+Ø58ð+à ð+à/2ð+à>Bó+ðF ð ¨sð °tó ðD˜Sð D Tô Dr+   