
    qiu                     *   d 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	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 ddlmZ dd	lmZmZm Z m!Z! dd
l"m#Z#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l0m1Z2 ddl3m4Z4 de(de9fdZ:e G d de             Z;e G d de             Z< G d de&      Z= G d de%      Z> G d d e#      Z?y# e5$ r7Z6 ejn                  de6         ejn                  d        e8de6       dZ6[6ww xY w)!zRime text-to-speech service implementations.

This module provides both WebSocket and HTTP-based text-to-speech services
using Rime's API for streaming and batch audio synthesis.
    N)	dataclassfield)AnyAsyncGeneratorClassVarDictOptional)logger)	BaseModel)	CancelFrameEndFrame
ErrorFrameFrameInterruptionFrame
StartFrameTTSAudioRawFrameTTSStartedFrameTTSStoppedFrame)FrameDirection)	NOT_GIVENTTSSettings	_NotGiven_warn_deprecated_param)InterruptibleTTSServiceTextAggregationMode
TTSServiceWebsocketTTSService)Languageresolve_language)BaseTextAggregator)SkipTagsAggregator)
traced_tts)connect)StatezException: zAIn order to use Rime, you need to `pip install pipecat-ai[rime]`.zMissing module: languagereturnc           
          t         j                  dt         j                  dt         j                  dt         j                  dt         j
                  di}t        | |d      S )zConvert pipecat Language to Rime language code.

    Args:
        language: The pipecat Language enum value.

    Returns:
        Three-letter language code used by Rime (e.g., 'eng' for English).
    gerfraengspahinF)use_base_code)r   DEFRENESHIr   )r%   LANGUAGE_MAPs     K/opt/pipecat/venv/lib/python3.12/site-packages/pipecat/services/rime/tts.pylanguage_to_rime_languager5   7   sI     	UUUUUL Hl%HH    c                      e Zd ZU dZ ed       Zedz  ez  ed<    ed       Z	e
dz  ez  ed<    ed       Zedz  ez  ed	<    ed
       Zedz  ez  ed<    ed       Zedz  ez  ed<    ed       Zedz  ez  ed<    ed       Zedz  ez  ed<    ed       Zedz  ez  ed<    ed       Ze
dz  ez  ed<    ed       Ze
dz  ez  ed<    ed       Ze
dz  ez  ed<   ddiZeeeef      ed<   y)RimeTTSSettingsa  Settings for RimeTTSService and RimeHttpTTSService.

    Parameters:
        segment: Text segmentation mode ("immediate", "bySentence", "never").
        speedAlpha: Speech speed multiplier (mistv2 only).
        reduceLatency: Whether to reduce latency at potential quality cost (mistv2 only).
        pauseBetweenBrackets: Whether to add pauses between bracketed content (mistv2 only).
        phonemizeBetweenBrackets: Whether to phonemize bracketed content (mistv2 only).
        noTextNormalization: Whether to disable text normalization (mistv2 only).
        saveOovs: Whether to save out-of-vocabulary words (mistv2 only).
        inlineSpeedAlpha: Inline speed control markup.
        repetition_penalty: Token repetition penalty (arcana only, 1.0-2.0).
        temperature: Sampling temperature (arcana only, 0.0-1.0).
        top_p: Cumulative probability threshold (arcana only, 0.0-1.0).
    c                      t         S Nr    r6   r4   <lambda>zRimeTTSSettings.<lambda>\       I r6   default_factoryNsegmentc                      t         S r:   r;   r<   r6   r4   r=   zRimeTTSSettings.<lambda>]   s     r6   
speedAlphac                      t         S r:   r;   r<   r6   r4   r=   zRimeTTSSettings.<lambda>^   s    9 r6   reduceLatencyc                      t         S r:   r;   r<   r6   r4   r=   zRimeTTSSettings.<lambda>_   s    R[ r6   pauseBetweenBracketsc                      t         S r:   r;   r<   r6   r4   r=   zRimeTTSSettings.<lambda>`   s    V_ r6   phonemizeBetweenBracketsc                      t         S r:   r;   r<   r6   r4   r=   zRimeTTSSettings.<lambda>a       QZ r6   noTextNormalizationc                      t         S r:   r;   r<   r6   r4   r=   zRimeTTSSettings.<lambda>b   s    i r6   saveOovsc                      t         S r:   r;   r<   r6   r4   r=   zRimeTTSSettings.<lambda>c   s    Y r6   inlineSpeedAlphac                      t         S r:   r;   r<   r6   r4   r=   zRimeTTSSettings.<lambda>d   rK   r6   repetition_penaltyc                      t         S r:   r;   r<   r6   r4   r=   zRimeTTSSettings.<lambda>e       ) r6   temperaturec                      t         S r:   r;   r<   r6   r4   r=   zRimeTTSSettings.<lambda>f   r>   r6   top_pspeakervoice_aliases)__name__
__module____qualname____doc__r   rA   strr   __annotations__rC   floatrE   boolrG   rI   rL   rN   rP   rR   rU   rW   rZ   r   r   r<   r6   r4   r8   r8   J   s=     ',<M&NGS4Z)#N+0AR+SJy(S-2CT-UM4$;*U49J[4\$+	1\8=N_8`dTkI5`38IZ3[y0[(->O(PHdTkI%P/4EV/WcDj9,W38IZ3[y0[,1BS,TK	)T&+<M&NE54<)#N*3W)=HhtCH~&=r6   r8   c                       e Zd ZU dZ ed       Zedz  ez  ed<    ed       Z	e
dz  ez  ed<    ed       Ze
dz  ez  ed	<    ed
       Ze
dz  ez  ed<   ddiZeeeef      ed<   y)RimeNonJsonTTSSettingsa7  Settings for RimeNonJsonTTSService.

    Parameters:
        segment: Text segmentation mode ("immediate", "bySentence", "never").
        repetition_penalty: Token repetition penalty (1.0-2.0).
        temperature: Sampling temperature (0.0-1.0).
        top_p: Cumulative probability threshold (0.0-1.0).
    c                      t         S r:   r;   r<   r6   r4   r=   zRimeNonJsonTTSSettings.<lambda>v   r>   r6   r?   NrA   c                      t         S r:   r;   r<   r6   r4   r=   zRimeNonJsonTTSSettings.<lambda>w   rK   r6   rR   c                      t         S r:   r;   r<   r6   r4   r=   zRimeNonJsonTTSSettings.<lambda>x   rT   r6   rU   c                      t         S r:   r;   r<   r6   r4   r=   zRimeNonJsonTTSSettings.<lambda>y   r>   r6   rW   rX   rY   rZ   )r[   r\   r]   r^   r   rA   r_   r   r`   rR   ra   rU   rW   rZ   r   r   r<   r6   r4   rd   rd   k   s     ',<M&NGS4Z)#N38IZ3[y0[,1BS,TK	)T&+<M&NE54<)#N*3W)=HhtCH~&=r6   rd   c                       e Zd ZU dZeZeed<    G d de      Zdddddddddd	de	d	e
e	   d
e	de
e	   de
e   de
e   de
e   de
e   de
e   de
e   f fdZdefdZdede	dz  fdZdee	ef   fdZde	de	fdZdede	fdZde	de	de	de	fdZde	dede	fd Zd!edee	ef   f fd"Zd<de	d#e	defd$Zde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- Z(d. Z)d/ Z*d#e	fd0Z+d#e	fd1Z,d#e	fd2Z-d3e.d4e.d5e.de.fd6Z/d=d#e
e	   fd7Z0d8 Z1e2jf                  fd'e4d9e2f fd:Z5e6de	d#e	de7e4df   fd;       Z8 xZ9S )>RimeTTSServicezText-to-Speech service using Rime's websocket API.

    Uses Rime's websocket JSON API to convert text to speech with word-level timing
    information. Supports interruptions and maintains context across multiple messages
    within a turn.
    	_settingsc                      e Zd ZU dZej
                  Zee   ed<   dZ	ee
   ed<   dZee   ed<   dZee   ed<   dZee   ed<   dZee   ed<   dZee   ed	<   dZee   ed
<   dZee   ed<   dZee   ed<   dZee   ed<   y)RimeTTSService.InputParamsa  Configuration parameters for Rime TTS service.

        .. deprecated:: 0.0.105
            Use ``settings=RimeTTSSettings(...)`` instead.

        Parameters:
            language: Language for synthesis. Defaults to English.
            segment: Text segmentation mode ("immediate", "bySentence", "never").
            speed_alpha: Speech speed multiplier.
            repetition_penalty: Token repetition penalty (arcana only).
            temperature: Sampling temperature (arcana only).
            top_p: Cumulative probability threshold (arcana only).
            reduce_latency: Whether to reduce latency at potential quality cost (mistv2 only).
            pause_between_brackets: Whether to add pauses between bracketed content (mistv2 only).
            phonemize_between_brackets: Whether to phonemize bracketed content (mistv2 only).
            no_text_normalization: Whether to disable text normalization (mistv2 only).
            save_oovs: Whether to save out-of-vocabulary words (mistv2 only).
        r%   NrA   speed_alpharR   rU   rW   reduce_latencypause_between_bracketsphonemize_between_bracketsno_text_normalization	save_oovs)r[   r\   r]   r^   r   r0   r%   r	   r`   rA   r_   rn   ra   rR   rU   rW   ro   rb   rp   rq   rr   rs   r<   r6   r4   InputParamsrm      s    	& (0{{(8$2!%#%'+Xe_+.2HUO2'+Xe_+!%x%)--15559"HTN904x~4$(	8D>(r6   rt   Nzwss://users-ws.rime.ai/ws3)	voice_idurlmodelsample_rateparamssettingstext_aggregatortext_aggregation_modeaggregate_sentencesapi_keyru   rv   rw   rx   ry   rz   r{   r|   r}   c       
         n   t        dddddddddddddd      }|t        dt         d       ||_        |t        dt         d       ||_        |t        dt                |s|j                  r| j                  |j                        nd|_        |j                  |_        |j                  |_        |j                  |_	        |j                  |_
        |j                  |_        |j                  |_        |j                  |_        |j                   |_        |j$                  |_        |j(                  |_        ||j-                  |       t/        | `  d|	|
dd	d	d	||d
| d| _        d| _        |st7        dg| j8                        | _        || _        || _        d| _         d| _!        i | _"        y)ao  Initialize Rime TTS service.

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

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

            url: Rime websocket API endpoint.
            model: Model ID to use for synthesis.

                .. deprecated:: 0.0.105
                    Use ``settings=RimeTTSSettings(model=...)`` instead.

            sample_rate: Audio sample rate in Hz.
            params: Additional configuration parameters.

                .. deprecated:: 0.0.105
                    Use ``settings=RimeTTSSettings(...)`` instead.

            settings: Runtime-updatable settings. When provided alongside deprecated
                parameters, ``settings`` values take precedence.
            text_aggregator: Custom text aggregator for processing input text.

                .. deprecated:: 0.0.95
                    Use an LLMTextProcessor before the TTSService for custom text aggregation.

            text_aggregation_mode: How to aggregate incoming text before synthesis.
            aggregate_sentences: Deprecated. Use text_aggregation_mode instead.

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

            **kwargs: Additional arguments passed to parent class.
        arcanaN)rw   rY   r%   rA   rP   rC   rR   rU   rW   rE   rG   rI   rL   rN   ru   rY   rw   ry   FT)r|   r}   push_text_framespush_stop_framespause_frame_processingappend_trailing_spacerx   rz   pcmr   )spell())aggregation_typer<   )#r8   r   rY   rw   r%   language_to_service_languagerA   rn   rC   rR   rU   rW   ro   rE   rp   rG   rq   rI   rr   rL   rs   rN   apply_updatesuper__init___audio_format_sampling_rater!   _text_aggregation_mode_text_aggregator_api_key_url_receive_task_cumulative_time_extra_msg_fields)selfr~   ru   rv   rw   rx   ry   rz   r{   r|   r}   kwargsdefault_settings	__class__s                r4   r   zRimeTTSService.__init__   s   h +!#!%%) $!
( ":H%-""7OWE%*" "8_=JP//D55fooF_c !) ,2>> (.4.@.@ +6<6O6O 3/5/A/A ,)/ &171F1F .8>8U8U 5<B<]<] 97=7S7S 4,2,<,< ) ))(3 
	
"7 3"!#'"&#%
	
 
	
 # %7 !D4O4O%D!
  	 " !!#r6   r&   c                      y)zCheck if this service can generate processing metrics.

        Returns:
            True, as Rime service supports metrics generation.
        Tr<   r   s    r4   can_generate_metricsz#RimeTTSService.can_generate_metrics5       r6   r%   c                     t        |      S zConvert pipecat language to Rime language code.

        Args:
            language: The language to convert.

        Returns:
            The Rime-specific language code, or None if not supported.
        r5   r   r%   s     r4   r   z+RimeTTSService.language_to_service_language=       )22r6   c                 d   | j                   j                  | j                   j                  | j                  | j                  d}| j                   j
                  | j                   j
                  |d<   | j                   j                  | j                   j                  |d<   | j                   j                  | j                   j                  |d<   | j                   j                  dk(  r| j                   j                  | j                   j                  |d<   | j                   j                  | j                   j                  |d<   | j                   j                  | j                   j                  |d<   |S | j                   j                  | j                   j                  |d	<   | j                   j                  ,t        j                  | j                   j                        |d
<   | j                   j                  ,t        j                  | j                   j                        |d<   | j                   j                   ,t        j                  | j                   j                         |d<   | j                   j"                  ,t        j                  | j                   j"                        |d<   |S )a-  Build query params for the WebSocket URL from current settings.

        Returns:
            Dictionary of query parameters for the WebSocket URL.
            Only explicitly-set values are included. Boolean mistv2 params
            are serialized with ``json.dumps()`` for the wire format.
        rX   modelIdaudioFormatsamplingRatelangrA   rC   r   rR   rU   rW   rE   rG   rI   rL   rN   )rk   rY   rw   r   r   r%   rA   rC   rR   rU   rW   rE   rG   jsondumpsrI   rL   rN   )r   ry   s     r4   _build_ws_paramszRimeTTSService._build_ws_paramsH  s    ~~++~~++-- //	"
 >>"".!^^44F6N>>!!- $ 6 6F9>>$$0#'>>#<#<F< >>8+~~00</3~~/P/P+,~~))5(,(B(B}%~~##/"&.."6"6w  ~~++7*...*F*F'~~22>15DNN<_<_1`-.~~66B59ZZNN;;612 ~~11=04

4>>;];]0^,-~~&&2%)ZZ0G0G%Hz"r6   textc                     d|  dS )z!Wrap text in Rime spell function.r   r   r<   )r   s    r4   SPELLzRimeTTSService.SPELLu  s    vQr6   secondsc                     d| dz   dS )z)Convenience method to create a pause tag.<i  >r<   )r   s    r4   	PAUSE_TAGzRimeTTSService.PAUSE_TAGy  s    7T>"!$$r6   wordphonemec                 F    d| j                   d<   |j                  ||       S )zConvenience method to support Rime's custom pronunciations feature.

        https://docs.rime.ai/api-reference/custom-pronunciation
        TrI   )r   replace)r   r   r   r   s       r4   	PRONOUNCEzRimeTTSService.PRONOUNCE}  s)    
 >B9:||DWI//r6   speedc                     | j                   si | _         | j                   j                  dd      j                  d      }dj                  |t	        |      gz         | j                   d<   d| dS )z,Convenience method to support inline speeds.rP    ,[])r   getsplitjoinr_   )r   r   r   
speed_valss       r4   INLINE_SPEEDzRimeTTSService.INLINE_SPEED  sk    %%%'D"++//0BBGMMcR
58XXjCPUJ<>W5X124&{r6   deltac                    K   t         |   |       d{   }|r<| j                  r0| j                          d{    | j	                          d{    |S 7 D7  7 
w)Apply a settings delta and reconnect if necessary.

        Since all settings are WebSocket URL query parameters,
        any setting change requires reconnecting to apply the new values.
        N)r   _update_settings
_websocket_disconnect_connectr   r   changedr   s      r4   r   zRimeTTSService._update_settings  sY      077t""$$$--/!! 8 %!s1   A!A%A!AA!AA!A!A!
context_idc                 T    ||d}| j                   r|| j                   z  }i | _         |S )z Build JSON message for Rime API.)r   	contextId)r   )r   r   r   msgs       r4   
_build_msgzRimeTTSService._build_msg  s2    *5!!4)))C%'D"
r6   c                 
    ddiS )zBuild clear operation message.	operationclearr<   r   s    r4   _build_clear_msgzRimeTTSService._build_clear_msg  s    W%%r6   c                 
    ddiS )z&Build end-of-stream operation message.r   eosr<   r   s    r4   _build_eos_msgzRimeTTSService._build_eos_msg  s    U##r6   framec                    K   t         |   |       d{    | j                  | _        | j	                          d{    y7 .7 w)zStart the service and establish websocket connection.

        Args:
            frame: The start frame containing initialization parameters.
        Nr   startrx   r   r   r   r   r   s     r4   r   zRimeTTSService.start  A      gmE""""..mmo 	#    A	A(A	A A	A	c                 t   K   t         |   |       d{    | j                          d{    y7 7 w)z`Stop the service and close connection.

        Args:
            frame: The end frame.
        Nr   stopr   r   s     r4   r   zRimeTTSService.stop  s6      gl5!!!    	"    848688c                 t   K   t         |   |       d{    | j                          d{    y7 7 w)zcCancel current operation and clean up.

        Args:
            frame: The cancel frame.
        Nr   cancelr   r   s     r4   r   zRimeTTSService.cancel  s6      gnU###    	$ r   c                   K   t         |           d{    | j                          d{    | j                  r=| j                  s0| j                  | j                  | j                              | _        yyy7 f7 Pw)z6Establish websocket connection and start receive task.Nr   r   _connect_websocketr   r   create_task_receive_task_handler_report_errorr   r   s    r4   r   zRimeTTSService._connect  sm     g   %%'''??4#5#5!%!1!1$2L2LTM_M_2`!aD $6?	 	!'    B A<B A>AB >B c                    K   t         |           d{    | j                  r*| j                  | j                         d{    d| _        | j	                          d{    y7 S7 &7 	w)z.Close websocket connection and clean up tasks.Nr   r   r   cancel_task_disconnect_websocketr   s    r4   r   zRimeTTSService._disconnect  sf     g!###""4#5#5666!%D((*** 	$ 7 	+3   A/A).A/A+A/#A-$A/+A/-A/c                 B  K   	 | j                   r'| j                   j                  t        j                  u ry| j	                         }dj                  d |j                         D              }| j                   d| }dd| j                   i}t        ||       d{   | _         | j                  d       d{    y7 #7 # t        $ rL}| j                  d	| |
       d{  7   d| _         | j                  d|        d{  7   Y d}~yd}~ww xY ww)z7Connect to Rime websocket API with configured settings.N&c              3   6   K   | ]  \  }}|	| d|   y wN=r<   .0kvs      r4   	<genexpr>z4RimeTTSService._connect_websocket.<locals>.<genexpr>  s"     XTQ!-1QCjX   
?AuthorizationBearer )additional_headerson_connectedzError connecting: 	error_msg	exceptionon_connection_error)r   stater$   OPENr   r   itemsr   r   websocket_connect_call_event_handler	Exception
push_error)r   	ws_paramsry   rv   headerses         r4   r   z!RimeTTSService._connect_websocket  s     	J4??#8#8EJJ#F--/IXXXY__5FXXFYYKq)C&'$--(ABG$5cg$VVDO**>::: W: 	J//.@,DPQ/RRR"DO**+@QCIII	Jsu   D2C DA(C C C =C>C DC C 	DD)C,*"DDDDDDc                   K   	 | j                          d{    | j                  rf| j                  j                  t        j                  | j                                      d{    | j                  j                          d{    | j                          d{    d| _        | j                  d       d{    y7 7 a7 A# t        $ r)}| j                  d| |       d{  7   Y d}~ld}~ww xY w7 `7 B# | j                          d{  7   d| _        | j                  d       d{  7   w xY ww)z+Close websocket connection and reset state.NzError disconnecting: r  on_disconnected)stop_all_metricsr   sendr   r   r   closer  r  remove_active_audio_contextr  r   r  s     r4   r   z$RimeTTSService._disconnect_websocket  s    
	>'')))oo**4::d6I6I6K+LMMMoo++--- 22444"DO**+<=== *M- 	V//.CA3,GST/UUU	V 5= 22444"DO**+<===s   EC CAC 'C	(!C 	C
C E!D"EDEC 	C C 	C?C:/C20C:5D :C??D EEED E;D><EEc                 H    | j                   r| j                   S t        d      )z3Get active websocket connection or raise exception.Websocket not connectedr   r  r   s    r4   _get_websocketzRimeTTSService._get_websocket      ????"122r6   c                    K   | j                          d{    |rI| j                         j                  t        j                  | j                                      d{    yy7 P7 w)z-Clear the Rime speech queue and stop metrics.N)r  r  r  r   r   r   r   r   s     r4   _close_contextzRimeTTSService._close_context   sX     ##%%%%%',,TZZ8M8M8O-PQQQ  	&Qs"   A+A'A	A+ A)!A+)A+c                 B   K   | j                  |       d{    y7 w)zIClear the Rime speech queue and stop metrics when the bot is interrupted.Nr   r  s     r4   on_audio_context_interruptedz+RimeTTSService.on_audio_context_interrupted  s     !!*---   c                 B   K   | j                  |       d{    y7 w)aS  Clear server-side state and stop metrics after the Rime context finishes playing.

        Rime does not send a server-side completion signal (e.g. ``done`` / ``end_of_stream`` /
        ``audio_end``), so we explicitly send a ``clear`` message to clean up
        any residual server-side state once all audio has been delivered.
        Nr"  r  s     r4   on_audio_context_completedz)RimeTTSService.on_audio_context_completed
  s      !!*---r$  wordsstartsendsc                    g }t        t        |||            D ]p  \  }\  }}}|j                         s|| j                  z   }	t	        |j                  d      dk(        }
|
r|r|d   \  }}||z   |f|d<   ^|j                  ||	f       r |S )a@  Calculate word timing pairs with proper spacing and punctuation.

        Args:
            words: List of words from Rime.
            starts: List of start times for each word.
            ends: List of end times for each word.

        Returns:
            List of (word, timestamp) pairs with proper timing.
        z,.!?r   )	enumeratezipstripr   rb   append)r   r'  r(  r)  
word_pairsir   
start_time_adjusted_startis_punctuation	prev_word	prev_times                r4   _calculate_word_timesz$RimeTTSService._calculate_word_times  s     
(1#eVT2J(K 	:$A$j!::< ($*?*??N "$**V"4":;N*'1"~$	9"+d"2I!>
2!!4"89	: r6   c                    K   |xs | j                         }|r| j                  syt        j                  |  d       | j	                         j                  t        j                  ddi             d{    y7 w)"Flush any pending audio synthesis.N: flushing audior   flush)get_active_audio_context_idr   r
   tracer  r  r   r   )r   r   flush_ids      r4   flush_audiozRimeTTSService.flush_audio0  sd     C!A!A!Ctv-./!!#((['4J)KLLLs   A3A=5A;6A=c                   K   | j                         2 3 d{   }t        j                  |      }|r | j                  |j	                  d            sA|d   }|d   dk(  rJt        t        j                  |d         | j                  d|      }| j                  ||       d{    |d   dk(  r|j	                  d	i       }|j	                  d
g       }|j	                  dg       }|j	                  dg       }|s|s| j                  |||      }	|	s| j                  |	|       d{    |d   | j                  z   | _        t        j                  d| j                          [|d   dk(  se| j                  t!                      d{    | j#                          d{    | j%                  d|d           d{    | j'                          7 7 A7 7 V7 @7 "6 yw)z$Process incoming websocket messages.Nr   typechunkdata   audiorx   num_channelsr   
timestampsword_timestampsr'  r   endr   r+  zUpdated cumulative time to: errorError: message)r  )r  r   loadsaudio_context_availabler   r   base64	b64decoderx   append_to_audio_contextr8  add_word_timestampsr   r
   debug
push_framer   r  r  reset_active_audio_context)
r   rO  r   r   r   rI  r'  r(  r)  r0  s
             r4   _receive_messagesz RimeTTSService._receive_messages9  s    !002 $	2 $	2'**W%Cd::377;;OP[)J6{g%( **3v;7 $ 0 0!")	 22:uEEEV, WW%6;
"w3#4!~~eR0V!%!;!;E64!PJ!"66zj6YYY04R4;P;P0P-'CDDYDYCZ%[\V'ooo&7888++---oo'#i.9I0JoKKK//1I$	2 F Z
 9-KG 3s   G3G1G#G1B
G3%G&&AG3>G3G3G3.G)/AG38G3G+G3,G--G3G/G3#G1&G3)G3+G3-G3/G31G3	directionc                    K   t         |   ||       d{    t        |t        t        f      r,t        |t              r| j                  dg       d{    yyy7 G7 	w)zPush frame and handle end-of-turn conditions.

        Args:
            frame: The frame to push.
            direction: The direction to push the frame.
        N)Resetr   )r   rW  
isinstancer   r   rU  r   r   rZ  r   s      r4   rW  zRimeTTSService.push_framea  sd      g 	222eo/@AB%1..~>>> 2 C 	3 ?s!   A#A?A#A!A#!A#c                  K   t        j                  |  d| d       	 | j                  r&| j                  j                  t        j
                  u r| j                          d{    	 | j                  |      sG| j                  |       d{    | j                          d{    t        |       d| _        | j                  ||      }| j                         j                  t        j                   |             d{    | j#                  |       d{    d y7 7 7 7 )7 # t$        $ r]}t'        d|        t)        |       | j+                          d{  7   | j                          d{  7   Y d}~yd}~ww xY w# t$        $ r}t'        d|        Y d}~yd}~ww xY ww)	a  Generate speech from text using Rime's 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.
        : Generating TTS [r   NrL  r   )r   r   Unknown error occurred: rM  )r
   rV  r   r  r$   CLOSEDr   rQ  create_audio_contextstart_ttfb_metricsr   r   r   r  r  r   r   start_tts_usage_metricsr  r   r   r   )r   r   r   r   r  s        r4   run_ttszRimeTTSService.run_ttsm  s     	v/vQ78	C??doo&;&;u||&Kmmo%%33J?33J???11333)Z@@,-D)oo4JoG))+00CAAA224888 J% & @3
 B8  )A!'EFF%<<&&(((mmo%%  	C%=aS#ABBB	Cs   G	AF! $D.%F! *%D8 D0D8 'D2(A"D8 
D4D8 #D6$D8 (F! -G	.F! 0D8 2D8 4D8 6D8 8	F4F5E86FFFF! G	FF! !	G*G<G	GG	)r   r   r:   ):r[   r\   r]   r^   r8   Settingsr`   r   rt   r_   r	   intr    r   rb   r   r   r   r   dictr   r   r   ra   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r   r#  r&  listr8  r@  rY  r   
DOWNSTREAMr   rW  r"   r   rg  __classcell__r   s   @r4   rj   rj   ~   s    H )i  )L #'/#%)(,.28<?C.2H$ H$ 3-	H$
 H$ }H$ c]H$ %H$ ?+H$ ""45H$  ((;<H$ &d^H$Td 	3X 	3#* 	3*$sCx. *Z C  C  %5 %S %0c 0 0s 0s 0 U s K DcN s S $ &$ &$ $ ! !!+ !b+J$>3Rs R.S ..3 .4  T d :MHSM M&2P JXIbIb 
?e 
? 
? !C# !C3 !C>%QU+;V !C !Cr6   rj   c                        e Zd ZU dZeZeed<    G d de      Zddddddde	de
e	   d	ej                  d
e
e	   de
e   de
e   de
e   f fdZdefdZdede	dz  fdZede	de	deedf   fd       Z xZS )RimeHttpTTSServicezRime HTTP-based text-to-speech service.

    Provides text-to-speech synthesis using Rime's HTTP API for batch processing.
    Suitable for use cases where streaming is not required.
    rk   c                       e Zd ZU dZej
                  Zee   ed<   dZ	ee
   ed<   dZee
   ed<   dZee   ed<   dZee   ed	<   dZee
   ed
<   y)RimeHttpTTSService.InputParamsaf  Configuration parameters for Rime HTTP TTS service.

        .. deprecated:: 0.0.105
            Use ``settings=RimeTTSSettings(...)`` instead.

        Parameters:
            language: Language for synthesis. Defaults to English.
            pause_between_brackets: Whether to add pauses between bracketed content.
            phonemize_between_brackets: Whether to phonemize bracketed content.
            inline_speed_alpha: Inline speed control markup.
            speed_alpha: Speech speed multiplier. Defaults to 1.0.
            reduce_latency: Whether to reduce latency at potential quality cost.
        r%   Frp   rq   Ninline_speed_alphag      ?rn   ro   )r[   r\   r]   r^   r   r0   r%   r	   r`   rp   rb   rq   rs  r_   rn   ra   ro   r<   r6   r4   rt   rr    se    	 (0{{(8$21665:"HTN:,0HSM0'*Xe_*)..r6   rt   N)ru   rw   rx   ry   rz   r~   ru   aiohttp_sessionrw   rx   ry   rz   c                p   t        dddddddddddddd      }	|t        dt         d       ||	_        |t        dt         d       ||	_        |t        dt                |s|j                  r| j                  |j                        nd|	_        |j                  |	_        |j                  |	_	        |j                  |	_        |j                  |	_        |j                  r|j                  nd|	_        ||	j!                  |       t#        
| H  d|d	d	|	d
| || _        || _        d| _        d| _        y)a  Initialize Rime HTTP TTS service.

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

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

            aiohttp_session: Shared aiohttp session for HTTP requests.
            model: Model ID to use for synthesis.

                .. deprecated:: 0.0.105
                    Use ``settings=RimeTTSSettings(model=...)`` instead.

            sample_rate: Audio sample rate in Hz.
            params: Additional configuration parameters.

                .. deprecated:: 0.0.105
                    Use ``settings=RimeTTSSettings(...)`` instead.

            settings: Runtime-updatable settings. When provided alongside deprecated
                parameters, ``settings`` values take precedence.
            **kwargs: Additional arguments passed to parent TTSService.
        mistv2Nr*   )rw   rY   r%   rA   rC   rE   rG   rI   rL   rN   rP   rR   rU   rW   ru   rY   rw   ry   T)rx   r   push_start_framerz   z!https://users.rime.ai/v1/rime-ttsr   r<   )r8   r   rY   rw   r%   r   rn   rC   ro   rE   rp   rG   rq   rI   rs  rP   r   r   r   r   _session	_base_urlr   )r   r~   ru   rt  rw   rx   ry   rz   r   r   r   s             r4   r   zRimeHttpTTSService.__init__  sd   L +!%%) $!#
$ ":H%-""7OWE%*" "8_=JP//D55fooF_d !) /5.@.@ +171F1F .8>8U8U 5<B<]<] 9171J1JF--PT !1
 ))(3 	
#!!%		

 	
  '< #r6   r&   c                      y)zCheck if this service can generate processing metrics.

        Returns:
            True, as Rime HTTP service supports metrics generation.
        Tr<   r   s    r4   r   z'RimeHttpTTSService.can_generate_metrics  r   r6   r%   c                     t        |      S r   r   r   s     r4   r   z/RimeHttpTTSService.language_to_service_language  r   r6   r   r   c                z  K   t        j                  |  d| d       dd| j                   dd}| j                  j                  | j                  j
                  | j                  j                  | j                  j                  | j                  j                  d}| j                  j                  | j                  j                  |d	<   ||d
<   | j                  j                  |d<   | j                  j                  |d<   | j                  |d<   |d   dk(  rd|d<   d}nd}	 | j                  j                  | j                  ||      4 d{   }|j                   dk7  rHd|j                    }t#        |       	 ddd      d{    | j%                          d{    y| j'                  |       d{    | j(                  }| j+                  |j,                  j/                  |      ||      2 3 d{   }	| j%                          d{    |	 '7 7 7 7 j7 *7 6 ddd      d{  7   n# 1 d{  7  sw Y   nxY wn(# t0        $ 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 Rime's HTTP 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.
        r`  r   z	audio/pcmr  zapplication/json)Acceptr   zContent-Type)r   rC   rE   rG   rI   NrP   r   rX   r   r   r   z	audio/wavr}  TF)r   r     zRime TTS error: HTTP rb  )strip_wav_headerr   ra  )r
   rV  r   rk   r%   rC   rE   rG   rI   rP   rY   rw   rx   rx  postry  statusr   stop_ttfb_metricsrf  
chunk_size"_stream_audio_frames_from_iteratorcontentiter_chunkedr  )r   r   r   r  payloadneed_to_strip_wav_headerresponseerror_message
CHUNK_SIZEr   r  s              r4   rg  zRimeHttpTTSService.run_tts&  s     	v/vQ78 "&t}}o6.
 NN++..33!^^99$(NN$G$G(,(O(O
 >>**6*...*I*IG&'!^^11	!^^11	"&"2"2 9) +GH'+$',$	+}}))Wg *     ??c)&;HOO;L$MM$=99   . ((*** 224888!__
#'#J#J$$11*=%=) $K $    %
 00222K%   . + 9 
 3$         (  	C%=aS#ABBB	C ((***$((***s  D"J;%,I H&I /II H(I J;'H*(J;-IH,=I?H2H.H2IH0
I&I (I *J;,I.H20I2I3I >I?I IIII J 	J $I;6J ;J  J J;JJ;J81J42J88J;)r[   r\   r]   r^   r8   rh  r`   r   rt   r_   r	   aiohttpClientSessionri  r   rb   r   r   r   r"   r   r   rg  rm  rn  s   @r4   rp  rp    s     H/i /4 #'#%)(,.2_# _# 3-	_#
 !.._# }_# c]_# %_# ?+_#Bd 	3X 	3#* 	3 ?+# ?+3 ?+>%QU+;V ?+ ?+r6   rp  c                       e Zd ZU dZeZeed<    G d de      Zd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   de
e   f fdZdefdZdede	fdZdef fdZdef fdZdef fdZej2                  fdedef fdZ fdZ fdZd  Zd! Zd" Z d*d#e
e	   fd$Z!d% Z"e#d&e	d#e	de$edf   fd'       Z%d(e&de'e	e(f   f fd)Z) xZ*S )+RimeNonJsonTTSServicea  Pipecat TTS service for Rime's non-JSON WebSocket API.

    .. deprecated:: 0.0.102
        Arcana now supports JSON WebSocket with word-level timestamps via the
        ``wss://users-ws.rime.ai/ws3`` endpoint. Use :class:`RimeTTSService`
        with ``model="arcana"`` instead.

    This service enables Text-to-Speech synthesis over WebSocket endpoints
    that require plain text (not JSON) messages and return raw audio bytes.

    Limitations:
        - Does not support word-level timestamps or context IDs.
        - Intended specifically for integrations where the TTS provider only
          accepts and returns non-JSON messages.
    rk   c                       e Zd ZU dZdZee   ed<   dZee	   ed<   dZ
ee   ed<   dZee   ed<   dZee   ed<   dZeee	ef      ed<   y)	!RimeNonJsonTTSService.InputParamsae  Configuration parameters for Rime Non-JSON WebSocket TTS service.

        .. deprecated:: 0.0.105
            Use ``settings=RimeNonJsonTTSSettings(...)`` instead.

        Args:
            language: Language for synthesis. Defaults to English.
            segment: Text segmentation mode ("immediate", "bySentence", "never").
            repetition_penalty: Token repetition penalty (1.0-2.0).
            temperature: Sampling temperature (0.0-1.0).
            top_p: Cumulative probability threshold (0.0-1.0).
            extra: Additional parameters to pass to the API (for future compatibility).
        Nr%   rA   rR   rU   rW   extra)r[   r\   r]   r^   r%   r	   r   r`   rA   r_   rR   ra   rU   rW   r  rj  r   r<   r6   r4   rt   r  }  sh    	 (,(8$+!%#%.2HUO2'+Xe_+!%x%*.xS#X'.r6   rt   Nzwss://users.rime.ai/wsr   )	ru   rv   rw   audio_formatrx   ry   rz   r}   r|   r~   ru   rv   rw   r  rx   ry   rz   r}   r|   c       
            t        ddddddd      }|t        dt         d       ||_        |t        dt         d       ||_        |t        dt                |sr|j                  r| j                  |j                        nd|_        |j                  |_        |j                  |_        |j                  |_        |j                  |_	        ||j                  |       t        | 0  d
||	|
dddd|d	| || _        || _        || _        || _        |r;|j"                  r/| j$                  j"                  j'                  |j"                         d| _        y)a  Initialize Rime Non-JSON WebSocket TTS service.

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

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

            url: Rime websocket API endpoint.
            model: Model ID to use for synthesis.

                .. deprecated:: 0.0.105
                    Use ``settings=RimeNonJsonTTSSettings(model=...)`` instead.

            audio_format: Audio format to use.
            sample_rate: Audio sample rate in Hz.
            params: Additional configuration parameters.

                .. deprecated:: 0.0.105
                    Use ``settings=RimeNonJsonTTSSettings(...)`` 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. Set to ``TextAggregationMode.SENTENCE``
                    to aggregate text into sentences before synthesis, or
                    ``TextAggregationMode.TOKEN`` to stream tokens directly for lower latency.

            text_aggregation_mode: How to aggregate text before synthesis.
            **kwargs: Additional arguments passed to parent class.
        Nr   )rY   rw   r%   rA   rR   rU   rW   ru   rY   rw   ry   T)rx   r}   r|   r   rw  r   r   rz   r<   )rd   r   rY   rw   r%   r   rA   rR   rU   rW   r   r   r   r   r   r   r   r  rk   updater   )r   r~   ru   rv   rw   r  rx   ry   rz   r}   r|   r   r   r   s                r4   r   zRimeNonJsonTTSService.__init__  sj   d 2#
 ":/EwO%-""7,BGL%*" "8-CDJP//D55fooF_c !) ,2>> (6<6O6O 3/5/A/A ,)/ & ))(3 
	
# 3"7!!#'"&%
	
 
	
 *)	fllNN  ''5!r6   r&   c                      y)zCheck if this service can generate processing metrics.

        Returns:
            True, as Rime Non-JSON WebSocket service supports metrics generation.
        Tr<   r   s    r4   r   z*RimeNonJsonTTSService.can_generate_metrics  r   r6   r%   c                     t        |      S )a>  Convert pipecat Language enum to Rime language code.

        Args:
            language: The Language enum value to convert.

        Returns:
            Three-letter Rime language code (e.g., 'eng' for English).
            Falls back to the language's base code with a warning if not in the verified list.
        r   r   s     r4   r   z2RimeNonJsonTTSService.language_to_service_language  s     )22r6   r   c                    K   t         |   |       d{    | j                  | _        | j	                          d{    y7 .7 w)zStart the Rime Non-JSON WebSocket TTS service.

        Args:
            frame: The start frame containing initialization parameters.
        Nr   r   s     r4   r   zRimeNonJsonTTSService.start  r   r   c                 t   K   t         |   |       d{    | j                          d{    y7 7 w)z&Stop the service and close connection.Nr   r   s     r4   r   zRimeNonJsonTTSService.stop  s4     gl5!!!    	" r   c                 t   K   t         |   |       d{    | j                          d{    y7 7 w)z&Cancel current operation and clean up.Nr   r   s     r4   r   zRimeNonJsonTTSService.cancel"  s4     gnU###    	$ r   rZ  c                 B   K   t         |   ||       d{    y7 w)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   rW  r^  s      r4   rW  z RimeNonJsonTTSService.push_frame'  s      g 	222s   c                   K   t         |           d{    | j                          d{    | j                  r=| j                  s0| j                  | j                  | j                              | _        yyy7 f7 Pw)z6Establish WebSocket connection and start receive task.Nr   r   s    r4   r   zRimeNonJsonTTSService._connect0  sm     g   %%'''??4#5#5!%!1!1$2L2LTM_M_2`!aD $6? 	!'r   c                    K   t         |           d{    | j                  r*| j                  | j                         d{    d| _        | j	                          d{    y7 S7 &7 	w)z.Close WebSocket connection and clean up tasks.Nr   r   s    r4   r   z!RimeNonJsonTTSService._disconnect8  sd     g!###""4#5#5666!%D((*** 	$ 7*r   c                   K   	 | j                   r'| j                   j                  t        j                  u ry| j                  j
                  | j                  j                  | j                  | j                  d}| j                  j                  | j                  j                  |d<   | j                  j                  | j                  j                  |d<   | j                  j                  | j                  j                  |d<   | j                  j                  | j                  j                  |d<   | j                  j                  | j                  j                  |d<   |j                  | j                  j                         dj!                  d	 |j#                         D              }| j$                   d
| }dd| j&                   i}t)        ||d       d{   | _         | j+                  d       d{    y7 #7 # t,        $ rL}| j/                  d| |       d{  7   d| _         | j+                  d|        d{  7   Y d}~yd}~ww xY ww)z:Establish WebSocket connection to Rime non-JSON websocket.Nr   r   rA   rR   rU   rW   r   c              3   6   K   | ]  \  }}|	| d|   y wr   r<   r   s      r4   r   z;RimeNonJsonTTSService._connect_websocket.<locals>.<genexpr>Y  s"     \TQam1QCj\r   r   r   r  i   )r  max_sizer  ra  r  r  )r   r  r$   r	  rk   rY   rw   r   r   r%   rA   rR   rU   rW   r  r  r   r
  r   r   r  r  r  r  )r   settings_dictry   rv   r  r  s         r4   r   z(RimeNonJsonTTSService._connect_websocketA  s     	J4??#8#8EJJ#F  >>//>>//#11 $ 3 3	M ~~&&2(,(?(?f%~~%%1+/>>+A+Ai(~~00<6:nn6W6W23~~))5/3~~/I/Im,~~##/)-)=)=g&  !5!56XX\]5H5H5J\\FYYKq)C&'$--(ABG$5:J% DO **>::: ; 	J//.Fqc,JVW/XXX"DO**+@QCIII	Jsu   I#2H I#F,H #H$H H	H I#H 	H 	I I-H0."IIII#I  I#c                   K   	 | j                          d{    | j                  rZ| j                  j                  d       d{    | j                  j                          d{    t	        j
                  d       d| _        | j                  d       d{    y7 7 ^7 ># t        $ r)}| j                  d| |       d{  7   Y d}~Td}~ww xY w7 @# d| _        | j                  d       d{  7   w xY ww)z.Close WebSocket connection and clean up state.Nz<EOS>z)Disconnected from Rime non-JSON websocketra  r  r  )	r  r   r  r  r
   rV  r  r  r  r  s     r4   r   z+RimeNonJsonTTSService._disconnect_websockete  s     	>'')))oo**7333oo++---HI #DO**+<=== * 4- 	Y//.Fqc,JVW/XXX	Y > #DO**+<===s   DB) B#.B) B%!B) (B')B) DCD#B) %B) 'B) )	C2CCCC  CC  D D<C?=DDc                 H    | j                   r| j                   S t        d      )z3Get active WebSocket connection or raise exception.r  r  r   s    r4   r  z$RimeNonJsonTTSService._get_websockett  r  r6   r   c                    K   | j                   syt        j                  |  d       | j                   j                  d       d{    y7 w)r:  Nr;  z<FLUSH>)r   r
   r>  r  r  s     r4   r@  z!RimeNonJsonTTSService.flush_audioz  s<     v-./oo""9---s   AAAAc                   K   | j                         2 3 d{   }	 t        |t              rX| j                          d{    t	        || j
                  d| j                               }| j                  |       d{    s7 n7 G7 	# t        $ r)}| j                  d| |       d{  7   Y d}~d}~ww xY w6 yw)z6Process incoming WebSocket messages (raw audio bytes).NrE  rF  rN  r  )
r  r]  bytesr  r   rx   r=  rW  r  r  )r   rO  r   r  s       r4   rY  z'RimeNonJsonTTSService._receive_messages  s     !002 	L 	L'Lgu-00222,%$($4$4%&#'#C#C#E	E //%000	L 3 1 Loo'!oKKKL 3sx   CCBCC#B B?B B
BCCB
B	B>B9.B1/B94C9B>>Cr   c                  K   t        j                  |  d| d       	 | j                  r&| j                  j                  t        j
                  u r| j                          d{    	 | j                         j                  |       d{    | j                  |       d{    d y7 K7 %7 # t        $ r]}t        d|        t        |       | j                          d{  7   | j                          d{  7   Y d}~yd}~ww xY w# t        $ r}t        d|        Y d}~yd}~ww xY ww)a  Generate speech from text using Rime's streaming 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.
        r`  r   Nra  rb  rL  )r
   rV  r   r  r$   rc  r   r  r  rf  r  r   r   r   )r   r   r   r  s       r4   rg  zRimeNonJsonTTSService.run_tts  s     	v/vQ78	C??doo&;&;u||&Kmmo%%
))+00666224888 J & 78  )A!'EFF%<<&&(((mmo%%  	C%=aS#ABBB	Cs   EAD $B0%D *"B6 B2B6 %B4&B6 *D /E0D 2B6 4B6 6	D?4D3C64DDDD EDD 	E(D?:E?EEr   c                    K   t         |   |       d{   }|rEt        j                  d       | j	                          d{    | j                          d{    |S 7 M7  7 
w)r   Nz<Settings changed, reconnecting WebSocket with new parameters)r   r   r
   rV  r   r   r   s      r4   r   z&RimeNonJsonTTSService._update_settings  s`      077LLWX""$$$--/!! 8 %!s3   A*A$.A*A&A*A(A*&A*(A*r:   )+r[   r\   r]   r^   rd   rh  r`   r   rt   r_   r	   ri  rb   r   r   r   r   r   r   r   r   r   r   r   r   rl  r   rW  r   r   r   r   r  r@  rY  r"   r   rg  r   rj  r   r   rm  rn  s   @r4   r  r  i  s     &H%%/i /4 #'+#!%)(,59.2?Cj" j" 3-	j"
 j" }j" j" c]j" %j" 12j" &d^j"  ((;<j"Xd 
3X 
3# 
3 ! !
!+ !
 JXIbIb 3e 3 3b+"JH>3.HSM .L$ C# C3 C>%QU+;V C C:K DcN  r6   r  )@r^   rR  r   dataclassesr   r   typingr   r   r   r   r	   r  logurur
   pydanticr   pipecat.frames.framesr   r   r   r   r   r   r   r   r   "pipecat.processors.frame_processorr   pipecat.services.settingsr   r   r   r   pipecat.services.tts_servicer   r   r   r   pipecat.transcriptions.languager   r   'pipecat.utils.text.base_text_aggregatorr    'pipecat.utils.text.skip_tags_aggregatorr!   (pipecat.utils.tracing.service_decoratorsr"   websockets.asyncio.clientr#   r  websockets.protocolr$   ModuleNotFoundErrorr  rM  r  r_   r5   r8   rd   rj   rp  r  r<   r6   r4   <module>r     s)     ( @ @   
 
 
 > _ _  G F F ?,F)I IS I& >k > >@ >[ > >$QC( QChT+ T+nV3 Vq  ,FLL;qc"#FLLTU
&qc*
++,s    C D2DD