o
    lWi#                     @   sb   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 de	eZ
G dd dZdS )    N)Enum)ClientConnectionc                   @   s\   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dS )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 r/   r/   b/var/www/html/asistente-voz-ia/venv/lib/python3.10/site-packages/elevenlabs/realtime/connection.pyr      s*    r   c                   @   s   e Zd ZdZddddedejej fddZ	d	e
d
ejddfddZd	e
ddfddZdddZdeje
ejf ddfddZdddZdddZdddZdS )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                 C   s"   || _ || _|| _i | _d | _d S N)r2   r3   r4   _event_handlers_message_task)selfr2   r3   r4   r/   r/   r0   __init__=   s
   
zRealtimeConnection.__init__eventcallbackreturnc                 C   s(   || j vr
g | j |< | j | | dS )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)r6   append)r8   r:   r;   r/   r/   r0   onD   s   

zRealtimeConnection.onc                 G   sf   || j v r/| j | D ]&}z||  W q
 ty. } ztd| d|  W Y d}~q
d}~ww dS dS )z(Emit an event to all registered handlerszError in event handler for z: N)r6   	Exceptionprint)r8   r:   argshandlerer/   r/   r0   _emitX   s   
 zRealtimeConnection._emitc                    sX  zzs| j 2 zl3 dH W }zGt|}|d}z1t|}| || 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 rG| tj| W n	 tyQ   Y nw W q tjyr } z| tjdd| i W Y d}~qd}~ww 6 W n ty } z| tjdt|i W Y d}~nd}~ww W | tj dS W | tj dS | tj w )z*Start handling incoming WebSocket messagesNmessage_typer   zFailed to parse message: )r2   jsonloadsgetr   rD   r#   r$   r%   r&   r'   r(   r)   r*   r+   r,   r-   r.   r"   
ValueErrorJSONDecodeErrorr?   strr   )r8   messagedatarE   r:   error_eventsrC   r/   r/   r0   _start_message_handlera   sT   

$ "#z)RealtimeConnection._start_message_handlerrM   c                    sL   | j stdd|ddd| j|dd}| j t|I dH  dS )	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)rE   rR   commitsample_raterT   N)r2   RuntimeErrorrH   r3   sendrF   dumps)r8   rM   rL   r/   r/   r0   rX      s   
zRealtimeConnection.sendc                    s<   | j stdddd| jd}| j t|I dH  dS )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()
            ```
        rP   rQ   rS   T)rE   rR   rU   rV   N)r2   rW   r3   rX   rF   rY   )r8   rL   r/   r/   r0   rU      s   zRealtimeConnection.commitc                    sv   |   I dH  | jr| jddI dH  | jr7| j s9| j  z	| jI dH  W dS  tjy6   Y dS w dS dS )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)_cleanupr2   r   r7   donecancelasyncioCancelledErrorr8   r/   r/   r0   r      s   
zRealtimeConnection.closec                    sR   | j r'| j   z	| j jdd W n tjy!   | j   Y nw d| _ dS dS )z(Clean up resources like ffmpeg processes   )timeoutN)r4   killwait
subprocessTimeoutExpiredr_   r/   r/   r0   rZ      s   

zRealtimeConnection._cleanupr5   )r<   N)r   r   r   r   inttypingOptionalrd   Popenr9   rK   Callabler>   rD   rO   DictAnyrX   rU   r   rZ   r/   r/   r/   r0   r1   #   s     
	(
(
"r1   )r]   rF   rd   rg   enumr   TYPE_CHECKINGwebsockets.asyncio.clientr   rK   r   r1   r/   r/   r/   r0   <module>   s    