
    /j                    r   S SK Jr  S SKrS SKrS SKrS SKrS SKJrJr  S SK	J
r
Jr  S SKJr  S SKJr  S SKJrJrJrJrJr  S SKJr  S S	KJrJrJr  S S
KJr  S SKJr  SSK J!r!J"r"  SSK#J$r$  SSK%J&r&  SSK'J(r(J)r)J*r+  SSKJ,r,J-r-J.r.  SSK*J/r/J0r0J1r1J2r2J3r3  \(       a  SSK4J5r5  \6" \Rn                  " SS 5      5      r8\ " S S5      5       r9\ " S S5      5       r: " S S\5      r;\" S5      r< " S S\\Rz                  \S   \<-     \\<   5      r> " S S \5      r? " S! S"\?5      r@ " S# S$\5      rA " S% S&5      rBg)'    )annotationsN)ABCabstractmethod)AsyncIterableAsyncIterator)	dataclass)TracebackType)TYPE_CHECKINGClassVarGenericLiteralTypeVar)trace)	BaseModel
ConfigDictField)rtc)Metadata   )APIErrorAPIStatusErrorlogger)
TTSMetrics)trace_typestracerutils)DEFAULT_API_CONNECT_OPTIONSUSERDATA_TIMED_TRANSCRIPTAPIConnectOptions)aioaudiocodecslog_exceptions	shortuuidTimedStringLK_DUMP_TTSc                  \    \ rS rSr% S\S'    S\S'    SrS\S'    S	rS\S
'    S	rS\S'   Srg)SynthesizedAudio    rtc.AudioFrameframestr
request_idFboolis_final 
segment_id
delta_text N)	__name__
__module____qualname____firstlineno____annotations__r1   r3   r4   __static_attributes__r5       G/app/agent/.venv/lib/python3.13/site-packages/livekit/agents/tts/tts.pyr*   r*       s:    !OHHd5JKJCr<   r*   c                  0    \ rS rSr% S\S'    SrS\S'   Srg)TTSCapabilities.   r0   	streamingFaligned_transcriptr5   N)r6   r7   r8   r9   r:   rB   r;   r5   r<   r=   r?   r?   .   s    OJ$$Lr<   r?   c                  f    \ rS rSr% \" SS9rSrS\S'   S\S'   S	\S
'   \" SSS9r	S\S'   S\S'   Sr
g)TTSError6   T)arbitrary_types_allowed	tts_errorzLiteral['tts_error']typefloat	timestampr.   label.)exclude	Exceptionerrorr0   recoverabler5   N)r6   r7   r8   r9   r   model_configrH   r:   r   rN   r;   r5   r<   r=   rD   rD   6   s9    d;L!,D
,JS$/E9/r<   rD   TEventc                  F  ^  \ rS rSr        SU 4S jjr\SS j5       r\SS j5       r\SS j5       r\SS j5       r	\SS j5       r
\SS j5       r\\S	.     SS
 jj5       r\S	.   SS jjr\S	.     SS jjrSS jrSS jrSS jr        SS jrSrU =r$ )TTSB   c                  > [         TU ]  5         Xl        X l        X0l        [        U 5      R                   S[        U 5      R                   3U l        g )N.)	super__init___capabilities_sample_rate_num_channelsrH   r7   r6   _label)selfcapabilitiessample_ratenum_channels	__class__s       r=   rX   TTS.__init__G   sJ     	)')d../qd1D1D0EFr<   c                    U R                   $ N)r\   r]   s    r=   rK   	TTS.labelT   s    {{r<   c                    g)zGet the model name/identifier for this TTS instance.

Returns:
    The model name if available, "unknown" otherwise.

Note:
    Plugins should override this property to provide their model information.
unknownr5   re   s    r=   model	TTS.modelX        r<   c                    g)zGet the provider name/identifier for this TTS instance.

Returns:
    The provider name if available, "unknown" otherwise.

Note:
    Plugins should override this property to provide their provider information.
rh   r5   re   s    r=   providerTTS.providerd   rk   r<   c                    U R                   $ rd   )rY   re   s    r=   r^   TTS.capabilitiesp       !!!r<   c                    U R                   $ rd   )rZ   re   s    r=   r_   TTS.sample_ratet   s       r<   c                    U R                   $ rd   )r[   re   s    r=   r`   TTS.num_channelsx   rq   r<   conn_optionsc                   g rd   r5   r]   textrw   s      r=   
synthesizeTTS.synthesize|   s     r<   c                   [        S5      e)NzYstreaming is not supported by this TTS, please use a different TTS or use a StreamAdapter)NotImplementedError)r]   rw   s     r=   stream
TTS.stream   s     "g
 	
r<   c                   [        U UUS9$ )zHelper method to implement synthesize() using stream() for TTS providers
that only support streaming inference.

This creates a stream, pushes the text as a single chunk, ends the input,
and returns a ChunkedStream wrapper around it.
tts
input_textrw   )_ChunkedStreamFromStreamry   s      r=   _synthesize_with_streamTTS._synthesize_with_stream   s     (%
 	
r<   c                    g)z&Pre-warm connection to the TTS serviceNr5   re   s    r=   prewarmTTS.prewarm   s    r<   c                   #    g 7frd   r5   re   s    r=   aclose
TTS.aclose   s     C   c                   #    U $ 7frd   r5   re   s    r=   
__aenter__TTS.__aenter__   
        c                @   #    U R                  5       I S h  vN   g  N7frd   r   r]   exc_typeexcexc_tbs       r=   	__aexit__TTS.__aexit__         kkm   )rY   r\   r[   rZ   )r^   r?   r_   intr`   r   returnNoner   r.   )r   r?   r   r   )rz   r.   rw   r    r   ChunkedStream)rw   r    r   SynthesizeStreamr   r   )r   rS   r   ztype[BaseException] | Noner   BaseException | Noner   zTracebackType | Noner   r   )r6   r7   r8   r9   rX   propertyrK   ri   rm   r^   r_   r`   r   r   r{   r   r   r   r   r   r   r;   __classcell__ra   s   @r=   rS   rS   B   sY   
G &G 	G
 G 
G   	 	 	 	 " " ! ! " " >Y*;	 
 4O
0
	
 ?Z

*;
	
 (, " %	
 
 r<   rS   )metrics_collectedrN   c                     \ rS rSr% SrSrS\S'           SS jr\SS j5       r	\SS j5       r
\SS	 j5       rS
S
S.SS jjrSS jrSS jr\S S j5       rS!S jrS"S jrS!S jrS#S jrS$S jrS%S jr        S&S jrSrg)'r      zVUsed by the non-streamed synthesize API, some providers support chunked http responsestts_requestClassVar[str]_tts_request_span_namec               *  ^  UT l         UT l        UT l        [        R                  [
           " 5       T l        ST l        ST l        ST l	        ST l
        [        R                  R                  T R                  S5      T l        T R                  u  T l        nST l        [         R"                  " T R%                  U5      SS9T l        S
U 4S jjn[         R"                  " U" 5       SS9T l        T R(                  R+                  U 4S	 j5        S T l        g )Nr           Fr   TTS._metrics_tasknamec                    >#    [         R                  " T R                  SS9   T R                  5       I S h  vN   S S S 5        g  N! , (       d  f       g = f7fNF)end_on_exitr   start_as_current_spanr   
_main_taskre   s   r=   _traceable_main_task4ChunkedStream.__init__.<locals>._traceable_main_task   B     --d.I.IW\]oo''' ^]' ^]+    AAAA	AA
AAzTTS._synthesize_taskc                8   > TR                   R                  5       $ rd   	_event_chclose_r]   s    r=   <lambda>(ChunkedStream.__init__.<locals>.<lambda>   s    $..:N:N:Pr<   r   )_input_text_tts_conn_optionsr!   Chanr*   r   _input_tokens_output_tokens_acquire_time_connection_reused	itertoolstee_tee_event_aiter_current_attempt_has_errorasynciocreate_task_metrics_monitor_task_metrics_task_synthesize_taskadd_done_callback_tts_request_span)r]   r   r   rw   monitor_aiterr   s   `     r=   rX   ChunkedStream.__init__   s     &	)"235$'(-MM%%dnna8	+/99(=*/'$00&&}5<O
	( !( 3 3 ")?!
 	//0PQ48r<   c                    U R                   $ rd   )r   re   s    r=   r   ChunkedStream.input_text   s    r<   c                6    U R                   R                  5       $ rd   )r   donere   s    r=   r   ChunkedStream.done   s    $$))++r<   c                6    U R                   R                  5       $ rd   )r   	exceptionre   s    r=   r   ChunkedStream.exception   s    $$..00r<   r   input_tokensoutput_tokensc                   Xl         X l        g rd   r   r   r]   r   r   s      r=   _set_token_usageChunkedStream._set_token_usage       )+r<   c                  #    [         R                  " 5       nSnSnSnU  Sh  vN nUR                  nUS:X  a  [         R                  " 5       U-
  nX6R                  R                  -  nMM   NH
 [         R                  " 5       U-
  nU R
                  (       a  g[        [         R                   " 5       UUU[        U R                  5      U R                  U R                  UU R                  R                  5       U R                  R                  SU R                  U R                   [#        U R                  R$                  U R                  R&                  S9S9nU R(                  (       a8  U R(                  R+                  [,        R.                  UR1                  5       5        U R                  R3                  SU5        g7f)	Task used to collect metricsr         r2   NF
model_namemodel_provider)rJ   r/   ttfbdurationcharacters_countr   r   audio_duration	cancelledrK   streamedacquire_timeconnection_reusedmetadatar   )timeperf_counterr/   r-   r   r   r   lenr   r   r   r   r   r   r\   r   r   r   ri   rm   r   set_attributer   ATTR_TTS_METRICSmodel_dump_jsonemit)	r]   event_aiter
start_timer   r   r/   evr   metricss	            r=   r   #ChunkedStream._metrics_monitor_task   sb     &&(

# 	0"Jt|((*Z7hh///N	0 $$&3**iik! !1!12++--)++557))""++"55I[I[\
  !!""00,,g.E.E.G 			*G4s'   G A/A-A/AG -A//EG c                   #    / nU   Sh  vN nUR                  UR                  5        M&   N!
 [        R                  " U5      $ 7f)z6Utility method to collect every frame in a single callN)appendr-   r   combine_audio_frames)r]   framesr  s      r=   collectChunkedStream.collect
  s>      	$"MM"((#	$ ''//s   A/-/A/Ac                   #    g 7frd   r5   r]   output_emitters     r=   _runChunkedStream._run       @Cr   c           	       #    [         R                  " 5       =U l        nUR                  [        R
                  S[        R                  U R                  R                  05        [        U R                  R                  S-   5       GH<  n[        U R                  R                  U R                  S9n [        R                  " S5       nUR!                  [        R"                  U5         U R%                  U5      I S h  vN    S S S 5        UR-                  5         UR/                  5       I S h  vN   U R0                  R3                  5       (       a,  UR5                  5       S::  a  [7        SU R0                   35      eUR!                  [        R8                  U R0                  5         UR;                  5       I S h  vN     g    g  N! [&         a  n[(        R*                  " XE5        e S nAff = f! , (       d  f       N= f N NG! [6         Ga  n[=        U[>        5      (       a/  UR@                  S:X  a   S nAUR;                  5       I S h  vN      g U R                  RC                  U5      nU R                  R                  S:X  d  U R                  R                  U:X  a  U RE                  USS	9  e U RE                  US
S	9  [F        RH                  " SU SU S3U R                  RJ                  US-   SS.S9  [L        RN                  " U5      I S h  vN    SU l(         S nAOS nAff = f UR;                  5       I S h  vN    GM  ! UR;                  5       I S h  vN    f = f7f)NF   rK   dst_chtts_request_runr   &no audio frames were pushed for text:   r   rO   Tzfailed to synthesize speech: z, retrying in sr   attemptr   extra))r   get_current_spanr   set_attributesr   ATTR_TTS_STREAMINGATTR_TTS_LABELr   rK   ranger   	max_retryAudioEmitterr   r   r   r  ATTR_RETRY_COUNTr  rM   telemetry_utilsrecord_exception	end_inputjoinr   strippushed_durationr   ATTR_TTS_INPUT_TEXTr   
isinstancer   status_code_interval_for_retry_emit_errorr   warningr\   r   sleepr   )r]   current_spanir  attempt_spaneretry_intervals          r=   r   ChunkedStream._main_task  s    050F0F0HH##..**DIIOO	
 t))33a78A)		WN&.112CD ..{/K/KQO"ii777 E ((*$))+++##))++0N0N0PTW0W"%KDL\L\K]#^__**;+J+JDL\L\]* %++---Q 9 8$ '88I	 ED ,6 .)  8a00Q]]c5I" %++--- "&!3!3!G!G!J%%//148J8J8T8TXY8Y$$QE$:$$QD$9NN7s.HXXYZ&*ii&6&61q5V[\
 mmN33327//%8$ 0$++---n++---s   B0M,3H	!G3+G
?G G
+H0H1A9H+M,>H?	M,G


G0G++G00G33
H	=HM,L.%L)8M<M,IM,C L)LL)$M)L..M2M,MM,M)"M%
#M))M,c           
         SU l         U R                  R                  S[        [        R                  " 5       U R                  R
                  UUS95        g NTrN   )rJ   rK   rN   rO   r   r   r  rD   r   r\   r]   	api_errorrO   s      r=   r5  ChunkedStream._emit_errorH  A    *.'		))+ii&&'		
r<   c                n  #    [         R                  " U R                  5      I Sh  vN   U R                  R	                  5         U R
                  I Sh  vN   U R                  R                  5       I Sh  vN   U R                  (       a"  U R                  R                  5         SU l        gg N N\ N<7f)zCClose is automatically called if the stream is completely collectedN)
r!   cancel_and_waitr   r   r   r   r   r   r   endre   s    r=   r   ChunkedStream.acloseT  s     !!$"7"7888    ii   !!""&&(%)D" "	 	9  s3   $B5B/-B5B1!B56B379B51B53B5c                  #     U R                   R                  5       I S h  vN nU$  N! [         aJ    U R                  R	                  5       (       d#  U R                  R                  5       =n(       a  Ue[        S ef = f7frd   )r   	__anext__StopAsyncIterationr   r   r   r]   valr   s      r=   rJ  ChunkedStream.__anext__^  sv     	/))3355C 
 6! 	/((2244AVAVA`A`Ab:b#:b	$$.		/&   B* (* B* AA>>Bc                    U $ rd   r5   re   s    r=   	__aiter__ChunkedStream.__aiter__i      r<   c                   #    U $ 7frd   r5   re   s    r=   r   ChunkedStream.__aenter__l  r   r   c                @   #    U R                  5       I S h  vN   g  N7frd   r   r   s       r=   r   ChunkedStream.__aexit__o  r   r   )r   r   r   r   r   r   r   r   r   r   r   r   r   r   Nr   rS   r   r.   rw   r    r   r   r   )r   r0   )r   r   r   r   r   r   r   r   r  zAsyncIterable[SynthesizedAudio]r   r   )r   r,   r  r)  r   r   r   rB  rM   rO   r0   r   r   r   r*   r   zAsyncIterator[SynthesizedAudio])r   r   r   )r6   r7   r8   r9   __doc__r   r:   rX   r   r   r   r   r   r   r  r   r  r   r5  r   rJ  rQ  r   r   r;   r5   r<   r=   r   r      s    `,9M9 9  9 	 9
 ( 9 
 9D     , , 1 1 78a ,(5T0 C C1.f

*	, " %	
 
r<   r   c                  J   ^  \ rS rSrSr        SU 4S jjrSS jrSrU =r$ )r   ix  zImplementation of ChunkedStream that wraps a SynthesizeStream.

Used by TTS providers that only support streaming inference to implement
the synthesize() method.
c               $   > [         TU ]  UUUS9  g )Nr   )rW   rX   )r]   r   r   rw   ra   s       r=   rX   !_ChunkedStreamFromStream.__init__  s      	!% 	 	
r<   c                  #    UR                  [        5       U R                  R                  U R                  R                  SSS9  U R                  R                  [        SU R                  R                  S9S9 IS h  vN nUR                  U R                  5        UR                  5         U  S h  vN nUR                  UR                  R                  R                  5       5        UR                  R                   R#                  [$        5      =n(       d  Mn  UR'                  U5        M   N N~
 S S S 5      IS h  vN    O! , IS h  vN  (       d  f       O= fUR)                  5         g 7f)N	audio/pcmF)r/   r_   r`   	mime_typer   r   )r(  timeoutrv   )
initializer%   r   r_   r`   r   r    r   rf  	push_textr   r-  pushr-   datatobytesuserdatagetr   push_timed_transcriptflush)r]   r  r   r  timed_transcriptss        r=   r  _ChunkedStreamFromStream._run  s)    !! {		--//! 	" 	
 99##*Q@R@R@Z@Z[ $ 
 
T--." Lb##BHHMM$9$9$;<(*(9(9(=(=>W(XX$X"889JK

LF
 
 
 
 
 
 	ss   A=E4?D2 E4.E	1D65D46D69A"E	E	2E44D66E	7E4EE4	E EE E4r5   rX  r[  )	r6   r7   r8   r9   r_  rX   r  r;   r   r   s   @r=   r   r   x  s?    
 
 	

 (
 

 r<   r   c                     ^  \ rS rSr% SrS\S'    " S S5      rSU 4S jjrSSS	.SS
 jjr\	SS j5       r
SS jrSS jrSS jrSS jrSS jrSS jrSS jrSS jrS S jrS!S jrS"S jr        S#S jrSrU =r$ )$r   i  r   r   r   c                      \ rS rSrSrg)SynthesizeStream._FlushSentineli  r5   Nr6   r7   r8   r9   r;   r5   r<   r=   _FlushSentinelrt    s    #r<   rv  c                 >^  [         TT ]  5         UT l        UT l        [        R
                  [        [        R                  -     " 5       T l	        [        R
                  [           " 5       T l        [        R                  R                  T R                  S5      T l        T R                  u  T l        T l        S
U 4S jjn["        R$                  " U" 5       SS9T l        T R&                  R)                  U 4S j5        S T l        ST l        ST l        ST l        / T l        ST l        / T l        ST l        ST l        ST l        ST l        S	T l         ST l!        S T l"        g )Nr   c                    >#    [         R                  " T R                  SS9   T R                  5       I S h  vN   S S S 5        g  N! , (       d  f       g = f7fr   r   re   s   r=   r   7SynthesizeStream.__init__.<locals>._traceable_main_task  r   r   zTTS._main_taskr   c                8   > TR                   R                  5       $ rd   r   r   s    r=   r   +SynthesizeStream.__init__.<locals>.<lambda>  s    t~~/C/C/Er<   Fr   r2   r   r   )#rW   rX   r   r   r!   r   r.   r   rv  	_input_chr*   r   r   r   r   r   _monitor_aiterr   r   _taskr   r   r   _started_time_pushed_text_input_buffer_input_ended_mtc_pending_texts	_mtc_text_num_segmentsr   r   r   r   r   )r]   r   rw   r   ra   s   `   r=   rX   SynthesizeStream.__init__  s(   	)#(8(G(G"GHJ"235MM%%dnna8	15.4.	( (()=)?FVW


$$%EF8<*/'$%!# KM! .0$'(-48r<   r   r   c                   Xl         X l        g rd   r   r   s      r=   r   !SynthesizeStream._set_token_usage  r   r<   c                   #    g 7frd   r5   r  s     r=   r  SynthesizeStream._run  r  r   c                D	  #    [         R                  " 5       =U l        nUR                  [        R
                  S[        R                  U R                  R                  05        [        U R                  R                  S-   5       GHz  n[        U R                  R                  U R                  S9n [        R                  " S5       nUR!                  [        R"                  U5         U R%                  U5      I S h  vN    S S S 5        UR-                  5         UR/                  5       I S h  vN   U R0                  R3                  5       (       aj  UR5                  SS9S::  a  [7        SU R0                   35      eU R8                  UR:                  :w  a%  [7        S	U R8                   S
UR:                   35      eUR!                  [        R<                  U R0                  5         UR?                  5       I S h  vN     g    g  GN! [&         a  n[(        R*                  " XE5        e S nAff = f! , (       d  f       GN4= f GN NJ! [6         Ga  n[A        U[B        5      (       a/  URD                  S:X  a   S nAUR?                  5       I S h  vN      g UR5                  5       nURF                  =(       aD    US:H  =(       a8    U R                  R                  S:  =(       a    X R                  R                  :  nU(       dD  US:  a-  [H        RJ                  " SU R                  RL                  SUS.S9  U RO                  USS9  e U R                  RQ                  U5      nU RO                  USS9  [H        RR                  " SUUU R                  RL                  US-   SS.S9  [T        RV                  " U5      I S h  vN    [X        RZ                  [\        [^        R`                  -     " 5       U l1        U Rd                   H  n	U Rb                  Rg                  U	5        M      U Rh                  (       a  U Rb                  Rk                  5         SU l6         S nAOS nAff = f UR?                  5       I S h  vN    GM  ! UR?                  5       I S h  vN    f = f7f)NTr  r  r  )idxr   r  z&number of segments mismatch: expected z
, but got r  r   zKTTS failed after partial audio was already sent to the user, skip retrying.)r   r   r0  r!  Fr  z0failed to synthesize speech: %s, retrying in %ssr  )7r   r#  r   r$  r   r%  r&  r   rK   r'  r   r(  r)  r   r   r   r  r*  r  rM   r+  r,  r-  r.  r  r/  r0  r   r  num_segmentsr1  r   r2  r   r3  	retryabler   rN   r\   r5  r4  r6  r   r7  r!   r   r.   r   rv  r|  r  send_nowaitr  r   r   )
r]   r8  r9  r  r:  r;  r0  should_retryr<  events
             r=   r   SynthesizeStream._main_task  s    050F0F0HH##..**DIIOO	
 t))33a78A)		WNH.112CD ..{/K/KQO"ii777 E ((*$))+++$$**,,%55"5=D&)OPTPaPaOb'cdd))^-H-HH&DTEWEWDX Y''5'B'B&CE 
 **;+J+JDL]L]^` %++---U 9 8$ '88I	 ED ,z ._  -8a00Q]]c5IX %++---U #1"@"@"BKK 9'3.9**44q89 ..888	  $&,i'+yy'7'7,03B# $$QE$:!%!3!3!G!G!J   5F""&))"2"2q1uRVW	 mmN333 "%#0@0O0O*O!P!R!//ENN..u5 0$$NN((* 38//[-8Z 0$++---n++---s   B0R 3I		!H2+H	?H H	+I	0I1B7I	)R <I=	R H		
H/H**H//H22
I	<	I	R 	Q"%Q9R=R JR D(Q OBQRQ""R&R 9Q<:R RR
RR c           
         SU l         U R                  R                  S[        [        R                  " 5       U R                  R
                  UUS95        g r?  r@  rA  s      r=   r5  SynthesizeStream._emit_error%  rD  r<   c                Z    U R                   S:X  a  [        R                  " 5       U l         g g )Nr   )r  r   r   re   s    r=   _mark_startedSynthesizeStream._mark_started1  s&    "!%!2!2!4D #r<   c                D  ^ ^^^^#    SmSmSmSmSUUUU U4S jjnU  Sh  vN nTS:X  a"  [         R                  " 5       T R                  -
  mTUR                  R                  -  mUR
                  mUR                  mUR                  (       d  Mu  U" 5         M~   Ny
 g7f)r   r   r   r2   c                 L  > TR                   (       a  TR                  (       a  g [        R                  " 5       TR                   -
  n TR                  (       d  g TR                  R                  S5      nU(       d  g [        [        R                  " 5       TTTU [        U5      TR                  TR                  TTR                  R                  5       TR                  R                  STR                  TR                  [!        TR                  R"                  TR                  R$                  S9S9nTR&                  (       a8  TR&                  R)                  [*        R,                  UR/                  5       5        TR                  R1                  SU5        SmSmSmSTl         g )	Nr   Tr   )rJ   r/   r3   r   r   r   r   r   r   r   rK   r   r   r   r   r   r   r   r2   )r  r   r   r   r  popr   r   r   r   r~  r   r   r\   r   r   r   ri   rm   r   r  r   r  r  r  )r   rz   r  r   r/   r3   r]   r   s      r=   _emit_metrics=SynthesizeStream._metrics_monitor_task.<locals>._emit_metrics=  sB    %%)H)H((*T-?-??H****..q1D ))+%%!!$T!//"11-**..0ii&&!//"&"9"9!TYY__TYYM_M_`G" %%&&4400'2I2I2K IINN.8 NDJ!"Dr<   Nr   )r   r   r  r-   r   r/   r3   r1   )r]   r  r  r  r   r/   r3   r   s   `   @@@@r=   r   &SynthesizeStream._metrics_monitor_task6  s     

)	# )	#V $ 		 "t|((*T-?-??bhh///NJJ{{{		 s,   B BBBA)B 	B BB c                $   U(       a  U R                   R                  (       a  gU =R                  U-  sl        U R                  c3  [        R
                  " U R                  U R                  5      SS9U l        U R                  (       d<  U R                  S:  a  [        R                  " S5        gU =R                  S-  sl	        U =R                  U-  sl        U R                   R                  U5        U R                  R                  U5        g)z Push some text to be synthesizedNr   r   r  zSynthesizeStream: handling multiple segments in a single instance is deprecated. Please create a new SynthesizeStream instance for each segment. Most TTS plugins now use pooled WebSocket connections via ConnectionPool.)r|  closedr  r   r   r   r   r}  r  r  r   r6  r  r  r  )r]   tokens     r=   rh  SynthesizeStream.push_texts  s    --U"%!(!4!4**4+>+>?FY"D ~~!!Q&`
 !#%""5)!!%(r<   c                B   U R                   R                  (       a  gU R                  (       a,  U R                  R	                  U R                  5        SU l        U R                  5       nU R                   R                  U5        U R                  R	                  U5        g)z#Mark the end of the current segmentNr2   )r|  r  r  r  r  rv  r  r  )r]   sentinels     r=   ro  SynthesizeStream.flush  sl    >>  >>##**4>>:DN&&(""8,!!(+r<   c                f    U R                  5         U R                  R                  5         SU l        g)z2Mark the end of input, no more text will be pushedTN)ro  r|  r   r  re   s    r=   r-  SynthesizeStream.end_input  s#    

 r<   c                  #    [         R                  " U R                  5      I Sh  vN   U R                  R	                  5         U R
                  R	                  5         U R                  b  U R                  I Sh  vN   U R                  R                  5       I Sh  vN   U R                  (       a"  U R                  R                  5         SU l	        gg N N\ N<7f)zClose ths stream immediatelyN)r!   rF  r~  r   r   r|  r   r   r   r   rG  re   s    r=   r   SynthesizeStream.aclose  s     !!$**---)$$$$ii   !!""&&(%)D" " 	.
 % s4   $CCAC;C<!CC9CCCc                  #     U R                   R                  5       I S h  vN nU$  N! [         aJ    U R                  R	                  5       (       d#  U R                  R                  5       =n(       a  Ue[        S ef = f7frd   )r   rJ  rK  r~  r   r   rL  s      r=   rJ  SynthesizeStream.__anext__  sr     	/))3355C 
 6! 	/::''))djj6J6J6L/Ls/L	$$.		/rO  c                    U $ rd   r5   re   s    r=   rQ  SynthesizeStream.__aiter__  rS  r<   c                   #    U $ 7frd   r5   re   s    r=   r   SynthesizeStream.__aenter__  r   r   c                @   #    U R                  5       I S h  vN   g  N7frd   r   r   s       r=   r   SynthesizeStream.__aexit__  r   r   )r   r   r   r   r   r   r  r|  r  r   r   r}  r  r  r  r   r  r  r~  r   r   r   )r   rS   rw   r    r   r   rY  r[  r   r\  rZ  )r  r.   r   r   r]  r^  )r   r   r   )r6   r7   r8   r9   r   r:   rv  rX   r   r   r  r   r5  r  r   rh  ro  r-  r   rJ  rQ  r   r   r;   r   r   s   @r=   r   r     s    ,9M9!9F 78a , C CS.j

5
; z)6,!*	, " %	
 
 r<   r   c                  ^   \ rS rSr " S S5      r\ " S S5      5       r " S S5      r\ " S S	5      5       r      SS
 jr	S S!S jjr
\S"S j5       rSSS.             S#S jjrS$S jrS$S jrS%S jrS%S jrS&S jrS'S jrS%S jrS%S jrS%S jrS%S jr\" \S9S%S j5       rSrg)(r)  i  c                      \ rS rSrSrg)AudioEmitter._FlushSegmenti  r5   Nru  r5   r<   r=   _FlushSegmentr        r<   r  c                       \ rS rSr% S\S'   Srg)AudioEmitter._StartSegmenti  r.   r3   r5   N)r6   r7   r8   r9   r:   r;   r5   r<   r=   _StartSegmentr    s    r<   r  c                      \ rS rSrSrg)AudioEmitter._EndSegmenti  r5   Nru  r5   r<   r=   _EndSegmentr    r  r<   r  c                  .    \ rS rSr% S\S'   SrS\S'   Srg)	AudioEmitter._SegmentContexti  r.   r3   r   rI   r   r5   N)r6   r7   r8   r9   r:   r   r;   r5   r<   r=   _SegmentContextr    s     ##r<   r  c               T    X l         Xl        SU l        SU l        SU l        / U l        g )Nr2   Fr   )_dst_chr\   _request_id_startedr  _audio_durations)r]   rK   r  s      r=   rX   AudioEmitter.__init__  s-      "-/r<   c                    [        U R                  5      * Us=::  a  [        U R                  5      :  a  O  OU R                  U   $ S$ )Nr   )r   r  )r]   r  s     r=   r0  AudioEmitter.pushed_duration  sI     D))**cNC8M8M4NN !!#&	
 	
r<   c                    U R                   $ rd   )r  re   s    r=   r  AudioEmitter.num_segments  rq   r<      F)frame_size_msr   c                  U R                   (       a  [        S5      eSU l        U(       aL  UR                  5       R	                  5       nUR                  S5      =(       d    UR                  S5      U l        X@l        U(       d#  [        R                  " SU R                  5        SnSU l         Xl
        XPl        X l        X0l        X`l        SS	KJn  ["        R$                  [&        [(        R*                  -  [(        R,                  -  [(        R.                  -  U-     " 5       U l        [2        R4                  " U R7                  5       S
S9U l        U R                  (       d  U R;                  SS9  g g )NzAudioEmitter already startedFrd  z	audio/rawz!no request_id provided for TTS %srh   Tr   r&   zAudioEmitter._main_taskr   r2   r3   )r  RuntimeError_is_raw_pcmlowerr/  
startswith
_mime_typer   r6  r\   r  _frame_size_msrZ   r[   
_streamingvoice.ior'   r!   r   bytesr)  r  r  r  	_write_chr   r   r   _main_atask_AudioEmitter__start_segment)	r]   r/   r_   r`   re  r  r   mtr'   s	            r=   rg  AudioEmitter.initialize  s'    ===>> "((*B!}}[9WR]];=WD#NN>L"J%+') *(()(() &&' 	
  #..t/@G`a  B / r<   c               X    U R                   (       d  [        S5      eU R                  US9$ )NzXstart_segment() can only be called when SynthesizeStream is initialized with stream=Truer  )r  r  r  r]   r3   s     r=   start_segmentAudioEmitter.start_segment  s1    # 
 ##z#::r<   c                   U R                   (       d  [        S5      eU R                  R                  (       a  g U =R                  S-  sl        U R                  R                  U R                  US95        g )NAudioEmitter isn't startedr  r  )r  r  r  r  r  r  r  r  s     r=   __start_segmentAudioEmitter.__start_segment(  sV    }};<<>>  a""4#5#5#5#LMr<   c                Z    U R                   (       d  [        S5      eU R                  5       $ )NzVend_segment() can only be called when SynthesizeStream is initialized with stream=True)r  r  _AudioEmitter__end_segmentre   s    r=   end_segmentAudioEmitter.end_segment2  s,    # 
 !!##r<   c                    U R                   (       d  [        S5      eU R                  R                  (       a  g U R                  R	                  U R                  5       5        g Nr  )r  r  r  r  r  r  re   s    r=   __end_segmentAudioEmitter.__end_segment;  s@    }};<<>>  ""4#3#3#56r<   c                    U R                   (       d  [        S5      eU R                  R                  (       a  g U R                  R	                  U5        g r  )r  r  r  r  r  )r]   rj  s     r=   ri  AudioEmitter.pushD  s7    }};<<>>  ""4(r<   c                   U R                   (       d  [        S5      eU R                  R                  (       a  g [	        U[
        5      (       a%  U H  nU R                  R                  U5        M      g U R                  R                  U5        g r  )r  r  r  r  r2  listr  )r]   r4   rz   s      r=   rn  "AudioEmitter.push_timed_transcriptM  sb    }};<<>>  j$''"**40 # NN&&z2r<   c                    U R                   (       d  [        S5      eU R                  R                  (       a  g U R                  R	                  U R                  5       5        g r  )r  r  r  r  r  r  re   s    r=   ro  AudioEmitter.flushZ  s@    }};<<>>  ""4#5#5#78r<   c                    U R                   (       d  [        S5      eU R                  R                  (       a  g U R	                  5         U R                  R                  5         g r  )r  r  r  r  r  r   re   s    r=   r-  AudioEmitter.end_inputc  sA    }};<<>>  r<   c                p   #    U R                   (       d  [        S5      eU R                  I S h  vN   g  N7fr  )r  r  r  re   s    r=   r.  AudioEmitter.joinm  s'     }};<<s   ,646c                   #    U R                   (       d  g [        R                  " U R                  5      I S h  vN   g  N7frd   )r  r!   rF  r  re   s    r=   r   AudioEmitter.acloses  s)     }}!!$"2"2333s   6A >A r   c           
     
  ^ ^	^
^^^^^^^^^^^^#    SSK Jn  S mS nS mS m/ m/ mS mS mSm[        R                  " 5       mSS.SUUU UU4S jjjmT R                  S-  S-  m	SU	4S	 jjmSUUUU U4S
 jjm
SSS.SU
UUUUU U4S jjjjmSUUUUUU UUU4	S jjnSUUU 4S jjn[        [        S9SUUUU 4S jj5       nS n T R                    S h  vN n[        Xq5      (       a  TR                  U5        M,  [        U[        R                  5      (       aL  T(       a  [        S5      eT R                  R                  S5        [        R                  UR                  S9mM  T(       dM  T R                   (       a<  [        U[        R"                  [        R$                  45      (       a  M  [        S5      eT R&                  (       Gab  [        U[(        5      (       at  UcN  [*        R,                  " T R                  T R.                  [1        T R                  S-  T R2                  -  5      SS9nUR5                  U5       H  nT" U5        M     GM  U(       a  [        U[        R$                  5      (       a9  UR7                  5        H  nT" U5        M     U" 5         UR9                  5         GM  [        U[        R"                  5      (       a5  UR7                  5        H  nT" U5        M     T" SS9  U" 5         S =m=nmGM9  [        R:                  " S[=        U5      5        GM\  GM_  [        U[(        5      (       aj  T(       dO  [>        R@                  " T R                  T R.                  T RB                  S9m[        RD                  " U" 5       5      nTR5                  U5        GM  U(       d  GM  [        U[        R$                  5      (       a0  T(       a&  TRG                  5         UI S h  vN   U" 5         S mGM4  GM7  [        U[        R"                  5      (       a@  T(       a9  T(       a  TRG                  5         UI S h  vN   T" SS9  U" 5         S =m=m=nmGM  [        R:                  " S[=        U5      5        GM   GN N ND
 Tb  TRI                  5         T(       aA  U(       a9  TRK                  5       I S h  vN    [L        RN                  " U5      I S h  vN    g g g ! Tb  TRI                  5         T(       aA  U(       a9  TRK                  5       I S h  vN    [L        RN                  " U5      I S h  vN    f f f = f7f)Nr   r&   r   Fflush_if_delayedc               J  > TR                   R                  U 5        Tc  TR                  5       mTU R                  R                  -  mTb  TR                  5         SU4S jjnU(       a9  TS:  a2  TTR                  5       T-
  -
  S-
  nUS:  a  TR                  X25      mg g g g )Nc                 R   > T R                  5         [        R                  " S5        g )Nz0flush audio emitter due to slow audio generation)ro  r   debugre   s   r=   _flush<AudioEmitter._main_task.<locals>._send_audio.<locals>._flush  s    

OPr<   g333333?g{Gz?r   r   )r  r  r   r-   r   cancel
call_later)	r  r  r  delay
event_loopflush_timerr]   sent_duration
sent_starts	       r=   _send_audio,AudioEmitter._main_task.<locals>._send_audio  s     LL$$R(!'__.
RXX...M&""$Q  MD$8 &):Z)GH4O19","7"7"FK  %9r<   
     c                L  > U R                   T::  a  SU 4$ U R                   T-
  nXR                  -  n[        R                  " U R                  SU U R
                  U R                  US9n[        R                  " U R                  US U R
                  U R                  TS9nX44$ )zSplit *frame* into (head, tail) where tail is exactly _TAIL_SAMPLES.

If the frame is too small to split, returns (None, frame).
Nrj  r_   r`   samples_per_channel)r  r`   r   
AudioFramerj  r_   )r-   head_samples	split_idxheadtail_TAIL_SAMPLESs        r=   _split_tail,AudioEmitter._main_task.<locals>._split_tail  s    
 ((M9U{" 44}DL$'9'99I>>ZZ
+!--"//$0	D >>ZZ	
+!--"//$1	D :r<   c          	     H  > Tc   eTU R                   [        '   / mT" [        U TR                  TR                  US9U(       + S9  T=R
                  U R                  -  sl        TR                  S==   U R                  -  ss'   [        (       a  TR                  U 5        gg)z/Send a frame downstream and update bookkeeping.Nr-   r/   r3   r1   r  r  )
rl  r   r*   r  r3   r   r   r  lk_dump_ttsr  )r-   r1   r  debug_framessegment_ctxr]   rp  s     r=   _do_send)AudioEmitter._main_task.<locals>._do_send  s     ***8IENN45 " #//*55%	 &. &&%..8&!!"%7%{##E* r<   r1   c          	     N  > T
c   eU(       a  T	b%  U b"  [         R                  " T	U /5      nT" USS9  S m	g T	b
  T" T	SS9  S m	g U b  T" U SS9  g T
R                  S:  a  [         R                  " STR                  S-  TR
                  -  -  TR                  TR
                  TR                  S-  S9nTUR                  [        '   / mT" [        UTR                  T
R                  SS9SS	9  g U c  g T	b  [         R                  " T	U /5      nOU nT" U5      u  pEUb  T" USS9  Um	g )
NTr  r   s     d   r  r  Fr  )r   r  r   r  rZ   r[   rl  r   r*   r  r3   )r-   r1   combinedmarkerr  r  r  r  r  
last_framer  r]   rp  s         r=   _emit_frame,AudioEmitter._main_task.<locals>._emit_frame  sm   ***)e.?"77U8KLHX5!%J4 3  +Z$7!%J. - &UT2* ) !//!3 !^^$(9(9S(@4CUCU(UV$($5$5%)%7%7,0,=,=,D	F BSFOO$=>(*%("('+'7'7'2'='=%)	 */ } %33Z4GH $X.JD.Jr<   c            	     |  >	 Tc   eTc  g TTR                   [        '   T " [        TTR                  TR                  SS9SS9  / mT=R
                  TR                  -  sl        TR                  S==   TR                  -  ss'   [        (       a  TR                  T5        S mS mSmTb  TR                  5         S mg g )NFr  r  r  r   )rl  r   r*   r  r3   r   r   r  r  r  r  )	r  r  r  r#  r  r]   r  r  rp  s	   r=   _flush_frame-AudioEmitter._main_task.<locals>._flush_frame  s     ***!=NJ 9: $#//*55"	 "' !#&&**=*==&!!"%)<)<<%{##J/JJM&""$" 'r<   c            	       > Tc   e[         (       a  T(       d  g [        R                  R                  5       R                  S5      n TR                  (       a-  STR
                   STR                   STR                   SU  S3	OSTR
                   STR                   SU  S3n[        US5       nUR                  [        R                  " T5      R                  5       5        S S S 5        TR                  5         g ! , (       d  f       N= f)Nz%Y-%m-%d_%H-%M-%Szlk_dump/r   z.wavwb)r  datetimenowstrftimer  r\   r  r3   openwriter   r  to_wav_bytesclear)tsfnamefr  r  r]   s      r=   dump_segment-AudioEmitter._main_task.<locals>.dump_segment)  s    ***;l""&&(112EFB ?? 4;;-q)9)9(:!K<R<R;SSTUWTXX\]}Ad.>.>-?qDI 
 eT"a00>KKMN #   #"s   14C>>
Dr   c            	       >#    Tc   eTc   eS n T  S h  vN nU cN  [         R                  " UR                  UR                  [	        UR                  S-  TR
                  -  5      SS9n U R                  UR                  5       H  nT" U5        M     M   N
 U (       a  U R                  5        H  nT" U5        M     TR                  5       I S h  vN    g 7f)Nr  Tr_   r`   r  progressive)
r"   AudioByteStreamr_   r`   r   r  ri  rj  ro  r   )audio_byte_streamr-   r4  r$  audio_decoderr  r]   s      r=   _decode_task-AudioEmitter._main_task.<locals>._decode_task;  s      *** ,,,>B, 	#e$,(-(=(=$)$5$5%*%7%7,/0A0AT0IDL_L_0_,`$(	)% +//

;AN <	#} !*002AN 3  &&(((s2   CBBBA>CB:CCCz<start_segment() called before the previous segment was endedr  z8start_segment() must be called before pushing audio dataTr8  zunknown data type: %s)r_   r`   format)r  r*   r  r0   r   r   )r-   r,   r   z,tuple[rtc.AudioFrame | None, rtc.AudioFrame])r-   r,   r1   r0   r   r   rd   )r-   zrtc.AudioFrame | Noner1   r0   r   r   r   )(r  r'   r   get_event_looprZ   r$   r   r  r2  r  r)  r  r  r  r  r3   r  r  r  r  r  r"   r:  r[   r   r  ri  ro  r1  r6  rH   r#   AudioStreamDecoderr  r   r-  r  r   r!   rF  )r]   r'   decode_ataskr'  r5  r=  r;  rj  r4  r  r  r$  r  r  r<  r  r  r  r#  r  r  r  rp  s   `        @@@@@@@@@@@@@@r=   r   AudioEmitter._main_tasky  se    *:>,0;?,0
-//126#'
"++-
JO 	G 	G4 ))B.$6	0	+ 	+*4	QV 4	 4	 4	l	# 	#B	! 	!$ 
v	&	) 	) 
'	). ;?Y	8"nn PPdd00%,,T2dL$>$>??"*Z  ))005".">">$//">"ZK"%d\-E-E|GaGa,bcc$*V  ###!$..,4050E0E,0,=,=-1-?-?47$($5$5$=@S@S$S5" -11- "3!7!7!=A'N ">*%dL,F,FGG%6%<%<%> +A &?(N-335'l.F.FGG%6%<%<%> +A &? (6(NKOOKO*;j"NN+BDJO +" "$..,,2,E,E,0,=,=-1-?-?'+-M
 ,3+>+>|~+NL%**40%%dL,F,FGG, - 7 7 9&2 2 2 ,04	  - (l.F.FGGK, - 7 7 9&2 2 2'6(N[__M_K_:Kj"NN+BDJOaPPH !3 !3W -f &""$#**,,,)),777 ".} &""$#**,,,)),777 ".}s   B/U
S* RRRKS* 5;S* 0R	1AS* R?S* R	S* S* S* 4U
SU
!S$"U
*5UT" U>U?UU
)r  r  r  r  r\   r  r  r[   r  r  rZ   r  r  r  N)rK   r.   r  zaio.Chan[SynthesizedAudio]r   r   )r  )r  r   r   rI   r   )r/   r.   r_   r   r`   r   re  r.   r  r   r   r0   r   r   )r3   r.   r   r   r   )rj  r  r   r   )r4   zTimedString | list[TimedString]r   r   )r6   r7   r8   r9   r  r   r  r  r  rX   r0  r   r  rg  r  r  r  r  ri  rn  ro  r-  r.  r   r$   r   r   r;   r5   r<   r=   r)  r)    s&         $ $ $0 0 +	0
 
0
 " " !+0 +0 	+0
 +0 +0 +0 +0 
+0Z;N$7)394 6"s8 #s8r<   r)  )C
__future__r   r   r+  osr   abcr   r   collections.abcr   r   dataclassesr   typesr	   typingr
   r   r   r   r   opentelemetryr   pydanticr   r   r   livekitr   livekit.agents.metrics.baser   _exceptionsr   r   logr   r  r   	telemetryr   r   r   r+  r   r   r    r!   r"   r#   r$   r%   r  r'   r   getenvr  r*   r?   rD   rQ   EventEmitterrS   r   r   r   r)  r5   r<   r=   <module>rT     s"   "   	  # 8 !  E E  1 1  0 2    E E ] ] A A&"))M1-. 
D 
D 
D M M My  
	dW9:VCDFOdNLC L^&} &Rfs fR	c8 c8r<   