@streamoji/aitwin 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -53,9 +53,7 @@ Provide **`id`** (cloud twin) **or** **`assets`** (fixed URLs). One is required.
53
53
  | `id` | Twin id for `getAiTwin` (e.g. `olivia`) |
54
54
  | `assets` | `{ twinBase, binBase, encrypted }` — skip `getAiTwin` (lab / custom CDN) |
55
55
  | `authToken` | Bearer for TTS + encrypted assets; omitted → dev `getAuthToken` |
56
- | `apiBase` | Default `https://ai.streamoji.com` |
57
- | `facesCdnBase` | R2 base when using `id` (default pub `custom-faces`) |
58
- | `tts` | Provider when using `assets` (default `google`) |
56
+ | `ttsEngineId` | TTS engine when using `assets` (default Google) |
59
57
  | `voiceId` | Override TTS voice |
60
58
  | `speakingRate` | Default `0.85` |
61
59
  | `showErrorOverlay` | Canvas error overlay (default `true`) |
@@ -87,6 +85,33 @@ Use **stable** `useCallback` handlers for `onReady` / `onError` / `onDisplayStat
87
85
 
88
86
  Do not duplicate renderer code under `frontend/src/lib`; extend the package instead.
89
87
 
88
+ ## Worker CDN
89
+
90
+ The viseme diff Web Worker is hosted on R2 and loaded at runtime via `fetch` + blob URL (cross-origin `new Worker(cdnUrl)` is blocked by browsers).
91
+
92
+ The worker URL is baked into each release from `package.json` version (`config/defaults.ts`) and uploaded to the matching versioned R2 path via `npm run upload:worker` (see below). This avoids CDN cache mismatches between the npm bundle and the worker script.
93
+
94
+ Example URL for `0.1.4`: `https://pub-607ad1fc22e2400eb57d17240aab857c.r2.dev/aitwin-workers/v0.1.4/visemeDiffPreview.worker.js`
95
+
96
+ ### Upload worker after build
97
+
98
+ ```bash
99
+ export R2_ACCESS_KEY_ID=...
100
+ export R2_SECRET_ACCESS_KEY=...
101
+ npm run build
102
+ npm run upload:worker
103
+ ```
104
+
105
+ ### R2 CORS (required for browser fetch)
106
+
107
+ Allow `GET` and `HEAD` from your app origins (`https://aitwin.me`, `http://localhost:3000`). Use Cloudflare dashboard → R2 → `aitwin` bucket → Settings → CORS, or:
108
+
109
+ ```bash
110
+ npx wrangler r2 bucket cors set aitwin --file scripts/r2-cors.json
111
+ ```
112
+
113
+ (`scripts/r2-cors.json` is included; needs a Cloudflare API token with R2 Admin permissions.)
114
+
90
115
  ## Publishing
91
116
 
92
117
  From `packages/aitwin`:
@@ -97,6 +122,8 @@ npm version patch
97
122
  npm publish --access public
98
123
  ```
99
124
 
125
+ `prepublishOnly` runs `build` and `upload:worker` automatically.
126
+
100
127
  The published tarball includes only **`dist/`** (bundled JS + `.d.ts` + worker chunk). **No `src/` and no source maps.**
101
128
 
102
129
  Scoped packages need `--access public` on the free npm plan.
package/dist/aitwin.cjs CHANGED
@@ -1,3 +1,3 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const Fe=require("react/jsx-runtime"),m=require("react"),De="https://ai.streamoji.com",We="https://pub-607ad1fc22e2400eb57d17240aab857c.r2.dev/custom-faces",vt="https://us-central1-streamoji-265f4.cloudfunctions.net/getAiTwin",re="eng_a7f2b9c1",ye="eng_d4e8f3a2",pe="eng_c9b1e6d4",Ke=ye,Rt=new Set([ye,pe]),ct={[re]:"oculus_direct",[pe]:"oculus_direct",[ye]:"inworld_word"},Je={google:re,inworld:ye,cartesia:pe};function bt(e){return ct[e]}function Dt(e){return e===pe}function xt(e){if(e.ttsEngineId&&e.ttsEngineId in ct)return e.ttsEngineId;const t=e.tts?.toLowerCase();return t&&t in Je?Je[t]:Ke}class Re extends Error{constructor(t="AI twin not found"){super(t),this.name="AiTwinNotFoundError"}}async function ut(e,t=vt){const n=new URL(t);n.searchParams.set("id",e);const r=await fetch(n.toString());if(r.status===404)throw new Re;if(!r.ok)throw new Error(`getAiTwin failed (${r.status})`);const s=await r.json();if(!s.success)throw new Re(s.error??"AI twin not found");const{tts:a,...o}=s.data;return{...o,ttsEngineId:xt(s.data)}}const Ct="https://us-central1-streamoji-265f4.cloudfunctions.net/getAuthToken",Mt="client_6TNvp3SCs4Og0a1ijm9TommXLql1",Ft="kk8Fq8EmexzP10jMIEwY3R44M5RKUEm1",Pt="6TNvp3SCs4Og0a1ijm9TommXLql1",Ot="Swaraj Mali";async function Oe(){const e=await fetch(Ct,{method:"POST",headers:{"Content-Type":"application/json","Client-Id":Mt,"Client-Secret":Ft},body:JSON.stringify({userId:Pt,userName:Ot})});if(!e.ok)throw new Error(`getAuthToken failed (${e.status})`);const t=await e.json(),n=t.authToken??t.token??"";if(!n.trim())throw new Error("getAuthToken returned no token");return n}async function Lt(e,t=De){const n=await fetch(`${t.replace(/\/$/,"")}/api/session-value`,{headers:{Authorization:`Bearer ${e}`}});if(!n.ok)throw new Error(`/api/session-value failed (${n.status})`);const r=await n.json();if(!r.value)throw new Error("Session value response missing value");return r}function Nt(e){const t=e.trim();if(t.length%2!==0)throw new Error("Invalid hex key");const n=new Uint8Array(t.length/2);for(let r=0;r<t.length;r+=2)n[r/2]=Number.parseInt(t.slice(r,r+2),16);return n}function Ie(e){return Uint8Array.from(e)}function Ut(e,t){const n=new Uint8Array(e.length+t.length);return n.set(e,0),n.set(t,e.length),n}async function Vt(e,t){if(!t)throw new Error("Asset key is required for encrypted assets");if(e.byteLength<28)throw new Error("Encrypted payload too small");const n=new Uint8Array(e),r=Ie(n.subarray(0,12)),s=Ie(n.subarray(12,28)),a=Ie(n.subarray(28)),o=Ie(Ut(a,s)),c=await crypto.subtle.importKey("raw",Nt(t),{name:"AES-GCM"},!1,["decrypt"]);return crypto.subtle.decrypt({name:"AES-GCM",iv:r,tagLength:128},c,o)}let Le=null;const Ne=new Set;function Bt(e,t=We){const n=`${t.replace(/\/$/,"")}/${e}`;return{twinBase:n,binBase:n,encrypted:!0}}function $t(e){Le=e;for(const t of Ne)t()}function se(){if(!Le)throw new Error("Twin assets not configured; call setActiveTwinAssets first");return Le}function Ht(e){return Ne.add(e),()=>Ne.delete(e)}function Wt(){return`${se().twinBase}/sil.png`}function Kt(){return`${se().twinBase}/idle.mp4`}function qt(){const{encrypted:e,binBase:t,twinBase:n}=se();return e?t:n}function lt(){return se().encrypted}function Gt(){const{binBase:e,twinBase:t,encrypted:n}=se();return n?`${e}/atlas.bin`:`${t}/atlas.json`}function jt(){const{binBase:e,twinBase:t,encrypted:n}=se();return n?`${e}/expression_atlas.bin`:`${t}/expression_atlas.json`}function zt(e){const t=e.split(/\r?\n/);let n="",r="";for(const a of t)a.startsWith("event:")?n=a.slice(6).trim():a.startsWith("data:")&&(r=a.slice(5).trim());if(!n)return null;let s={};if(r)try{s=JSON.parse(r)}catch{s={raw:r}}return{event:n,data:s}}const ft=["aa","CH","DD","E","FF","I","O","PP","RR","SS","TH","U","kk","nn","sil"],Qt=new Map(ft.map(e=>[e.toLowerCase(),e]));function dt(e){const t=(e??"").trim();return t?Qt.get(t.toLowerCase())??"sil":"sil"}const Jt={aei:["aa","E","I"],o:["O","U"],ee:["I"],bmp:["PP"],fv:["FF"],l:["nn"],r:["RR"],th:["TH"],qw:["U","O"],cdgknstxyz:["DD","SS","kk","CH"]};function Xt(e){if(!e)return["sil"];const t=e.toLowerCase();return Jt[t]??["sil"]}function Yt(e,t){const n=e.word.length;if(n<=0)return 0;const r=e.wduration;if(r<=0)return 0;const s=Math.max(0,Math.min(1,(t-e.wtime)/r));return Math.min(n-1,Math.floor(s*n))}function xe(e,t){const n=Math.max(0,Math.min(e.length-1,t));return e[n]??""}function Zt(e,t){const n=e.toLowerCase(),r=xe(n,t),s=n.slice(Math.max(0,t-1),t+2);return r==="i"||r==="y"?"I":s.includes("ee")||r==="e"||n.includes("ea")?"E":"aa"}function en(e,t){const n=e.toLowerCase(),r=n.slice(Math.max(0,t-1),Math.min(n.length,t+3));if(/oo|ou|uw/.test(r))return"U";const s=xe(n,t);return s==="u"||s==="w"?"U":"O"}function tn(e,t){const n=e.toLowerCase(),r=n.slice(Math.max(0,t-2),t+1);if(/qu/.test(r))return"U";const s=n.slice(Math.max(0,t-1),Math.min(n.length,t+3));return/wo|wh/.test(s)||xe(n,t)==="o"?"O":"U"}const Ae={d:"DD",t:"DD",n:"DD",s:"SS",z:"SS",k:"kk",g:"kk",c:"CH",x:"CH",j:"CH"};function nn(e,t){const n=e.toLowerCase(),r=xe(n,t);if(Ae[r])return Ae[r];for(let s=0;s<n.length;s++){const a=n[s];if(Ae[a])return Ae[a]}return"DD"}function rn(e,t,n){const r=Xt(e);if(r.length===1)return r[0];const s=t.trim();if(!s)return r[0];const a=(e??"").toLowerCase(),o=Math.max(0,n);switch(a){case"aei":return Zt(s,o);case"o":return en(s,o);case"qw":return tn(s,o);case"cdgknstxyz":return nn(s,o);default:return r[0]}}function sn(e){let t=e.trim();const n=t.indexOf(",");t.startsWith("data:")&&n>=0&&(t=t.slice(n+1)),t=t.replace(/\s+/g,"").replace(/-/g,"+").replace(/_/g,"/");const r=t.length%4;return r!==0&&(t+="=".repeat(4-r)),t}const on=24e3;function an(e){return e.length>=4&&e[0]===82&&e[1]===73&&e[2]===70&&e[3]===70}function Xe(e,t,n=on){const r=t.byteOffset%2===0?t:t.slice(),s=new Int16Array(r.buffer,r.byteOffset,r.byteLength/2),a=new Float32Array(s.length);for(let c=0;c<s.length;c++)a[c]=s[c]>=32768?-(65536-s[c])/32768:s[c]/32767;const o=e.createBuffer(1,a.length,n);return o.copyToChannel(a,0),o}function cn(e){const t=sn(e),n=window.atob(t),r=new Uint8Array(n.length);for(let s=0;s<n.length;s++)r[s]=n.charCodeAt(s);return r}async function un(e,t){const n=cn(t);if(an(n)){const r=n.buffer.slice(n.byteOffset,n.byteOffset+n.byteLength);return e.decodeAudioData(r)}if(n.length>=2&&n.length%2===0)return Xe(e,n);try{const r=n.buffer.slice(n.byteOffset,n.byteOffset+n.byteLength);return await e.decodeAudioData(r)}catch{return Xe(e,n)}}function ht(e,t){let n=null;for(const r of e)t<r.vtime||t>=r.vtime+r.vduration||(!n||r.vtime>=n.vtime)&&(n=r);return n?n.viseme:"sil"}function _t(e,t){for(const n of e)if(t>=n.wtime&&t<n.wtime+n.wduration)return n;return null}function Ye(e){let t=0;for(const n of e)t=Math.max(t,n.vtime+n.vduration);return t}const mt=.5,wt=1.5,qe="Olivia",gt="f786b574-daa5-4673-aa0c-cbe3e8534c02",Ge=.85;function Et(e,t=De){const n=`${t.replace(/\/$/,"")}/avatar_ttsWithPoses`,r=[],s=[],a=[];let o="neutral";const c=[],f=[];let h=null,_=!1,d=!1,u=!1,i=!1,T=0,R=0,S=0,Q=0,W=null,N=1,K="",g=re,E=re,k=!1;const V=new Set,q=()=>{for(const w of f)w.playbackRate.value=N},I=()=>V.forEach(w=>w()),J=()=>{W!=null&&(clearTimeout(W),W=null)},ie=()=>{for(const w of f)try{w.stop()}catch{}f.length=0},le=()=>{k=!0,J(),ie(),c.length=0,_=!1,d=!1,u=!1,i=!1,r.length=0,s.length=0,a.length=0,o="neutral",S=0,Q=0,R=0,e("idle"),I()},oe=()=>{!i||_||f.length>0||c.length>0||(d=!1,J(),e("done"),I())},fe=()=>{const w=Ye(r);if(w<=0){e("done"),I();return}d=!0,T=performance.now(),e("speaking"),I(),J();const C=N>0?w/N:w;W=setTimeout(()=>{k||(d=!1,W=null,e("done"),I())},C)},Y=(w,C,A)=>{w.length!==0&&(A&&(S=C),w.forEach(v=>{const F=String(v.word??"").trim();if(!F)return;const D=Math.round((v.start??0)*1e3),G=Math.round((v.duration??0)*1e3);s.push({word:F,wtime:S+D,wduration:G,queueIndex:s.length})}))},Se=(w,C,A,v)=>{w.length!==0&&(A&&(S=C),w.forEach(b=>{const F=String(b.symbol??"").trim();if(!F)return;const D=Math.round((b.start??0)*1e3),G=Math.max(1,Math.round((b.duration??0)*1e3)),M=S+D;let B;if(bt(v)==="oculus_direct")B=dt(F);else{const $=_t(s,M),P=$?Yt($,M):0;B=rn(F,$?.word??"",P)}r.push({viseme:B,weight:1,vtime:M,vduration:G})}),I())},de=(w,C,A,v,b)=>{Y(C,A,v),Se(w,A,v,b)},ae=async(w,C,A,v)=>{if(k||!w?.trim()){(C.length>0||A.length>0)&&!u&&de(C,A,S,v,E);return}if(_){c.push({audio:w,visemes:C,words:A,isNewSegment:v});return}_=!0;try{const b=window.AudioContext||window.webkitAudioContext,F=h??new b;F.state==="suspended"&&await F.resume(),h=F;const D=await un(F,w);u=!0;const G=F.currentTime;let M=Q;const B=!d;M<G&&(M=G+.1),Q=M+D.duration;const $=F.createBufferSource();if($.buffer=D,$.playbackRate.value=N,$.connect(F.destination),f.push($),k){f.pop();return}if(B){d=!0,e("speaking"),R=M,S=0,r.length=0,s.length=0;const L=(M-G)*1e3;T=performance.now()+L}$.onended=()=>{const L=f.indexOf($);L>=0&&f.splice(L,1),oe(),I()},$.start(M);const P=(M-R)*1e3;de(C,A,P,v,E)}catch(b){console.error("[avatarTtsLipsync] audio chunk failed:",b)}finally{_=!1;const b=c.shift();b?await ae(b.audio,b.visemes,b.words,b.isNewSegment):oe()}},Te=()=>{if(i=!0,!u&&r.length>0){fe();return}oe()};return{setDeveloperToken:w=>{K=w},setTtsEngineId:w=>{g=w},getTtsEngineId:()=>g,speak:async(w,C)=>{le(),k=!1,e("loading");const A=K.trim();if(!A)throw new Error("Developer token required for avatar_ttsWithPoses");const v=C?.ttsEngineId??g??Ke;E=v;const b=C?.voiceId??qe,F=C?.speakingRate??Ge,D=Math.max(mt,Math.min(wt,F)),G={user_query:w,ttsEngineId:v,speakingRate:D};Rt.has(v)&&(G.voice_id=b);try{const M=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${A}`},body:JSON.stringify(G)});if(!M.ok)throw new Error(`avatar_ttsWithPoses failed (${M.status})`);const B=M.body;if(!B)throw new Error("No response body");const $=B.getReader(),P=new TextDecoder;let L="";const ce=async Z=>{const U=zt(Z);if(U){if(U.event==="audio"){const X=U.data.chunk,l=U.data.visemes??[],p=U.data.words??[],y=U.data.is_new_segment??!1;if(X)await ae(X,l,p,y);else if(l.length>0||p.length>0){const x=y&&r.length>0?Ye(r):S;de(l,p,x,y,v)}}else if(U.event==="metadata"){const X=U.data.mood;typeof X=="string"&&X.trim()&&(o=X.trim());const l=U.data.sentence_emotions;if(Array.isArray(l)){a.length=0;for(const p of l){if(!p||typeof p!="object")continue;const y=p;a.push({sentence_index:Number(y.sentence_index??0),text:String(y.text??""),sentiment:typeof y.sentiment=="string"?y.sentiment:void 0,emotion:String(y.emotion??o),start_word:Number(y.start_word??0),end_word:Number(y.end_word??0)})}}I()}else if(U.event==="error")throw new Error(String(U.data.message??"avatar_ttsWithPoses stream error"))}};for(;;){const{done:Z,value:U}=await $.read();U&&(L+=P.decode(U,{stream:!0}));const X=L.split(`
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const Me=require("react/jsx-runtime"),_=require("react"),At="https://pub-607ad1fc22e2400eb57d17240aab857c.r2.dev",ot={publicBase:At},vt="0.1.4",Rt={version:vt},Ae="https://ai.streamoji.com",bt=`${ot.publicBase}/custom-faces`,Dt=`${ot.publicBase}/aitwin-workers/v${Rt.version}/visemeDiffPreview.worker.js`,xt="https://us-central1-streamoji-265f4.cloudfunctions.net/getAiTwin",te="eng_a7f2b9c1",we="eng_d4e8f3a2",ge="eng_c9b1e6d4",He=we,Ct=new Set([we,ge]),at={[te]:"oculus_direct",[ge]:"oculus_direct",[we]:"inworld_word"},je={google:te,inworld:we,cartesia:ge};function Mt(e){return at[e]}function Pt(e){return e===ge}function Ft(e){if(e.ttsEngineId&&e.ttsEngineId in at)return e.ttsEngineId;const t=e.tts?.toLowerCase();return t&&t in je?je[t]:He}class ve extends Error{constructor(t="AI twin not found"){super(t),this.name="AiTwinNotFoundError"}}async function ct(e,t=xt){const n=new URL(t);n.searchParams.set("id",e);const r=await fetch(n.toString());if(r.status===404)throw new ve;if(!r.ok)throw new Error(`getAiTwin failed (${r.status})`);const s=await r.json();if(!s.success)throw new ve(s.error??"AI twin not found");const{tts:o,...a}=s.data;return{...a,ttsEngineId:Ft(s.data)}}const Ot="https://us-central1-streamoji-265f4.cloudfunctions.net/getAuthToken",Lt="client_6TNvp3SCs4Og0a1ijm9TommXLql1",Nt="kk8Fq8EmexzP10jMIEwY3R44M5RKUEm1",Ut="6TNvp3SCs4Og0a1ijm9TommXLql1",Bt="Swaraj Mali";async function Fe(){const e=await fetch(Ot,{method:"POST",headers:{"Content-Type":"application/json","Client-Id":Lt,"Client-Secret":Nt},body:JSON.stringify({userId:Ut,userName:Bt})});if(!e.ok)throw new Error(`getAuthToken failed (${e.status})`);const t=await e.json(),n=t.authToken??t.token??"";if(!n.trim())throw new Error("getAuthToken returned no token");return n}async function Vt(e,t=Ae){const n=await fetch(`${t.replace(/\/$/,"")}/api/session-value`,{headers:{Authorization:`Bearer ${e}`}});if(!n.ok)throw new Error(`/api/session-value failed (${n.status})`);const r=await n.json();if(!r.value)throw new Error("Session value response missing value");return r}function $t(e){const t=e.trim();if(t.length%2!==0)throw new Error("Invalid hex key");const n=new Uint8Array(t.length/2);for(let r=0;r<t.length;r+=2)n[r/2]=Number.parseInt(t.slice(r,r+2),16);return n}function Se(e){return Uint8Array.from(e)}function Ht(e,t){const n=new Uint8Array(e.length+t.length);return n.set(e,0),n.set(t,e.length),n}async function Wt(e,t){if(!t)throw new Error("Asset key is required for encrypted assets");if(e.byteLength<28)throw new Error("Encrypted payload too small");const n=new Uint8Array(e),r=Se(n.subarray(0,12)),s=Se(n.subarray(12,28)),o=Se(n.subarray(28)),a=Se(Ht(o,s)),c=await crypto.subtle.importKey("raw",$t(t),{name:"AES-GCM"},!1,["decrypt"]);return crypto.subtle.decrypt({name:"AES-GCM",iv:r,tagLength:128},c,a)}let Oe=null;const Le=new Set;function Kt(e,t=bt){const n=`${t.replace(/\/$/,"")}/${e}`;return{twinBase:n,binBase:n,encrypted:!0}}function qt(e){Oe=e;for(const t of Le)t()}function ne(){if(!Oe)throw new Error("Twin assets not configured; call setActiveTwinAssets first");return Oe}function Gt(e){return Le.add(e),()=>Le.delete(e)}function jt(){return`${ne().twinBase}/sil.png`}function zt(){return`${ne().twinBase}/idle.mp4`}function Qt(){const{encrypted:e,binBase:t,twinBase:n}=ne();return e?t:n}function ut(){return ne().encrypted}function Jt(){const{binBase:e,twinBase:t,encrypted:n}=ne();return n?`${e}/atlas.bin`:`${t}/atlas.json`}function Xt(){const{binBase:e,twinBase:t,encrypted:n}=ne();return n?`${e}/expression_atlas.bin`:`${t}/expression_atlas.json`}function Yt(e){const t=e.split(/\r?\n/);let n="",r="";for(const o of t)o.startsWith("event:")?n=o.slice(6).trim():o.startsWith("data:")&&(r=o.slice(5).trim());if(!n)return null;let s={};if(r)try{s=JSON.parse(r)}catch{s={raw:r}}return{event:n,data:s}}const lt=["aa","CH","DD","E","FF","I","O","PP","RR","SS","TH","U","kk","nn","sil"],Zt=new Map(lt.map(e=>[e.toLowerCase(),e]));function ft(e){const t=(e??"").trim();return t?Zt.get(t.toLowerCase())??"sil":"sil"}const en={aei:["aa","E","I"],o:["O","U"],ee:["I"],bmp:["PP"],fv:["FF"],l:["nn"],r:["RR"],th:["TH"],qw:["U","O"],cdgknstxyz:["DD","SS","kk","CH"]};function tn(e){if(!e)return["sil"];const t=e.toLowerCase();return en[t]??["sil"]}function nn(e,t){const n=e.word.length;if(n<=0)return 0;const r=e.wduration;if(r<=0)return 0;const s=Math.max(0,Math.min(1,(t-e.wtime)/r));return Math.min(n-1,Math.floor(s*n))}function be(e,t){const n=Math.max(0,Math.min(e.length-1,t));return e[n]??""}function rn(e,t){const n=e.toLowerCase(),r=be(n,t),s=n.slice(Math.max(0,t-1),t+2);return r==="i"||r==="y"?"I":s.includes("ee")||r==="e"||n.includes("ea")?"E":"aa"}function sn(e,t){const n=e.toLowerCase(),r=n.slice(Math.max(0,t-1),Math.min(n.length,t+3));if(/oo|ou|uw/.test(r))return"U";const s=be(n,t);return s==="u"||s==="w"?"U":"O"}function on(e,t){const n=e.toLowerCase(),r=n.slice(Math.max(0,t-2),t+1);if(/qu/.test(r))return"U";const s=n.slice(Math.max(0,t-1),Math.min(n.length,t+3));return/wo|wh/.test(s)||be(n,t)==="o"?"O":"U"}const Te={d:"DD",t:"DD",n:"DD",s:"SS",z:"SS",k:"kk",g:"kk",c:"CH",x:"CH",j:"CH"};function an(e,t){const n=e.toLowerCase(),r=be(n,t);if(Te[r])return Te[r];for(let s=0;s<n.length;s++){const o=n[s];if(Te[o])return Te[o]}return"DD"}function cn(e,t,n){const r=tn(e);if(r.length===1)return r[0];const s=t.trim();if(!s)return r[0];const o=(e??"").toLowerCase(),a=Math.max(0,n);switch(o){case"aei":return rn(s,a);case"o":return sn(s,a);case"qw":return on(s,a);case"cdgknstxyz":return an(s,a);default:return r[0]}}function un(e){let t=e.trim();const n=t.indexOf(",");t.startsWith("data:")&&n>=0&&(t=t.slice(n+1)),t=t.replace(/\s+/g,"").replace(/-/g,"+").replace(/_/g,"/");const r=t.length%4;return r!==0&&(t+="=".repeat(4-r)),t}const ln=24e3;function fn(e){return e.length>=4&&e[0]===82&&e[1]===73&&e[2]===70&&e[3]===70}function ze(e,t,n=ln){const r=t.byteOffset%2===0?t:t.slice(),s=new Int16Array(r.buffer,r.byteOffset,r.byteLength/2),o=new Float32Array(s.length);for(let c=0;c<s.length;c++)o[c]=s[c]>=32768?-(65536-s[c])/32768:s[c]/32767;const a=e.createBuffer(1,o.length,n);return a.copyToChannel(o,0),a}function dn(e){const t=un(e),n=window.atob(t),r=new Uint8Array(n.length);for(let s=0;s<n.length;s++)r[s]=n.charCodeAt(s);return r}async function hn(e,t){const n=dn(t);if(fn(n)){const r=n.buffer.slice(n.byteOffset,n.byteOffset+n.byteLength);return e.decodeAudioData(r)}if(n.length>=2&&n.length%2===0)return ze(e,n);try{const r=n.buffer.slice(n.byteOffset,n.byteOffset+n.byteLength);return await e.decodeAudioData(r)}catch{return ze(e,n)}}function dt(e,t){let n=null;for(const r of e)t<r.vtime||t>=r.vtime+r.vduration||(!n||r.vtime>=n.vtime)&&(n=r);return n?n.viseme:"sil"}function ht(e,t){for(const n of e)if(t>=n.wtime&&t<n.wtime+n.wduration)return n;return null}function Qe(e){let t=0;for(const n of e)t=Math.max(t,n.vtime+n.vduration);return t}const _t=.5,mt=1.5,We="Olivia",wt="f786b574-daa5-4673-aa0c-cbe3e8534c02",Ke=.85;function gt(e,t=Ae){const n=`${t.replace(/\/$/,"")}/avatar_ttsWithPoses`,r=[],s=[],o=[];let a="neutral";const c=[],u=[];let m=null,d=!1,T=!1,f=!1,i=!1,g=0,v=0,E=0,$=0,F=null,B=1,Q="",w=te,y=te,b=!1;const R=new Set,H=()=>{for(const h of u)h.playbackRate.value=B},W=()=>R.forEach(h=>h()),ie=()=>{F!=null&&(clearTimeout(F),F=null)},Ee=()=>{for(const h of u)try{h.stop()}catch{}u.length=0},Y=()=>{b=!0,ie(),Ee(),c.length=0,d=!1,T=!1,f=!1,i=!1,r.length=0,s.length=0,o.length=0,a="neutral",E=0,$=0,v=0,e("idle"),W()},K=()=>{!i||d||u.length>0||c.length>0||(T=!1,ie(),e("done"),W())},ye=()=>{const h=Qe(r);if(h<=0){e("done"),W();return}T=!0,g=performance.now(),e("speaking"),W(),ie();const D=B>0?h/B:h;F=setTimeout(()=>{b||(T=!1,F=null,e("done"),W())},D)},xe=(h,D,N)=>{h.length!==0&&(N&&(E=D),h.forEach(M=>{const O=String(M.word??"").trim();if(!O)return;const z=Math.round((M.start??0)*1e3),U=Math.round((M.duration??0)*1e3);s.push({word:O,wtime:E+z,wduration:U,queueIndex:s.length})}))},oe=(h,D,N,M)=>{h.length!==0&&(N&&(E=D),h.forEach(S=>{const O=String(S.symbol??"").trim();if(!O)return;const z=Math.round((S.start??0)*1e3),U=Math.max(1,Math.round((S.duration??0)*1e3)),P=E+z;let x;if(Mt(M)==="oculus_direct")x=ft(O);else{const C=ht(s,P),J=C?nn(C,P):0;x=cn(O,C?.word??"",J)}r.push({viseme:x,weight:1,vtime:P,vduration:U})}),W())},re=(h,D,N,M,S)=>{xe(D,N,M),oe(h,N,M,S)},pe=async(h,D,N,M)=>{if(b||!h?.trim()){(D.length>0||N.length>0)&&!f&&re(D,N,E,M,y);return}if(d){c.push({audio:h,visemes:D,words:N,isNewSegment:M});return}d=!0;try{const S=window.AudioContext||window.webkitAudioContext,O=m??new S;O.state==="suspended"&&await O.resume(),m=O;const z=await hn(O,h);f=!0;const U=O.currentTime;let P=$;const x=!T;P<U&&(P=U+.1),$=P+z.duration;const C=O.createBufferSource();if(C.buffer=z,C.playbackRate.value=B,C.connect(O.destination),u.push(C),b){u.pop();return}if(x){T=!0,e("speaking"),v=P,E=0,r.length=0,s.length=0;const V=(P-U)*1e3;g=performance.now()+V}C.onended=()=>{const V=u.indexOf(C);V>=0&&u.splice(V,1),K(),W()},C.start(P);const J=(P-v)*1e3;re(D,N,J,M,y)}catch(S){console.error("[avatarTtsLipsync] audio chunk failed:",S)}finally{d=!1;const S=c.shift();S?await pe(S.audio,S.visemes,S.words,S.isNewSegment):K()}},Z=()=>{if(i=!0,!f&&r.length>0){ye();return}K()};return{setDeveloperToken:h=>{Q=h},setTtsEngineId:h=>{w=h},getTtsEngineId:()=>w,speak:async(h,D)=>{Y(),b=!1,e("loading");const N=Q.trim();if(!N)throw new Error("Developer token required for avatar_ttsWithPoses");const M=D?.ttsEngineId??w??He;y=M;const S=D?.voiceId??We,O=D?.speakingRate??Ke,z=Math.max(_t,Math.min(mt,O)),U={user_query:h,ttsEngineId:M,speakingRate:z};Ct.has(M)&&(U.voice_id=S);try{const P=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${N}`},body:JSON.stringify(U)});if(!P.ok)throw new Error(`avatar_ttsWithPoses failed (${P.status})`);const x=P.body;if(!x)throw new Error("No response body");const C=x.getReader(),J=new TextDecoder;let V="";const ce=async ue=>{const l=Yt(ue);if(l){if(l.event==="audio"){const p=l.data.chunk,k=l.data.visemes??[],I=l.data.words??[],A=l.data.is_new_segment??!1;if(p)await pe(p,k,I,A);else if(k.length>0||I.length>0){const q=A&&r.length>0?Qe(r):E;re(k,I,q,A,M)}}else if(l.event==="metadata"){const p=l.data.mood;typeof p=="string"&&p.trim()&&(a=p.trim());const k=l.data.sentence_emotions;if(Array.isArray(k)){o.length=0;for(const I of k){if(!I||typeof I!="object")continue;const A=I;o.push({sentence_index:Number(A.sentence_index??0),text:String(A.text??""),sentiment:typeof A.sentiment=="string"?A.sentiment:void 0,emotion:String(A.emotion??a),start_word:Number(A.start_word??0),end_word:Number(A.end_word??0)})}}W()}else if(l.event==="error")throw new Error(String(l.data.message??"avatar_ttsWithPoses stream error"))}};for(;;){const{done:ue,value:l}=await C.read();l&&(V+=J.decode(l,{stream:!0}));const p=V.split(`
2
2
 
3
- `);L=X.pop()??"";for(const l of X)await ce(l);if(Z){L.trim()&&await ce(L.trim()),k||Te();break}}}catch(M){throw console.error("[avatarTtsLipsync]",M),le(),e("error"),M}},stop:le,getVisemeQueue:()=>r,getWordQueue:()=>s,getSentenceEmotions:()=>a,getStreamMood:()=>o,getPlaybackElapsedMs:()=>d?u&&h&&R>0?Math.max(0,(h.currentTime-R)*1e3):Math.max(0,(performance.now()-T)*N):0,isSpeaking:()=>d,setPlaybackSpeed:w=>{N=Math.max(.1,Math.min(1,w)),q()},getPlaybackSpeed:()=>N,subscribe:w=>(V.add(w),()=>V.delete(w))}}function ln(e,t,n){return{width:e.crop?.source_width??t,height:e.crop?.source_height??n}}function fn(e,t){const n=e.crop;return{x:t?.source_x??n?.x??0,y:t?.source_y??n?.y??0,width:t?.source_w??n?.width??e.frame_width??0,height:t?.source_h??n?.height??e.frame_height??0}}function dn(e){return e?(e.w??0)>0&&(e.h??0)>0:!1}async function yt(e,t){const n=await fetch(e);if(!n.ok)throw new Error(`Failed to load encrypted asset: ${e}`);const r=await n.arrayBuffer();return Vt(r,t)}async function hn(e,t){if(!t)throw new Error("Missing asset key for encrypted JSON");const n=await yt(e,t),r=new TextDecoder().decode(n);return JSON.parse(r)}async function _n(e){const t=new Blob([e],{type:"image/webp"}),n=URL.createObjectURL(t);return new Promise((r,s)=>{const a=new Image;a.decoding="async",a.onload=()=>{URL.revokeObjectURL(n),r(a)},a.onerror=()=>{URL.revokeObjectURL(n),s(new Error("Failed to decode decrypted image"))},a.src=n})}function pt(e,t){return`${e}/${t}_minus_sil.png`}const je=15,mn=["aa","E","I","O","U","PP","FF","DD","SS","TH","CH","RR","kk","nn"],Ue=["t01_0.17","t02_0.33","t03_0.50","t04_0.67","t05_0.83"],wn=Ue.length,Ze=new Set(["aa__kk","aa__nn","aa__sil","CH__aa","CH__DD","CH__E","CH__FF","CH__I","CH__kk","CH__nn","CH__O","CH__PP","CH__RR","CH__sil","CH__SS","CH__TH","CH__U","DD__aa","DD__E","DD__FF","DD__I","DD__kk","DD__nn","DD__O","DD__PP","DD__RR","DD__sil","DD__SS","DD__TH","DD__U","E__aa","E__FF","E__I","E__kk","E__nn","E__O","E__PP","E__RR","E__sil","E__SS","E__TH","E__U","FF__aa","FF__I","FF__kk","FF__nn","FF__O","FF__PP","FF__RR","FF__sil","FF__SS","FF__TH","FF__U","I__aa","I__kk","I__nn","I__O","I__PP","I__RR","I__sil","I__SS","I__TH","I__U","kk__nn","kk__sil","nn__sil","O__aa","O__kk","O__nn","O__PP","O__RR","O__sil","O__SS","O__TH","O__U","PP__aa","PP__kk","PP__nn","PP__RR","PP__sil","PP__SS","PP__TH","PP__U","RR__aa","RR__kk","RR__nn","RR__sil","RR__SS","RR__TH","RR__U","SS__aa","SS__kk","SS__nn","SS__sil","SS__TH","SS__U","TH__aa","TH__kk","TH__nn","TH__sil","TH__U","U__aa","U__kk","U__nn","U__sil"]);function et(e,t){return`${e}__${t}`}function tt(e,t){return`pairs/${e}/${t}_minus_sil.png`}function Ve(e){return`${e}_minus_sil.png`}function gn(e,t){if(e===t)return[];const n=[],r=et(e,t);if(Ze.has(r)){for(const a of Ue)n.push(tt(r,a));return n}const s=et(t,e);if(Ze.has(s)){for(let a=wn-1;a>=0;a--)n.push(tt(s,Ue[a]));return n}return[]}function En(e){return e<16?[]:e<35?[2]:e<51?[0,4]:e<67?[0,2,4]:e<83?[0,1,2,3]:[0,1,2,3,4]}function yn(e,t){return En(t).map(r=>e[r]).filter(r=>r!=null)}function pn(e,t,n,r){if(r<=0)return 0;const a=Math.max(1,n-t)/r,o=e-t,c=Math.floor(o/a);return Math.min(r-1,Math.max(0,c))}function Sn(e,t,n){if(!n)return`${e}/${t}`;const r=t.split("/").pop()??t,s=r.includes(".")?r.slice(0,r.lastIndexOf(".")):r;return`${e}/${s}.bin`}const Tn=[.32,.24,.16,.08,0],Ce=Tn.map(e=>`eyes_${e.toFixed(2)}`),In=["eyes_0.32","eyes_0.16","eyes_0.00"],An=["eyes_0.32","eyes_0.16","eyes_0.08","eyes_0.00"],kn={fear:"fear",afraid:"fear",anxiety:"fear",anger:"anger",angry:"anger",mad:"anger",sad:"sad",sadness:"sad",sorrow:"sad",neutral:"neutral",calm:"neutral",love:"love",loving:"love",affection:"love",happy:"happy",happiness:"happy",joy:"happy",joyful:"happy",excited:"happy",disgust:"disgust",disgusted:"disgust"};function ue(e,t="neutral"){const n=String(e??"").trim().toLowerCase();return n?kn[n]??t:t}function z(e){return e==="neutral"?null:pt(e,"eyes_standard")}function Be(e,t){return!t||t==="eyes_standard"?z(e):e==="neutral"&&t==="eyes_standard"?null:pt(e,t)}function vn(e){if(!e)return"open";const t=e.match(/\/(eyes_[^/]+)_minus_sil\.png$/);if(!t?.[1])return"open";const n=t[1];return Ce.includes(n)?n:"open"}function Rn(e){return e==="open"?-1:Ce.indexOf(e)}function bn(e,t){const n=[];for(const r of t)n.push(Be(e,r));for(let r=t.length-2;r>=0;r--)n.push(Be(e,t[r]));return n.push(z(e)),n}function Dn(e,t){if(t==="open")return[z(e)];const n=Rn(t);if(n<0)return[z(e)];const r=[];for(let s=n;s>=0;s--)r.push(Be(e,Ce[s]));return r.push(z(e)),r}const xn=["t01_0.20","t02_0.40","t03_0.60","t04_0.80"];function Cn(e,t){return`${e}__${t}`}function Mn(e,t,n){return`pairs/${Cn(e,t)}/${n}_minus_sil.png`}function Fn(e,t){return xn.map(n=>Mn(e,t,n))}function we(e,t){return e+Math.random()*(t-e)}function ke(){return we(14,32)}function Pn(e={}){const{initialDelayMs:t=800+Math.random()*1200,intervalMinMs:n=2200,intervalMaxMs:r=5800,doubleBlinkChance:s=.18,doubleBlinkGapMinMs:a=120,doubleBlinkGapMaxMs:o=220,fullBlinkChance:c=.75,postEmotionChangeDelayMs:f=380,minDwellMs:h=550}=e;let _="neutral",d="neutral",u=0,i={kind:"idle",nextBlinkAt:performance.now()+t},T=null,R="__eyes_open__|neutral";function S(g,E){T=g,R=`${g??"__eyes_open__"}|${E}`}function Q(g,E){i={kind:"idle",nextBlinkAt:g+we(n,r)},d=E,S(z(E),E)}function W(g,E,k){const V=k?In:Math.random()<c?Ce:An;i={kind:"playing",paths:bn(E,V),index:0,holdUntil:g+ke(),after:"idle",blinkEmotion:E},d=E,S(i.paths[0]??null,E)}function N(g,E,k){const V=vn(T),q=[];if(V!=="open"){const I=Dn(E,V);q.push(...I.slice(0,-1))}q.push(...Fn(E,k)),q.push(z(k)),i={kind:"emotionBlend",paths:q,index:0,holdUntil:g+ke(),thenEmotion:k},S(q[0]??null,E)}function K(g){if(i.kind==="emotionBlend"){for(;g>=i.holdUntil&&i.index<i.paths.length-1;)i.index+=1,i.holdUntil=g+ke();const E=i.paths[i.index]??null;S(E,i.thenEmotion),g>=i.holdUntil&&i.index>=i.paths.length-1&&(_=i.thenEmotion,d=i.thenEmotion,S(z(i.thenEmotion),i.thenEmotion),i={kind:"idle",nextBlinkAt:g+f});return}if(i.kind==="idle"){S(z(d),d),g>=i.nextBlinkAt&&W(g,d,!1);return}if(i.kind==="doublePause"){S(z(i.blinkEmotion),i.blinkEmotion),g>=i.resumeAt&&W(g,i.blinkEmotion,!0);return}if(i.kind==="playing"){for(;g>=i.holdUntil&&i.index<i.paths.length-1;)i.index+=1,i.holdUntil=g+ke();if(S(i.paths[i.index]??null,i.blinkEmotion),g>=i.holdUntil&&i.index>=i.paths.length-1){if(i.after==="resumeIdle"){Q(g+f,_);return}if(i.after==="doublePause"){i={kind:"doublePause",resumeAt:g+we(a,o),blinkEmotion:i.blinkEmotion},S(z(i.blinkEmotion),i.blinkEmotion);return}if(i.after==="idle"&&Math.random()<s){i={kind:"doublePause",resumeAt:g+we(a,o),blinkEmotion:i.blinkEmotion},S(z(i.blinkEmotion),i.blinkEmotion);return}Q(g,i.blinkEmotion)}}}return{advance:K,setTargetEmotion(g){const E=ue(g,_);if(E===_&&i.kind!=="emotionBlend")return;const k=performance.now();if(h>0&&E!==_&&i.kind!=="emotionBlend"&&!(_==="neutral"&&E!=="neutral")&&k-u<h)return;const V=_;if(_=E,u=k,i.kind==="playing"){N(k,d,E);return}if(i.kind==="emotionBlend"){i={...i,thenEmotion:E};return}N(k,V,E)},getTargetEmotion:()=>_,getExpressionPath:()=>T,getDrawKey:()=>R,reset(){_="neutral",d="neutral",u=0,Q(performance.now()+we(n,r),"neutral")}}}function On(e){const t=document.createElement("video");t.muted=!0,t.playsInline=!0,t.preload="auto",t.setAttribute("playsinline",""),t.loop=!0;let n=!1;return{async load(){n||await new Promise((r,s)=>{const a=()=>{const o=t.duration;if(!Number.isFinite(o)||o<=0){s(new Error(`Idle video has invalid duration: ${e}`));return}n=!0,t.currentTime=0,r()};t.addEventListener("loadeddata",a,{once:!0}),t.addEventListener("error",()=>s(new Error(`Failed to load idle video: ${e}`)),{once:!0}),t.src=e,t.load()})},isReady(){return n},getVideo(){return t},setActive(r){n&&(r?t.paused&&t.play().catch(()=>{}):t.paused||t.pause())},restart(){n&&(t.currentTime=0)}}}const Ln=50,St=400;function Nn(e,t,n){return e.filter(r=>{const s=r.queueIndex??-1;return s>=t&&s<=n})}function Un(e,t){const n=[];for(const r of e){const s=Nn(t,r.start_word,r.end_word);if(s.length===0)continue;const a=s[0],o=s[s.length-1];n.push({sentence:r,startMs:Math.max(0,a.wtime-Ln),endMs:o.wtime+o.wduration+St})}return n.sort((r,s)=>r.startMs-s.startMs)}function Vn(e,t,n,r="neutral"){const s=ue(r);if(t.length===0)return s;if(n.length===0||e<n[0].wtime)return ue(t[0]?.emotion,s);const a=Un(t,n);let o=null;for(const h of a)e>=h.startMs&&e<=h.endMs&&(o=h);if(o)return ue(o.sentence.emotion,s);const c=n[n.length-1],f=c.wtime+c.wduration;return e>f+St?ue(t[t.length-1]?.emotion,s):s}function Tt(e,t,n,r,s=je){const a=new OffscreenCanvas(n,r),o=a.getContext("2d",{willReadFrequently:!0});o.drawImage(e,0,0,n,r);const c=o.getImageData(0,0,n,r),f=o.createImageData(n,r);f.data.set(c.data);const _=new OffscreenCanvas(n,r).getContext("2d",{willReadFrequently:!0});for(const d of t){_.clearRect(0,0,n,r),_.drawImage(d,0,0,n,r);const u=_.getImageData(0,0,n,r);for(let i=0;i<f.data.length;i+=4){const T=u.data[i],R=u.data[i+1],S=u.data[i+2];Math.max(T,R,S)>s&&(f.data[i]=T,f.data[i+1]=R,f.data[i+2]=S,f.data[i+3]=255)}}return o.putImageData(f,0,0),a}let ne=null,ge=null;const be=new Map;function Bn(){ne=null,ge=null,be.clear()}Ht(Bn);function $n(e){return e??ge??void 0}function ze(e){return new Promise((t,n)=>{const r=new Image;r.decoding="async",r.onload=()=>t(r),r.onerror=()=>n(new Error(`Failed to load image: ${e}`)),r.src=e})}async function nt(e,t,n,r){const s=n?await hn(e,r):await fetch(e).then(h=>{if(!h.ok)throw new Error(`Failed to load ${e}`);return h.json()}),a=s.sheets?.[0];if(!a?.path)throw new Error(`${e} has no sheets[0].path`);const o=n?await _n(await yt(Sn(t,a.path,n),r??"")):await ze(`${t}/${a.path}`),c=new Map;for(const h of s.cells??[])h.path&&c.set(h.path,h);const f=new Map;for(const h of s.sheets??[])f.set(h.index,h);return{atlas:o,atlasMeta:s,cellByPath:c,sheetByIndex:f,diffBase:t}}async function $e(e){const t=$n(e),n=lt();if(n&&!t)throw new Error("Encrypted assets enabled but no key provided");if(ne&&(!n||ge===(t??null))){const a=await ne;return Ee(a)}ge=t??null,be.clear();const r=qt();ne=(async()=>{const a=await ze(Wt()),o=await nt(Gt(),r,n,t);let c=null;try{c=await nt(jt(),r,n,t)}catch{c=null}return{sil:a,viseme:o,expression:c}})();const s=await ne;return Ee(s)}async function It(e){if(await $e(e),!ne)throw new Error("Assets not loaded");return ne}function Ee(e){return ln(e.viseme.atlasMeta,e.sil.naturalWidth,e.sil.naturalHeight)}function Hn(e,t){const n=document.createElement("canvas");return n.width=t.w,n.height=t.h,n.getContext("2d",{willReadFrequently:!0}).drawImage(e.atlas,t.x,t.y,t.w,t.h,0,0,t.w,t.h),n}async function rt(e,t,n){const r=`${t.diffBase}::${n}`,s=be.get(r);if(s)return s;const a=(async()=>{const o=t.cellByPath.get(n);if(!o)throw new Error(`No atlas cell for path: ${n}`);const c=fn(t.atlasMeta,o),f=Ee(e);if(dn(o)){const d=Hn(t,o),u=document.createElement("canvas");u.width=f.width,u.height=f.height;const i=u.getContext("2d");return i.fillStyle="#000",i.fillRect(0,0,f.width,f.height),i.drawImage(d,c.x,c.y),u}const h=`${t.diffBase}/${n}`,_=await ze(h);if(_.naturalWidth===f.width&&_.naturalHeight===f.height)return _;throw new Error(`Diff PNG wrong size for ${n}`)})();return be.set(r,a),a}async function st(e,t,n,r=je,s,a){if(s){const{width:u,height:i}=s;if(a&&!a()||t.readyState<HTMLMediaElement.HAVE_CURRENT_DATA)return;const T=document.createElement("canvas");T.width=u,T.height=i;const R=T.getContext("2d");if(R.clearRect(0,0,u,i),R.drawImage(t,0,0,u,i),a&&!a())return;(e.width!==u||e.height!==i)&&(e.width=u,e.height=i);const S=e.getContext("2d");S.clearRect(0,0,u,i),S.drawImage(T,0,0);return}const o=await It(),{width:c,height:f}=Ee(o);(e.width!==c||e.height!==f)&&(e.width=c,e.height=f);const h=[],_=e.getContext("2d");if(_.clearRect(0,0,c,f),t.readyState<HTMLMediaElement.HAVE_CURRENT_DATA){const u=o.sil;_.drawImage(u,0,0,c,f);return}if(h.length===0){_.drawImage(t,0,0,c,f);return}const d=Tt(t,h,c,f,r);_.drawImage(d,0,0)}async function He(e,t,n=je){const r=await It(ge??void 0),{width:s,height:a}=Ee(r);(e.width!==s||e.height!==a)&&(e.width=s,e.height=a);const o=[];t.mouthPath&&o.push(await rt(r,r.viseme,t.mouthPath)),t.expressionPath&&r.expression&&o.push(await rt(r,r.expression,t.expressionPath));const c=e.getContext("2d");if(c.clearRect(0,0,s,a),o.length===0){c.drawImage(r.sil,0,0,s,a);return}const f=Tt(r.sil,o,s,a,n);c.drawImage(f,0,0)}async function Wn(e){await He(e,{mouthPath:null,expressionPath:null})}function Kn(e){const t=new Map;for(const n of e)t.has(n.vtime)||t.set(n.vtime,n);return[...t.values()].sort((n,r)=>n.vtime-r.vtime)}function qn(e){const t=Kn(e),n=[];for(let r=0;r<t.length-1;r++){const s=t[r].viseme,a=t[r+1].viseme,o=t[r].vtime,c=t[r+1].vtime;s===a||c<=o||n.push({from:s,to:a,fromVtime:o,toVtime:c})}return n}function Gn(e,t){let n=null;for(const r of e)t>=r.fromVtime&&t<r.toVtime&&(n=r);return n}function jn(e,t){return{gapMs:Math.max(0,t-e),holdEnd:e,transStart:e}}const zn=500,Qn="__sil__";function Jn(){return{lastDrawnKey:""}}function me(e){e.lastDrawnKey=""}function it(e){return e??Qn}function Xn(e,t){if(e.length===0)return{diffPath:null,label:"sil"};const n=qn(e),r=Gn(n,t);if(r){const a=r.toVtime-r.fromVtime,o=jn(r.fromVtime,r.toVtime);if(t>=o.transStart&&t<r.toVtime){const c=gn(r.from,r.to),f=yn(c,a);if(f.length>0){const h=pn(t,o.transStart,r.toVtime,f.length);return{diffPath:f[h]??f[f.length-1],label:`${r.from}→${r.to}`}}return{diffPath:Ve(r.to),label:r.to}}}const s=ht(e,t);return s==="sil"?{diffPath:null,label:"sil"}:{diffPath:Ve(s),label:s}}function At(e,t){const n=t??it(e.expressionPath);return`${it(e.mouthPath)}|${n}`}function Yn(e,t,n,r,s,a,o,c){const f=Xn(t,n),h={mouthPath:f.diffPath,expressionPath:r},_=At(h,s);_!==a.lastDrawnKey&&(a.lastDrawnKey=_,c(f.label),o(e,h))}function ot(e,t,n,r,s,a,o=null){const c={mouthPath:null,expressionPath:t},f=o!=null?`|idle@${Math.round(o*1e3)}`:"",h=At(c,n)+f;!(o!=null)&&h===r.lastDrawnKey||(r.lastDrawnKey=h,a(o!=null?"idle":"sil"),s(e,c))}function Zn(e){return new Worker("/assets/visemeDiffPreview.worker-D2ggcW5u.js",{name:e?.name})}function er(){return typeof Worker<"u"&&typeof OffscreenCanvas<"u"}function tr(e,t){(e.width!==t.width||e.height!==t.height)&&(e.width=t.width,e.height=t.height);const n=e.getContext("2d");n&&n.drawImage(t,0,0)}function at(e,t){let n=0;return{usesWorker:!1,async loadAssets(r){return await $e(r)},async renderSilOnly(){n+=1,await Wn(e)},async drawLiveFrame(r,s){await $e(),await He(r,s)},async renderViseme(r,s){n+=1;const a=n;t.onStatus?.(s),await He(r,{mouthPath:Ve(s),expressionPath:null})},dispose(){n+=1}}}function nr(e,t){const n=new Zn;let r=1,s=0,a=!1,o=!1;const c=new Map,f=(d,u)=>{o||n.postMessage(d,[])},h=(d,u,i=!1)=>{if(o)return Promise.resolve();const T=r++;return new Promise((R,S)=>{c.set(T,{resolve:Q=>R(Q),reject:S,generation:typeof d.generation=="number"?d.generation:void 0,expectRenderDone:i}),f({...d,requestId:T})})};n.onmessage=d=>{if(o)return;const u=d.data;if(u.type==="status"){t.onStatus?.(u.label);return}if(u.type==="frame"){const T=u.generation<0;if(!T&&u.generation!==s){u.bitmap.close();return}if(T&&t.shouldAcceptLiveFrame&&!t.shouldAcceptLiveFrame()){u.bitmap.close();return}tr(e,u.bitmap),u.bitmap.close();return}const i=c.get(u.requestId);if(i)switch(u.type){case"ready":c.delete(u.requestId),i.resolve();break;case"loadAssetsDone":c.delete(u.requestId),i.resolve({width:u.width,height:u.height});break;case"renderDone":if(i.expectRenderDone&&i.generation!=null&&u.generation!==i.generation)return;c.delete(u.requestId),i.resolve();break;case"renderAborted":c.delete(u.requestId),i.resolve();break;case"error":c.delete(u.requestId),t.onError?.(u.message),i.reject(new Error(u.message));break}},n.onerror=d=>{if(o)return;const u=d.message||"Worker error";t.onError?.(u);for(const[,i]of c)i.reject(new Error(u));c.clear()};const _=(async()=>{await h({type:"init"}),a=!0})();return{usesWorker:!0,async loadAssets(d){if(o)return{width:842,height:1264};if(await _,o)return{width:842,height:1264};if(!a)throw new Error("Worker init failed");return await h({type:"loadAssets",keyHex:d,urls:se()})??{width:842,height:1264}},async renderSilOnly(){if(o||(await _,o))return;s+=1;const d=s;await h({type:"renderSil",generation:d},void 0,!0)},async drawLiveFrame(d,u){o||(await _,!o&&await h({type:"drawFrame",diffPath:u.mouthPath,expressionDiffPath:u.expressionPath},void 0,!0))},async renderViseme(d,u,i={}){if(o||(await _,o))return;s+=1;const T=s;try{await h({type:"renderViseme",generation:T,to:u,from:i.from,transitionDurationMs:i.transitionDurationMs,gapMs:i.gapMs,threshold:i.threshold},void 0,!0)}catch(R){if(R?.name==="AbortError")return;throw R}},dispose(){if(!o){o=!0,s+=1;for(const[,d]of c)d.resolve();c.clear(),n.terminate()}}}}function rr(e,t={}){if(!er())return at(e,t);try{return nr(e,t)}catch{return at(e,t)}}class sr extends Error{constructor(t,n){super(`${t} timed out after ${Math.round(n/1e3)}s`),this.name="LoadTimeoutError"}}function Pe(e,t,n){return new Promise((r,s)=>{const a=globalThis.setTimeout(()=>{s(new sr(n,t))},t);e.then(o=>{globalThis.clearTimeout(a),r(o)},o=>{globalThis.clearTimeout(a),s(o)})})}const ir={position:"relative",display:"inline-block",lineHeight:0},or={display:"block",maxWidth:"100%",height:"auto"},ar={position:"absolute",inset:0,display:"flex",alignItems:"center",justifyContent:"center",padding:"1rem",background:"rgba(0,0,0,0.55)",color:"#fff",fontSize:"0.875rem",textAlign:"center"};function ve(e){return Dt(e)?gt:qe}const cr=m.forwardRef(function({id:t,assets:n,authToken:r,apiBase:s=De,facesCdnBase:a=We,ttsEngineId:o=re,voiceId:c,speakingRate:f=Ge,className:h,style:_,canvasStyle:d,onStatusChange:u,onDisplayStatus:i,onError:T,onReady:R,showErrorOverlay:S=!0},Q){const W=m.useRef(null),N=m.useRef(null),K=m.useRef(Jn()),g=m.useRef(Pn()),E=m.useRef(0),k=m.useRef(0),V=m.useRef(null),q=m.useRef(!1),I=m.useRef(null),J=m.useRef(!1),[ie,le]=m.useState("idle"),[oe,fe]=m.useState(null),[Y,Se]=m.useState(!1),[de,ae]=m.useState(!1),[Te,Qe]=m.useState({width:842,height:1264}),w=m.useRef(r??null),C=m.useRef(null),A=m.useRef(null),v=m.useRef(!1),b=m.useRef({width:842,height:1264}),F=m.useRef(R),D=m.useRef(i),G=m.useRef(T);F.current=R,D.current=i,G.current=T;const M=m.useCallback(l=>{const p=l?.ttsEngineId??o??A.current?.ttsEngineId??re,y=l?.voiceId??c??A.current?.voiceId??ve(p);return{ttsEngineId:p,voiceId:y}},[o,c]),B=m.useCallback(l=>{fe(l),G.current?.(l)},[]),$=m.useCallback(l=>{le(l),u?.(l)},[u]),P=m.useRef(Et($,s)),L=m.useCallback(()=>{V.current!=null&&(clearTimeout(V.current),V.current=null)},[]),ce=m.useCallback(async()=>{const l=k.current,p=N.current;!p||!Y||P.current.isSpeaking()||(me(K.current),await p.renderSilOnly(),l===k.current&&(P.current.isSpeaking()||(D.current?.("sil"),J.current&&I.current&&(I.current.restart(),I.current.setActive(!0)))))},[Y]),Z=m.useCallback(()=>{L();const l=k.current;ce(),V.current=setTimeout(()=>{V.current=null,l===k.current&&ce()},zn)},[L,ce]),U=m.useCallback(async()=>{const l=Math.floor(Date.now()/1e3);if(C.current&&l<C.current.expiresAt-60)return C.current.key;const p=w.current??await Oe();w.current=p,P.current.setDeveloperToken(p);const y=await Lt(p,s);return C.current={key:y.value,expiresAt:y.expiresAt},y.value},[s]);m.useEffect(()=>{r&&(w.current=r,P.current.setDeveloperToken(r))},[r]),m.useEffect(()=>{P.current.setTtsEngineId(o),A.current&&(A.current.ttsEngineId=o)},[o]),m.useEffect(()=>{const l=c??ve(o);A.current&&(A.current.voiceId=l)},[c,o]);const X=m.useMemo(()=>n?JSON.stringify(n):`id:${t??""}:${a}`,[n,t,a]);return m.useEffect(()=>{if(!t&&!n){B("AiTwin requires either `id` or `assets`");return}let l=!1;v.current=!1,Se(!1),ae(!1),fe(null),A.current=null,I.current=null,J.current=!1;const p=W.current;if(!p)return;let y=null;return(async()=>{try{let x,H,ee;if(n)x=n,H=o,ee=c??ve(H);else{D.current?.("getAiTwin");const O=await Pe(ut(t),3e4,"getAiTwin");if(l)return;if(!O.faceId?.trim())throw new Error("getAiTwin returned no faceId");H=O.ttsEngineId,ee=c??O.voiceId??ve(H),x=Bt(O.faceId,a)}A.current={ttsEngineId:H,voiceId:ee},$t(x),I.current=On(Kt()),y=rr(p,{onStatus:O=>{l||D.current?.(O)},onError:O=>{l||B(O)},shouldAcceptLiveFrame:()=>P.current.isSpeaking()}),N.current=y,D.current?.("auth");const te=w.current??r??await Pe(Oe(),3e4,"getAuthToken");if(l)return;w.current=te,P.current.setDeveloperToken(te),P.current.setTtsEngineId(H);const Me=lt()?await U():void 0;if(l)return;D.current?.("loadAssets");const j=await Pe(y.loadAssets(Me),18e4,"load face assets");if(!l&&j.width>0&&j.height>0&&(b.current=j,Qe(j)),l)return;v.current=!0,Se(!0),F.current?.(),y.renderSilOnly().then(()=>{l||D.current?.("sil")}),(async()=>{try{if(await I.current.load(),l)return;J.current=!0,ae(!0),me(K.current),I.current.setActive(!0);const O=I.current.getVideo();await st(p,O,null,void 0,b.current),l||D.current?.("idle")}catch(O){if(l)return;J.current=!1,ae(!1),console.warn("[AiTwin] Idle video unavailable:",O)}})()}catch(x){if(l)return;if(x instanceof Re){B(x.message);return}B(x instanceof Error?x.message:"Failed to load AI twin")}})(),()=>{l=!0,y?.dispose(),N.current=null}},[X,n,o,c,a,r,s,U,B]),m.useEffect(()=>{ie==="done"&&Y&&!P.current.isSpeaking()&&Z()},[ie,Y,Z]),m.useEffect(()=>{const l=P.current,p={current:!1},y=()=>{const x=W.current,H=N.current;if(!x||!H||!Y){E.current=requestAnimationFrame(y);return}const ee=l.isSpeaking(),te=l.getPlaybackElapsedMs(),Me=ee?Vn(te,l.getSentenceEmotions(),l.getWordQueue(),l.getStreamMood()):l.getStreamMood();if(ee){if(J.current&&I.current?.setActive(!1),l.getVisemeQueue().length===0){E.current=requestAnimationFrame(y);return}g.current.setTargetEmotion(Me),g.current.advance(performance.now());const O=g.current.getExpressionPath(),he=g.current.getDrawKey();Yn(x,l.getVisemeQueue(),te,O,he,K.current,(_e,kt)=>H.drawLiveFrame(_e,kt),_e=>D.current?.(_e))}else if(J.current&&I.current){const j=I.current,O=j.getVideo();O.readyState>=HTMLMediaElement.HAVE_CURRENT_DATA?(j.setActive(!0),p.current||(p.current=!0,st(x,O,null,void 0,b.current,()=>!l.isSpeaking()).then(()=>D.current?.("idle")).finally(()=>{p.current=!1}))):ot(x,null,"__sil__",K.current,(he,_e)=>H.drawLiveFrame(he,_e),he=>D.current?.(he))}else ot(x,null,"__sil__",K.current,(j,O)=>H.drawLiveFrame(j,O),j=>D.current?.(j));q.current&&!ee&&(g.current.reset(),I.current?.setActive(!1),Z()),q.current=ee,E.current=requestAnimationFrame(y)};return E.current=requestAnimationFrame(y),()=>{cancelAnimationFrame(E.current),L(),l.stop()}},[Y,de,Z,L]),m.useImperativeHandle(Q,()=>({speakText:async(l,p)=>{const y=l.trim();if(!y)return;const x=N.current;if(!x||!v.current&&!Y)throw new Error("AI twin is not ready");const{ttsEngineId:H,voiceId:ee}=M(p);fe(null),k.current+=1,L(),me(K.current),g.current.reset(),q.current=!1;try{J.current?(I.current?.setActive(!1),I.current?.restart(),me(K.current)):await x.renderSilOnly(),await P.current.speak(y,{voiceId:ee,speakingRate:p?.speakingRate??f,ttsEngineId:H})}catch(te){throw B(te instanceof Error?te.message:"TTS failed"),te}},stop:()=>{k.current+=1,L(),P.current.stop(),me(K.current),q.current=!1,Z()},setTtsEngineId:l=>{P.current.setTtsEngineId(l),A.current&&(A.current.ttsEngineId=l)},renderViseme:async(l,p)=>{const y=N.current,x=W.current;if(!y||!x||!v.current)throw new Error("AI twin is not ready");await y.renderViseme(x,l,{from:p?.from,transitionDurationMs:p?.transitionDurationMs,gapMs:p?.gapMs,onStatus:H=>D.current?.(H)})},isReady:()=>v.current,getStatus:()=>ie}),[Y,f,L,Z,B,M,ie]),Fe.jsxs("div",{className:h,style:{...ir,..._},children:[Fe.jsx("canvas",{ref:W,width:Te.width,height:Te.height,style:{...or,...d},"aria-label":t?`AI twin ${t}`:"AI twin face"}),S&&oe?Fe.jsx("div",{style:ar,children:oe}):null]})});exports.AiTwin=cr;exports.AiTwinNotFoundError=Re;exports.DEFAULT_API_BASE=De;exports.DEFAULT_FACES_CDN_BASE=We;exports.DEFAULT_TTS_ENGINE_ID=Ke;exports.OCULUS_VISEME_IDS=ft;exports.SPEAKING_RATE_MAX=wt;exports.SPEAKING_RATE_MIN=mt;exports.TTS_ENGINE_CARTESIA=pe;exports.TTS_ENGINE_GOOGLE=re;exports.TTS_ENGINE_INWORLD=ye;exports.VISEME_IDS=mn;exports.VISEME_TEST_CARTESIA_VOICE_ID=gt;exports.VISEME_TEST_SPEAKING_RATE=Ge;exports.VISEME_TEST_VOICE_ID=qe;exports.createAvatarTtsLipsyncController=Et;exports.fetchAiTwin=ut;exports.fetchDevAuthToken=Oe;exports.normalizeOculusViseme=dt;exports.resolveVisemeAtTime=ht;exports.resolveWordAtTime=_t;
3
+ `);V=p.pop()??"";for(const k of p)await ce(k);if(ue){V.trim()&&await ce(V.trim()),b||Z();break}}}catch(P){throw console.error("[avatarTtsLipsync]",P),Y(),e("error"),P}},stop:Y,getVisemeQueue:()=>r,getWordQueue:()=>s,getSentenceEmotions:()=>o,getStreamMood:()=>a,getPlaybackElapsedMs:()=>T?f&&m&&v>0?Math.max(0,(m.currentTime-v)*1e3):Math.max(0,(performance.now()-g)*B):0,isSpeaking:()=>T,setPlaybackSpeed:h=>{B=Math.max(.1,Math.min(1,h)),H()},getPlaybackSpeed:()=>B,subscribe:h=>(R.add(h),()=>R.delete(h))}}function _n(e,t,n){return{width:e.crop?.source_width??t,height:e.crop?.source_height??n}}function mn(e,t){const n=e.crop;return{x:t?.source_x??n?.x??0,y:t?.source_y??n?.y??0,width:t?.source_w??n?.width??e.frame_width??0,height:t?.source_h??n?.height??e.frame_height??0}}function wn(e){return e?(e.w??0)>0&&(e.h??0)>0:!1}async function Et(e,t){const n=await fetch(e);if(!n.ok)throw new Error(`Failed to load encrypted asset: ${e}`);const r=await n.arrayBuffer();return Wt(r,t)}async function gn(e,t){if(!t)throw new Error("Missing asset key for encrypted JSON");const n=await Et(e,t),r=new TextDecoder().decode(n);return JSON.parse(r)}async function En(e){const t=new Blob([e],{type:"image/webp"}),n=URL.createObjectURL(t);return new Promise((r,s)=>{const o=new Image;o.decoding="async",o.onload=()=>{URL.revokeObjectURL(n),r(o)},o.onerror=()=>{URL.revokeObjectURL(n),s(new Error("Failed to decode decrypted image"))},o.src=n})}function yt(e,t){return`${e}/${t}_minus_sil.png`}const qe=15,yn=["aa","E","I","O","U","PP","FF","DD","SS","TH","CH","RR","kk","nn"],Ne=["t01_0.17","t02_0.33","t03_0.50","t04_0.67","t05_0.83"],pn=Ne.length,Je=new Set(["aa__kk","aa__nn","aa__sil","CH__aa","CH__DD","CH__E","CH__FF","CH__I","CH__kk","CH__nn","CH__O","CH__PP","CH__RR","CH__sil","CH__SS","CH__TH","CH__U","DD__aa","DD__E","DD__FF","DD__I","DD__kk","DD__nn","DD__O","DD__PP","DD__RR","DD__sil","DD__SS","DD__TH","DD__U","E__aa","E__FF","E__I","E__kk","E__nn","E__O","E__PP","E__RR","E__sil","E__SS","E__TH","E__U","FF__aa","FF__I","FF__kk","FF__nn","FF__O","FF__PP","FF__RR","FF__sil","FF__SS","FF__TH","FF__U","I__aa","I__kk","I__nn","I__O","I__PP","I__RR","I__sil","I__SS","I__TH","I__U","kk__nn","kk__sil","nn__sil","O__aa","O__kk","O__nn","O__PP","O__RR","O__sil","O__SS","O__TH","O__U","PP__aa","PP__kk","PP__nn","PP__RR","PP__sil","PP__SS","PP__TH","PP__U","RR__aa","RR__kk","RR__nn","RR__sil","RR__SS","RR__TH","RR__U","SS__aa","SS__kk","SS__nn","SS__sil","SS__TH","SS__U","TH__aa","TH__kk","TH__nn","TH__sil","TH__U","U__aa","U__kk","U__nn","U__sil"]);function Xe(e,t){return`${e}__${t}`}function Ye(e,t){return`pairs/${e}/${t}_minus_sil.png`}function Ue(e){return`${e}_minus_sil.png`}function Sn(e,t){if(e===t)return[];const n=[],r=Xe(e,t);if(Je.has(r)){for(const o of Ne)n.push(Ye(r,o));return n}const s=Xe(t,e);if(Je.has(s)){for(let o=pn-1;o>=0;o--)n.push(Ye(s,Ne[o]));return n}return[]}function Tn(e){return e<16?[]:e<35?[2]:e<51?[0,4]:e<67?[0,2,4]:e<83?[0,1,2,3]:[0,1,2,3,4]}function kn(e,t){return Tn(t).map(r=>e[r]).filter(r=>r!=null)}function In(e,t,n,r){if(r<=0)return 0;const o=Math.max(1,n-t)/r,a=e-t,c=Math.floor(a/o);return Math.min(r-1,Math.max(0,c))}function An(e,t,n){if(!n)return`${e}/${t}`;const r=t.split("/").pop()??t,s=r.includes(".")?r.slice(0,r.lastIndexOf(".")):r;return`${e}/${s}.bin`}const vn=[.32,.24,.16,.08,0],De=vn.map(e=>`eyes_${e.toFixed(2)}`),Rn=["eyes_0.32","eyes_0.16","eyes_0.00"],bn=["eyes_0.32","eyes_0.16","eyes_0.08","eyes_0.00"],Dn={fear:"fear",afraid:"fear",anxiety:"fear",anger:"anger",angry:"anger",mad:"anger",sad:"sad",sadness:"sad",sorrow:"sad",neutral:"neutral",calm:"neutral",love:"love",loving:"love",affection:"love",happy:"happy",happiness:"happy",joy:"happy",joyful:"happy",excited:"happy",disgust:"disgust",disgusted:"disgust"};function se(e,t="neutral"){const n=String(e??"").trim().toLowerCase();return n?Dn[n]??t:t}function j(e){return e==="neutral"?null:yt(e,"eyes_standard")}function Be(e,t){return!t||t==="eyes_standard"?j(e):e==="neutral"&&t==="eyes_standard"?null:yt(e,t)}function xn(e){if(!e)return"open";const t=e.match(/\/(eyes_[^/]+)_minus_sil\.png$/);if(!t?.[1])return"open";const n=t[1];return De.includes(n)?n:"open"}function Cn(e){return e==="open"?-1:De.indexOf(e)}function Mn(e,t){const n=[];for(const r of t)n.push(Be(e,r));for(let r=t.length-2;r>=0;r--)n.push(Be(e,t[r]));return n.push(j(e)),n}function Pn(e,t){if(t==="open")return[j(e)];const n=Cn(t);if(n<0)return[j(e)];const r=[];for(let s=n;s>=0;s--)r.push(Be(e,De[s]));return r.push(j(e)),r}const Fn=["t01_0.20","t02_0.40","t03_0.60","t04_0.80"];function On(e,t){return`${e}__${t}`}function Ln(e,t,n){return`pairs/${On(e,t)}/${n}_minus_sil.png`}function Nn(e,t){return Fn.map(n=>Ln(e,t,n))}function he(e,t){return e+Math.random()*(t-e)}function ke(){return he(14,32)}function Un(e={}){const{initialDelayMs:t=800+Math.random()*1200,intervalMinMs:n=2200,intervalMaxMs:r=5800,doubleBlinkChance:s=.18,doubleBlinkGapMinMs:o=120,doubleBlinkGapMaxMs:a=220,fullBlinkChance:c=.75,postEmotionChangeDelayMs:u=380,minDwellMs:m=550}=e;let d="neutral",T="neutral",f=0,i={kind:"idle",nextBlinkAt:performance.now()+t},g=null,v="__eyes_open__|neutral";function E(w,y){g=w,v=`${w??"__eyes_open__"}|${y}`}function $(w,y){i={kind:"idle",nextBlinkAt:w+he(n,r)},T=y,E(j(y),y)}function F(w,y,b){const R=b?Rn:Math.random()<c?De:bn;i={kind:"playing",paths:Mn(y,R),index:0,holdUntil:w+ke(),after:"idle",blinkEmotion:y},T=y,E(i.paths[0]??null,y)}function B(w,y,b){const R=xn(g),H=[];if(R!=="open"){const W=Pn(y,R);H.push(...W.slice(0,-1))}H.push(...Nn(y,b)),H.push(j(b)),i={kind:"emotionBlend",paths:H,index:0,holdUntil:w+ke(),thenEmotion:b},E(H[0]??null,y)}function Q(w){if(i.kind==="emotionBlend"){for(;w>=i.holdUntil&&i.index<i.paths.length-1;)i.index+=1,i.holdUntil=w+ke();const y=i.paths[i.index]??null;E(y,i.thenEmotion),w>=i.holdUntil&&i.index>=i.paths.length-1&&(d=i.thenEmotion,T=i.thenEmotion,E(j(i.thenEmotion),i.thenEmotion),i={kind:"idle",nextBlinkAt:w+u});return}if(i.kind==="idle"){E(j(T),T),w>=i.nextBlinkAt&&F(w,T,!1);return}if(i.kind==="doublePause"){E(j(i.blinkEmotion),i.blinkEmotion),w>=i.resumeAt&&F(w,i.blinkEmotion,!0);return}if(i.kind==="playing"){for(;w>=i.holdUntil&&i.index<i.paths.length-1;)i.index+=1,i.holdUntil=w+ke();if(E(i.paths[i.index]??null,i.blinkEmotion),w>=i.holdUntil&&i.index>=i.paths.length-1){if(i.after==="resumeIdle"){$(w+u,d);return}if(i.after==="doublePause"){i={kind:"doublePause",resumeAt:w+he(o,a),blinkEmotion:i.blinkEmotion},E(j(i.blinkEmotion),i.blinkEmotion);return}if(i.after==="idle"&&Math.random()<s){i={kind:"doublePause",resumeAt:w+he(o,a),blinkEmotion:i.blinkEmotion},E(j(i.blinkEmotion),i.blinkEmotion);return}$(w,i.blinkEmotion)}}}return{advance:Q,setTargetEmotion(w){const y=se(w,d);if(y===d&&i.kind!=="emotionBlend")return;const b=performance.now();if(m>0&&y!==d&&i.kind!=="emotionBlend"&&!(d==="neutral"&&y!=="neutral")&&b-f<m)return;const R=d;if(d=y,f=b,i.kind==="playing"){B(b,T,y);return}if(i.kind==="emotionBlend"){i={...i,thenEmotion:y};return}B(b,R,y)},getTargetEmotion:()=>d,getExpressionPath:()=>g,getDrawKey:()=>v,reset(){d="neutral",T="neutral",f=0,$(performance.now()+he(n,r),"neutral")}}}function Bn(e){const t=document.createElement("video");t.muted=!0,t.playsInline=!0,t.preload="auto",t.setAttribute("playsinline",""),t.loop=!0;let n=!1;return{async load(){n||await new Promise((r,s)=>{const o=()=>{const a=t.duration;if(!Number.isFinite(a)||a<=0){s(new Error(`Idle video has invalid duration: ${e}`));return}n=!0,t.currentTime=0,r()};t.addEventListener("loadeddata",o,{once:!0}),t.addEventListener("error",()=>s(new Error(`Failed to load idle video: ${e}`)),{once:!0}),t.src=e,t.load()})},isReady(){return n},getVideo(){return t},setActive(r){n&&(r?t.paused&&t.play().catch(()=>{}):t.paused||t.pause())},restart(){n&&(t.currentTime=0)}}}const Vn=50,pt=400;function $n(e,t,n){return e.filter(r=>{const s=r.queueIndex??-1;return s>=t&&s<=n})}function Hn(e,t){const n=[];for(const r of e){const s=$n(t,r.start_word,r.end_word);if(s.length===0)continue;const o=s[0],a=s[s.length-1];n.push({sentence:r,startMs:Math.max(0,o.wtime-Vn),endMs:a.wtime+a.wduration+pt})}return n.sort((r,s)=>r.startMs-s.startMs)}function Wn(e,t,n,r="neutral"){const s=se(r);if(t.length===0)return s;if(n.length===0||e<n[0].wtime)return se(t[0]?.emotion,s);const o=Hn(t,n);let a=null;for(const m of o)e>=m.startMs&&e<=m.endMs&&(a=m);if(a)return se(a.sentence.emotion,s);const c=n[n.length-1],u=c.wtime+c.wduration;return e>u+pt?se(t[t.length-1]?.emotion,s):s}function St(e,t,n,r,s=qe){const o=new OffscreenCanvas(n,r),a=o.getContext("2d",{willReadFrequently:!0});a.drawImage(e,0,0,n,r);const c=a.getImageData(0,0,n,r),u=a.createImageData(n,r);u.data.set(c.data);const d=new OffscreenCanvas(n,r).getContext("2d",{willReadFrequently:!0});for(const T of t){d.clearRect(0,0,n,r),d.drawImage(T,0,0,n,r);const f=d.getImageData(0,0,n,r);for(let i=0;i<u.data.length;i+=4){const g=f.data[i],v=f.data[i+1],E=f.data[i+2];Math.max(g,v,E)>s&&(u.data[i]=g,u.data[i+1]=v,u.data[i+2]=E,u.data[i+3]=255)}}return a.putImageData(u,0,0),o}let ee=null,_e=null;const Re=new Map;function Kn(){ee=null,_e=null,Re.clear()}Gt(Kn);function qn(e){return e??_e??void 0}function Ge(e){return new Promise((t,n)=>{const r=new Image;r.decoding="async",r.onload=()=>t(r),r.onerror=()=>n(new Error(`Failed to load image: ${e}`)),r.src=e})}async function Ze(e,t,n,r){const s=n?await gn(e,r):await fetch(e).then(m=>{if(!m.ok)throw new Error(`Failed to load ${e}`);return m.json()}),o=s.sheets?.[0];if(!o?.path)throw new Error(`${e} has no sheets[0].path`);const a=n?await En(await Et(An(t,o.path,n),r??"")):await Ge(`${t}/${o.path}`),c=new Map;for(const m of s.cells??[])m.path&&c.set(m.path,m);const u=new Map;for(const m of s.sheets??[])u.set(m.index,m);return{atlas:a,atlasMeta:s,cellByPath:c,sheetByIndex:u,diffBase:t}}async function Ve(e){const t=qn(e),n=ut();if(n&&!t)throw new Error("Encrypted assets enabled but no key provided");if(ee&&(!n||_e===(t??null))){const o=await ee;return me(o)}_e=t??null,Re.clear();const r=Qt();ee=(async()=>{const o=await Ge(jt()),a=await Ze(Jt(),r,n,t);let c=null;try{c=await Ze(Xt(),r,n,t)}catch{c=null}return{sil:o,viseme:a,expression:c}})();const s=await ee;return me(s)}async function Tt(e){if(await Ve(e),!ee)throw new Error("Assets not loaded");return ee}function me(e){return _n(e.viseme.atlasMeta,e.sil.naturalWidth,e.sil.naturalHeight)}function Gn(e,t){const n=document.createElement("canvas");return n.width=t.w,n.height=t.h,n.getContext("2d",{willReadFrequently:!0}).drawImage(e.atlas,t.x,t.y,t.w,t.h,0,0,t.w,t.h),n}async function et(e,t,n){const r=`${t.diffBase}::${n}`,s=Re.get(r);if(s)return s;const o=(async()=>{const a=t.cellByPath.get(n);if(!a)throw new Error(`No atlas cell for path: ${n}`);const c=mn(t.atlasMeta,a),u=me(e);if(wn(a)){const T=Gn(t,a),f=document.createElement("canvas");f.width=u.width,f.height=u.height;const i=f.getContext("2d");return i.fillStyle="#000",i.fillRect(0,0,u.width,u.height),i.drawImage(T,c.x,c.y),f}const m=`${t.diffBase}/${n}`,d=await Ge(m);if(d.naturalWidth===u.width&&d.naturalHeight===u.height)return d;throw new Error(`Diff PNG wrong size for ${n}`)})();return Re.set(r,o),o}async function tt(e,t,n,r=qe,s,o){if(s){const{width:f,height:i}=s;if(o&&!o()||t.readyState<HTMLMediaElement.HAVE_CURRENT_DATA)return;const g=document.createElement("canvas");g.width=f,g.height=i;const v=g.getContext("2d");if(v.clearRect(0,0,f,i),v.drawImage(t,0,0,f,i),o&&!o())return;(e.width!==f||e.height!==i)&&(e.width=f,e.height=i);const E=e.getContext("2d");E.clearRect(0,0,f,i),E.drawImage(g,0,0);return}const a=await Tt(),{width:c,height:u}=me(a);(e.width!==c||e.height!==u)&&(e.width=c,e.height=u);const m=[],d=e.getContext("2d");if(d.clearRect(0,0,c,u),t.readyState<HTMLMediaElement.HAVE_CURRENT_DATA){const f=a.sil;d.drawImage(f,0,0,c,u);return}if(m.length===0){d.drawImage(t,0,0,c,u);return}const T=St(t,m,c,u,r);d.drawImage(T,0,0)}async function $e(e,t,n=qe){const r=await Tt(_e??void 0),{width:s,height:o}=me(r);(e.width!==s||e.height!==o)&&(e.width=s,e.height=o);const a=[];t.mouthPath&&a.push(await et(r,r.viseme,t.mouthPath)),t.expressionPath&&r.expression&&a.push(await et(r,r.expression,t.expressionPath));const c=e.getContext("2d");if(c.clearRect(0,0,s,o),a.length===0){c.drawImage(r.sil,0,0,s,o);return}const u=St(r.sil,a,s,o,n);c.drawImage(u,0,0)}async function jn(e){await $e(e,{mouthPath:null,expressionPath:null})}function zn(e){const t=new Map;for(const n of e)t.has(n.vtime)||t.set(n.vtime,n);return[...t.values()].sort((n,r)=>n.vtime-r.vtime)}function Qn(e){const t=zn(e),n=[];for(let r=0;r<t.length-1;r++){const s=t[r].viseme,o=t[r+1].viseme,a=t[r].vtime,c=t[r+1].vtime;s===o||c<=a||n.push({from:s,to:o,fromVtime:a,toVtime:c})}return n}function Jn(e,t){let n=null;for(const r of e)t>=r.fromVtime&&t<r.toVtime&&(n=r);return n}function Xn(e,t){return{gapMs:Math.max(0,t-e),holdEnd:e,transStart:e}}const Yn=500,Zn="__sil__";function er(){return{lastDrawnKey:""}}function de(e){e.lastDrawnKey=""}function nt(e){return e??Zn}function tr(e,t){if(e.length===0)return{diffPath:null,label:"sil"};const n=Qn(e),r=Jn(n,t);if(r){const o=r.toVtime-r.fromVtime,a=Xn(r.fromVtime,r.toVtime);if(t>=a.transStart&&t<r.toVtime){const c=Sn(r.from,r.to),u=kn(c,o);if(u.length>0){const m=In(t,a.transStart,r.toVtime,u.length);return{diffPath:u[m]??u[u.length-1],label:`${r.from}→${r.to}`}}return{diffPath:Ue(r.to),label:r.to}}}const s=dt(e,t);return s==="sil"?{diffPath:null,label:"sil"}:{diffPath:Ue(s),label:s}}function kt(e,t){const n=t??nt(e.expressionPath);return`${nt(e.mouthPath)}|${n}`}function nr(e,t,n,r,s,o,a,c){const u=tr(t,n),m={mouthPath:u.diffPath,expressionPath:r},d=kt(m,s);d!==o.lastDrawnKey&&(o.lastDrawnKey=d,c(u.label),a(e,m))}function rt(e,t,n,r,s,o,a=null){const c={mouthPath:null,expressionPath:t},u=a!=null?`|idle@${Math.round(a*1e3)}`:"",m=kt(c,n)+u;!(a!=null)&&m===r.lastDrawnKey||(r.lastDrawnKey=m,o(a!=null?"idle":"sil"),s(e,c))}const st=new Map;async function rr(e){let t=st.get(e);if(!t){const n=await fetch(e);if(!n.ok)throw new Error(`Failed to fetch worker script (${n.status}): ${e}`);const r=await n.blob();t=URL.createObjectURL(r),st.set(e,t)}return new Worker(t,{name:"visemeDiffPreview"})}function sr(){return typeof Worker<"u"&&typeof OffscreenCanvas<"u"}function ir(e,t){(e.width!==t.width||e.height!==t.height)&&(e.width=t.width,e.height=t.height);const n=e.getContext("2d");n&&n.drawImage(t,0,0)}function it(e,t){let n=0;return{usesWorker:!1,async loadAssets(r){return await Ve(r)},async renderSilOnly(){n+=1,await jn(e)},async drawLiveFrame(r,s){await Ve(),await $e(r,s)},async renderViseme(r,s){n+=1;const o=n;t.onStatus?.(s),await $e(r,{mouthPath:Ue(s),expressionPath:null})},dispose(){n+=1}}}function or(e,t,n){let r=null,s=1,o=0,a=!1,c=!1;const u=new Map,m=(f,i)=>{c||!r||r.postMessage(f,[])},d=(f,i,g=!1)=>{if(c)return Promise.resolve();const v=s++;return new Promise((E,$)=>{u.set(v,{resolve:F=>E(F),reject:$,generation:typeof f.generation=="number"?f.generation:void 0,expectRenderDone:g}),m({...f,requestId:v})})},T=(async()=>{r=await rr(n),r.onmessage=f=>{if(c)return;const i=f.data;if(i.type==="status"){t.onStatus?.(i.label);return}if(i.type==="frame"){const v=i.generation<0;if(!v&&i.generation!==o){i.bitmap.close();return}if(v&&t.shouldAcceptLiveFrame&&!t.shouldAcceptLiveFrame()){i.bitmap.close();return}ir(e,i.bitmap),i.bitmap.close();return}const g=u.get(i.requestId);if(g)switch(i.type){case"ready":u.delete(i.requestId),g.resolve();break;case"loadAssetsDone":u.delete(i.requestId),g.resolve({width:i.width,height:i.height});break;case"renderDone":if(g.expectRenderDone&&g.generation!=null&&i.generation!==g.generation)return;u.delete(i.requestId),g.resolve();break;case"renderAborted":u.delete(i.requestId),g.resolve();break;case"error":u.delete(i.requestId),t.onError?.(i.message),g.reject(new Error(i.message));break}},r.onerror=f=>{if(c)return;const i=f.message||"Worker error";t.onError?.(i);for(const[,g]of u)g.reject(new Error(i));u.clear()},await d({type:"init"}),a=!0})();return{usesWorker:!0,async loadAssets(f){if(c)return{width:842,height:1264};if(await T,c)return{width:842,height:1264};if(!a)throw new Error("Worker init failed");return await d({type:"loadAssets",keyHex:f,urls:ne()})??{width:842,height:1264}},async renderSilOnly(){if(c||(await T,c))return;o+=1;const f=o;await d({type:"renderSil",generation:f},void 0,!0)},async drawLiveFrame(f,i){c||(await T,!c&&await d({type:"drawFrame",diffPath:i.mouthPath,expressionDiffPath:i.expressionPath},void 0,!0))},async renderViseme(f,i,g={}){if(c||(await T,c))return;o+=1;const v=o;try{await d({type:"renderViseme",generation:v,to:i,from:g.from,transitionDurationMs:g.transitionDurationMs,gapMs:g.gapMs,threshold:g.threshold},void 0,!0)}catch(E){if(E?.name==="AbortError")return;throw E}},dispose(){if(!c){c=!0,o+=1;for(const[,f]of u)f.resolve();u.clear(),r?.terminate(),r=null}}}}function ar(e,t={}){if(!sr())return it(e,t);const n=t.workerScriptUrl??Dt;try{return or(e,t,n)}catch{return it(e,t)}}class cr extends Error{constructor(t,n){super(`${t} timed out after ${Math.round(n/1e3)}s`),this.name="LoadTimeoutError"}}function Pe(e,t,n){return new Promise((r,s)=>{const o=globalThis.setTimeout(()=>{s(new cr(n,t))},t);e.then(a=>{globalThis.clearTimeout(o),r(a)},a=>{globalThis.clearTimeout(o),s(a)})})}const ur={position:"relative",display:"inline-block",lineHeight:0},lr={display:"block",maxWidth:"100%",height:"auto"},fr={position:"absolute",inset:0,display:"flex",alignItems:"center",justifyContent:"center",padding:"1rem",background:"rgba(0,0,0,0.55)",color:"#fff",fontSize:"0.875rem",textAlign:"center"};function Ie(e){return Pt(e)?wt:We}const dr=_.forwardRef(function({id:t,assets:n,authToken:r,ttsEngineId:s=te,voiceId:o,speakingRate:a=Ke,className:c,style:u,canvasStyle:m,onStatusChange:d,onDisplayStatus:T,onError:f,onReady:i,showErrorOverlay:g=!0},v){const E=_.useRef(null),$=_.useRef(null),F=_.useRef(er()),B=_.useRef(Un()),Q=_.useRef(0),w=_.useRef(0),y=_.useRef(null),b=_.useRef(!1),R=_.useRef(null),H=_.useRef(!1),[W,ie]=_.useState("idle"),[Ee,Y]=_.useState(null),[K,ye]=_.useState(!1),[xe,oe]=_.useState(!1),[re,pe]=_.useState({width:842,height:1264}),Z=_.useRef(r??null),ae=_.useRef(null),h=_.useRef(null),D=_.useRef(!1),N=_.useRef({width:842,height:1264}),M=_.useRef(i),S=_.useRef(T),O=_.useRef(f);M.current=i,S.current=T,O.current=f;const z=_.useCallback(l=>{const p=l?.ttsEngineId??s??h.current?.ttsEngineId??te,k=l?.voiceId??o??h.current?.voiceId??Ie(p);return{ttsEngineId:p,voiceId:k}},[s,o]),U=_.useCallback(l=>{Y(l),O.current?.(l)},[]),P=_.useCallback(l=>{ie(l),d?.(l)},[d]),x=_.useRef(gt(P,Ae)),C=_.useCallback(()=>{y.current!=null&&(clearTimeout(y.current),y.current=null)},[]),J=_.useCallback(async()=>{const l=w.current,p=$.current;!p||!K||x.current.isSpeaking()||(de(F.current),await p.renderSilOnly(),l===w.current&&(x.current.isSpeaking()||(S.current?.("sil"),H.current&&R.current&&(R.current.restart(),R.current.setActive(!0)))))},[K]),V=_.useCallback(()=>{C();const l=w.current;J(),y.current=setTimeout(()=>{y.current=null,l===w.current&&J()},Yn)},[C,J]),ce=_.useCallback(async()=>{const l=Math.floor(Date.now()/1e3);if(ae.current&&l<ae.current.expiresAt-60)return ae.current.key;const p=Z.current??await Fe();Z.current=p,x.current.setDeveloperToken(p);const k=await Vt(p,Ae);return ae.current={key:k.value,expiresAt:k.expiresAt},k.value},[]);_.useEffect(()=>{r&&(Z.current=r,x.current.setDeveloperToken(r))},[r]),_.useEffect(()=>{x.current.setTtsEngineId(s),h.current&&(h.current.ttsEngineId=s)},[s]),_.useEffect(()=>{const l=o??Ie(s);h.current&&(h.current.voiceId=l)},[o,s]);const ue=_.useMemo(()=>n?JSON.stringify(n):`id:${t??""}`,[n,t]);return _.useEffect(()=>{if(!t&&!n){U("AiTwin requires either `id` or `assets`");return}let l=!1;D.current=!1,ye(!1),oe(!1),Y(null),h.current=null,R.current=null,H.current=!1;const p=E.current;if(!p)return;let k=null;return(async()=>{try{let I,A,q;if(n)I=n,A=s,q=o??Ie(A);else{S.current?.("getAiTwin");const L=await Pe(ct(t),3e4,"getAiTwin");if(l)return;if(!L.faceId?.trim())throw new Error("getAiTwin returned no faceId");A=L.ttsEngineId,q=o??L.voiceId??Ie(A),I=Kt(L.faceId)}h.current={ttsEngineId:A,voiceId:q},qt(I),R.current=Bn(zt()),k=ar(p,{onStatus:L=>{l||S.current?.(L)},onError:L=>{l||U(L)},shouldAcceptLiveFrame:()=>x.current.isSpeaking()}),$.current=k,S.current?.("auth");const X=Z.current??r??await Pe(Fe(),3e4,"getAuthToken");if(l)return;Z.current=X,x.current.setDeveloperToken(X),x.current.setTtsEngineId(A);const Ce=ut()?await ce():void 0;if(l)return;S.current?.("loadAssets");const G=await Pe(k.loadAssets(Ce),18e4,"load face assets");if(!l&&G.width>0&&G.height>0&&(N.current=G,pe(G)),l)return;D.current=!0,ye(!0),M.current?.(),k.renderSilOnly().then(()=>{l||S.current?.("sil")}),(async()=>{try{if(await R.current.load(),l)return;H.current=!0,oe(!0),de(F.current),R.current.setActive(!0);const L=R.current.getVideo();await tt(p,L,null,void 0,N.current),l||S.current?.("idle")}catch(L){if(l)return;H.current=!1,oe(!1),console.warn("[AiTwin] Idle video unavailable:",L)}})()}catch(I){if(l)return;if(I instanceof ve){U(I.message);return}U(I instanceof Error?I.message:"Failed to load AI twin")}})(),()=>{l=!0,k?.dispose(),$.current=null}},[ue,n,s,o,r,ce,U]),_.useEffect(()=>{W==="done"&&K&&!x.current.isSpeaking()&&V()},[W,K,V]),_.useEffect(()=>{const l=x.current,p={current:!1},k=()=>{const I=E.current,A=$.current;if(!I||!A||!K){Q.current=requestAnimationFrame(k);return}const q=l.isSpeaking(),X=l.getPlaybackElapsedMs(),Ce=q?Wn(X,l.getSentenceEmotions(),l.getWordQueue(),l.getStreamMood()):l.getStreamMood();if(q){if(H.current&&R.current?.setActive(!1),l.getVisemeQueue().length===0){Q.current=requestAnimationFrame(k);return}B.current.setTargetEmotion(Ce),B.current.advance(performance.now());const L=B.current.getExpressionPath(),le=B.current.getDrawKey();nr(I,l.getVisemeQueue(),X,L,le,F.current,(fe,It)=>A.drawLiveFrame(fe,It),fe=>S.current?.(fe))}else if(H.current&&R.current){const G=R.current,L=G.getVideo();L.readyState>=HTMLMediaElement.HAVE_CURRENT_DATA?(G.setActive(!0),p.current||(p.current=!0,tt(I,L,null,void 0,N.current,()=>!l.isSpeaking()).then(()=>S.current?.("idle")).finally(()=>{p.current=!1}))):rt(I,null,"__sil__",F.current,(le,fe)=>A.drawLiveFrame(le,fe),le=>S.current?.(le))}else rt(I,null,"__sil__",F.current,(G,L)=>A.drawLiveFrame(G,L),G=>S.current?.(G));b.current&&!q&&(B.current.reset(),R.current?.setActive(!1),V()),b.current=q,Q.current=requestAnimationFrame(k)};return Q.current=requestAnimationFrame(k),()=>{cancelAnimationFrame(Q.current),C(),l.stop()}},[K,xe,V,C]),_.useImperativeHandle(v,()=>({speakText:async(l,p)=>{const k=l.trim();if(!k)return;const I=$.current;if(!I||!D.current&&!K)throw new Error("AI twin is not ready");const{ttsEngineId:A,voiceId:q}=z(p);Y(null),w.current+=1,C(),de(F.current),B.current.reset(),b.current=!1;try{H.current?(R.current?.setActive(!1),R.current?.restart(),de(F.current)):await I.renderSilOnly(),await x.current.speak(k,{voiceId:q,speakingRate:p?.speakingRate??a,ttsEngineId:A})}catch(X){throw U(X instanceof Error?X.message:"TTS failed"),X}},stop:()=>{w.current+=1,C(),x.current.stop(),de(F.current),b.current=!1,V()},setTtsEngineId:l=>{x.current.setTtsEngineId(l),h.current&&(h.current.ttsEngineId=l)},renderViseme:async(l,p)=>{const k=$.current,I=E.current;if(!k||!I||!D.current)throw new Error("AI twin is not ready");await k.renderViseme(I,l,{from:p?.from,transitionDurationMs:p?.transitionDurationMs,gapMs:p?.gapMs,onStatus:A=>S.current?.(A)})},isReady:()=>D.current,getStatus:()=>W}),[K,a,C,V,U,z,W]),Me.jsxs("div",{className:c,style:{...ur,...u},children:[Me.jsx("canvas",{ref:E,width:re.width,height:re.height,style:{...lr,...m},"aria-label":t?`AI twin ${t}`:"AI twin face"}),g&&Ee?Me.jsx("div",{style:fr,children:Ee}):null]})});exports.AiTwin=dr;exports.AiTwinNotFoundError=ve;exports.DEFAULT_TTS_ENGINE_ID=He;exports.OCULUS_VISEME_IDS=lt;exports.SPEAKING_RATE_MAX=mt;exports.SPEAKING_RATE_MIN=_t;exports.TTS_ENGINE_CARTESIA=ge;exports.TTS_ENGINE_GOOGLE=te;exports.TTS_ENGINE_INWORLD=we;exports.VISEME_IDS=yn;exports.VISEME_TEST_CARTESIA_VOICE_ID=wt;exports.VISEME_TEST_SPEAKING_RATE=Ke;exports.VISEME_TEST_VOICE_ID=We;exports.createAvatarTtsLipsyncController=gt;exports.fetchAiTwin=ct;exports.fetchDevAuthToken=Fe;exports.normalizeOculusViseme=ft;exports.resolveVisemeAtTime=dt;exports.resolveWordAtTime=ht;