
    @i'                     ~    S SK r S SKrS SKrS SKrS SKrS SKrS SKrS SKJrJ	r	J
r
  S SKJr  \" 5          " S S5      rg)    N)OptionalListTuple)load_dotenvc                       \ rS rSrS rS\S\4S jrS\\   4S jrS\S\\   4S jr	S	\S\
4S
 jrSS\S	\\   S\\   4S jjrSrg)
TTSService   c                    [         R                  R                  [         R                  R                  [         R                  R                  [        5      5      5      U l        U R                  5       U l        [         R                  " SS5      n[         R                  " SS5      nU R                  U5      U l
        U R                  U5      U l        SU l        [        S5        U R                  (       d  [        S5        O[        SU R                   35        U R                  (       a.  [         R                  R                  U R                  5      (       d  [        S	U R                   S
35        O2[        SU R                   35        U R                  (       a  SOSU l        U R                  (       a  [        S5        g[        S5        g)z[
Initializes the Piper TTS service with automatic path correction and absolute resolution.
PIPER_MODEL_PATHz&assets/models/en_US-lessac-medium.onnxPIPER_CONFIG_PATHz+assets/models/en_US-lessac-medium.onnx.jsonFu!   
🔍 Piper TTS Diagnostic Check:u8      - Binary: ❌ NOT FOUND (Check PIPER_EXECUTABLE_PATH)u      - Binary: ✅ FOUND at u%      - Model:  ❌ NOT FOUND (Checked: )u      - Model:  ✅ FOUND at Tu$   🚀 Piper TTS Service Fully Active
u9   ⚠️ Piper TTS Service Disabled (Missing requirements)
N)ospathdirnameabspath__file__base_dir_resolve_piper_executable
piper_pathgetenv_make_absolute
model_pathconfig_path	availableprintexists)self	model_env
config_envs      F/var/www/eduai.edurigo.com/roleplay/production/services/tts_service.py__init__TTSService.__init__   s5   
 8Q(RS 88: II02Z[	YY24ab
--i8..z:23LM.t.?@AbggnnT__&E&E9$//9J!LM.t.?@A%)__T%DN>>9:NO    r   returnc                     U(       d  g[         R                  R                  U5      (       a  U$ [         R                  R                  U R                  U5      $ )z@Converts relative paths to absolute paths based on project root. )r   r   isabsjoinr   )r   r   s     r    r   TTSService._make_absolute2   s7    B77==tww||DMM400r#   c                   ^^ SS/n[         R                  " S5      nU(       a  [         R                  R                  U5      (       aV  X!;  aP  [         R                  R	                  U5      (       a,  [         R
                  " U[         R                  5      (       a  U$ O9[        R                  " U5      mT(       a  [        U4S jU 5       5      (       d  T$ S H@  n[        R                  " U5      mT(       d  M"  [        U4S jU 5       5      (       a  M>  Ts  $    S H_  m[         R                  R	                  T5      (       d  M)  [         R
                  " T[         R                  5      (       d  MU  TU;  d  M]  Ts  $    g)	z
Strategically searches for the piper binary in common production paths.
STRICTLY blocks /usr/bin/piper to avoid the Ubuntu GTK conflict.
z/usr/bin/piperz
/bin/piperPIPER_EXECUTABLE_PATHc              3   ,   >#    U  H	  oT;   v   M     g 7fN ).0bresolveds     r    	<genexpr>7TTSService._resolve_piper_executable.<locals>.<genexpr>I   s     'Iy!Xy   )z	piper-ttspiperc              3   ,   >#    U  H	  oT;   v   M     g 7fr-   r.   )r/   r0   r   s     r    r2   r3   O   s     =9aT	9r4   )z/usr/local/bin/piper-ttsz/usr/local/bin/piperz/opt/piper/piperz/opt/piper/piper/piperN)
r   r   r   r'   r   accessX_OKshutilwhichany)r   	BLACKLISTenv_pathnamer   r1   s       @@r    r   $TTSService._resolve_piper_executable8   s   
 &|4	 9945ww}}X&&,1I1IbiiX`bdbibiNjNj#O "<<1C'Iy'I$I$I#O +D<<%DtC=9=== + wDww~~d##		$(@(@TQZEZ w r#   r   c                 \    US-   n[         R                  R                  U5      (       a  U$ S$ )z7Returns the .json config path for a model if it exists.z.jsonN)r   r   r   )r   r   r   s      r    _get_config_pathTTSService._get_config_pathZ   s)     7* ggnn[99{CtCr#   voicec           
         [         R                  R                  U R                  SS5      n[         R                  R	                  U5      (       d  gUUR                  SS5      UR                  SS5      /n[        R                  " SU5      n[        U5      S:  aF  UR                  SR                  USS	 5      5        UR                  SR                  USS	 5      5        [        [        R                  U5      5      nU H]  n[         R                  R                  X% S
35      n[         R                  R	                  U5      (       d  MK  X`R                  U5      4s  $    U/U-   n1 SknU V	s/ s H+  oR                  5       U;  d  M  [        U	5      S:  d  M)  U	PM-     nn	U H  n
[         R                  R                  USU
 S35      n[        R                  " U5      nU(       d  MF  US   n[!        SU S[         R                  R#                  U5       35        XR                  U5      4s  $    U R$                  (       a  [         R                  R	                  U R$                  5      (       a\  [!        SU S[        U5       S[         R                  R#                  U R$                  5       35        U R$                  U R&                  4$ [        R                  " [         R                  R                  US5      5      nU(       aB  US   n[!        S[         R                  R#                  U5       35        XR                  U5      4$ gs  sn	f )z
Ultra-robust resolution for Piper voice models.
Tries exact match, naming variants, and globbing to find the best possible file.
assetsmodels)NN_-z[-_]   Nz.onnx>	   engbinuslowhighrC   mediumlow-poly   *z*.onnxr   u   🎙️ Fuzzy match found for 'z': u   ⚠️ Piper voice 'z' not found (tried z, variants + glob). Falling back to default: u!   ⚠️ Using emergency fallback: )r   r   r(   r   r   replaceresplitlenappendlistdictfromkeysrA   lowerglobr   basenamer   r   )r   rC   
models_dirvariantspartsvr   search_terms	stopwordsttermpatternmatchesmatchavailable_modelsfallbacks                   r    _resolve_voice_modelTTSService._resolve_voice_model_   s   
 WW\\$--8D
ww~~j)) MM#s#MM#s#
 %(u:>OOCHHU23Z01OOCHHU23Z01 h/0A77<<
cK8Dww~~d##224888  wZ	#/]<a779I3MRUVWRX[\R\<] Dggll:4&/?@Gii(Gw
7wc"''BRBRSXBYAZ[\33E::: ! ??rww~~doo>>(/B3x=/Q}  A  F  F  O  O  PT  P_  P_  `  ~a  b  c??D$4$444  99RWW\\*h%GH'*H5bgg6F6Fx6P5QRS228<<</ ^s   1MMMNtextc           	      
   U R                   (       d  [        S5        gU(       a  UR                  5       (       d  [        S5        gU(       a+  U R                  U5      u  p4U(       d  [        SU S35        gOU R                  nU R
                  nUR                  SS5      R                  SS5      R                  5       nSn [        R                  " S	S
S9 nUR                  nSSS5        U R                  SUSU/nU(       a7  [        R                  R                  U5      (       a  UR                  SU/5        [        SU=(       d    S SUSS  S35        [        R                   " U[        R"                  [        R"                  [        R"                  SSS9n	U	R%                  USS9u  pU	R&                  S:w  aa  [        SU	R&                   SU 35         U(       a=  [        R                  R                  U5      (       a   [        R(                  " U5        ggg[        R                  R                  U5      (       a  [        R                  R-                  U5      S:  a  [/        US5       n[0        R2                  " UR5                  5       5      R7                  S5      n[        S[9        U5       S35        UsSSS5        U(       a=  [        R                  R                  U5      (       a   [        R(                  " U5        $ $ $ [        S5         U(       a=  [        R                  R                  U5      (       a   [        R(                  " U5        ggg! , (       d  f       GN= f! [*         a     gf = f! [*         a     $ f = f! , (       d  f       N= f! [*         a     gf = f! [        R:                   ab    [        S 5         U(       aM  [        R                  R                  U5      (       a(   [        R(                  " U5        g! [*         a     gf = fgg[*         au  n[        S![=        U5       35         SnAU(       aM  [        R                  R                  U5      (       a(   [        R(                  " U5        g! [*         a     gf = fggSnAff = f! U(       aM  [        R                  R                  U5      (       a(   [        R(                  " U5        f ! [*         a     f f = ff f = f)"aN  
Generates high-quality audio base64 string using the specified Piper voice model.
Thread-safe and optimized using temporary file isolation.

Args:
    text: The text to synthesize.
    voice: Optional Piper voice model name (e.g. "en_US-hfc_female-medium").
           If provided, uses that model; otherwise uses the default model.
uE   ⚠️ TTS skipped: Service not available (Check binary/model paths).Nu(   ⚠️ TTS skipped: Empty text provided.u!   ⚠️ TTS skipped: Voice model 'z' not found in assets/models/."r&   'z.wavF)suffixdeletez--modelz--output_filez--configu   🎙️ Generating voice (defaultz) for text: 2   z...Tzutf-8)stdinstdoutstderrro   encoding   )inputtimeoutr   u    ❌ Piper Execution Error (Code z): rbu"   ✅ Voice generated successfully (z chars)u"   ❌ Piper generated an empty file.u(   ❌ Piper process timed out (30s limit).u'   ❌ Exception in Piper TTS processing: )r   r   striprm   r   r   rU   tempfileNamedTemporaryFiler>   r   r   r   r   extend
subprocessPopenPIPEcommunicate
returncoderemove	Exceptiongetsizeopenbase64	b64encodereaddecoderX   TimeoutExpiredstr)r   ro   rC   active_modelactive_config
clean_texttemp_wav_pathtemp_wavcommandprocessrx   ry   
audio_fileb64es                  r    generate_voice_base64 TTSService.generate_voice_base64   s    ~~YZ4::<<<= *.*C*CE*J'L9%@^_`    ??L ,,M \\#r*223;AAC
5	,,F5IX ( J <G !>!>
M:;.u/A	.B,zZ][]N__bcd !&& oo!! G %00z20NNF!!Q&89K9K8LCPVxXY& !>!>IIm, "?}! ww~~m,,1ORS1S-.* **:??+<=DDWMC>s3xjPQ /. !>!>IIm, "?} 67 !>!>IIm, "?}_ JId ! y % /.$ !  (( 	<=
 !>!>IIm,   "?}	  	;CF8DE!>!>IIm,   "?}		 !>!>IIm,   "?}s   N2 M%C5N2 M1  AN2 3AN 	N2 5NN2 N" 
M.)N2 1
M>=M>
NN
NN2 "
N/.N/2R%R( >P 
P"!P"'	R%0R R( 7R 
RR R%%R( (,S>S,+S>,
S96S>8S99S>)r   r   r   r   r   r-   )__name__
__module____qualname____firstlineno__r!   r   r   r   r   rA   tuplerm   r   __static_attributes__r.   r#   r    r   r      s    "PH13 13 1 8C=  DD3 D8C= D
:# :% :xU# Uhsm UxX[} U Ur#   r   )r   r   r   r   r9   rV   r^   typingr   r   r   dotenvr   r   r.   r#   r    <module>r      s4    	     	  ( (  c cr#   