Ë
    Š‰Œj!*  ã                  ó|   — d Z ddlmZ ddlZddlZ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mZmZmZ  G d„ d«      Zy)	a»  Ahead-of-air neural TTS cache for trusted live commentary events.

The browser can safely use a clip only when its rendered text is an exact match.  This cache receives
events from the scoring process, which already knows the upcoming pre-start script, and prepares those
clips before their air time.  A synthesis failure is deliberately non-fatal: the live player keeps its
browser-voice fallback and the race never waits on a cloud request.
é    )ÚannotationsNé   )Úmake_engine)Ú	AUDIO_DIRÚ	LANG_CODEÚRATEÚto_ssmlc                  ó^   — e Zd ZdZddedœdd„Zdd„Zedd„«       Zedd„«       Z	dd	„Z
dd
„Zy)ÚLiveNeuralTtsCachez?Prepare exact-match neural clips in bounded background workers.r   gš™™™™™É?)ÚworkersÚmin_request_interval_sÚon_logc               ó€  — || _         t        j                  «       | _        t	        j
                  «       | _        t        «       | _        i | _	        d| _
        d | _        d| _        t        dt        |«      «      | _        d| _        t"        dz  | _        	 t'        j(                  | j$                  j+                  d¬«      «      | _        t3        t        d|«      «      D ]8  }t	        j4                  | j6                  dd|dz   › �¬	«      j9                  «        Œ: y # t.        t&        j0                  f$ r
 i | _        Y Œsw xY w)
Nç        Fz
index.jsonúutf-8©Úencodingr   Tzlive-neural-tts-)ÚtargetÚdaemonÚname)Ú_logÚqueueÚQueueÚ_queueÚ	threadingÚLockÚ_lockÚsetÚ
_scheduledÚ_voicesÚ_unavailable_untilÚ_unavailable_reasonÚ_unavailable_loggedÚmaxÚfloatÚ_min_request_interval_sÚ_next_request_atr   Ú_index_pathÚjsonÚloadsÚ	read_textÚ_indexÚFileNotFoundErrorÚJSONDecodeErrorÚrangeÚThreadÚ_runÚstart)Úselfr   r   r   Úns        úA/srv/vr/releases/25f455cc4e75/v3/broadcast/live/tts/live_cache.pyÚ__init__zLiveNeuralTtsCache.__init__   s  € ØˆŒ	Übg×bmÑbmÓboˆŒÜ—^‘^Ó%ˆŒ
Ü58³UˆŒØ24ˆŒð
 #&ˆÔØ/3ˆÔ Ø#(ˆÔ ô (+¨3´Ð6LÓ0MÓ'NˆÔ$Ø #ˆÔÜ$ |Ñ3ˆÔð	ÜŸ*™* T×%5Ñ%5×%?Ñ%?ÈÐ%?Ó%QÓRˆDŒKô ”s˜1˜g“Ó'ò 	eˆAÜ×Ñ D§I¡I°dÐCSÐTUÐXYÑTYÐSZÐA[Ô\×bÑbÕdñ	eøô "¤4×#7Ñ#7Ð8ò 	ØˆDŽKð	ús   Â4D Ä D=Ä<D=c                ó   — | j                   5  t        j                  «       }t        d| j                  |z
  «      }t        || j                  «      | j
                  z   | _        ddd«       rt        j                  |«       yy# 1 sw Y   Œ"xY w)zUPace calls against the project quota, shared even if a caller opts into more workers.r   N)r   ÚtimeÚ	monotonicr$   r'   r&   Úsleep)r3   ÚnowÚwait_ss      r5   Ú_wait_for_request_slotz)LiveNeuralTtsCache._wait_for_request_slot6   s{   € à�Z‰Zñ 	cÜ—.‘.Ó"ˆCÜ˜˜d×3Ñ3°cÑ9Ó:ˆFÜ$'¨¨T×-BÑ-BÓ$CÀd×FbÑFbÑ$bˆDÔ!÷	cñ Ü�J‰J�vÕð ÷		cð 	cús   �ABÂBc                óz   — | j                  d«      }|dv r|S ddddœj                  | j                  d«      d«      S )NÚcommentaryRole>   ÚleadÚrulesÚtacticalr@   rB   rA   )ÚmÚfÚrÚvoice©Úget)ÚeventÚroles     r5   Ú_rolezLiveNeuralTtsCache._role?   sC   € à�y‰yÐ)Ó*ˆØÐ0Ñ0ØˆKØ *°7Ñ;×?Ñ?ÀÇ	Á	È'Ó@RÐT^Ó_Ð_ó    c           	     ó  — | j                  d«      g}|j                  | j                  d«      xs g «       g }t        «       }|D ]±  }t        |t        «      sŒ|j                  «       D ��ci c]7  \  }}t        |xs d«      j                  «       rt        |«      t        |«      “Œ9 }}}|sŒit        t        |j                  «       «      «      }||vsŒ�|j                  |«       |j                  |«       Œ³ |S c c}}w )aÃ  Return the source line plus every approved on-air wording alternative.

        ``StreamingScorer`` deliberately selects a wording only once the event crosses its
        settled live seam.  The TTS cache sees the event earlier, so it must prepare the whole
        approved bank rather than only the producer's default wording.  Otherwise a rotated line
        reaches air without a neural clip and the player falls back to a browser voice.
        Úi18nÚ_commentaryVariantsÚ )rH   Úextendr   Ú
isinstanceÚdictÚitemsÚstrÚstripÚtupleÚsortedÚaddÚappend)	rI   Ú
candidatesÚoptionsÚseenÚ	candidateÚlangÚtextÚoptionÚkeys	            r5   Ú_spoken_i18n_optionsz'LiveNeuralTtsCache._spoken_i18n_optionsF   sç   € ð —i‘i Ó'Ð(ˆ
Ø×Ñ˜%Ÿ)™)Ð$9Ó:Ò@¸bÔAØ ˆÜ14³ˆØ#ò 
	'ˆIÜ˜i¬Ô.ØØ=F¿_¹_Ó=N÷ 2©z¨t°TÜ˜TšZ R›×.Ñ.Ô0ô ˜$“i¤ T£Ñ*ð 2ˆFñ 2áØÜœ˜vŸ|™|›~Ó.Ó/ˆCØ˜$ŠØ—‘˜”Ø—‘˜vÕ&ð
	'ð ˆùó2s   Á,<C;c           	     ó
  — | j                   5  t        j                  «       }|| j                  k  r
	 ddd«       y| j                  rd| _        d| _        d| _        ddd«       t        t        d„ |D «       «      «      }|D ]ç  }| j                  |«      }| j                  |«      D ]À  }|j                  «       D ]«  \  }}	|	j                  «       }	|t        vrŒ||	|f}
| j                   5  |	| j                  j                  |«      xs i v s|
| j                  v r
	 ddd«       Œj| j                  j!                  |
«       ddd«       | j"                  j%                  ||	||f«       Œ­ ŒÂ Œé y# 1 sw Y   �ŒxY w# 1 sw Y   Œ<xY w)aE  Queue every known spoken line once; caller remains on the scoring thread.

        The producer's first i18n value and all of its approved wording alternatives are prepared
        together.  The later live rotation can then select any variant without changing speaker
        quality or dropping to a browser voice.
        Nr   Fc              3  óœ   K  — | ]D  }|j                  d «      r1|j                  d«      r |d    |d   |j                  d«      xs df–— ŒF y­w)r   ÚnameLangÚiparP   NrG   )Ú.0Úts     r5   ú	<genexpr>z,LiveNeuralTtsCache.submit.<locals>.<genexpr>q   sL   è ø€ ò GÐRSØ"#§%¡%¨¤-°A·E±E¸*Ô4Eð !" &¡	¨1¨Z©=¸!¿%¹%À»,Ò:LÈ"ÔMñ Gùs   ‚A
A)r   r8   r9   r!   r"   r#   rW   rX   rK   rc   rT   rV   r   r,   rH   r   rY   r   Úput)r3   ÚeventsÚteamsr;   ÚforeignrI   rJ   ra   r_   r`   rb   s              r5   ÚsubmitzLiveNeuralTtsCache.submit`   sƒ  € ð �Z‰Zñ 		1Ü—.‘.Ó"ˆCØ�T×,Ñ,Ò,Ø÷		1ð 		1ð ×&Ò&Ø*-�Ô'Ø+/�Ô(Ø+0�Ô(÷		1ô œñ GÐW\ô Gó Gó Hˆàò 	AˆEØ—:‘:˜eÓ$ˆDØ×3Ñ3°EÓ:ò 
A�Ø"(§,¡,£.ò 	A‘J�D˜$ØŸ:™:›<�DØ¤9Ñ,Ø Ø  tÐ,�CØŸ™ñ 1Ø D§K¡K§O¡O°DÓ$9Ò$?¸RÑ@ÀCÈ4Ï?É?ÑDZØ$÷1ð 1ð Ÿ™×+Ñ+¨CÔ0÷1ð —K‘K—O‘O T¨4°°wÐ$?Õ@ñ	Añ
Añ	A÷		1ñ 		1ú÷(1ð 1ús"   �%E,»!E,Ã)1E9	Ä#E9	Å,E6Å9Fc           	     óÊ  — d }	 | j                   j                  «       }|€y |\  }}}}d}	 | j                  5  t        j                  «       | j
                  k  }d d d «       rQ	 |s3| j                  5  | j                  j                  |||f«       d d d «       | j                   j                  «        Œ±|€t        | j                  ¬«      }| j                  j                  |«      }	|	€ |j                  |«      }	|	| j                  |<   t        j                  dd|«      }
t        ||
t!        |«      «      \  }}|	|   }t#        j$                  |› dt&        › d|› �j)                  «       «      j+                  «       d d }|› d|› |j,                  › �}t.        |z  }|j0                  j3                  dd¬	«       |j5                  «       s^| j7                  «        |j9                  ||||
|t&        ¬
«      }|j;                  d«      }|j=                  |«       |j?                  |«       | j                  5  || j@                  jC                  |i «      |<   | jD                  j;                  d«      }|jG                  tI        jJ                  | j@                  dd¬«      d¬«       |j?                  | jD                  «       d| _        d | _&        d| _'        d d d «       d}|s3| j                  5  | j                  j                  |||f«       d d d «       | j                   j                  «        �Œ&# 1 sw Y   �ŒÓxY w# 1 sw Y   �Œ¨xY w# 1 sw Y   ŒvxY w# tP        $ rœ}| j                  5  t        j                  «       dz   | _        tS        |«      | _&        | jN                   }d| _'        d d d «       n# 1 sw Y   nxY wr-| j                  dtU        |dd«      › d| jL                  › d�«       Y d }~�Œd }~ww xY w# 1 sw Y   ŒóxY w# |s@| j                  5  | j                  j                  |||f«       d d d «       n# 1 sw Y   nxY w| j                   j                  «        w xY w)NTF)r   u	   \s*â€”\s*z, ú|é   ú/)ÚparentsÚexist_ok)r_   ÚpayloadÚis_ssmlÚspokenÚ
voice_nameÚratez.tmpr   )Úensure_asciiÚindentr   r   r   g      ^@z[live-neural-tts] r   Úttsz< synthesis paused for 120 s; browser fallback remains live (ú))+r   rH   r   r8   r9   r!   r   ÚdiscardÚ	task_doner   r   r    ÚvoicesÚreÚsubr	   ÚlistÚhashlibÚsha1r   ÚencodeÚ	hexdigestÚsuffixr   ÚparentÚmkdirÚexistsr=   Ú
synthesizeÚwith_suffixÚwrite_bytesÚreplacer,   Ú
setdefaultr(   Ú
write_textr)   Údumpsr"   r#   Ú	ExceptionrU   Úgetattr)r3   ÚengineÚjobr_   r`   rJ   rn   ÚsuccessÚunavailableÚnamesrx   rv   rw   ry   ÚdigestÚrelr   ÚaudioÚtmpÚ	tmp_indexÚexcÚ
should_logs                         r5   r1   zLiveNeuralTtsCache._run�   s  € ð ˆØØ—+‘+—/‘/Ó#ˆCØˆ{ØØ(+Ñ%ˆD�$˜˜gØˆGð:(Ø—Z‘Zñ MÜ"&§.¡.Ó"2°T×5LÑ5LÑ"L�K÷MáØñf ØŸ™ñ DØŸ™×/Ñ/°°t¸TÐ0BÔC÷Dà—‘×%Ñ%Õ'ðk �>Ü(°·	±	Ô:�FØŸ™×(Ñ(¨Ó.�Ø�=Ø"ŸM™M¨$Ó/�EØ).�D—L‘L Ñ&ÜŸ™ ¨d°DÓ9�Ü#*¨4°¼¸g»Ó#GÑ �˜Ø" 4™[�
Ü Ÿ™¨¨°A´d°V¸1¸W¸IÐ&F×&MÑ&MÓ&OÓP×ZÑZÓ\Ð]`Ð^`Ða�ð ˜˜a ˜x¨¯© Ð7�Ü" S™�Ø—‘×#Ñ#¨D¸4Ð#Ô@Ø—}‘}”Ø×/Ñ/Ô1Ø"×-Ñ-°4ÀÐRYØ5;È
ÔY]ð .ó _�Eà ×,Ñ,¨VÓ4�CØ—O‘O EÔ*Ø—K‘K Ô'Ø—Z‘Zñ 5Ø=@�D—K‘K×*Ñ*¨4°Ó4°TÑ:Ø $× 0Ñ 0× <Ñ <¸VÓ D�IØ×(Ñ(¬¯©°D·K±KÈeÐ\]Ô)^ÐipÐ(ÔqØ×%Ñ% d×&6Ñ&6Ô7Ø.1�DÔ+Ø/3�DÔ,Ø/4�DÔ,÷5ð �ñ" ØŸ™ñ DØŸ™×/Ñ/°°t¸TÐ0BÔC÷Dà—‘×%Ñ%Ô'ñA ÷Mñ Mú÷nDñ Dú÷55ð 5ûô ò Ø—Z‘Zñ 4Ü.2¯n©nÓ.>ÀÑ.F�DÔ+Ü/2°3«x�DÔ,Ø%)×%=Ñ%=Ð!=�JØ/3�DÔ,÷	4÷ 4ñ 4úñ
 Ø—I‘Ið -¬W°V¸VÀUÓ-KÐ,Lð Mà ×4Ñ4Ð5°Qð8ô	ÿùðú÷"Dð Dûñ ØŸ™ñ DØŸ™×/Ñ/°°t¸TÐ0BÔC÷D÷ Dñ Dúà—‘×%Ñ%Õ'ús©   «M ·"L*Á
M Á2L7Â4E=M È1BMË
M Ë'O8Ì*L4Ì/M Ì7MÍMÍ	M Í	O5ÍO0Í%AN/Î&	O0Î/N8	Î46O0Ï*P Ï0O5Ï5P Ï8PÐQ"ÐP;Ð2	Q"Ð;QÑ "Q"N)r   Úintr   r%   )ÚreturnÚNone)rI   rS   r£   rU   )rI   rS   r£   ú
list[dict])rl   r¥   rm   r¥   r£   r¤   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__Úprintr6   r=   ÚstaticmethodrK   rc   ro   r1   © rL   r5   r   r      sO   „ ÙIà)*ÈDÐY^õ eó<ð ò`ó ð`ð òó ðó2AôBG(rL   r   )r©   Ú
__future__r   r…   r)   r   r‚   r   r8   Úenginesr   Úsynthr   r   r   r	   r   r¬   rL   r5   ú<module>r°      s6   ðñõ #ã Û Û Û 	Û Û å  ß 6Ó 6÷s(ò s(rL   