
    b6i:                     $   d dl Z d dlZd dlZd dlZd dlmZ d dlmZ d dlmZ 	 d dl	m
Z ddlmZ  G d	 d
ee      Z G d dee      Z G d dej$                  d      Z G d dej$                  d      Z G d d      Zy# e$ r	  ed      w xY w)    N)Enum)overload)Required)connectzgThe websockets package is required for realtime speech-to-text. Install it with: pip install websockets   )RealtimeConnectionc                   ,    e Zd ZdZdZdZdZdZdZdZ	dZ
y	)
AudioFormatz/Audio format options for realtime transcriptionpcm_8000	pcm_16000	pcm_22050	pcm_24000	pcm_44100	pcm_48000	ulaw_8000N)__name__
__module____qualname____doc__PCM_8000	PCM_16000	PCM_22050	PCM_24000	PCM_44100	PCM_48000	ULAW_8000     e/root/.openclaw/workspace/visionaryfx/venv/lib/python3.12/site-packages/elevenlabs/realtime/scribe.pyr
   r
      s(    9HIIIIIIr   r
   c                       e Zd ZdZdZdZy)CommitStrategyz
    Strategy for committing transcription results.

    VAD: Voice Activity Detection - automatically commits when speech ends
    MANUAL: Manual commit - requires calling commit() to commit the segment
    vadmanualN)r   r   r   r   VADMANUALr   r   r   r!   r!       s     CFr   r!   c                       e Zd ZU dZee   ed<   ee   ed<   ee   ed<   e	ed<   e
ed<   e
ed<   eed<   eed	<   eed
<   eed<   y)RealtimeAudioOptionsa0  
    Options for providing audio chunks manually.

    Attributes:
        model_id: The model ID to use for transcription (required)
        audio_format: The audio format (required)
        sample_rate: The sample rate in Hz (required)
        commit_strategy: Strategy for committing transcriptions (optional, defaults to MANUAL)
        vad_silence_threshold_secs: Silence threshold in seconds for VAD (must be between 0.3 and 3.0)
        vad_threshold: Threshold for voice activity detection (must be between 0.1 and 0.9)
        min_speech_duration_ms: Minimum speech duration in milliseconds (must be between 50 and 2000)
        min_silence_duration_ms: Minimum silence duration in milliseconds (must be between 50 and 2000)
        language_code: An ISO-639-1 or ISO-639-3 language_code corresponding to the language of the audio file. Can sometimes improve transcription performance if known beforehand.
        include_timestamps: Whether to receive the committed_transcript_with_timestamps event after committing the segment (optional, defaults to False)
    model_idaudio_formatsample_ratecommit_strategyvad_silence_threshold_secsvad_thresholdmin_speech_duration_msmin_silence_duration_mslanguage_codeinclude_timestampsN)r   r   r   r   r   str__annotations__r
   intr!   floatboolr   r   r   r'   r'   +   sR     sm;''### %%  r   r'   F)totalc                   x    e Zd ZU dZee   ed<   ee   ed<   eed<   eed<   eed<   e	ed<   e	ed<   eed	<   e
ed
<   y)RealtimeUrlOptionsa  
    Options for streaming audio from a URL.

    Attributes:
        model_id: The model ID to use for transcription (required)
        url: The URL of the audio stream (required)
        commit_strategy: Strategy for committing transcriptions (optional, defaults to MANUAL)
        vad_silence_threshold_secs: Silence threshold in seconds for VAD (must be between 0.3 and 3.0)
        vad_threshold: Threshold for voice activity detection (must be between 0.1 and 0.9)
        min_speech_duration_ms: Minimum speech duration in milliseconds (must be between 50 and 2000)
        min_silence_duration_ms: Minimum silence duration in milliseconds (must be between 50 and 2000)
        language_code: An ISO-639-1 or ISO-639-3 language_code corresponding to the language of the audio file. Can sometimes improve transcription performance if known beforehand.
        include_timestamps: Whether to receive the committed_transcript_with_timestamps event after committing the segment (optional, defaults to False)
    r(   urlr+   r,   r-   r.   r/   r0   r1   N)r   r   r   r   r   r2   r3   r!   r5   r4   r6   r   r   r   r9   r9   G   sG     sm	### %%  r   r9   c                      e Zd ZdZddedefdZededefd       Z	ede
defd       Z	dej                  ee
f   defd	Z	dedefd
Zde
defdZdeddfdZ	 	 	 	 	 	 ddedededej                   e   dej                   e   dej                   e   dej                   e   dej                   e   dej                   e   defdZy)ScribeRealtimea+  
    Helper class for creating realtime speech-to-text connections.

    Supports two modes:
    1. URL-based: Stream audio from a URL (uses ffmpeg for conversion)
    2. Manual: Send audio chunks yourself

    Example (URL-based):
        ```python
        connection = await elevenlabs.speech_to_text.realtime.connect({
            "model_id": "scribe_v2_realtime",
            "url": "https://stream.example.com/audio.mp3"
        })
        ```

    Example (Manual chunks):
        ```python
        connection = await elevenlabs.speech_to_text.realtime.connect({
            "model_id": "scribe_v2_realtime",
            "audio_format": AudioFormat.PCM_16000,
            "sample_rate": 16000
        })

        # Send audio chunks
        await connection.send({"audio_base_64": chunk})
        ```
    api_keybase_urlc                      || _         || _        y N)r=   r>   )selfr=   r>   s      r   __init__zScribeRealtime.__init__~   s     r   optionsreturnc                    K   y wr@   r   rA   rC   s     r   r   zScribeRealtime.connect         !   c                    K   y wr@   r   rF   s     r   r   zScribeRealtime.connect   rG   rH   c                    K   d|v }d|vrt        d      |r1| j                  t        j                  t        |             d{   S | j                  t        j                  t        |             d{   S 7 57 w)a  
        Create a realtime transcription connection.

        Args:
            options: Either RealtimeAudioOptions for manual chunk sending or RealtimeUrlOptions for URL streaming

        Returns:
            RealtimeConnection instance ready to send/receive data

        Raises:
            ValueError: If invalid options are provided
            RuntimeError: If ffmpeg is not available (for URL-based streaming)

        Example:
            ```python
            # URL-based streaming
            connection = await elevenlabs.speech_to_text.realtime.connect({
                "model_id": "scribe_v2_realtime",
                "url": "https://stream.example.com/audio.mp3",
            })

            # Manual chunks
            connection = await elevenlabs.speech_to_text.realtime.connect({
                "model_id": "scribe_v2_realtime",
                "audio_format": AudioFormat.PCM_16000,
                "sample_rate": 16000,
                "commit_strategy": CommitStrategy.MANUAL
            })
            ```
        r:   r(   z/model_id is required for realtime transcriptionN)
ValueError_connect_urltypingcastr9   _connect_audior'   )rA   rC   is_url_modes      r   r   zScribeRealtime.connect   st     F w&W$NOO**6;;7I7+STTT,,V[[9Mw-WXXX UXs$   AA>A:0A>5A<6A><A>c                   K   |d   }|j                  d      }|j                  d      }|j                  dt        j                        }|j                  d      }|j                  d      }|j                  d      }|j                  d      }	|j                  d	      }
|j                  d
d      }|r|st        d      | j	                  ||j
                  |j
                  ||||	|
|	      }t        |d| j                  i       d{   }t        ||d      }t        j                  |j                               |_        |j                  d       |S 7 Mw)z'Connect with manual audio chunk sendingr(   r)   r*   r+   r,   r-   r.   r/   r0   r1   Fz?audio_format and sample_rate are required for manual audio mode	r(   r)   r+   r,   r-   r.   r/   r0   r1   
xi-api-keyadditional_headersN	websocketcurrent_sample_rateffmpeg_processopen)getr!   r%   rK   _build_websocket_urlvaluewebsocket_connectr=   r   asynciocreate_task_start_message_handler_message_task_emit)rA   rC   r(   r)   r*   r+   r,   r-   r.   r/   r0   r1   ws_urlrW   
connections                  r   rO   zScribeRealtime._connect_audio   s\    :&{{>2kk-0!++&79N9NO%,[[1M%N"O4!(-E!F")++.G"HO4$[[)=uE;^__ **%+++11'A'#9$;'1 + 

 , ,dll;
 
	 ( +

 $+#6#6z7X7X7Z#[
  !
s   DE
EAEc                   K   |d   }|j                  d      }|j                  dt        j                        }|j                  d      }|j                  d      }|j                  d      }|j                  d      }|j                  d      }	|j                  d	d
      }
|st        d      d}t        j
                  }| j                  ||j                  |j                  |||||	|
	      }t        |d| j                  i       d{   }	 t        j                  dd|dddt        |      dddg
t        j                  t        j                  d      }t%        |||      }t'        j(                  |j+                               |_        |j/                  d       t'        j(                  | j1                  |             |S 7 # t        $ r' |j!                  dd       d{  7   t#        d      w xY ww) z3Connect with URL-based audio streaming using ffmpegr(   r:   r+   r,   r-   r.   r/   r0   r1   Fzurl is required for URL modei>  rR   rS   rT   Nffmpegz-iz-fs16lez-arz-ac1-r   )stdoutstderrbufsizei  zffmpeg not foundziffmpeg is required for URL-based audio streaming. Please install ffmpeg: https://ffmpeg.org/download.htmlrV   rZ   )r[   r!   r%   rK   r
   r   r\   r]   r^   r=   
subprocessPopenr2   PIPEDEVNULLFileNotFoundErrorcloseRuntimeErrorr   r_   r`   ra   rb   rc   _stream_ffmpeg_to_websocket)rA   rC   r(   r:   r+   r,   r-   r.   r/   r0   r1   r*   r)   rd   rW   rY   re   s                    r   rL   zScribeRealtime._connect_url   s     :&kk% !++&79N9NO%,[[1M%N"O4!(-E!F")++.G"HO4$[[)=uE;<< ",, **%+++11'A'#9$;'1 + 

 , ,dll;
 
		'--#'3{+3 "!))N* ( +)

 $+#6#6z7X7X7Z#[
   	D<<ZHIS
( ! 	//$(:;;;J 	s8   DG9	G
G9AG A.G9G6$G'%G66G9re   Nc                 \  K   |j                   r|j                   j                  sy	 d}t        j                         }	 |j	                  d|j                   j                  j
                  |       d{   }|sn^t        j                  |      j                  d      }	 |j                  d|i       d{    t        j                  d       d{    |j                   r8|j                   j                          	 |j                   j                  d	
       yy7 7 i# t        $ r!}|j                  ddd| i       Y d}~nd}~ww xY w7 {# t        $ r!}|j                  ddd| i       Y d}~d}~ww xY w# t        j                   $ r |j                   j                          Y yw xY w# |j                   rk|j                   j                          	 |j                   j                  d	
       w # t        j                   $ r |j                   j                          Y w w xY ww xY ww)z-Stream audio from ffmpeg process to WebSocketNi    zutf-8audio_base_64errorzFailed to send audio: g{Gz?zFFmpeg streaming error: r   )timeout)rY   rk   r_   get_event_looprun_in_executorreadbase64	b64encodedecodesend	Exceptionrc   sleepkillwaitrn   TimeoutExpired)rA   re   
chunk_sizeloopchunkchunk_base64es          r   ru   z*ScribeRealtime._stream_ffmpeg_to_websocket7  s    ((
0I0I0P0P'	5J))+D"22--4499    &//6==gF$//?L*IJJJ mmD)))- 8 (())..05--2212= )5 K  $$Ww:PQRPS8T.UV
 * 	QWw2J1#0N&OPP	Q "00 5--2245	 (())..05--2212=!00 5--2245	 )s   $H,AE 2D3+E D! 5D6D! :E EE &H,?E= H,E D! !	E*EE EE 	E:E50F0 5E::F0 =-F-*H,,F--H,0'H)G54H)5-H%"H)$H%%H))H,r(   r)   r+   r,   r-   r.   r/   r0   r1   c
                    | j                   j                  dd      j                  dd      }
d| d| d| g}||j                  d|        ||j                  d	|        ||j                  d
|        ||j                  d|        ||j                  d|        |	+|j                  dt        |	      j	                                 dj                  |      }|
 d| S )z-Build the WebSocket URL with query parameterszhttps://zwss://zhttp://zws://z	model_id=zaudio_format=zcommit_strategy=zvad_silence_threshold_secs=zvad_threshold=zmin_speech_duration_ms=zmin_silence_duration_ms=zlanguage_code=zinclude_timestamps=&z/v1/speech-to-text/realtime?)r>   replaceappendr2   lowerjoin)rA   r(   r)   r+   r,   r-   r.   r/   r0   r1   baseparamsquery_strings                r   r\   z#ScribeRealtime._build_websocket_urle  s!    }}$$Z:BB9gV z"L>*/0
 &1MM78R7STU$MMN=/:;!-MM34J3KLM".MM45L4MNO$MMN=/:;)MM/4F0G0M0M0O/PQRxx'3L>BBr   )zwss://api.elevenlabs.io)NNNNNN)r   r   r   r   r2   rB   r   r'   r   r   r9   rM   UnionrO   rL   ru   Optionalr5   r4   r6   r\   r   r   r   r<   r<   a   s   8! !s ! !%! 
! !
 !#! 
! !
+Y24FFG+Y 
+YZ.,@ .EW .`J*< JAS JX,5<N ,5SW ,5f >B047;8<.248&C&C &C 	&C
 %+OOE$:&C u-&C !' 4&C "(!5&C s+&C #OOD1&C 
&Cr   r<   )r_   r}   rn   rM   enumr   r   typing_extensionsr   websockets.asyncio.clientr   r^   ImportErrorre   r   r2   r
   r!   	TypedDictr'   r9   r<   r   r   r   <module>r      s          &F +#t S$ 6++5 8)) 4jC jCk  
	2 s   B B