
    3h\              	       (   S r SSKrSSKrSSKrSSKrSSKrSSKrSSKJ	r	  SSK
Jr  SSKJr  SSKJrJrJrJrJrJrJrJr  SSKJrJr  SSKrSSKrSS	KJrJrJrJ r   SS
K!J"r"  SSK#J$r$  SSK%J&r&J'r'J(r(J)r)  SSKJ*r*J+r+  S\,S\-S\\\,\,4   \,4   4S jr.S\\/\,4   S\/4S jr0S\/4S jr1S\,S\-S\-4S jr2S\,S\-4S jr3S\,S\-S\-4S jr4S\\/\,4   S\-S\\,SS4   4S jr5S\"S\\/\,4   S\/4S  jr6S\/4S! jr7S"\/S#\/S$\/S\/4S% jr8S&\"S\-4S' jr9 " S( S)5      r:g)*zCommunicate with the service. Only the Communicate class should be used by
end-users. The other classes and functions are for internal use only.    N)nullcontext)TextIOWrapper)Queue)AsyncGeneratorContextManagerDict	GeneratorListOptionalTupleUnion)escapeunescape   )DEFAULT_VOICESEC_MS_GEC_VERSIONWSS_HEADERSWSS_URL)	TTSConfig)DRM)NoAudioReceivedUnexpectedResponseUnknownResponseWebSocketError)CommunicateStateTTSChunkdataheader_lengthreturnc                     [        U [        5      (       d  [        S5      e0 nU SU R                  S5       H  nUR                  SS5      u  pEXRU'   M     X US-   S 4$ )z
Returns the headers and data from the given data.

Args:
    data (bytes): The data to be parsed.
    header_length (int): The length of the header.

Returns:
    tuple: The headers and data to be used in the request.
zdata must be bytesNs   
   :r      )
isinstancebytes	TypeErrorsplit)r   r   headerslinekeyvalues         L/var/www/auris/envauris/lib/python3.13/site-packages/edge_tts/communicate.pyget_headers_and_datar,   (   so     dE"",--G^m$**73ZZa(
 4 *,---    stringc                 n   [        U [        5      (       a  U R                  S5      n [        U [        5      (       d  [	        S5      e[        U 5      n[        U5       HE  u  p#[        U5      nSUs=::  a  S::  d$  O  SUs=::  a  S::  d  O  SUs=::  a  S::  d  M=  O  MA  S	X'   MG     S
R                  U5      $ )a/  
The service does not support a couple character ranges.
Most important being the vertical tab character which is
commonly present in OCR-ed PDFs. Not doing this will
result in an error from the service.

Args:
    string (str or bytes): The string to be cleaned.

Returns:
    str: The cleaned string.
utf-8zstring must be str or bytesr                    )	r#   r$   decodestrr%   list	enumerateordjoin)r.   charsidxcharcodes        r+   remove_incompatible_charactersrB   @   s     &%  w'fc""566F|Eu%	INNd 0b 0bD6FB6F6FEJ &
 775>r-   c                  ^    [        [        R                  " 5       5      R                  SS5      $ )zJ
Returns a UUID without dashes.

Returns:
    str: A UUID without dashes.
-r7   )r9   uuiduuid4replace r-   r+   
connect_idrI   \   s"     tzz|$$S"--r-   textlimitc                 ^    U R                  SSU5      nUS:  a  U R                  SSU5      nU$ )a  
Finds the index of the rightmost preferred split character (newline or space)
within the initial `limit` bytes of the text.

This helps find a natural word or sentence boundary for splitting, prioritizing
newlines over spaces.

Args:
    text (bytes): The byte string to search within.
    limit (int): The maximum index (exclusive) to search up to.

Returns:
    int: The index of the last found newline or space within the limit,
         or -1 if neither is found in that range.
   
r       )rfind)rJ   rK   split_ats      r+   (_find_last_newline_or_space_within_limitrQ   f   s4    " zz%E*H!|::dAu-Or-   text_segmentc                     [        U 5      nUS:  a   U SU R                  S5        U$ U$ ! [         a    US-  n Of = fUS:  a  M6  N )a  
Finds the rightmost possible byte index such that the
segment `text_segment[:index]` is a valid UTF-8 sequence.

This prevents splitting in the middle of a multi-byte UTF-8 character.

Args:
    text_segment (bytes): The byte segment being considered for splitting.

Returns:
    int: The index of the safe split point. Returns 0 if no valid split
         point is found (e.g., if the first byte is part of a multi-byte
         sequence longer than the limit allows).
r   Nr0   r   )lenr8   UnicodeDecodeError)rR   rP   s     r+   _find_safe_utf8_split_pointrV   ~   s^     < H
Q,	(#**73O
 O	 " 	MH	 Q,s   + ==rP   c                     US:  aH  SU SU ;   a?  U R                  SSU5      nU R                  SX!5      S:w  a   U$ UnUS:  a  SU SU ;   a  M?  U$ )aq  
Adjusts a proposed split point backward to prevent splitting inside an XML entity.

For example, if `text` is `b"this &amp; that"` and `split_at` falls between
`&` and `;`, this function moves `split_at` to the index before `&`.

Args:
    text (bytes): The text segment being considered.
    split_at (int): The proposed split point index, determined by whitespace
                    or UTF-8 safety.

Returns:
    int: The adjusted split point index. It will be moved to the '&'
         if an unterminated entity is detected right before the original `split_at`.
         Otherwise, the original `split_at` is returned.
r      &N   ;)rindexfind)rJ   rP   ampersand_indexs      r+   "_adjust_split_point_for_xml_entityr^      sk    " Q,44	?2++dAx899T?5;
 O # Q,44	?2 Or-   byte_lengthc              #     #    [        U [        5      (       a  U R                  S5      n [        U [        5      (       d  [	        S5      eUS::  a  [        S5      e[        U 5      U:  as  [        X5      nUS:  a  [        U 5      n[        X5      nUS:  a  [        S5      eU SU R                  5       nU(       a  Uv   XS:  a  UOSS n [        U 5      U:  a  Ms  U R                  5       nU(       a  Uv   gg7f)a  
Splits text into chunks, each not exceeding a maximum byte length.

This function prioritizes splitting at natural boundaries (newlines, spaces)
while ensuring that:
1. No chunk exceeds `byte_length` bytes.
2. Chunks do not end with an incomplete UTF-8 multi-byte character.
3. Chunks do not split XML entities (like `&amp;`) in the middle.

Args:
    text (str or bytes): The input text. If str, it's encoded to UTF-8.
    byte_length (int): The maximum allowed byte length for any yielded chunk.
                       Must be positive.

Yields:
    bytes: Text chunks (UTF-8 encoded, stripped of leading/trailing whitespace)
           that conform to the byte length and integrity constraints.

Raises:
    TypeError: If `text` is not str or bytes.
    ValueError: If `byte_length` is not positive, or if a split point
                cannot be determined (e.g., due to extremely small byte_length
                relative to character/entity sizes).
r0   ztext must be str or bytesr   z"byte_length must be greater than 0zTMaximum byte length is too small or invalid text structure near '&' or invalid UTF-8Nr   )r#   r9   encoder$   r%   
ValueErrorrT   rQ   rV   r^   strip)rJ   r_   rP   chunkremaining_chunks        r+   split_text_by_byte_lengthrf      s     6 ${{7#dE""344a=>>
d)k
!;DNa<248H 6dEa< C  Yh%%'K 1H!565 d)k
!: jjlO s   CC9C9tcescaped_textc                     [        U[        5      (       a  UR                  S5      nSU R                   SU R                   SU R
                   SU R                   SU S3$ )z
Creates a SSML string from the given parameters.

Args:
    tc (TTSConfig): The TTS configuration.
    escaped_text (str or bytes): The escaped text. If bytes, it must be UTF-8 encoded.

Returns:
    str: The SSML string.
r0   z_<speak version='1.0' xmlns='http://www.w3.org/2001/10/synthesis' xml:lang='en-US'><voice name='z'><prosody pitch='z' rate='z
' volume='z'>z</prosody></voice></speak>)r#   r$   r8   voicepitchratevolume)rg   rh   s     r+   mkssmlrn      sg     ,&&#**73	z "88*HRWWIZ		{".			r-   c                  V    [         R                  " S[         R                  " 5       5      $ )zW
Return Javascript-style date string.

Returns:
    str: Javascript-style date string.
z:%a %b %d %Y %H:%M:%S GMT+0000 (Coordinated Universal Time))timestrftimegmtimerH   r-   r+   date_to_stringrs     s      ==Ddkkm r-   
request_id	timestampssmlc                     SU  SU SU 3$ )z|
Returns the headers and data to be used in the request.

Returns:
    str: The headers and data to be used in the request.
zX-RequestId:z1
Content-Type:application/ssml+xml
X-Timestamp:zZ
Path:ssml

rH   )rt   ru   rv   s      r+   ssml_headers_plus_datarx   &  s)     zl # k "&		r-   
tts_configc           
      t    Sn[        [        [        5       [        5       [	        U S5      5      5      S-   nX-
  $ )zxCalculates the maximum message size for the given voice, rate, and volume.

Returns:
    int: The maximum message size.
i   r7   2   )rT   rx   rI   rs   rn   )ry   websocket_max_sizeoverhead_per_messages      r+   calc_max_mesg_sizer~   7  sI     $" z2&	
 	  44r-   c                   T   \ rS rSrSr\4SSSSSSSS.S	\S
\S\S\S\S\\R                     S\\   S\\
   S\\
   4S jjjrS\S\4S jrS\\S4   4S jrS\\S4   4S jr SS\\\4   S\\\\4      SS4S jjrS\\SS4   4S jr SS\\\4   S\\\\4      SS4S jjrSrg)CommunicateiK  z
Communicate with the service.
z+0%z+0HzN
   <   )rl   rm   rk   	connectorproxyconnect_timeoutreceive_timeoutrJ   rj   rl   rm   rk   r   r   r   r   c                Z   [        X#XE5      U l        [        U[        5      (       d  [	        S5      e[        [        [        U5      5      [        U R                  5      5      U l	        Ub   [        U[        5      (       d  [	        S5      eXpl
        [        U[        5      (       d  [	        S5      e[        U	[        5      (       d  [	        S5      e[        R                  " S S UU	S9U l        Ub*  [        U[        R                  5      (       d  [	        S5      eX`l        SSSS	S
.U l        g )Nztext must be strzproxy must be strzconnect_timeout must be intzreceive_timeout must be int)totalconnectsock_connect	sock_readz'connector must be aiohttp.BaseConnectorr-   r   F)partial_textoffset_compensationlast_duration_offsetstream_was_called)r   ry   r#   r9   r%   rf   r   rB   r~   textsr   intaiohttpClientTimeoutsession_timeoutBaseConnectorr   state)
selfrJ   rj   rl   rm   rk   r   r   r   r   s
             r+   __init__Communicate.__init__P  s    $E? $$$.// /1$78t/

 Zs%;%;/00$)
 /3//9::/3//9::&44(%	 
  Iw?T?T)U)UEFF:C  #$$%!&	(

r-   r   r   c                    [         R                  " U5      S    H]  nUS   nUS:X  a;  US   S   U R                  S   -   nUS   S   nUUU[        US   S   S	   5      S
.s  $ US;   a  MQ  [	        SU 35      e   [        S5      e)NMetadataTypeWordBoundaryDataOffsetr   DurationrJ   Text)typeoffsetdurationrJ   )
SessionEndzUnknown metadata type: zNo WordBoundary metadata found)jsonloadsr   r   r   r   )r   r   meta_obj	meta_typecurrent_offsetcurrent_durations         r+   __parse_metadataCommunicate.__parse_metadata  s    

4(4H (IN*V$X.<Q1RR  $,F#3J#? %, 0$Xf%5f%=f%EF	  O+!$;I;"GHH 5  !!ABBr-   c                  ^ ^#    S(U4S jjnS(U U4S jjnSn[         R                  " [        R                  " 5       S9n[        R
                  " T R                  ST R                  S9 IS h  vN oUR                  [         S[        R                  " 5        S[         S	[        5        3S
T R                  [        US9 IS h  vN mU" 5       I S h  vN   U" 5       I S h  vN   T  S h  vN nUR                   [        R"                  R$                  :X  a  UR&                  R)                  S5      n[+        XwR-                  S5      5      u  pUR/                  SS 5      n
U
S:X  a0  T R1                  U	5      nU7v   US   US   -   T R2                  S'   M  U
S:X  a6  T R2                  S   T R2                  S'   T R2                  S==   S-  ss'     GOU
S;  a  [5        S5      eM  UR                   [        R"                  R6                  :X  Ga  [9        UR&                  5      S:  a  [;        S5      e[<        R?                  UR&                  S S S5      nU[9        UR&                  5      :  a  [;        S5      e[+        UR&                  U5      u  pUR/                  S5      S:w  a  [;        S5      eUR/                  SS 5      nUS;  a  [;        S 5      eUc  [9        U	5      S!:X  a  GM  [;        S"5      e[9        U	5      S!:X  a  [;        S#5      eSnS$U	S%.7v   GM5  UR                   [        R"                  R@                  :X  d  GM`  [C        UR&                  (       a  UR&                  5      eS&5      eU(       d  [E        S'5      eS S S 5      IS h  vN   S S S 5      IS h  vN   g  GN; GN GN GN GN
 ND N&! , IS h  vN  (       d  f       N;= f N2! , IS h  vN  (       d  f       g = f7f))Nc                  \   >#    T R                  S[        5        S35      I Sh  vN   g N7f)z)Sends the command request to the service.zX-Timestamp:z
Content-Type:application/json; charset=utf-8
Path:speech.config

{"context":{"synthesis":{"audio":{"metadataoptions":{"sentenceBoundaryEnabled":"false","wordBoundaryEnabled":"true"},"outputFormat":"audio-24khz-48kbitrate-mono-mp3"}}}}
N)send_strrs   )	websockets   r+   send_command_request2Communicate.__stream.<locals>.send_command_request  s3     $$~/0 1   s   !,*,c                     >#    TR                  [        [        5       [        5       [	        T R
                  T R                  S   5      5      5      I Sh  vN   g N7f)z&Sends the SSML request to the service.r   N)r   rx   rI   rs   rn   ry   r   )r   r   s   r+   send_ssml_request/Communicate.__stream.<locals>.send_ssml_request  sL     $$&L"$

>2	 	 	s   AAAAF)cafileT)r   	trust_envtimeoutz&Sec-MS-GEC=z&Sec-MS-GEC-Version=z&ConnectionId=   )compressr   r'   sslr0   s   

s   Paths   audio.metadatar   r   r   s   turn.endr   i )s   responses
   turn.startzUnknown path receivedr"   zBWe received a binary message, but it is missing the header length.bigz9The header length is greater than the length of the data.s   audioz3Received binary message, but the path is not audio.s   Content-Type)s
   audio/mpegNz=Received binary message, but with an unexpected Content-Type.r   z<Received binary message with no Content-Type, but with data.z:Received binary message, but it is missing the audio data.audio)r   r   zUnknown errorzFNo audio was received. Please verify that your parameters are correct.r   N)#r   create_default_contextcertifiwherer   ClientSessionr   r   
ws_connectr   r   generate_sec_ms_gecr   rI   r   r   r   	WSMsgTypeTEXTr   ra   r,   r\   get_Communicate__parse_metadatar   r   BINARYrT   r   r   
from_bytesERRORr   r   )r   r   r   audio_was_receivedssl_ctxsessionreceivedencoded_data
parametersr   pathparsed_metadatar   content_typer   s   `             @r+   __streamCommunicate.__stream  s    
		 	  # ,,GMMOD((nn((
 
 ((i|C$;$;$=#>"#5"6Z\N, ** ) 
 
 &(((#%%%"+ Zh==G$5$5$:$::*2--*>*>w*GL';$&7&7&D($J &>>'48D00*.*?*?*E-- ,H5
8SS 

#9: ,<@JJ2=

#89 

#89YF9 %AA-.EFF B]]g&7&7&>&>>8==)A-0` 
 %(NN8==!3De$LM$s8=='990W 
 (< }($J
 "~~g.(:0Q  $.>>/4#HL#+@@0[ 
 $+t9>$ 1Z 
 4yA~0X 
 *.&#*D99]]g&7&7&=&==()1 <K  &%\ U
 
	
 
 

 )%Z)
 
 
 
	
 
 
 
s   A)O1-N(.O11AON+ON;N.N;"N1#N;)N7-N4
.N71IN;	>N;ON9OO1"O#O1+O.N;1N;4N77N;9O;O	OO	OO1O.O O.*O1c                  #    U R                   S   (       a  [        S5      eSU R                   S'   U R                   H/  U R                   S'    U R                  5         Sh  vN nU7v   M     g N
 M9  ! [        R
                   aT  nUR                  S:w  a  e [        R                  " U5        U R                  5         Sh  vN  nU7v   M  
  SnAM  SnAff = f7f)a=  
Streams audio and metadata from the service.

Raises:
    NoAudioReceived: If no audio is received from the service.
    UnexpectedResponse: If the response from the service is unexpected.
    UnknownResponse: If the response from the service is unknown.
    WebSocketError: If there is an error with the websocket.
r   zstream can only be called once.Tr   Ni  )	r   RuntimeErrorr   _Communicate__streamr   ClientResponseErrorstatusr   handle_client_response_error)r   messagees      r+   streamCommunicate.stream.  s      ::)*@AA*.

&' +/**DJJ~&	"%)]]_ "'!M +5"_.. "88s?003%)]]_ " "'!M &5"sr   AC!A6A3"A1#A3&A6.C!1A33A64C!6C
7CCC
C
	CC!CC!audio_fnamemetadata_fnamec                   #    Ub  [        USSS9O	[        5       nU   [        US5       nU R                  5         Sh  vN nUS   S:X  a  UR                  US   5        M(  [	        U[
        5      (       d  M?  US   S	:X  d  MJ  [        R                  " XS5        UR                  S
5        Ms   Nn
 SSS5        O! , (       d  f       O= fSSS5        g! , (       d  f       g= f7f)z5
Save the audio and metadata to the specified files.
Nwr0   )encodingwbr   r   r   r   
)openr   r   writer#   r   r   dump)r   r   r   metadatar   r   s         r+   saveCommunicate.saveM  s      ) w7 	
 tK.%!% )g6?g-KK0x77>9IIg0NN4() /..XXXsa   C%CB:B0B.
 B03B::B:)B:.B00B:1	C:
C	C	C%
C"C%c              #   
  ^ #    S[         SS4U 4S jjn[        5       n[        R                  R                  5        nUR	                  X5         UR                  5       nUc  OUv   M  SSS5        g! , (       d  f       g= f7f)z-Synchronous interface for async stream methodqueuer   Nc                    >^  SU U4S jjn[         R                  " 5       n[         R                  " U5        UR                  U" 5       5        UR	                  5         g )Nc                     >#    TR                  5         S h  vN n TR                  U 5        M   N
 TR                  S 5        g 7fN)r   put)itemr   r   s    r+   	get_itemsECommunicate.stream_sync.<locals>.fetch_async_items.<locals>.get_itemsi  s3     "&++- $$IIdO$-		$s   A202A2Ar   )asyncionew_event_loopset_event_looprun_until_completeclose)r   r   loopr   s   `  r+   fetch_async_items2Communicate.stream_sync.<locals>.fetch_async_itemsh  sD       
 ))+D""4(##IK0JJLr-   )r   
concurrentfuturesThreadPoolExecutorsubmitr   )r   r   r   executorr   s   `    r+   stream_syncCommunicate.stream_synce  sn     		U 		t 		 w224OO-5yy{<
	  544s   9B-A2)	B2
B <Bc                     [         R                  R                  5        nUR                  [        R
                  U R                  X5      5      nUR                  5         SSS5        g! , (       d  f       g= f)z,Synchronous interface for async save method.N)r   r  r  r  r   runr   result)r   r   r   r  futures        r+   	save_syncCommunicate.save_sync~  sO     224__TYY{CF MMO	 544s   A A((
A6)r   r   r   r   r   ry   r   )__name__
__module____qualname____firstlineno____doc__r   r9   r   r   r   r   r   r$   r   r   r   r   r   r   r   r	   r  r  __static_attributes__rH   r-   r+   r   r   K  sy    #6

 59#)+)+6
6
 6

 6
 6
 6
 G1126
 }6
 "#6
 "#6
pCU Cx C&Qx~ > Qf"	$	'"D 7;)3:&) !sEz!23) 
	)0Yxt';< 8 7;
3:&
 !sEz!23
 
	
 
r-   r   );r  r   concurrent.futuresr   r   r   rp   rE   
contextlibr   ior   r   r   typingr   r   r   r	   r
   r   r   r   xml.sax.saxutilsr   r   r   r   	constantsr   r   r   r   data_classesr   drmr   
exceptionsr   r   r   r   r   r   r$   r   r,   r9   rB   rI   rQ   rV   r^   rf   rn   rs   rx   r~   r   rH   r-   r+   <module>r     s  I    
   "  	 	 	 .   N N #   /.
. #.
4uu$%.05e+<  8.C .5   0e  8U c c <B
U

B*-BudD !BJy c5j(9 c 2  s s # # "59 5 5(} }r-   