
    /j4C                       S SK Jr  S SKrS SKrS SKrS SKrS SKrS SKJr  S SK	J
r
  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  SS jr " S S5      r " S S\R2                  5      r " S S5      r " S S5      rg)    )annotationsN)AsyncIterator)ThreadPoolExecutor)cast)rtc   )logger   )aio)AudioByteStreamc                v    U (       d  gU R                  5       n SSSSSSSSSSSSSSS	.nUR                  U 5      $ )
u   Return the libav *container* short‑name for a given MIME‑type.

If *mime* is *None* or not recognised, return *None* so that PyAV will
fall back to auto‑detection.
Nmp3aacflacwavoggwebmmp4)z
audio/mpegz	audio/mp3zaudio/x-mpegz	audio/aaczaudio/x-aacz
audio/flaczaudio/x-flacz	audio/wavz
audio/wavezaudio/x-wavz
audio/opusz	audio/oggz
audio/webmz	audio/mp4)lowerget)mime_TABLEs     T/app/agent/.venv/lib/python3.13/site-packages/livekit/agents/utils/codecs/decoder.py_mime_to_av_formatr   $   sW     ::<DF  ::d    c                  R    \ rS rSrSrSrSS jrSS jrSSS jjrSS jr	SS jr
S	rg
)StreamBufferB   zo
A thread-safe buffer that behaves like an IO stream.
Allows writing from one thread and reading from another.
i  P c                    [         R                  " 5       U l        [        R                  " 5       U l        [        R                  " U R
                  5      U l        SU l        SU l	        SU l
        SU l        g )NFr   )ioBytesIO_bio	threadingLock_lock	Condition_data_available_eof_closed
_write_pos	_read_posselfs    r   __init__StreamBuffer.__init__J   sP    JJL	^^%
(224::>	r   c                B   U R                      U R                  R                  U R                  5        U R                  R	                  U5        U R                  R                  5       U l        U R                   R                  5         SSS5        g! , (       d  f       g= f)z.Write data to the buffer from a writer thread.N)r'   r"   seekr*   writetell
notify_all)r-   datas     r   r2   StreamBuffer.writeS   s_    !!IINN4??+IIOOD!"iinn.DO  ++-	 "!!s   A:B
Bc                   US:X  a  gU R                       U R                  (       a
   SSS5        gU R                  U R                  -
  nUS:  Ga=  U R                  R                  U R                  5        US:  a  U R                  R                  U5      nO$U R                  R                  [        X5      5      nU R                  R                  5       U l        U R                  U R                  :  a  U R                  R                  5       n[        R                  " U5      U l        U R                  R                  S[        R                  5        U R                  R                  5       U l        SU l        U(       a  UOSsSSS5        $ U R                  (       a
   SSS5        gU R                   R                  5         GM  ! , (       d  f       g= f)z-Read data from the buffer in a reader thread.r   r   N)r'   r)   r*   r+   r"   r1   readminr3   _COMPACT_THRESHOLDr    r!   SEEK_ENDr(   wait)r-   size	availabler5   	remainings        r   r8   StreamBuffer.read[   sA   19!!<< "!
 !OOdnn<	q=IINN4>>2ax#yy~~i8#yy~~c$.BC%)YY^^%5DN~~)@)@@$(IINN$4	$&JJy$9			q"++6*.))..*:)*#'4S+ "!. 991 "!4 $$))+3  "!s   GEGG)G
Gc                    U R                      SU l        U R                   R                  5         SSS5        g! , (       d  f       g= f)z)Signal that no more data will be written.TN)r'   r(   r4   r,   s    r   	end_inputStreamBuffer.end_input|   s0    !!DI  ++- "!!s	   "8
Ac                    U R                      SU l        U R                   R                  5         U R                  R	                  5         S S S 5        g ! , (       d  f       g = f)NT)r'   r)   r4   r"   closer,   s    r   rE   StreamBuffer.close   s>    !!DL  ++-IIOO "!!s   <A
A )r"   r)   r'   r(   r%   r+   r*   NreturnNoner5   bytesrH   rI   ))r=   intrH   rK   )__name__
__module____qualname____firstlineno____doc__r:   r.   r2   r8   rB   rE   __static_attributes__ r   r   r   r   B   s)    
 ).,B.r   r   c                  (    \ rS rSrSrSrSrSrSrSr	g)		_WavState   r      r
   r      rT   N)
rN   rO   rP   rQ   RIFF_HEADERCHUNK_HEADERFMT_DATASKIP_CHUNK_DATA	STREAMINGrS   rT   r   r   rV   rV      s    KLHOIr   rV   c                      \ rS rSrSrS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g)_WavInlineDecoder   u  Incremental WAV decoder that runs entirely on the event loop (no thread).

Processes WAV bytes via a state machine:
RIFF_HEADER → CHUNK_HEADER → FMT_DATA/SKIP_CHUNK_DATA → STREAMING.
Once in STREAMING state, subsequent push() calls feed bytes directly to
AudioByteStream → optional resampler → output channel.

Each push() may contain a complete WAV file (with its own headers). When a
new RIFF header is detected while already streaming, the current stream is
flushed and the state machine resets to parse the new file's headers.
   RIFFc                    Xl         X l        [        R                  U l        [        5       U l        SU l        SU l        SU l	        S U l
        S U l        SU l        SU l        g )N   r   )
_output_ch_sample_raterV   rZ   _state	bytearray_hdr_buf_need_skip_remaining_chunk_size_bstream
_resampler_wave_channels
_wave_rate)r-   	output_chsample_rates      r   r.   _WavInlineDecoder.__init__   s[    
 $'++!
  1559r   c                @   U R                   [        R                  :X  aU  [        U5      S:  a4  US S U R                  :X  a!  U R                  5         U R                  5         OU R                  U5        g [        U5      nSnU[        U5      :  Ga  U R                   [        R                  :X  a  U R                  X#5      nOU R                   [        R                  :X  a  U R                  X#5      nOU R                   [        R                  :X  a  U R                  X#5      nOkU R                   [        R                  :X  a  U R!                  X#5      nO;U R                   [        R                  :X  a  U R                  [#        X#S  5      5        g U[        U5      :  a  GM  g g )NrY   r   )rg   rV   r^   len_RIFF_MAGIC_flush_current_reset_state	_push_pcm
memoryviewrZ   _consume_riffr[   _consume_chunk_headerr\   _consume_fmt_datar]   _consume_skiprK   )r-   r5   bufposs       r   push_WavInlineDecoder.push   s4   ;;)---4yA~$r(d.>.>">##%!!#t$CHn{{i333((2	 6 6600:	 2 22,,S6	 9 99((2	 3 33uSY/0 CHnnr   c                $    U R                  5         g N)rw   r,   s    r   flush_WavInlineDecoder.flush   s    r   c                   U R                   b  U R                   R                  5       nU R                  b  U H@  nU R                  R                  U5       H  nU R                  R                  U5        M      MB     U R                  R                  5        H0  nUR                  S:  d  M  U R                  R                  U5        M2     gU H  nU R                  R                  U5        M      gg)z@Flush AudioByteStream and resampler for the current WAV segment.Nr   )rm   r   rn   r   re   send_nowaitsamples_per_channel)r-   r?   frame	resampleds       r   rw    _WavInlineDecoder._flush_current   s    ==$++-I*&E%)__%9%9%%@	33I> &A ' "__224E001433E: 5 'EOO//6 ' %r   c                    [         R                  U l        U R                  R	                  5         SU l        SU l        SU l        SU l        SU l	        SU l
        SU l        g)z0Reset the state machine to parse a new WAV file.rd   r   N)rV   rZ   rg   ri   clearrj   rk   rl   rm   rn   ro   rp   r,   s    r   rx   _WavInlineDecoder._reset_state   sS    ++
 r   c                   [        U R                  [        U R                  5      -
  [        U5      U-
  5      nU R                  R	                  XX#-    5        X#-  n[        U R                  5      U R                  :  a  U$ U R                  S S S:w  d  U R                  SS S:w  a"  [        S[        U R                  5      < 35      eU R                  R                  5         SU l        [        R                  U l
        U$ )NrY   rb      rd   s   WAVEz%Invalid WAV file: missing RIFF/WAVE: )r9   rj   ru   ri   extend
ValueErrorrK   r   rV   r[   rg   r-   r   r   takes       r   r{   _WavInlineDecoder._consume_riff   s    4::DMM 22CHsNCSsz23t}}

*J==!'4==2+>'+IDU4==EYD\]^^
,,
r   c                z   [        U R                  [        U R                  5      -
  [        U5      U-
  5      nU R                  R	                  XX#-    5        X#-  n[        U R                  5      U R                  :  a  U$ [
        R                  " S[        U R                  S S 5      5      u  pEU R                  R                  5         XPl	        US:X  a  XPl        [        R                  U l        U$ US:X  a'  U R                  5         [        R                  U l        U$ XPl        [        R                   U l        U$ )Nz<4sIr   s   fmt s   data)r9   rj   ru   ri   r   structunpackrK   r   rl   rV   r\   rg   _init_streamingr^   rk   r]   )r-   r   r   r   chunk_id
chunk_sizes         r   r|   '_WavInlineDecoder._consume_chunk_header   s    4::DMM 22CHsNCSsz23t}}

*J%}}VU4==!;L5MN%w#J#,,DK 
    "#--DK 
 $. #33DK
r   c                   [        U R                  [        U R                  5      -
  [        U5      U-
  5      nU R                  R	                  XX#-    5        X#-  n[        U R                  5      U R                  :  a  U$ [        U R                  S U R                   5      n[        R                  " SUS S 5      u  pVn[        U5      S:  a2  [        R                  " SUSS 5      S   nUS:w  a  [        SU S35      eUS	:w  a  [        S
U 35      eX`l
        Xpl        U R                  R                  5         SU l        [        R                  U l        U$ )Nz<HHIr      z<H   r   z!Unsupported WAV bits per sample: z (only 16-bit PCM supported)rX   zUnsupported WAV audio format: )r9   rj   ru   ri   r   rK   rl   r   r   r   ro   rp   r   rV   r[   rg   )	r-   r   r   r   fmtaudio_formatchannelsratebits_per_samples	            r   r}   #_WavInlineDecoder._consume_fmt_data  s5   4::DMM 22CHsNCSsz23t}}

*JDMM"4D$4$456'-}}VS!W'E$s8r>$mmD#b*=a@O"$ 77H23  1=l^LMM&
,,
r   c                   [        U R                  [        U5      U-
  5      nU =R                  U-  sl        X#-  nU R                  S:X  a6  U R                  R	                  5         SU l        [        R                  U l        U$ )Nr   r   )	r9   rk   ru   ri   r   rj   rV   r[   rg   r   s       r   r~   _WavInlineDecoder._consume_skip+  sk    4''SC8$1$MM!DJ#00DK
r   c                D   U R                   S:X  a  [        S5      e[        U R                   U R                  S9U l        U R
                  bU  U R
                  U R                   :w  a:  [        R                  " U R                   U R
                  U R                  S9U l        g g g )Nr   z-Invalid WAV file: data chunk before fmt chunk)rr   num_channels)
input_rateoutput_rater   )	rp   r   r   ro   rm   rf   r   AudioResamplerrn   r,   s    r   r   !_WavInlineDecoder._init_streaming7  s    ??aLMM'd6I6I
 (T->->$//-Q!00?? --!00DO .R(r   c                v   U R                   c   eU R                  b`  U R                   R                  U5       H@  nU R                  R                  U5       H  nU R                  R	                  U5        M      MB     g U R                   R                  U5       H  nU R                  R	                  U5        M      g r   )rm   rn   r   re   r   )r-   r5   r   r   s       r   ry   _WavInlineDecoder._push_pcmE  s    }}(((??&++D1!%!5!5e!<IOO//	: "= 2 ++D1++E2 2r   )rm   rl   ri   rj   re   rn   rf   rk   rg   ro   rp   N)rq   zaio.Chan[rtc.AudioFrame]rr   
int | NonerH   rI   rJ   rG   )r   rz   r   rM   rH   rM   )rN   rO   rP   rQ   rR   rv   r.   r   r   rw   rx   r{   r|   r}   r~   r   ry   rS   rT   r   r   r`   r`      sa    
 K+   
	(27
,43r   r`   c                  ~    \ rS rSrSrS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rg)AudioStreamDecoderiP  zA class that can be used to decode audio stream into PCM AudioFrames.

Decoders are stateful, and it should not be reused across multiple streams. Each decoder
is designed to decode a single stream.
i  rX   N)rr   r   formatc                  Xl         SU l        US:X  a  SU l        U(       a  UR                  5       OS U l        [	        U R                  5      U l        U R
                  S:H  U l        [        R                  [        R                     " 5       U l        SU l        SU l        [        R                  " 5       U l        S U l        S U l        S U l        g )Nmonor
   stereor   F)rf   _layoutr   
_mime_typer   
_av_format_is_wavr   Chanr   
AudioFramere   r)   _startedasyncioget_event_loop_loop
_input_buf	_executor_wav_decoder)r-   rr   r   r   s       r   r.   AudioStreamDecoder.__init__W  s     (1#DL,2&,,.,T__=%/((3>>24++-
 0448 7;r   c                   U R                   (       aV  U R                  c%  [        U R                  U R                  5      U l         U R                  R                  U5        SU l        g U R                  c  [        5       U l        [        SSS9U l        U R                  R!                  U5        U R                  (       d8  SU l        U R"                  R%                  U R                  U R&                  5        g g ! [         aK    U R                  (       d7  [        R                  " S5        U R                  R                  5         SU l         g f = f)Nzerror decoding WAV audioTrX   AudioDecoder)max_workersthread_name_prefix)r   r   r`   re   rf   r   	Exceptionr)   r	   	exceptionrE   r   r   r   r   r   r2   r   run_in_executor_decode_loop)r-   chunks     r   r   AudioStreamDecoder.pusht  s    <<  ($5dootGXGX$Y!!!&&u- !DM??"*nDO/AR`aDNe$}} DMJJ&&t~~t7H7HI   ||$$%?@OO))+#'DLs   C8 8AEEc                   U R                   (       ae  U R                  b,  U R                  (       d   U R                  R                  5         U R                  (       d  U R                  R                  5         g U R                  b  U R                  R                  5         U R                  (       d  U R                  R                  5         g g ! [         a    [
        R                  " S5         Nf = f)Nzerror flushing WAV audio)r   r   r)   r   r   r	   r   re   rE   r   rB   r   r,   s    r   rB   AudioStreamDecoder.end_input  s    <<  ,T\\A%%++- <<%%'??&OO%%'}}OO!!#  ! A$$%?@As   C  C.-C.c                   S nS n [         R                  " U R                  SU R                  SSSSSSSSS.S	9nU=R                  [        [        [         R                  R                  R                  R                  [         R                  R                  R                  R                  -  5      -  sl        [        UR                  R                  5      S
:X  a  [        S5      eUR                  R                  S
   nU R                   c  U R"                  b*  [         R$                  " SU R"                  U R                   S9nUR'                  U5       H  nU R(                  (       aI    U R*                  R-                  U R.                  R0                  5        U(       a  UR1                  5         g g U(       a  UR3                  U5      nOU/nU H  nU R5                  U5        M     M     U(       a:  U R(                  (       d)  UR3                  S 5       H  nU R5                  U5        M     U R*                  R-                  U R.                  R0                  5        U(       a  UR1                  5         g g ! [6         a    [8        R:                  " S5         Njf = f! U R*                  R-                  U R.                  R0                  5        U(       a  UR1                  5         f f = f)Nr   320znobuffer+flush_packets	low_delaydirect)	probesizeanalyzedurationfflagsflagsreorder_queue_size	max_delay	avioflags)moder   buffer_sizeoptionsr   zno audio stream founds16)r   layoutr   zerror decoding audio)avopenr   r   r   r   rM   	containerFlags	no_buffervalueflush_packetsru   streamsaudior   rf   r   r   decoder)   r   call_soon_threadsafere   rE   resample_emit_av_framer   r	   r   )r-   r   	resampleraudio_streamr   framesfs          r   r   AudioStreamDecoder._decode_loop  sC   8<	.2	7	"!%'*6(*-!$!)I  OOtR\\''1177",,:L:L:Z:Z:`:``  O 9$$**+q0 !899$,,2215L   ,0H-- D<M<M	 #)),7<<$ JJ++DOO,A,AB! # &//6F#WFA''*   8 "++D1A''* 2 JJ++DOO,A,AB! 	  	534	5 JJ++DOO,A,AB! s,   E#I4 1A;I4 4 JJ JJ A	K#c           
     :   U R                   R                  U R                  R                  [        R
                  " UR                  5       R                  5       [        UR                  R                  5      [        UR                  5      UR                  S95        g )N)r5   r   rr   r   )r   r   re   r   r   r   
to_ndarraytobytesru   r   r   rM   rr   samples)r-   r   s     r   r   !AudioStreamDecoder._emit_av_frame  sd    

''OO''NN\\^++- !2!23.$%II		
r   c                    U $ r   rT   r,   s    r   	__aiter__AudioStreamDecoder.__aiter__  s    r   c                R   #    U R                   R                  5       I S h  vN $  N7fr   )re   	__anext__r,   s    r   r   AudioStreamDecoder.__anext__  s     __..0000s   '%'c                T  #    U R                   (       a  g U R                  5         SU l         U R                  b  U R                  R                  5         U R                  (       d  g U R
                    S h  vN nM   N
 U R                  b  U R                  R                  SSS9  g g 7f)NTF)r<   cancel_futures)r)   rB   r   rE   r   re   r   shutdown)r-   _s     r   acloseAudioStreamDecoder.aclose  s     <<??&OO!!#}} 	!	 >>%NN##t#D &s*   A/B(1A>5A<6A>9B(<A>>*B()r   r)   r   r   r   r   r   r   re   rf   r   r   )rr   r   r   r   r   
str | None)r   rK   rH   rI   rG   )r   zav.AudioFramerH   rI   )rH   zAsyncIterator[rtc.AudioFrame])rH   zrtc.AudioFrame)rN   rO   rP   rQ   rR   r.   r   rB   r   r   r   r   r  rS   rT   r   r   r   r   P  s[     #(#$!;  ; !	;
 ;:J.$ :"x	
1Er   r   )r   r  rH   r  )
__future__r   r   enumr    r   r#   collections.abcr   concurrent.futuresr   typingr   r   av.containerlivekitr   logr	    r   r   r   r   r   IntEnumrV   r`   r   rT   r   r   <module>r     sq    #   	   ) 1  	     #<D DN |3 |3~iE iEr   