+
    PcjN                         R t ^ RIt^ RIt^ RIHtHt ^t]P                  ! 4       t^(t	Rt
]! 4       tR tR tRR ltRR ltR tR	 tR
 tR tR tR# )u  
Audio-piece timing tracer  (ADD-ON, diagnostic only — safe to remove).

Records, per call, two timestamps for every audio piece:

    Alibaba cloud  --recv-->  THIS server  --send-->  bridge  ----->  caller
                   ^ recv gap               ^ send gap        ^ (bridge's own log)

  * record_recv() is called the moment an audio delta ARRIVES from the cloud
    model (in callbacks.py, response.audio.delta).
  * record_send() is called the moment that server SENDS a piece out to the
    phone bridge (in qwen_pipeline_server.py, _sender()).

Comparing the two gap timelines (plus the bridge's own AudioTrace receive log)
tells you WHERE a speech "freeze" is introduced:

  * a big RECV gap  ............... the cloud paused generating (Alibaba side)
  * RECV smooth but SEND gappy .... this server delayed relaying it
                                    (e.g. the event loop was blocked)
  * RECV + SEND both smooth, but
    the bridge still saw a gap ..... the network between here and the bridge

This module is a pure add-on. It touches no call logic; every public function
swallows its own errors and returns fast, so it can never disturb a live call.
View it at  /audio_timing.html  on this server's dashboard.
N)dequeOrderedDicti0u  c                 B   \         P                  V 4      pVf   R\        P                  ! 4       R\        P                  ! 4       R\	        \
        R7      R\	        \
        R7      /pV\         V &   \        \         4      \        8  d   \         P                  RR7       K0  V# )Nstarted_wallstarted_monorecv)maxlensendF)last)	_CALLSgettime	monotonicr   _MAX_EVENTSlen
_MAX_CALLSpopitem)call_idbs   & audio_timing_trace.py_bucketr   +   sq    

7AyDIIKDNN,E-E-	
 w&kJ&NNN&H    c                 V    \         P                  ! 4       V R ,          ,
          R,          # )r        @@)r   r   )r   s   &r   _rel_msr   :   s    NNq00F::r   c                    V '       g   R# \         ;_uu_ 4        \        V 4      pVR,          P                  \        V4      \	        V4      34       RRR4       R#   + '       g   i     R# ; i  \
         d     R# i ; i)z,An audio piece arrived from the cloud model.Nr   _LOCKr   appendr   int	Exceptionr   nbytesr   s   && r   record_recvr#   >   Z    U AfIgaj#f+67 UUU  3   A0 A0 8AA0 A-	'A0 -A0 0A?>A?c                    V '       g   R# \         ;_uu_ 4        \        V 4      pVR,          P                  \        V4      \	        V4      34       RRR4       R#   + '       g   i     R# ; i  \
         d     R# i ; i)z0An audio piece was sent out to the phone bridge.Nr	   r   r!   s   && r   record_sendr'   J   r$   r%   c                 \    . R r!V  F"  w  r4Ve   VP                  W2,
          4       TpK$  	  V# )N)r   )eventsoutprevt_s   &    r   _gapsr.   V   s5    DJJqx   Jr   c                 "   \        V 4      pV Uu. uF  q"\        8  g   K  VNK  	  ppR \        V 4      RV'       d   \        \	        V4      ^4      MRR\        V4      RV '       d#   \        V R,          ^ ,          R,          ^4      /# R/# u upi )pieces
max_gap_ms        gaps_over_threshspan_sr   )r.   GAP_THRESHOLD_MSr   roundmax)r)   gapsgbigs   &   r   _summaryr<   _   s    =D
4d#3311dC
4#f+TeCIq)sCHf%r
1.2	  CF	  5s
   BBc                    V R,          pVR,          pV\         8  d   V\         8  d   R# V\         8  d   W#R,          8  d   R# V\         8  d   W2R,          8  d   R# R# )zCBest-guess of where the worst gap came from (see module docstring).r1   cleangffffff?cloudg      ?zthis-servermixed)r6   )recv_summarysend_summaryrss   &&  r   _verdictrE   j   sU    \"A\"A$4 4#gWr   c                 <    \         ;_uu_ 4        \        P                  4        U Uu. uF2  w  rV \        VR,          4      \        VR,          4      VR,          3NK4  	  pp pRRR4       . pX Fi  w  rrV\	        V4      p\	        V4      pVP                  RV R\        P                  ! R\        P                  ! V4      4      RVRVR\        Wx4      /4       Kk  	  VP                  R	 R
R7       V# u upp i   + '       g   i     L; i  \         d    . u # i ; i)z#Summary row per call, newest first.r   r	   r   Nr   started%Y-%m-%d %H:%M:%Sverdictc                     V R ,          # )r    )cs   &r   <lambda>get_calls.<locals>.<lambda>   s    q|r   T)keyreverse)r   r   itemslistr<   r   r   strftime	localtimerE   sortr    )	cidr   rQ   r*   r   r	   rG   rssss	            r   	get_callsrY   y   s   U#)<<>3#1 4&	?D6OQ~=NO#1  3  (-$Ct$B$BJJ34==)<)-)@B8B+  ). 	+T:
3 U"  	s:   D C88C2
 C8#BD 2C88D	D DDc                     \         ;_uu_ 4        \        P                  V 4      pV'       g    RRR4       R# \        VR,          4      p\        VR,          4      pVR,          pRRR4       R p\	        X4      p\	        X4      pRV R\
        P                  ! R\
        P                  ! X4      4      R	\        R
\        Wg4      RVRVRV! V4      RV! V4      /#   + '       g   i     L}; i  \         d     R# i ; i)z;Full per-piece timeline for one call (recv + send streams).Nr   r	   r   c           
          . R r!V  F@  w  r4Ve	   W2,
          MRpVP                  R\        V^4      R\        V^4      RV/4       TpKB  	  V# )Nr2   t_msgap_msbytes)r   r7   )r)   r*   r+   r,   nbgaps   &     r   rowsget_series.<locals>.rows   s\    D$($4qx#

FE!QK$eCm#R) *    Jr   r   rG   rH   threshold_msrI   rA   rB   )r   r   r   rR   r<   r   rS   rT   r6   rE   r    )r   r   r   r	   rG   ra   rW   rX   s   &       r   
get_seriesrd      s     U

7#A U &	?D&	?D'G 	 d^d^wt}}%8$..:QR,x'BBDJDJ	
 		
) U<  s3   C. CC. -C&A4C. C+	&C. .C=<C=)    )__doc__	threadingr   collectionsr   r   r6   Lockr   r   r   r   r   r   r#   r'   r.   r<   rE   rY   rd   rK   r   r   <module>rj      si   6   *  
 
;		0"r   