
    /j%                        S SK Jr  S SKrS SKrS SK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5      5       r " S S5      r " S S\5      rg)    )annotationsN)	dataclass   )utils)logger)SentenceStream	TokenData   )AudioEmitterc                  *    \ rS rSr% S\S'   S\S'   Srg)StreamPacerOptions   floatmin_remaining_audiointmax_text_length N)__name__
__module____qualname____firstlineno____annotations____static_attributes__r       P/app/agent/.venv/lib/python3.13/site-packages/livekit/agents/tts/stream_pacer.pyr   r      s    r   r   c                  2    \ rS rSrSSS.S	S jjrS
S jrSrg)SentenceStreamPacer   g      @i,  r   r   c               "    [        UUS9U l        g)a  
Controls the pacing of text sent to TTS. It buffers sentences and decides when to flush
based on remaining audio duration. This may reduce waste from interruptions and improve
speech quality by sending larger chunks of text with more context.

Args:
    min_remaining_audio: Minimum remaining audio duration (seconds) before sending next batch.
    max_text_length: Maximum text length sent to TTS at once.
r   N)r   _options)selfr   r   s      r   __init__SentenceStreamPacer.__init__   s     + 3+
r   c                *    [        U R                  XS9$ )N)optionssent_streamaudio_emitter)StreamPacerWrapperr!   )r"   r'   r(   s      r   wrapSentenceStreamPacer.wrap#   s    !MM{
 	
r   )r!   N)r   r   r   r   returnNone)r'   r   r(   r   r,   r)   )r   r   r   r   r#   r*   r   r   r   r   r   r      s    7:SV 

r   r   c                  x   ^  \ rS rSr        S
U 4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	rU =r$ )r)   )   c                 >^  [         TT ]  5         UT l        UT l        UT l        ST l        ST l        / T l        [        R                  " 5       T l
        S T l        [        R                  " T R                  5       5      T l        [        R                  " T R                  5       5      T l        T R                   R#                  U 4S j5        g )NFc                8   > TR                   R                  5       $ N)	_event_chclose)_r"   s    r   <lambda>-StreamPacerWrapper.__init__.<locals>.<lambda>>   s    T^^5I5I5Kr   )superr#   _sent_streamr!   _audio_emitter_closing_input_ended
_sentencesasyncioEvent_wakeup_event_wakeup_timercreate_task
_recv_task_recv_atask
_send_task_send_ataskadd_done_callback)r"   r'   r(   r&   	__class__s   `   r   r#   StreamPacerWrapper.__init__*   s     	'+!%'$]]_9="..t/@A"..t/@A**+KLr   c                :    U R                   R                  U5        g r2   )r9   	push_text)r"   texts     r   rK   StreamPacerWrapper.push_text@   s    ##D)r   c                8    U R                   R                  5         g r2   )r9   flushr"   s    r   rO   StreamPacerWrapper.flushC   s    !r   c                    U R                   R                  5         SU l        U R                  R                  R
                  (       a"  SU l        U R                  R                  5         g g NT)	r9   	end_inputr<   r:   _dst_chclosedr;   r@   setrP   s    r   rT   StreamPacerWrapper.end_inputF   sO    ##% &&-- DM""$ .r   c                v  #    U R                   R                  5       I S h  vN   SU l        U R                  (       a!  U R                  R	                  5         S U l        U R
                  R                  5         [        R                  R                  U R                  U R                  5      I S h  vN   g  N N7frS   )r9   acloser;   rA   cancelr@   rW   r   aiocancel_and_waitrD   rF   rP   s    r   rZ   StreamPacerWrapper.acloseN   s     &&(((%%'!%D ii''(8(8$:J:JKKK 	) 	Ls"   B9B5BB9/B70B97B9c                N  #     U R                     S h  vN nU R                  R                  UR                  5        U R                  R                  5         MJ   NE
 SU l        U R                  R                  5         g ! SU l        U R                  R                  5         f = f7frS   )r9   r=   appendtokenr@   rW   r<   )r"   evs     r   rC   StreamPacerWrapper._recv_taskX   s     	% -- )b&&rxx0""&&()- !%D""$ !%D""$s=   B%A? AAAAA? AA? "B%?#B""B%c                n  #    SnSnSnSnSnSnU R                   (       Gd  U R                  R                  5       I S h  vN   U R                  R                  5         U R                  (       a!  U R                  R                  5         S U l        U R                   (       d"  U R                  (       a  U R                  (       d  g U R                  R                  5       n[        R                  " 5       nUS:  a  US:X  a  UnX-
  S:  a  X7:  a  SnO	U(       a  SnUnUnUS:  a  X-   U-
  OSn	U(       d   U(       a  XR                  R                  ::  a  / n
U R                  (       ao  U
R                  U R                  R                  S5      5        U(       d*  [        S U
 5       5      U R                  R                   :  a  OU R                  (       a  Mo  U
(       aP  SR#                  U
5      nU R$                  R'                  [)        US95        [*        R,                  " S	XS
.S9  SnSnSnU(       a
  U(       d  SnO"[/        SXR                  R                  -
  5      n[0        R2                  " 5       R5                  XR                  R6                  5      U l        U R                   (       d  GM  g g  GNt7f)Ng        TFg?r   c              3  8   #    U  H  n[        U5      v   M     g 7fr2   )len).0ss     r   	<genexpr>0StreamPacerWrapper._send_task.<locals>.<genexpr>   s     5u!s1vvus    )ra   zsent text to tts)rL   remaining_audio)extrag?g      ?)r;   r@   waitclearrA   r[   r<   r=   r:   pushed_durationtimer!   r   r`   popsumr   joinr3   send_nowaitr	   r   debugmaxr>   get_event_loop
call_laterrW   )r"   audio_start_timefirst_sentenceprev_audio_durationprev_check_timegeneration_startedgeneration_stoppedaudio_duration	curr_timerl   batchrL   	wait_times                r   rE   StreamPacerWrapper._send_taska   s6     """---$$))+++$$&!!""))+%)"}}!2!24??!00@@BN		I#(8C(?#,  *c1&7)-&')-&&4#"+ BRTWAW 1I=]`  "--:[:['[#%ooLL!4!4Q!78&5u559V9VV ooo 88E?DNN..yt/DELL*'+P */&).&%*N "*<	_}}7X7X%XY	!(!7!7!9!D!D--11"Do ---+s   <J5J2FJ5CJ50J5)
r:   r;   r<   r!   rD   rF   r9   r=   r@   rA   )r'   r   r(   r   r&   r   r,   r-   )rL   strr,   r-   )r,   r-   )r   r   r   r   r#   rK   rO   rT   rZ   rC   rE   r   __classcell__)rH   s   @r   r)   r)   )   sY    M#M $M
 $M 
M,*"%L%C Cr   r)   )
__future__r   r>   rq   dataclassesr    r   logr   tokenizer   r	   ttsr   r   r   r)   r   r   r   <module>r      sN    "   !   0    

 
,{ {r   