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