
    b6i#                         d dl Z d dlZd dlZd dlZd dlmZ ej                  rd dlmZ  G d de	e      Z
 G d d      Zy)    N)Enum)ClientConnectionc                   \    e Zd ZdZdZdZdZdZdZdZ	dZ
d	Zd
ZdZdZdZdZdZdZdZdZdZdZy)RealtimeEventsz(Events emitted by the RealtimeConnectionopenclosesession_startedpartial_transcriptcommitted_transcript$committed_transcript_with_timestampserror
auth_errorquota_exceededcommit_throttledtranscriber_errorunaccepted_terms_errorrate_limitedinput_errorqueue_overflowresource_exhaustedsession_time_limit_exceededchunk_size_exceededinsufficient_audio_activityN)__name__
__module____qualname____doc__OPENCLOSESESSION_STARTEDPARTIAL_TRANSCRIPTCOMMITTED_TRANSCRIPT$COMMITTED_TRANSCRIPT_WITH_TIMESTAMPSERROR
AUTH_ERRORQUOTA_EXCEEDEDCOMMIT_THROTTLEDTRANSCRIBER_ERRORUNACCEPTED_TERMS_ERRORRATE_LIMITEDINPUT_ERRORQUEUE_OVERFLOWRESOURCE_EXHAUSTEDSESSION_TIME_LIMIT_EXCEEDEDCHUNK_SIZE_EXCEEDEDINSUFFICIENT_AUDIO_ACTIVITY     i/root/.openclaw/workspace/visionaryfx/venv/lib/python3.12/site-packages/elevenlabs/realtime/connection.pyr   r      sn    2DE'O-1+Q(EJ%N)+5!LK%N-"?/"?r2   r   c                       e Zd ZdZddddedej                  ej                     fdZ	de
d	ej                  d
dfdZde
d
dfdZddZdej                  e
ej                   f   d
dfdZddZddZddZy)RealtimeConnectiona
  
    A WebSocket connection for real-time speech-to-text transcription.

    This class handles bidirectional WebSocket communication with the ElevenLabs
    speech-to-text API, managing audio streaming and receiving transcription results.

    Example:
        ```python
        connection = await client.speech_to_text.realtime.connect({
            "audio_format": AudioFormat.PCM_16000,
            "sample_rate": 16000
        })

        connection.on(RealtimeEvents.PARTIAL_TRANSCRIPT, lambda data: print(data))
        connection.on(RealtimeEvents.COMMITTED_TRANSCRIPT, lambda data: print(data))

        # Send audio
        connection.send({"audioBase64": audio_chunk})

        # When done
        connection.commit()
        await connection.close()
        ```
    N	websocketr   current_sample_rateffmpeg_processc                 J    || _         || _        || _        i | _        d | _        y N)r6   r7   r8   _event_handlers_message_task)selfr6   r7   r8   s       r3   __init__zRealtimeConnection.__init__=   s)    "#6 ,OQ<@r2   eventcallbackreturnc                 z    || j                   vrg | j                   |<   | j                   |   j                  |       y)a  
        Register an event handler for a specific event type.

        Args:
            event: The event type to listen for (from RealtimeEvents enum)
            callback: The function to call when the event occurs

        Example:
            ```python
            def handle_transcript(data):
                print(f"Transcript: {data['transcript']}")

            connection.on(RealtimeEvents.PARTIAL_TRANSCRIPT, handle_transcript)
            ```
        N)r;   append)r=   r?   r@   s      r3   onzRealtimeConnection.onD   s;      ,,,*,D  'U#**84r2   c                     || j                   v r| j                   |   D ]  }	  ||  
 yy# t        $ r}t        d| d|        Y d}~,d}~ww xY w)z(Emit an event to all registered handlerszError in event handler for z: N)r;   	Exceptionprint)r=   r?   argshandleres        r3   _emitzRealtimeConnection._emitX   sk    D(((//6 FFTNF ) ! F7wbDEEFs   +	AA

Ac                 6  K   	 | j                   2 3 d{   }	 t        j                  |      }|j                  d      }	 t	        |      }| j                  ||       t        j                  t        j                  t        j                  t        j                  t        j                  t        j                  t        j                  t        j                  t        j                  t        j                  t        j                   t        j"                  h}||v r | j                  t        j$                  |       *7 &# t&        $ r Y w xY w# t        j(                  $ r0}| j                  t        j$                  dd| i       Y d}~zd}~ww xY w6 nA# t*        $ r5}| j                  t        j$                  dt-        |      i       Y d}~nd}~ww xY w| j                  t        j.                         y# | j                  t        j.                         w xY ww)z*Start handling incoming WebSocket messagesNmessage_typer   zFailed to parse message: )r6   jsonloadsgetr   rK   r%   r&   r'   r(   r)   r*   r+   r,   r-   r.   r/   r0   r$   
ValueErrorJSONDecodeErrorrF   strr   )r=   messagedatarM   r?   error_eventsrJ   s          r3   _start_message_handlerz)RealtimeConnection._start_message_handlera   s    $	-!% a aga::g.D#'88N#;L .| <

5$/ +55*99*;;*<<*AA*77*66*99*==*FF*>>*FF( !L0 JJ~';';TB5a6 &  ++ aJJ~33gAZ[\Z]?^5_``a= "0@  	@JJ~++gs1v->??	@ JJ~++,DJJ~++,s   HF FD:FF &EC7D=8F :F=	E	EE		EF%F
F 
FF G5 	G+GG5 GG5  H5!HHrU   c                   K   | j                   st        d      d|j                  dd      d| j                  |j                  d      d}| j                   j	                  t        j                  |             d{    y7 w)	a  
        Send an audio chunk to the server for transcription.

        Args:
            data: Dictionary containing the following keys:
                - audio_base_64 (str): Base64-encoded audio data to transcribe
                - previous_text (str, optional): Previous transcript text to provide context
                  for more accurate transcription

        Raises:
            RuntimeError: If the WebSocket connection is not open

        Example:
            ```python
            # Send audio chunk
            connection.send({
                "audio_base_64": base64_encoded_audio
            })

            # Send audio chunk with context - can only be sent with the first chunk of audio
            connection.send({
                "audio_base_64": base64_encoded_audio,
                "previous_text": "Previously transcribed text for context"
            })
            ```
        WebSocket is not connectedinput_audio_chunkaudio_base_64 Fprevious_text)rM   r[   commitsample_rater]   N)r6   RuntimeErrorrP   r7   sendrN   dumps)r=   rU   rT   s      r3   ra   zRealtimeConnection.send   sp     6 ~~;<< 0!XXor:33!XXo6
 nn!!$**W"5666s   A:B<B=Bc                    K   | j                   st        d      ddd| j                  d}| j                   j                  t	        j
                  |             d{    y7 w)a  
        Commits the segment, triggering a COMMITTED_TRANSCRIPT event and clearing the buffer.
        It's recommend to commit often when using CommitStrategy.MANUAL to keep latency low.

        Raises:
            RuntimeError: If the WebSocket connection is not open

        Remarks:
            Only needed when using CommitStrategy.MANUAL.
            When using CommitStrategy.VAD, commits are handled automatically by the server.

        Example:
            ```python
            # Send all audio chunks
            for chunk in audio_chunks:
                connection.send({"audioBase64": chunk})

            # Commit the audio segment
            await connection.commit()
            ```
        rY   rZ   r\   T)rM   r[   r^   r_   N)r6   r`   r7   ra   rN   rb   )r=   rT   s     r3   r^   zRealtimeConnection.commit   sY     , ~~;<< 033	
 nn!!$**W"5666s   AA$A"A$c                   K   | j                          d{    | j                  r$| j                  j                  dd       d{    | j                  rK| j                  j	                         s0| j                  j                          	 | j                   d{    yyy7 7 ^7 # t        j                  $ r Y yw xY ww)aG  
        Closes the WebSocket connection and cleans up resources.
        This will terminate any ongoing transcription and stop ffmpeg processes if running.

        Remarks:
            After calling close(), this connection cannot be reused.
            Create a new connection if you need to start transcribing again.

        Example:
            ```python
            connection.on(RealtimeEvents.COMMITTED_TRANSCRIPT, async lambda data: (
                print("Committed:", data["transcript"]),
                await connection.close()
            ))
            ```
        Ni  zUser ended conversation)_cleanupr6   r   r<   donecancelasyncioCancelledErrorr=   s    r3   r   zRealtimeConnection.close   s     " mmo>>..&&t-FGGGd&8&8&=&=&?%%'(((( '@ 	G ))) sX   CB#/CB%ACB) B'B)  C%C'B) )B?<C>B??Cc                   K   | j                   r?| j                   j                          	 | j                   j                  d       d| _         yy# t        j                  $ r | j                   j                          Y 8w xY ww)z(Clean up resources like ffmpeg processes   )timeoutN)r8   killwait
subprocessTimeoutExpiredrj   s    r3   re   zRealtimeConnection._cleanup   st     $$&+##(((3 #'D  ,, +##((*+s(   'BA 	B-A?<B>A??Br:   )rA   N)r   r   r   r   inttypingOptionalrp   Popenr>   rS   CallablerD   rK   rW   DictAnyra   r^   r   re   r1   r2   r3   r5   r5   #   s    2A"4 A3 A`f`o`opz  qA  qA  aB A5 5v 54 5(F3 F$ F&-P&7v{{3

?; &7 &7P 7D6'r2   r5   )rh   rN   rp   rs   enumr   TYPE_CHECKINGwebsockets.asyncio.clientr   rS   r   r5   r1   r2   r3   <module>r|      s<        	:@S$ @0S' S'r2   