o
    iF                     @  s>  d dl mZ d dlZd dlZd dlZd dlmZmZ d dlmZ d dl	m
Z
mZmZ d dlmZ ddlmZ dd	lmZ dd
lmZ ddlmZmZmZ ddlmZ ddlmZ ddlmZmZmZm Z m!Z!m"Z" ed ej#dZ$eG dd dZ%eG dd dZ&G dd deed  Z'G dd deZ(G dd de!Z)dS )    )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                   @  s&   e Zd ZU ded< ded< ded< dS )
_TTSStatusbool	availablezasyncio.Task[None] | Nonerecovering_taskneeds_resamplingN__name__
__module____qualname____annotations__ r'   r'   e/var/www/html/livekit_bhavya/venv/lib/python3.10/site-packages/livekit/agents/tts/fallback_adapter.pyr   !   s   
 r   c                   @  s   e Zd ZU ded< ded< dS )AvailabilityChangedEventr   ttsr   r   Nr"   r'   r'   r'   r(   r)   (   s   
 r)   c                      s   e Zd ZdZdddd' fddZed(ddZed(ddZedd)ddZ	edd*ddZ
d+ddZd,d#d$Zd+d%d&Z  ZS )-FallbackAdapterzj
    Manages multiple TTS instances, providing a fallback mechanism to ensure continuous TTS service.
    r
   N)max_retry_per_ttssample_rater*   	list[TTS]r,   intr-   
int | NonereturnNonec             
     s   t |dk r
tdt dd |D dkrtd|du r&tdd |D }|d	 j}t jttd
d |D tdd |D d||d || _	|| _
g | _|D ],}||jk}|rktd|j d|j d| d | jtdd|d |d| j qQdS )aU  
        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.c                 S  s   h | ]}|j qS r'   )num_channels.0tr'   r'   r(   	<setcomp>L       z+FallbackAdapter.__init__.<locals>.<setcomp>z-all TTS must have the same number of channelsNc                 s  s    | ]}|j V  qd S N)r-   r4   r'   r'   r(   	<genexpr>P   s    z+FallbackAdapter.__init__.<locals>.<genexpr>r   c                 s      | ]}|j jV  qd S r9   )capabilities	streamingr4   r'   r'   r(   r:   V       c                 s  r;   r9   )r<   aligned_transcriptr4   r'   r'   r(   r:   W   r>   )r=   r?   )r<   r-   r3   zresampling z from zHz to HzT)r   r    r!   metrics_collected)len
ValueErrormaxr3   super__init__r   anyall_tts_instances_max_retry_per_tts_statusr-   r   infolabelappendr   on_on_metrics_collected)selfr*   r,   r-   r3   r6   r!   	__class__r'   r(   rF   5   s6   
	
"zFallbackAdapter.__init__strc                 C     dS )Nr+   r'   rQ   r'   r'   r(   modell      zFallbackAdapter.modelc                 C  rU   )Nlivekitr'   rV   r'   r'   r(   providerp   rX   zFallbackAdapter.providerconn_optionstextr\   r   FallbackChunkedStreamc                C  s   t | ||dS N)r*   
input_textr\   )r^   )rQ   r]   r\   r'   r'   r(   
synthesizet   s   zFallbackAdapter.synthesizeFallbackSynthesizeStreamc                C  s   t | |dS N)r*   r\   )rb   )rQ   r\   r'   r'   r(   streamy   s   zFallbackAdapter.streamc                 C  s   | j r| j d   d S d S )Nr   )rI   prewarmrV   r'   r'   r(   re   ~   s   zFallbackAdapter.prewarmargsr   kwargsc                 O  s   | j dg|R i | d S NrA   )emit)rQ   rf   rg   r'   r'   r(   rP      s   z%FallbackAdapter._on_metrics_collectedc                   sH   | j D ]}|jd urt|jI d H  q| jD ]	}|d| j qd S rh   )rK   r    r   cancel_and_waitrI   offrP   )rQ   
tts_statusr6   r'   r'   r(   aclose   s   


zFallbackAdapter.aclose)r*   r.   r,   r/   r-   r0   r1   r2   )r1   rT   )r]   rT   r\   r   r1   r^   )r\   r   r1   rb   r1   r2   )rf   r   rg   r   r1   r2   )r#   r$   r%   __doc__rF   propertyrW   rZ   $DEFAULT_FALLBACK_API_CONNECT_OPTIONSra   rd   re   rP   rm   __classcell__r'   r'   rR   r(   r+   .   s     7

r+   tts_availability_changedc                      sZ   e Zd ZU dZded< d  fddZd!ddZddd"ddZd#ddZd$ddZ	  Z
S )%r^   tts_fallback_adapterClassVar[str]_tts_request_span_namer*   r+   r`   rT   r\   r   r1   r2   c                  s   t  j|||d || _d S r_   )rE   rF   _fallback_adapter)rQ   r*   r`   r\   rR   r'   r(   rF      s   
zFallbackChunkedStream.__init__event_aiterAsyncIterable[SynthesizedAudio]c                      d S r9   r'   rQ   rx   r'   r'   r(   _metrics_monitor_task      z+FallbackChunkedStream._metrics_monitor_taskF
recoveringr   r   r   &AsyncGenerator[SynthesizedAudio, None]c             
   C s   zB|j | jtj| j| jj| jj| jjdd4 I d H }|2 z	3 d H W }|V  q6 W d   I d H  W d S 1 I d H s<w   Y  W d S  t	yn } z|r\t
j|j dddi|d  t
j|j dddid  d }~ww )	Nr   r   retry_intervalr[    recovery failedstreamedFextraexc_info error, switching to next TTSr   )ra   _input_textdataclassesreplace_conn_optionsrw   rJ   r   r   	Exceptionr   warningrM   )rQ   r*   r   rd   audioer'   r'   r(   _try_synthesize   s:   2
z%FallbackChunkedStream._try_synthesizec                   sb   t  jtsJ  jj jj| jd u sj r/d fdd}t	||_d S d S )Nr*   r   r1   r2   c                   sl   z* j | dd2 z3 d H W }q	6 d_td| j d  jdt| dd W d S  ty5   Y d S w )NTr*   r   tts.FallbackAdapter, 
 recoveredrs   r*   r   )	r   r   r   rL   rM   _ttsri   r)   r   )r*   _rQ   rl   r'   r(   _recover_tts_task   s   

z>FallbackChunkedStream._try_recovery.<locals>._recover_tts_taskr*   r   r1   r2   )

isinstancer   r+   rK   rI   indexr    doneasynciocreate_taskrQ   r*   r   r'   r   r(   _try_recovery   s   z#FallbackChunkedStream._try_recoveryoutput_emitterr   c                   s  t | jts	J t }tdd | jjD }|rtd |jt	
 | jj| jjdd t| jjD ]\}}| jj| }|jsC|rzb|jrQtj|j| jjdnd }| j|dd2 z33 d H W }|jjt }	rn||	 |d ur||jD ]
}
||
j  qxqZ||jj  qZ6 |d ur| D ]
}
||
j  qW  d S  ty   |jrd|_| jd	t|dd
 |  dkrt!|j" d Y  d S Y nw | #| q4t$ddd | jjD  dt |  d)Nc                 s      | ]}|j  V  qd S r9   r   r5   rl   r'   r'   r(   r:      r>   z-FallbackChunkedStream._run.<locals>.<genexpr>$all TTSs are unavailable, retrying..	audio/pcm)
request_idr-   r3   	mime_type
input_rateoutput_rateFr   rs   r           z0 already synthesized of audio, ignoring fallbackall TTSs failed (c                 S     g | ]}|j qS r'   rM   r5   r*   r'   r'   r(   
<listcomp>	  r8   z.FallbackChunkedStream._run.<locals>.<listcomp>) after  seconds)%r   r   r+   timerH   rK   r   error
initializer   	shortuuidr-   r3   	enumeraterI   r   r!   r	   AudioResamplerr   frameuserdatagetr   push_timed_transcriptpushdatatobytesflushr   ri   r)   pushed_durationr   rM   r   r   )rQ   r   
start_time
all_failedir*   rl   	resamplersynthesized_audiotextsrfr'   r'   r(   _run   sl   





&zFallbackChunkedStream._run)r*   r+   r`   rT   r\   r   r1   r2   rx   ry   r1   r2   )r*   r   r   r   r1   r   r   r   r   r1   r2   )r#   r$   r%   rv   r&   rF   r|   r   r   r   rr   r'   r'   rR   r(   r^      s   
 

r^   c                      sZ   e Zd ZU dZded< d  fdd	Zd!ddZddd"ddZd#ddZd$ddZ	  Z
S )%rb   rt   ru   rv   r*   r+   r\   r   c                  s    t  j||d || _g | _d S rc   )rE   rF   rw   _pushed_tokens)rQ   r*   r\   rR   r'   r(   rF     s   
z!FallbackSynthesizeStream.__init__rx   ry   r1   r2   c                   rz   r9   r'   r{   r'   r'   r(   r|     r}   z.FallbackSynthesizeStream._metrics_monitor_taskFr~   r   input_ch7aio.ChanReceiver[str | SynthesizeStream._FlushSentinel]r   r   r   c             
    sL  |j jr|j|dnddlm} t||jjddd}|j|dtj	t
dd fd
d}t| }zcz+4 I d H  2 z	3 d H W }	|	V  qC6 W d   I d H  n1 I d H s^w   Y  W n+ ty }
 z|r}t
j|j dddi|
d  t
j|j dddid  d }
~
ww W tj|I d H  d S tj|I d H  w )Nr[   r
   )tokenizeT)retain_format)r*   sentence_tokenizerr   r1   r2   c                    sZ   z& 2 z3 d H W } t | tr|  qt | jr  q6 W   d S   w r9   )r   rT   	push_text_FlushSentinelr   	end_inputr   r   rQ   rd   r'   r(   _forward_input_task,  s   
zEFallbackSynthesizeStream._try_synthesize.<locals>._forward_input_taskr   r   r   r   r   rn   )r<   r=   rd    r   r   	blingfireSentenceTokenizerr   log_exceptionsr   r   r   r   r   rM   	exceptionr   rj   )rQ   r*   r   r\   r   r   wrapped_ttsr   
input_taskr   r   r'   r   r(   r     sH   	

(

*z(FallbackSynthesizeStream._try_synthesizer   r   c                   s  t   }tdd jjD }|rtd d  |jt jj	jj
ddd |jt d d fd
d}t| }ztjjD ]\}}jj| }|jsW|r)ztjttjB    jD ]}	 |	 qd| rt   |jrtj|j	jj	dnd }
j| tjj jj!j j"j j#ddd2 zE3 d H W }|j$j%&t' }r|(| |
d ur|
)|j$D ]
}|)|j*+  q|j,r|
- D ]
}|)|j*+  qq|)|j$j*+  q6 W  W tj.|I d H  d S  t/y(   |jrd|_j01dt2|dd |3 dkr&t4|j5 d Y  W tj.|I d H  d S Y nw 6| qGt7ddd jjD  dt   |  dtj.|I d H  w )Nc                 s  r   r9   r   r   r'   r'   r(   r:   Q  r>   z0FallbackSynthesizeStream._run.<locals>.<genexpr>r   r   T)r   r-   r3   r   rd   )
segment_idr1   r2   c                    sT   j 2 z3 d H W }  r |  t| tr| rj|  q6  r(   d S d S r9   )	_input_chsend_nowaitr   rT   r   rN   closer   new_input_chrQ   r'   r(   r   _  s   
z:FallbackSynthesizeStream._run.<locals>._forward_input_taskr   r   F)r*   r   r\   r   rs   r   r   zP already synthesized of audio, ignoring the current segment for the tts fallbackr   c                 S  r   r'   r   r   r'   r'   r(   r     r8   z1FallbackSynthesizeStream._run.<locals>.<listcomp>r   r   rn   )8r   rH   rw   rK   r   r   r   r   r   r-   r3   start_segmentr   r   r   rI   r   r   ChanrT   r   r   r   r   r   r   r!   r	   r   r   r   r   r   rJ   r   r   r   r   r   r   r   r   r   r   is_finalr   rj   r   r   ri   r)   r   r   rM   r   r   )rQ   r   r   r   r   r   r   r*   rl   r]   r   r   r   resampled_framer'   r   r(   r   N  s   




&zFallbackSynthesizeStream._runc                   sv   t jtsJ j   sd S jjjj| jd u s&j	 r9d fdd}t
||_d S d S )Nr*   r   r1   r2   c              
     s   zOt jttjB   } D ]}|| q|  j| |dtj	j
dj
jj
jdd2 z3 d H W }q.6 d_td| j d jdt| dd W d S  tyZ   Y d S w )	NTr   r   )r*   r   r   r\   r   r   rs   r   )r   r   rT   r   r   r   r   r   r   r   r   r   r   r   r   rL   rM   r   ri   r)   r   )r*   r   r6   r   
retry_textrQ   rl   r'   r(   r     s8   

zAFallbackSynthesizeStream._try_recovery.<locals>._recover_tts_taskr   )r   r   r+   r   copyrK   rI   r   r    r   r   r   r   r'   r   r(   r     s   
z&FallbackSynthesizeStream._try_recovery)r*   r+   r\   r   r   )
r*   r   r   r   r\   r   r   r   r1   r   r   r   )r#   r$   r%   rv   r&   rF   r|   r   r   r   rr   r'   r'   rR   r(   rb     s   
 
	
6frb   )*
__future__r   r   r   r   collections.abcr   r   r   typingr   r   r   rY   r	   r   r   _exceptionsr   logr   typesr   r   r   r   stream_adapterr   r*   r   r   r   r   r   r   r   rq   r   r)   r+   r^   rb   r'   r'   r'   r(   <module>   s6     


`