
    rp0j]              	       h   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  S	S
KJrJ r 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/  \R`                  " \Rb                  " 5       S9r2S\3S\4S\\\3\34   \34   4S jr5S\\6\34   S\64S jr7S\64S jr8S\3S\4S\44S jr9S\3S\44S jr:S\3S\4S\44S jr;S\\6\34   S\4S\\3SS4   4S jr<S \&S!\\6\34   S\64S" jr=S\64S# jr>S$\6S%\6S&\6S\64S' jr? " 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)Literal   )DEFAULT_VOICEMP3_BITRATE_BPSSEC_MS_GEC_VERSIONTICKS_PER_SECONDWSS_HEADERSWSS_URL)	TTSConfig)DRM)NoAudioReceivedUnexpectedResponseUnknownResponseWebSocketError)CommunicateStateTTSChunk)cafile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         N/home/wildlama/miniconda3/lib/python3.13/site-packages/edge_tts/communicate.pyget_headers_and_datar0   2   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)r2   charsidxcharcodes        r/   remove_incompatible_charactersrF   J   s     &%  w'fc""566F|Eu%	INNd 0b 0bD6FB6F6FEJ &
 775>r1   c                  @    [         R                  " 5       R                  $ )zJ
Returns a UUID without dashes.

Returns:
    str: A UUID without dashes.
)uuiduuid4hex r1   r/   
connect_idrL   f   s     ::<r1   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)rM   rN   split_ats      r/   (_find_last_newline_or_space_within_limitrT   p   s4    " zz%E*H!|::dAu-Or1   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   Nr4   r   )lenr<   UnicodeDecodeError)rU   rS   s     r/   _find_safe_utf8_split_pointrY      s^     < H
Q,	(#**73O
 O	 " 	MH	 Q,s   + ==rS   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)rM   rS   ampersand_indexs      r/   "_adjust_split_point_for_xml_entityra      sk    " Q,44	?2++dAx899T?5;
 O # Q,44	?2 Or1   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).
r4   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'   r=   encoder(   r)   
ValueErrorrW   rT   rY   ra   strip)rM   rb   rS   chunkremaining_chunks        r/   split_text_by_byte_lengthri      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.
r4   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(   r<   voicepitchratevolume)rj   rk   s     r/   mkssmlrq     sg     ,&&#**73	z "88*HRWWIZ		{".			r1   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gmtimerK   r1   r/   date_to_stringrv      s      ==Ddkkm r1   
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

rK   )rw   rx   ry   s      r/   ssml_headers_plus_datar{   0  s)     zl # k "&		r1   c                   j   \ rS rSrSr\4SSS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 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)$CommunicateiA  z
Communicate with the service.
z+0%z+0HzSentenceBoundaryN
   <   )ro   rp   rn   boundary	connectorproxyconnect_timeoutreceive_timeoutrM   rm   ro   rp   rn   r   WordBoundaryr~   r   r   r   r   c                :   [        X#XEU5      U l        [        U[        5      (       d  [	        S5      e[        [        [        U5      5      S5      U l        Ub   [        U[        5      (       d  [	        S5      eXl	        [        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Xpl        SS	S	S
S	S	S.U l        g )Nztext must be stri   zproxy must be strzconnect_timeout must be intzreceive_timeout must be int)totalconnectsock_connect	sock_readz'connector must be aiohttp.BaseConnectorr1   r   F)partial_textoffset_compensationlast_duration_offsetstream_was_calledchunk_audio_bytescumulative_audio_bytes)r   
tts_configr'   r=   r)   ri   r   rF   textsr   intaiohttpClientTimeoutsession_timeoutBaseConnectorr   state)selfrM   rm   ro   rp   rn   r   r   r   r   r   s              r/   __init__Communicate.__init__G  s    $EI $$$.// /1$78

 Zs%;%;/00$)
 /3//9::/3//9::&44(%	 
  Iw?T?T)U)UEFF:C  #$$%!&!"&'(

r1   r!   r#   c                    [         R                  " U5      S    H]  nUS   nUS;   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Typer   DataOffsetr   DurationrM   Text)typeoffsetdurationrM   )
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@@V$X.<Q1RR  $,F#3J#? %, 0$Xf%5f%=f%EF	  O+!$;I;"GHH 5  !!ABBr1   c                     U R                   S==   U R                   S   -  ss'   U R                   S   S-  [        -  [        -  U R                   S'   SU R                   S'   g)a  Update inter-chunk offset_compensation from cumulative CBR audio bytes.

The output format is audio-24khz-48kbitrate-mono-mp3 (48 kbps CBR).
For any CBR stream the byte-to-tick conversion is exact integer
arithmetic:  ticks = total_bytes * 8 * 10_000_000 // 48_000.

This replaces the previous metadata-based accumulation which drifted
on long texts due to variable AI silence and Microsoft's integer
overflow in reported offsets.
r   r   r5   r   r   N)r   r   r   )r   s    r/   __compensate_offsetCommunicate.__compensate_offset  sj     	

+,

;N0OO,JJ/0  	

() +,

&'r1   c           
       ^ ^#    S&U U4S jjnS&U U4S jjnSn[         R                  " T R                  ST R                  S9 IS h  vN oDR	                  [
         S[        5        S[        R                  " 5        S[         3S	T R                  [        R                  " [        5      [        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['        XfR)                  S5      5      u  pxUR+                  SS 5      n	U	S:X  a0  T R-                  U5      n
U
7v   U
S   U
S   -   T R.                  S'   M  U	S:X  a  T R1                  5           GOU	S;  a  [3        S5      eM  UR                  [         R                  R4                  :X  Ga-  [7        UR"                  5      S:  a  [9        S5      e[:        R=                  UR"                  S S S5      nU[7        UR"                  5      :  a  [9        S5      e['        UR"                  U5      u  pxUR+                  S5      S:w  a  [9        S5      eUR+                  SS 5      nUS;  a  [9        S5      eUc  [7        U5      S:X  a  GM  [9        S5      e[7        U5      S:X  a  [9        S 5      eSnT R.                  S!==   [7        U5      -  ss'   S"US#.7v   GM2  UR                  [         R                  R>                  :X  d  GM]  [A        UR"                  (       a  UR"                  5      eS$5      eU(       d  [C        S%5      eS S S 5      IS h  vN   S S S 5      IS h  vN   g  GNP 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                   R                  S:H  n U (       a  SOSnU (       d  SOSnTR                  S[        5        SU SU S35      I Sh  vN   g N7f)	z)Sends the command request to the service.r   truefalsezX-Timestamp:z
Content-Type:application/json; charset=utf-8
Path:speech.config

{"context":{"synthesis":{"audio":{"metadataoptions":{"sentenceBoundaryEnabled":"z","wordBoundaryEnabled":"z9"},"outputFormat":"audio-24khz-48kbitrate-mono-mp3"}}}}
N)r   r   send_strrv   )word_boundarywdsqr   	websockets      r/   send_command_request2Communicate.__stream.<locals>.send_command_request  sm      OO44FM(gB,'B$$~/0 1. /1T1J2$ O		 	 	s   AA!AA!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   r{   rL   rv   rq   r   r   )r   r   s   r/   send_ssml_request/Communicate.__stream.<locals>.send_ssml_request  sL     $$&L"$

>2	 	 	s   AAAAFT)r   	trust_envtimeoutz&ConnectionId=z&Sec-MS-GEC=z&Sec-MS-GEC-Version=   )compressr   r+   sslr4   s   

s   Paths   audio.metadatar   r   r   s   turn.end)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.r   audio)r   r!   zUnknown errorzFNo audio was received. Please verify that your parameters are correct.r#   N)"r   ClientSessionr   r   
ws_connectr   rL   r   generate_sec_ms_gecr   r   headers_with_muidr   _SSL_CTXr   	WSMsgTypeTEXTr!   rd   r0   r_   get_Communicate__parse_metadatar   _Communicate__compensate_offsetr   BINARYrW   r   r   
from_bytesERRORr   r   )r   r   r   audio_was_receivedsessionreceivedencoded_data
parametersr!   pathparsed_metadatar"   content_typer   s   `            @r/   __streamCommunicate.__stream  s    	 	 	 	  # ((nn((
 
 ((i~jl^32245"#5"68 **))+6 ) 
 
 &(((#%%%"+ Qh==G$5$5$:$::*2--*>*>w*GL';$&7&7&D($J &>>'48D00*.*?*?*E-- ,H5
8SS 

#9: , 002%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 
 *.&JJ23s4y@3#*D99]]g&7&7&=&==()1 <K  &%\ C
 
	
 
 

 )%Q)
 
 
 
	
 
 
 
s   AO NO A+O6N7O:N*NN*N N*N&N#
 N&#IN*8>N*6ON(OO OO ON* N*#N&&N*(O*O	0N31O	=OO OOOO c                  #    U R                   S   (       a  [        S5      eSU R                   S'   U R                   H>  U R                   S'   SU R                   S'    U R                  5         Sh  vN nU7v   M     g N
 MH  ! [        R
                   ac  nUR                  S:w  a  e [        R                  " U5        SU R                   S'   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   r   r   Ni  )	r   RuntimeErrorr   _Communicate__streamr   ClientResponseErrorstatusr   handle_client_response_error)r   messagees      r/   streamCommunicate.stream6  s      ::)*@AA*.

&' +/**DJJ~&./DJJ*+
"%)]]_ "'!M	 +5"_.. "88s?00323

./%)]]_ " "'!M &5"ss   AC?B-B1B 2B5B=C? BBC?C<AC7C0#C&
$C0(	C71C?7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	;   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wr4   )encodingwbr   r   r!   r   
)openr   r   writer'   r   r   dump)r   r   r   metadatar   r   s         r/   saveCommunicate.saveW  s      ) w7 	
 tK.%!% )g6?g-KK0-88WV_ Q > 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_itemss  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_itemsr  sD       
 ))+D""4(##IK0JJLr1   )r   
concurrentfuturesThreadPoolExecutorsubmitr   )r   r  r   executorr   s   `    r/   stream_syncCommunicate.stream_synco  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   r   r   r   )__name__
__module____qualname____firstlineno____doc__r   r=   r   r   r   r   r   r   r(   r   r   r   r   r   r   r   r   r	   r  r  __static_attributes__rK   r1   r/   r}   r}   A  s    #9

 @R59#)+)+9
9
 9

 9
 9
 9
 <=9
 G1129
 }9
 "#9
 "#9
vCU Cx C&,(Kx~ > KZ"	$	'"H 7;)3:&) !sEz!23) 
	)0Yxt';< 8 7;
3:&
 !sEz!23
 
	
 
r1   r}   )Ar  r  concurrent.futuresr	  r   r   rs   rH   
contextlibr   ior   r   r   typingr   r   r   r	   r
   r   r   r   xml.sax.saxutilsr   r   r   certifityping_extensionsr   	constantsr   r   r   r   r   r   data_classesr   drmr   
exceptionsr   r   r   r   r   r   create_default_contextwherer   r(   r   r0   r=   rF   rL   rT   rY   ra   ri   rq   rv   r{   r}   rK   r1   r/   <module>r)     s  I    
   "  	 	 	 .   %  $   /%%W]]_=.
. #.
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 # # "Q Qr1   