o
    ui4                     @   s  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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mZ dd Zdd Zd	d
 Zdd Zdd Zdd Zdd Zdd Zdd Zedd Zedd Zedd Z dd Z!	!d$d"d#Z"dS )%    )ThreadPoolExecutorN)AudioSegment)Loggertime_loggerc                 C   s   t j| st|  d|  dt| d#}zt|}W n tjjy/ } zt	dd}~ww W d   |S 1 s;w   Y  |S )z
    Load configuration from a JSON file.

    Args:
        cfg_path (str): Path to the configuration file.

    Returns:
        dict: Configuration dictionary.
    zI not found. Please copy, configure, and rename `config.json.example` to `z`.rznPlease finish the `// TODO:` in the `config.json` file before running the script. Check README.md for details.N)
ospathexistsFileNotFoundErroropenjsonloaddecoderJSONDecodeError	TypeError)cfg_pathfcfge r   5/home/ubuntu/sommelier/podcast-pipeline/utils/tool.pyload_cfg   s$   

r   c                 C   s   t | || dS )zWrite numpy array to WAV file.N)sfwrite)r   srxr   r   r   	write_wav1   s   r   c              
   C   s   z+|j tjkrt|tt| d }t| ||j jdd}|j| dd W dS  t	yF } zt
| t
d W Y d}~dS d}~ww )zConvert numpy array to MP3.i     )
frame_ratesample_widthchannelsmp3)formatz Error: Failed to write MP3 file.N)dtypenpint16maxabsr   tobytesitemsizeexport	Exceptionprint)r   r   r   audior   r   r   r   	write_mp36   s   r.   c                 C   sZ   g }t | D ]#\}}}d|v rq|D ]}d|v rq|dr)|t j|| qq|S )z Get all audio files in a folder.
_processed.temp).mp3.wavz.flacz.m4az.aacr   walkendswithappendr   join)folder_pathaudio_filesroot_filesfiler   r   r   get_audio_filesI      
r>   c                 C   sZ   g }t | D ]#\}}}d|v rq|D ]}d|v rq||r)|t j|| qq|S )z6Get specific files with a given extension in a folder.r/   r0   r3   )r8   extr9   r:   r;   r<   r=   r   r   r   get_specific_filesW   r?   rA   c              	   C   s   t |dB}dd }t| D ]0\}}||d  d |||d  d||d  d ||d	  d
|d  d qW d   dS 1 sJw   Y  dS )zExport ASR result to SRT file.wc                 S   s*   t dt | dt| d d d S )Nz%H:%M:%S,i  03d)timestrftimegmtimeint)secondsr   r   r   format_timei   s   z"export_to_srt.<locals>.format_timer   
startz --> endspeaker: textz

N)r   	enumerater   )
asr_result	file_pathr   rJ   idxsegmentr   r   r   export_to_srte   s    "rV   c                  C   s  t  } dtjvr| d ntjd }| d|  tj s(| d dS tj	 }| 
d| d t|D ]}tj|}| 
d| d	|  q:| 
d
ttjj   tjj sh| d dS | 
d t }| 
d|  d|vr| d dS )z9Detect if GPU is available and print related information.CUDA_VISIBLE_DEVICESz6ENV: CUDA_VISIBLE_DEVICES not set, use default settingzENV: CUDA_VISIBLE_DEVICES = z?Torch CUDA: No GPU detected. torch.cuda.is_available() = False.FzTorch CUDA: Detected z GPUs.z * GPU rO   zTorch: CUDNN version = zTorch: CUDNN is not available.zTorch: CUDNN is available.zORT: Available providers: CUDAExecutionProviderzORT: CUDAExecutionProvider is not available. Please install a compatible version of ONNX Runtime. See https://onnxruntime.ai/docs/execution-providers/CUDA-ExecutionProvider.htmlT)r   
get_loggerr   environinfotorchcudais_availableerrordevice_countdebugrangeget_device_namestrbackendscudnnversionortget_available_providerswarning)loggergpu_idnum_gpusigpu_nameort_providersr   r   r   
detect_gpuw   s2   






rq   c               
   C   sj   t  } ztjddd}t|  }W |S  ty4 } z| dt	|  d}W Y d}~|S d}~ww )zGet GPU nums by nvidia-smi.znvidia-smi -L | wc -lT)shellz(Error occurred while getting GPU count:    N)
r   rY   
subprocesscheck_outputrH   decodestripr+   r_   rd   )rk   result
gpus_countr   r   r   r   get_gpu_nums   s   rz   c                 C   s   dt jv r| dt jd   n| d dt jv r'| dt jd   n| d dt jv r>| dt jd  d	 n| d
 t d  }| d|  t jd }t jdd}| d| d|  dS )zCheck environment variables.
http_proxyzENV: http_proxy = zENV: http_proxy not sethttps_proxyzENV: https_proxy = zENV: https_proxy not setHF_ENDPOINTzENV: HF_ENDPOINT = z., if downloading slow, try `unset HF_ENDPOINT`zENV: HF_ENDPOINT not sethostnamez
HOSTNAME: PATHLD_LIBRARY_PATH zENV: PATH = z, LD_LIBRARY_PATH = N)r   rZ   r[   popenreadrw   ra   get)rk   r~   environ_pathenviron_ld_libraryr   r   r   	check_env   s    






r   c                    s    d  d  t jdd  fddtdd&fd	d
t|D }tj|t|ddD ]}|  q4W d   dS 1 sFw   Y  dS )$Export segmented audio to MP3 files.sample_ratewaveformTexist_okc                    sf   t |d  t |d  }} || }t|} d|  d}tj|}t|| d S )NrL   rM   r;   r1   )rH   librosato_monor   r   r7   r.   )rT   rU   rL   rM   split_audioout_fileout_path)r-   	file_namer8   r   r   r   process_segment   s   "
z&export_to_mp3.<locals>.process_segmentH   max_workersc                       g | ]\}}  ||qS r   submit.0rT   rU   executorr   r   r   
<listcomp>       z!export_to_mp3.<locals>.<listcomp>Exporting to MP3totaldescN)r   makedirsr   rQ   tqdmlenrx   )r-   rR   r8   r   futuresfuturer   )r-   r   r   r8   r   r   r   export_to_mp3   s   	


"r   c                    s   | d | d t jdd fddtddA  fd	d
t|D }tj|t|ddD ]!}z|  W q4 tyU } ztd|  W Y d}~q4d}~ww W d   dS 1 saw   Y  dS )r   r   r   Tr   c           	         s   d }d|v r| ddr|d }tj|rt|\}}n1d|v r-|d d ur-|d }n"t|d  }t|d  }t|t}t||}|| }t|dkrWd S t	
|}  d| d	d
}tj|}t|| d S )Ndenoised_audio_pathflowse_denoisedFenhanced_audiorL   rM   r   r;   05dr1   )r   r   r   r	   r   r   rH   minr   r   r   r7   r.   )	rT   rU   r   denoised_pathr;   rL   rM   r   r   )r   r8   full_waveformr   r   r   r      s&   


z*export_to_mp3_new.<locals>.process_segmentr   r   c                    r   r   r   r   r   r   r   r     r   z%export_to_mp3_new.<locals>.<listcomp>r   r   zError exporting segment: N)	r   r   r   rQ   r   r   rx   r+   r,   )r-   rR   r8   r   r   r   r   r   )r   r   r8   r   r   r   r   export_to_mp3_new   s&   '

"r   c                 C   s   | d }| d } t j|dd ttj|ddD ]5\}}t|d | t|d | }}| || }	t|	}	| d	| d
}
t j||
}t	|||	 qdS )z$Export segmented audio to WAV files.r   r   Tr   zExporting to WAV)r   rL   rM   r;   r2   N)
r   r   rQ   r   rH   r   r   r   r7   r   )r-   rR   r8   r   r   rT   rU   rL   rM   r   r   r   r   r   r   export_to_wav$  s   "
r   c                 C   s   t dd| }t|}|S )z
    Get the number of characters in the text.

    Args:
        text (str): Input text.

    Returns:
        int: Number of characters in the text.
    u"   [,.!?\"'，。！？“”‘’ ]r   )resubr   )rP   cleaned_text
char_countr   r   r   get_char_count5  s   r            c                 C   sJ  g }g }g }| D ]}t |d }	|d |d  }
|	dkr#||
|	  qt|dkrGt|d}t|d}|| }|d|  }|d|  }ndtj}}t| D ]O\}}|d |d  }
|d }t |d }	|	dkrp|
|	 }nd}|||
f ||
  kr|krn qQ||kr|	|kr||  kr|krn qQ|||
f qQ||fS )	a  
    Reading the proviced json, calculate and return the audio ID and their duration that meet the given filtering criteria.

    Args:
        data: JSON.
        min_duration: Minimum duration of the audio in seconds.
        max_duration: Maximum duration of the audio in seconds.
        min_dnsmos: Minimum DNSMOS value.
        min_char_count: Minimum number of characters.

    Returns:
        valid_audio_stats: A list containing tuples of audio ID and their duration.
    rP   rM   rL   r      K   g      ?dnsmos)r   r6   r   r$   
percentileinfrQ   )datamin_durationmax_duration
min_dnsmosmin_char_countall_audio_statsvalid_audio_statsavg_durationsentryr   durationq1q3iqrlower_boundupper_boundrT   r   avg_char_durationr   r   r   calculate_audio_statsE  s>   
r   )r   r   r   r   )#concurrent.futuresr   r   r   r   numpyr$   rE   r\   pydubr   	soundfiler   onnxruntimerh   r   rt   r   utils.loggerr   r   r   r   r.   r>   rA   rV   rq   rz   r   r   r   r   r   r   r   r   r   r   <module>   s@   &

@
