o
    
j%                     @   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)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)voices_dictconfig_pathsr   	onnx_pathconfig_pathmodel_idconfig_file)args
model_path D/home/kuhnn/.local/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/   r0   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)r6   )r%   loadsr	   dataget
ValueErrorr   )r8   r+   r6   )download_dirr/   r0   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 providedr5   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@   rB   rC   rD   z&Synthesizing text: '%s' with config=%swbFT   ),r%   r7   r	   r8   r9   stripr:   _LOGGERdebugr   r   r!   r   r&   cudawarningconfignum_speakersspeaker_id_mapkeysrA   r   floatrB   rC   rD   ioBytesIOwaver$   	enumerate
synthesizesetframeratesample_ratesetsampwidthsample_widthsetnchannelssample_channelswriteframesbytesintsentence_silenceaudio_int16_bytesgetvalue)r8   r>   r+   r5   r   maybe_model_pathr@   rA   
syn_configwav_iowav_filewav_params_setiaudio_chunk)r-   default_model_iddefault_voiceloaded_voicesr/   r0   app_synthesize   s   











"

&zmain.<locals>.app_synthesize)hostportN)"argparseArgumentParseradd_argumentr^   rP   strr   cwd
parse_argsloggingbasicConfigrI   DEBUGINFOrH   r;   r   modelr!   r:   r"   r#   r   r&   rJ   r   __name__router   r   r]   runrm   rn   )	parser
voice_namer   rb   appr1   r3   r<   rl   r/   )r-   ri   rj   r;   rk   r.   r0   main   s   	




	pr   __main__)r   N)__doc__ro   rQ   r%   ru   rS   pathlibr   typingr   r   r   r   urllib.requestr   flaskr   r	   r?   r   r   download_voicesr   r   	getLoggerrH   r   rz   r/   r/   r/   r0   <module>   s&    
  
