o
    Wli%                     @   s   d 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	m
Z
mZmZ ddlmZ ddlmZmZ ddlmZmZ dd	lmZmZ e ZdddZedkrXe  dS dS )z)Flask web server with HTTP API for Piper.    N)Path)AnyDictListOptional)urlopen)Flaskrequest   )
PiperVoiceSynthesisConfig)VOICES_JSONdownload_voicereturnc            	         sz  t  } | jdddd | jdtddd | jd	d
ddd | jddtdd | jddtdd | jddtdd | jddddtdd | jdddd  | jd!d"td#d$d | jd%d&d'tt gd(d) | jd*d+d,d- | jd.dd/d  |   t	j
 jrt	jnt	jd0 t   js jd1  _t jt j s j} jD ]}t|| d2 }td3| | r| nq std4 d5jd2tj jd6itt}|jd7d8gd9d:tttf f fd;d<}|jd=d8gd9d:tttf fd>d?}|jd@dAgd9d:tffdBdC}|jdDdAgd9d:tf fdEdF}|j j  j!dG dHS )IzRun HTTP server.z--hostz0.0.0.0zHTTP server host)defaulthelpz--porti  zHTTP server port)typer   r   z-mz--modelTzPath to Onnx model file)requiredr   z-sz	--speakerzId of speaker (default: 0))r   r   z--length-scalez--length_scalezPhoneme lengthz--noise-scalez--noise_scalezGenerator noisez--noise-w-scalez--noise_w_scalez	--noise-wz	--noise_wzPhoneme width noisez--cuda
store_truezUse GPU)actionr   z--sentence-silencez--sentence_silenceg        z&Seconds of silence after each sentencez
--data-dirz
--data_dirappendzJData directory to check for downloaded models (default: current directory))r   r   r   z--download-dirz--download_dirz1Path to download voices (default: first data dir))r   z--debugzPrint DEBUG messages to console)levelr   .onnxzChecking '%s'zUnable to find voice: z (use piper.download_voices)Zuse_cudaz/voicesGET)methodsr   c               	      s   i } t  dg} jD ]}t |dD ]}t | d}| r(|| qq|D ]+}|jd}|| v r9q,t|ddd}t	|| |< W d   n1 sRw   Y  q,| S )zList downloaded voices.

        Outputs a JSON object with the format:
        {
          "<voice name>": { <voice config> },
          ...
        }

        for each voice in your data directories.
        z.jsonz*.onnxz
.onnx.jsonrzutf-8)encodingN)
r   data_dirglobexistsr   namerstripopenjsonload)Zvoices_dictZconfig_pathsr   Z	onnx_pathZconfig_pathmodel_idconfig_file)args
model_path K/home/kim/smarthome/.venv/lib/python3.10/site-packages/piper/http_server.py
app_voicesj   s$   

zmain.<locals>.app_voicesz/all-voicesc                  S   s6   t t} t| W  d   S 1 sw   Y  dS )zList all Piper voices.

        Outputs voices.json from the piper-voices repo on HuggingFace.
        See: https://huggingface.co/rhasspy/piper-voices
        N)r   r   r$   r%   )responser*   r*   r+   app_all_voices   s   
$zmain.<locals>.app_all_voicesz	/downloadPOSTc                     s@   t tj} | d}|std| dd}t| |d |S )a  Download a voice.

        Downloads the .onnx and .onnx.json file from piper-voices repo on HuggingFace.
        See: https://huggingface.co/rhasspy/piper-voices

        Expects a JSON object with the format:
        {
          "voice": "<voice name>",   (required)
          "force_redownload": false  (optional)
        }

        Returns the name of the voice.
        Voice format must be <language>-<name>-<quality> like "en_US-lessac-medium".
        voicezvoice is requiredforce_redownloadF)r1   )r$   loadsr	   dataget
ValueErrorr   )r3   r&   r1   )download_dirr*   r+   app_download   s   
zmain.<locals>.app_download/c               
      s  t tj} | dd }|stdt|  | d}|}|du rO j	D ]#}t
|| d }| rNtd| tj| jd}||<  nq+|du r[td	| }| d
}|jjdkr|du r| d}|rx|jj|}|du rtd||jj   jpd}|dur||jjkrd}t|t| d jdur jn|jjt| d jdur jn|jjt| d jdurȈ jn|jjd}td|| t f}	t|	d}
|
I d}t|||D ]6\}}|s
|
 |j! |
"|j# |
$|j% d}|dkr|
&t't(|jj! j) d  |
&|j* qW d   n	1 s1w   Y  |	+ W  d   S 1 sEw   Y  dS )a  Synthesize audio from text.

        Expects a JSON object with the format:
        {
          "text": "Text to speak.",      (required)
          "voice": "<voice name>",       (optional)
          "speaker": "<speaker name>",   (optional)
          "speaker_id": "<speaker id>",  (optional, overrides speaker)
          "length_scale": 1.0,           (optional)
          "noise_scale": 0.667,          (optional)
          "length_w_scale": 0.8          (optional)
        }
        text zNo text providedr0   Nr   zLoading voice %sr   z)Voice not found: %s. Using default voice.
speaker_idr
   speakerzSpeaker not found: '%s' in %sr   length_scalenoise_scalenoise_w_scale)r;   r=   r>   r?   z&Synthesizing text: '%s' with config=%swbFT   ),r$   r2   r	   r3   r4   stripr5   _LOGGERdebugr   r   r    r   r%   cudawarningconfigZnum_speakersZspeaker_id_mapkeysr<   r   floatr=   r>   r?   ioBytesIOwaver#   	enumerateZ
synthesizeZsetframerateZsample_rateZsetsampwidthZsample_widthZsetnchannelsZsample_channelsZwriteframesbytesintZsentence_silenceZaudio_int16_bytesgetvalue)r3   r9   r&   r0   r   maybe_model_pathr;   r<   Z
syn_configZwav_ioZwav_fileZwav_params_setiZaudio_chunk)r(   default_model_iddefault_voiceloaded_voicesr*   r+   app_synthesize   s   











"

&zmain.<locals>.app_synthesize)hostportN)"argparseArgumentParseradd_argumentrO   rI   strr   cwd
parse_argsloggingbasicConfigrD   DEBUGINFOrC   r6   r   modelr    r5   r!   r"   r   r%   rE   r   __name__Zrouter   r   rN   runrW   rX   )	parserZ
voice_namer   rQ   Zappr,   r.   r7   rV   r*   )r(   rS   rT   r6   rU   r)   r+   main   s   	




	prg   __main__)r   N)__doc__rY   rJ   r$   r_   rL   pathlibr   typingr   r   r   r   urllib.requestr   Zflaskr   r	   r:   r   r   Zdownload_voicesr   r   	getLoggerrC   rg   rd   r*   r*   r*   r+   <module>   s&    
  
