
    qi=F                     x   d Z ddlZddl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mZmZmZmZmZmZ ddl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 e G d de             Z$ G d de      Z% G d de      Z&y# e $ r7Z! e
jD                  de!         e
jD                  d        e#de!       dZ![!ww xY w)zDeepgram text-to-speech service implementation.

This module provides integration with Deepgram's text-to-speech API
for generating speech from text using various voice models.
    N)	dataclass)AnyAsyncGeneratorOptional)logger)CancelFrameEndFrame
ErrorFrameFrame
StartFrameTTSAudioRawFrameTTSStoppedFrame)TTSSettings_warn_deprecated_param)
TTSServiceWebsocketTTSService)
traced_tts)connect)StatezException: z\In order to use DeepgramWebsocketTTSService, you need to `pip install pipecat-ai[deepgram]`.zMissing module: c                       e Zd ZdZy)DeepgramTTSSettingsz;Settings for DeepgramTTSService and DeepgramHttpTTSService.N)__name__
__module____qualname____doc__     O/opt/pipecat/venv/lib/python3.12/site-packages/pipecat/services/deepgram/tts.pyr   r   ,   s    Er   r   c                   >    e Zd ZU dZeZeed<   dZddddddded	e	e   d
ede	e
   dede	e   f fdZdefdZdef fdZdef fdZdef fdZ fdZ fdZdedeeef   f fdZd Zd Zd ZdefdZd Zd"de	e   fdZe d edede!e"df   fd!       Z# xZ$S )#DeepgramTTSServicea  Deepgram WebSocket-based text-to-speech service.

    Provides real-time text-to-speech synthesis using Deepgram's WebSocket API.
    Supports streaming audio generation with interruption handling via the Clear
    message for conversational AI use cases.
    	_settings)linear16mulawalawNzwss://api.deepgram.comr"   voicebase_urlsample_rateencodingsettingsapi_keyr&   r'   r(   r)   r*   c          
      |   |j                         | j                  vr+t        d| ddj                  | j                         d      t	        ddd      }|t        dt        d       ||_        ||_        ||j                  |       t        	| (  d|d	d
d	d	|d| || _        || _        || _        d| _        y)a  Initialize the Deepgram WebSocket TTS service.

        Args:
            api_key: Deepgram API key for authentication.
            voice: Voice model to use for synthesis.

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

            base_url: WebSocket base URL for Deepgram API. Defaults to "wss://api.deepgram.com".
            sample_rate: Audio sample rate in Hz. If None, uses service default.
            encoding: Audio encoding format. Defaults to "linear16". Must be one of SUPPORTED_ENCODINGS.
            settings: Runtime-updatable settings. When provided alongside deprecated
                parameters, ``settings`` values take precedence.
            **kwargs: Additional arguments passed to parent InterruptibleTTSService class.

        Raises:
            ValueError: If encoding is not in SUPPORTED_ENCODINGS.
        zUnsupported encoding 'z'. Must be one of z, z for WebSocket TTS.Naura-2-helena-enmodelr&   languager&   TF)r(   pause_frame_processingpush_stop_framespush_start_frameappend_trailing_spacer*   r   )lowerSUPPORTED_ENCODINGS
ValueErrorjoinr   r   r/   r&   apply_updatesuper__init___api_key	_base_url	_encoding_receive_task)
selfr+   r&   r'   r(   r)   r*   kwargsdefault_settings	__class__s
            r   r;   zDeepgramTTSService.__init__@   s    < >>4#;#;;(
2DTYYtOgOgEhDii|} 
 /$
 "7,?I%*"%*"
 ))(3 	
##'"!"&%	
 	
  !!!r   returnc                      y)zCheck if the service can generate metrics.

        Returns:
            True, as Deepgram WebSocket TTS service supports metrics generation.
        Tr   r@   s    r   can_generate_metricsz'DeepgramTTSService.can_generate_metrics        r   framec                 t   K   t         |   |       d{    | j                          d{    y7 7 w)zStart the Deepgram WebSocket TTS service.

        Args:
            frame: The start frame containing initialization parameters.
        N)r:   start_connectr@   rI   rC   s     r   rK   zDeepgramTTSService.start   s3      gmE"""mmo 	#   848688c                 t   K   t         |   |       d{    | j                          d{    y7 7 w)zbStop the Deepgram WebSocket TTS service.

        Args:
            frame: The end frame.
        N)r:   stop_disconnectrM   s     r   rP   zDeepgramTTSService.stop   s6      gl5!!!    	" rN   c                 t   K   t         |   |       d{    | j                          d{    y7 7 w)zgCancel the Deepgram WebSocket TTS service.

        Args:
            frame: The cancel frame.
        N)r:   cancelrQ   rM   s     r   rS   zDeepgramTTSService.cancel   s6      gnU###    	$ rN   c                   K   t         |           d{    | j                          d{    | j                  r=| j                  s0| j                  | j                  | j                              | _        yyy7 f7 Pw)z5Connect to Deepgram WebSocket and start receive task.N)r:   rL   _connect_websocket
_websocketr?   create_task_receive_task_handler_report_errorr@   rC   s    r   rL   zDeepgramTTSService._connect   sm     g   %%'''??4#5#5!%!1!1$2L2LTM_M_2`!aD $6?	 	!'s    B A<B A>AB >B c                    K   t         |           d{    | j                  r*| j                  | j                         d{    d| _        | j	                          d{    y7 S7 &7 	w)z6Disconnect from Deepgram WebSocket and clean up tasks.N)r:   rQ   r?   cancel_task_disconnect_websocketrZ   s    r   rQ   zDeepgramTTSService._disconnect   sf     g!###""4#5#5666!%D((*** 	$ 7 	+s3   A/A).A/A+A/#A-$A/+A/-A/deltac                    K   t         |   |       d{   }d|v r5| j                  j                  | j                  _        | j                          |r0| j                          d{    | j                          d{    |S 7 q7  7 
w)zApply a settings delta.

        Args:
            delta: A :class:`TTSSettings` (or ``DeepgramTTSSettings``) delta.

        Returns:
            Dict mapping changed field names to their previous values.
        Nr&   )r:   _update_settingsr!   r&   r/   _sync_model_name_to_metricsrQ   rL   )r@   r^   changedrC   s      r   r`   z#DeepgramTTSService._update_settings   s      077 g#'>>#7#7DNN ,,.""$$$--/!! 8 %!s4   BBAB)B
*BBB
BBc                   K   	 | j                   r'| j                   j                  t        j                  u ryt	        j
                  d       g }|j                  d| j                  j                          |j                  d| j                          |j                  d| j                          | j                   ddj                  |       }dd	| j                   i}t        ||
       d{   | _         | j                   j                  j                   j#                         D ci c]  \  }}|j%                  d      s|| }}}t	        j
                  |  d| d       | j'                  d       d{    y7 c c}}w 7 # t(        $ rp}t	        j*                  |  d|        | j-                  t/        |  d|              d{  7   d| _         | j'                  d|        d{  7   Y d}~yd}~ww xY ww)z;Connect to Deepgram WebSocket API with configured settings.Nz Connecting to Deepgram WebSocketzmodel=z	encoding=zsample_rate=z
/v1/speak?&AuthorizationToken )additional_headerszdg-z0: Websocket connection initialized: {"headers": }on_connected exception:  error: erroron_connection_error)rV   stater   OPENr   debugappendr!   r&   r>   r(   r=   r8   r<   websocket_connectresponseheadersitems
startswith_call_event_handler	Exceptionrm   
push_errorr
   )r@   paramsurlru   kves          r   rU   z%DeepgramTTSService._connect_websocket   s    	J4??#8#8EJJ#FLL;< FMMF4>>#7#7"89:MMIdnn%567MML)9)9(:;<^^$Jsxx/?.@AC&&(@AG$5cg$VVDO "&!9!9!A!A!G!G!IAQ\\Z_M`1G  LLD6!RSZR[[]^_**>::: W
 ; 	JLLD6aS12//*dV8A33G"HIII"DO**+@QCIII		Js   H2F HB<F 3F4:F .FF2F ?F F HF F 	H=HG"H8G;9H>HHHc                   K   	 | j                          d{    | j                  rot        j                  d       | j                  j	                  t        j                  ddi             d{    | j                  j                          d{    d| _        | j                  d       d{    y7 7 I7 )# t        $ rM}t        j                  |  d|        | j                  t        |  d|              d{  7   Y d}~xd}~ww xY w7 d# d| _        | j                  d       d{  7   w xY ww)	z+Close WebSocket connection and reset state.Nz%Disconnecting from Deepgram WebSockettypeCloserj   rk   rl   on_disconnected)stop_all_metricsrV   r   rq   sendjsondumpsclosery   rm   rz   r
   rx   )r@   r   s     r   r]   z(DeepgramTTSService._disconnect_websocket   s
    	>'')))DEoo**4::vw6G+HIIIoo++---
 #DO**+<=== *
 J- 	JLLD6aS12//*dV8A33G"HIII	J
 > #DO**+<===s   D?B> B8AB> 0B:1!B> B<B> D?2D3D?8B> :B> <B> >	D=DDD
D DD D?D<5D86D<<D?c                 H    | j                   r| j                   S t        d      )z3Get active websocket connection or raise exception.zWebsocket not connected)rV   ry   rF   s    r   _get_websocketz!DeepgramTTSService._get_websocket  s    ????"122r   
context_idc                 0  K   | j                          d{    | j                  r:	 | j                  j                  t        j                  ddi             d{    yy7 K7 # t
        $ r$}t        j                  |  d|        Y d}~yd}~ww xY ww)a9  Send Clear message to Deepgram when an audio context is interrupted.

        The Clear message will clear Deepgram's internal text buffer and stop
        sending audio, allowing for a new response to be generated.

        Args:
            context_id: The ID of the audio context that was interrupted.
        Nr   Clearz error sending Clear message: )r   rV   r   r   r   ry   r   rm   )r@   r   r   s      r   on_audio_context_interruptedz/DeepgramTTSService.on_audio_context_interrupted	  s      ##%%%??Ioo**4::vw6G+HIII  	& J Iv%CA3GHHIsJ   BA"B3A& A$A&  B$A& &	B/B	BBBc           	        K   | j                         2 3 d{   }t        |t              rD| j                         }t	        || j
                  d|      }| j                  ||       d{    ]t        |t              sn	 t        j                  |      }|j                  d      }|dk(  rt        j                  d|        n|dk(  rft        j                  d|        | j                         }| j                  |t        |             d{    | j                  |       d{    nf|d	k(  rt        j                  d
|        nH|dk(  r+t        j                  |  d|j                  dd              nt        j                   d|        7 7 27 7 u# t        j"                  $ r t        j$                  d|        Y w xY w6 yw)z5Receive and process messages from Deepgram WebSocket.N   )r   r   MetadatazReceived metadata: FlushedzReceived Flushed: ClearedzReceived Cleared: Warningz
 warning: descriptionzUnknown warningzReceived unknown message type: zInvalid JSON message: )r   
isinstancebytesget_active_audio_context_idr   r(   append_to_audio_contextstrr   loadsgetr   tracer   remove_audio_contextwarningrq   JSONDecodeErrorrm   )r@   messagectx_idrI   msgmsg_types         r   _receive_messagesz$DeepgramTTSService._receive_messages  s    !002  	E  	E''5)99;($2B2BARXY2265AAAGS)E**W-C"wwvH:-':3%%@A!Y.'9#%?@!%!A!A!C"::"Ov$F   #77???!Y.'9#%?@ "Y.#fJsww}FW/X.YZ 'Fse%LM= 	E
 B @ ++ ELL#9'!CDE? 3s|   GGFGAG*F+GBF#FF#+F!,A+F#GGGF#!F##+GGGGc                    K   | j                   r<	 ddi}| j                   j                  t        j                  |             d{    yy7 # t        $ r$}t        j                  |  d|        Y d}~yd}~ww xY ww)zFlush any pending audio synthesis by sending Flush command.

        This should be called when the LLM finishes a complete response to force
        generation of audio from Deepgram's internal text buffer.
        r   FlushNz error sending Flush message: )rV   r   r   r   ry   r   rm   )r@   r   	flush_msgr   s       r   flush_audiozDeepgramTTSService.flush_audio=  sw      ??I#W-	oo**4::i+@AAA  B Iv%CA3GHHIs@   A>5A AA 
A>A 	A;A61A>6A;;A>textc                  K   t        j                  |  d| d       	 | j                  r&| j                  j                  t        j
                  u r| j                          d{    d|d}| j                         j                  t        j                  |             d{    d y7 I7 # t        $ r}t        d|        Y d}~yd}~ww xY ww)a9  Generate speech from text using Deepgram's WebSocket TTS API.

        Args:
            text: The text to synthesize into speech.
            context_id: The context ID for tracking audio frames.

        Yields:
            Frame: Audio frames containing the synthesized speech, plus start/stop frames.
        : Generating TTS []NSpeak)r   r   zUnknown error occurred: rl   )r   rq   rV   ro   r   CLOSEDrL   r   r   r   r   ry   r
   )r@   r   r   	speak_msgr   s        r   run_ttszDeepgramTTSService.run_ttsJ  s      	v/vQ78	C??doo&;&;u||&Kmmo%%
 ")$7I%%',,TZZ	-BCCC J & D
  	C%=aS#ABBB	CsS   CAB2 $B.%>B2 #B0$	B2 -C.B2 0B2 2	C;CCCC)N)%r   r   r   r   r   Settings__annotations__r6   r   r   intr;   boolrG   r   rK   r	   rP   r   rS   rL   rQ   r   dictr   r`   rU   r]   r   r   r   r   r   r   r   r   __classcell__rC   s   @r   r    r    3   sI    #H""7  $0%)"26D" D" }	D"
 D" c]D" D" ./D"Ld  ! !!+ !b+K DcN ,J@>"3IS I "EHIHSM I C# C3 C>%QU+;V C Cr   r    c                        e Zd ZU dZeZeed<   dddddddedee   d	e	j                  d
edee   d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 )DeepgramHttpTTSServicezDeepgram HTTP text-to-speech service.

    Provides text-to-speech synthesis using Deepgram's HTTP TTS API.
    Supports various voice models and audio encoding formats with
    configurable sample rates and quality settings.
    r!   Nzhttps://api.deepgram.comr"   r%   r+   r&   aiohttp_sessionr'   r(   r)   r*   c                    t        ddd      }	|t        dt         d       ||	_        ||	_        ||	j	                  |       t        
|   d|dd|	d| || _        || _        || _	        || _
        y)a[  Initialize the Deepgram TTS service.

        Args:
            api_key: Deepgram API key for authentication.
            voice: Voice model to use for synthesis.

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

            aiohttp_session: Shared aiohttp session for HTTP requests with connection pooling.
            base_url: Custom base URL for Deepgram API. Defaults to "https://api.deepgram.com".
            sample_rate: Audio sample rate in Hz. If None, uses service default.
            encoding: Audio encoding format. Defaults to "linear16".
            settings: Runtime-updatable settings. When provided alongside deprecated
                parameters, ``settings`` values take precedence.
            **kwargs: Additional arguments passed to parent TTSService class.
        Nr-   r.   r&   T)r(   r3   r2   r*   r   )r   r   r/   r&   r9   r:   r;   r<   _sessionr=   r>   )r@   r+   r&   r   r'   r(   r)   r*   rA   rB   rC   s             r   r;   zDeepgramHttpTTSService.__init__t  s    < /$
 "7,?I%*"%*"
 ))(3 	
#!!%		

 	
  '!!r   rD   c                      y)zCheck if the service can generate metrics.

        Returns:
            True, as Deepgram TTS service supports metrics generation.
        Tr   rF   s    r   rG   z+DeepgramHttpTTSService.can_generate_metrics  rH   r   r   r   c                  K   t        j                  |  d| d       | j                   d}d| j                   dd}| j                  j
                  | j                  | j                  dd}d	|i}	 | j                          d
{    | j                  j                  ||||      4 d
{   }|j                  dk7  r3|j                          d
{   }t        d|j                   d|       | j                  |       d
{    | j                  }	d}
|j                   j#                  |	      2 3 d
{   }|
r| j%                          d
{    d}
|s(t'        || j                  d|       E7 7 7 7 x7 H7 06 d
d
d
      d
{  7   y
# 1 d
{  7  sw Y   y
xY w# t        $ r$}t)        dt+        |              Y d
}~y
d
}~ww xY ww)a/  Generate speech from text using Deepgram's TTS API.

        Args:
            text: The text to synthesize into speech.
            context_id: The context ID for tracking audio frames.

        Yields:
            Frame: Audio frames containing the synthesized speech, plus start/stop frames.
        r   r   z	/v1/speakrf   zapplication/json)re   zContent-Typenone)r/   r)   r(   	containerr   N)ru   r   r{      zHTTP z: TFr   )audior(   num_channelsr   zError getting audio: )r   rq   r=   r<   r!   r&   r>   r(   start_ttfb_metricsr   poststatusr   ry   start_tts_usage_metrics
chunk_sizecontentiter_chunkedstop_ttfb_metricsr   r
   r   )r@   r   r   r|   ru   r{   payloadrt   
error_text
CHUNK_SIZEfirst_chunkchunkr   s                r   r   zDeepgramHttpTTSService.run_tts  s     	v/vQ78  	*&,T]]O$<N`a ^^))++	
 D
	?))+++}}))W76 *   ??c)'/}}!6J#eHOO+<Bzl$KLL224888!__
"#+#3#3#@#@#L  %""44666&+."'(,(8(8)*'1	 ) , "7 9
6 $M    2  	?4SVH=>>>	?s   A0G 3F0 E<'F0 .E>/F0 2#FF 3F	F
-F7F;F<F?FFFF<F0 >F0  FFFFF	F0 FF0 G F-!F$"F-)F0 ,G -F0 0	G9GG GG )r   r   r   r   r   r   r   r   r   aiohttpClientSessionr   r;   r   rG   r   r   r   r   r   r   s   @r   r   r   i  s     #H""  $2%)"26;" ;" }	;"
 !..;" ;" c];" ;" ./;"zd  9?# 9?3 9?>%QU+;V 9? 9?r   r   )'r   r   dataclassesr   typingr   r   r   r   logurur   pipecat.frames.framesr   r	   r
   r   r   r   r   pipecat.services.settingsr   r   pipecat.services.tts_servicer   r   (pipecat.utils.tracing.service_decoratorsr   websockets.asyncio.clientr   rs   websockets.protocolr   ModuleNotFoundErrorr   rm   ry   r   r    r   r   r   r   <module>r      s     ! 0 0     J H ?,F) 	+ 	 	sC, sCl	J?Z J?K
  ,FLL;qc"#FLLf &qc*
++,s   
A= =B92B44B9