
    /jF                       S SK J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  S SK	J
r
JrJr  S SKJr  SSK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  SSKJr  SSKJrJrJrJ r J!r!J"r"  \" S \RF                  S9r$\ " S S5      5       r%\ " S S5      5       r& " S S\\S      5      r' " S S\5      r( " S S\!5      r)g)    )annotationsN)AsyncGeneratorAsyncIterable)	dataclass)AnyClassVarLiteral)rtc   )utils)APIConnectionErrorlogger)DEFAULT_API_CONNECT_OPTIONSUSERDATA_TIMED_TRANSCRIPTAPIConnectOptions)aio   )StreamAdapter)TTSAudioEmitterChunkedStreamSynthesizedAudioSynthesizeStreamTTSCapabilities)	max_retrytimeoutc                  4    \ rS rSr% S\S'   S\S'   S\S'   Srg)	
_TTSStatus!   bool	availablezasyncio.Task[None] | Nonerecovering_taskneeds_resampling N__name__
__module____qualname____firstlineno____annotations____static_attributes__r%       T/app/agent/.venv/lib/python3.13/site-packages/livekit/agents/tts/fallback_adapter.pyr   r   !   s    O..r-   r   c                  *    \ rS rSr% S\S'   S\S'   Srg)AvailabilityChangedEvent(   r   ttsr!   r"   r%   Nr&   r%   r-   r.   r0   r0   (   s    	HOr-   r0   c                     ^  \ rS rSrSrSSS.       SU 4S jjjr\SS j5       r\SS 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rU =r$ )FallbackAdapter.   zb
Manages multiple TTS instances, providing a fallback mechanism to ensure continuous TTS service.
r   N)max_retry_per_ttssample_ratec          
       > [        U5      S:  a  [        S5      e[        U Vs1 s H  oDR                  iM     sn5      S:w  a  [        S5      eUc  [        S U 5       5      nUS   R                  n[        TU ]  [        [        S U 5       5      [        S U 5       5      S	9UUS
9  Xl	        X l
        / U l        U H  nX4R                  :g  nU(       a4  [        R                  " SUR                   SUR                   SU S35        U R                  R!                  [#        SSUS95        UR%                  SU R&                  5        M     gs  snf )a  
Initialize a FallbackAdapter that manages multiple TTS instances.

Args:
    tts (list[TTS]): A list of TTS instances to use for fallback.
    max_retry_per_tts (int, optional): Maximum number of retries per TTS instance. Defaults to 2.
    sample_rate (int | None, optional): Desired sample rate for the synthesized audio. If None, uses the maximum sample rate among the TTS instances.

Raises:
    ValueError: If less than one TTS instance is provided.
    ValueError: If TTS instances have different numbers of channels.
r   z+at least one TTS instance must be provided.z-all TTS must have the same number of channelsNc              3  8   #    U  H  oR                   v   M     g 7fN)r7   .0ts     r.   	<genexpr>+FallbackAdapter.__init__.<locals>.<genexpr>P   s     9SmmSs   r   c              3  L   #    U  H  oR                   R                  v   M     g 7fr:   )capabilities	streamingr;   s     r.   r>   r?   V   s     D1nn66   "$c              3  L   #    U  H  oR                   R                  v   M     g 7fr:   )rA   aligned_transcriptr;   s     r.   r>   r?   W   s     &VRUQ~~'H'HRUrC   )rB   rE   )rA   r7   num_channelszresampling z from zHz to HzT)r"   r#   r$   metrics_collected)len
ValueErrorrF   maxsuper__init__r   anyall_tts_instances_max_retry_per_tts_statusr7   r   infolabelappendr   on_on_metrics_collected)selfr2   r6   r7   r=   rF   r$   	__class__s          r.   rM   FallbackAdapter.__init__5   s>   ( s8a<JKK,1,-2LMM9S99K1v**(DDD#&&VRU&V#V $% 	 	
 ""3)+A*mm;k!''&vk]Z\]^LLT4Rbc DD$d&@&@A + -s   Ec                    g)Nr4   r%   rX   s    r.   modelFallbackAdapter.modell   s     r-   c                    g)Nlivekitr%   r\   s    r.   providerFallbackAdapter.providerp   s    r-   conn_optionsc                   [        XUS9$ N)r2   
input_textrd   )FallbackChunkedStream)rX   textrd   s      r.   
synthesizeFallbackAdapter.synthesizet   s     %\ZZr-   c                   [        XS9$ N)r2   rd   )FallbackSynthesizeStream)rX   rd   s     r.   streamFallbackAdapter.streamy   s     (DLLr-   c                b    U R                   (       a  U R                   S   R                  5         g g )Nr   )rP   prewarmr\   s    r.   rr   FallbackAdapter.prewarm~   s'    "**, r-   c                0    U R                   " S/UQ70 UD6  g NrH   )emit)rX   argskwargss      r.   rW   %FallbackAdapter._on_metrics_collected   s    		%777r-   c                  #    U R                    H:  nUR                  c  M  [        R                  " UR                  5      I S h  vN   M<     U R                   H  nUR                  SU R                  5        M!     g  N87fru   )rR   r#   r   cancel_and_waitrP   offrW   )rX   
tts_statusr=   s      r.   acloseFallbackAdapter.aclose   sf     ,,J))5))**D*DEEE ' $$AEE%t'A'AB % Fs   A?#A?A=9A?)rQ   rR   rP   )r2   z	list[TTS]r6   intr7   z
int | NonereturnNone)r   str)ri   r   rd   r   r   rh   )rd   r   r   rn   r   r   )rw   r   rx   r   r   r   )r'   r(   r)   r*   __doc__rM   propertyr]   ra   $DEFAULT_FALLBACK_API_CONNECT_OPTIONSrj   ro   rr   rW   r~   r,   __classcell__rY   s   @r.   r4   r4   .   s     "#"&5B5B 	5B
  5B 
5B 5Bn ! !   ?c[[*;[	[ 4XM0M	!M
-8C Cr-   r4   tts_availability_changedc                     ^  \ rS rSr% SrS\S'           SU 4S jjrSS jrSS.     SS	 jjrSS
 jr	SS jr
SrU =r$ )rh      tts_fallback_adapterClassVar[str]_tts_request_span_namec               .   > [         TU ]  XUS9  Xl        g rf   )rL   rM   _fallback_adapter)rX   r2   rg   rd   rY   s       r.   rM   FallbackChunkedStream.__init__   s     	SlS!$r-   c                   #    g 7fr:   r%   rX   event_aiters     r.   _metrics_monitor_task+FallbackChunkedStream._metrics_monitor_task           F
recoveringc          
    V  #     UR                  U R                  [        R                  " U R                  U R
                  R                  U R                  R                  U R                  R                  S9S9 IS h  vN nU  S h  vN nU7v   M   N N
 S S S 5      IS h  vN    g ! , IS h  vN  (       d  f       g = f! [         aW  nU(       a&  [        R                  " UR                   S3SS0US9  e [        R                  " UR                   S3SS0S9  e S nAff = f7f)	Nr   r   retry_intervalrc    recovery failedstreamedFextraexc_info error, switching to next TTSr   )rj   _input_textdataclassesreplace_conn_optionsr   rQ   r   r   	Exceptionr   warningrT   )rX   r2   r   ro   audioes         r.   _try_synthesize%FallbackChunkedStream._try_synthesize   s    	~~  (00&&"44GG ..66#'#5#5#D#D	 &   #)  %K 6       	yyk!12:u:MXY NN99+:;!5) 	s   D)A9C =B>C B+BB	BB+C BB+C $B'%C *D)+C1B42C>C D)C 
D&AD!!D&&D)c                p  ^ ^ [        T R                  [        5      (       d   eT R                  R                  T R                  R                  R                  U5         mTR                  b  TR                  R                  5       (       a+  SU U4S jjn[        R                  " U" U5      5      Tl        g g )Nc                
  >#     TR                  U SS9  S h  vN nM   N
 STl        [        R                  " SU R                   S35        TR
                  R                  S[        U SS95        g ! [         a     g f = f7f)NTr2   r   tts.FallbackAdapter, 
 recoveredr   r2   r"   )	r   r"   r   rS   rT   _ttsrv   r0   r   )r2   _rX   r}   s     r.   _recover_tts_task>FallbackChunkedStream._try_recovery.<locals>._recover_tts_task   s     #'#7#7CD#7#Q a#Q ,0J(KK"7		{* MNIINN20SDI ! sC   BA3 " "A3 "AA3 2B3
B =B?B  Br2   r   r   r   )

isinstancer   r4   rR   rP   indexr#   doneasynciocreate_task)rX   r2   r   r}   s   `  @r.   _try_recovery#FallbackChunkedStream._try_recovery   s    $))_5555YY&&tyy'?'?'E'Ec'JK
%%-1K1K1P1P1R1R  *1)<)<=Ns=S)TJ&! 2Sr-   c           
       #    [        U R                  [        5      (       d   e[        R                  " 5       n[	        S U R                  R
                   5       5      nU(       a  [        R                  " S5        UR                  [        R                  " 5       U R                  R                  U R                  R                  SS9  [        U R                  R                  5       GHo  u  pEU R                  R
                  U   nUR                  (       d  U(       Ga&   UR                   (       a3  ["        R$                  " UR                  U R                  R                  S9OS nU R'                  USS9  S h  vN nUR(                  R*                  R-                  [.        5      =n	(       a  UR1                  U	5        UbM  UR3                  UR(                  5       H,  n
UR3                  U
R4                  R7                  5       5        M.     M  UR3                  UR(                  R4                  R7                  5       5        M  U RG                  U5        GMr     [I        SU R                  R                   Vs/ s H  oURD                  PM     sn S[        R                  " 5       U-
   S35      e GN7
 Ub@  UR9                  5        H,  n
UR3                  U
R4                  R7                  5       5        M.       g ! [:         az    UR                  (       a+  SUl        U R                  R=                  S[?        USS	95        URA                  5       S
:  a&  [        RB                  " URD                   S35           g  GN8f = fs  snf 7f)Nc              3  B   #    U  H  oR                   (       + v   M     g 7fr:   r"   r<   r}   s     r.   r>   -FallbackChunkedStream._run.<locals>.<genexpr>   s     VDUj1111DU   $all TTSs are unavailable, retrying..	audio/pcm)
request_idr7   rF   	mime_type
input_rateoutput_rateFr   r   r           z0 already synthesized of audio, ignoring fallbackall TTSs failed () after  seconds)%r   r   r4   timerO   rR   r   error
initializer   	shortuuidr7   rF   	enumeraterP   r"   r$   r
   AudioResamplerr   frameuserdatagetr   push_timed_transcriptpushdatatobytesflushr   rv   r0   pushed_durationr   rT   r   r   )rX   output_emitter
start_time
all_failedir2   r}   	resamplersynthesized_audiotextsrfs              r.   _runFallbackChunkedStream._run   s    $))_5555YY[
VDIIDUDUVV
LL?@!!(		--//!	 	" 	
  		 8 89FA**1-J##z$ &66	 **'*(,		(=(=
 "  483G3GC\a3G3b X/$5$;$;$D$D$H$HIb$cc5c*@@G$0&/nn5F5L5L&M . 3 3BGGOO4E F 'N +//0A0G0G0L0L0T0T0VW* s#S :V !dii6N6N O6Ns6N OPPXY]YbYbYdgqYqXrrz{
 	
?X3b !,"+//"3B*//0AB #4   !++/4
,		64N
 &557#="yyk)YZ 	 >" !Psd   DN!AK;7J5;J2<J5?CK;4N:N
#N2J55AK;9N;A=M?8N>M??N)r   )r2   r4   rg   r   rd   r   r   r   r   zAsyncIterable[SynthesizedAudio]r   r   )r2   r   r   r!   r   &AsyncGenerator[SynthesizedAudio, None]r   r   r   r   r   )r'   r(   r)   r*   r   r+   rM   r   r   r   r   r,   r   r   s   @r.   rh   rh      sj    ,BMB%%%36%FW%	% /4'+	/:U,=
 =
r-   rh   c                  ~   ^  \ rS rSr% SrS\S'   SU 4S jjrSS jrSS.         SS	 jjrSS
 jr	SS jr
SrU =r$ )rn   i  r   r   r   c               :   > [         TU ]  XS9  Xl        / U l        g rm   )rL   rM   r   _pushed_tokens)rX   r2   rd   rY   s      r.   rM   !FallbackSynthesizeStream.__init__  s!    S<!$)+r-   c                   #    g 7fr:   r%   r   s     r.   r   .FallbackSynthesizeStream._metrics_monitor_task  r   r   Fr   c              d  ^ ^^#    UR                   R                  (       a  UR                  US9mO6SSKJn  [        UUR                  R                  SS9S9nUR                  US9m[        R                  " [        S9SUU U4S jj5       n[        R                  " U" 5       5      n T IS h  vN   T  S h  vN n	U	7v   M   N N
 S S S 5      IS h  vN    O~! , IS h  vN  (       d  f       Og= f! [         aW  n
U(       a&  [        R                  " UR                   S	3S
S0U
S9  e [        R                   " UR                   S3S
S0S9  e S n
A
ff = f[        R"                  R%                  U5      I S h  vN    g ! [        R"                  R%                  U5      I S h  vN    f = f7f)Nrc   r   )tokenizeT)retain_format)r2   sentence_tokenizerr   c                 $  >#     T  S h  vN n [        U [        5      (       a  TR                  U 5        M1  [        U TR                  5      (       d  MN  TR	                  5         M`   N[
 TR                  5         g ! TR                  5         f = f7fr:   )r   r   	push_text_FlushSentinelr   	end_input)r   input_chrX   ro   s    r.   _forward_input_taskEFallbackSynthesizeStream._try_synthesize.<locals>._forward_input_task,  sm     #"* '$!$,,((.#D$*=*=>>	'(   "  "sC   BA; A)A'A)AA; A; 'A))A; *B;BBr   r   r   r   r   r   )rA   rB   ro    r   r   	blingfireSentenceTokenizerr   log_exceptionsr   r   r   r   r   rT   	exceptionr   r{   )rX   r2   r   rd   r   r   wrapped_ttsr   
input_taskr   r   ro   s   ` `        @r.   r   (FallbackSynthesizeStream._try_synthesize  sl     %%ZZ\Z:F#'#+#5#5#G#GVZ#G#[K !''\'BF			V	,	# 	# 
-	# (()<)>?
	8v#)  %K  6 vvvvv  	yyk!12%t,
 99+:;!4( 	 ))++J777%))++J777s   B"F0(C6 .C/C6 2C5C	9C:C	=CC6 C		C
C6 CC6 F C3"C%#C3/C6 2F 3C6 6
E AEEF "F0<E?=F0#F-&F)'F--F0c                *
  ^ ^#    [         R                   " 5       n[        S T R                  R                   5       5      nU(       a  [        R
                  " S5        S mUR                  [        R                  " 5       T R                  R                  T R                  R                  SSS9  UR                  [        R                  " 5       S9  SUU 4S jjn[        R                  " U" 5       5      n [        T R                  R                  5       GH  u  pgT R                  R                  U   nUR                   (       d  U(       GaM   ["        R$                  [&        [(        R*                  -     " 5       mT R,                   H  n	TR/                  U	5        M     UR1                  5       (       a  TR3                  5         UR4                  (       a3  [6        R8                  " UR                  T R                  R                  S9OS n
T R;                  UT[<        R>                  " T R@                  T R                  RB                  T R@                  RD                  T R@                  RF                  S	9S
S9  S h  vN nURH                  RJ                  RM                  [N        5      =n(       a  URQ                  U5        U
b  U
RS                  URH                  5       H,  nURS                  URT                  RW                  5       5        M.     URX                  (       aB  U
R[                  5        H,  nURS                  URT                  RW                  5       5        M.     M  M  URS                  URH                  RT                  RW                  5       5        GM#  T Rm                  U5        GM     [o        ST R                  R                   Vs/ s H  owRj                  PM     sn S[         R                   " 5       U-
   S35      e GN
   [        R"                  R]                  U5      I S h  vN    g ! [^         a    UR                   (       a+  S
Ul        T R`                  Rc                  S[e        US
S95        URg                  5       S:  aN  [        Rh                  " URj                   S35           [        R"                  R]                  U5      I S h  vN    g  GNEf = fs  snf ! [        R"                  R]                  U5      I S h  vN    f = f7f)Nc              3  B   #    U  H  oR                   (       + v   M     g 7fr:   r   r   s     r.   r>   0FallbackSynthesizeStream._run.<locals>.<genexpr>Q  s     cDbj1111Dbr   r   r   T)r   r7   rF   r   ro   )
segment_idc                   >#    TR                     S h  vN n T(       a  TR                  U 5        [        U [        5      (       d  M8  U (       d  MA  TR                  R                  U 5        M^   NY
 T(       a  TR                  5         g g 7fr:   )	_input_chsend_nowaitr   r   r   rU   close)r   new_input_chrX   s    r.   r   :FallbackSynthesizeStream._run.<locals>._forward_input_task_  si      #nn 5d ,,T2dC((TT''..t45n ""$ s1   B
A0A.A0,B
B
B
.A00B
r   r   F)r2   r   rd   r   r   r   r   zP already synthesized of audio, ignoring the current segment for the tts fallbackr   r   r   r   )8r   rO   r   rR   r   r   r   r   r   r7   rF   start_segmentr   r   r   rP   r"   r   Chanr   r   r   r   r  r   r  r$   r
   r   r   r   r   r   rQ   r   r   r   r   r   r   r   r   r   r   is_finalr   r{   r   r   rv   r0   r   r   rT   r   r   )rX   r   r   r   r   r  r   r2   r}   ri   r   r   r   resampled_framer  s   `             @r.   r   FallbackSynthesizeStream._runN  s:    YY[
cDDZDZDbDbcc
LL?@OS!!(..:://<<! 	" 	
 	$$0A$B	% 	% (()<)>?
D	8#D$:$:$I$IJ!33;;A>
'':8#'*xx6F6U6U0U'V'X$($7$7D(44T: %8 &??,,(..0  *::	  ..+.??,0,B,B,N,N
 "& " 8<7K7K #%1)4)<)< $ 2 2*.*@*@*S*S(,(:(:(B(B/3/A/A/P/P	* (- 8L 
8 \"3 ):(?(?(H(H(L(L 9)  u   !/ D DU K(47@~~FWF]F]7^O$2$7$78L8L8T8T8V$W 8_ $5#=#=;D??;L(6(;(;O<P<P<X<X<Z([ <M $> !/ 3 34E4K4K4P4P4X4X4Z [" ""3'{ K~ %#$:P:P:_:_$`:_3YY:_$`#aaijnjsjsju  yC  kC  jD  DL  M W\ 
84 * ))++J777) % #%//38J0 IINN : 8SE R
 *99;cA"NN#&99+-} ~ # ))++J777 B#" %a ))++J777s   C/T4AS& D)P25P9P:P=DP24S& S!
!#S& PP2S& 	"T+P.,T2A=S/S& 1"TSTS& SS& &#T	T
TTc                  ^ ^^ [        T R                  [        5      (       d   eT R                  R	                  5       mT(       d  g T R                  R
                  T R                  R                  R                  U5         mTR                  b  TR                  R                  5       (       a,  SUU U4S jjn[        R                  " U" U5      5      Tl        g g )Nc                J  >#     [         R                  [        [        R                  -     " 5       nT H  nUR                  U5        M     UR                  5         TR                  U US[        R                  " TR                  STR                  R                  TR                  R                  S9S9  S h  vN nM   N
 STl        [        R                  " SU R                    S35        TR"                  R%                  S['        U SS95        g ! [(         a     g f = f7f)	NTr   r   )r2   r   r   rd   r   r   r   r   )r   r  r   r   r   r  r  r   r   r   r   r   r   r"   r   rS   rT   r   rv   r0   r   )r2   r   r=   r   
retry_textrX   r}   s       r.   r   AFallbackSynthesizeStream._try_recovery.<locals>._recover_tts_task  s
    "xx.>.M.M(MNPH' ,,Q/ ( NN$#'#7#7!)#'%0%8%8 ..&'$($6$6$>$>+/+=+=+L+L	&	 $8 
$ a  
$ ,0J(KK"7		{* MNIINN20SDI ! sN   D#B0D 5C9C :C=D  CAD D#
D D#D  D#r   )r   r   r4   r   copyrR   rP   r   r#   r   r   r   )rX   r2   r   r  r}   s   `  @@r.   r   &FallbackSynthesizeStream._try_recovery  s    $))_5555((--/
YY&&tyy'?'?'E'Ec'JK
%%-1K1K1P1P1R1R < *1)<)<=Ns=S)TJ&A 2Sr-   )r   r   )r2   r4   rd   r   r   )
r2   r   r   z7aio.ChanReceiver[str | SynthesizeStream._FlushSentinel]rd   r   r   r!   r   r   r   r   )r'   r(   r)   r*   r   r+   rM   r   r   r   r   r,   r   r   s   @r.   rn   rn     si    ,BMB,
 !48 48 J	48
 (48 48 
048ld8L(U (Ur-   rn   )*
__future__r   r   r   r   collections.abcr   r   r   typingr   r   r	   r`   r
   r   r   _exceptionsr   logr   typesr   r   r   r   stream_adapterr   r2   r   r   r   r   r   r   r   r   r   r0   r4   rh   rn   r%   r-   r.   <module>r$     s    "    9 ! ) )   ,  ] ]  )  (94<<( $
      
]C*+,]C@|
M |
~OU/ OUr-   