
    qi(                        d Z ddlZddlmZ ddlmZ ddlmZmZm	Z	m
Z
 ddlZddlmZ ddlmZmZmZ ddlmZmZ dd	lmZ dd
lmZ 	 ddlmZ ddlmZ e G d de             Z! G d de      Z"e G d de             Z# G d de      Z$y# e$ r7Z ej>                  de         ej>                  d        e de       dZ[ww xY w)z!Piper TTS service implementation.    N)	dataclass)Path)AnyAsyncGeneratorAsyncIteratorOptional)logger)
ErrorFrameFrameTTSStoppedFrame)TTSSettings_warn_deprecated_param)
TTSService)
traced_tts)
PiperVoice)download_voicezException: zCIn order to use Piper, you need to `pip install pipecat-ai[piper]`.zMissing module: c                       e Zd ZdZy)PiperTTSSettingszSettings for PiperTTSService.N__name__
__module____qualname____doc__     L/opt/pipecat/venv/lib/python3.12/site-packages/pipecat/services/piper/tts.pyr   r   #   s    'r   r   c                        e Zd ZU dZeZeed<   dddddddee   dee	   de
d	e
d
ee   f
 fdZde
fdZdedeeef   f fdZedededeedf   fd       Z xZS )PiperTTSServicezPiper TTS service implementation.

    Provides local text-to-speech synthesis using Piper voice models. Automatically
    downloads voice models if not already present and resamples audio output to
    match the configured sample rate.
    	_settingsNF)voice_iddownload_dirforce_redownloaduse_cudasettingsr    r!   r"   r#   r$   c                2   t        ddd      }|t        dt         d       ||_        ||j                  |       t	        |   ddd|d| |xs t        j                         }| j                  j                  }| d}	t        |      |	z  }
|
j                         s't        j                  d| d	       t        |||
       t        j                  d| d|
        t        j                  |
|      | _        t        j                  d| d	       y)a  Initialize the Piper TTS service.

        Args:
            voice_id: Piper voice model identifier (e.g. `en_US-ryan-high`).

                .. deprecated:: 0.0.105
                    Use ``settings=PiperTTSSettings(voice=...)`` instead.

            download_dir: Directory for storing voice model files. Defaults to
                the current working directory.
            force_redownload: Re-download the voice model even if it already exists.
            use_cuda: Use CUDA for GPU-accelerated inference.
            settings: Runtime-updatable settings. When provided alongside deprecated
                parameters, ``settings`` values take precedence.
            **kwargs: Additional arguments passed to the parent `TTSService`.
        Nmodelvoicelanguager    r(   Tpush_start_framepush_stop_framesr$   z.onnxzDownloading Piper 'z' model)r"   zLoading Piper 'z' model from )r#   zLoaded Piper 'r   )r   r   r(   apply_updatesuper__init__r   cwdr   existsr	   debugr   r   load_voice)selfr    r!   r"   r#   r$   kwargsdefault_settingsr4   
model_filemodel_path_resolved	__class__s              r   r/   zPiperTTSService.__init__5   s   6 ,$dTR ":/?I%-"
 ))(3 	
!!%	
 		
 $1txxz%%xu%
"<0:="))+LL.vhg>?6<BRSvhm<O;PQR oo&9HM~fXW56r   returnc                      yzCheck if this service can generate processing metrics.

        Returns:
            True, as Piper service supports metrics generation.
        Tr   r5   s    r   can_generate_metricsz$PiperTTSService.can_generate_metricst        r   deltac                 l   K   t         |   |       d{   }|s|S | j                  |       |S 7 w)zgApply a settings delta.

        Settings are stored but not applied to the active connection.
        N)r.   _update_settings _warn_unhandled_updated_settings)r5   rA   changedr:   s      r   rC   z PiperTTSService._update_settings|   s;     
 077N--g6 8s   424text
context_idc                  K   d dt         t           ffd}t        j                  |  d| d       	 | j	                  |       d{    | j                   || j                  j                  |            | j                  j                  j                  |      2 3 d{   }| j                          d{    | '7 |7 $7 6 nB# t        $ r6}t        j                  |  d|        t        d	| 
       Y d}~nd}~ww xY wt        j                  |  d| d       | j                          d{  7   y# t        j                  |  d| d       | j                          d{  7   w xY ww)a  Generate speech from text using Piper.

        Args:
            text: The text to convert to speech.
            context_id: Unique identifier for this TTS context.

        Yields:
            Frame: Audio frames containing the synthesized speech and status frames.
        c                 8    	 t        |       S # t        $ r Y y w xY wN)nextStopIteration)its    r   
async_nextz+PiperTTSService.run_tts.<locals>.async_next   s"    Bx  s   
 	r;   c                t   K   	 t        j                  |        d {   }|y |j                   17 wrJ   )asyncio	to_threadaudio_int16_bytes)iteratoritemrN   s     r   async_iteratorz/PiperTTSService.run_tts.<locals>.async_iterator   s;     $..z8DD<,,,	 Ds   868: Generating TTS []N)in_sample_raterG   z exception: Unknown error occurred: errorz: Finished TTS [)r   bytesr	   r2   start_tts_usage_metrics"_stream_audio_frames_from_iteratorr4   
synthesizeconfigsample_ratestop_ttfb_metrics	Exceptionr[   r
   )r5   rF   rG   rU   frameerN   s         @r   run_ttszPiperTTSService.run_tts   sm    		-mE.B 	- 	v/vQ78	+..t444#FFt{{55d;<#{{11==%  G    e
 ,,... 5
 /   	CLLD6aS12%=aS#ABBB	C LLD6!1$q9:((*** LLD6!1$q9:((***s   2E?C 
CAC  C$C	%C(C <C=C 	CC C E 	D,D	E 	DE .E??E E?/E<5E86E<<E?)r   r   r   r   r   Settings__annotations__r   strr   boolr/   r?   dictr   rC   r   r   r   rf   __classcell__r:   s   @r   r   r   *   s      H
 #''+!&/3=7 3-=7 tn	=7
 =7 =7 +,=7~d 
,< 
c3h 
 )+# )+3 )+>%QU+;V )+ )+r   r   c                       e Zd ZdZy)PiperHttpTTSSettingsz!Settings for PiperHttpTTSService.Nr   r   r   r   ro   ro      s    +r   ro   c            
            e Zd ZU dZeZeed<   ddddedej                  de
e   de
e   f fd	Zd
efdZededed
eedf   fd       Z xZS )PiperHttpTTSServicezPiper HTTP TTS service implementation.

    Provides integration with Piper's HTTP TTS server for text-to-speech
    synthesis. Supports streaming audio generation with configurable sample
    rates and automatic WAV header removal.
    r   N)r    r$   base_urlaiohttp_sessionr    r$   c                   t        ddd      }|t        dt         d       ||_        ||j                  |       t	        |   d
dd|d| |j                  d      rt        j                  d       |dd	 }|| _	        || _
        y)ak  Initialize the Piper TTS service.

        Args:
            base_url: Base URL for the Piper TTS HTTP server.
            aiohttp_session: aiohttp ClientSession for making HTTP requests.
            voice_id: Piper voice model identifier (e.g. `en_US-ryan-high`).

                .. deprecated:: 0.0.105
                    Use ``settings=PiperHttpTTSSettings(voice=...)`` instead.

            settings: Runtime-updatable settings. When provided alongside deprecated
                parameters, ``settings`` values take precedence.
            **kwargs: Additional arguments passed to the parent TTSService.
        Nr&   r    r(   Tr*   /z0Base URL ends with a slash, this is not allowed.r   )ro   r   r(   r-   r.   r/   endswithr	   warning	_base_url_session)r5   rr   rs   r    r$   r6   r7   r:   s          r   r/   zPiperHttpTTSService.__init__   s    0 0d$QUV ":/CWM%-"
 ))(3 	
!!%	
 		
 S!NNMN}H!'r   r;   c                      yr=   r   r>   s    r   r?   z(PiperHttpTTSService.can_generate_metrics  r@   r   rF   rG   c                  K   t        j                  |  d| d       ddi}	 || j                  j                  d}| j                  j                  | j                  ||      4 d{   }|j                  dk7  rq|j                          d{   }t        d	|j                   d
| d       t        |       	 ddd      d{    | j                          d{    y| j                  |       d{    | j                  }| j                  |j                  j!                  |      d|      2 3 d{   }| j                          d{    | '7 7 7 7 7 l7 ,7 6 ddd      d{  7   n# 1 d{  7  sw Y   nxY wn(# t"        $ r}	t        d|	        Y d}	~	nd}	~	ww xY w| j                          d{  7   y# | j                          d{  7   w xY ww)a   Generate speech from text using Piper's HTTP API.

        Args:
            text: The text to convert to speech.
            context_id: Unique identifier for this TTS context.

        Yields:
            Frame: Audio frames containing the synthesized speech and status frames.
        rV   rW   zContent-Typezapplication/json)rF   r(   )jsonheadersN   zError getting audio (status: z	, error: )rZ   )rG   T)strip_wav_headerrG   rY   )r	   r2   r   r(   rz   postry   statusrF   r
   r   rb   r]   
chunk_sizer^   contentiter_chunkedrc   )
r5   rF   rG   r~   dataresponser[   
CHUNK_SIZErd   re   s
             r   rf   zPiperHttpTTSService.run_tts
  s     	v/vQ78.
	+--D
 }}))$..tW)U    Ya??c)"*--/1E$ =hoo=NiX]W^^_`  *Z@@   . ((*** 224888!__
#'#J#J$$11*=%)) $K $    %
 00222K' 1 . + 9 
 3$         (  	C%=aS#ABBB	C ((***$((***s+   G=AF (E&)F ,#FE(4FF E*F G='E,(G=-FE.=F?E4E0E4FE2
F&F (F*F ,G=.F0E42F4F5F  FF FFFF G 	G&F=8G =GG G=GG=G:3G64G::G=)r   r   r   r   ro   rg   rh   ri   aiohttpClientSessionr   r/   rj   r?   r   r   r   rf   rl   rm   s   @r   rq   rq      s     $H## #'371( 1( !..	1(
 3-1( /01(fd  ++# ++3 ++>%QU+;V ++ ++r   rq   )%r   rP   dataclassesr   pathlibr   typingr   r   r   r   r   logurur	   pipecat.frames.framesr
   r   r   pipecat.services.settingsr   r   pipecat.services.tts_servicer   (pipecat.utils.tracing.service_decoratorsr   piperr   piper.download_voicesr   ModuleNotFoundErrorre   r[   rc   r   r   ro   rq   r   r   r   <module>r      s    (  !  ? ?   
 J 3 ?, 4 	{ 	 	H+j H+f 	; 	 	r+* r+O  ,FLL;qc"#FLLVW
&qc*
++,s   B C2CC