o
    iG\                  
   @   s  d Z ddlZddlZddlZddlmZmZ ddlmZm	Z	m
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mZmZmZmZmZmZ ddlmZ dd	lmZmZm Z  dd
l!m"Z"m#Z#m$Z$ ddl%m&Z&m'Z' ddl(m)Z) zddl*m+Z, ddl-m.Z. W n  e/y Z0 ze1de0  e1d e2de0 dZ0[0ww de&de
e3 fddZ4eG dd deZ5G dd de"Z6G dd de$Z7dS )zNeuphonic text-to-speech service implementations.

This module provides WebSocket and HTTP-based integrations with Neuphonic's
text-to-speech API for real-time audio synthesis.
    N)	dataclassfield)AnyAsyncGeneratorOptional)logger)	BaseModel)
BotStoppedSpeakingFrameCancelFrameEndFrame
ErrorFrameFrameLLMFullResponseEndFrame
StartFrameTTSAudioRawFrameTTSSpeakFrameTTSStoppedFrame)FrameDirection)	NOT_GIVENTTSSettings	_NotGiven)InterruptibleTTSServiceTextAggregationMode
TTSService)Languageresolve_language)
traced_tts)connect)StatezException: zKIn order to use Neuphonic, you need to `pip install pipecat-ai[neuphonic]`.zMissing module: languagereturnc                 C   sN   t jdt jdt jdt jdt jdt jdt jdt jdt j	d	t j
d
i
}t| |ddS )zConvert a Language enum to Neuphonic language code.

    Args:
        language: The Language enum value to convert.

    Returns:
        The corresponding Neuphonic language code, or None if not supported.
    deenesnlarfrptruHIzhT)use_base_code)r   DEENESNLARFRPTRUr)   ZHr   )r   LANGUAGE_MAP r6   R/home/ubuntu/.local/lib/python3.10/site-packages/pipecat/services/neuphonic/tts.pylanguage_to_neuphonic_lang_code2   s   
r8   c                   @   s,   e Zd ZU dZedd dZeeB ed< dS )NeuphonicTTSSettingszSettings for NeuphonicTTSService and NeuphonicHttpTTSService.

    Parameters:
        speed: Speech speed multiplier. Defaults to 1.0.
    c                   C   s   t S N)r   r6   r6   r6   r7   <lambda>S   s    zNeuphonicTTSSettings.<lambda>)default_factoryspeedN)	__name__
__module____qualname____doc__r   r=   floatr   __annotations__r6   r6   r6   r7   r9   K   s   
 r9   c                       s  e Zd ZU dZeZeed< G dd deZddddddddd	d
e	de
e	 de	de
e de	de
e de
e de
e de
e f fddZdefddZdede
e	 fddZdedee	ef f fddZdef fdd Zdef fd!d"Zdef fd#d$Zd@d%e
e	 fd&d'Zejfded(ef fd)d*Z ded(ef fd+d,Z! fd-d.Z" fd/d0Z#d1d2 Z$d3d4 Z%d5d6 Z&d7d8 Z'd9d: Z(d;e	fd<d=Z)e*d;e	d%e	de+edf fd>d?Z,  Z-S )ANeuphonicTTSServicea!  Neuphonic real-time text-to-speech service using WebSocket streaming.

    Provides real-time text-to-speech synthesis using Neuphonic's WebSocket API.
    Supports interruption handling, keepalive connections, and configurable voice
    parameters for high-quality speech generation.
    	_settingsc                   @   4   e Zd ZU dZejZee ed< dZ	ee
 ed< dS )zNeuphonicTTSService.InputParamsa8  Input parameters for Neuphonic TTS configuration.

        .. deprecated:: 0.0.105
            Use ``settings=NeuphonicTTSService.Settings(...)`` instead.

        Parameters:
            language: Language for synthesis. Defaults to English.
            speed: Speech speed multiplier. Defaults to 1.0.
        r         ?r=   Nr>   r?   r@   rA   r   r-   r   r   rC   r=   rB   r6   r6   r6   r7   InputParamsa      
 
rI   Nzwss://api.neuphonic.com"V  
pcm_linear)voice_idurlsample_rateencodingparamssettingsaggregate_sentencestext_aggregation_modeapi_keyrM   rN   rO   rP   rQ   rR   rS   rT   c       	      
      s   | j ddtjdd}|dur| dd ||_|dur4| d |s4|jdur+|j|_|jdur4|j|_|dur=|| t j	d
||	ddd||d	|
 || _
|| _d| _d| _|| _|| _dS )a  Initialize the Neuphonic TTS service.

        Args:
            api_key: Neuphonic API key for authentication.
            voice_id: ID of the voice to use for synthesis.

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

            url: WebSocket URL for the Neuphonic API.
            sample_rate: Audio sample rate in Hz. Defaults to 22050.
            encoding: Audio encoding format. Defaults to "pcm_linear".
            params: Additional input parameters for TTS configuration.

                .. deprecated:: 0.0.105
                    Use ``settings=NeuphonicTTSService.Settings(...)`` instead.

            settings: Runtime-updatable settings. When provided alongside deprecated
                parameters, ``settings`` values take precedence.
            aggregate_sentences: Deprecated. Use text_aggregation_mode instead.

                .. deprecated:: 0.0.104
                    Use ``text_aggregation_mode`` instead.

            text_aggregation_mode: How to aggregate text before synthesis.
            **kwargs: Additional arguments passed to parent InterruptibleTTSService.
        NrG   modelvoicer   r=   rM   rX   rQ   Tg       @)rS   rT   push_stop_framespush_start_framestop_frame_timeout_srO   rR   r6   )Settingsr   r-   "_warn_init_param_moved_to_settingsrX   r   r=   apply_updatesuper__init___api_key_url_receive_task_keepalive_task	_encoding_sampling_rate)selfrU   rM   rN   rO   rP   rQ   rR   rS   rT   kwargsdefault_settings	__class__r6   r7   r`   o   sF   *




zNeuphonicTTSService.__init__r    c                 C      dS )zCheck if this service can generate processing metrics.

        Returns:
            True, as Neuphonic service supports metrics generation.
        Tr6   rg   r6   r6   r7   can_generate_metrics      z(NeuphonicTTSService.can_generate_metricsr   c                 C      t |S zConvert a Language enum to Neuphonic service language format.

        Args:
            language: The language to convert.

        Returns:
            The Neuphonic-specific language code, or None if not supported.
        r8   rg   r   r6   r6   r7   language_to_service_language      	z0NeuphonicTTSService.language_to_service_languagedeltac                    sL   t  |I dH }|r$|  I dH  |  I dH  td| j d |S )z<Apply a settings delta and reconnect with new configuration.NzSwitching TTS to settings: [])r_   _update_settings_disconnect_connectr   inforE   )rg   rv   changedrj   r6   r7   rx      s   z$NeuphonicTTSService._update_settingsframec                    &   t  |I dH  |  I dH  dS )zStart the Neuphonic TTS service.

        Args:
            frame: The start frame containing initialization parameters.
        N)r_   startrz   rg   r}   rj   r6   r7   r         zNeuphonicTTSService.startc                    r~   )zYStop the Neuphonic TTS service.

        Args:
            frame: The end frame.
        N)r_   stopry   r   rj   r6   r7   r      r   zNeuphonicTTSService.stopc                    r~   )z^Cancel the Neuphonic TTS service.

        Args:
            frame: The cancel frame.
        N)r_   cancelry   r   rj   r6   r7   r      r   zNeuphonicTTSService.cancel
context_idc                    s0   | j rddi}| j t|I dH  dS dS )z:Flush any pending audio synthesis by sending stop command.textz<STOP>N
_websocketsendjsondumps)rg   r   msgr6   r6   r7   flush_audio   s
   zNeuphonicTTSService.flush_audio	directionc                    s   t  ||I dH  dS )zPush a frame downstream with special handling for stop conditions.

        Args:
            frame: The frame to push.
            direction: The direction to push the frame.
        N)r_   
push_framerg   r}   r   rj   r6   r7   r     s   zNeuphonicTTSService.push_framec                    sn   t  ||I dH  t|tr|  I dH  dS t|tr'|  I dH  dS t|tr5|  I dH  dS dS )zProcess frames with special handling for speech control.

        Args:
            frame: The frame to process.
            direction: The direction of frame processing.
        N)r_   process_frame
isinstancer   pause_processing_framesr   r	   resume_processing_framesr   rj   r6   r7   r   
  s   


z!NeuphonicTTSService.process_framec                    sh   t   I dH  |  I dH  | jr | js | | | j| _| jr0| js2| | 	 | _dS dS dS )z:Connect to Neuphonic WebSocket and start background tasks.N)
r_   rz   _connect_websocketr   rc   create_task_receive_task_handler_report_errorrd   _keepalive_task_handlerrm   rj   r6   r7   rz     s   zNeuphonicTTSService._connectc                    s`   t   I dH  | jr| | jI dH  d| _| jr'| | jI dH  d| _|  I dH  dS )z7Disconnect from Neuphonic WebSocket and clean up tasks.N)r_   ry   rc   cancel_taskrd   _disconnect_websocketrm   rj   r6   r7   ry   )  s   zNeuphonicTTSService._disconnectc              
      s4  zk| j r| j jtju rW dS td | jj| jj| j	| j
| jjd}g }| D ]\}}|dur<|| d|  q*| j d| jj }|rS|dd| 7 }d| ji}t||d	I dH | _ | d
I dH  W dS  ty } z!| jd| |dI dH  d| _ | d| I dH  W Y d}~dS d}~ww )z0Establish WebSocket connection to Neuphonic API.NzConnecting to Neuphonic)	lang_coder=   rP   sampling_raterM   =z/speak/?&z	x-api-key)additional_headerson_connectedUnknown error occurred: 	error_msg	exceptionon_connection_error)r   stater   OPENr   debugrE   r   r=   re   rf   rX   itemsappendrb   joinra   websocket_connect_call_event_handler	Exception
push_error)rg   
tts_configquery_paramskeyvaluerN   headerser6   r6   r7   r   7  s8   

"z&NeuphonicTTSService._connect_websocketc              
      s   zUz|   I dH  | jrtd | j I dH  W n ty: } z| jd| |dI dH  W Y d}~nd}~ww W d| _| dI dH  dS W d| _| dI dH  dS d| _| dI dH  w )z.Close WebSocket connection and clean up state.NzDisconnecting from Neuphonicr   r   on_disconnected)stop_all_metricsr   r   r   closer   r   r   )rg   r   r6   r6   r7   r   Z  s&   
&z)NeuphonicTTSService._disconnect_websocketc                    s   | j 2 z?3 dH W }t|trCt|}|drC|d drC|  I dH  t|d d }t	|| j
d|  d}| |I dH  q6 dS )z6Receive and process messages from Neuphonic WebSocket.Ndataaudio   r   )r   r   strr   loadsgetstop_ttfb_metricsbase64	b64decoder   rO   get_active_audio_context_idr   )rg   messager   r   r}   r6   r6   r7   _receive_messagesh  s   

z%NeuphonicTTSService._receive_messagesc                    s(   d}	 t |I dH  |  I dH  q)z;Handle keepalive messages to maintain WebSocket connection.
   TN)asynciosleep_send_keepalive)rg   KEEPALIVE_SLEEPr6   r6   r7   r   v  s   z+NeuphonicTTSService._keepalive_task_handlerc                    s0   | j rddi}| j t|I dH  dS dS )z.Send keepalive message to maintain connection.r    Nr   )rg   r   r6   r6   r7   r   }  s
   z#NeuphonicTTSService._send_keepaliver   c                    sF   | j r!d| di}td|  | j t|I dH  dS dS )z/Send text to Neuphonic WebSocket for synthesis.r   z <STOP>zSending text to websocket: N)r   r   r   r   r   r   )rg   r   r   r6   r6   r7   
_send_text  s   zNeuphonicTTSService._send_textc              
   C  s  t d| d z[| jr| jjtju r|  I dH  z| |I dH  | |I dH  W n1 t	y_ } z%t
d| dV  t|dV  |  I dH  |  I dH  W Y d}~W dS d}~ww dV  W dS  t	y } zt
d| dV  W Y d}~dS d}~ww )a  Generate speech from text using Neuphonic's streaming API.

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

        Yields:
            Frame: Audio frames containing the synthesized speech.
        Generating TTS: [rw   Nr   errorr   )r   r   r   r   r   CLOSEDrz   r   start_tts_usage_metricsr   r   r   ry   )rg   r   r   r   r6   r6   r7   run_tts  s*    zNeuphonicTTSService.run_ttsr:   ).r>   r?   r@   rA   r9   r\   rC   r   rI   r   r   intboolr   r`   rn   r   rt   r   dictr   rx   r   r   r   r   r
   r   r   r   
DOWNSTREAMr   r   r   rz   ry   r   r   r   r   r   r   r   r   r   __classcell__r6   r6   rj   r7   rD   V   sf   
 	
U					#(rD   c                       s  e Zd ZU dZeZeed< G dd deZddddddd	d
e	de
e	 dejde	de
e de
e	 de
e de
e f fddZdefddZdede
e	 fddZdef fddZd&de
e	 fddZd e	dedB fd!d"Zed#e	de	deedf fd$d%Z  ZS )'NeuphonicHttpTTSServicea  Neuphonic text-to-speech service using HTTP streaming.

    Provides text-to-speech synthesis using Neuphonic's HTTP API with server-sent
    events for streaming audio delivery. Suitable for applications that prefer
    HTTP-based communication over WebSocket connections.
    rE   c                   @   rF   )z#NeuphonicHttpTTSService.InputParamsaA  Input parameters for Neuphonic HTTP TTS configuration.

        .. deprecated:: 0.0.105
            Use ``settings=NeuphonicHttpTTSService.Settings(...)`` instead.

        Parameters:
            language: Language for synthesis. Defaults to English.
            speed: Speech speed multiplier. Defaults to 1.0.
        r   rG   r=   NrH   r6   r6   r6   r7   rI     rJ   rI   Nzhttps://api.neuphonic.comrK   rL   )rM   rN   rO   rP   rQ   rR   rU   rM   aiohttp_sessionrN   rO   rP   rQ   rR   c                   s   | j ddtjdd}
|dur| dd ||
_|dur4| d |s4|jdur+|j|
_|jdur4|j|
_|dur=|
| t j	d
|dd|
d|	 || _
|| _|d	| _|| _dS )a  Initialize the Neuphonic HTTP TTS service.

        Args:
            api_key: Neuphonic API key for authentication.
            voice_id: ID of the voice to use for synthesis.

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

            aiohttp_session: Shared aiohttp session for HTTP requests.
            url: Base URL for the Neuphonic HTTP API.
            sample_rate: Audio sample rate in Hz. Defaults to 22050.
            encoding: Audio encoding format. Defaults to "pcm_linear".
            params: Additional input parameters for TTS configuration.

                .. deprecated:: 0.0.105
                    Use ``settings=NeuphonicHttpTTSService.Settings(...)`` instead.

            settings: Runtime-updatable settings. When provided alongside deprecated
                parameters, ``settings`` values take precedence.
            **kwargs: Additional arguments passed to parent TTSService.
        NrG   rV   rM   rX   rQ   T)rO   rY   rZ   rR   /r6   )r\   r   r-   r]   rX   r   r=   r^   r_   r`   ra   _sessionrstrip	_base_urlre   )rg   rU   rM   r   rN   rO   rP   rQ   rR   rh   ri   rj   r6   r7   r`     s<   $




z NeuphonicHttpTTSService.__init__r    c                 C   rl   )zCheck if this service can generate processing metrics.

        Returns:
            True, as Neuphonic HTTP service supports metrics generation.
        Tr6   rm   r6   r6   r7   rn     ro   z,NeuphonicHttpTTSService.can_generate_metricsr   c                 C   rp   rq   rr   rs   r6   r6   r7   rt     ru   z4NeuphonicHttpTTSService.language_to_service_languager}   c                    s   t  |I dH  dS )zStart the Neuphonic HTTP TTS service.

        Args:
            frame: The start frame containing initialization parameters.
        N)r_   r   r   rj   r6   r7   r      s   zNeuphonicHttpTTSService.startr   c                    s   dS )z|Flush any pending audio synthesis.

        Note:
            HTTP-based service doesn't require explicit flushing.
        Nr6   )rg   r   r6   r6   r7   r   (  s   z#NeuphonicHttpTTSService.flush_audior   c              
   C   s   |  }|r
d|vrdS z0|dd\}}|r|dkrW dS t|}|ddur:td|dd	 d|d  |W S  ttjfyZ } zt	d
|  W Y d}~dS d}~ww )zParse a Server-Sent Event message.

        Args:
            message: The SSE message to parse.

        Returns:
            Parsed message dictionary or None if not a data message.
        r   Nz: r   z[DONE]errorszNeuphonic API error status_codeunknownzFailed to parse SSE message: )
stripsplitr   r   r   r   
ValueErrorJSONDecodeErrorr   warning)rg   r   _data_contentmessage_dictr   r6   r6   r7   _parse_sse_message0  s$   	
z*NeuphonicHttpTTSService._parse_sse_messager   c                 C  s~  t d| d | j d| jj }| jdd}|| jj| j| j| jjd}| jj	r2| jj	|d< zz| j
j|||d4 I d	H }|jd
krs| I d	H }d|j d| }t|dV  	 W d	  I d	H  W W |  I d	H  d	S | |I d	H  |j2 zb3 d	H W }	|	sq~|	jddd}
|
 sq~z2| |
}|d	ur|di dd	ur|d d }t|}|  I d	H  t|| jd|dV  W q~ ty } ztd| dV  W Y d	}~q~d	}~ww 6 W d	  I d	H  n1 I d	H sw   Y  W n* tjy   t d   ty" } ztd| dV  W Y d	}~nd	}~ww W |  I d	H  d	S W |  I d	H  d	S |  I d	H  w )a,  Generate speech from text using Neuphonic streaming 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 information.
        r   rw   z/sse/speak/zapplication/json)z	X-API-KEYzContent-Type)r   r   rP   r   r=   rM   )r   r   N   zNeuphonic API error: HTTP z - r   zutf-8ignore)r   r   r   r   r   r   zTTS generation cancelled)r   r   r   rE   r   ra   re   rO   r=   rX   r   poststatusr   r   r   r   contentdecoder   r   r   r   r   r   r   r   CancelledError)rg   r   r   rN   r   payloadresponse
error_texterror_messageliner   parsed_message	audio_b64audio_bytesr   r6   r6   r7   r   R  sx   
,


(&
"zNeuphonicHttpTTSService.run_ttsr:   )r>   r?   r@   rA   r9   r\   rC   r   rI   r   r   aiohttpClientSessionr   r`   r   rn   r   rt   r   r   r   r   r   r   r   r   r   r   r6   r6   rj   r7   r     sF   
 	
J"(r   )8rA   r   r   r   dataclassesr   r   typingr   r   r   r   logurur   pydanticr   pipecat.frames.framesr	   r
   r   r   r   r   r   r   r   r   "pipecat.processors.frame_processorr   pipecat.services.settingsr   r   r   pipecat.services.tts_servicer   r   r   pipecat.transcriptions.languager   r   (pipecat.utils.tracing.service_decoratorsr   websockets.asyncio.clientr   r   websockets.protocolr   ModuleNotFoundErrorr   r   r   r   r8   r9   rD   r   r6   r6   r6   r7   <module>   s>   0

  V