@streamoji/aitwin 0.1.7 → 0.1.8

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/dist/aitwin.cjs CHANGED
@@ -1,3 +1,3 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const Pe=require("react/jsx-runtime"),p=require("react");var Le=typeof document<"u"?document.currentScript:null;const Ct="https://pub-607ad1fc22e2400eb57d17240aab857c.r2.dev",ht={publicBase:Ct},Mt="0.1.7",Ft={version:Mt},Ot={},ve="https://ai.streamoji.com",Pt=`${ht.publicBase}/custom-faces`,Lt=`${ht.publicBase}/aitwin-workers/v${Ft.version}/visemeDiffPreview.worker.js`;function Ut(e){if(e)return e;const t=typeof{url:typeof document>"u"?require("url").pathToFileURL(__filename).href:Le&&Le.tagName.toUpperCase()==="SCRIPT"&&Le.src||new URL("aitwin.cjs",document.baseURI).href}<"u"?Ot?.VITE_AITWIN_WORKER_URL:void 0;return t?.trim()?t.trim():Lt}const Nt="https://us-central1-streamoji-265f4.cloudfunctions.net/getAiTwin",Ge="eng_a7f2b9c1",be="eng_d4e8f3a2",ae="eng_c9b1e6d4",re=ae,Bt=new Set([be,ae]),_t={[Ge]:"oculus_direct",[ae]:"oculus_direct",[be]:"inworld_word"},Xe={google:Ge,inworld:be,cartesia:ae};function Vt(e){return _t[e]}function $t(e){return e===ae}function Ht(e){if(e.ttsEngineId&&e.ttsEngineId in _t)return e.ttsEngineId;const t=e.tts?.toLowerCase();return t&&t in Xe?Xe[t]:re}class Ae extends Error{constructor(t="AI twin not found"){super(t),this.name="AiTwinNotFoundError"}}async function mt(e,t=Nt){const n=new URL(t);n.searchParams.set("id",e);const r=await fetch(n.toString());if(r.status===404)throw new Ae;if(!r.ok)throw new Error(`getAiTwin failed (${r.status})`);const s=await r.json();if(!s.success)throw new Ae(s.error??"AI twin not found");const{tts:i,...c}=s.data;return{...c,ttsEngineId:Ht(s.data)}}const Wt="https://us-central1-streamoji-265f4.cloudfunctions.net/getAuthToken",qt="client_6TNvp3SCs4Og0a1ijm9TommXLql1",Kt="kk8Fq8EmexzP10jMIEwY3R44M5RKUEm1",Gt="6TNvp3SCs4Og0a1ijm9TommXLql1",jt="Swaraj Mali";async function Ne(){const e=await fetch(Wt,{method:"POST",headers:{"Content-Type":"application/json","Client-Id":qt,"Client-Secret":Kt},body:JSON.stringify({userId:Gt,userName:jt})});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 zt(e,t=ve){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 Qt(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 Jt(e,t){const n=new Uint8Array(e.length+t.length);return n.set(e,0),n.set(t,e.length),n}async function Yt(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)),i=Se(n.subarray(28)),c=Se(Jt(i,s)),a=await crypto.subtle.importKey("raw",Qt(t),{name:"AES-GCM"},!1,["decrypt"]);return crypto.subtle.decrypt({name:"AES-GCM",iv:r,tagLength:128},a,c)}let Be=null;const Ve=new Set;function Xt(e,t=Pt){const n=`${t.replace(/\/$/,"")}/${e}`;return{twinBase:n,binBase:n,encrypted:!0}}function Zt(e){Be=e;for(const t of Ve)t()}function en(e,t){const n=typeof globalThis.location<"u"?globalThis.location.href:void 0;if(!n)return e;const r=s=>{try{return new URL(s,n).href.replace(/\/$/,"")}catch{return s}};return{twinBase:r(e.twinBase),binBase:r(e.binBase),encrypted:e.encrypted}}function se(){if(!Be)throw new Error("Twin assets not configured; call setActiveTwinAssets first");return Be}function tn(e){return Ve.add(e),()=>Ve.delete(e)}function Ze(){const{binBase:e,twinBase:t,encrypted:n}=se();return n?`${e}/sil.bin`:`${t}/sil.png`}function nn(){const{binBase:e,twinBase:t,encrypted:n}=se();return n?`${e}/idle.bin`:`${t}/idle.mp4`}function rn(){const{encrypted:e,binBase:t,twinBase:n}=se();return e?t:n}function je(){return se().encrypted}function sn(){const{binBase:e,twinBase:t,encrypted:n}=se();return n?`${e}/atlas.bin`:`${t}/atlas.json`}function on(){const{binBase:e,twinBase:t,encrypted:n}=se();return n?`${e}/expression_atlas.bin`:`${t}/expression_atlas.json`}function an(e){const t=e.split(/\r?\n/);let n="",r="";for(const i of t)i.startsWith("event:")?n=i.slice(6).trim():i.startsWith("data:")&&(r=i.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 wt=["aa","CH","DD","E","FF","I","O","PP","RR","SS","TH","U","kk","nn","sil"],cn=new Map(wt.map(e=>[e.toLowerCase(),e]));function gt(e){const t=(e??"").trim();return t?cn.get(t.toLowerCase())??"sil":"sil"}const un={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 ln(e){if(!e)return["sil"];const t=e.toLowerCase();return un[t]??["sil"]}function fn(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 De(e,t){const n=Math.max(0,Math.min(e.length-1,t));return e[n]??""}function dn(e,t){const n=e.toLowerCase(),r=De(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 hn(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=De(n,t);return s==="u"||s==="w"?"U":"O"}function _n(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)||De(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 mn(e,t){const n=e.toLowerCase(),r=De(n,t);if(Te[r])return Te[r];for(let s=0;s<n.length;s++){const i=n[s];if(Te[i])return Te[i]}return"DD"}function wn(e,t,n){const r=ln(e);if(r.length===1)return r[0];const s=t.trim();if(!s)return r[0];const i=(e??"").toLowerCase(),c=Math.max(0,n);switch(i){case"aei":return dn(s,c);case"o":return hn(s,c);case"qw":return _n(s,c);case"cdgknstxyz":return mn(s,c);default:return r[0]}}function gn(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 yn=24e3;function pn(e){return e.length>=4&&e[0]===82&&e[1]===73&&e[2]===70&&e[3]===70}function et(e,t,n=yn){const r=t.byteOffset%2===0?t:t.slice(),s=new Int16Array(r.buffer,r.byteOffset,r.byteLength/2),i=new Float32Array(s.length);for(let a=0;a<s.length;a++)i[a]=s[a]>=32768?-(65536-s[a])/32768:s[a]/32767;const c=e.createBuffer(1,i.length,n);return c.copyToChannel(i,0),c}function En(e){const t=gn(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 Sn(e,t){const n=En(t);if(pn(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 et(e,n);try{const r=n.buffer.slice(n.byteOffset,n.byteOffset+n.byteLength);return await e.decodeAudioData(r)}catch{return et(e,n)}}function yt(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 pt(e,t){for(const n of e)if(t>=n.wtime&&t<n.wtime+n.wduration)return n;return null}function tt(e){let t=0;for(const n of e)t=Math.max(t,n.vtime+n.vduration);return t}const Et=.5,St=1.5,ze="Olivia",Tt="f786b574-daa5-4673-aa0c-cbe3e8534c02",Qe=.85;function kt(e,t=ve){const n=`${t.replace(/\/$/,"")}/avatar_ttsWithPoses`,r=[],s=[],i=[];let c="neutral";const a=[],l=[];let d=null,m=!1,_=!1,k=!1,o=!1,x=0,w=0,u=0,g=0,E=null,R=1,$="",y=re,S=re,C=!1;const D=new Set,W=()=>{for(const h of l)h.playbackRate.value=R},q=()=>D.forEach(h=>h()),ce=()=>{E!=null&&(clearTimeout(E),E=null)},ge=()=>{for(const h of l)try{h.stop()}catch{}l.length=0},Z=()=>{C=!0,ce(),ge(),a.length=0,m=!1,_=!1,k=!1,o=!1,r.length=0,s.length=0,i.length=0,c="neutral",u=0,g=0,w=0,e("idle"),q()},K=()=>{!o||m||l.length>0||a.length>0||(_=!1,ce(),e("done"),q())},ye=()=>{const h=tt(r);if(h<=0){e("done"),q();return}_=!0,x=performance.now(),e("speaking"),q(),ce();const M=R>0?h/R:h;E=setTimeout(()=>{C||(_=!1,E=null,e("done"),q())},M)},Me=(h,M,B)=>{h.length!==0&&(B&&(u=M),h.forEach(P=>{const U=String(P.word??"").trim();if(!U)return;const Q=Math.round((P.start??0)*1e3),V=Math.round((P.duration??0)*1e3);s.push({word:U,wtime:u+Q,wduration:V,queueIndex:s.length})}))},ue=(h,M,B,P)=>{h.length!==0&&(B&&(u=M),h.forEach(I=>{const U=String(I.symbol??"").trim();if(!U)return;const Q=Math.round((I.start??0)*1e3),V=Math.max(1,Math.round((I.duration??0)*1e3)),L=u+Q;let F;if(Vt(P)==="oculus_direct")F=gt(U);else{const O=pt(s,L),J=O?fn(O,L):0;F=wn(U,O?.word??"",J)}r.push({viseme:F,weight:1,vtime:L,vduration:V})}),q())},ie=(h,M,B,P,I)=>{Me(M,B,P),ue(h,B,P,I)},pe=async(h,M,B,P)=>{if(C||!h?.trim()){(M.length>0||B.length>0)&&!k&&ie(M,B,u,P,S);return}if(m){a.push({audio:h,visemes:M,words:B,isNewSegment:P});return}m=!0;try{const I=window.AudioContext||window.webkitAudioContext,U=d??new I;U.state==="suspended"&&await U.resume(),d=U;const Q=await Sn(U,h);k=!0;const V=U.currentTime;let L=g;const F=!_;L<V&&(L=V+.1),g=L+Q.duration;const O=U.createBufferSource();if(O.buffer=Q,O.playbackRate.value=R,O.connect(U.destination),l.push(O),C){l.pop();return}if(F){_=!0,e("speaking"),w=L,u=0,r.length=0,s.length=0;const H=(L-V)*1e3;x=performance.now()+H}O.onended=()=>{const H=l.indexOf(O);H>=0&&l.splice(H,1),K(),q()},O.start(L);const J=(L-w)*1e3;ie(M,B,J,P,S)}catch(I){console.error("[avatarTtsLipsync] audio chunk failed:",I)}finally{m=!1;const I=a.shift();I?await pe(I.audio,I.visemes,I.words,I.isNewSegment):K()}},ee=()=>{if(o=!0,!k&&r.length>0){ye();return}K()};return{setDeveloperToken:h=>{$=h},setTtsEngineId:h=>{y=h},getTtsEngineId:()=>y,speak:async(h,M)=>{Z(),C=!1,e("loading");const B=$.trim();if(!B)throw new Error("Developer token required for avatar_ttsWithPoses");const P=M?.ttsEngineId??y??re;S=P;const I=M?.voiceId??ze,U=M?.speakingRate??Qe,Q=Math.max(Et,Math.min(St,U)),V={user_query:h,ttsEngineId:P,speakingRate:Q};Bt.has(P)&&(V.voice_id=I);try{const L=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${B}`},body:JSON.stringify(V)});if(!L.ok)throw new Error(`avatar_ttsWithPoses failed (${L.status})`);const F=L.body;if(!F)throw new Error("No response body");const O=F.getReader(),J=new TextDecoder;let H="";const fe=async de=>{const f=an(de);if(f){if(f.event==="audio"){const T=f.data.chunk,v=f.data.visemes??[],A=f.data.words??[],b=f.data.is_new_segment??!1;if(T)await pe(T,v,A,b);else if(v.length>0||A.length>0){const G=b&&r.length>0?tt(r):u;ie(v,A,G,b,P)}}else if(f.event==="metadata"){const T=f.data.mood;typeof T=="string"&&T.trim()&&(c=T.trim());const v=f.data.sentence_emotions;if(Array.isArray(v)){i.length=0;for(const A of v){if(!A||typeof A!="object")continue;const b=A;i.push({sentence_index:Number(b.sentence_index??0),text:String(b.text??""),sentiment:typeof b.sentiment=="string"?b.sentiment:void 0,emotion:String(b.emotion??c),start_word:Number(b.start_word??0),end_word:Number(b.end_word??0)})}}q()}else if(f.event==="error")throw new Error(String(f.data.message??"avatar_ttsWithPoses stream error"))}};for(;;){const{done:de,value:f}=await O.read();f&&(H+=J.decode(f,{stream:!0}));const T=H.split(`
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const We=require("react/jsx-runtime"),h=require("react");var qe=typeof document<"u"?document.currentScript:null;const qt="https://pub-607ad1fc22e2400eb57d17240aab857c.r2.dev",kt={publicBase:qt},Kt="0.1.8",Gt={version:Kt},jt={},Oe="https://ai.streamoji.com",zt=`${kt.publicBase}/custom-faces`,Qt=`${kt.publicBase}/aitwin-workers/v${Gt.version}/visemeDiffPreview.worker.js`;function Jt(e){if(e)return e;const t=typeof{url:typeof document>"u"?require("url").pathToFileURL(__filename).href:qe&&qe.tagName.toUpperCase()==="SCRIPT"&&qe.src||new URL("aitwin.cjs",document.baseURI).href}<"u"?jt?.VITE_AITWIN_WORKER_URL:void 0;return t?.trim()?t.trim():Qt}const Yt="https://us-central1-streamoji-265f4.cloudfunctions.net/getAiTwin",et="eng_a7f2b9c1",Pe="eng_d4e8f3a2",pe="eng_c9b1e6d4",de=pe,Xt=new Set([Pe,pe]),It={[et]:"oculus_direct",[pe]:"oculus_direct",[Pe]:"inworld_word"},ct={google:et,inworld:Pe,cartesia:pe};function Zt(e){return It[e]}function en(e){return e===pe}function tn(e){if(e.ttsEngineId&&e.ttsEngineId in It)return e.ttsEngineId;const t=e.tts?.toLowerCase();return t&&t in ct?ct[t]:de}class Le extends Error{constructor(t="AI twin not found"){super(t),this.name="AiTwinNotFoundError"}}async function Rt(e,t=Yt){const n=new URL(t);n.searchParams.set("id",e);const r=await fetch(n.toString());if(r.status===404)throw new Le;if(!r.ok)throw new Error(`getAiTwin failed (${r.status})`);const s=await r.json();if(!s.success)throw new Le(s.error??"AI twin not found");const{tts:i,...c}=s.data;return{...c,ttsEngineId:tn(s.data)}}const nn="https://us-central1-streamoji-265f4.cloudfunctions.net/getAuthToken",rn="client_6TNvp3SCs4Og0a1ijm9TommXLql1",sn="kk8Fq8EmexzP10jMIEwY3R44M5RKUEm1",on="6TNvp3SCs4Og0a1ijm9TommXLql1",an="Swaraj Mali";async function Ge(){const e=await fetch(nn,{method:"POST",headers:{"Content-Type":"application/json","Client-Id":rn,"Client-Secret":sn},body:JSON.stringify({userId:on,userName:an})});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 cn(e,t=Oe){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 un(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 De(e){return Uint8Array.from(e)}function ln(e,t){const n=new Uint8Array(e.length+t.length);return n.set(e,0),n.set(t,e.length),n}async function fn(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=De(n.subarray(0,12)),s=De(n.subarray(12,28)),i=De(n.subarray(28)),c=De(ln(i,s)),a=await crypto.subtle.importKey("raw",un(t),{name:"AES-GCM"},!1,["decrypt"]);return crypto.subtle.decrypt({name:"AES-GCM",iv:r,tagLength:128},a,c)}let je=null;const ze=new Set;function dn(e,t=zt){const n=`${t.replace(/\/$/,"")}/${e}`;return{twinBase:n,binBase:n,encrypted:!0}}function hn(e){je=e;for(const t of ze)t()}function _n(e,t){const n=typeof globalThis.location<"u"?globalThis.location.href:void 0;if(!n)return e;const r=s=>{try{return new URL(s,n).href.replace(/\/$/,"")}catch{return s}};return{twinBase:r(e.twinBase),binBase:r(e.binBase),encrypted:e.encrypted}}function he(){if(!je)throw new Error("Twin assets not configured; call setActiveTwinAssets first");return je}function mn(e){return ze.add(e),()=>ze.delete(e)}function ut(){const{encrypted:e,binBase:t,twinBase:n}=he();return e?`${t}/sil.bin`:`${n}/sil.png`}function wn(){const{encrypted:e,binBase:t,twinBase:n}=he();return e?`${t}/idle.bin`:`${n}/idle.mp4`}function gn(){const{encrypted:e,binBase:t,twinBase:n}=he();return e?t:n}function Ue(){return he().encrypted}function yn(){const{binBase:e,twinBase:t,encrypted:n}=he();return n?`${e}/atlas.bin`:`${t}/atlas.json`}function pn(){const{binBase:e,twinBase:t,encrypted:n}=he();return n?`${e}/expression_atlas.bin`:`${t}/expression_atlas.json`}function En(e){const t=e.split(/\r?\n/);let n="",r="";for(const i of t)i.startsWith("event:")?n=i.slice(6).trim():i.startsWith("data:")&&(r=i.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 vt=["aa","CH","DD","E","FF","I","O","PP","RR","SS","TH","U","kk","nn","sil"],Sn=new Map(vt.map(e=>[e.toLowerCase(),e]));function At(e){const t=(e??"").trim();return t?Sn.get(t.toLowerCase())??"sil":"sil"}const Tn={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 kn(e){if(!e)return["sil"];const t=e.toLowerCase();return Tn[t]??["sil"]}function In(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 Ne(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=Ne(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 vn(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=Ne(n,t);return s==="u"||s==="w"?"U":"O"}function An(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)||Ne(n,t)==="o"?"O":"U"}const Ce={d:"DD",t:"DD",n:"DD",s:"SS",z:"SS",k:"kk",g:"kk",c:"CH",x:"CH",j:"CH"};function bn(e,t){const n=e.toLowerCase(),r=Ne(n,t);if(Ce[r])return Ce[r];for(let s=0;s<n.length;s++){const i=n[s];if(Ce[i])return Ce[i]}return"DD"}function Dn(e,t,n){const r=kn(e);if(r.length===1)return r[0];const s=t.trim();if(!s)return r[0];const i=(e??"").toLowerCase(),c=Math.max(0,n);switch(i){case"aei":return Rn(s,c);case"o":return vn(s,c);case"qw":return An(s,c);case"cdgknstxyz":return bn(s,c);default:return r[0]}}function Cn(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 xn=24e3;function Mn(e){return e.length>=4&&e[0]===82&&e[1]===73&&e[2]===70&&e[3]===70}function lt(e,t,n=xn){const r=t.byteOffset%2===0?t:t.slice(),s=new Int16Array(r.buffer,r.byteOffset,r.byteLength/2),i=new Float32Array(s.length);for(let a=0;a<s.length;a++)i[a]=s[a]>=32768?-(65536-s[a])/32768:s[a]/32767;const c=e.createBuffer(1,i.length,n);return c.copyToChannel(i,0),c}function On(e){const t=Cn(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 Ln(e,t){const n=On(t);if(Mn(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 lt(e,n);try{const r=n.buffer.slice(n.byteOffset,n.byteOffset+n.byteLength);return await e.decodeAudioData(r)}catch{return lt(e,n)}}function tt(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 bt(e,t){for(const n of e)if(t>=n.wtime&&t<n.wtime+n.wduration)return n;return null}function ft(e){let t=0;for(const n of e)t=Math.max(t,n.vtime+n.vduration);return t}const Dt=.5,Ct=1.5,nt="Olivia",xt="f786b574-daa5-4673-aa0c-cbe3e8534c02",rt=.85;function Mt(e,t=Oe){const n=`${t.replace(/\/$/,"")}/avatar_ttsWithPoses`,r=[],s=[],i=[];let c="neutral";const a=[],l=[];let d=null,w=!1,m=!1,T=!1,o=!1,O=0,g=0,u=0,y=0,p=null,R=1,H="",_=de,S=de,D=!1;const L=new Set,z=()=>{for(const E of l)E.playbackRate.value=R},U=()=>L.forEach(E=>E()),oe=()=>{p!=null&&(clearTimeout(p),p=null)},_e=()=>{for(const E of l)try{E.stop()}catch{}l.length=0},B=()=>{D=!0,oe(),_e(),a.length=0,w=!1,m=!1,T=!1,o=!1,r.length=0,s.length=0,i.length=0,c="neutral",u=0,y=0,g=0,e("idle"),U()},X=()=>{!o||w||l.length>0||a.length>0||(m=!1,oe(),e("done"),U())},Re=()=>{const E=ft(r);if(E<=0){e("done"),U();return}m=!0,O=performance.now(),e("speaking"),U(),oe();const V=R>0?E/R:E;p=setTimeout(()=>{D||(m=!1,p=null,e("done"),U())},V)},$e=(E,V,W)=>{E.length!==0&&(W&&(u=V),E.forEach(C=>{const v=String(C.word??"").trim();if(!v)return;const Q=Math.round((C.start??0)*1e3),J=Math.round((C.duration??0)*1e3);s.push({word:v,wtime:u+Q,wduration:J,queueIndex:s.length})}))},ve=(E,V,W,C)=>{E.length!==0&&(W&&(u=V),E.forEach(x=>{const v=String(x.symbol??"").trim();if(!v)return;const Q=Math.round((x.start??0)*1e3),J=Math.max(1,Math.round((x.duration??0)*1e3)),P=u+Q;let F;if(Zt(C)==="oculus_direct")F=At(v);else{const q=bt(s,P),ae=q?In(q,P):0;F=Dn(v,q?.word??"",ae)}r.push({viseme:F,weight:1,vtime:P,vduration:J})}),U())},ce=(E,V,W,C,x)=>{$e(V,W,C),ve(E,W,C,x)},se=async(E,V,W,C)=>{if(D||!E?.trim()){(V.length>0||W.length>0)&&!T&&ce(V,W,u,C,S);return}if(w){a.push({audio:E,visemes:V,words:W,isNewSegment:C});return}w=!0;try{const x=window.AudioContext||window.webkitAudioContext,v=d??new x;v.state==="suspended"&&await v.resume(),d=v;const Q=await Ln(v,E);T=!0;const J=v.currentTime;let P=y;const F=!m;P<J&&(P=J+.1),y=P+Q.duration;const q=v.createBufferSource();if(q.buffer=Q,q.playbackRate.value=R,q.connect(v.destination),l.push(q),D){l.pop();return}if(F){m=!0,e("speaking"),g=P,u=0,r.length=0,s.length=0;const $=(P-J)*1e3;O=performance.now()+$}q.onended=()=>{const $=l.indexOf(q);$>=0&&l.splice($,1),X(),U()},q.start(P);const ae=(P-g)*1e3;ce(V,W,ae,C,S)}catch(x){console.error("[avatarTtsLipsync] audio chunk failed:",x)}finally{w=!1;const x=a.shift();x?await se(x.audio,x.visemes,x.words,x.isNewSegment):X()}},Ae=()=>{if(o=!0,!T&&r.length>0){Re();return}X()};return{setDeveloperToken:E=>{H=E},setTtsEngineId:E=>{_=E},getTtsEngineId:()=>_,speak:async(E,V)=>{B(),D=!1,e("loading");const W=H.trim();if(!W)throw new Error("Developer token required for avatar_ttsWithPoses");const C=V?.ttsEngineId??_??de;S=C;const x=V?.voiceId??nt,v=V?.speakingRate??rt,Q=Math.max(Dt,Math.min(Ct,v)),J={user_query:E,ttsEngineId:C,speakingRate:Q};Xt.has(C)&&(J.voice_id=x);try{const P=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${W}`},body:JSON.stringify(J)});if(!P.ok)throw new Error(`avatar_ttsWithPoses failed (${P.status})`);const F=P.body;if(!F)throw new Error("No response body");const q=F.getReader(),ae=new TextDecoder;let $="";const be=async N=>{const b=En(N);if(b){if(b.event==="audio"){const K=b.data.chunk,te=b.data.visemes??[],Z=b.data.words??[],G=b.data.is_new_segment??!1;if(K)await se(K,te,Z,G);else if(te.length>0||Z.length>0){const me=G&&r.length>0?ft(r):u;ce(te,Z,me,G,C)}}else if(b.event==="metadata"){const K=b.data.mood;typeof K=="string"&&K.trim()&&(c=K.trim());const te=b.data.sentence_emotions;if(Array.isArray(te)){i.length=0;for(const Z of te){if(!Z||typeof Z!="object")continue;const G=Z;i.push({sentence_index:Number(G.sentence_index??0),text:String(G.text??""),sentiment:typeof G.sentiment=="string"?G.sentiment:void 0,emotion:String(G.emotion??c),start_word:Number(G.start_word??0),end_word:Number(G.end_word??0)})}}U()}else if(b.event==="error")throw new Error(String(b.data.message??"avatar_ttsWithPoses stream error"))}};for(;;){const{done:N,value:b}=await q.read();b&&($+=ae.decode(b,{stream:!0}));const K=$.split(`
2
2
 
3
- `);H=T.pop()??"";for(const v of T)await fe(v);if(de){H.trim()&&await fe(H.trim()),C||ee();break}}}catch(L){throw console.error("[avatarTtsLipsync]",L),Z(),e("error"),L}},stop:Z,getVisemeQueue:()=>r,getWordQueue:()=>s,getSentenceEmotions:()=>i,getStreamMood:()=>c,getPlaybackElapsedMs:()=>_?k&&d&&w>0?Math.max(0,(d.currentTime-w)*1e3):Math.max(0,(performance.now()-x)*R):0,isSpeaking:()=>_,setPlaybackSpeed:h=>{R=Math.max(.1,Math.min(1,h)),W()},getPlaybackSpeed:()=>R,subscribe:h=>(D.add(h),()=>D.delete(h))}}function Tn(e,t,n){return{width:e.crop?.source_width??t,height:e.crop?.source_height??n}}function kn(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 In(e){return e?(e.w??0)>0&&(e.h??0)>0:!1}async function xe(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 Yt(r,t)}async function vn(e,t){if(!t)throw new Error("Missing asset key for encrypted JSON");const n=await xe(e,t),r=new TextDecoder().decode(n);return JSON.parse(r)}async function An(e){const t=new Blob([e],{type:"image/webp"}),n=URL.createObjectURL(t);return new Promise((r,s)=>{const i=new Image;i.decoding="async",i.onload=()=>{URL.revokeObjectURL(n),r(i)},i.onerror=()=>{URL.revokeObjectURL(n),s(new Error("Failed to decode decrypted image"))},i.src=n})}async function Rn(e){const t=new Blob([e],{type:"image/png"}),n=URL.createObjectURL(t);return new Promise((r,s)=>{const i=new Image;i.decoding="async",i.onload=()=>{URL.revokeObjectURL(n),r(i)},i.onerror=()=>{URL.revokeObjectURL(n),s(new Error("Failed to decode decrypted PNG"))},i.src=n})}async function bn(e){const t=nn();if(!je())return t;if(!e)throw new Error("Missing asset key for encrypted idle video");const n=await xe(t,e);return URL.createObjectURL(new Blob([n],{type:"video/mp4"}))}function It(e,t){return`${e}/${t}_minus_sil.png`}const Je=15,Dn=["aa","E","I","O","U","PP","FF","DD","SS","TH","CH","RR","kk","nn"],$e=["t01_0.17","t02_0.33","t03_0.50","t04_0.67","t05_0.83"],xn=$e.length,nt=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 rt(e,t){return`${e}__${t}`}function st(e,t){return`pairs/${e}/${t}_minus_sil.png`}function He(e){return`${e}_minus_sil.png`}function Cn(e,t){if(e===t)return[];const n=[],r=rt(e,t);if(nt.has(r)){for(const i of $e)n.push(st(r,i));return n}const s=rt(t,e);if(nt.has(s)){for(let i=xn-1;i>=0;i--)n.push(st(s,$e[i]));return n}return[]}function Mn(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 Fn(e,t){return Mn(t).map(r=>e[r]).filter(r=>r!=null)}function On(e,t,n,r){if(r<=0)return 0;const i=Math.max(1,n-t)/r,c=e-t,a=Math.floor(c/i);return Math.min(r-1,Math.max(0,a))}function Pn(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 Ln=[.32,.24,.16,.08,0],Ce=Ln.map(e=>`eyes_${e.toFixed(2)}`),Un=["eyes_0.32","eyes_0.16","eyes_0.00"],Nn=["eyes_0.32","eyes_0.16","eyes_0.08","eyes_0.00"],Bn={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 oe(e,t="neutral"){const n=String(e??"").trim().toLowerCase();return n?Bn[n]??t:t}function z(e){return e==="neutral"?null:It(e,"eyes_standard")}function We(e,t){return!t||t==="eyes_standard"?z(e):e==="neutral"&&t==="eyes_standard"?null:It(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 $n(e){return e==="open"?-1:Ce.indexOf(e)}function Hn(e,t){const n=[];for(const r of t)n.push(We(e,r));for(let r=t.length-2;r>=0;r--)n.push(We(e,t[r]));return n.push(z(e)),n}function Wn(e,t){if(t==="open")return[z(e)];const n=$n(t);if(n<0)return[z(e)];const r=[];for(let s=n;s>=0;s--)r.push(We(e,Ce[s]));return r.push(z(e)),r}const qn=["t01_0.20","t02_0.40","t03_0.60","t04_0.80"];function Kn(e,t){return`${e}__${t}`}function Gn(e,t,n){return`pairs/${Kn(e,t)}/${n}_minus_sil.png`}function jn(e,t){return qn.map(n=>Gn(e,t,n))}function _e(e,t){return e+Math.random()*(t-e)}function ke(){return _e(14,32)}function zn(e={}){const{initialDelayMs:t=800+Math.random()*1200,intervalMinMs:n=2200,intervalMaxMs:r=5800,doubleBlinkChance:s=.18,doubleBlinkGapMinMs:i=120,doubleBlinkGapMaxMs:c=220,fullBlinkChance:a=.75,postEmotionChangeDelayMs:l=380,minDwellMs:d=550}=e;let m="neutral",_="neutral",k=0,o={kind:"idle",nextBlinkAt:performance.now()+t},x=null,w="__eyes_open__|neutral";function u(y,S){x=y,w=`${y??"__eyes_open__"}|${S}`}function g(y,S){o={kind:"idle",nextBlinkAt:y+_e(n,r)},_=S,u(z(S),S)}function E(y,S,C){const D=C?Un:Math.random()<a?Ce:Nn;o={kind:"playing",paths:Hn(S,D),index:0,holdUntil:y+ke(),after:"idle",blinkEmotion:S},_=S,u(o.paths[0]??null,S)}function R(y,S,C){const D=Vn(x),W=[];if(D!=="open"){const q=Wn(S,D);W.push(...q.slice(0,-1))}W.push(...jn(S,C)),W.push(z(C)),o={kind:"emotionBlend",paths:W,index:0,holdUntil:y+ke(),thenEmotion:C},u(W[0]??null,S)}function $(y){if(o.kind==="emotionBlend"){for(;y>=o.holdUntil&&o.index<o.paths.length-1;)o.index+=1,o.holdUntil=y+ke();const S=o.paths[o.index]??null;u(S,o.thenEmotion),y>=o.holdUntil&&o.index>=o.paths.length-1&&(m=o.thenEmotion,_=o.thenEmotion,u(z(o.thenEmotion),o.thenEmotion),o={kind:"idle",nextBlinkAt:y+l});return}if(o.kind==="idle"){u(z(_),_),y>=o.nextBlinkAt&&E(y,_,!1);return}if(o.kind==="doublePause"){u(z(o.blinkEmotion),o.blinkEmotion),y>=o.resumeAt&&E(y,o.blinkEmotion,!0);return}if(o.kind==="playing"){for(;y>=o.holdUntil&&o.index<o.paths.length-1;)o.index+=1,o.holdUntil=y+ke();if(u(o.paths[o.index]??null,o.blinkEmotion),y>=o.holdUntil&&o.index>=o.paths.length-1){if(o.after==="resumeIdle"){g(y+l,m);return}if(o.after==="doublePause"){o={kind:"doublePause",resumeAt:y+_e(i,c),blinkEmotion:o.blinkEmotion},u(z(o.blinkEmotion),o.blinkEmotion);return}if(o.after==="idle"&&Math.random()<s){o={kind:"doublePause",resumeAt:y+_e(i,c),blinkEmotion:o.blinkEmotion},u(z(o.blinkEmotion),o.blinkEmotion);return}g(y,o.blinkEmotion)}}}return{advance:$,setTargetEmotion(y){const S=oe(y,m);if(S===m&&o.kind!=="emotionBlend")return;const C=performance.now();if(d>0&&S!==m&&o.kind!=="emotionBlend"&&!(m==="neutral"&&S!=="neutral")&&C-k<d)return;const D=m;if(m=S,k=C,o.kind==="playing"){R(C,_,S);return}if(o.kind==="emotionBlend"){o={...o,thenEmotion:S};return}R(C,D,S)},getTargetEmotion:()=>m,getExpressionPath:()=>x,getDrawKey:()=>w,reset(){m="neutral",_="neutral",k=0,g(performance.now()+_e(n,r),"neutral")}}}function Qn(){const e=document.createElement("video");e.muted=!0,e.playsInline=!0,e.preload="auto",e.setAttribute("playsinline",""),e.loop=!0;let t=!1,n=null,r="";const s=()=>{n&&(URL.revokeObjectURL(n),n=null)};return{async load(i){t&&r===i||(s(),t=!1,r=i,i.startsWith("blob:")&&(n=i),await new Promise((c,a)=>{const l=()=>{const d=e.duration;if(!Number.isFinite(d)||d<=0){a(new Error(`Idle video has invalid duration: ${i}`));return}t=!0,e.currentTime=0,c()};e.addEventListener("loadeddata",l,{once:!0}),e.addEventListener("error",()=>a(new Error(`Failed to load idle video: ${i}`)),{once:!0}),e.src=i,e.load()}))},isReady(){return t},getVideo(){return e},setActive(i){t&&(i?e.paused&&e.play().catch(()=>{}):e.paused||e.pause())},restart(){t&&(e.currentTime=0)},dispose(){e.pause(),e.removeAttribute("src"),e.load(),s(),t=!1,r=""}}}const Jn=50,vt=400;function Yn(e,t,n){return e.filter(r=>{const s=r.queueIndex??-1;return s>=t&&s<=n})}function Xn(e,t){const n=[];for(const r of e){const s=Yn(t,r.start_word,r.end_word);if(s.length===0)continue;const i=s[0],c=s[s.length-1];n.push({sentence:r,startMs:Math.max(0,i.wtime-Jn),endMs:c.wtime+c.wduration+vt})}return n.sort((r,s)=>r.startMs-s.startMs)}function Zn(e,t,n,r="neutral"){const s=oe(r);if(t.length===0)return s;if(n.length===0||e<n[0].wtime)return oe(t[0]?.emotion,s);const i=Xn(t,n);let c=null;for(const d of i)e>=d.startMs&&e<=d.endMs&&(c=d);if(c)return oe(c.sentence.emotion,s);const a=n[n.length-1],l=a.wtime+a.wduration;return e>l+vt?oe(t[t.length-1]?.emotion,s):s}function At(e,t,n,r,s=Je){const i=new OffscreenCanvas(n,r),c=i.getContext("2d",{willReadFrequently:!0});c.drawImage(e,0,0,n,r);const a=c.getImageData(0,0,n,r),l=c.createImageData(n,r);l.data.set(a.data);const m=new OffscreenCanvas(n,r).getContext("2d",{willReadFrequently:!0});for(const _ of t){m.clearRect(0,0,n,r),m.drawImage(_,0,0,n,r);const k=m.getImageData(0,0,n,r);for(let o=0;o<l.data.length;o+=4){const x=k.data[o],w=k.data[o+1],u=k.data[o+2];Math.max(x,w,u)>s&&(l.data[o]=x,l.data[o+1]=w,l.data[o+2]=u,l.data[o+3]=255)}}return c.putImageData(l,0,0),i}let ne=null,me=null;const Re=new Map;function er(){ne=null,me=null,Re.clear()}tn(er);function tr(e){return e??me??void 0}function Ye(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 it(e,t,n,r){const s=n?await vn(e,r):await fetch(e).then(d=>{if(!d.ok)throw new Error(`Failed to load ${e}`);return d.json()}),i=s.sheets?.[0];if(!i?.path)throw new Error(`${e} has no sheets[0].path`);const c=n?await An(await xe(Pn(t,i.path,n),r??"")):await Ye(`${t}/${i.path}`),a=new Map;for(const d of s.cells??[])d.path&&a.set(d.path,d);const l=new Map;for(const d of s.sheets??[])l.set(d.index,d);return{atlas:c,atlasMeta:s,cellByPath:a,sheetByIndex:l,diffBase:t}}async function qe(e){const t=tr(e),n=je();if(n&&!t)throw new Error("Encrypted assets enabled but no key provided");if(ne&&(!n||me===(t??null))){const i=await ne;return we(i)}me=t??null,Re.clear();const r=rn();ne=(async()=>{const i=n?await Rn(await xe(Ze(),t??"")):await Ye(Ze()),c=await it(sn(),r,n,t);let a=null;try{a=await it(on(),r,n,t)}catch{a=null}return{sil:i,viseme:c,expression:a}})();const s=await ne;return we(s)}async function Rt(e){if(await qe(e),!ne)throw new Error("Assets not loaded");return ne}function we(e){return Tn(e.viseme.atlasMeta,e.sil.naturalWidth,e.sil.naturalHeight)}function nr(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 ot(e,t,n){const r=`${t.diffBase}::${n}`,s=Re.get(r);if(s)return s;const i=(async()=>{const c=t.cellByPath.get(n);if(!c)throw new Error(`No atlas cell for path: ${n}`);const a=kn(t.atlasMeta,c),l=we(e);if(In(c)){const _=nr(t,c),k=document.createElement("canvas");k.width=l.width,k.height=l.height;const o=k.getContext("2d");return o.fillStyle="#000",o.fillRect(0,0,l.width,l.height),o.drawImage(_,a.x,a.y),k}const d=`${t.diffBase}/${n}`,m=await Ye(d);if(m.naturalWidth===l.width&&m.naturalHeight===l.height)return m;throw new Error(`Diff PNG wrong size for ${n}`)})();return Re.set(r,i),i}async function at(e,t,n,r=Je,s,i){if(s){const{width:k,height:o}=s;if(i&&!i()||t.readyState<HTMLMediaElement.HAVE_CURRENT_DATA)return;const x=document.createElement("canvas");x.width=k,x.height=o;const w=x.getContext("2d");if(w.clearRect(0,0,k,o),w.drawImage(t,0,0,k,o),i&&!i())return;(e.width!==k||e.height!==o)&&(e.width=k,e.height=o);const u=e.getContext("2d");u.clearRect(0,0,k,o),u.drawImage(x,0,0);return}const c=await Rt(),{width:a,height:l}=we(c);(e.width!==a||e.height!==l)&&(e.width=a,e.height=l);const d=[],m=e.getContext("2d");if(m.clearRect(0,0,a,l),t.readyState<HTMLMediaElement.HAVE_CURRENT_DATA){const k=c.sil;m.drawImage(k,0,0,a,l);return}if(d.length===0){m.drawImage(t,0,0,a,l);return}const _=At(t,d,a,l,r);m.drawImage(_,0,0)}async function Ke(e,t,n=Je){const r=await Rt(me??void 0),{width:s,height:i}=we(r);(e.width!==s||e.height!==i)&&(e.width=s,e.height=i);const c=[];t.mouthPath&&c.push(await ot(r,r.viseme,t.mouthPath)),t.expressionPath&&r.expression&&c.push(await ot(r,r.expression,t.expressionPath));const a=e.getContext("2d");if(a.clearRect(0,0,s,i),c.length===0){a.drawImage(r.sil,0,0,s,i);return}const l=At(r.sil,c,s,i,n);a.drawImage(l,0,0)}async function rr(e){await Ke(e,{mouthPath:null,expressionPath:null})}function sr(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 ir(e){const t=sr(e),n=[];for(let r=0;r<t.length-1;r++){const s=t[r].viseme,i=t[r+1].viseme,c=t[r].vtime,a=t[r+1].vtime;s===i||a<=c||n.push({from:s,to:i,fromVtime:c,toVtime:a})}return n}function or(e,t){let n=null;for(const r of e)t>=r.fromVtime&&t<r.toVtime&&(n=r);return n}function ar(e,t){return{gapMs:Math.max(0,t-e),holdEnd:e,transStart:e}}const cr=500,ur="__sil__";function lr(){return{lastDrawnKey:""}}function he(e){e.lastDrawnKey=""}function ct(e){return e??ur}function fr(e,t){if(e.length===0)return{diffPath:null,label:"sil"};const n=ir(e),r=or(n,t);if(r){const i=r.toVtime-r.fromVtime,c=ar(r.fromVtime,r.toVtime);if(t>=c.transStart&&t<r.toVtime){const a=Cn(r.from,r.to),l=Fn(a,i);if(l.length>0){const d=On(t,c.transStart,r.toVtime,l.length);return{diffPath:l[d]??l[l.length-1],label:`${r.from}→${r.to}`}}return{diffPath:He(r.to),label:r.to}}}const s=yt(e,t);return s==="sil"?{diffPath:null,label:"sil"}:{diffPath:He(s),label:s}}function bt(e,t){const n=t??ct(e.expressionPath);return`${ct(e.mouthPath)}|${n}`}function dr(e,t,n,r,s,i,c,a){const l=fr(t,n),d={mouthPath:l.diffPath,expressionPath:r},m=bt(d,s);m!==i.lastDrawnKey&&(a(l.label),c(e,d,m,_=>{_===m&&(i.lastDrawnKey=m)}))}function ut(e,t,n,r,s,i,c=null){const a={mouthPath:null,expressionPath:t},l=c!=null?`|idle@${Math.round(c*1e3)}`:"",d=bt(a,n)+l;!(c!=null)&&d===r.lastDrawnKey||(i(c!=null?"idle":"sil"),s(e,a,d,_=>{_===d&&(r.lastDrawnKey=d)}))}function Dt(e){let t=0,n=null,r=!1,s=!1;const i=async()=>{if(!r){r=!0;try{for(;n;){const a=n;n=null;const l=++t,d=await e(a.diffs,l,a);n||d&&l===t&&a.onDisplayed?.(a.drawKey)}}finally{r=!1,n&&i()}}},c=()=>{s||(s=!0,queueMicrotask(()=>{s=!1,i()}))};return{enqueue(a,l,d){n={diffs:a,drawKey:l,onDisplayed:d},c()},reset(){t+=1,n=null},isLatestSeq(a){return a===t},getLatestSeq(){return t}}}const lt=-1,ft=new Map;async function hr(e){let t=ft.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),ft.set(e,t)}return new Worker(t,{name:"visemeDiffPreview"})}function _r(){return typeof Worker<"u"&&typeof OffscreenCanvas<"u"}function mr(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 dt(e,t){let n=0;const r=Dt(async(s,i)=>(await qe(),await Ke(e,s),r.isLatestSeq(i)));return{usesWorker:!1,async loadAssets(s){return await qe(s)},async renderSilOnly(){n+=1,r.reset(),await rr(e)},drawLiveFrame(s,i,c,a){r.enqueue(i,c,a)},async renderViseme(s,i){n+=1;const c=n;t.onStatus?.(i),await Ke(s,{mouthPath:He(i),expressionPath:null})},dispose(){n+=1,r.reset()}}}function wr(e,t,n){let r=null,s=1,i=0,c=!1,a=!1;const l=new Map,d=Dt(async(w,u,g)=>(l.set(u,{drawKey:g.drawKey,onDisplayed:g.onDisplayed}),await o({type:"drawFrame",diffPath:w.mouthPath,expressionDiffPath:w.expressionPath,liveSeq:u},void 0,!0),!1)),m=w=>{if(w===lt){let E=-1,R;for(const[$,y]of l)$>=E&&(E=$,R=y);E>=0&&l.delete(E),R?.onDisplayed?.(R.drawKey);return}const u=-w,g=l.get(u);l.delete(u),g?.onDisplayed?.(g.drawKey)},_=new Map,k=(w,u)=>{a||!r||r.postMessage(w,[])},o=(w,u,g=!1)=>{if(a)return Promise.resolve();const E=s++;return new Promise((R,$)=>{_.set(E,{resolve:y=>R(y),reject:$,generation:typeof w.generation=="number"?w.generation:void 0,expectRenderDone:g}),k({...w,requestId:E})})},x=(async()=>{r=await hr(n),r.onmessage=w=>{if(a)return;const u=w.data;if(u.type==="status"){t.onStatus?.(u.label);return}if(u.type==="frame"){const E=u.generation<0;if(!E&&u.generation!==i){u.bitmap.close();return}if(E&&!(u.generation===lt)){const $=-u.generation;if(!d.isLatestSeq($)){u.bitmap.close();return}}if(E&&t.shouldAcceptLiveFrame&&!t.shouldAcceptLiveFrame()){u.bitmap.close();return}mr(e,u.bitmap),u.bitmap.close(),E&&m(u.generation);return}const g=_.get(u.requestId);if(g)switch(u.type){case"ready":_.delete(u.requestId),g.resolve();break;case"loadAssetsDone":_.delete(u.requestId),g.resolve({width:u.width,height:u.height});break;case"renderDone":if(g.expectRenderDone&&g.generation!=null&&u.generation!==g.generation)return;_.delete(u.requestId),g.resolve();break;case"renderAborted":_.delete(u.requestId),g.resolve();break;case"error":_.delete(u.requestId),t.onError?.(u.message),g.reject(new Error(u.message));break}},r.onerror=w=>{if(a)return;const u=w.message||"Worker error";t.onError?.(u);for(const[,g]of _)g.reject(new Error(u));_.clear()},await o({type:"init"}),c=!0})();return{usesWorker:!0,async loadAssets(w){if(a)return{width:842,height:1264};if(await x,a)return{width:842,height:1264};if(!c)throw new Error("Worker init failed");return await o({type:"loadAssets",keyHex:w,urls:en(se())})??{width:842,height:1264}},async renderSilOnly(){if(a||(await x,a))return;i+=1,d.reset(),l.clear();const w=i;await o({type:"renderSil",generation:w},void 0,!0)},drawLiveFrame(w,u,g,E){a||x.then(()=>{a||d.enqueue(u,g,E)})},async renderViseme(w,u,g={}){if(a||(await x,a))return;i+=1;const E=i;try{await o({type:"renderViseme",generation:E,to:u,from:g.from,transitionDurationMs:g.transitionDurationMs,gapMs:g.gapMs,threshold:g.threshold},void 0,!0)}catch(R){if(R?.name==="AbortError")return;throw R}},dispose(){if(!a){a=!0,i+=1,d.reset(),l.clear();for(const[,w]of _)w.resolve();_.clear(),r?.terminate(),r=null}}}}function gr(e,t={}){if(!_r())return dt(e,t);const n=Ut(t.workerScriptUrl);try{return wr(e,t,n)}catch{return dt(e,t)}}class yr extends Error{constructor(t,n){super(`${t} timed out after ${Math.round(n/1e3)}s`),this.name="LoadTimeoutError"}}function Ue(e,t,n){return new Promise((r,s)=>{const i=globalThis.setTimeout(()=>{s(new yr(n,t))},t);e.then(c=>{globalThis.clearTimeout(i),r(c)},c=>{globalThis.clearTimeout(i),s(c)})})}const pr={position:"relative",display:"inline-block",lineHeight:0},Er={display:"block",maxWidth:"100%",height:"auto"},Sr={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 $t(e)?Tt:ze}const Tr=p.forwardRef(function({id:t,assets:n,authToken:r,ttsEngineId:s=re,voiceId:i,speakingRate:c=Qe,className:a,style:l,canvasStyle:d,onStatusChange:m,onDisplayStatus:_,onError:k,onReady:o,showErrorOverlay:x=!0},w){const u=p.useRef(null),g=p.useRef(null),E=p.useRef(lr()),R=p.useRef(zn()),$=p.useRef(0),y=p.useRef(0),S=p.useRef(null),C=p.useRef(!1),D=p.useRef(null),W=p.useRef(!1),[q,ce]=p.useState("idle"),[ge,Z]=p.useState(null),[K,ye]=p.useState(!1),[Me,ue]=p.useState(!1),[ie,pe]=p.useState({width:842,height:1264}),ee=p.useRef(r??null),le=p.useRef(null),h=p.useRef(null),M=p.useRef(!1),B=p.useRef({width:842,height:1264}),P=p.useRef(o),I=p.useRef(_),U=p.useRef(k);P.current=o,I.current=_,U.current=k;const Q=p.useCallback(f=>{const T=f?.ttsEngineId??s??h.current?.ttsEngineId??re,v=f?.voiceId??i??h.current?.voiceId??Ie(T);return{ttsEngineId:T,voiceId:v}},[s,i]),V=p.useCallback(f=>{Z(f),U.current?.(f)},[]),L=p.useCallback(f=>{ce(f),m?.(f)},[m]),F=p.useRef(kt(L,ve)),O=p.useCallback(()=>{S.current!=null&&(clearTimeout(S.current),S.current=null)},[]),J=p.useCallback(async()=>{const f=y.current,T=g.current;!T||!K||F.current.isSpeaking()||(he(E.current),await T.renderSilOnly(),f===y.current&&(F.current.isSpeaking()||(I.current?.("sil"),W.current&&D.current&&(D.current.restart(),D.current.setActive(!0)))))},[K]),H=p.useCallback(()=>{O();const f=y.current;J(),S.current=setTimeout(()=>{S.current=null,f===y.current&&J()},cr)},[O,J]),fe=p.useCallback(async()=>{const f=Math.floor(Date.now()/1e3);if(le.current&&f<le.current.expiresAt-60)return le.current.key;const T=ee.current??await Ne();ee.current=T,F.current.setDeveloperToken(T);const v=await zt(T,ve);return le.current={key:v.value,expiresAt:v.expiresAt},v.value},[]);p.useEffect(()=>{r&&(ee.current=r,F.current.setDeveloperToken(r))},[r]),p.useEffect(()=>{F.current.setTtsEngineId(s),h.current&&(h.current.ttsEngineId=s)},[s]),p.useEffect(()=>{const f=i??Ie(s);h.current&&(h.current.voiceId=f)},[i,s]);const de=p.useMemo(()=>n?JSON.stringify(n):`id:${t??""}`,[n,t]);return p.useEffect(()=>{if(!t&&!n){V("AiTwin requires either `id` or `assets`");return}let f=!1;M.current=!1,ye(!1),ue(!1),Z(null),h.current=null,D.current=null,W.current=!1;const T=u.current;if(!T)return;let v=null;return(async()=>{try{let A,b,G;if(n)A=n,b=s,G=i??Ie(b);else{I.current?.("getAiTwin");const N=await Ue(mt(t),3e4,"getAiTwin");if(f)return;if(!N.faceId?.trim())throw new Error("getAiTwin returned no faceId");b=N.ttsEngineId,G=i??N.voiceId??Ie(b),A=Xt(N.faceId)}h.current={ttsEngineId:b,voiceId:G},Zt(A),D.current=Qn(),v=gr(T,{onStatus:N=>{f||I.current?.(N)},onError:N=>{f||V(N)},shouldAcceptLiveFrame:()=>F.current.isSpeaking()}),g.current=v,I.current?.("auth");const Y=ee.current??r??await Ue(Ne(),3e4,"getAuthToken");if(f)return;ee.current=Y,F.current.setDeveloperToken(Y),F.current.setTtsEngineId(b);const Ee=je()?await fe():void 0;if(f)return;I.current?.("loadAssets");const j=await Ue(v.loadAssets(Ee),18e4,"load face assets");if(!f&&j.width>0&&j.height>0&&(B.current=j,pe(j)),f)return;M.current=!0,ye(!0),P.current?.(),v.renderSilOnly().then(()=>{f||I.current?.("sil")}),(async()=>{try{const N=await bn(Ee);if(await D.current.load(N),f)return;W.current=!0,ue(!0),he(E.current),D.current.setActive(!0);const X=D.current.getVideo();await at(T,X,null,void 0,B.current),f||I.current?.("idle")}catch(N){if(f)return;W.current=!1,ue(!1),console.warn("[AiTwin] Idle video unavailable:",N)}})()}catch(A){if(f)return;if(A instanceof Ae){V(A.message);return}V(A instanceof Error?A.message:"Failed to load AI twin")}})(),()=>{f=!0,D.current?.dispose(),v?.dispose(),g.current=null}},[de,n,s,i,r,fe,V]),p.useEffect(()=>{q==="done"&&K&&!F.current.isSpeaking()&&H()},[q,K,H]),p.useEffect(()=>{const f=F.current,T={current:!1},v=()=>{const A=u.current,b=g.current;if(!A||!b||!K){$.current=requestAnimationFrame(v);return}const G=f.isSpeaking(),Y=f.getPlaybackElapsedMs(),Ee=G?Zn(Y,f.getSentenceEmotions(),f.getWordQueue(),f.getStreamMood()):f.getStreamMood();if(G){if(W.current&&D.current?.setActive(!1),f.getVisemeQueue().length===0){$.current=requestAnimationFrame(v);return}R.current.setTargetEmotion(Ee),R.current.advance(performance.now());const N=R.current.getExpressionPath(),X=R.current.getDrawKey();dr(A,f.getVisemeQueue(),Y,N,X,E.current,(te,Fe,Oe,xt)=>b.drawLiveFrame(te,Fe,Oe,xt),te=>I.current?.(te))}else if(W.current&&D.current){const j=D.current,N=j.getVideo();N.readyState>=HTMLMediaElement.HAVE_CURRENT_DATA?(j.setActive(!0),T.current||(T.current=!0,at(A,N,null,void 0,B.current,()=>!f.isSpeaking()).then(()=>I.current?.("idle")).finally(()=>{T.current=!1}))):ut(A,null,"__sil__",E.current,(X,te,Fe,Oe)=>b.drawLiveFrame(X,te,Fe,Oe),X=>I.current?.(X))}else ut(A,null,"__sil__",E.current,(j,N,X,te)=>b.drawLiveFrame(j,N,X,te),j=>I.current?.(j));C.current&&!G&&(R.current.reset(),D.current?.setActive(!1),H()),C.current=G,$.current=requestAnimationFrame(v)};return $.current=requestAnimationFrame(v),()=>{cancelAnimationFrame($.current),O(),f.stop()}},[K,Me,H,O]),p.useImperativeHandle(w,()=>({speakText:async(f,T)=>{const v=f.trim();if(!v)return;const A=g.current;if(!A||!M.current&&!K)throw new Error("AI twin is not ready");const{ttsEngineId:b,voiceId:G}=Q(T);Z(null),y.current+=1,O(),he(E.current),R.current.reset(),C.current=!1;try{W.current?(D.current?.setActive(!1),D.current?.restart(),he(E.current)):await A.renderSilOnly(),await F.current.speak(v,{voiceId:G,speakingRate:T?.speakingRate??c,ttsEngineId:b})}catch(Y){throw V(Y instanceof Error?Y.message:"TTS failed"),Y}},stop:()=>{y.current+=1,O(),F.current.stop(),he(E.current),C.current=!1,H()},setTtsEngineId:f=>{F.current.setTtsEngineId(f),h.current&&(h.current.ttsEngineId=f)},renderViseme:async(f,T)=>{const v=g.current,A=u.current;if(!v||!A||!M.current)throw new Error("AI twin is not ready");await v.renderViseme(A,f,{from:T?.from,transitionDurationMs:T?.transitionDurationMs,gapMs:T?.gapMs,onStatus:b=>I.current?.(b)})},isReady:()=>M.current,getStatus:()=>q}),[K,c,O,H,V,Q,q]),Pe.jsxs("div",{className:a,style:{...pr,...l},children:[Pe.jsx("canvas",{ref:u,width:ie.width,height:ie.height,style:{...Er,...d},"aria-label":t?`AI twin ${t}`:"AI twin face"}),x&&ge?Pe.jsx("div",{style:Sr,children:ge}):null]})});exports.AiTwin=Tr;exports.AiTwinNotFoundError=Ae;exports.DEFAULT_TTS_ENGINE_ID=re;exports.OCULUS_VISEME_IDS=wt;exports.SPEAKING_RATE_MAX=St;exports.SPEAKING_RATE_MIN=Et;exports.TTS_ENGINE_CARTESIA=ae;exports.TTS_ENGINE_GOOGLE=Ge;exports.TTS_ENGINE_INWORLD=be;exports.VISEME_IDS=Dn;exports.VISEME_TEST_CARTESIA_VOICE_ID=Tt;exports.VISEME_TEST_SPEAKING_RATE=Qe;exports.VISEME_TEST_VOICE_ID=ze;exports.createAvatarTtsLipsyncController=kt;exports.fetchAiTwin=mt;exports.fetchDevAuthToken=Ne;exports.normalizeOculusViseme=gt;exports.resolveVisemeAtTime=yt;exports.resolveWordAtTime=pt;
3
+ `);$=K.pop()??"";for(const te of K)await be(te);if(N){$.trim()&&await be($.trim()),D||Ae();break}}}catch(P){throw console.error("[avatarTtsLipsync]",P),B(),e("error"),P}},stop:B,getVisemeQueue:()=>r,getWordQueue:()=>s,getSentenceEmotions:()=>i,getStreamMood:()=>c,getPlaybackElapsedMs:()=>m?T&&d&&g>0?Math.max(0,(d.currentTime-g)*1e3):Math.max(0,(performance.now()-O)*R):0,isSpeaking:()=>m,setPlaybackSpeed:E=>{R=Math.max(.1,Math.min(1,E)),z()},getPlaybackSpeed:()=>R,subscribe:E=>(L.add(E),()=>L.delete(E))}}function Fn(e,t,n){return{width:e.crop?.source_width??t,height:e.crop?.source_height??n}}function Pn(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 Un(e){return e?(e.w??0)>0&&(e.h??0)>0:!1}async function Be(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 fn(r,t)}async function Nn(e,t){if(!t)throw new Error("Missing asset key for encrypted JSON");const n=await Be(e,t),r=new TextDecoder().decode(n);return JSON.parse(r)}async function Bn(e){const t=new Blob([e],{type:"image/webp"}),n=URL.createObjectURL(t);return new Promise((r,s)=>{const i=new Image;i.decoding="async",i.onload=()=>{URL.revokeObjectURL(n),r(i)},i.onerror=()=>{URL.revokeObjectURL(n),s(new Error("Failed to decode decrypted image"))},i.src=n})}async function Vn(e){const t=new Blob([e],{type:"image/png"}),n=URL.createObjectURL(t);return new Promise((r,s)=>{const i=new Image;i.decoding="async",i.onload=()=>{URL.revokeObjectURL(n),r(i)},i.onerror=()=>{URL.revokeObjectURL(n),s(new Error("Failed to decode decrypted PNG"))},i.src=n})}function $n(e){const t=new Blob([e],{type:"video/mp4"});return URL.createObjectURL(t)}async function Hn(e){const t=wn();if(!Ue())return t;if(!e)throw new Error("Missing asset key for encrypted idle video");const n=await Be(t,e);return $n(n)}function Ot(e,t){return`${e}/${t}_minus_sil.png`}const st=15,Wn=["aa","E","I","O","U","PP","FF","DD","SS","TH","CH","RR","kk","nn"],Qe=["t01_0.17","t02_0.33","t03_0.50","t04_0.67","t05_0.83"],qn=Qe.length,dt=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 ht(e,t){return`${e}__${t}`}function _t(e,t){return`pairs/${e}/${t}_minus_sil.png`}function Je(e){return`${e}_minus_sil.png`}function Lt(e,t){if(e===t)return[];const n=[],r=ht(e,t);if(dt.has(r)){for(const i of Qe)n.push(_t(r,i));return n}const s=ht(t,e);if(dt.has(s)){for(let i=qn-1;i>=0;i--)n.push(_t(s,Qe[i]));return n}return[]}function Kn(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 Gn(e,t){return Kn(t).map(r=>e[r]).filter(r=>r!=null)}function jn(e,t,n,r){if(r<=0)return 0;const i=Math.max(1,n-t)/r,c=e-t,a=Math.floor(c/i);return Math.min(r-1,Math.max(0,a))}function zn(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 Qn=[.32,.24,.16,.08,0],Ve=Qn.map(e=>`eyes_${e.toFixed(2)}`),Jn=["eyes_0.32","eyes_0.16","eyes_0.00"],Yn=["eyes_0.32","eyes_0.16","eyes_0.08","eyes_0.00"],Xn={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 ye(e,t="neutral"){const n=String(e??"").trim().toLowerCase();return n?Xn[n]??t:t}function ee(e){return e==="neutral"?null:Ot(e,"eyes_standard")}function Ye(e,t){return!t||t==="eyes_standard"?ee(e):e==="neutral"&&t==="eyes_standard"?null:Ot(e,t)}function Zn(e){if(!e)return"open";const t=e.match(/\/(eyes_[^/]+)_minus_sil\.png$/);if(!t?.[1])return"open";const n=t[1];return Ve.includes(n)?n:"open"}function er(e){return e==="open"?-1:Ve.indexOf(e)}function tr(e,t){const n=[];for(const r of t)n.push(Ye(e,r));for(let r=t.length-2;r>=0;r--)n.push(Ye(e,t[r]));return n.push(ee(e)),n}function nr(e,t){if(t==="open")return[ee(e)];const n=er(t);if(n<0)return[ee(e)];const r=[];for(let s=n;s>=0;s--)r.push(Ye(e,Ve[s]));return r.push(ee(e)),r}const rr=["t01_0.20","t02_0.40","t03_0.60","t04_0.80"];function sr(e,t){return`${e}__${t}`}function ir(e,t,n){return`pairs/${sr(e,t)}/${n}_minus_sil.png`}function or(e,t){return rr.map(n=>ir(e,t,n))}function Te(e,t){return e+Math.random()*(t-e)}function xe(){return Te(14,32)}function ar(e={}){const{initialDelayMs:t=800+Math.random()*1200,intervalMinMs:n=2200,intervalMaxMs:r=5800,doubleBlinkChance:s=.18,doubleBlinkGapMinMs:i=120,doubleBlinkGapMaxMs:c=220,fullBlinkChance:a=.75,postEmotionChangeDelayMs:l=380,minDwellMs:d=550}=e;let w="neutral",m="neutral",T=0,o={kind:"idle",nextBlinkAt:performance.now()+t},O=null,g="__eyes_open__|neutral";function u(_,S){O=_,g=`${_??"__eyes_open__"}|${S}`}function y(_,S){o={kind:"idle",nextBlinkAt:_+Te(n,r)},m=S,u(ee(S),S)}function p(_,S,D){const L=D?Jn:Math.random()<a?Ve:Yn;o={kind:"playing",paths:tr(S,L),index:0,holdUntil:_+xe(),after:"idle",blinkEmotion:S},m=S,u(o.paths[0]??null,S)}function R(_,S,D){const L=Zn(O),z=[];if(L!=="open"){const U=nr(S,L);z.push(...U.slice(0,-1))}z.push(...or(S,D)),z.push(ee(D)),o={kind:"emotionBlend",paths:z,index:0,holdUntil:_+xe(),thenEmotion:D},u(z[0]??null,S)}function H(_){if(o.kind==="emotionBlend"){for(;_>=o.holdUntil&&o.index<o.paths.length-1;)o.index+=1,o.holdUntil=_+xe();const S=o.paths[o.index]??null;u(S,o.thenEmotion),_>=o.holdUntil&&o.index>=o.paths.length-1&&(w=o.thenEmotion,m=o.thenEmotion,u(ee(o.thenEmotion),o.thenEmotion),o={kind:"idle",nextBlinkAt:_+l});return}if(o.kind==="idle"){u(ee(m),m),_>=o.nextBlinkAt&&p(_,m,!1);return}if(o.kind==="doublePause"){u(ee(o.blinkEmotion),o.blinkEmotion),_>=o.resumeAt&&p(_,o.blinkEmotion,!0);return}if(o.kind==="playing"){for(;_>=o.holdUntil&&o.index<o.paths.length-1;)o.index+=1,o.holdUntil=_+xe();if(u(o.paths[o.index]??null,o.blinkEmotion),_>=o.holdUntil&&o.index>=o.paths.length-1){if(o.after==="resumeIdle"){y(_+l,w);return}if(o.after==="doublePause"){o={kind:"doublePause",resumeAt:_+Te(i,c),blinkEmotion:o.blinkEmotion},u(ee(o.blinkEmotion),o.blinkEmotion);return}if(o.after==="idle"&&Math.random()<s){o={kind:"doublePause",resumeAt:_+Te(i,c),blinkEmotion:o.blinkEmotion},u(ee(o.blinkEmotion),o.blinkEmotion);return}y(_,o.blinkEmotion)}}}return{advance:H,setTargetEmotion(_){const S=ye(_,w);if(S===w&&o.kind!=="emotionBlend")return;const D=performance.now();if(d>0&&S!==w&&o.kind!=="emotionBlend"&&!(w==="neutral"&&S!=="neutral")&&D-T<d)return;const L=w;if(w=S,T=D,o.kind==="playing"){R(D,m,S);return}if(o.kind==="emotionBlend"){o={...o,thenEmotion:S};return}R(D,L,S)},getTargetEmotion:()=>w,getExpressionPath:()=>O,getDrawKey:()=>g,reset(){w="neutral",m="neutral",T=0,y(performance.now()+Te(n,r),"neutral")}}}function cr(){const e=document.createElement("video");e.muted=!0,e.playsInline=!0,e.preload="auto",e.setAttribute("playsinline",""),e.loop=!0;let t=!1,n=null,r="";const s=()=>{n&&(URL.revokeObjectURL(n),n=null)};return{async load(i){t&&r===i||(s(),t=!1,r=i,i.startsWith("blob:")&&(n=i),await new Promise((c,a)=>{const l=()=>{const d=e.duration;if(!Number.isFinite(d)||d<=0){a(new Error(`Idle video has invalid duration: ${i}`));return}t=!0,e.currentTime=0,c()};e.addEventListener("loadeddata",l,{once:!0}),e.addEventListener("error",()=>a(new Error(`Failed to load idle video: ${i}`)),{once:!0}),e.src=i,e.load()}))},isReady(){return t},getVideo(){return e},setActive(i){t&&(i?e.paused&&e.play().catch(()=>{}):e.paused||e.pause())},restart(){t&&(e.currentTime=0)},dispose(){e.pause(),e.removeAttribute("src"),e.load(),s(),t=!1,r=""}}}const ur=50,Ft=400;function lr(e,t,n){return e.filter(r=>{const s=r.queueIndex??-1;return s>=t&&s<=n})}function fr(e,t){const n=[];for(const r of e){const s=lr(t,r.start_word,r.end_word);if(s.length===0)continue;const i=s[0],c=s[s.length-1];n.push({sentence:r,startMs:Math.max(0,i.wtime-ur),endMs:c.wtime+c.wduration+Ft})}return n.sort((r,s)=>r.startMs-s.startMs)}function dr(e,t,n,r="neutral"){const s=ye(r);if(t.length===0)return s;if(n.length===0||e<n[0].wtime)return ye(t[0]?.emotion,s);const i=fr(t,n);let c=null;for(const d of i)e>=d.startMs&&e<=d.endMs&&(c=d);if(c)return ye(c.sentence.emotion,s);const a=n[n.length-1],l=a.wtime+a.wduration;return e>l+Ft?ye(t[t.length-1]?.emotion,s):s}function Pt(e,t,n,r,s=st){const i=new OffscreenCanvas(n,r),c=i.getContext("2d",{willReadFrequently:!0});c.drawImage(e,0,0,n,r);const a=c.getImageData(0,0,n,r),l=c.createImageData(n,r);l.data.set(a.data);const w=new OffscreenCanvas(n,r).getContext("2d",{willReadFrequently:!0});for(const m of t){w.clearRect(0,0,n,r),w.drawImage(m,0,0,n,r);const T=w.getImageData(0,0,n,r);for(let o=0;o<l.data.length;o+=4){const O=T.data[o],g=T.data[o+1],u=T.data[o+2];Math.max(O,g,u)>s&&(l.data[o]=O,l.data[o+1]=g,l.data[o+2]=u,l.data[o+3]=255)}}return c.putImageData(l,0,0),i}let fe=null,ke=null;const Fe=new Map;function hr(){fe=null,ke=null,Fe.clear()}mn(hr);function _r(e){return e??ke??void 0}function it(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 mr(e){return Ue()?Vn(await Be(ut(),e??"")):it(ut())}async function mt(e,t,n,r){const s=n?await Nn(e,r):await fetch(e).then(d=>{if(!d.ok)throw new Error(`Failed to load ${e}`);return d.json()}),i=s.sheets?.[0];if(!i?.path)throw new Error(`${e} has no sheets[0].path`);const c=n?await Bn(await Be(zn(t,i.path,n),r??"")):await it(`${t}/${i.path}`),a=new Map;for(const d of s.cells??[])d.path&&a.set(d.path,d);const l=new Map;for(const d of s.sheets??[])l.set(d.index,d);return{atlas:c,atlasMeta:s,cellByPath:a,sheetByIndex:l,diffBase:t}}async function Xe(e){const t=_r(e),n=Ue();if(n&&!t)throw new Error("Encrypted assets enabled but no key provided");if(fe&&(!n||ke===(t??null))){const i=await fe;return Ie(i)}ke=t??null,Fe.clear();const r=gn();fe=(async()=>{const i=await mr(t),c=await mt(yn(),r,n,t);let a=null;try{a=await mt(pn(),r,n,t)}catch{a=null}return{sil:i,viseme:c,expression:a}})();const s=await fe;return Ie(s)}async function Ut(e){if(await Xe(e),!fe)throw new Error("Assets not loaded");return fe}function Ie(e){return Fn(e.viseme.atlasMeta,e.sil.naturalWidth,e.sil.naturalHeight)}function wr(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 wt(e,t,n){const r=`${t.diffBase}::${n}`,s=Fe.get(r);if(s)return s;const i=(async()=>{const c=t.cellByPath.get(n);if(!c)throw new Error(`No atlas cell for path: ${n}`);const a=Pn(t.atlasMeta,c),l=Ie(e);if(Un(c)){const m=wr(t,c),T=document.createElement("canvas");T.width=l.width,T.height=l.height;const o=T.getContext("2d");return o.fillStyle="#000",o.fillRect(0,0,l.width,l.height),o.drawImage(m,a.x,a.y),T}const d=`${t.diffBase}/${n}`,w=await it(d);if(w.naturalWidth===l.width&&w.naturalHeight===l.height)return w;throw new Error(`Diff PNG wrong size for ${n}`)})();return Fe.set(r,i),i}async function gt(e,t,n,r=st,s,i){if(s){const{width:T,height:o}=s;if(i&&!i()||t.readyState<HTMLMediaElement.HAVE_CURRENT_DATA)return;const O=document.createElement("canvas");O.width=T,O.height=o;const g=O.getContext("2d");if(g.clearRect(0,0,T,o),g.drawImage(t,0,0,T,o),i&&!i())return;(e.width!==T||e.height!==o)&&(e.width=T,e.height=o);const u=e.getContext("2d");u.clearRect(0,0,T,o),u.drawImage(O,0,0);return}const c=await Ut(),{width:a,height:l}=Ie(c);(e.width!==a||e.height!==l)&&(e.width=a,e.height=l);const d=[],w=e.getContext("2d");if(w.clearRect(0,0,a,l),t.readyState<HTMLMediaElement.HAVE_CURRENT_DATA){const T=c.sil;w.drawImage(T,0,0,a,l);return}if(d.length===0){w.drawImage(t,0,0,a,l);return}const m=Pt(t,d,a,l,r);w.drawImage(m,0,0)}async function Ze(e,t,n=st){const r=await Ut(ke??void 0),{width:s,height:i}=Ie(r);(e.width!==s||e.height!==i)&&(e.width=s,e.height=i);const c=[];t.mouthPath&&c.push(await wt(r,r.viseme,t.mouthPath)),t.expressionPath&&r.expression&&c.push(await wt(r,r.expression,t.expressionPath));const a=e.getContext("2d");if(a.clearRect(0,0,s,i),c.length===0){a.drawImage(r.sil,0,0,s,i);return}const l=Pt(r.sil,c,s,i,n);a.drawImage(l,0,0)}async function gr(e){await Ze(e,{mouthPath:null,expressionPath:null})}function yr(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 pr(e){const t=yr(e),n=[];for(let r=0;r<t.length-1;r++){const s=t[r].viseme,i=t[r+1].viseme,c=t[r].vtime,a=t[r+1].vtime;s===i||a<=c||n.push({from:s,to:i,fromVtime:c,toVtime:a})}return n}function Er(e,t){let n=null;for(const r of e)t>=r.fromVtime&&t<r.toVtime&&(n=r);return n}function Sr(e,t){return{gapMs:Math.max(0,t-e),holdEnd:e,transStart:e}}const Nt=400,Tr=200,kr=600,Ir="__sil__";function Rr(){return{lastDrawnKey:""}}function ge(e){e.lastDrawnKey=""}function vr(e){let t="sil";for(const n of e)n.viseme!=="sil"&&(t=n.viseme);return t}function Ar(e){return e==="sil"?!1:Lt(e,"sil").length>0}function br(){return Nt+kr}function yt(e){return e??Ir}function Dr(e,t){if(e.length===0)return{diffPath:null,label:"sil"};const n=pr(e),r=Er(n,t);if(r){const i=r.toVtime-r.fromVtime,c=Sr(r.fromVtime,r.toVtime);if(t>=c.transStart&&t<r.toVtime){const a=Lt(r.from,r.to),l=Gn(a,i);if(l.length>0){const d=jn(t,c.transStart,r.toVtime,l.length);return{diffPath:l[d]??l[l.length-1],label:`${r.from}→${r.to}`}}return{diffPath:Je(r.to),label:r.to}}}const s=tt(e,t);return s==="sil"?{diffPath:null,label:"sil"}:{diffPath:Je(s),label:s}}function Bt(e,t){const n=t??yt(e.expressionPath);return`${yt(e.mouthPath)}|${n}`}function Cr(e,t,n,r,s,i,c,a){const l=Dr(t,n),d={mouthPath:l.diffPath,expressionPath:r},w=Bt(d,s);w!==i.lastDrawnKey&&(a(l.label),c(e,d,w,m=>{m===w&&(i.lastDrawnKey=w)}))}function pt(e,t,n,r,s,i,c=null){const a={mouthPath:null,expressionPath:t},l=c!=null?`|idle@${Math.round(c*1e3)}`:"",d=Bt(a,n)+l;!(c!=null)&&d===r.lastDrawnKey||(i(c!=null?"idle":"sil"),s(e,a,d,m=>{m===d&&(r.lastDrawnKey=d)}))}function Vt(e){let t=0,n=null,r=!1,s=!1;const i=async()=>{if(!r){r=!0;try{for(;n;){const a=n;n=null;const l=++t,d=await e(a.diffs,l,a);n||d&&l===t&&a.onDisplayed?.(a.drawKey)}}finally{r=!1,n&&i()}}},c=()=>{s||(s=!0,queueMicrotask(()=>{s=!1,i()}))};return{enqueue(a,l,d){n={diffs:a,drawKey:l,onDisplayed:d},c()},reset(){t+=1,n=null},isLatestSeq(a){return a===t},getLatestSeq(){return t}}}const Et=-1,St=new Map;async function xr(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 Mr(){return typeof Worker<"u"&&typeof OffscreenCanvas<"u"}function Or(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 Tt(e,t){let n=0;const r=Vt(async(s,i)=>(await Xe(),await Ze(e,s),r.isLatestSeq(i)));return{usesWorker:!1,async loadAssets(s){return await Xe(s)},async renderSilOnly(){n+=1,r.reset(),await gr(e)},drawLiveFrame(s,i,c,a){r.enqueue(i,c,a)},async renderViseme(s,i){n+=1;const c=n;t.onStatus?.(i),await Ze(s,{mouthPath:Je(i),expressionPath:null})},dispose(){n+=1,r.reset()}}}function Lr(e,t,n){let r=null,s=1,i=0,c=!1,a=!1;const l=new Map,d=Vt(async(g,u,y)=>(l.set(u,{drawKey:y.drawKey,onDisplayed:y.onDisplayed}),await o({type:"drawFrame",diffPath:g.mouthPath,expressionDiffPath:g.expressionPath,liveSeq:u},void 0,!0),!1)),w=g=>{if(g===Et){let p=-1,R;for(const[H,_]of l)H>=p&&(p=H,R=_);p>=0&&l.delete(p),R?.onDisplayed?.(R.drawKey);return}const u=-g,y=l.get(u);l.delete(u),y?.onDisplayed?.(y.drawKey)},m=new Map,T=(g,u)=>{a||!r||r.postMessage(g,[])},o=(g,u,y=!1)=>{if(a)return Promise.resolve();const p=s++;return new Promise((R,H)=>{m.set(p,{resolve:_=>R(_),reject:H,generation:typeof g.generation=="number"?g.generation:void 0,expectRenderDone:y}),T({...g,requestId:p})})},O=(async()=>{r=await xr(n),r.onmessage=g=>{if(a)return;const u=g.data;if(u.type==="status"){t.onStatus?.(u.label);return}if(u.type==="frame"){const p=u.generation<0;if(!p&&u.generation!==i){u.bitmap.close();return}if(p&&!(u.generation===Et)){const H=-u.generation;if(!d.isLatestSeq(H)){u.bitmap.close();return}}if(p&&t.shouldAcceptLiveFrame&&!t.shouldAcceptLiveFrame()){u.bitmap.close();return}Or(e,u.bitmap),u.bitmap.close(),p&&w(u.generation);return}const y=m.get(u.requestId);if(y)switch(u.type){case"ready":m.delete(u.requestId),y.resolve();break;case"loadAssetsDone":m.delete(u.requestId),y.resolve({width:u.width,height:u.height});break;case"renderDone":if(y.expectRenderDone&&y.generation!=null&&u.generation!==y.generation)return;m.delete(u.requestId),y.resolve();break;case"renderAborted":m.delete(u.requestId),y.resolve();break;case"error":m.delete(u.requestId),t.onError?.(u.message),y.reject(new Error(u.message));break}},r.onerror=g=>{if(a)return;const u=g.message||"Worker error";t.onError?.(u);for(const[,y]of m)y.reject(new Error(u));m.clear()},await o({type:"init"}),c=!0})();return{usesWorker:!0,async loadAssets(g){if(a)return{width:842,height:1264};if(await O,a)return{width:842,height:1264};if(!c)throw new Error("Worker init failed");return await o({type:"loadAssets",keyHex:g,urls:_n(he())})??{width:842,height:1264}},async renderSilOnly(){if(a||(await O,a))return;i+=1,d.reset(),l.clear();const g=i;await o({type:"cancelLiveDraws"}),await o({type:"renderSil",generation:g},void 0,!0)},drawLiveFrame(g,u,y,p){a||O.then(()=>{a||d.enqueue(u,y,p)})},async renderViseme(g,u,y={}){if(a||(await O,a))return;i+=1,d.reset(),l.clear();const p=i;try{await o({type:"cancelLiveDraws"}),await o({type:"renderViseme",generation:p,to:u,from:y.from,transitionDurationMs:y.transitionDurationMs,gapMs:y.gapMs,threshold:y.threshold},void 0,!0)}catch(R){if(R?.name==="AbortError")return;throw R}},dispose(){if(!a){a=!0,i+=1,d.reset(),l.clear();for(const[,g]of m)g.resolve();m.clear(),r?.terminate(),r=null}}}}function Fr(e,t={}){if(!Mr())return Tt(e,t);const n=Jt(t.workerScriptUrl);try{return Lr(e,t,n)}catch{return Tt(e,t)}}class Pr extends Error{constructor(t,n){super(`${t} timed out after ${Math.round(n/1e3)}s`),this.name="LoadTimeoutError"}}function Ke(e,t,n){return new Promise((r,s)=>{const i=globalThis.setTimeout(()=>{s(new Pr(n,t))},t);e.then(c=>{globalThis.clearTimeout(i),r(c)},c=>{globalThis.clearTimeout(i),s(c)})})}const Ur={position:"relative",display:"inline-block",lineHeight:0},Nr={display:"block",maxWidth:"100%",height:"auto"},Br={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 Me(e){return en(e)?xt:nt}const Vr=h.forwardRef(function({id:t,assets:n,authToken:r,ttsEngineId:s=de,voiceId:i,speakingRate:c=rt,className:a,style:l,canvasStyle:d,onStatusChange:w,onDisplayStatus:m,onError:T,onReady:o,showErrorOverlay:O=!0},g){const u=h.useRef(null),y=h.useRef(null),p=h.useRef(Rr()),R=h.useRef(ar()),H=h.useRef(0),_=h.useRef(0),S=h.useRef(null),D=h.useRef(null),L=h.useRef(!1),z=h.useRef(!1),U=h.useRef(!1),oe=h.useRef("sil"),_e=h.useRef(!1),B=h.useRef(null),X=h.useRef(!1),[Re,$e]=h.useState("idle"),[ve,ce]=h.useState(null),[se,Ae]=h.useState(!1),[ot,E]=h.useState(!1),[V,W]=h.useState({width:842,height:1264}),C=h.useRef(r??null),x=h.useRef(null),v=h.useRef(null),Q=h.useRef(!1),J=h.useRef({width:842,height:1264}),P=h.useRef(o),F=h.useRef(m),q=h.useRef(T);P.current=o,F.current=m,q.current=T;const ae=h.useCallback(f=>{const k=f?.ttsEngineId??s??v.current?.ttsEngineId??de,I=f?.voiceId??i??v.current?.voiceId??Me(k);return{ttsEngineId:k,voiceId:I}},[s,i]),$=h.useCallback(f=>{ce(f),q.current?.(f)},[]),be=h.useCallback(f=>{$e(f),w?.(f)},[w]),N=h.useRef(Mt(be,Oe)),b=h.useCallback(()=>{S.current!=null&&(clearTimeout(S.current),S.current=null)},[]),K=h.useCallback(()=>{D.current!=null&&(clearTimeout(D.current),D.current=null),U.current=!1},[]),te=h.useCallback(()=>{!X.current||!B.current||(K(),U.current=!0,D.current=setTimeout(()=>{if(D.current=null,N.current.isSpeaking()){U.current=!1;return}if(L.current){U.current=!1;return}const f=B.current;if(!f){U.current=!1;return}f.restart(),f.setActive(!0);const k=f.getVideo();let I=!1;const A=()=>{I||(I=!0,k.removeEventListener("playing",M),U.current=!1)},M=()=>{A()};if(k.addEventListener("playing",M,{once:!0}),k.readyState>=HTMLMediaElement.HAVE_CURRENT_DATA&&!k.paused){A();return}setTimeout(A,300)},Tr))},[K]),Z=h.useCallback(()=>{if(b(),F.current?.("sil"),L.current=!1,!X.current||!B.current){U.current=!1;return}te()},[b,te]),G=h.useCallback(async f=>{const k=_.current,I=y.current,A=u.current,M=()=>{f?.fallbackOnly||(L.current=!1)};if(!I||!A||!se){M();return}if(N.current.isSpeaking()){M();return}if(f?.fallbackOnly){if(!L.current||(ge(p.current),await I.renderSilOnly(),k!==_.current)||N.current.isSpeaking())return;Z();return}const Y=oe.current!=="sil"?oe.current:vr(N.current.getVisemeQueue()),ne=Ar(Y);if(ge(p.current),!ne){if(await I.renderSilOnly(),k!==_.current||N.current.isSpeaking())return;Z();return}try{await I.renderViseme(A,"sil",{from:Y,transitionDurationMs:Nt})}catch(ie){if(ie?.name!=="AbortError")throw ie}if(k!==_.current){M();return}if(N.current.isSpeaking()){M();return}Z()},[se,Z]),me=h.useCallback(()=>{if(z.current||L.current)return;z.current=!0,L.current=!0,b();const f=_.current;G().finally(()=>{z.current=!1}),S.current=setTimeout(()=>{S.current=null,f===_.current&&G({fallbackOnly:!0})},br())},[b,G]),at=h.useCallback(async()=>{const f=Math.floor(Date.now()/1e3);if(x.current&&f<x.current.expiresAt-60)return x.current.key;const k=C.current??await Ge();C.current=k,N.current.setDeveloperToken(k);const I=await cn(k,Oe);return x.current={key:I.value,expiresAt:I.expiresAt},I.value},[]);h.useEffect(()=>{r&&(C.current=r,N.current.setDeveloperToken(r))},[r]),h.useEffect(()=>{N.current.setTtsEngineId(s),v.current&&(v.current.ttsEngineId=s)},[s]),h.useEffect(()=>{const f=i??Me(s);v.current&&(v.current.voiceId=f)},[i,s]);const $t=h.useMemo(()=>n?JSON.stringify(n):`id:${t??""}`,[n,t]);return h.useEffect(()=>{if(!t&&!n){$("AiTwin requires either `id` or `assets`");return}let f=!1;Q.current=!1,Ae(!1),E(!1),ce(null),v.current=null,B.current=null,X.current=!1;const k=u.current;if(!k)return;let I=null;return(async()=>{try{let A,M,Y;if(n)A=n,M=s,Y=i??Me(M);else{F.current?.("getAiTwin");const j=await Ke(Rt(t),3e4,"getAiTwin");if(f)return;if(!j.faceId?.trim())throw new Error("getAiTwin returned no faceId");M=j.ttsEngineId,Y=i??j.voiceId??Me(M),A=dn(j.faceId)}v.current={ttsEngineId:M,voiceId:Y},hn(A),B.current=cr(),I=Fr(k,{onStatus:j=>{f||F.current?.(j)},onError:j=>{f||$(j)},shouldAcceptLiveFrame:()=>N.current.isSpeaking()&&!L.current}),y.current=I,F.current?.("auth");const ne=C.current??r??await Ke(Ge(),3e4,"getAuthToken");if(f)return;C.current=ne,N.current.setDeveloperToken(ne),N.current.setTtsEngineId(M);const ie=Ue()?await at():void 0;if(f)return;F.current?.("loadAssets");const we=await Ke(I.loadAssets(ie),18e4,"load face assets");if(!f&&we.width>0&&we.height>0&&(J.current=we,W(we)),f)return;Q.current=!0,Ae(!0),P.current?.(),I.renderSilOnly().then(()=>{f||F.current?.("sil")}),(async()=>{try{const j=await Hn(ie);if(await B.current.load(j),f)return;X.current=!0,E(!0),ge(p.current),B.current.setActive(!0);const re=B.current.getVideo();await gt(k,re,null,void 0,J.current),f||F.current?.("idle")}catch(j){if(f)return;X.current=!1,E(!1),console.warn("[AiTwin] Idle video unavailable:",j)}})()}catch(A){if(f)return;if(A instanceof Le){$(A.message);return}$(A instanceof Error?A.message:"Failed to load AI twin")}})(),()=>{f=!0,B.current?.dispose(),I?.dispose(),y.current=null}},[$t,n,s,i,r,at,$]),h.useEffect(()=>{const f=N.current,k={current:!1},I=()=>{const A=u.current,M=y.current;if(!A||!M||!se){H.current=requestAnimationFrame(I);return}const Y=f.isSpeaking(),ne=_e.current&&!Y;ne&&(R.current.reset(),B.current?.setActive(!1),me());const ie=f.getPlaybackElapsedMs(),we=Y?dr(ie,f.getSentenceEmotions(),f.getWordQueue(),f.getStreamMood()):f.getStreamMood(),j=ne||L.current||U.current;if(Y){X.current&&B.current?.setActive(!1);const re=f.getVisemeQueue();if(re.length===0){H.current=requestAnimationFrame(I);return}const ue=tt(re,ie);ue!=="sil"&&(oe.current=ue),R.current.setTargetEmotion(we),R.current.advance(performance.now());const le=R.current.getExpressionPath(),Ee=R.current.getDrawKey();Cr(A,f.getVisemeQueue(),ie,le,Ee,p.current,(Se,He,Ht,Wt)=>M.drawLiveFrame(Se,He,Ht,Wt),Se=>F.current?.(Se))}else if(!j&&X.current&&B.current){const re=B.current,ue=re.getVideo();ue.readyState>=HTMLMediaElement.HAVE_CURRENT_DATA?(re.setActive(!0),k.current||(k.current=!0,gt(A,ue,null,void 0,J.current,()=>!f.isSpeaking()&&!L.current&&!U.current).then(()=>F.current?.("idle")).finally(()=>{k.current=!1}))):pt(A,null,"__sil__",p.current,(le,Ee,Se,He)=>M.drawLiveFrame(le,Ee,Se,He),le=>F.current?.(le))}else j||pt(A,null,"__sil__",p.current,(re,ue,le,Ee)=>M.drawLiveFrame(re,ue,le,Ee),re=>F.current?.(re));_e.current=Y,H.current=requestAnimationFrame(I)};return H.current=requestAnimationFrame(I),()=>{cancelAnimationFrame(H.current),b(),K(),f.stop()}},[se,ot,me,b,K]),h.useImperativeHandle(g,()=>({speakText:async(f,k)=>{const I=f.trim();if(!I)return;const A=y.current;if(!A||!Q.current&&!se)throw new Error("AI twin is not ready");const{ttsEngineId:M,voiceId:Y}=ae(k);ce(null),_.current+=1,b(),K(),L.current=!1,z.current=!1,oe.current="sil",ge(p.current),R.current.reset(),_e.current=!1;try{X.current?(B.current?.setActive(!1),B.current?.restart(),ge(p.current)):await A.renderSilOnly(),await N.current.speak(I,{voiceId:Y,speakingRate:k?.speakingRate??c,ttsEngineId:M})}catch(ne){throw $(ne instanceof Error?ne.message:"TTS failed"),ne}},stop:()=>{_.current+=1,b(),K(),L.current=!1,z.current=!1,N.current.stop(),ge(p.current),_e.current=!1,me()},setTtsEngineId:f=>{N.current.setTtsEngineId(f),v.current&&(v.current.ttsEngineId=f)},renderViseme:async(f,k)=>{const I=y.current,A=u.current;if(!I||!A||!Q.current)throw new Error("AI twin is not ready");await I.renderViseme(A,f,{from:k?.from,transitionDurationMs:k?.transitionDurationMs,gapMs:k?.gapMs,onStatus:M=>F.current?.(M)})},isReady:()=>Q.current,getStatus:()=>Re}),[se,c,b,me,$,ae,Re]),We.jsxs("div",{className:a,style:{...Ur,...l},children:[We.jsx("canvas",{ref:u,width:V.width,height:V.height,style:{...Nr,...d},"aria-label":t?`AI twin ${t}`:"AI twin face"}),O&&ve?We.jsx("div",{style:Br,children:ve}):null]})});exports.AiTwin=Vr;exports.AiTwinNotFoundError=Le;exports.DEFAULT_TTS_ENGINE_ID=de;exports.OCULUS_VISEME_IDS=vt;exports.SPEAKING_RATE_MAX=Ct;exports.SPEAKING_RATE_MIN=Dt;exports.TTS_ENGINE_CARTESIA=pe;exports.TTS_ENGINE_GOOGLE=et;exports.TTS_ENGINE_INWORLD=Pe;exports.VISEME_IDS=Wn;exports.VISEME_TEST_CARTESIA_VOICE_ID=xt;exports.VISEME_TEST_SPEAKING_RATE=rt;exports.VISEME_TEST_VOICE_ID=nt;exports.createAvatarTtsLipsyncController=Mt;exports.fetchAiTwin=Rt;exports.fetchDevAuthToken=Ge;exports.normalizeOculusViseme=At;exports.resolveVisemeAtTime=tt;exports.resolveWordAtTime=bt;