
    ^j 3                         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	m
Z
 d dlmZ d dlZ ee                                          j        d         Zedz  dz  Zedz  dz  Zed	z  d
z  Zed	z  dz  Zedz  dz  Zedz  dz  Zedz  dz  Zedz  dz  ZdZ ej        dej                  ZdZd Zd Z d Z!d Z"d'dZ#d Z$d Z%d Z&d Z'd(d"Z(d# Z)d$ Z*d% Z+e,d&k    r ej-         e+                       dS dS ))    N)ThreadPoolExecutoras_completed)datetimetimezone)Path   storyzspoken-narration.txtzpromotion-report.jsonscriptzproduction-plan.jsonztts-manifest.jsonaudiosegmentszstory-full.wavzstory-full.mp3logztts-verification.jsonz0http://192.168.40.32:7861/voice/ngoc-huyen-cloneu   \b[\wÀ-ỹĐđ]+\b   c                 N    t          j        |                                           S N)hashlibsha256	hexdigest)datas    script/render-tts.pysha256_bytesr      s    >$))+++    c                    t          j                    }|                     d          5 t          fdd          D ]}|                    |           	 d d d            n# 1 swxY w Y   |                                S )Nrbc                  .                          d          S )Ni   )read)handles   r   <lambda>zsha256_file.<locals>.<lambda>#   s    &++o">"> r   r   )r   r   openiterupdater   )pathdigestblockr   s      @r   sha256_filer$       s    ^F	4 !F>>>>DD 	! 	!EMM%    	!! ! ! ! ! ! ! ! ! ! ! ! ! ! ! s   ,A##A'*A'c                     t          j        dddddddddt          |           g
d	d	d	
          }t          j        |j                  S )Nffprobez-verrorz-show_entrieszformat=duration,sizez,stream=index,codec_name,sample_rate,channelsz-ofjsonT)checkcapture_outputtext)
subprocessrunstrr(   loadsstdout)r!   results     r   prober2   (   sY    ^tWo"O:E63t99	

 	 	 	F :fm$$$r   c                    t          j        d|                                           }g }g }d}|D ].}|                                }|st          |          |rdndz   }|r5||z   |k    r,|                    d                    |                     g }d}t          |          |k    rt          j        d|          }|D ]}	|	                                }	|	st          |	          |rdndz   }|r5||z   |k    r,|                    d                    |                     g }d}|                    |	           ||z  }|                    |           ||z  }0|r(|                    d                    |                     |S )Nu   (?<=[.!?…])\s+r   r    z(?<=[,;:])\s+)resplitstriplenappendjoin)
	paragraph	max_chars	sentenceschunkscurrentcurrent_lensentenceextraclausesclauses
             r   split_long_paragraphrE   6   s   ,ioo.?.?@@IFGK ! !>>## 	Hg!415 	{U*Y66MM#((7++,,,GKx==9$$h/::G! 
% 
% FG':qq; ${U2Y>>MM#((7"3"3444 G"#Kv&&&u$
% NN8$$$5 KK )chhw''(((Mr     `	  c                    d t          j        d|           D             }g }|D ]N}t          |          k    r|                    |           +|                    t          |                     Og }g }d}|D ]}	t          |	          |rdndz   }
|r5||
z   k    r,|                    d                    |                     g }d}|                    |	           ||
z  }||k    r,|                    d                    |                     g }d}|rd                    |          }|rSt          |          dk     r@t          |d                   dz   t          |          z   k    r|dxx         d|z   z  cc<   n|                    |           t          fd|D                       rt          d	          |S )
Nc                 ^    g | ]*}|                                 |                                 +S  )r7   ).0items     r   
<listcomp>zchunk_text.<locals>.<listcomp>Z   s-    VVV4V$**,,VVVr   z\n\s*\nr      z

i  c              3   >   K   | ]}t          |          k    V  d S r   )r8   )rK   chunkr<   s     r   	<genexpr>zchunk_text.<locals>.<genexpr>w   s.      
6
6e3u::	!
6
6
6
6
6
6r   z/Chunker exceeded max_chars after tail balancing)	r5   r6   r8   r9   extendrE   r:   anyRuntimeError)r+   	min_charsr<   
paragraphsunitsr;   r>   r?   sizeunitrB   tails     `         r   
chunk_textr\   Y   s   VV28J+E+EVVVJE E E	y>>Y&&LL####LL-iCCDDDDFGD  D		'0QQq1 	te|i//MM&++g..///GDt9MM&++g..///GD  {{7## 	 c$ii#oo#fRj//A*=D		*IY*V*V2JJJ&4-'JJJJMM$

6
6
6
6v
6
6
666 NLMMMMr   c                     t           t          t          fD ](} |                                 st	          d|            )t          j        t                              d                    }|                    d          dus|                    d          dk    rt	          d          t           	                                }t          |          }|                    d	          |k    rt	          d
          t          |                    dd                    }d|cxk    rdk    sn t	          d          |t          z  }d|cxk    rdk    sn t	          d          t          j        t                              d                    }|                    d          dk    s|                    d          |k    rt	          d          |                    d          ||fS )NzRequired authority missing: utf-8encodingverifiedTstatuspassedz+Story is not promoted; TTS spend is blockedspoken_sha256z*Story hash differs from promoted authoritytotal_wordsr   i3  i5  z+Promoted word count is outside target range(   <   zCFixed 231 words/minute duration prediction is outside 40-60 minutesstory_promoted_ready_for_ttscanon_sha256z.Production plan is not unlocked for this canon)STORY	PROMOTIONPLANexistsrU   r(   r/   	read_textget
read_bytesr   intTTS_WORDS_PER_MINUTEdecode)r!   	promotionstory_bytes
canon_hashre   predicted_minutesplans          r   require_promoted_storyry   |   s   	4( F F{{}} 	FDdDDEEE	F
9...@@AAI}}Z  ,,	h0G0G80S0SHIII""$$Kk**J}}_%%33GHHHimmM15566KK((((5((((HIII#&::"((((b((((`aaa:dnngn6677Dxx;;;txx?W?W[e?e?eKLLLg&&	:==r   c                 ~   t          |           }|st          d          g }t          |d          D ]\  }}|                    ||t	          |                    d                    t          t                              |                    t          t          d|ddz                      t                              dd           ddt          t                              t                              ||d	         t          d
ddd|t          j        t"          j                                                  d	S )NzChunker produced no TTS workr   r^   zsegment-04dz.wavpending)indexr+   text_sha256wordsoutputrb   re   
doc_truyen1.0true)stylespeeddenoise)	versionrb   sourcesource_canon_sha256source_wordsendpointrequestr>   
created_at)r\   rU   	enumerater9   r   encoder8   WORD_REfindallr.   SEGMENTSrelative_toPROJECTrj   ENDPOINTr   nowr   utc	isoformat)r+   rt   rv   r>   rowsr}   rQ   s          r   build_manifestr      s:   F ;9:::D!&!,,  u'W(=(=>>//008&@&@&@&@&@@MMgVVWW
 
 	 	 	 	 e''0011)!-0)EfMMl8<00::<<
 
 
r   c                 p   t                                           rWt          j        t                               d                    }|                    d          |k    rt          d          |S t          | ||          }t                               t          j	        |dd          dz   d           |S )	Nr^   r_   r   z3Existing TTS manifest belongs to another canon hashFrN   ensure_asciiindent
)
MANIFESTrm   r(   r/   rn   ro   rU   r   
write_textdumps)r+   rt   rv   manifests       r   load_or_create_manifestr      s     :h00'0BBCC<<-..*<<TUUUdIz::H
8%JJJTQ\cdddOr   c                 8   t           | d         z  }|                                r|                                j        dk     rdS 	 t	          |          }|                    dg           }t          |d         d                   }t          |          dk    o$|d                             d	          d
k    o|dk    }|rJ|| d<   |                                j        | d<   t          |	                                          | d<   d| d<   |S # t          $ r Y dS w xY w)Nr   i   Fstreamsformatdurationr   r   
codec_name	pcm_s16leduration_secondsbytesfile_sha256	completedrb   )r   rm   statst_sizer2   ro   floatr8   r   rp   	Exception)rowr!   r   r   r   valids         r   verify_existing_segmentr      s$   S]"D;;== DIIKK/$66uT{{((9b))h
344LLA 
|,,;1 	
  	(&.C"#99;;.CL!-doo.?.?!@!@C'CM   uus   CD 
DD   Tc           	         t           | d         z  }|j                            dd           d }t          d|dz             D ](}	 t	          j        t          | d         dddd	d
          }|                                 |j        	                    d          st          d          |                    d          }|                    |j                   |                    |           t          |           st          d          || d<    d S # t          $ rK}	t!          |	          }||k     rdnd| d<   || d<   ||k     r|rt#          j        d|z             Y d }	~	"d }	~	ww xY wt          d| d          d|           )Nr   Tparentsexist_okr   r+   r   r   r   )r+   r   r   r   i  )r   timeouts   RIFFz#TTS response is not a RIFF/WAV filez	.wav.partz(Rendered WAV failed ffprobe verificationattemptsretryingfailedrb   r'   rN   zSegment r}   z	 failed: )r   parentmkdirrangerequestspostr   raise_for_statuscontent
startswithrU   with_suffixwrite_bytesreplacer   r   r.   timesleep)
r   r   max_attemptsretry_sleepr!   
last_errorattemptresponsetempexcs
             r   render_segmentr      s   S]"DKdT222JL1,-- ) )	)}K)"%	  	 	 	H %%'''#..w77 J"#HIII##K00DX-...LL*3// O"#MNNN%C
OFF 	) 	) 	)SJ*1L*@*@JJhCM%CL%%+%
1<(((	) E#g,EEEE
F
FFs   CD
E)A E$$E)c                    t           dz  dz  }g }| d         D ]`}t           |d         z                                  }|                    dt          |                              dd          z   dz              a|                    d                    |          dz   d	
           t          j        	                    dd           t          j        ddddddddddt          |          ddt          t                    gd           t          j        ddddddt          t                    ddddt          t                    gd           d S )Nr
   ztts-concat.txtr>   r   zfile ''z'\''r   r^   r_   Tr   ffmpegz-hide_bannerz	-loglevelr'   z-yz-fconcatz-safe0z-iz-ccopy)r)   z-c:a
libmp3lamez-b:a192k)r   resolver9   r.   r   r   r:   
OUTPUT_WAVr   r   r,   r-   
OUTPUT_MP3)r   concat_filelinesr   r!   s        r   concatenater      s   H$'77KE! G G#h-'0022XD		 1 1#w ? ??#EFFFF499U++d2WEEED4888N	>;tXwX[]acfgrcscsuy  |B  DG  HR  DS  DS  	T    N	>;tS__V\^jlrtz|  AK  }L  }L  	M     r   c           	      f   t          t                    }|                    dg           }t          |d         d                   }t	          d | d         D                       }t          d | d         D                       ovt          |          dk    oc|d                             d	          d
k    oD|d                             d          dk    o%t          ||z
            dk     od|cxk    odk    nc }i ddd|d|dt	          d | d         D                       dt          | d                   dt          dt          t	          d | d         D                       t          z  d          d|dt          |dz  d          d|dt          ||z
  d          d t          t                              t                              d!t          t                              t                              d"t          t                    d#|d$t          j        t"          j                                                  }t(          j                            d%d%&           t(                              t1          j        |d'd()          d*z   d+,           |st5          d-          |S ).Nr   r   r   c              3   @   K   | ]}t          |d                    V  dS )r   N)r   rK   r   s     r   rR   z!verify_outputs.<locals>.<genexpr>	  s0      XXc5%7!899XXXXXXr   r>   c              3   H   K   | ]}|                     d           dk    V  dS rb   r   Nro   r   s     r   rR   z!verify_outputs.<locals>.<genexpr>  s3      KKCGGH,KKKKKKr   r   r   r   r   sample_rate48000g?rG   i.  r   ra   r   segments_completedc              3   H   K   | ]}|                     d           dk    V  dS r   r   r   s     r   rR   z!verify_outputs.<locals>.<genexpr>  s3      !a!as#''("3"3{"B!a!a!a!a!a!ar   segments_totaltts_words_per_minutepredicted_duration_minutesc              3   &   K   | ]}|d          V  dS )r   NrJ   r   s     r   rR   z!verify_outputs.<locals>.<genexpr>  s&      /[/[G/[/[/[/[/[/[r   r   r   duration_minutesrg   segment_duration_sumduration_delta_seconds   
output_wav
output_mp3
wav_sha256r2   
checked_atTr   FrN   r   r   r^   r_   zFinal TTS verification failed)r2   r   ro   r   sumallr8   absrr   roundr.   r   r   r   r$   r   r   r   r   r   RECEIPTr   r   r   r(   r   rU   )r   rv   	wav_prober   r   segment_durationra   receipts           r   verify_outputsr     s   j!!ImmIr**GYx(455HXXXhEWXXXXXKK8JKKKKK 	0LLA	0AJNN<((K7	0 AJNN=))W4	0 ++,,s2		0
 x////<//// 1H 	z 	c!a!ahW_N`!a!a!aaa	
 	#hx011 	 4 	%eC/[/[QYHZ/[/[/[,[,[^r,rtu&v&v 	H 	E(R-33 	 0 	!%3C(CQ"G"G 	c*0099:: 	c*0099:: 	k*-- 	  	hl8<00::<<!G$ N555tz'aHHH4OZabbb <:;;;Nr   c                    	
 	 t                      \  } }}t                              dd           t          | ||          	d	d<   t                              t          j        	dd          dz   d	
           g }	d         D ]@}|                    d          dk    rt          |          r+|
                    |           At          d          5 
	
fd|D             }t          |          D ]}||         }|                                 t                              t          j        	dd          dz   d	
           t          t          j        |d         |d         |                    d          dd          d           	 d d d            n# 1 swxY w Y   t          	           t!          	|          }d	d<   t#          j        t&          j                                                  	d<   t-          t.                              t2                              	d<   t-          t4                              t2                              	d<   t                              t          j        	dd          dz   d	
           t          t          j        d|d         |d         dd                     dS # t6          $ r)}t          d| t8          j                   Y d }~dS d }~ww xY w)NTr   runningrb   FrN   r   r   r^   r_   r>   r   r   )max_workersc                 J    i | ]}                     t          |          | S rJ   )submitr   )rK   r   r   pools     r   
<dictcomp>zmain.<locals>.<dictcomp>8  s+    ZZZ3t{{>3AA3ZZZr   r}   r   )segmentrb   r   )r   )flushcompleted_atr   r   ra   )rb   ra   r   r   zTTS blocked: )filer   )ry   r   r   r   r   r   r(   r   ro   r   r9   r   r   r1   printr   r   r   r   r   r   r   r.   r   r   r   r   r   sysstderr)r+   rt   rv   r|   r   futuresfuturer   r   r   r  s            @@r   mainr  +  s   &<&>&>#itd333*4JGG&DJxeANNNQUU`ghhhH% 	  	 Cwwx  K//4KC4P4P/NN3A... 	_$ZZZZZRYZZZG&w// _ _fo##DJxeTU$V$V$VY]$]ho#pppdjS\S]`c`g`ghz`{`{!|!|  LQ  R  R  R  Z^  _  _  _  _  _	_	_ 	_ 	_ 	_ 	_ 	_ 	_ 	_ 	_ 	_ 	_ 	_ 	_ 	_ 	_ 	H :66(#+<#=#=#G#G#I#I !$Z%;%;G%D%D!E!E!$Z%;%;G%D%D!E!EDJxeANNNQUU`ghhhdjKWZ=Pfm  oA  gB  C  C  RW  X  X  X  	Y  	Y  	Yq   #c###*5555qqqqqs>   CK B:FK F""K %F"&DK 
K:K55K:__main__)rF   rG   )r   T).r   r(   r5   r,   r  r   concurrent.futuresr   r   r   r   pathlibr   r   __file__r   r   r   rj   rk   rl   r   r   r   r   r   r   compileUNICODEr   rr   r   r$   r2   rE   r\   ry   r   r   r   r   r   r   r  __name__exitrJ   r   r   <module>r     sR     				     



  ? ? ? ? ? ? ? ? ' ' ' ' ' ' ' '       
$x..
 
 
"
"
*1
-'22g 77	22X 33Wz)w!11
w!11

E/3
3=
"*+RZ
8
8 , , ,  % % %     F       F> > >.  6    . G  G  G  GF  $# # #L  B zCHTTVV r   