ó
    ¡ü8jRn  ã                  óä  • S r SSKJr  SSKrSSKrSSK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  SSKJr  S	S
KJr  S	SKJr  \" \5      R9                  5       R:                  S   r\S-  S-  r\S-  S-  r \S-  S-  r!\S-  S-  S-  S-  r"SS/r#Sr$\%" \&" \5      \&" \5      -  5      r'/ SQr(SS/r)SS/r*/ SQr+   S,       S-S jjr,   S.       S/S jjr-    S0         S1S  jjr.    S2         S1S! jjr/    S2         S1S" jjr0    S3         S1S# jjr1    S4         S5S$ jjr2S6S% jr3S7S& jr4S8S' jr5S9S( jr6S:S) jr7S* r8\9S+:X  a  \8" 5         gg);uG  V3 face inference â€” run the trained student on baked scenarios and write
the prediction as a viewer JSON so you can A/B against the teacher target.

Usage:
    # Predict a few scenarios, write viewer files, also print per-channel L1
    PYTHONPATH=. python3 -m models.v3_face.infer -s long_001 long_046 long_001_p0

    # Use latest.pt instead of best.pt
    PYTHONPATH=. python3 -m models.v3_face.infer --ckpt models/v3_face/checkpoints/latest.pt -s long_001

    # All curated viewer scenarios (anything currently in data/viewer/)
    PYTHONPATH=. python3 -m models.v3_face.infer --all-viewer

Output:
    data/viewer/<sid>_pred_dataset.json   (V3 student prediction)
    data/viewer/<sid>_pred_dataset.mp3    (symlink to teacher's mp3 â€” same audio)
    manifest.json updated with the _pred entries so the player dropdown shows them
é    )ÚannotationsN)ÚPath)ÚDictÚList)Úgaussian_filter1d)ÚARKIT_52_NAMESÚLIPSYNC_ONLYÚEXPRESSION_ONLYÚSHARED_CHANNELS)Ú
add_blinksé   )ÚV3FaceConfig)ÚV3FaceModelé   ÚdataÚv3_trainingÚviewerÚemotionÚmodelsÚv3_faceÚcheckpointszbest.pté   é	   é   )r   r   r   é   é   é   é   é   é   )é
   é   é   é   é   é   é   é   c                óä  ^• SSK m[        U 5      nUS::  a  U R                  [        R                  SS9$ [        R
                  " U[        R                  S9n[        U S   5      US'   SnSU-  nU4S	 jn	[        SU5       Hj  n
U	" X„5      n[        X
   5      XjS-
     -
  U-  nX¼-  SU-
  U-  -   nUnX#[        U5      -  -   nU	" XŽ5      nU[        X
   5      -  SU-
  XjS-
     -  -   Xj'   Ml     U$ )
zÍAdaptive low-pass. Cutoff rises with |dx|, so fast changes pass through
with minimal smoothing and slow drift gets aggressively smoothed.
Reference: animasync-face-v1/training/inference.py::OneEuroFilter.
r   Nr   T)Úcopy)Údtypeç        ç      ð?c                ó<   >• STR                   -  U-  U -  nX"S-   -  $ )Nç       @r-   )Úpi)Út_eÚcutoffÚrÚmaths      €ÚX/home/ubuntu/service/kemix-engine/package/face/animasync-face-v3/models/v3_face/infer.pyÚsfÚ_one_euro.<locals>.sfR   s&   ø€ Ø�$—'‘'‰M˜FÑ" SÑ(ˆØ˜‘G‰}Ðó    )	r4   ÚlenÚastypeÚnpÚfloat32ÚzerosÚfloatÚrangeÚabs)ÚsignalÚfpsÚ
min_cutoffÚbetaÚd_cutoffÚTÚoutÚdx_prevÚter6   ÚiÚa_dÚdxÚdx_hatr2   Úar4   s                   @r5   Ú	_one_eurorO   B   s  ø€ ó ÜˆF‹€AØˆAƒvØ�}‰}œRŸZ™Z¨dˆ}Ð3Ð3Ü
�(Š(�1œBŸJ™JÑ
'€CÜ�6˜!‘9Ó€Cˆ�FØ€GØ	ˆs‰€Bõô �1�aŽ[ˆÙ�ÓˆÜ�F‘IÓ ¨¡U¡Ñ+¨rÑ1ˆØ‘˜S 3™Y¨'Ñ1Ñ1ˆØˆØ¤S¨£[Ñ0Ñ0ˆÙˆr‹NˆØ”U˜6™9Ó%Ñ%¨¨q©°C¸A¹±JÑ(>Ñ>ˆ‹ñ ð €Jr8   c                óV  • U R                  5       R                  [        R                  5      n[        R                  " USS2S4   X5SS2S4   S9  [        R                  " USS2S4   X5SS2S4   S9  S H'  n[        R                  " USS2U4   SUSS2U4   S9  M)     [        XQXBS9$ )ux  Inject procedurally generated Poisson-distributed blinks on channels
8 and 9. Blink timing is decoupled from audio in real speech, so V3 can't
learn it; we use the same deterministic generator the teacher uses
(scripts.compiler.eye_motion.add_blinks) seeded by scenario_id.

The model's existing values on channels 8 and 9 are preserved up to
`expressive_cap` so legitimate sustained partial closure (squinty smile,
sleepy, crying â€” typically 0.2â€“0.4) survives. add_blinks composes via
max(), so the procedural 0.70 blink peaks always show through. Anything
the model produced above the cap (e.g., the solo failure mode where it
locks at 0.99) is clamped â€” that's a model failure, not expression.

Also caps eyeSquint (18, 19) and eyeWide (20, 21) at 0.84 (just under the
0.85 suppression threshold in add_blinks) so a misprediction in those
channels doesn't block blinks entirely.
Nr   )rG   r   )r   r   r   r    gáz®Gáê?)Úseed_strrB   Úmean_interval_s)r*   r:   r;   r<   ÚminimumÚ_add_blinks_proc)ÚblendshapesÚscenario_idrR   Úexpressive_caprB   ÚresultÚchs          r5   Úinject_blinksrZ   a   s›   € ð( ×ÑÓ×&Ñ&¤r§z¡zÓ2€FÜ‡J‚Jˆv’a˜�d‰|˜^º¸1¸±Ò>Ü‡J‚Jˆv’a˜�d‰|˜^º¸1¸±Ò>ÛˆÜ
�
Š
�6š!˜R˜%‘= $¨F²1°b°5©MÔ:ñ ä˜FØ #ñFð Fr8   c           	     ó  • U R                  5       R                  [        R                  5      n[         H  n[        USS2U4   UUX#S9USS2U4'   M     [        R                  " USS5      R                  [        R                  5      $ )z`Apply One-Euro to the 5 brow channels. Transition spikes preserved,
intra-turn jitter smoothed.
N©rB   rC   rD   rE   r,   r-   )r*   r:   r;   r<   ÚBROW_CHANNELSrO   Úclip©rU   rC   rD   rE   rB   rX   rY   s          r5   Úsmooth_browsr`   ~   st   € ð ×ÑÓ×&Ñ&¤r§z¡zÓ2€FßˆÜ! &ª¨B¨¡-°SØ-7Ø'+ñ@ˆŠq�"ˆu‹ñ ô �7Š7�6˜3 Ó$×+Ñ+¬B¯J©JÓ7Ð7r8   c           	     ó  • U R                  5       R                  [        R                  5      n[         H  n[        USS2U4   UUX#S9USS2U4'   M     [        R                  " USS5      R                  [        R                  5      $ )uÙ   Apply One-Euro to eyeSquint L/R (ch 18, 19). Heavier than brows by
default (min_cutoff 0.8 vs 1.5) â€” orbicularis oculi is naturally slow
and sustained, so we can attenuate sub-Hz wiggle without losing real
squints.
Nr\   r,   r-   )r*   r:   r;   r<   ÚEYE_SQUINT_CHANNELSrO   r^   r_   s          r5   Úsmooth_eye_squintrc   Ž   st   € ð ×ÑÓ×&Ñ&¤r§z¡zÓ2€Fß!ˆÜ! &ª¨B¨¡-°SØ-7Ø'+ñ@ˆŠq�"ˆu‹ñ "ô �7Š7�6˜3 Ó$×+Ñ+¬B¯J©JÓ7Ð7r8   c           	     ó  • U R                  5       R                  [        R                  5      n[         H  n[        USS2U4   UUX#S9USS2U4'   M     [        R                  " USS5      R                  [        R                  5      $ )uÎ   Apply One-Euro to eyeWide L/R (ch 20, 21). Same shape as eyeSquint â€”
paired anti-correlated channel that transitions from surprise to other
emotions, where smoothing helps the cross-fade look continuous.
Nr\   r,   r-   )r*   r:   r;   r<   ÚEYE_WIDE_CHANNELSrO   r^   r_   s          r5   Úsmooth_eye_widerf       st   € ð ×ÑÓ×&Ñ&¤r§z¡zÓ2€FßˆÜ! &ª¨B¨¡-°SØ-7Ø'+ñ@ˆŠq�"ˆu‹ñ  ô �7Š7�6˜3 Ó$×+Ñ+¬B¯J©JÓ7Ð7r8   c           	     ó  • U R                  5       R                  [        R                  5      n[         H  n[        USS2U4   UUX#S9USS2U4'   M     [        R                  " USS5      R                  [        R                  5      $ )u  Apply One-Euro to the 8 eyeLook channels (10â€“17 = gaze direction /
pupils). The compiler's iris drift is already smooth; this filter kills
the model's residual high-frequency reproduction noise. Slightly higher
cutoff than eyeSquint so saccade-like rapid gaze shifts still pass.
Nr\   r,   r-   )r*   r:   r;   r<   ÚEYE_LOOK_CHANNELSrO   r^   r_   s          r5   Úsmooth_eye_lookri   ±   st   € ð ×ÑÓ×&Ñ&¤r§z¡zÓ2€FßˆÜ! &ª¨B¨¡-°SØ-7Ø'+ñ@ˆŠq�"ˆu‹ñ  ô �7Š7�6˜3 Ó$×+Ñ+¬B¯J©JÓ7Ð7r8   c                ó  • Uc  UnU R                  5       R                  [        R                  5      nUS-  nUS-  n[         Hº  nU[
        :X  a  UOUn	USS2U4   R                  5       n
U	S:”  a	  [        X©S9n
U
R                  5       S:”  a  [        U
R                  5       5      OSnX«-  n[        R                  " XÆ-
  Xv-
  -  SS5      nXÝ-  SS	U-  -
  -  n[        R                  " X®-  U-  SS5      USS2U4'   M¼     U$ )
u¸  V1's crisp_mouth â€” soft-threshold gate on mouth/jaw channels.

For each lipsync-branch channel:
  1. Pre-smooth with a small Gaussian (kills HF noise without distorting
     legitimate phoneme onsets)
  2. Normalize to [0, 1] by channel max
  3. Apply smoothstep gate with edges (0.3Â·threshold, 1.2Â·threshold) â€”
     values below 0.3Â·threshold fade to 0, values above 1.2Â·threshold
     pass through fully
  4. Scale and clip

Args:
    pre_smooth_sigma: Gaussian Ïƒ for every lipsync channel EXCEPT
        mouthClose.
    mouth_close_sigma: Gaussian Ïƒ for mouthClose (ch 26). If None,
        falls back to `pre_smooth_sigma`. Set lower than the main sigma
        to keep m/b/p closures crisp while smoothing the rest.

Reference: animasync-face-v1/deployment/lipsync_distilled.py::crisp_mouth.
The smoothstep gate is the key: it kills sub-threshold jitter (our 13%
HF residual) WITHOUT being a low-pass filter that smears phoneme attacks.
Nç333333Ó?g333333ó?r   )Úsigmar-   r,   g      @r/   )
r*   r:   r;   r<   ÚCRISP_CHANNELSÚMOUTH_CLOSE_CHr   Úmaxr>   r^   )rU   Ú	thresholdÚscaleÚpre_smooth_sigmaÚmouth_close_sigmarX   Úedge0Úedge1rY   Úsigma_chÚvalsÚmax_valÚ
normalizedÚtÚgates                  r5   Úcrisp_mouthr|   Ã   sý   € ð6 Ñ Ø,ÐØ×ÑÓ×&Ñ&¤r§z¡zÓ2€FØ˜‰O€EØ˜‰O€EßˆØ(*¬nÓ(<Ñ$ÐBRˆØ’a˜�e‰}×!Ñ!Ó#ˆØ�a‹<Ü$ TÑ:ˆDØ'+§x¡x£z°A£~”%˜Ÿ™›
Ô#¸3ˆØ‘^ˆ
Ü�GŠG�ZÑ'¨E©MÑ:¸CÀÓEˆØ‰u˜˜c A™g™Ñ&ˆÜŸš ¡¨eÑ 3°S¸#Ó>ˆŠq�"ˆu‹ñ ð €Mr8   c                ó&  • [         R                  " XSS9nUS   n[        5       nUR                  5        HI  u  pV[	        XE5      (       d  M  US:X  a   [        U[        5      (       a  [        U5      n[        XEU5        MK     [        U5      R                  U5      nUR                  US   5        UR                  5         [        SU  SUR                  SS	5       S
UR                  S[        S5      5      S SUR                   S-  S S3	5        Xt4$ )NF)Úmap_locationÚweights_onlyÚconfigÚ	dilationsÚmodelz[ckpt] z  epoch=ÚepochÚ?z	  val_l1=Úval_l1Únanú.4fz	  params=g    €„.Az.2fÚM)ÚtorchÚloadr   ÚitemsÚhasattrÚ
isinstanceÚlistÚtupleÚsetattrr   ÚtoÚload_state_dictÚevalÚprintÚgetr>   Ún_params)Ú	ckpt_pathÚdeviceÚckptÚcfg_dictÚcfgÚkÚvr‚   s           r5   Ú
load_modelrž   ð   sú   € Ü�:Š:�iÀ5ÑI€DØ�H‰~€Hä
‹.€CØ—‘Ö ‰ˆÜ�3�?‹?Ø�KÓ¤J¨q´$×$7Ñ$7Ü˜!“H�Ü�C˜AÖñ	 !ô
 ˜Ó×Ñ Ó'€EØ	×Ñ˜$˜w™-Ô(Ø	‡J�J„LÜ	ˆG�I�;˜h t§x¡x°¸Ó'=Ð&>ð ?Ø—H‘H˜X¤u¨U£|Ó4°SÐ9ð :Ø—N‘N 3Ñ& sÐ+¨1ð.ô /ð ˆ:Ðr8   c                ó  • U R                   UR                   :w  a/  [        U R                   S   UR                   S   5      nU SU USU p[        R                  " X-
  5      R	                  SS9n[        U[           R	                  5       5      n[        U[           R	                  5       5      n[        U[           R	                  5       5      n[        U[           R	                  5       5      n[        UR	                  5       5      nX„UXgS.$ )z'Average L1 grouped by channel category.r   N)Úaxis)ÚoverallÚlipsyncÚ
expressionÚsharedÚblink)
ÚshapeÚminr;   r@   Úmeanr>   r	   r
   r   Ú	EYE_BLINK)	ÚpredÚtargetrF   ÚdiffÚlipÚexpÚshrr¥   r¡   s	            r5   Úper_channel_l1r°     sà   € à‡z�z�V—\‘\Ó!Ü�—
‘
˜1‘˜vŸ|™|¨A™Ó/ˆØ˜B˜Q�x ¨¨ ˆfÜ�6Š6�$‘-Ó ×%Ñ%¨1Ð%Ð-€DÜ
�”\Ñ"×'Ñ'Ó)Ó
*€CÜ
�”_Ñ%×*Ñ*Ó,Ó
-€CÜ
�”_Ñ%×*Ñ*Ó,Ó
-€CÜ�$”y‘/×&Ñ&Ó(Ó)€EÜ�D—I‘I“KÓ €GØ¸cØñ+ð +r8   c                óZ  • SSK nUR                  S5      nS GHã  nX-  nUR                  5       (       d  M  UR                  5        nU HÀ  n[        R
                  " U5      nUS   U :X  d  M$  [        US   5       V	V
s/ s Hu  u  pšU
R                  SS5      R                  5       (       d  M,  XšR                  S	S
5      U
R                  S/ SQ5      U
R                  SS5      U
R                  SS5      S.PMw     sn
n	s  sSSS5        s  $    SSS5        UR                  U 5      nU(       d  GM  UR                  5        nU H«  n[        R
                  " U5      nUS   UR                  S5      :X  d  M3  [        UR                  S5      5      n	US   U	   n
U	U
R                  S	S
5      U
R                  S/ SQ5      U
R                  SS5      U
R                  SS5      S./s  sSSS5        s  $    SSS5        GMæ     / $ s  sn
n	f ! , (       d  f       GN= f! , (       d  f       GM  = f)zAFind turns metadata for a scenario across the three split JSONLs.r   Nz^(daily_.+)_t(\d+)$)zseed_train_final.jsonlzseed_val.jsonlzseed_test.jsonlrV   ÚturnsÚtextÚ r   ÚneutralÚvad)r   r   r   Úspeaker)Úturn_idxr   r¶   r³   r·   r   r   )ÚreÚcompileÚexistsÚopenÚjsonÚloadsÚ	enumerater•   ÚstripÚmatchÚgroupÚint)ÚsidÚemotion_dirr¹   ÚSPLIT_REÚfnameÚpÚfÚlineÚrowÚtirz   Úms               r5   Úload_turns_metarÎ     sÒ  € ãØ�z‰zÐ0Ó1€HÜPˆØÑˆØ�x‰x�z‰z™8Ø�V‰VŒX˜Û�Ü—j’j Ó&�Ø�}Ñ%¨Õ,ô
 &/¨s°7©|Ô%<ô	ò &=™E˜BØŸ5™5 ¨Ó,×2Ñ2×4ó	: R·E±E¸)ÀYÓ4OØ !§¡ eªYÓ 7ÀÇÁÀvÈrÓARØ$%§E¡E¨)°RÓ$8ô:ñ &=ò	ñ ÷	 ‹XÙ÷ ð �N‰N˜3Óˆß‰1Ø—‘”˜QÛ�DÜŸ*š* TÓ*�CØ˜=Ñ)¨Q¯W©W°Q«ZÕ7Ü  §¡¨£›_˜Ø ™L¨Ñ,˜Ø-/Ø,-¯E©E°)¸YÓ,GØ()¯©¨e²YÓ(?Ø)*¯©¨v°rÓ):Ø,-¯E©E°)¸RÓ,@ñ	!Bð  Cñ C÷ “Ù÷ ’ñ# Qð8 €Iùó+÷	 ŽXú÷ —úsJ   Á#HÁ.HÁ?+HÂ.AHÃ;HÄHÅ2HÅ7A.HÇ1HÈHÈ
H	È
H*	c                óÜ	  • UR                   U  S3-  nUR                  5       (       d  [        SU  SU 35        0 $ [        R                  " U5      n[
        R                  " US   R                  [        R                  5      5      R                  S5      R                  U5      nUS   R                  [        R                  5      n[        USS5      =(       d    SnUS:”  a  [        US	S	2S	S
24   USSS9US	S	2S	S
24'   [
        R                  " U5      R                  S5      R                  U5      n	US   R                  [        R                  5      n
[
        R                  " 5          U" Xi5      R                  S5      R                  5       R!                  5       R                  [        R                  5      nS	S	S	5        [        USS5      (       a5  [#        WUR$                  UR&                  UR(                  UR*                  S9n[        USS5      (       a*  [-        WUR.                  UR0                  UR2                  S9n[        USS5      (       a*  [5        WUR6                  UR8                  UR:                  S9n[        USS5      (       a*  [=        WUR>                  UR@                  URB                  S9n[        USS5      (       a*  [E        WURF                  URH                  URJ                  S9n[        USS5      (       a   [M        WU URN                  URP                  S9n[S        WU
5      nURT                  (       a  SURT                   3OSnU  SU S3nUS[W        URX                  S   5      [Z        []        XR^                  5      [        R`                  " US5      Rc                  5       S.nURd                  U S3-  nURg                  [h        Rj                  " USS 95        URd                  U  S!3-  nURd                  U S"3-  nUR                  5       (       d  URm                  5       (       a  URo                  5         UR                  5       (       a  URq                  URr                  5        O[        S#U  S$U S%35        [        S&U  S'US(   S) S*US+   S) S,US-   S) S.US/   S) S0US1   S) S2URX                  S    S335        XS4.UE$ ! , (       d  f       GN&= f)5zDRun model on one scenario, write viewer JSON, return per-channel L1.z.npzu     âœ— z: no npz found at Úaudior   ÚcondÚsmooth_cond_sigma_emotionr,   Nr'   Únearest)rl   r    Úmoder«   ÚcrispF)rp   rq   rr   rs   Úbrow_smooth)rC   rD   rE   Úeye_squint_smoothÚeye_wide_smoothÚeye_look_smoothr   )rV   rR   rW   Ú_r´   Ú_predÚ_dataseté   r   )rV   rB   Ú
num_framesÚnamesr²   rU   z.json)Úensure_asciiz_dataset.mp3z.mp3z  ! z: teacher mp3 not found at uG    â€” the prediction will play silently. Run dataset_to_viewer.py first.u     âœ“ z  L1: overall=r¡   r‡   z  lip=r¢   z  exp=r£   z  shr=r¤   z  blink=r¥   z  (z frames))rÄ   Únew_base):Únpz_dirr»   r”   r;   rŠ   r‰   Ú
from_numpyr:   r<   Ú	unsqueezer‘   Úgetattrr   Úno_gradÚsqueezeÚcpuÚnumpyr|   Úcrisp_thresholdÚcrisp_scaleÚcrisp_sigmaÚcrisp_mouthclose_sigmar`   Úbrow_min_cutoffÚ	brow_betaÚbrow_d_cutoffrc   Úeye_squint_min_cutoffÚeye_squint_betaÚeye_squint_d_cutoffrf   Úeye_wide_min_cutoffÚeye_wide_betaÚeye_wide_d_cutoffri   Úeye_look_min_cutoffÚeye_look_betaÚeye_look_d_cutoffrZ   Úblink_intervalÚblink_expressive_capr°   Úvariant_tagrÃ   r¦   r   rÎ   rÅ   ÚroundÚtolistÚ
viewer_dirÚ
write_textr½   ÚdumpsÚ
is_symlinkÚunlinkÚ
symlink_toÚname)rÄ   r‚   r˜   ÚargsÚnpz_pathr   rÐ   Úcond_npÚsmooth_sigmarÑ   r«   rª   ÚmetricsÚvariant_partrá   Úviewer_jsonÚout_jsonÚteacher_mp3Úpred_mp3s                      r5   Úpredict_and_saver  5  s¢  € à�|‰|   T˜lÑ*€HØ�?‰?×ÑÜ��s�eÐ-¨h¨ZÐ8Ô9Øˆ	Ü�7Š7�8Ó€DÜ×Ò˜T '™]×1Ñ1´"·*±*Ó=Ó>×HÑHÈÓK×NÑNÈvÓV€EØ�6‰l×!Ñ!¤"§*¡*Ó-€Gô
 ˜4Ð!<¸cÓB×IÀc€LØ�cÓÜ+¨G²A°s¸°s°F©OØ3?Ø23¸)ñEˆ’�3�B�3�‰ô ×Ò˜GÓ$×.Ñ.¨qÓ1×4Ñ4°VÓ<€DØ�(‰^×"Ñ"¤2§:¡:Ó.€Fä	�Š�Ù�UÓ!×)Ñ)¨!Ó,×0Ñ0Ó2×8Ñ8Ó:×AÑAÄ"Ç*Á*ÓMˆ÷ 
ô ˆt�W˜e×$Ñ$ÜØØ×*Ñ*Ø×"Ñ"Ø!×-Ñ-Ø"×9Ñ9ñ
ˆô ˆt�] E×*Ñ*ÜØØ×+Ñ+Ø—‘Ø×'Ñ'ñ	
ˆô ˆtÐ(¨%×0Ñ0Ü ØØ×1Ñ1Ø×%Ñ%Ø×-Ñ-ñ	
ˆô ˆtÐ&¨×.Ñ.ÜØØ×/Ñ/Ø×#Ñ#Ø×+Ñ+ñ	
ˆô ˆtÐ&¨×.Ñ.ÜØØ×/Ñ/Ø×#Ñ#Ø×+Ñ+ñ	
ˆô ˆt�\ 5×)Ñ)Ü˜T¨sØ-1×-@Ñ-@Ø,0×,EÑ,EñGˆô ˜T 6Ó*€Gð .2×-=×-=�Q�t×'Ñ'Ð(Ñ)À2€LØ��e˜L˜>¨Ð2€HàØÜ˜$Ÿ*™* Q™-Ó(ÜÜ  ×&6Ñ&6Ó7Ü—x’x  aÓ(×/Ñ/Ó1ñ€Kð �‰ H :¨UÐ!3Ñ3€HØ×ÑœŸ
š
 ;¸UÑCÔDð —/‘/ s e¨<Ð$8Ñ8€KØ�‰ H :¨TÐ!2Ñ2€HØ‡�×Ñ˜H×/Ñ/×1Ñ1Ø�‰ÔØ×Ñ×ÑØ×Ñ˜K×,Ñ,Õ-ä��S�EÐ4°[°Mð BSð Sô 	Tô 
ˆF�3�%�~ g¨iÑ&8¸Ð%=ð >Ø˜Ñ# CÐ(¨¨w°|Ñ/DÀSÐ.Ið JØ˜Ñ" 3Ð' x°¸Ñ0@ÀÐ/Eð FØ�j‰j˜‰mˆ_˜Hð&ô 'ð Ñ8°Ð8Ð8÷g 
Žús   Å,ASÓ
S+c                ó$  • U S-  nUR                  5       (       a$  [        R                  " UR                  5       5      OS/ 0nUS    Vs0 s H  oDR	                  S5      U_M     nnU H^  nUS   nUR	                  US    S30 5      nUU/ UR	                  SS5      UR	                  S	/ 5      S
UR	                  SS5      -   S.XW'   M`     [        UR                  5       5      US'   UR                  [        R                  " USSS95        gs  snf )z8Add _pred_dataset entries to the viewer's manifest.json.zmanifest.jsonÚ	scenariosÚbaserá   rÄ   rÜ   Ún_turnsr   Úemotionsz
[V3 pred] Útext_previewr´   )r  rV   Úvariantsr  r  r  Fr   )rà   ÚindentN)	r»   r½   r¾   Ú	read_textr•   rŽ   Úvaluesr   r  )	rÿ   ÚpredictionsÚmanifest_pathÚmanifestÚsÚseenrÈ   rá   Úteacher_entrys	            r5   Úupdate_manifestr!     s  € à Ñ0€Mà ×'Ñ'×)Ñ)ô —
’
˜=×2Ñ2Ó4Ô5Ø0;¸RÐ/@ð à&.¨{Ò&;Ó<Ò&; �E‰E�&‹M˜1ÒÑ&;€DÐ<ÛˆØ�Z‘=ˆàŸ™ A e¡H :¨XÐ!6¸Ó;ˆàØ#ØØ$×(Ñ(¨°AÓ6Ø%×)Ñ)¨*°bÓ9Ø(¨=×+<Ñ+<¸^ÈRÓ+PÑPñ
ˆ‹ñ	 ô ! §¡£Ó/€Hˆ[ÑØ×ÑœTŸZšZ¨¸uÈQÑOÕPùò =s   Á
Dc                 óú
  • [         R                  " 5       n U R                  S[        [        S9  U R                  S[        [
        S9  U R                  S[        [        S9  U R                  S[        [        S9  U R                  SSS9  U R                  S	[        S
SS9  U R                  S[        S SS9  U R                  SSSS SS9  U R                  SSSS9  U R                  SSSS9  U R                  S[        SSS9  U R                  S[        SSS9  U R                  S [        SS!S9  U R                  S"[        SS#S9  U R                  S$SS%S9  U R                  S&[        S'S(S9  U R                  S)[        S*S+S9  U R                  S,[        SS-S9  U R                  S.SS/S9  U R                  S0[        S1S2S9  U R                  S3[        S*S4S9  U R                  S5[        SS6S9  U R                  S7SS8S9  U R                  S9[        S1S:S9  U R                  S;[        S*S<S9  U R                  S=[        SS>S9  U R                  S?SS@S9  U R                  SA[        SSBS9  U R                  SC[        S*SDS9  U R                  SE[        SSFS9  U R                  SGSSHS9  U R                  SI[        SJSKS9  U R                  SL[        SMSNS9  U R                  5       nUR                  (       d"  UR                  (       d  U R                  SO5        UR                  (       ax  / n[        UR                  R!                  SP5      5       H5  nUR"                  nSQU;   a  M  UR%                  US ['        SR5      *  5        M7     [)        SS['        U5       ST35        OUR                  n[*        R,                  " UR,                  5      n[/        UR0                  U5      u  pg[)        SU['        U5       SVUR                   35        / nU H)  n	[3        X–XQ5      n
U
(       d  M  UR%                  U
5        M+     U(       Ga  [5        UR                  U5        [6        R8                  " U Vs/ s H  o3SW   PM	     sn5      n[6        R8                  " U Vs/ s H  o3SX   PM	     sn5      n[6        R8                  " U Vs/ s H  o3SY   PM	     sn5      n[6        R8                  " U Vs/ s H  o3SZ   PM	     sn5      n[)        S[['        U5       S\35        [)        S]US^ 35        [)        S_US^ 35        [)        S`US^ 35        [)        SaUS^ 35        [)        Sb5        [)        Sc5        [)        Sd5        g s  snf s  snf s  snf s  snf )eNz--ckpt)ÚtypeÚdefaultz	--npz_dirz--viewer_dirz--emotion_dirz--devicezcuda:0)r$  z--smooth-cond-sigma-emotionr,   u°   Gaussian Ïƒ (frames @ 30 fps) for smoothing the emotion one-hot in cond[:, :16]. MUST match the value used during training of the loaded checkpoint. 0 = no smoothing (default).)r#  r$  Úhelpz--variant-tagzªOptional tag baked into output filenames ({sid}_pred_{tag}_dataset.json). Use to keep predictions from different gain variants from clobbering each other in data/viewer/.z-sz--scenariosÚ+z!Specific scenario IDs to predict.)Únargsr$  r%  z--all-viewerÚ
store_truezcPredict every scenario currently curated in data/viewer/ (i.e. every *_dataset.json without _pred).)Úactionr%  z--crispz÷Apply V1-style crisp_mouth post-processing to lipsync channels (Gaussian pre-smooth + smoothstep soft-threshold gate). Kills sub-threshold mouth jitter without smearing phoneme attacks. Reference: animasync-face-v1/deployment/lipsync_distilled.py.z--crisp-thresholdrk   z4Smoothstep center for crisp_mouth gate. Default 0.3.z--crisp-scaler-   zhAmplification factor after the gate. Default 1.0 (V1 used 1.2 to compensate for the gate's attenuation).z--crisp-sigmau˜   Gaussian Ïƒ (frames) for pre-smoothing before the gate, applied to every lipsync channel EXCEPT mouthClose. Default 1.0 (V1's smooth_frames=2 â†’ Ïƒ=1).z--crisp-mouthclose-sigmau¸   Separate Gaussian Ïƒ for mouthClose (ch 26). Default 1.0. Keep at or below --crisp-sigma so m/b/p phoneme closures stay sharp while the rest of the mouth can be slightly more smoothed.z--brow-smoothz Apply gentle One-Euro adaptive filter to brow channels (0-4). Transition spikes pass through; intra-turn micro-jitter is softened. Matches V1's brow deployment.z--brow-min-cutoffç      ø?z¦One-Euro min_cutoff for brows. V1 used 1.5 in deployment, 2.0 in training inference. Default 1.5 (barely visible smoothing). Raise toward 2.0 for even subtler effect.z--brow-betaç{®Gáz„?u‰   One-Euro Î² â€” how fast the cutoff rises with |dx|. Higher = transitions pass through faster. Default 0.01 (V1's brow-deployment value).z--brow-d-cutoffz(One-Euro derivative cutoff. Default 1.0.z--eye-squint-smoothu  Apply One-Euro adaptive filter to eyeSquint L/R (ch 18, 19). Mirrors --brow-smooth but heavier â€” orbicularis oculi is naturally slow so we can smooth sub-Hz wiggle hard without killing real squints. Use this when training-time target smoothing alone doesn't kill the visible jitter.z--eye-squint-min-cutoffçš™™™™™é?z_One-Euro min_cutoff for eyeSquint. Lower than brows (default 0.8 vs 1.5) for heavier smoothing.z--eye-squint-betau(   One-Euro Î² for eyeSquint. Default 0.01.z--eye-squint-d-cutoffz6One-Euro derivative cutoff for eyeSquint. Default 1.0.z--eye-wide-smoothu´   Apply One-Euro adaptive filter to eyeWide L/R (ch 20, 21). Paired with eyeSquint for surprise â†’ other-emotion transitions where eyeWideâ†“ and eyeSquintâ†‘ cross discontinuously.z--eye-wide-min-cutoffz-One-Euro min_cutoff for eyeWide. Default 0.8.z--eye-wide-betau&   One-Euro Î² for eyeWide. Default 0.01.z--eye-wide-d-cutoffz4One-Euro derivative cutoff for eyeWide. Default 1.0.z--eye-look-smoothu  Apply One-Euro adaptive filter to the 8 eyeLook channels (10â€“17, gaze direction / pupils). The compiler's iris drift is already smooth; this kills the model's residual reproduction noise. Cutoff slightly higher than eyeSquint so saccade-like rapid shifts still pass.z--eye-look-min-cutoffz6One-Euro min_cutoff for eyeLook (pupils). Default 1.0.z--eye-look-betau&   One-Euro Î² for eyeLook. Default 0.01.z--eye-look-d-cutoffz4One-Euro derivative cutoff for eyeLook. Default 1.0.z--add-blinksa  Replace V3's blink channels (8, 9) with procedural Poisson-distributed blinks. Uses the same generator as the training teacher (eye_motion.add_blinks), seeded deterministically by scenario_id. Use this because blink timing isn't audio-determined and V3 cannot learn it from audio alone.z--blink-intervalç      @u‚   Mean blink interval in seconds. Default 4.0 (matches the teacher's bake-time value). Real human blink rate is 15-20/min â‰ˆ 3-4 s.z--blink-expressive-capç      à?a  Cap for the model's pre-existing eyeBlink (ch 8, 9) values. Below the cap, expressive sustained eye closure (squinty smile, sleepy) survives. Above, broken predictions (locked-shut eyes) are clamped. Procedural blinks always poke through via max(). Default 0.5.z#provide --scenarios or --all-viewerz*_dataset.jsonÚ_pred_datasetrÜ   zall-viewer: z
 scenariosz
Predicting u    scenarios â†’ r¡   r¢   r£   r¥   u   
â”€â”€ aggregate over u    scenarios â”€â”€z  overall L1: r‡   z  lipsync L1: z  expression L1: z  blink L1: z;
Done. Hard-reload viewer. Each scenario now appears twice:z%  <sid>_dataset      = teacher targetz,  <sid>_pred_dataset = V3 student prediction)ÚargparseÚArgumentParserÚadd_argumentr   ÚDEFAULT_CKPTÚDEFAULT_NPZ_DIRÚDEFAULT_VIEWER_DIRÚDEFAULT_EMOTION_DIRr>   ÚstrÚ
parse_argsr  Ú
all_viewerÚerrorÚsortedrÿ   ÚglobÚstemÚappendr9   r”   r‰   r˜   rž   r™   r  r!  r;   r¨   )Úapr  ÚsidsrÈ   r=  r˜   r‚   r›   r  rÄ   rX   r¡   r­   r®   r¥   s                  r5   ÚmainrA  ¶  sÏ  € Ü	×	 Ò	 Ó	"€BØ‡O�O�H¤4´€OÑ>Ø‡O�O�K¤d´O€OÑDØ‡O�O�N¬Ô7I€OÑJØ‡O�O�O¬$Ô8K€OÑLØ‡O�O�J¨€OÑ1Ø‡O�OÐ1¼ÀsðCð ñ Dð
 ‡O�O�O¬#°tðBð ñ Cð
 ‡O�O�D˜-¨s¸DØ<ð ñ >à‡O�O�N¨<ðFð ñ Gð ‡O�O�I lðNð ñ Oð ‡O�OÐ'¬e¸SØOð ñ Qà‡O�O�O¬%¸ðSð ñ Tð ‡O�O�O¬%¸ðTð ñ Uð ‡O�OÐ.´UÀCð6ð ñ 7ð
 ‡O�O�O¨Lð,ð ñ -ð
 ‡O�OÐ'¬e¸Sð0ð ñ 1ð
 ‡O�O�M¬°tð>ð ñ ?ð ‡O�OÐ%¬E¸3ØCð ñ Eà‡O�OÐ)°,ðLð ñ Mð ‡O�OÐ-´EÀ3ðMð ñ Nð ‡O�OÐ'¬e¸TØCð ñ Eà‡O�OÐ+´%ÀØQð ñ Sà‡O�OÐ'°ð?ð ñ @ð
 ‡O�OÐ+´%ÀØHð ñ Jà‡O�OÐ%¬E¸4ØAð ñ Cà‡O�OÐ)´¸sØOð ñ Qà‡O�OÐ'°ð9ð ñ :ð ‡O�OÐ+´%ÀØQð ñ Sà‡O�OÐ%¬E¸4ØAð ñ Cà‡O�OÐ)´¸sØOð ñ Qà‡O�O�N¨<ð@ð ñ Að ‡O�OÐ&¬U¸Cð>ð ñ ?ð ‡O�OÐ,´5À#ð(ð ñ )ð �=‰=‹?€Dà�>�> $§/§/Ø
�‰Ð6Ô7à‡‡àˆÜ˜Ÿ™×,Ñ,Ð-=Ó>Ö?ˆAØ—6‘6ˆDØ $Ó&©Ø�K‰K˜Ð/¤ J£Ð/Ð0Ö1ñ @ô 	�œS ›Y˜K zÐ2Õ3à�~‰~ˆä�\Š\˜$Ÿ+™+Ó&€FÜ˜DŸI™I vÓ.�J€Eä	ˆMœ#˜d›)˜ O°D·O±OÐ3DÐ
EÔFØ€KÛˆÜ! #¨fÓ;ˆßˆ6Ø×Ñ˜vÖ&ñ ÷
 Ü˜Ÿ™¨Ô5ä—'’'±Ó=²¨A˜Yœ<±Ñ=Ó>ˆÜ�gŠg©[Ó9ª[¨˜”|©[Ñ9Ó:ˆÜ�gŠg±Ó<²¨1˜”±Ñ<Ó=ˆÜ—’©[Ó9ª[¨˜7œ©[Ñ9Ó:ˆÜÐ(¬¨[Ó)9Ð(:Ð:KÐLÔMÜ�˜w s˜mÐ,Ô-Ü�˜s 3˜iÐ(Ô)ÜÐ! # c Ð+Ô,Ü�˜U 3˜KÐ(Ô)Ü	ÐHÔJÜ	Ð1Ô3Ü	Ð8Õ:ùò >ùÚ9ùÚ<ùÚ9s   Ñ#U)ÒU.Ò5U3ÓU8Ú__main__)ç      >@r*  r+  r-   )rA   ú
np.ndarrayrB   r>   rC   r>   rD   r>   rE   r>   ÚreturnrD  )r-  r.  rÝ   )rU   rD  rV   r7  rR   r>   rW   r>   rB   rÃ   rE  rD  )r*  r+  r-   rC  )rU   rD  rC   r>   rD   r>   rE   r>   rB   r>   rE  rD  )r,  r+  r-   rC  )r-   r+  r-   rC  )rk   r-   r-   N)rU   rD  rp   r>   rq   r>   rr   r>   rs   zfloat | NonerE  rD  )r—   r   r˜   ztorch.device)rª   rD  r«   rD  rE  úDict[str, float])rÄ   r7  rÅ   r   rE  ú
List[dict])rÄ   r7  rE  rF  )rÿ   r   r  rG  ):Ú__doc__Ú
__future__r   r0  r½   Úpathlibr   Útypingr   r   ré   r;   r‰   Úscipy.ndimager   Úscripts.compiler.constantsr   r	   r
   r   Úscripts.compiler.eye_motionr   rT   r€   r   r‚   r   Ú__file__ÚresolveÚparentsÚPROJECT_ROOTr4  r5  r6  r3  r©   rn   r;  Úsetrm   r]   rb   re   rh   rO   rZ   r`   rc   rf   ri   r|   rž   r°   rÎ   r  r!  rA  Ú__name__© r8   r5   Ú<module>rV     sÔ  ðñõ$ #ã Û Ý ß ã Û Ý +÷ó õ Gå  Ý á�H‹~×%Ñ%Ó'×/Ñ/°Ñ2€Ø Ñ'¨-Ñ7€Ø! FÑ*¨XÑ5Ð Ø" VÑ+¨iÑ7Ð Ø˜hÑ&¨Ñ2°]ÑBÀYÑN€à�ˆF€	ð
 €ñ ™˜LÓ)©C°Ó,@Ñ@ÓA€ò  €Ø˜2�hÐ Ø˜�HÐ Ú4Ð ð 04Ø59Ø #ðØðØ-2ðàðà(2õð@ ,/Ø*-ØðFØ#(ðFà"'ðFð ðFð %/õFð< &)Ø#Ø#&Ø"ð	8Ø"ð8àð8ð !ð8ð ð	8ð (2õ	8ð" ,/Ø%)Ø),Ø$(ð	8Ø#(ð8à"ð8ð "'ð8ð "ð	8ð .8õ	8ð& *-Ø#'Ø'*Ø"&ð	8Ø!&ð8à ð8ð  %ð8ð  ð	8ð ,6õ	8ð$ *-Ø#'Ø'*Ø"&ð	8Ø!&ð8à ð8ð  %ð8ð  ð	8ð ,6õ	8ð& $'Ø"Ø*-Ø26ð	*Ø ð*àð*ð #(ð*ð $0ð	*ð <Fõ	*ôZô&+ô ôFh9ôVQò,Z;ðz ˆzÓÙ…Fð r8   