o
    GY)j                     @  s   d Z ddlmZ ddlZddlZddlZddlZddlZddlm	Z	 ddl
mZ ddlZeeZedeeddZed	eed
dZedd dvZd"ddZd#ddZd$ddZd%ddZd&d d!ZdS )'zFProbe WAV recording duration from a URL without calling STT providers.    )annotationsN)Optional)urlparsei   MIN_DURATION_PROBE_RANGE_BYTES65536   MIN_DURATION_PROBE_TIMEOUT_S20 MIN_DURATION_PROBE_FULL_FALLBACK1)0falsenopathstrreturnOptional[float]c                 C  s   z4t | d#}| }|dkr	 W d    W dS | t| W  d    W S 1 s-w   Y  W d S  tyG   tt| dd Y S w )Nrbr           i   )waveopengetframerate
getnframesfloat	Exception_wav_duration_from_header_bytesread)r   wfrate r   9/home/aiteam/pcaa-dev/dashboard-backend/wav_probe_util.py_wav_duration_from_path   s   (r!   databytesc           	      C  s\  t | dk s| dd dks| dd dkrdS d}d}d}d}|d t | kr| ||d  }td	| |d |d  d }|d }|| }|d
krw|t | krw|dkrwtd	| |d |d  d }td	| |d |d  d }n|dkr~|}n||d  }|d t | ks(|r|dkr|dur|t| S |r|dkr|dur|t| S dS )zJParse standard PCM WAV header when wave module cannot read a partial file.,   r      s   RIFF      s   WAVENz<Is   fmt    s   data   )lenstructunpackr   )	r"   offsetsample_rate	byte_rate
data_byteschunk_id
chunk_sizechunk_start	chunk_endr   r   r    r   %   s0   ,  "r   urlOptional[bytes]c              
   C  s  t | pd } | dsd S ddtd  i}z+tj| |tdd}|jdv r+|jW S |jd	krBt	rBtj| td
}|jdkrB|jW S W n t
y\ } ztd| | W Y d }~nd }~ww t	rztj| td
}|jdkrp|jW S W d S  t
y } ztd| | W Y d }~d S d }~ww d S )N )zhttp://zhttps://Rangezbytes=0-   T)headerstimeoutstream)      i  )r;   r=   z!WAV probe fetch failed for %s: %sz&WAV probe full fetch failed for %s: %s)r   strip
startswith_PROBE_RANGE_BYTESrequestsget_PROBE_TIMEOUT_Sstatus_codecontent_PROBE_FULL_FALLBACKr   loggerdebug)r5   r:   respexcr   r   r    _fetch_recording_bytes@   s<   



rL   c                 C  sR  t | }|sdS d}zrzMtjdddd}|| |j}W d   n1 s'w   Y  t|}|durWtdt|W W |rUtj	
|rVzt| W S  tyT   Y S w S S W n	 tya   Y nw W |r|tj	
|r|zt| W n% ty{   Y nw n|rtj	
|rzt| W w  ty   Y w w w w t|}|durtdt|S dS )z}
    Return recording duration in seconds, or None when the URL is unreachable
    or the payload is not a readable WAV.
    Nz.wavFz/tmp)suffixdeletedirr   )rL   tempfileNamedTemporaryFilewritenamer!   maxr   osr   existsunlinkOSErrorr   r   )r5   r"   tmp_pathtmpdurationheader_durationr   r   r    probe_wav_duration_from_urlY   sT   
r]   boolc                 C  s(   t t| pd }|jdv ot|jS )z9True when a URL looks like a fetchable http(s) recording.r7   )httphttps)r   r   r?   schemer^   netloc)r5   parsedr   r   r    recording_url_probe_readyy   s   rd   )r   r   r   r   )r"   r#   r   r   )r5   r   r   r6   )r5   r   r   r   )r5   r   r   r^   )__doc__
__future__r   loggingrU   r+   rP   r   typingr   urllib.parser   rB   	getLogger__name__rH   rT   intgetenvrA   rD   lowerrG   r!   r   rL   r]   rd   r   r   r   r    <module>   s&    




 