@streamoji/aitwin 0.6.5 → 0.6.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/README.md +1 -0
- package/dist/aitwin.cjs +6 -6
- package/dist/aitwin.js +2446 -2310
- package/dist/index.d.ts +58 -2
- package/package.json +1 -1
package/dist/aitwin.cjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const R=require("react/jsx-runtime"),h=require("react"),us=require("@pipecat-ai/client-js"),Hn=require("@pipecat-ai/websocket-transport"),we=require("pixi.js");var xn=typeof document<"u"?document.currentScript:null;const ds="https://aitwin.bubu.social",ri={publicBase:ds},fs="0.6.5",ms={version:fs},hs={},ht="https://ai.aitwin.me",$n=`${ri.publicBase}/custom-faces`,gs=`${ri.publicBase}/aitwin-workers/v${ms.version}/visemeDiffPreview.worker.js`;function ws(e){if(e)return e;const t=typeof{url:typeof document>"u"?require("url").pathToFileURL(__filename).href:xn&&xn.tagName.toUpperCase()==="SCRIPT"&&xn.src||new URL("aitwin.cjs",document.baseURI).href}<"u"?hs?.VITE_AITWIN_WORKER_URL:void 0;return t?.trim()?t.trim():gs}const ps="https://us-central1-streamoji-265f4.cloudfunctions.net/getAiTwin",In=3e3,Ot=16,Er=3e3,ys=4e3,vs=.85,_s=8,jn=400,Kn="eng_a7f2b9c1",un="eng_d4e8f3a2",tt="eng_c9b1e6d4",nt="visemetts",dt=tt,dn="eve",ii=new Set([un,tt,nt]),Gn={[Kn]:"oculus_direct",[tt]:"oculus_direct",[nt]:"oculus_direct",[un]:"inworld_word"},Dn={google:Kn,inworld:un,cartesia:tt,visemetts:nt};function bs(e){const t=e.trim();if(t)return t in Gn?t:Dn[t.toLowerCase()]}function si(e){const t=e?.trim();if(!t)return{};const n=t.indexOf(":");if(n<=0)return{voiceId:t};const r=bs(t.slice(0,n));if(!r)return{voiceId:t};const i=t.slice(n+1).trim();return{ttsEngineId:r,voiceId:i||void 0}}function et(e,t){const n=si(t);return{ttsEngineId:e??n.ttsEngineId,voiceId:n.voiceId}}function ai(e){return Gn[e]}function Ss(e){return e===tt}function oi(e){return e===nt}function Ts(e){if(e.ttsEngineId&&e.ttsEngineId in Gn)return e.ttsEngineId;const t=e.tts?.toLowerCase();return t&&t in Dn?Dn[t]:dt}class nn extends Error{constructor(t="AI twin not found"){super(t),this.name="AiTwinNotFoundError"}}function qn(e,...t){const n=typeof e=="string"?e:e?.brainId?.trim()||e?.knowledgeContextId?.trim();for(const r of[n,...t]){const i=r?.trim();if(i)return i}}async function ci(e,t=ps){const n=new URL(t);n.searchParams.set("id",e);const r=await fetch(n.toString());if(r.status===404)throw new nn;if(!r.ok)throw new Error(`getAiTwin failed (${r.status})`);const i=await r.json();if(!i.success)throw new nn(i.error??"AI twin not found");const{tts:s,token:o,...a}=i.data,u=String(a.authToken??o??"").trim()||void 0,d=qn(a);return{...a,ttsEngineId:Ts(i.data),authToken:u,brainId:d,knowledgeContextId:d}}const Yn="thumbnail.webp";function li(e,t=$n){const n=e.trim();if(!n)throw new Error("faceId is required");return`${t.replace(/\/$/,"")}/${n}/${Yn}`}function xr(e){const t=e?.trim();if(!t)return null;try{return li(t)}catch{return null}}function ks(e){if(!e)return null;const t=(e.binBase||e.twinBase).trim().replace(/\/$/,"");return t?`${t}/${Yn}`:null}const Es="https://us-central1-streamoji-265f4.cloudfunctions.net/getAuthToken",xs="client_6TNvp3SCs4Og0a1ijm9TommXLql1",Is="kk8Fq8EmexzP10jMIEwY3R44M5RKUEm1",As="6TNvp3SCs4Og0a1ijm9TommXLql1",Ms="Swaraj Mali";async function Nt(){const e=await fetch(Es,{method:"POST",headers:{"Content-Type":"application/json","Client-Id":xs,"Client-Secret":Is},body:JSON.stringify({userId:As,userName:Ms})});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 Ps(e,t=ht){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 Cs(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 Xt(e){return Uint8Array.from(e)}function Rs(e,t){const n=new Uint8Array(e.length+t.length);return n.set(e,0),n.set(t,e.length),n}async function Ds(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=Xt(n.subarray(0,12)),i=Xt(n.subarray(12,28)),s=Xt(n.subarray(28)),o=Xt(Rs(s,i)),a=await crypto.subtle.importKey("raw",Cs(t),{name:"AES-GCM"},!1,["decrypt"]);return crypto.subtle.decrypt({name:"AES-GCM",iv:r,tagLength:128},a,o)}let Bn=null;const Fn=new Set;function Jt(e){return e.includes("/custom-faces/")}function rn(e){const t=e.binBase.trim().replace(/\/$/,""),n=e.twinBase.trim().replace(/\/$/,"");if(!(e.encrypted||Jt(t)||Jt(n)))return{twinBase:n,binBase:t,encrypted:!1};const i=Jt(t)?t:Jt(n)?n:t;return{twinBase:i,binBase:i,encrypted:!0}}function gt(e){return rn(e).encrypted}function Ln(e,t=$n){const n=`${t.replace(/\/$/,"")}/${e}`;return{twinBase:n,binBase:n,encrypted:!0}}function ui(e,t){return(e??t)?.trim()||void 0}function di(e){Bn=rn(e);for(const t of Fn)t()}function Bs(e,t){const n=typeof globalThis.location<"u"?globalThis.location.href:void 0;if(!n)return rn(e);const r=i=>{try{return new URL(i,n).href.replace(/\/$/,"")}catch{return i}};return rn({twinBase:r(e.twinBase),binBase:r(e.binBase),encrypted:e.encrypted})}function wt(){if(!Bn)throw new Error("Twin assets not configured; call setActiveTwinAssets first");return Bn}function fi(e){return Fn.add(e),()=>Fn.delete(e)}function sn(){const e=wt();return gt(e)?`${e.binBase}/sil.bin`:`${e.twinBase}/sil.png`}function Fs(){const e=wt();return gt(e)?`${e.binBase}/idle.bin`:`${e.twinBase}/idle.mp4`}function mi(){const e=wt();return gt(e)?e.binBase:e.twinBase}function Wt(){return gt(wt())}function hi(){const e=wt();return gt(e)?`${e.binBase}/atlas.bin`:`${e.twinBase}/atlas.json`}function gi(){const e=wt();return gt(e)?`${e.binBase}/expression_atlas.bin`:`${e.twinBase}/expression_atlas.json`}const ft=[{code:"en",label:"English",visemetts:!0,cartesia:!0},{code:"es",label:"Spanish",visemetts:!0,cartesia:!0},{code:"es-MX",label:"Spanish (Mexico)",visemetts:!0,cartesia:!0},{code:"es-ES",label:"Spanish (Spain)",visemetts:!0,cartesia:!0},{code:"pt",label:"Portuguese",visemetts:!0,cartesia:!0},{code:"pt-BR",label:"Portuguese (Brazil)",visemetts:!0,cartesia:!0},{code:"pt-PT",label:"Portuguese (Portugal)",visemetts:!0,cartesia:!0},{code:"fr",label:"French",visemetts:!0,cartesia:!0},{code:"de",label:"German",visemetts:!0,cartesia:!0},{code:"it",label:"Italian",visemetts:!0,cartesia:!0},{code:"zh",label:"Chinese",visemetts:!0,cartesia:!0},{code:"ja",label:"Japanese",visemetts:!0,cartesia:!0},{code:"hi",label:"Hindi",visemetts:!0,cartesia:!0},{code:"ko",label:"Korean",visemetts:!0,cartesia:!0},{code:"ru",label:"Russian",visemetts:!0,cartesia:!0},{code:"tr",label:"Turkish",visemetts:!0,cartesia:!0},{code:"id",label:"Indonesian",visemetts:!0,cartesia:!0},{code:"ar",label:"Arabic",visemetts:!0,cartesia:!0},{code:"ar-EG",label:"Arabic (Egypt)",visemetts:!0,cartesia:!0},{code:"ar-AE",label:"Arabic (UAE)",visemetts:!0,cartesia:!0},{code:"vi",label:"Vietnamese",visemetts:!0,cartesia:!0},{code:"bn",label:"Bengali",visemetts:!0,cartesia:!0},{code:"auto",label:"Auto-detect",visemetts:!0,cartesia:!1},{code:"nl",label:"Dutch",visemetts:!1,cartesia:!0},{code:"pl",label:"Polish",visemetts:!1,cartesia:!0},{code:"sv",label:"Swedish",visemetts:!1,cartesia:!0},{code:"tl",label:"Tagalog",visemetts:!1,cartesia:!0},{code:"bg",label:"Bulgarian",visemetts:!1,cartesia:!0},{code:"ro",label:"Romanian",visemetts:!1,cartesia:!0},{code:"cs",label:"Czech",visemetts:!1,cartesia:!0},{code:"el",label:"Greek",visemetts:!1,cartesia:!0},{code:"fi",label:"Finnish",visemetts:!1,cartesia:!0},{code:"hr",label:"Croatian",visemetts:!1,cartesia:!0},{code:"ms",label:"Malay",visemetts:!1,cartesia:!0},{code:"sk",label:"Slovak",visemetts:!1,cartesia:!0},{code:"da",label:"Danish",visemetts:!1,cartesia:!0},{code:"ta",label:"Tamil",visemetts:!1,cartesia:!0},{code:"uk",label:"Ukrainian",visemetts:!1,cartesia:!0},{code:"hu",label:"Hungarian",visemetts:!1,cartesia:!0},{code:"no",label:"Norwegian",visemetts:!1,cartesia:!0},{code:"th",label:"Thai",visemetts:!1,cartesia:!0},{code:"he",label:"Hebrew",visemetts:!1,cartesia:!0},{code:"ka",label:"Georgian",visemetts:!1,cartesia:!0},{code:"te",label:"Telugu",visemetts:!1,cartesia:!0},{code:"gu",label:"Gujarati",visemetts:!1,cartesia:!0},{code:"kn",label:"Kannada",visemetts:!1,cartesia:!0},{code:"ml",label:"Malayalam",visemetts:!1,cartesia:!0},{code:"mr",label:"Marathi",visemetts:!1,cartesia:!0},{code:"pa",label:"Punjabi",visemetts:!1,cartesia:!0}],wi=ft.map(e=>e.code),Ls=new Set(wi),Os=new Set(ft.filter(e=>e.visemetts).map(e=>e.code)),Ns=new Set(ft.filter(e=>e.cartesia).map(e=>e.code)),Vs="en";function pi(e){return Ls.has(e)}function fn(e){const t=e?.trim();if(t)return t}function Us(e){return e===nt?ft.filter(t=>t.visemetts).map(t=>t.code):e===tt?ft.filter(t=>t.cartesia).map(t=>t.code):ft.filter(t=>t.visemetts&&t.cartesia).map(t=>t.code)}function Ws(e,t){const n=t.trim();return n?e===nt?Os.has(n):e===tt?Ns.has(n):pi(n):!1}function yi(e){const t=e.split(/\r?\n/);let n="",r="";for(const s of t)s.startsWith("event:")?n=s.slice(6).trim():s.startsWith("data:")&&(r=s.slice(5).trim());if(!n)return null;let i={};if(r)try{i=JSON.parse(r)}catch{i={raw:r}}return{event:n,data:i}}const vi=["aa","CH","DD","E","FF","I","O","PP","RR","SS","TH","U","kk","nn","sil"],zs=new Map(vi.map(e=>[e.toLowerCase(),e]));function mn(e){const t=(e??"").trim();return t?zs.get(t.toLowerCase())??"sil":"sil"}const Hs={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 $s(e){if(!e)return["sil"];const t=e.toLowerCase();return Hs[t]??["sil"]}function _i(e,t){const n=e.word.length;if(n<=0)return 0;const r=e.wduration;if(r<=0)return 0;const i=Math.max(0,Math.min(1,(t-e.wtime)/r));return Math.min(n-1,Math.floor(i*n))}function Et(e,t){const n=Math.max(0,Math.min(e.length-1,t));return e[n]??""}function hn(e,t){const n=e.toLowerCase().replace(/[^a-z']/g,"");return!n||Et(n,t)!=="w"||t>0&&Et(n,t-1)==="q"?!1:t===0&&/^w[aeiouy]/.test(n)}function js(e,t){const n=e.toLowerCase(),r=Et(n,t),i=n.slice(Math.max(0,t-1),t+2);return r==="i"||r==="y"?"I":i.includes("ee")||r==="e"||n.includes("ea")?"E":"aa"}function Ks(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";if(hn(n,t))return"FF";const i=Et(n,t);return i==="u"||i==="w"?"U":"O"}function Gs(e,t){const n=e.toLowerCase();if(hn(n,t))return"FF";const r=n.slice(Math.max(0,t-2),t+1);if(/qu/.test(r))return"U";const i=n.slice(Math.max(0,t-1),Math.min(n.length,t+3));return/wo|wh/.test(i)||Et(n,t)==="o"?"O":"U"}const Zt={d:"DD",t:"DD",n:"DD",s:"SS",z:"SS",k:"kk",g:"kk",c:"CH",x:"CH",j:"CH"};function qs(e,t){const n=e.toLowerCase(),r=Et(n,t);if(Zt[r])return Zt[r];for(let i=0;i<n.length;i++){const s=n[i];if(Zt[s])return Zt[s]}return"DD"}function bi(e,t,n){const r=$s(e);if(r.length===1)return r[0];const i=t.trim();if(!i)return r[0];const s=(e??"").toLowerCase(),o=Math.max(0,n);switch(s){case"aei":return js(i,o);case"o":return Ks(i,o);case"qw":return Gs(i,o);case"cdgknstxyz":return qs(i,o);default:return r[0]}}const Qn=16,On=47,Si=new Set(["aa","E","I"]),Ti=new Set(["DD","SS","kk","CH"]),Ys=[Si,Ti];function Qs(e){for(const t of Ys)if(t.has(e))return t;return null}function Xs(e){return Qs(e)!=null}function ki(e,t=Qn){return t<=0?e:Math.round(e/t)*t}function Xn(e,t=Qn){return e.map(n=>({...n,vtime:ki(n.vtime,t)}))}function Ei(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 Jn(e){if(e.length<=2)return[...e];const t=[e[0]];for(let n=1;n<e.length-1;n++){const r=e[n],i=e[n+1],s=t[t.length-1];if(!Xs(r.viseme)){t.push(r);continue}const o=r.vtime-s.vtime,a=i.vtime-r.vtime;o<On||a<On||t.push(r)}return t.push(e[e.length-1]),t}function gn(e){return Jn(Ei(Xn(e)))}function xi(e,t){let n="sil";for(const r of e){if(r.vtime>t)break;r.viseme!=="sil"&&(n=r.viseme)}return n}function wn(e){const t=Ei(Xn(e)),n=Jn(t),r=new Set(n.map(s=>s.vtime)),i=[];for(const s of t)r.has(s.vtime)||i.push({viseme:s.viseme,vtime:s.vtime});return i}function Js(e){return wn(e).map(t=>t.viseme)}const Zs=32,Ir=48;function Ii(e){let t=0;for(const n of e)t=Math.max(t,n.vtime+n.vduration);return t}function Ai(e){let t=null,n=-1;for(const r of e){if(r.viseme==="sil")continue;const i=r.vtime+r.vduration;i>n&&(t=r,n=i)}return t}function ea(e){return gn(e).find(n=>n.viseme!=="sil")??null}function lt(e){const t=Ii(e);return Ai(e)?t+jn:t}function ta(e){const t=[],n=ea(e);n&&n.vtime>0&&t.push({from:"sil",to:n.viseme,fromVtime:0,toVtime:n.vtime});const r=Ai(e),i=Ii(e);return r&&t.push({from:r.viseme,to:"sil",fromVtime:i,toVtime:i+jn}),t}function Mi(e){const t=gn(e),n=[];for(let r=0;r<t.length-1;r++){const i=t[r].viseme,s=t[r+1].viseme,o=t[r].vtime,a=t[r+1].vtime;i===s||a<=o||n.push({from:i,to:s,fromVtime:o,toVtime:a})}return n}function Pi(e){return e.length===0?[]:[...ta(e),...Mi(e)]}function na(e,t){let n=null;for(const r of e){const{transStart:i,transEnd:s}=Ci(r.fromVtime,r.toVtime,r.from,r.to);t>=i&&t<s&&(n=r)}return n}function Ci(e,t,n,r){const i=Math.max(0,t-e);if((n==="PP"||r==="PP")&&i>Ir){const d=Ir,l=t,c=l-d;return{gapMs:i,effectiveGapMs:d,holdEnd:c,transStart:c,transEnd:l}}const o=i>0?Math.max(i,Zs):0,a=e,u=e+o;return{gapMs:i,effectiveGapMs:o,holdEnd:e,transStart:a,transEnd:u}}function Ri(e,t,n,r,i,s){r.forEach(o=>{const u=String(o.word??"").trim();if(!u)return;const d=Math.round((o.start??0)*1e3),l=o.duration!=null?Math.round(o.duration*1e3):o.end!=null?Math.max(1,Math.round((o.end-(o.start??0))*1e3)):0;t.push({word:u,wtime:i+d,wduration:l,queueIndex:t.length,gesture:o.gesture??null,emphasis:o.emphasis===!0})}),n.forEach(o=>{const a=String(o.symbol??o.viseme??"").trim();if(!a)return;const u=Math.round((o.start??0)*1e3),d=Math.max(1,Math.round((o.duration??0)*1e3)),l=i+u,c=Fi(t,l),m=c?_i(c,l):0;let w;ai(s)==="oculus_direct"?(w=mn(a),w==="U"&&c&&hn(c.word,m)&&(w="FF")):w=bi(a,c?.word??"",m),e.push({viseme:w,weight:1,vtime:l,vduration:d})})}function Di(e,t){let n=t;for(const r of e){const i=Math.round((r.start??0)*1e3),s=Math.max(1,Math.round((r.duration??0)*1e3));n=Math.max(n,t+i+s)}return n}const Zn=16e3;function Bi(e){const t=Number(e);return Number.isFinite(t)&&t>0?t:Zn}function ra(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}function ia(e){return e.length>=4&&e[0]===82&&e[1]===73&&e[2]===70&&e[3]===70}function Ar(e,t,n=Zn){const r=t.byteOffset%2===0?t:t.slice(),i=new Int16Array(r.buffer,r.byteOffset,r.byteLength/2),s=new Float32Array(i.length);for(let a=0;a<i.length;a++)s[a]=i[a]>=32768?-(65536-i[a])/32768:i[a]/32767;const o=e.createBuffer(1,s.length,n);return o.copyToChannel(s,0),o}function sa(e){const t=ra(e),n=window.atob(t),r=new Uint8Array(n.length);for(let i=0;i<n.length;i++)r[i]=n.charCodeAt(i);return r}async function Mr(e,t,n=Zn){const r=sa(t),i=Bi(n);if(ia(r)){const s=r.buffer.slice(r.byteOffset,r.byteOffset+r.byteLength);return e.decodeAudioData(s)}if(r.length>=2&&r.length%2===0)return Ar(e,r,i);try{const s=r.buffer.slice(r.byteOffset,r.byteOffset+r.byteLength);return await e.decodeAudioData(s)}catch{return Ar(e,r,i)}}function Fi(e,t){for(const n of e)if(t>=n.wtime&&t<n.wtime+n.wduration)return n;return null}function Li(e,t){const n=[],r=[];let i=null,s=!1,o=!1,a=!1,u=!1,d=0,l=0,c=0,m=null,w=1,T=t,f=!1,E=null,D=0,B=!1,v=!1,k=0,L=null,A=null,ie=null;const de=()=>({visemes:[],words:[],segmentOffsetMs:0}),I=()=>{v=!1,k=0},V=()=>{m!=null&&(clearTimeout(m),m=null)},G=()=>{for(const b of r){try{b.onended=null,b.stop(0)}catch{}try{b.disconnect()}catch{}}r.length=0},ae=()=>{for(const b of r)b.playbackRate.value=w},se=()=>{if(!(f||!u||s||v||r.length>0||n.length>0)){if(a&&i&&l>0){const b=(i.currentTime-l)*1e3;if(b<D){V();const P=w>0?(D-b)/w:D-b;m=setTimeout(()=>{f||(o=!1,m=null,e.onSpeakingDone(),e.onNotify())},Math.max(0,P));return}}o=!1,V(),e.onSpeakingDone(),e.onNotify()}},re=b=>{const P=lt(b);if(P<=0){e.onSpeakingDone(),e.onNotify();return}o=!0,d=performance.now(),e.onSpeakingStart(),e.onNotify(),V();const H=w>0?P/w:P;m=setTimeout(()=>{f||(o=!1,m=null,e.onSpeakingDone(),e.onNotify())},H)},O=(b,P,H,le)=>{P.length!==0&&(c=H,P.forEach(j=>{const p=String(j.word??"").trim();if(!p)return;const S=Math.round((j.start??0)*1e3),x=j.duration!=null?Math.round(j.duration*1e3):j.end!=null?Math.max(1,Math.round((j.end-(j.start??0))*1e3)):0;b.push({word:p,wtime:c+S,wduration:x,queueIndex:b.length,gesture:j.gesture??null,emphasis:j.emphasis===!0})}))},J=(b,P,H,le,j,q)=>{H.length!==0&&(c=le,H.forEach(p=>{const S=String(p.symbol??p.viseme??"").trim();if(!S)return;const x=Math.round((p.start??0)*1e3),_=Math.max(1,Math.round((p.duration??0)*1e3)),U=c+x,Z=Fi(P,U),te=Z?_i(Z,U):0;let z;ai(q)==="oculus_direct"?(z=mn(S),z==="U"&&Z&&hn(Z.word,te)&&(z="FF")):z=bi(S,Z?.word??"",te),b.push({viseme:z,weight:1,vtime:U,vduration:_})}),e.onNotify())},W=(b,P,H,le,j,q,p)=>{O(P,le,j),J(b,P,H,j,q,p)},he=(b,P,H)=>{ie===b&&b.visemes===P||(P.length=0,H.length=0,b.visemes=P,b.words=H,b.segmentOffsetMs=0,ie=b,c=0,D=0)},K=async()=>{const b=window.AudioContext||window.webkitAudioContext;return i||(i=new b),i.state==="suspended"&&await i.resume(),E||(E=i.createMediaStreamDestination()),i},ee=(b,P)=>{if(!i)return 0;const H=i,le=H.currentTime,j=le+.02;if(P.isFirstAudio){l<=0&&(l=j);const p=(j-le)*1e3;d=performance.now()+p}P.onBeforeStart?.(j);const q=H.createBufferSource();return q.buffer=b,q.playbackRate.value=w,q.connect(H.destination),E&&q.connect(E),r.push(q),f?(r.pop(),j):(P.isFirstAudio&&(o=!0,e.onSpeakingStart()),q.onended=()=>{const p=r.indexOf(q);p>=0&&r.splice(p,1),e.onNotify(),!f&&(L&&A?$(L,A):se())},q.start(j),j)},$=async(b,P)=>{if(f||s||r.length>0)return;if(n.length===0){se();return}s=!0;let H=!1;try{const le=await K();if(f)return;const j=n[0];if(!j)return;const q=!o;if(B&&(e.shouldHoldForWarmup?.()??!1)&&(v||q&&j.newStream)||v){he(j.utterance,b,P);for(const x of n){if(f)return;x.audioBuffer||(x.audioBuffer=await Mr(le,x.audio,x.sampleRate)),a=!0,v||(v=!0,k=0,x.newStream&&x.onNewStream?.()),x.visemesQueued||(W(b,P,x.visemes,x.words,k,!0,T),x.visemesQueued=!0,k+=Math.round(x.audioBuffer.duration*1e3),D=Math.max(D,lt(b)))}e.onNotify();return}const S=n.shift();if(!S||(S.audioBuffer||(S.audioBuffer=await Mr(le,S.audio,S.sampleRate)),f))return;a=!0,V(),he(S.utterance,b,P),S.visemesQueued=!1,S.newStream&&S.onNewStream?.(),ee(S.audioBuffer,{isFirstAudio:!o,isFirstOfStream:!1,onBeforeStart:x=>{l=x,c=0,d=performance.now()+(x-le.currentTime)*1e3,b.length=0,P.length=0,W(b,P,S.visemes,S.words,0,!0,T),S.visemesQueued=!0,S.utterance.segmentOffsetMs=0}}),H=r.length>0,D=lt(b),e.onNotify()}catch(le){console.error("[avatarChunkPlayback] audio chunk failed:",le)}finally{if(s=!1,f)return;if(v){n.some(j=>!j.audioBuffer||!j.visemesQueued)&&$(b,P);return}!H&&r.length===0&&n.length>0?$(b,P):r.length===0&&n.length===0&&se()}};return{setStreamTtsEngineId:b=>{T=b},setPlaybackSpeed:b=>{w=Math.max(.1,Math.min(1,b)),ae()},getPlaybackSpeed:()=>w,setLipsyncWarmupHoldEnabled:b=>{B=b,b||I()},isWarmingUp:()=>v,releaseWarmupHold:()=>{if(v){v=!1,k=0;for(const b of n)b.newStream=!1;L&&A&&$(L,A),e.onNotify()}},resetForNewStream:b=>{f=!1,u=!1,T=b,D=0},resumeBotStream:()=>{f=!1,u=!1},clearAborted:()=>{f=!1},primeAudioContext:async()=>{const b=window.AudioContext||window.webkitAudioContext;i||(i=new b),i.state==="suspended"&&await i.resume(),i&&!E&&(E=i.createMediaStreamDestination())},stop:()=>{f=!0,V(),G(),n.length=0,s=!1,o=!1,a=!1,u=!1,c=0,l=0,d=0,D=0,L=null,A=null,ie=null,I()},markStreamComplete:b=>{if(D=Math.max(D,lt(b)),u=!0,!a&&b.length>0){re(b);return}se()},playAudioChunk:async(b,P,H,le,j,q,p)=>{if(f)return;L=b,A=P;const S=Bi(p?.sampleRate),x=p?.newStream===!0,_=de();if(!H?.trim()){if(le.length===0&&j.length===0)return;he(_,b,P),x&&p?.onNewStream?.(),W(b,P,le,j,0,!0,T),D=lt(b),!o&&D>0&&re(b),e.onNotify();return}n.push({audio:H,audioBuffer:null,utterance:_,visemes:le,words:j,isNewSegment:q,sampleRate:S,newStream:x,onNewStream:p?.onNewStream,visemesQueued:!1}),await $(b,P)},queueTimingsOnly:(b,P,H,le,j,q)=>{if(f)return;const p=de();he(p,b,P),W(b,P,H,le,0,!0,T),p.segmentOffsetMs=0,D=lt(b)},getPlaybackElapsedMs:()=>a&&i&&l>0?Math.max(0,(i.currentTime-l)*1e3*w):o?Math.max(0,(performance.now()-d)*w):0,isSpeaking:()=>o?!0:!a||!i||l<=0?!1:(i.currentTime-l)*1e3<D,getVoiceStream:()=>E?E.stream:null,getPlaybackStartPerf:()=>d,bargeIn:()=>{f=!0,u=!1,V(),G(),n.length=0,s=!1,o=!1,a=!1,c=0,l=0,d=0,D=0,L=null,A=null,ie=null,I()},interrupt:()=>{f=!0,u=!1,V(),G(),n.length=0,s=!1,o=!1,a=!1,c=0,l=0,d=0,D=0,L=null,A=null,ie=null,I()}}}function zt(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 Oi(e,t,n=120){const r=zt(e,t);if(r!=="sil")return r;let i=null;for(const s of e){if(s.vtime>t)break;const o=s.vtime+s.vduration;o<=t&&t-o<=n&&(i=s)}return i?.viseme??"sil"}function aa(e,t,n=400){const r=t-n;let i=0;for(const s of e)if(s.vtime+s.vduration<r)i+=1;else break;i>0&&e.splice(0,i)}function oa(e,t){for(const n of e)if(t>=n.wtime&&t<n.wtime+n.wduration)return n;return null}function Pr(e,t){const n=e.trim();if(!n)return null;try{const r=n.replace(/\s+/g,""),i=atob(r).length,s=Number.isFinite(t)&&(t??0)>0?Number(t):16e3;return i/2/s*1e3}catch{return null}}const pn=.5,yn=1.5,er="Olivia",tr="f786b574-daa5-4673-aa0c-cbe3e8534c02",Ht=.85;function Nn(e,t=ht,n={}){const r=`${t.replace(/\/$/,"")}/avatar_ttsWithPoses`,i=[],s=[],o=[],a=[];let u=0;const d=[],l=[];let c="",m="neutral",w="",T=dt;const f=new Set;let E=0,D=null,B=0,v=null;const k=()=>f.forEach(O=>O());let L=()=>!1;const A=Li({onSpeakingStart:()=>e("speaking"),onSpeakingDone:()=>e("done"),onNotify:k,shouldHoldForWarmup:()=>L()},dt),ie=()=>A.getPlaybackElapsedMs(),de=(O,J=c)=>{if(!n.onLipsyncDebug)return;const W=ie(),he=i,K=wn(o).map(ee=>({viseme:ee.viseme,vtimeMs:ee.vtime}));n.onLipsyncDebug({event:O,spokenText:J,mood:m,playbackAnchorPerf:A.getPlaybackStartPerf(),playbackElapsedMs:W,queueLength:he.length,activeViseme:zt(he,W),segments:l.map(ee=>({...ee,visemes:[...ee.visemes]})),fullQueueLength:o.length,compactionSkipped:K})},I=(O,J)=>{n.onLipsyncDebug&&(D={event:O,spokenText:J},E===0&&(E=requestAnimationFrame(()=>{E=0;const W=D;D=null,W&&de(W.event,W.spokenText)})))},V=(O,J,W,he,K)=>{if(!n.onLipsyncDebug)return;const ee=i.slice(J),$=W.filter(X=>String(X.symbol??X.viseme??"").trim());l.push({spokenText:O,audioOffsetMs:ee[0]?.vtime??0,isNewSegment:he,chunkDurationMs:K,receivedAtMs:performance.now(),visemes:ee.map((X,_e)=>{const oe=$[_e];return{rawSymbol:String(oe?.symbol??oe?.viseme??X.viseme).trim(),viseme:X.viseme,startSec:Number(oe?.start??0),durationSec:Number(oe?.duration??0),vtimeMs:X.vtime,vdurationMs:X.vduration}})})},G=()=>{o.length=0,a.length=0,u=0},ae=(O,J,W,he,K)=>{if(O.length===0&&J.length===0)return;Ri(o,a,O,J,u,K);const ee=Di(O,u),$=W?Pr(W,he):null;u=Math.max(ee,$!=null?u+$:u)},se=()=>{B+=1,v?.abort(),v=null,A.stop(),i.length=0,s.length=0,G(),d.length=0,m="neutral",l.length=0,c="",e("idle"),I("reset"),k()};return{setDeveloperToken:O=>{w=O},setTtsEngineId:O=>{T=O},getTtsEngineId:()=>T,speak:async(O,J)=>{se();const W=B;v=new AbortController,e("loading"),c=O,l.length=0,G();const he=w.trim();if(!he)throw new Error("Developer token required for avatar_ttsWithPoses");const K=et(J?.ttsEngineId,J?.voiceId),ee=K.ttsEngineId??T??dt;A.resetForNewStream(ee),A.setStreamTtsEngineId(ee);const $=K.voiceId??(ee===nt?dn:er),X=J?.speakingRate??Ht,_e=Math.max(pn,Math.min(yn,X)),oe={user_query:O,ttsEngineId:ee,speakingRate:_e,tenant:"aiTwin"};ii.has(ee)&&(oe.voice_id=$);const b=fn(J?.language);b&&(oe.language=b);try{const P=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${he}`},body:JSON.stringify(oe),signal:v.signal});if(!P.ok)throw new Error(`avatar_ttsWithPoses failed (${P.status})`);const H=P.body;if(!H)throw new Error("No response body");const le=H.getReader(),j=new TextDecoder;let q="",p=!0;const S=async x=>{if(W!==B)return;const _=yi(x);if(_){if(_.event==="audio"){const U=_.data.chunk,Z=_.data.visemes??[],te=_.data.words??[],z=_.data.is_new_segment??!1,be=_.data.sample_rate,Xe=Number(_.data.audio_offset_ms??0),Pt=i.length;if(ae(Z,te,U,be,ee),U){const pt=p;p=!1,await A.playAudioChunk(i,s,U,Z,te,z,{sampleRate:be,newStream:pt,audioOffsetMs:Xe}),V(O,Pt,Z,z,Pr(U,be)),I("audio_chunk",O)}else(Z.length>0||te.length>0)&&(A.queueTimingsOnly(i,s,Z,te,z,{audioOffsetMs:Xe,newStream:p}),V(O,Pt,Z,z,null),I("audio_chunk",O))}else if(_.event==="metadata"){const U=_.data.mood;typeof U=="string"&&U.trim()&&(m=U.trim());const Z=_.data.sentence_emotions;if(Array.isArray(Z)){d.length=0;for(const te of Z){if(!te||typeof te!="object")continue;const z=te;d.push({sentence_index:Number(z.sentence_index??0),text:String(z.text??""),sentiment:typeof z.sentiment=="string"?z.sentiment:void 0,emotion:String(z.emotion??m),start_word:Number(z.start_word??0),end_word:Number(z.end_word??0)})}}k(),I("metadata",O)}else if(_.event==="error")throw new Error(String(_.data.message??"avatar_ttsWithPoses stream error"))}};for(;W===B;){const{done:x,value:_}=await le.read();_&&(q+=j.decode(_,{stream:!0}));const U=q.split(`
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const D=require("react/jsx-runtime"),h=require("react"),us=require("@pipecat-ai/client-js"),Kn=require("@pipecat-ai/websocket-transport"),ge=require("pixi.js");var An=typeof document<"u"?document.currentScript:null;const ds="https://aitwin.bubu.social",si={publicBase:ds},fs="0.6.8",ms={version:fs},hs={},Pt="https://ai.aitwin.me",Gn=`${si.publicBase}/custom-faces`,gs=`${si.publicBase}/aitwin-workers/v${ms.version}/visemeDiffPreview.worker.js`;function ps(e){if(e)return e;const t=typeof{url:typeof document>"u"?require("url").pathToFileURL(__filename).href:An&&An.tagName.toUpperCase()==="SCRIPT"&&An.src||new URL("aitwin.cjs",document.baseURI).href}<"u"?hs?.VITE_AITWIN_WORKER_URL:void 0;return t?.trim()?t.trim():gs}const ws="https://us-central1-streamoji-265f4.cloudfunctions.net/getAiTwin",Mn=3e3,Ft=16,Ir=3e3,ys=4e3,vs=.85,_s=8,qn=400,Yn="eng_a7f2b9c1",ln="eng_d4e8f3a2",nt="eng_c9b1e6d4",rt="visemetts",mt=nt,un="eve",Fn=new Set([ln,nt,rt]),Qn={[Yn]:"oculus_direct",[nt]:"oculus_direct",[rt]:"oculus_direct",[ln]:"inworld_word"},Ln={google:Yn,inworld:ln,cartesia:nt,visemetts:rt};function bs(e){const t=e.trim();if(t)return t in Qn?t:Ln[t.toLowerCase()]}function ai(e){const t=e?.trim();if(!t)return{};const n=t.indexOf(":");if(n<=0)return{voiceId:t};const r=bs(t.slice(0,n));if(!r)return{voiceId:t};const i=t.slice(n+1).trim();return{ttsEngineId:r,voiceId:i||void 0}}function tt(e,t){const n=ai(t);return{ttsEngineId:e??n.ttsEngineId,voiceId:n.voiceId}}function oi(e){return Qn[e]}function Ss(e){return e===nt}function ci(e){return e===rt}function Ts(e){if(e.ttsEngineId&&e.ttsEngineId in Qn)return e.ttsEngineId;const t=e.tts?.toLowerCase();return t&&t in Ln?Ln[t]:mt}class tn extends Error{constructor(t="AI twin not found"){super(t),this.name="AiTwinNotFoundError"}}function Xn(e,...t){const n=typeof e=="string"?e:e?.brainId?.trim()||e?.knowledgeContextId?.trim();for(const r of[n,...t]){const i=r?.trim();if(i)return i}}function Jn(e,...t){const n=typeof e=="string"?e:e?.brainUrl?.trim();for(const r of[n,...t]){const i=r?.trim();if(i)return i}}function ks(e){const t=(e??"").trim();if(!t)return;let n;try{n=new URL(t)}catch{throw new Error("brainUrl must be an http or https URL")}if(n.protocol!=="http:"&&n.protocol!=="https:")throw new Error("brainUrl must be an http or https URL");if(!n.host)throw new Error("brainUrl must be an http or https URL");if(n.hash)throw new Error("brainUrl must not include a fragment");return t}async function li(e,t=ws){const n=new URL(t);n.searchParams.set("id",e);const r=await fetch(n.toString());if(r.status===404)throw new tn;if(!r.ok)throw new Error(`getAiTwin failed (${r.status})`);const i=await r.json();if(!i.success)throw new tn(i.error??"AI twin not found");const{tts:s,token:o,...a}=i.data,u=String(a.authToken??o??"").trim()||void 0,d=Xn(a),l=Jn(a);return{...a,ttsEngineId:Ts(i.data),authToken:u,brainId:d,knowledgeContextId:d,brainUrl:l}}const Zn="thumbnail.webp";function ui(e,t=Gn){const n=e.trim();if(!n)throw new Error("faceId is required");return`${t.replace(/\/$/,"")}/${n}/${Zn}`}function Ar(e){const t=e?.trim();if(!t)return null;try{return ui(t)}catch{return null}}function Es(e){if(!e)return null;const t=(e.binBase||e.twinBase).trim().replace(/\/$/,"");return t?`${t}/${Zn}`:null}const xs="https://us-central1-streamoji-265f4.cloudfunctions.net/getAuthToken",Is="client_6TNvp3SCs4Og0a1ijm9TommXLql1",As="kk8Fq8EmexzP10jMIEwY3R44M5RKUEm1",Ms="6TNvp3SCs4Og0a1ijm9TommXLql1",Rs="Swaraj Mali";async function en(){const e=await fetch(xs,{method:"POST",headers:{"Content-Type":"application/json","Client-Id":Is,"Client-Secret":As},body:JSON.stringify({userId:Ms,userName:Rs})});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 Ps(e,t=Pt){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 Cs(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 Yt(e){return Uint8Array.from(e)}function Ds(e,t){const n=new Uint8Array(e.length+t.length);return n.set(e,0),n.set(t,e.length),n}async function Bs(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=Yt(n.subarray(0,12)),i=Yt(n.subarray(12,28)),s=Yt(n.subarray(28)),o=Yt(Ds(s,i)),a=await crypto.subtle.importKey("raw",Cs(t),{name:"AES-GCM"},!1,["decrypt"]);return crypto.subtle.decrypt({name:"AES-GCM",iv:r,tagLength:128},a,o)}let On=null;const Nn=new Set;function Qt(e){return e.includes("/custom-faces/")}function nn(e){const t=e.binBase.trim().replace(/\/$/,""),n=e.twinBase.trim().replace(/\/$/,"");if(!(e.encrypted||Qt(t)||Qt(n)))return{twinBase:n,binBase:t,encrypted:!1};const i=Qt(t)?t:Qt(n)?n:t;return{twinBase:i,binBase:i,encrypted:!0}}function pt(e){return nn(e).encrypted}function Un(e,t=Gn){const n=`${t.replace(/\/$/,"")}/${e}`;return{twinBase:n,binBase:n,encrypted:!0}}function di(e,t){return(e??t)?.trim()||void 0}function fi(e){On=nn(e);for(const t of Nn)t()}function Fs(e,t){const n=typeof globalThis.location<"u"?globalThis.location.href:void 0;if(!n)return nn(e);const r=i=>{try{return new URL(i,n).href.replace(/\/$/,"")}catch{return i}};return nn({twinBase:r(e.twinBase),binBase:r(e.binBase),encrypted:e.encrypted})}function wt(){if(!On)throw new Error("Twin assets not configured; call setActiveTwinAssets first");return On}function mi(e){return Nn.add(e),()=>Nn.delete(e)}function rn(){const e=wt();return pt(e)?`${e.binBase}/sil.bin`:`${e.twinBase}/sil.png`}function Ls(){const e=wt();return pt(e)?`${e.binBase}/idle.bin`:`${e.twinBase}/idle.mp4`}function hi(){const e=wt();return pt(e)?e.binBase:e.twinBase}function Nt(){return pt(wt())}function gi(){const e=wt();return pt(e)?`${e.binBase}/atlas.bin`:`${e.twinBase}/atlas.json`}function pi(){const e=wt();return pt(e)?`${e.binBase}/expression_atlas.bin`:`${e.twinBase}/expression_atlas.json`}const ht=[{code:"en",label:"English",visemetts:!0,cartesia:!0},{code:"es",label:"Spanish",visemetts:!0,cartesia:!0},{code:"es-MX",label:"Spanish (Mexico)",visemetts:!0,cartesia:!0},{code:"es-ES",label:"Spanish (Spain)",visemetts:!0,cartesia:!0},{code:"pt",label:"Portuguese",visemetts:!0,cartesia:!0},{code:"pt-BR",label:"Portuguese (Brazil)",visemetts:!0,cartesia:!0},{code:"pt-PT",label:"Portuguese (Portugal)",visemetts:!0,cartesia:!0},{code:"fr",label:"French",visemetts:!0,cartesia:!0},{code:"de",label:"German",visemetts:!0,cartesia:!0},{code:"it",label:"Italian",visemetts:!0,cartesia:!0},{code:"zh",label:"Chinese",visemetts:!0,cartesia:!0},{code:"ja",label:"Japanese",visemetts:!0,cartesia:!0},{code:"hi",label:"Hindi",visemetts:!0,cartesia:!0},{code:"ko",label:"Korean",visemetts:!0,cartesia:!0},{code:"ru",label:"Russian",visemetts:!0,cartesia:!0},{code:"tr",label:"Turkish",visemetts:!0,cartesia:!0},{code:"id",label:"Indonesian",visemetts:!0,cartesia:!0},{code:"ar",label:"Arabic",visemetts:!0,cartesia:!0},{code:"ar-EG",label:"Arabic (Egypt)",visemetts:!0,cartesia:!0},{code:"ar-AE",label:"Arabic (UAE)",visemetts:!0,cartesia:!0},{code:"vi",label:"Vietnamese",visemetts:!0,cartesia:!0},{code:"bn",label:"Bengali",visemetts:!0,cartesia:!0},{code:"auto",label:"Auto-detect",visemetts:!0,cartesia:!1},{code:"nl",label:"Dutch",visemetts:!1,cartesia:!0},{code:"pl",label:"Polish",visemetts:!1,cartesia:!0},{code:"sv",label:"Swedish",visemetts:!1,cartesia:!0},{code:"tl",label:"Tagalog",visemetts:!1,cartesia:!0},{code:"bg",label:"Bulgarian",visemetts:!1,cartesia:!0},{code:"ro",label:"Romanian",visemetts:!1,cartesia:!0},{code:"cs",label:"Czech",visemetts:!1,cartesia:!0},{code:"el",label:"Greek",visemetts:!1,cartesia:!0},{code:"fi",label:"Finnish",visemetts:!1,cartesia:!0},{code:"hr",label:"Croatian",visemetts:!1,cartesia:!0},{code:"ms",label:"Malay",visemetts:!1,cartesia:!0},{code:"sk",label:"Slovak",visemetts:!1,cartesia:!0},{code:"da",label:"Danish",visemetts:!1,cartesia:!0},{code:"ta",label:"Tamil",visemetts:!1,cartesia:!0},{code:"uk",label:"Ukrainian",visemetts:!1,cartesia:!0},{code:"hu",label:"Hungarian",visemetts:!1,cartesia:!0},{code:"no",label:"Norwegian",visemetts:!1,cartesia:!0},{code:"th",label:"Thai",visemetts:!1,cartesia:!0},{code:"he",label:"Hebrew",visemetts:!1,cartesia:!0},{code:"ka",label:"Georgian",visemetts:!1,cartesia:!0},{code:"te",label:"Telugu",visemetts:!1,cartesia:!0},{code:"gu",label:"Gujarati",visemetts:!1,cartesia:!0},{code:"kn",label:"Kannada",visemetts:!1,cartesia:!0},{code:"ml",label:"Malayalam",visemetts:!1,cartesia:!0},{code:"mr",label:"Marathi",visemetts:!1,cartesia:!0},{code:"pa",label:"Punjabi",visemetts:!1,cartesia:!0}],wi=ht.map(e=>e.code),Os=new Set(wi),Ns=new Set(ht.filter(e=>e.visemetts).map(e=>e.code)),Us=new Set(ht.filter(e=>e.cartesia).map(e=>e.code)),Vs="en";function yi(e){return Os.has(e)}function dn(e){const t=e?.trim();if(t)return t}function Ws(e){return e===rt?ht.filter(t=>t.visemetts).map(t=>t.code):e===nt?ht.filter(t=>t.cartesia).map(t=>t.code):ht.filter(t=>t.visemetts&&t.cartesia).map(t=>t.code)}function zs(e,t){const n=t.trim();return n?e===rt?Ns.has(n):e===nt?Us.has(n):yi(n):!1}function vi(e){const t=e.split(/\r?\n/);let n="",r="";for(const s of t)s.startsWith("event:")?n=s.slice(6).trim():s.startsWith("data:")&&(r=s.slice(5).trim());if(!n)return null;let i={};if(r)try{i=JSON.parse(r)}catch{i={raw:r}}return{event:n,data:i}}const _i=["aa","CH","DD","E","FF","I","O","PP","RR","SS","TH","U","kk","nn","sil"],Hs=new Map(_i.map(e=>[e.toLowerCase(),e]));function fn(e){const t=(e??"").trim();return t?Hs.get(t.toLowerCase())??"sil":"sil"}const $s={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 js(e){if(!e)return["sil"];const t=e.toLowerCase();return $s[t]??["sil"]}function bi(e,t){const n=e.word.length;if(n<=0)return 0;const r=e.wduration;if(r<=0)return 0;const i=Math.max(0,Math.min(1,(t-e.wtime)/r));return Math.min(n-1,Math.floor(i*n))}function It(e,t){const n=Math.max(0,Math.min(e.length-1,t));return e[n]??""}function mn(e,t){const n=e.toLowerCase().replace(/[^a-z']/g,"");return!n||It(n,t)!=="w"||t>0&&It(n,t-1)==="q"?!1:t===0&&/^w[aeiouy]/.test(n)}function Ks(e,t){const n=e.toLowerCase(),r=It(n,t),i=n.slice(Math.max(0,t-1),t+2);return r==="i"||r==="y"?"I":i.includes("ee")||r==="e"||n.includes("ea")?"E":"aa"}function Gs(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";if(mn(n,t))return"FF";const i=It(n,t);return i==="u"||i==="w"?"U":"O"}function qs(e,t){const n=e.toLowerCase();if(mn(n,t))return"FF";const r=n.slice(Math.max(0,t-2),t+1);if(/qu/.test(r))return"U";const i=n.slice(Math.max(0,t-1),Math.min(n.length,t+3));return/wo|wh/.test(i)||It(n,t)==="o"?"O":"U"}const Xt={d:"DD",t:"DD",n:"DD",s:"SS",z:"SS",k:"kk",g:"kk",c:"CH",x:"CH",j:"CH"};function Ys(e,t){const n=e.toLowerCase(),r=It(n,t);if(Xt[r])return Xt[r];for(let i=0;i<n.length;i++){const s=n[i];if(Xt[s])return Xt[s]}return"DD"}function Si(e,t,n){const r=js(e);if(r.length===1)return r[0];const i=t.trim();if(!i)return r[0];const s=(e??"").toLowerCase(),o=Math.max(0,n);switch(s){case"aei":return Ks(i,o);case"o":return Gs(i,o);case"qw":return qs(i,o);case"cdgknstxyz":return Ys(i,o);default:return r[0]}}const er=16,Vn=47,Ti=new Set(["aa","E","I"]),ki=new Set(["DD","SS","kk","CH"]),Qs=[Ti,ki];function Xs(e){for(const t of Qs)if(t.has(e))return t;return null}function Js(e){return Xs(e)!=null}function Ei(e,t=er){return t<=0?e:Math.round(e/t)*t}function tr(e,t=er){return e.map(n=>({...n,vtime:Ei(n.vtime,t)}))}function xi(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 nr(e){if(e.length<=2)return[...e];const t=[e[0]];for(let n=1;n<e.length-1;n++){const r=e[n],i=e[n+1],s=t[t.length-1];if(!Js(r.viseme)){t.push(r);continue}const o=r.vtime-s.vtime,a=i.vtime-r.vtime;o<Vn||a<Vn||t.push(r)}return t.push(e[e.length-1]),t}function hn(e){return nr(xi(tr(e)))}function Ii(e,t){let n="sil";for(const r of e){if(r.vtime>t)break;r.viseme!=="sil"&&(n=r.viseme)}return n}function gn(e){const t=xi(tr(e)),n=nr(t),r=new Set(n.map(s=>s.vtime)),i=[];for(const s of t)r.has(s.vtime)||i.push({viseme:s.viseme,vtime:s.vtime});return i}function Zs(e){return gn(e).map(t=>t.viseme)}const ea=32,Mr=48;function Ai(e){let t=0;for(const n of e)t=Math.max(t,n.vtime+n.vduration);return t}function Mi(e){let t=null,n=-1;for(const r of e){if(r.viseme==="sil")continue;const i=r.vtime+r.vduration;i>n&&(t=r,n=i)}return t}function ta(e){return hn(e).find(n=>n.viseme!=="sil")??null}function dt(e){const t=Ai(e);return Mi(e)?t+qn:t}function na(e){const t=[],n=ta(e);n&&n.vtime>0&&t.push({from:"sil",to:n.viseme,fromVtime:0,toVtime:n.vtime});const r=Mi(e),i=Ai(e);return r&&t.push({from:r.viseme,to:"sil",fromVtime:i,toVtime:i+qn}),t}function Ri(e){const t=hn(e),n=[];for(let r=0;r<t.length-1;r++){const i=t[r].viseme,s=t[r+1].viseme,o=t[r].vtime,a=t[r+1].vtime;i===s||a<=o||n.push({from:i,to:s,fromVtime:o,toVtime:a})}return n}function Pi(e){return e.length===0?[]:[...na(e),...Ri(e)]}function ra(e,t){let n=null;for(const r of e){const{transStart:i,transEnd:s}=Ci(r.fromVtime,r.toVtime,r.from,r.to);t>=i&&t<s&&(n=r)}return n}function Ci(e,t,n,r){const i=Math.max(0,t-e);if((n==="PP"||r==="PP")&&i>Mr){const d=Mr,l=t,c=l-d;return{gapMs:i,effectiveGapMs:d,holdEnd:c,transStart:c,transEnd:l}}const o=i>0?Math.max(i,ea):0,a=e,u=e+o;return{gapMs:i,effectiveGapMs:o,holdEnd:e,transStart:a,transEnd:u}}function Di(e,t,n,r,i,s){r.forEach(o=>{const u=String(o.word??"").trim();if(!u)return;const d=Math.round((o.start??0)*1e3),l=o.duration!=null?Math.round(o.duration*1e3):o.end!=null?Math.max(1,Math.round((o.end-(o.start??0))*1e3)):0;t.push({word:u,wtime:i+d,wduration:l,queueIndex:t.length,gesture:o.gesture??null,emphasis:o.emphasis===!0})}),n.forEach(o=>{const a=String(o.symbol??o.viseme??"").trim();if(!a)return;const u=Math.round((o.start??0)*1e3),d=Math.max(1,Math.round((o.duration??0)*1e3)),l=i+u,c=Li(t,l),m=c?bi(c,l):0;let p;oi(s)==="oculus_direct"?(p=fn(a),p==="U"&&c&&mn(c.word,m)&&(p="FF")):p=Si(a,c?.word??"",m),e.push({viseme:p,weight:1,vtime:l,vduration:d})})}function Bi(e,t){let n=t;for(const r of e){const i=Math.round((r.start??0)*1e3),s=Math.max(1,Math.round((r.duration??0)*1e3));n=Math.max(n,t+i+s)}return n}const rr=16e3;function Fi(e){const t=Number(e);return Number.isFinite(t)&&t>0?t:rr}function ia(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}function sa(e){return e.length>=4&&e[0]===82&&e[1]===73&&e[2]===70&&e[3]===70}function Rr(e,t,n=rr){const r=t.byteOffset%2===0?t:t.slice(),i=new Int16Array(r.buffer,r.byteOffset,r.byteLength/2),s=new Float32Array(i.length);for(let a=0;a<i.length;a++)s[a]=i[a]>=32768?-(65536-i[a])/32768:i[a]/32767;const o=e.createBuffer(1,s.length,n);return o.copyToChannel(s,0),o}function aa(e){const t=ia(e),n=window.atob(t),r=new Uint8Array(n.length);for(let i=0;i<n.length;i++)r[i]=n.charCodeAt(i);return r}async function Pr(e,t,n=rr){const r=aa(t),i=Fi(n);if(sa(r)){const s=r.buffer.slice(r.byteOffset,r.byteOffset+r.byteLength);return e.decodeAudioData(s)}if(r.length>=2&&r.length%2===0)return Rr(e,r,i);try{const s=r.buffer.slice(r.byteOffset,r.byteOffset+r.byteLength);return await e.decodeAudioData(s)}catch{return Rr(e,r,i)}}function Li(e,t){for(const n of e)if(t>=n.wtime&&t<n.wtime+n.wduration)return n;return null}function Oi(e,t){const n=[],r=[];let i=null,s=!1,o=!1,a=!1,u=!1,d=0,l=0,c=0,m=null,p=1,T=t,f=!1,I=null,F=0,L=!1,b=!1,k=0,V=null,C=null,ae=null;const fe=()=>({visemes:[],words:[],segmentOffsetMs:0}),M=()=>{b=!1,k=0},z=()=>{m!=null&&(clearTimeout(m),m=null)},Y=()=>{for(const y of r){try{y.onended=null,y.stop(0)}catch{}try{y.disconnect()}catch{}}r.length=0},ce=()=>{for(const y of r)y.playbackRate.value=p},oe=()=>{if(!(f||!u||s||b||r.length>0||n.length>0)){if(a&&i&&l>0){const y=(i.currentTime-l)*1e3;if(y<F){z();const O=p>0?(F-y)/p:F-y;m=setTimeout(()=>{f||(o=!1,m=null,e.onSpeakingDone(),e.onNotify())},Math.max(0,O));return}}o=!1,z(),e.onSpeakingDone(),e.onNotify()}},re=y=>{const O=dt(y);if(O<=0){e.onSpeakingDone(),e.onNotify();return}o=!0,d=performance.now(),e.onSpeakingStart(),e.onNotify(),z();const N=p>0?O/p:O;m=setTimeout(()=>{f||(o=!1,m=null,e.onSpeakingDone(),e.onNotify())},N)},le=(y,O,N,G)=>{O.length!==0&&(c=N,O.forEach($=>{const _=String($.word??"").trim();if(!_)return;const w=Math.round(($.start??0)*1e3),S=$.duration!=null?Math.round($.duration*1e3):$.end!=null?Math.max(1,Math.round(($.end-($.start??0))*1e3)):0;y.push({word:_,wtime:c+w,wduration:S,queueIndex:y.length,gesture:$.gesture??null,emphasis:$.emphasis===!0})}))},pe=(y,O,N,G,$,ee)=>{N.length!==0&&(c=G,N.forEach(_=>{const w=String(_.symbol??_.viseme??"").trim();if(!w)return;const S=Math.round((_.start??0)*1e3),j=Math.max(1,Math.round((_.duration??0)*1e3)),te=c+S,E=Li(O,te),K=E?bi(E,te):0;let J;oi(ee)==="oculus_direct"?(J=fn(w),J==="U"&&E&&mn(E.word,K)&&(J="FF")):J=Si(w,E?.word??"",K),y.push({viseme:J,weight:1,vtime:te,vduration:j})}),e.onNotify())},ie=(y,O,N,G,$,ee,_)=>{le(O,G,$),pe(y,O,N,$,ee,_)},W=(y,O,N)=>{ae===y&&y.visemes===O||(O.length=0,N.length=0,y.visemes=O,y.words=N,y.segmentOffsetMs=0,ae=y,c=0,F=0)},A=async()=>{const y=window.AudioContext||window.webkitAudioContext;return i||(i=new y),i.state==="suspended"&&await i.resume(),I||(I=i.createMediaStreamDestination()),i},Q=(y,O)=>{if(!i)return 0;const N=i,G=N.currentTime,$=G+.02;if(O.isFirstAudio){l<=0&&(l=$);const _=($-G)*1e3;d=performance.now()+_}O.onBeforeStart?.($);const ee=N.createBufferSource();return ee.buffer=y,ee.playbackRate.value=p,ee.connect(N.destination),I&&ee.connect(I),r.push(ee),f?(r.pop(),$):(O.isFirstAudio&&(o=!0,e.onSpeakingStart()),ee.onended=()=>{const _=r.indexOf(ee);_>=0&&r.splice(_,1),e.onNotify(),!f&&(V&&C?R(V,C):oe())},ee.start($),$)},R=async(y,O)=>{if(f||s||r.length>0)return;if(n.length===0){oe();return}s=!0;let N=!1;try{const G=await A();if(f)return;const $=n[0];if(!$)return;const ee=!o;if(L&&(e.shouldHoldForWarmup?.()??!1)&&(b||ee&&$.newStream)||b){W($.utterance,y,O);for(const S of n){if(f)return;S.audioBuffer||(S.audioBuffer=await Pr(G,S.audio,S.sampleRate)),a=!0,b||(b=!0,k=0,S.newStream&&S.onNewStream?.()),S.visemesQueued||(ie(y,O,S.visemes,S.words,k,!0,T),S.visemesQueued=!0,k+=Math.round(S.audioBuffer.duration*1e3),F=Math.max(F,dt(y)))}e.onNotify();return}const w=n.shift();if(!w||(w.audioBuffer||(w.audioBuffer=await Pr(G,w.audio,w.sampleRate)),f))return;a=!0,z(),W(w.utterance,y,O),w.visemesQueued=!1,w.newStream&&w.onNewStream?.(),Q(w.audioBuffer,{isFirstAudio:!o,isFirstOfStream:!1,onBeforeStart:S=>{l=S,c=0,d=performance.now()+(S-G.currentTime)*1e3,y.length=0,O.length=0,ie(y,O,w.visemes,w.words,0,!0,T),w.visemesQueued=!0,w.utterance.segmentOffsetMs=0}}),N=r.length>0,F=dt(y),e.onNotify()}catch(G){console.error("[avatarChunkPlayback] audio chunk failed:",G)}finally{if(s=!1,f)return;if(b){n.some($=>!$.audioBuffer||!$.visemesQueued)&&R(y,O);return}!N&&r.length===0&&n.length>0?R(y,O):r.length===0&&n.length===0&&oe()}};return{setStreamTtsEngineId:y=>{T=y},setPlaybackSpeed:y=>{p=Math.max(.1,Math.min(1,y)),ce()},getPlaybackSpeed:()=>p,setLipsyncWarmupHoldEnabled:y=>{L=y,y||M()},isWarmingUp:()=>b,releaseWarmupHold:()=>{if(b){b=!1,k=0;for(const y of n)y.newStream=!1;V&&C&&R(V,C),e.onNotify()}},resetForNewStream:y=>{f=!1,u=!1,T=y,F=0},resumeBotStream:()=>{f=!1,u=!1},clearAborted:()=>{f=!1},primeAudioContext:async()=>{const y=window.AudioContext||window.webkitAudioContext;i||(i=new y),i.state==="suspended"&&await i.resume(),i&&!I&&(I=i.createMediaStreamDestination())},stop:()=>{f=!0,z(),Y(),n.length=0,s=!1,o=!1,a=!1,u=!1,c=0,l=0,d=0,F=0,V=null,C=null,ae=null,M()},markStreamComplete:y=>{if(F=Math.max(F,dt(y)),u=!0,!a&&y.length>0){re(y);return}oe()},playAudioChunk:async(y,O,N,G,$,ee,_)=>{if(f)return;V=y,C=O;const w=Fi(_?.sampleRate),S=_?.newStream===!0,j=fe();if(!N?.trim()){if(G.length===0&&$.length===0)return;W(j,y,O),S&&_?.onNewStream?.(),ie(y,O,G,$,0,!0,T),F=dt(y),!o&&F>0&&re(y),e.onNotify();return}n.push({audio:N,audioBuffer:null,utterance:j,visemes:G,words:$,isNewSegment:ee,sampleRate:w,newStream:S,onNewStream:_?.onNewStream,visemesQueued:!1}),await R(y,O)},queueTimingsOnly:(y,O,N,G,$,ee)=>{if(f)return;const _=fe();W(_,y,O),ie(y,O,N,G,0,!0,T),_.segmentOffsetMs=0,F=dt(y)},getPlaybackElapsedMs:()=>a&&i&&l>0?Math.max(0,(i.currentTime-l)*1e3*p):o?Math.max(0,(performance.now()-d)*p):0,isSpeaking:()=>o?!0:!a||!i||l<=0?!1:(i.currentTime-l)*1e3<F,getVoiceStream:()=>I?I.stream:null,getPlaybackStartPerf:()=>d,bargeIn:()=>{f=!0,u=!1,z(),Y(),n.length=0,s=!1,o=!1,a=!1,c=0,l=0,d=0,F=0,V=null,C=null,ae=null,M()},interrupt:()=>{f=!0,u=!1,z(),Y(),n.length=0,s=!1,o=!1,a=!1,c=0,l=0,d=0,F=0,V=null,C=null,ae=null,M()}}}function Ut(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 Ni(e,t,n=120){const r=Ut(e,t);if(r!=="sil")return r;let i=null;for(const s of e){if(s.vtime>t)break;const o=s.vtime+s.vduration;o<=t&&t-o<=n&&(i=s)}return i?.viseme??"sil"}function oa(e,t,n=400){const r=t-n;let i=0;for(const s of e)if(s.vtime+s.vduration<r)i+=1;else break;i>0&&e.splice(0,i)}function ca(e,t){for(const n of e)if(t>=n.wtime&&t<n.wtime+n.wduration)return n;return null}function Cr(e,t){const n=e.trim();if(!n)return null;try{const r=n.replace(/\s+/g,""),i=atob(r).length,s=Number.isFinite(t)&&(t??0)>0?Number(t):16e3;return i/2/s*1e3}catch{return null}}const pn=.5,wn=1.5,ir="Olivia",sr="f786b574-daa5-4673-aa0c-cbe3e8534c02",Vt=.85;function Wn(e,t=Pt,n={}){const r=`${t.replace(/\/$/,"")}/avatar_ttsWithPoses`,i=[],s=[],o=[],a=[];let u=0;const d=[],l=[];let c="",m="neutral",p="",T=mt;const f=new Set;let I=0,F=null,L=0,b=null;const k=()=>f.forEach(W=>W());let V=()=>!1;const C=Oi({onSpeakingStart:()=>e("speaking"),onSpeakingDone:()=>e("done"),onNotify:k,shouldHoldForWarmup:()=>V()},mt),ae=()=>C.getPlaybackElapsedMs(),fe=(W,A=c)=>{if(!n.onLipsyncDebug)return;const Q=ae(),R=i,H=gn(o).map(Z=>({viseme:Z.viseme,vtimeMs:Z.vtime}));n.onLipsyncDebug({event:W,spokenText:A,mood:m,playbackAnchorPerf:C.getPlaybackStartPerf(),playbackElapsedMs:Q,queueLength:R.length,activeViseme:Ut(R,Q),segments:l.map(Z=>({...Z,visemes:[...Z.visemes]})),fullQueueLength:o.length,compactionSkipped:H})},M=(W,A)=>{n.onLipsyncDebug&&(F={event:W,spokenText:A},I===0&&(I=requestAnimationFrame(()=>{I=0;const Q=F;F=null,Q&&fe(Q.event,Q.spokenText)})))},z=(W,A,Q,R,H)=>{if(!n.onLipsyncDebug)return;const Z=i.slice(A),se=Q.filter(y=>String(y.symbol??y.viseme??"").trim());l.push({spokenText:W,audioOffsetMs:Z[0]?.vtime??0,isNewSegment:R,chunkDurationMs:H,receivedAtMs:performance.now(),visemes:Z.map((y,O)=>{const N=se[O];return{rawSymbol:String(N?.symbol??N?.viseme??y.viseme).trim(),viseme:y.viseme,startSec:Number(N?.start??0),durationSec:Number(N?.duration??0),vtimeMs:y.vtime,vdurationMs:y.vduration}})})},Y=()=>{o.length=0,a.length=0,u=0},ce=(W,A,Q,R,H)=>{if(W.length===0&&A.length===0)return;Di(o,a,W,A,u,H);const Z=Bi(W,u),se=Q?Cr(Q,R):null;u=Math.max(Z,se!=null?u+se:u)},oe=()=>{L+=1,b?.abort(),b=null,C.stop(),i.length=0,s.length=0,Y(),d.length=0,m="neutral",l.length=0,c="",e("idle"),M("reset"),k()},re=W=>{const A=tt(W?.ttsEngineId,W?.voiceId),Q=A.ttsEngineId??T??mt,R=A.voiceId??(Q===rt?un:ir),H=W?.speakingRate??Vt,Z=Math.max(pn,Math.min(wn,H));return{engineId:Q,voiceId:R,speakingRate:Z,language:dn(W?.language)}},le=async W=>{oe();const A=L;b=new AbortController,e("loading"),c=W.debugSpokenFallback,l.length=0,Y();const Q=p.trim();if(!Q)throw new Error("Developer token required for avatar_ttsWithPoses");C.resetForNewStream(W.engineId),C.setStreamTtsEngineId(W.engineId);let R="",H="";try{const Z=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${Q}`,Accept:"text/event-stream"},body:JSON.stringify(W.requestBody),signal:b.signal});if(!Z.ok)throw new Error(`avatar_ttsWithPoses failed (${Z.status})`);const se=Z.body;if(!se)throw new Error("No response body");const y=se.getReader(),O=new TextDecoder;let N="",G=!0;const $=()=>R||W.debugSpokenFallback,ee=async _=>{if(A!==L)return;const w=vi(_);if(w){if(w.event==="spokenText"){const S=typeof w.data.text=="string"?w.data.text.trim():"";S&&(R=S,c=S,W.onSpokenText?.(S),k());return}if(w.event==="displayText"){const S=typeof w.data.text=="string"?w.data.text.trim():"";S&&(H=S,W.onDisplayText?.(S),k());return}if(w.event!=="done"){if(w.event==="audio"){const S=w.data.chunk,j=w.data.visemes??[],te=w.data.words??[],E=w.data.is_new_segment??!1,K=w.data.sample_rate,J=Number(w.data.audio_offset_ms??0),we=i.length,De=$();if(ce(j,te,S,K,W.engineId),S){const yt=G;G=!1,await C.playAudioChunk(i,s,S,j,te,E,{sampleRate:K,newStream:yt,audioOffsetMs:J}),z(De,we,j,E,Cr(S,K)),M("audio_chunk",De)}else(j.length>0||te.length>0)&&(C.queueTimingsOnly(i,s,j,te,E,{audioOffsetMs:J,newStream:G}),z(De,we,j,E,null),M("audio_chunk",De))}else if(w.event==="metadata"){const S=w.data.mood;typeof S=="string"&&S.trim()&&(m=S.trim());const j=w.data.spoken_text??w.data.text;typeof j=="string"&&j.trim()&&!R&&(R=j.trim(),c=R);const te=w.data.sentence_emotions;if(Array.isArray(te)){d.length=0;for(const E of te){if(!E||typeof E!="object")continue;const K=E;d.push({sentence_index:Number(K.sentence_index??0),text:String(K.text??""),sentiment:typeof K.sentiment=="string"?K.sentiment:void 0,emotion:String(K.emotion??m),start_word:Number(K.start_word??0),end_word:Number(K.end_word??0)})}}k(),M("metadata",$())}else if(w.event==="error")throw new Error(String(w.data.message??"avatar_ttsWithPoses stream error"))}}};for(;;){if(A!==L)return{displayText:H,spokenText:R,aborted:!0};const{done:_,value:w}=await y.read();w&&(N+=O.decode(w,{stream:!0}));const S=N.split(`
|
|
2
2
|
|
|
3
|
-
`);q=U.pop()??"";for(const Z of U)await S(Z);if(x){q.trim()&&await S(q.trim()),A.markStreamComplete(i),I("bot_stopped",O);break}}}catch(P){if(W!==B||P instanceof DOMException&&P.name==="AbortError")return;throw console.error("[avatarTtsLipsync]",P),se(),e("error"),P}},stop:se,getVisemeQueue:()=>i,getWordQueue:()=>s,getFullVisemeQueue:()=>o,getFullWordQueue:()=>a,getSentenceEmotions:()=>d,getStreamMood:()=>m,getPlaybackElapsedMs:()=>A.getPlaybackElapsedMs(),isSpeaking:()=>A.isSpeaking(),isWarmingUp:()=>A.isWarmingUp(),releaseWarmupHold:()=>A.releaseWarmupHold(),setLipsyncWarmupHold:(O,J)=>{J&&(L=J),A.setLipsyncWarmupHoldEnabled(O)},getVoiceStream:()=>A.getVoiceStream(),setPlaybackSpeed:O=>{A.setPlaybackSpeed(O)},getPlaybackSpeed:()=>A.getPlaybackSpeed(),subscribe:O=>(f.add(O),()=>f.delete(O))}}const nr=16e3,rr=16e3;class ca extends Hn.ProtobufFrameSerializer{async deserialize(t){try{return await super.deserialize(t)}catch(n){if(n instanceof Error&&n.message==="Unknown frame kind")return{type:"raw",message:null};throw n}}}class la extends Hn.DailyMediaManager{constructor(){super(!0,!0,void 0,void 0,512,nr,rr)}bufferBotAudio(t,n){}}const ua=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function Cr(e){return ua.test(e.trim())}function da(e){const t=e.replace(/\/$/,"");return t.startsWith("https://")?`wss://${t.slice(8)}`:t.startsWith("http://")?`ws://${t.slice(7)}`:t}function Ni(e){if(e.wsUrl?.trim())return e.wsUrl.trim();const t=e.authToken?.trim();if(!t)throw new Error("Voice connect requires authToken (same JWT as SSE Authorization Bearer).");const n=e.apiBase??ht,r=new URL(`${da(n)}/ws/voice`);r.searchParams.set("authToken",t),r.searchParams.set("tenant","aiTwin");const i=et(e.ttsEngineId,e.voiceId),s=i.ttsEngineId;s&&r.searchParams.set("ttsEngineId",s);const o=i.voiceId?.trim();o&&(s&&oi(s)?Cr(o)||r.searchParams.set("voiceId",o):Cr(o)&&r.searchParams.set("voiceId",o));const a=fn(e.language);a&&r.searchParams.set("language",a);const u=e.brainId?.trim()||e.personaId?.trim();u&&r.searchParams.set("brainId",u);const d=e.speakingRate??Ht;r.searchParams.set("speaking_rate",String(Math.max(pn,Math.min(yn,d)))),e.ttsStream===!1?r.searchParams.set("tts_stream","false"):r.searchParams.set("tts_stream","true"),e.speakOnlyWhenSpokenTo&&r.searchParams.set("speakOnlyWhenSpokenTo","true");const l=e.avatarName?.trim();return l&&r.searchParams.set("avatarName",l),r.toString()}function An(e,t){if(!Array.isArray(e))return[];const n=[];for(const r of e)!r||typeof r!="object"||n.push({sentence_index:Number(r.sentence_index??0),text:String(r.text??""),sentiment:typeof r.sentiment=="string"?r.sentiment:void 0,emotion:String(r.emotion??t),start_word:Number(r.start_word??0),end_word:Number(r.end_word??0)});return n}function fa(e){if(!e||typeof e!="object")return null;const t=e,r=(t.data&&typeof t.data=="object"&&!Array.isArray(t.data)?t.data:null)||t;return{...r,type:String(r.type??t.type??"server-message")}}function Rr(e){return e.is_new_segment===!0||Number(e.audio_offset_ms??-1)===0?!0:Number(e.chunk_index??-1)===0}function ma(e){return e?.transport?._mediaManager?._wavStreamPlayer??null}function Vi(e,t={}){const n=[],r=[],i=[],s=[];let o=0;const a=[],u=[];let d="",l="neutral",c=tt,m=!1,w=null,T=null,f={...t},E=0,D=null;const B=new Set,v=[];let k=!1,L=null,A=!0,ie="default";const de=new Set;let I=null,V=0,G=!1,ae=!1,se=null,re=!1;const O=()=>{se!=null&&(clearTimeout(se),se=null)},J=()=>{O(),se=setTimeout(()=>{se=null,A&&(K.markStreamComplete(n),oe("bot_stopped"))},450)},W=()=>B.forEach(g=>g());let he=()=>!1;const K=Li({onSpeakingStart:()=>e("speaking"),onSpeakingDone:()=>{re=!1,ae=!1,e("done")},onNotify:W,shouldHoldForWarmup:()=>he()},c),ee=()=>{if(L)return L;const g=new MessageChannel;return g.port1.onmessage=()=>{const C=v.shift();C!==void 0&&be(C),v.length>0?g.port2.postMessage(null):k=!1},L=g,g},$=g=>{v.push(g),!k&&(k=!0,ee().port2.postMessage(null))},X=()=>K.getPlaybackElapsedMs(),_e=(g,C=d)=>{if(!f.onLipsyncDebug)return;const ne=X(),ue=n,Te=wn(i).map(ve=>({viseme:ve.viseme,vtimeMs:ve.vtime}));f.onLipsyncDebug({event:g,spokenText:C,mood:l,playbackAnchorPerf:K.getPlaybackStartPerf(),playbackElapsedMs:ne,queueLength:ue.length,activeViseme:zt(ue,ne),segments:u.map(ve=>({...ve,visemes:[...ve.visemes]})),fullQueueLength:i.length,compactionSkipped:Te})},oe=(g,C)=>{f.onLipsyncDebug&&(D={event:g,spokenText:C},E===0&&(E=requestAnimationFrame(()=>{E=0;const ne=D;D=null,ne&&_e(ne.event,ne.spokenText)})))},b=()=>{A=!0,de.clear(),K.clearAborted()},P=()=>{const g=ma(w);if(g){ie=`bot-${Date.now()}`,g.interruptedTrackIds={[ie]:!0};try{g.interrupt?.()}catch{}}const C=T;try{C?.interrupt?.()}catch{}},H=g=>{if(re&&K.isSpeaking())return!0;const C=g.context_id?.trim();return C&&de.has(C)?!0:A?!1:!(g.type==="avatar_metadata"||Rr(g))},le=g=>{A=!1,re=!1;const C=g.context_id?.trim();C&&de.add(C),O(),G=!1,ae=!1,v.length=0,k=!1,I?.abort(),I=null,V+=1,P(),K.bargeIn(),j(),e("idle"),oe("interrupt"),W()},j=()=>{n.length=0,r.length=0,i.length=0,s.length=0,o=0,u.length=0,d="",l="neutral",a.length=0},q=()=>{O(),ae=!1,G=!1,K.stop(),j(),oe("reset"),W()},p=()=>{q(),e("idle"),W()},S=(g,C)=>{typeof g.mood=="string"&&g.mood.trim()&&(l=g.mood.trim()),Array.isArray(g.sentence_emotions)&&g.sentence_emotions.length>0&&(C&&(a.length=0),a.push(...An(g.sentence_emotions,l)))},x=g=>{if(H({...g,type:"avatar_metadata"}))return;b(),G=!0;const C=String(g.spoken_text??g.text??"").trim();C&&(d=C),K.resetForNewStream(c),typeof g.mood=="string"&&g.mood.trim()&&(l=g.mood.trim()),a.length=0,a.push(...An(g.sentence_emotions,l)),Array.isArray(g.gestures)&&g.gestures,oe("metadata",C),W()},_=(g,C,ne,ue)=>{if(!f.onLipsyncDebug)return;const Te=n.slice(ne),ve=ue.filter(ke=>String(ke.symbol??ke.viseme??"").trim());u.push({spokenText:C,audioOffsetMs:Te[0]?.vtime??0,isNewSegment:!!g.is_new_segment,chunkDurationMs:g.chunk_duration_ms!=null?Number(g.chunk_duration_ms):null,receivedAtMs:performance.now(),visemes:Te.map((ke,We)=>{const Fe=ve[We];return{rawSymbol:String(Fe?.symbol??Fe?.viseme??ke.viseme).trim(),viseme:ke.viseme,startSec:Number(Fe?.start??0),durationSec:Number(Fe?.duration??0),vtimeMs:ke.vtime,vdurationMs:ke.vduration}})})},U=(g,C,ne,ue)=>{if(g.length===0&&C.length===0)return;Ri(i,s,g,C,o,c);const Te=Di(g,o);let ve=null;const ke=ne.trim();if(ke)try{const We=atob(ke.replace(/\s+/g,"")).length,Fe=Number.isFinite(ue)&&(ue??0)>0?Number(ue):16e3;ve=We/2/Fe*1e3}catch{ve=null}o=Math.max(Te,ve!=null?o+ve:o)},Z=g=>{if(H(g))return;const C=Rr(g);C&&(O(),b());const ne=String(g.spoken_text??g.text??"").trim(),ue=g.visemes??[],Te=g.words??[],ve=String(g.chunk??"").trim(),ke=G||C||!ae;G&&(G=!1),ke&&(ae=!0),ne&&(d=ne),S(g,C),ke?(K.resetForNewStream(c),i.length=0,s.length=0,o=0):C&&K.resumeBotStream(),U(ue,Te,ve,g.sample_rate);const We=n.length;K.playAudioChunk(n,r,ve,ue,Te,C,{sampleRate:g.sample_rate,newStream:ke,audioOffsetMs:Number(g.audio_offset_ms??0),onNewStream:()=>{u.length=0}}).then(()=>{_(g,ne,We,ue),oe("audio_chunk",ne),J()})},te=g=>{if(H(g))return;(g.is_new_segment||Number(g.audio_offset_ms??-1)===0)&&b(),console.warn("[realtimeVoice] avatar_lipsync is deprecated — expect avatar_audio_chunk");const C=String(g.spoken_text??g.text??"").trim();C&&(d=C),S(g,!!g.is_new_segment),U(g.visemes??[],g.words??[],"",void 0);const ne=n.length;K.queueTimingsOnly(n,r,g.visemes??[],g.words??[],!!g.is_new_segment,{audioOffsetMs:Number(g.audio_offset_ms??0)}),_(g,C,ne,g.visemes??[]),oe("lipsync",C),W()},z=async g=>{const C=String(g.text??"").trim();if(!C)return;const ne=f.authToken?.trim();if(!ne){console.error("[realtimeVoice] avatar_speak requires authToken");return}I?.abort();const ue=new AbortController;I=ue;const Te=++V;b(),K.resetForNewStream(c),d=C;const ke=`${(f.apiBase??ht).replace(/\/$/,"")}/avatar_ttsWithPoses`,We=et(c,f.voiceId);We.ttsEngineId&&(c=We.ttsEngineId,K.setStreamTtsEngineId(c));const Fe=We.voiceId?.trim()||(c===nt?dn:tr),$t=f.speakingRate??Ht,bn=Math.max(pn,Math.min(yn,$t)),Rt={user_query:C,ttsEngineId:c,speakingRate:bn,tenant:"aiTwin"};ii.has(c)&&(Rt.voice_id=Fe);const yt=fn(f.language);yt&&(Rt.language=yt);try{const Ce=await fetch(ke,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${ne}`},body:JSON.stringify(Rt),signal:ue.signal});if(!Ce.ok)throw new Error(`avatar_ttsWithPoses failed (${Ce.status})`);const He=Ce.body;if(!He)throw new Error("No response body");const vt=He.getReader(),Ie=new TextDecoder;let xe="",$e=!0;const je=async rt=>{if(Te!==V||ue.signal.aborted||!A)return;const pe=yi(rt);if(pe){if(pe.event==="audio"){const Le=pe.data.chunk,Pe=pe.data.visemes??[],Oe=pe.data.words??[],Ne=pe.data.is_new_segment??!1,Dt=pe.data.sample_rate,ct=Number(pe.data.audio_offset_ms??0);if(Le){const Bt=$e;$e=!1,await K.playAudioChunk(n,r,Le,Pe,Oe,Ne,{sampleRate:Dt,newStream:Bt,audioOffsetMs:ct})}else(Pe.length>0||Oe.length>0)&&K.queueTimingsOnly(n,r,Pe,Oe,Ne,{audioOffsetMs:ct,newStream:$e})}else if(pe.event==="metadata"){const Le=pe.data.mood;typeof Le=="string"&&Le.trim()&&(l=Le.trim());const Pe=pe.data.sentence_emotions;Array.isArray(Pe)&&(a.length=0,a.push(...An(Pe,l))),W()}else if(pe.event==="error")throw new Error(String(pe.data.message??"avatar_ttsWithPoses stream error"))}};for(;!(Te!==V||ue.signal.aborted||!A);){const{done:rt,value:pe}=await vt.read();pe&&(xe+=Ie.decode(pe,{stream:!0}));const Le=xe.split(`
|
|
3
|
+
`);N=S.pop()??"";for(const j of S)await ee(j);if(_){N.trim()&&await ee(N.trim()),C.markStreamComplete(i),M("bot_stopped",$());break}}}catch(Z){if(A!==L)return{displayText:H,spokenText:R,aborted:!0};if(Z instanceof DOMException&&Z.name==="AbortError")return{displayText:H,spokenText:R,aborted:!0};throw console.error("[avatarTtsLipsync]",Z),oe(),e("error"),Z}return{displayText:H,spokenText:R}};return{setDeveloperToken:W=>{p=W},setTtsEngineId:W=>{T=W},getTtsEngineId:()=>T,speak:async(W,A)=>{const{engineId:Q,voiceId:R,speakingRate:H,language:Z}=re(A),se={user_query:W,ttsEngineId:Q,speakingRate:H,tenant:"aiTwin"};Fn.has(Q)&&(se.voice_id=R),Z&&(se.language=Z),await le({requestBody:se,engineId:Q,debugSpokenFallback:W})},speakWithReply:async(W,A)=>{const Q=W.trim();if(!Q)throw new Error("Message is required");const{engineId:R,voiceId:H,speakingRate:Z,language:se}=re(A),y={generateReply:!0,message:Q,ttsEngineId:R,speakingRate:Z,tenant:"aiTwin",history:A?.history??[]};Fn.has(R)&&(y.voice_id=H),se&&(y.language=se);const O=A?.brainId?.trim();O&&(y.brainId=O);const N=A?.brainUrl?.trim();N&&(y.brainUrl=N);const G=await le({requestBody:y,engineId:R,debugSpokenFallback:Q,onSpokenText:A?.onSpokenText,onDisplayText:A?.onDisplayText});if(G.aborted)return{spokenText:G.spokenText,displayText:G.displayText};if(!G.spokenText&&!G.displayText)throw new Error("avatar_ttsWithPoses generateReply stream missing spokenText or displayText");return{spokenText:G.spokenText||G.displayText,displayText:G.displayText||G.spokenText}},stop:oe,getVisemeQueue:()=>i,getWordQueue:()=>s,getFullVisemeQueue:()=>o,getFullWordQueue:()=>a,getSentenceEmotions:()=>d,getStreamMood:()=>m,getPlaybackElapsedMs:()=>C.getPlaybackElapsedMs(),isSpeaking:()=>C.isSpeaking(),isWarmingUp:()=>C.isWarmingUp(),releaseWarmupHold:()=>C.releaseWarmupHold(),setLipsyncWarmupHold:(W,A)=>{A&&(V=A),C.setLipsyncWarmupHoldEnabled(W)},getVoiceStream:()=>C.getVoiceStream(),setPlaybackSpeed:W=>{C.setPlaybackSpeed(W)},getPlaybackSpeed:()=>C.getPlaybackSpeed(),subscribe:W=>(f.add(W),()=>f.delete(W))}}const ar=16e3,or=16e3;class la extends Kn.ProtobufFrameSerializer{async deserialize(t){try{return await super.deserialize(t)}catch(n){if(n instanceof Error&&n.message==="Unknown frame kind")return{type:"raw",message:null};throw n}}}class ua extends Kn.DailyMediaManager{constructor(){super(!0,!0,void 0,void 0,512,ar,or)}bufferBotAudio(t,n){}}const da=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function Dr(e){return da.test(e.trim())}function fa(e){const t=e.replace(/\/$/,"");return t.startsWith("https://")?`wss://${t.slice(8)}`:t.startsWith("http://")?`ws://${t.slice(7)}`:t}function Ui(e){if(e.wsUrl?.trim())return e.wsUrl.trim();const t=e.authToken?.trim();if(!t)throw new Error("Voice connect requires authToken (same JWT as SSE Authorization Bearer).");const n=e.apiBase??Pt,r=new URL(`${fa(n)}/ws/voice`);r.searchParams.set("authToken",t),r.searchParams.set("tenant","aiTwin");const i=tt(e.ttsEngineId,e.voiceId),s=i.ttsEngineId;s&&r.searchParams.set("ttsEngineId",s);const o=i.voiceId?.trim();o&&(s&&ci(s)?Dr(o)||r.searchParams.set("voiceId",o):Dr(o)&&r.searchParams.set("voiceId",o));const a=dn(e.language);a&&r.searchParams.set("language",a);const u=e.brainId?.trim()||e.personaId?.trim();u&&r.searchParams.set("brainId",u);const d=e.brainUrl?.trim();d&&r.searchParams.set("brainUrl",d);const l=e.speakingRate??Vt;r.searchParams.set("speaking_rate",String(Math.max(pn,Math.min(wn,l)))),e.ttsStream===!1?r.searchParams.set("tts_stream","false"):r.searchParams.set("tts_stream","true"),e.speakOnlyWhenSpokenTo&&r.searchParams.set("speakOnlyWhenSpokenTo","true");const c=e.avatarName?.trim();return c&&r.searchParams.set("avatarName",c),r.toString()}function Rn(e,t){if(!Array.isArray(e))return[];const n=[];for(const r of e)!r||typeof r!="object"||n.push({sentence_index:Number(r.sentence_index??0),text:String(r.text??""),sentiment:typeof r.sentiment=="string"?r.sentiment:void 0,emotion:String(r.emotion??t),start_word:Number(r.start_word??0),end_word:Number(r.end_word??0)});return n}function ma(e){if(!e||typeof e!="object")return null;const t=e,r=(t.data&&typeof t.data=="object"&&!Array.isArray(t.data)?t.data:null)||t;return{...r,type:String(r.type??t.type??"server-message")}}function Br(e){return e.is_new_segment===!0||Number(e.audio_offset_ms??-1)===0?!0:Number(e.chunk_index??-1)===0}function ha(e){return e?.transport?._mediaManager?._wavStreamPlayer??null}function Vi(e,t={}){const n=[],r=[],i=[],s=[];let o=0;const a=[],u=[];let d="",l="neutral",c=nt,m=!1,p=null,T=null,f={...t},I=0,F=null;const L=new Set,b=[];let k=!1,V=null,C=!0,ae="default";const fe=new Set;let M=null,z=0,Y=!1,ce=!1,oe=null,re=!1;const le=()=>{oe!=null&&(clearTimeout(oe),oe=null)},pe=()=>{le(),oe=setTimeout(()=>{oe=null,C&&(A.markStreamComplete(n),se("bot_stopped"))},450)},ie=()=>L.forEach(g=>g());let W=()=>!1;const A=Oi({onSpeakingStart:()=>e("speaking"),onSpeakingDone:()=>{re=!1,ce=!1,e("done")},onNotify:ie,shouldHoldForWarmup:()=>W()},c),Q=()=>{if(V)return V;const g=new MessageChannel;return g.port1.onmessage=()=>{const B=b.shift();B!==void 0&&we(B),b.length>0?g.port2.postMessage(null):k=!1},V=g,g},R=g=>{b.push(g),!k&&(k=!0,Q().port2.postMessage(null))},H=()=>A.getPlaybackElapsedMs(),Z=(g,B=d)=>{if(!f.onLipsyncDebug)return;const ne=H(),ue=n,xe=gn(i).map(be=>({viseme:be.viseme,vtimeMs:be.vtime}));f.onLipsyncDebug({event:g,spokenText:B,mood:l,playbackAnchorPerf:A.getPlaybackStartPerf(),playbackElapsedMs:ne,queueLength:ue.length,activeViseme:Ut(ue,ne),segments:u.map(be=>({...be,visemes:[...be.visemes]})),fullQueueLength:i.length,compactionSkipped:xe})},se=(g,B)=>{f.onLipsyncDebug&&(F={event:g,spokenText:B},I===0&&(I=requestAnimationFrame(()=>{I=0;const ne=F;F=null,ne&&Z(ne.event,ne.spokenText)})))},y=()=>{C=!0,fe.clear(),A.clearAborted()},O=()=>{const g=ha(p);if(g){ae=`bot-${Date.now()}`,g.interruptedTrackIds={[ae]:!0};try{g.interrupt?.()}catch{}}const B=T;try{B?.interrupt?.()}catch{}},N=g=>{if(re&&A.isSpeaking())return!0;const B=g.context_id?.trim();return B&&fe.has(B)?!0:C?!1:!(g.type==="avatar_metadata"||Br(g))},G=g=>{C=!1,re=!1;const B=g.context_id?.trim();B&&fe.add(B),le(),Y=!1,ce=!1,b.length=0,k=!1,M?.abort(),M=null,z+=1,O(),A.bargeIn(),$(),e("idle"),se("interrupt"),ie()},$=()=>{n.length=0,r.length=0,i.length=0,s.length=0,o=0,u.length=0,d="",l="neutral",a.length=0},ee=()=>{le(),ce=!1,Y=!1,A.stop(),$(),se("reset"),ie()},_=()=>{ee(),e("idle"),ie()},w=(g,B)=>{typeof g.mood=="string"&&g.mood.trim()&&(l=g.mood.trim()),Array.isArray(g.sentence_emotions)&&g.sentence_emotions.length>0&&(B&&(a.length=0),a.push(...Rn(g.sentence_emotions,l)))},S=g=>{if(N({...g,type:"avatar_metadata"}))return;y(),Y=!0;const B=String(g.spoken_text??g.text??"").trim();B&&(d=B),A.resetForNewStream(c),typeof g.mood=="string"&&g.mood.trim()&&(l=g.mood.trim()),a.length=0,a.push(...Rn(g.sentence_emotions,l)),Array.isArray(g.gestures)&&g.gestures,se("metadata",B),ie()},j=(g,B,ne,ue)=>{if(!f.onLipsyncDebug)return;const xe=n.slice(ne),be=ue.filter(Me=>String(Me.symbol??Me.viseme??"").trim());u.push({spokenText:B,audioOffsetMs:xe[0]?.vtime??0,isNewSegment:!!g.is_new_segment,chunkDurationMs:g.chunk_duration_ms!=null?Number(g.chunk_duration_ms):null,receivedAtMs:performance.now(),visemes:xe.map((Me,Ue)=>{const He=be[Ue];return{rawSymbol:String(He?.symbol??He?.viseme??Me.viseme).trim(),viseme:Me.viseme,startSec:Number(He?.start??0),durationSec:Number(He?.duration??0),vtimeMs:Me.vtime,vdurationMs:Me.vduration}})})},te=(g,B,ne,ue)=>{if(g.length===0&&B.length===0)return;Di(i,s,g,B,o,c);const xe=Bi(g,o);let be=null;const Me=ne.trim();if(Me)try{const Ue=atob(Me.replace(/\s+/g,"")).length,He=Number.isFinite(ue)&&(ue??0)>0?Number(ue):16e3;be=Ue/2/He*1e3}catch{be=null}o=Math.max(xe,be!=null?o+be:o)},E=g=>{if(N(g))return;const B=Br(g);B&&(le(),y());const ne=String(g.spoken_text??g.text??"").trim(),ue=g.visemes??[],xe=g.words??[],be=String(g.chunk??"").trim(),Me=Y||B||!ce;Y&&(Y=!1),Me&&(ce=!0),ne&&(d=ne),w(g,B),Me?(A.resetForNewStream(c),i.length=0,s.length=0,o=0):B&&A.resumeBotStream(),te(ue,xe,be,g.sample_rate);const Ue=n.length;A.playAudioChunk(n,r,be,ue,xe,B,{sampleRate:g.sample_rate,newStream:Me,audioOffsetMs:Number(g.audio_offset_ms??0),onNewStream:()=>{u.length=0}}).then(()=>{j(g,ne,Ue,ue),se("audio_chunk",ne),pe()})},K=g=>{if(N(g))return;(g.is_new_segment||Number(g.audio_offset_ms??-1)===0)&&y(),console.warn("[realtimeVoice] avatar_lipsync is deprecated — expect avatar_audio_chunk");const B=String(g.spoken_text??g.text??"").trim();B&&(d=B),w(g,!!g.is_new_segment),te(g.visemes??[],g.words??[],"",void 0);const ne=n.length;A.queueTimingsOnly(n,r,g.visemes??[],g.words??[],!!g.is_new_segment,{audioOffsetMs:Number(g.audio_offset_ms??0)}),j(g,B,ne,g.visemes??[]),se("lipsync",B),ie()},J=async g=>{const B=String(g.text??"").trim();if(!B)return;const ne=f.authToken?.trim();if(!ne){console.error("[realtimeVoice] avatar_speak requires authToken");return}M?.abort();const ue=new AbortController;M=ue;const xe=++z;y(),A.resetForNewStream(c),d=B;const Me=`${(f.apiBase??Pt).replace(/\/$/,"")}/avatar_ttsWithPoses`,Ue=tt(c,f.voiceId);Ue.ttsEngineId&&(c=Ue.ttsEngineId,A.setStreamTtsEngineId(c));const He=Ue.voiceId?.trim()||(c===rt?un:sr),_n=f.speakingRate??Vt,bn=Math.max(pn,Math.min(wn,_n)),ot={user_query:B,ttsEngineId:c,speakingRate:bn,tenant:"aiTwin"};Fn.has(c)&&(ot.voice_id=He);const je=dn(f.language);je&&(ot.language=je);try{const Ve=await fetch(Me,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${ne}`},body:JSON.stringify(ot),signal:ue.signal});if(!Ve.ok)throw new Error(`avatar_ttsWithPoses failed (${Ve.status})`);const ct=Ve.body;if(!ct)throw new Error("No response body");const Se=ct.getReader(),Be=new TextDecoder;let We="",ze=!0;const lt=async Ke=>{if(xe!==z||ue.signal.aborted||!C)return;const Ie=vi(Ke);if(Ie){if(Ie.event==="audio"){const Ce=Ie.data.chunk,Re=Ie.data.visemes??[],Fe=Ie.data.words??[],_t=Ie.data.is_new_segment??!1,bt=Ie.data.sample_rate,St=Number(Ie.data.audio_offset_ms??0);if(Ce){const zt=ze;ze=!1,await A.playAudioChunk(n,r,Ce,Re,Fe,_t,{sampleRate:bt,newStream:zt,audioOffsetMs:St})}else(Re.length>0||Fe.length>0)&&A.queueTimingsOnly(n,r,Re,Fe,_t,{audioOffsetMs:St,newStream:ze})}else if(Ie.event==="metadata"){const Ce=Ie.data.mood;typeof Ce=="string"&&Ce.trim()&&(l=Ce.trim());const Re=Ie.data.sentence_emotions;Array.isArray(Re)&&(a.length=0,a.push(...Rn(Re,l))),ie()}else if(Ie.event==="error")throw new Error(String(Ie.data.message??"avatar_ttsWithPoses stream error"))}};for(;!(xe!==z||ue.signal.aborted||!C);){const{done:Ke,value:Ie}=await Se.read();Ie&&(We+=Be.decode(Ie,{stream:!0}));const Ce=We.split(`
|
|
4
4
|
|
|
5
|
-
`);xe=Le.pop()??"";for(const Pe of Le)await je(Pe);if(rt){xe.trim()&&await je(xe.trim()),Te===V&&!ue.signal.aborted&&A&&K.markStreamComplete(n);break}}}catch(Ce){if(ue.signal.aborted||!A)return;console.error("[realtimeVoice] avatar_speak failed:",Ce),e("error"),W()}finally{I===ue&&(I=null)}},be=g=>{const C=fa(g);if(!C){console.warn("[realtimeVoice] server message with no payload",g);return}const ne=String(C.type??"unknown");switch(ne!=="avatar_metadata"&&ne!=="avatar_audio_chunk"&&ne!=="avatar_lipsync"&&ne!=="avatar_interrupt"&&ne!=="error"&&console.debug("[realtimeVoice] server message",ne,C),ne){case"avatar_metadata":x(C);break;case"avatar_audio_chunk":Z(C);break;case"avatar_lipsync":te(C);break;case"avatar_interrupt":le(C);break;case"error":{const ue=String(C.message??"Voice session error");console.error("[realtimeVoice] server error:",ue),e("error"),W();break}case"avatar_speak":z(C);break}},Xe=()=>w||(T=new la,w=new us.PipecatClient({transport:new Hn.WebSocketTransport({mediaManager:T,serializer:new ca,recorderSampleRate:nr,playerSampleRate:rr}),enableCam:!1,enableMic:!0,callbacks:{onBotReady:()=>{m=!0,e("idle"),W()},onDisconnected:()=>{m=!1,p()},onError:g=>{const C=typeof g=="object"&&g!==null&&"data"in g?String(g.data??g):String(g);console.error("[realtimeVoice]",C,g),e("error"),W()},onTransportStateChanged:g=>{g==="error"&&(e("error"),W())},onServerMessage:g=>{$(g)},onUserStartedSpeaking:()=>{},onBotStartedSpeaking:()=>{b(),oe("bot_started")},onBotStoppedSpeaking:()=>{A&&J()},onUserTranscript:g=>{String(g.text??""),f.onUserTranscript?.(g.text,!!g.final)},onBotOutput:g=>{f.onBotOutput?.(g.text)}}}),w);return{setDeveloperToken:g=>{},setTtsEngineId:g=>{c=g,K.setStreamTtsEngineId(g)},getTtsEngineId:()=>c,speak:async(g,C)=>{const ne=g.trim();if(ne){if(!w||!m)throw new Error("Realtime voice is not connected. Call connect() first.");q(),await w.sendText(ne)}},stop:()=>{I?.abort(),I=null,V+=1,b(),q(),e("idle"),W()},connect:async g=>{g&&(f={...f,...g});const C=et(f.ttsEngineId,f.voiceId);if(C.ttsEngineId&&(c=C.ttsEngineId,K.setStreamTtsEngineId(c)),f={...f,ttsEngineId:c,...C.voiceId?{voiceId:C.voiceId}:{}},!f.authToken?.trim())throw new Error("Voice connect requires authToken (same JWT as SSE Authorization Bearer).");e("loading");const ne=Xe();await ne.initDevices();const ue=Ni({...f,ttsEngineId:c});console.info("[realtimeVoice] connecting (avatar_audio_chunk RTVI):",ue);try{await ne.connect({wsUrl:ue})}catch(Te){m=!1,e("error"),W();const ve=Te instanceof Error?Te.message:"Realtime voice connect failed (WebSocket 101 only means upgrade OK — check authToken/origin/RTVI handshake)";throw new Error(`${ve} — ${ue}`)}m=!0,e("idle"),W()},disconnect:async()=>{if(O(),G=!1,ae=!1,v.length=0,k=!1,I?.abort(),I=null,V+=1,b(),w)try{await w.disconnect()}catch(g){console.error("[realtimeVoice] disconnect failed:",g)}m=!1,p()},isConnected:()=>m,unlockAudio:async()=>{await K.primeAudioContext()},getVisemeQueue:()=>n,getWordQueue:()=>r,getFullVisemeQueue:()=>i,getFullWordQueue:()=>s,getSentenceEmotions:()=>a,getStreamMood:()=>l,getPlaybackElapsedMs:X,isSpeaking:()=>K.isSpeaking(),isWarmingUp:()=>K.isWarmingUp(),releaseWarmupHold:()=>K.releaseWarmupHold(),setLipsyncWarmupHold:(g,C)=>{C&&(he=C),K.setLipsyncWarmupHoldEnabled(g)},getVoiceStream:()=>K.getVoiceStream(),setPlaybackSpeed:g=>{K.setPlaybackSpeed(g)},getPlaybackSpeed:()=>K.getPlaybackSpeed(),subscribe:g=>(B.add(g),()=>B.delete(g))}}function Ui(e,t,n){return{width:e.crop?.source_width??t,height:e.crop?.source_height??n}}function Wi(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 zi(e){return e?(e.w??0)>0&&(e.h??0)>0:!1}async function Mt(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 Ds(r,t)}async function Hi(e,t){if(!t)throw new Error("Missing asset key for encrypted JSON");const n=await Mt(e,t),r=new TextDecoder().decode(n);return JSON.parse(r)}async function ha(e){const t=new Blob([e],{type:"image/webp"});return createImageBitmap(t)}async function ga(e){const t=new Blob([e],{type:"image/webp"}),n=URL.createObjectURL(t);return new Promise((r,i)=>{const s=new Image;s.decoding="async",s.onload=()=>{URL.revokeObjectURL(n),r(s)},s.onerror=()=>{URL.revokeObjectURL(n),i(new Error("Failed to decode decrypted image"))},s.src=n})}async function wa(e){const t=new Blob([e],{type:"image/png"});return createImageBitmap(t)}async function pa(e){const t=new Blob([e],{type:"image/png"}),n=URL.createObjectURL(t);return new Promise((r,i)=>{const s=new Image;s.decoding="async",s.onload=()=>{URL.revokeObjectURL(n),r(s)},s.onerror=()=>{URL.revokeObjectURL(n),i(new Error("Failed to decode decrypted PNG"))},s.src=n})}function ya(e){const t=new Blob([e],{type:"video/mp4"});return URL.createObjectURL(t)}async function va(e){const t=Fs();if(!Wt())return t;if(!e)throw new Error("Missing asset key for encrypted idle video");const n=await Mt(t,e);return ya(n)}function kt(e,t){return`${e}/${t}_minus_sil.png`}const $i=5;function vn(e){const t=e?.composite_threshold;if(typeof t=="number"&&t>0)return t;const n=e?.crop?.content_threshold;return typeof n=="number"&&n>0?n:$i}const _a=["aa","E","I","O","U","PP","FF","DD","SS","TH","CH","RR","kk","nn"],Vn=["t01_0.25","t02_0.50","t03_0.75"],ba=Vn.length,Dr=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 Br(e,t){return`${e}__${t}`}function Fr(e,t){return`pairs/${e}/${t}_minus_sil.png`}function xt(e){return`${e}_minus_sil.png`}function ir(e,t){if(t.has(e))return e;const n=/^pairs\/([^/]+)\//.exec(e);if(!n)return null;const r=n[1].split("__")[1];if(!r||r==="sil")return null;const i=xt(r);return t.has(i)?i:null}function ji(e,t){return e.filter(n=>t.has(n))}function Sa(e,t,n){const r=sr(e,t);return ji(r,n).length>0}function sr(e,t){if(e===t)return[];const n=[],r=Br(e,t);if(Dr.has(r)){for(const s of Vn)n.push(Fr(r,s));return n}const i=Br(t,e);if(Dr.has(i)){for(let s=ba-1;s>=0;s--)n.push(Fr(i,Vn[s]));return n}return[]}function Ta(e){return e<16?[1]:e<24?[1]:e<35?[0,1,2]:[0,1,2]}function ka(e,t){return Ta(t).map(r=>e[r]).filter(r=>r!=null)}function Ea(e,t,n,r){if(r<=0)return 0;const s=Math.max(1,n-t)/r,o=e-t,a=Math.floor(o/s);return Math.min(r-1,Math.max(0,a))}function Ki(e,t,n){if(!n)return`${e}/${t}`;const r=t.split("/").pop()??t,i=r.includes(".")?r.slice(0,r.lastIndexOf(".")):r;return`${e}/${i}.bin`}const xa=[.32,.24,.16,.08,0],Ia=xa.map(e=>`eyes_${e.toFixed(2)}`),Aa=["eyes_0.32","eyes_0.16","eyes_0.00"],Ma=["eyes_0.32","eyes_0.16","eyes_0.08","eyes_0.00"],ze=2,Pa=-20,an=16,Gi={fear:-20,anger:-20,sad:-10,neutral:0,love:0,happy:0,disgust:10};function Vt(e){return`brow_${e}`}function mt(e){return Gi[e]}function Qe(e){return Math.max(Pa,Math.min(an,e))}function Ca(e,t){if(e===t)return[];const n=e<t,r=n?ze:-ze,i=[];let s=e;if(s%ze!==0){const o=n?Math.ceil(s/ze)*ze:Math.floor(s/ze)*ze,a=Qe(o);if(n?a>=t:a<=t)return[t];s=a,i.push(s)}for(;;){const o=s+r;if(n?o>=t:o<=t){t!==s&&i.push(t);break}s=o,i.push(s)}return i}function Lr(e){const t=Qe(e);if(t%ze===0)return[t];const n=Math.floor(t/ze)*ze,r=Math.min(an,n+ze),i=Qe(n);return t-i<=r-t?i===r?[i]:[i,r]:i===r?[r]:[r,i]}const Ra=["fear","anger","sad","neutral","love","happy","disgust"],Da={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 Ze(e,t="neutral"){const n=String(e??"").trim().toLowerCase();return n?Da[n]??t:t}function qi(e){return e===0?null:kt(Vt(e),"eyes_standard")}function Yi(e){return qi(mt(e))}const Ba={[-20]:"anger",[-10]:"sad",0:"neutral",10:"disgust"};function ar(e,t){if(!e)return null;if(t(e))return e;const n=e.match(/^brow_(-?\d+)\/(eyes_[^/]+)_minus_sil\.png$/);if(n){const i=Number(n[1]),s=n[2];for(const a of Lr(i)){if(a===i)continue;const u=kt(Vt(a),s);if(t(u))return u}const o=Ba[i];if(o){const a=kt(o,s);if(t(a))return a}return null}const r=e.match(/^(fear|anger|sad|neutral|love|happy|disgust)\/(eyes_[^/]+)_minus_sil\.png$/);if(r){const i=r[1],s=r[2],o=mt(i);for(const a of[o,...Lr(o)]){const u=kt(Vt(a),s);if(t(u))return u}}return null}function Or(e,t){const n=Vt(mt(e));return!t||t==="eyes_standard"?Yi(e):e==="neutral"&&t==="eyes_standard"?null:kt(n,t)}function Fa(e,t){const n=[];for(const r of t)n.push(Or(e,r));for(let r=t.length-2;r>=0;r--)n.push(Or(e,t[r]));return n.push(Yi(e)),n}function La(e){return kt(Vt(e),"eyes_standard")}function Oa(e,t){return Ca(e,t).map(La)}const Na=6;function Va(e,t){for(const n of e)if(t>=n.wtime&&t<n.wtime+n.wduration)return n;return null}function Ua(e){const t=Qe(e);return t>=an?an:Qe(t+Na)}function Wa(e,t,n){const r=Qe(n);return Va(t,e)?.emphasis?Ua(r):r}function Nr(e){if(!e)return 0;const t=e.match(/^brow_(-?\d+)\//);if(!t?.[1])return null;const n=Number.parseInt(t[1],10);return Number.isFinite(n)?Qe(n):null}function Ye(e,t){return e+Math.random()*(t-e)}function Vr(){return Ye(14,32)}function za(e){if(e)return{holdMinMs:10,holdMaxMs:18,closedExtraMs:0};const t=Math.random();return t<.18?{holdMinMs:38,holdMaxMs:62,closedExtraMs:Ye(40,90)}:t<.42?{holdMinMs:26,holdMaxMs:44,closedExtraMs:Ye(12,36)}:t<.82?{holdMinMs:14,holdMaxMs:28,closedExtraMs:Math.random()<.35?Ye(8,22):0}:{holdMinMs:10,holdMaxMs:18,closedExtraMs:0}}function Ur(e,t){const n=Ye(e.holdMinMs,e.holdMaxMs);return t?n+e.closedExtraMs:n}function Ha(e={}){const{initialDelayMs:t=800+Math.random()*1200,intervalMinMs:n=2200,intervalMaxMs:r=5800,doubleBlinkChance:i=.18,doubleBlinkGapMinMs:s=120,doubleBlinkGapMaxMs:o=220,fullBlinkChance:a=.75,postEmotionChangeDelayMs:u=380,minDwellMs:d=550}=e;let l="neutral",c="neutral",m=0,w=0,T=0,f={kind:"idle",nextBlinkAt:performance.now()+t},E=null,D="__eyes_open__|neutral|brow:0";function B(I=l){D=`${E??"__eyes_open__"}|${I}|brow:${w}`}function v(I,V=l){E=I;const G=Nr(I);G!=null?w=G:I==null&&(w=0),B(V)}function k(I){return qi(I)}function L(I,V,G){const ae=Qe(V),se=Qe(G);if(m=se,ae===se){v(k(se));return}const re=[...Oa(ae,se),k(se)];f={kind:"browBlend",paths:re,index:0,holdUntil:I+Vr(),targetBrow:se},v(re[0]??null)}function A(I,V){f={kind:"idle",nextBlinkAt:I+Ye(n,r)},c=V,v(k(m),V)}function ie(I,V,G){const ae=G?Aa:Math.random()<a?Ia:Ma,se=za(G),re=ae.length-1;f={kind:"playing",paths:Fa(V,ae),index:0,holdUntil:I+Ur(se,re===0),after:"idle",blinkEmotion:V,pace:se,closedFrameIndex:re},c=V,v(f.paths[0]??null,V)}function de(I){if(f.kind==="browBlend"){for(;I>=f.holdUntil&&f.index<f.paths.length-1;)f.index+=1,f.holdUntil=I+Vr();const V=f.paths[f.index]??null;v(V),I>=f.holdUntil&&f.index>=f.paths.length-1&&(w=f.targetBrow,m=f.targetBrow,v(k(f.targetBrow)),f={kind:"idle",nextBlinkAt:I+u});return}if(f.kind==="idle"){v(k(m),c),I>=f.nextBlinkAt&&ie(I,c,!1);return}if(f.kind==="doublePause"){v(k(m),f.blinkEmotion),I>=f.resumeAt&&ie(I,f.blinkEmotion,!0);return}if(f.kind==="playing"){for(;I>=f.holdUntil&&f.index<f.paths.length-1;)f.index+=1,f.holdUntil=I+Ur(f.pace,f.index===f.closedFrameIndex);if(v(f.paths[f.index]??null,f.blinkEmotion),I>=f.holdUntil&&f.index>=f.paths.length-1){if(f.after==="resumeIdle"){A(I+u,l);return}if(f.after==="doublePause"){f={kind:"doublePause",resumeAt:I+Ye(s,o),blinkEmotion:f.blinkEmotion},v(k(m),f.blinkEmotion);return}if(f.after==="idle"&&Math.random()<i){f={kind:"doublePause",resumeAt:I+Ye(s,o),blinkEmotion:f.blinkEmotion},v(k(m),f.blinkEmotion);return}A(I,f.blinkEmotion)}}}return{advance:de,setTargetEmotion(I,V){const G=Ze(I,l);if(G===l)return;const ae=performance.now();!V?.force&&d>0&&!(l==="neutral"&&G!=="neutral")&&ae-T<d||(l=G,c=G,T=ae)},setTargetEyebrow(I){const V=Qe(I);if(V===m)return;const G=performance.now(),ae=f.kind==="browBlend"?Nr(E)??w:w;m=V,!(V===ae&&f.kind!=="browBlend")&&(f.kind==="playing"||f.kind==="doublePause"||L(G,ae,V))},snapToEmotion(I){const V=Ze(I),G=mt(V);l=V,c=V,m=G,w=G,T=performance.now(),f={kind:"idle",nextBlinkAt:performance.now()+Ye(4e3,7e3)},v(k(G),V)},getTargetEmotion:()=>l,getTargetEyebrow:()=>m,getExpressionPath:()=>E,getDrawKey:()=>D,reset(){l="neutral",c="neutral",m=0,w=0,T=0,A(performance.now()+Ye(n,r),"neutral")}}}function $a(){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 i=()=>{n&&(URL.revokeObjectURL(n),n=null)};return{async load(s){t&&r===s||(i(),t=!1,r=s,s.startsWith("blob:")&&(n=s),await new Promise((o,a)=>{const u=()=>{const d=e.duration;if(!Number.isFinite(d)||d<=0){a(new Error(`Idle video has invalid duration: ${s}`));return}t=!0,e.currentTime=0,o()};e.addEventListener("loadeddata",u,{once:!0}),e.addEventListener("error",()=>a(new Error(`Failed to load idle video: ${s}`)),{once:!0}),e.src=s,e.load()}))},isReady(){return t},getVideo(){return e},setActive(s){t&&(s?e.paused&&e.play().catch(()=>{}):e.paused||e.pause())},restart(){t&&(e.currentTime=0)},dispose(){e.pause(),e.removeAttribute("src"),e.load(),i(),t=!1,r=""}}}const ja=50,Qi=400;function Ka(e,t,n){return e.filter(r=>{const i=r.queueIndex??-1;return i>=t&&i<=n})}function Ga(e,t){const n=[];for(const r of e){const i=Ka(t,r.start_word,r.end_word);if(i.length===0)continue;const s=i[0],o=i[i.length-1];n.push({sentence:r,startMs:Math.max(0,s.wtime-ja),endMs:o.wtime+o.wduration+Qi})}return n.sort((r,i)=>r.startMs-i.startMs)}function qa(e,t,n,r="neutral"){const i=Ze(r);if(t.length===0)return i;if(n.length===0||e<n[0].wtime)return Ze(t[0]?.emotion,i);const s=Ga(t,n);let o=null;for(const d of s)e>=d.startMs&&e<=d.endMs&&(o=d);if(o)return Ze(o.sentence.emotion,i);const a=n[n.length-1],u=a.wtime+a.wduration;return e>u+Qi?Ze(t[t.length-1]?.emotion,i):i}function or(e,t,n,r,i=$i){const s=new OffscreenCanvas(n,r),o=s.getContext("2d",{willReadFrequently:!0});o.drawImage(e,0,0,n,r);const a=o.getImageData(0,0,n,r),u=o.createImageData(n,r);u.data.set(a.data);const l=new OffscreenCanvas(n,r).getContext("2d",{willReadFrequently:!0});for(const c of t){l.clearRect(0,0,n,r),l.drawImage(c,0,0,n,r);const m=l.getImageData(0,0,n,r);for(let w=0;w<u.data.length;w+=4){const T=m.data[w],f=m.data[w+1],E=m.data[w+2];Math.max(T,f,E)>i&&(u.data[w]=T,u.data[w+1]=f,u.data[w+2]=E,u.data[w+3]=255)}}return o.putImageData(u,0,0),s}let ut=null,It=null;const on=new Map;function Ya(){ut=null,It=null,on.clear()}fi(Ya);function Qa(e){return e??It??void 0}function cr(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 Xa(e){return Wt()?pa(await Mt(sn(),e??"")):cr(sn())}async function Wr(e,t,n,r){const i=n?await Hi(e,r):await fetch(e).then(d=>{if(!d.ok)throw new Error(`Failed to load ${e}`);return d.json()}),s=i.sheets?.[0];if(!s?.path)throw new Error(`${e} has no sheets[0].path`);const o=n?await ga(await Mt(Ki(t,s.path,n),r??"")):await cr(`${t}/${s.path}`),a=new Map;for(const d of i.cells??[])d.path&&a.set(d.path,d);const u=new Map;for(const d of i.sheets??[])u.set(d.index,d);return{atlas:o,atlasMeta:i,cellByPath:a,sheetByIndex:u,diffBase:t}}async function Un(e){const t=Qa(e),n=Wt();if(n&&!t)throw new Error("Encrypted assets enabled but no key provided");if(ut&&(!n||It===(t??null))){const s=await ut;return{...At(s),visemePaths:[...s.viseme.cellByPath.keys()]}}It=t??null,on.clear();const r=mi();ut=(async()=>{const s=await Xa(t),o=await Wr(hi(),r,n,t);let a=null;try{a=await Wr(gi(),r,n,t)}catch{a=null}return{sil:s,viseme:o,expression:a}})();const i=await ut;return{...At(i),visemePaths:[...i.viseme.cellByPath.keys()]}}async function lr(e){if(await Un(e),!ut)throw new Error("Assets not loaded");return ut}function At(e){return Ui(e.viseme.atlasMeta,e.sil.naturalWidth,e.sil.naturalHeight)}function Ja(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 cn(e,t,n){const r=`${t.diffBase}::${n}`,i=on.get(r);if(i)return i;const s=(async()=>{const o=t.cellByPath.get(n);if(!o)throw new Error(`No atlas cell for path: ${n}`);const a=Wi(t.atlasMeta,o),u=At(e);if(zi(o)){const c=Ja(t,o),m=document.createElement("canvas");m.width=u.width,m.height=u.height;const w=m.getContext("2d");return w.fillStyle="#000",w.fillRect(0,0,u.width,u.height),w.drawImage(c,a.x,a.y),m}const d=`${t.diffBase}/${n}`,l=await cr(d);if(l.naturalWidth===u.width&&l.naturalHeight===u.height)return l;throw new Error(`Diff PNG wrong size for ${n}`)})();return on.set(r,s),s}async function Mn(e,t,n,r,i,s){if(i){const{width:w,height:T}=i;if(s&&!s()||t.readyState<HTMLMediaElement.HAVE_CURRENT_DATA)return;const f=document.createElement("canvas");f.width=w,f.height=T;const E=f.getContext("2d");if(E.clearRect(0,0,w,T),E.drawImage(t,0,0,w,T),s&&!s())return;(e.width!==w||e.height!==T)&&(e.width=w,e.height=T);const D=e.getContext("2d");D.clearRect(0,0,w,T),D.drawImage(f,0,0);return}const o=await lr(),a=vn(o.viseme.atlasMeta),{width:u,height:d}=At(o);(e.width!==u||e.height!==d)&&(e.width=u,e.height=d);const l=[],c=e.getContext("2d");if(c.clearRect(0,0,u,d),t.readyState<HTMLMediaElement.HAVE_CURRENT_DATA){const w=o.sil;c.drawImage(w,0,0,u,d);return}if(l.length===0){c.drawImage(t,0,0,u,d);return}const m=or(t,l,u,d,a);c.drawImage(m,0,0)}async function Wn(e,t,n){const r=await lr(It??void 0),i=vn(r.viseme.atlasMeta),{width:s,height:o}=At(r);(e.width!==s||e.height!==o)&&(e.width=s,e.height=o);const a=[];if(t.mouthPath){const l=new Set(r.viseme.cellByPath.keys()),c=ir(t.mouthPath,l)??(l.has(t.mouthPath)?t.mouthPath:null);c&&a.push(await cn(r,r.viseme,c))}if(t.expressionPath&&r.expression){const l=ar(t.expressionPath,c=>r.expression.cellByPath.has(c));l&&a.push(await cn(r,r.expression,l))}const u=e.getContext("2d");if(u.clearRect(0,0,s,o),a.length===0){u.drawImage(r.sil,0,0,s,o);return}const d=or(r.sil,a,s,o,i);u.drawImage(d,0,0)}async function Za(e,t){const n=await lr(It??void 0),r=vn(n.viseme.atlasMeta),{width:i,height:s}=At(n),o=[];if(e.mouthPath){const l=new Set(n.viseme.cellByPath.keys()),c=ir(e.mouthPath,l)??(l.has(e.mouthPath)?e.mouthPath:null);c&&o.push(await cn(n,n.viseme,c))}if(e.expressionPath&&n.expression){const l=ar(e.expressionPath,c=>n.expression.cellByPath.has(c));l&&o.push(await cn(n,n.expression,l))}const a=new OffscreenCanvas(i,s),u=a.getContext("2d");if(o.length===0)return u.drawImage(n.sil,0,0,i,s),a.transferToImageBitmap();const d=or(n.sil,o,i,s,r);return u.drawImage(d,0,0),a.transferToImageBitmap()}async function eo(e){await Wn(e,{mouthPath:null,expressionPath:null})}const en={fontFamily:"system-ui, -apple-system, sans-serif",fontSize:"clamp(0.875rem, 2.5vw, 1.125rem)",color:"rgba(255,255,255,0.85)"};function to(e){return e.length===0?"":e.map(t=>t.word).join(" ")}function no(e){if(!e)return{enabled:!1,style:en};const t=e===!0?{}:e;return{enabled:!0,style:{fontFamily:t.fontFamily??en.fontFamily,fontSize:t.fontSize??en.fontSize,color:t.color??en.color}}}const ro={position:"absolute",bottom:0,left:0,right:0,display:"flex",justifyContent:"center",padding:"0.75rem 1rem",pointerEvents:"none"},io={display:"inline-block",maxWidth:"100%",padding:"0.45rem 0.85rem",borderRadius:"0.75rem",background:"rgba(0,0,0,0.55)",lineHeight:1.4,textAlign:"center"},so={display:"-webkit-box",WebkitLineClamp:2,WebkitBoxOrient:"vertical",overflow:"hidden",maxWidth:"100%",margin:0};function ao({text:e,style:t}){return R.jsx("div",{style:ro,"aria-live":"polite","aria-atomic":"true",children:R.jsx("div",{style:{...io,fontFamily:t.fontFamily,fontSize:t.fontSize,color:t.color},children:R.jsx("p",{style:so,children:e})})})}const oo={inset:0,overflow:"hidden",pointerEvents:"none",position:"absolute",zIndex:3},co={filter:"blur(22px)",height:"100%",inset:0,objectFit:"cover",objectPosition:"top",position:"absolute",transform:"scale(1.08)",width:"100%"},lo={backdropFilter:"blur(10px)",WebkitBackdropFilter:"blur(10px)",inset:0,position:"absolute"};function uo({thumbnailUrl:e}){const[t,n]=h.useState(!1);h.useEffect(()=>{n(!1)},[e]);const r=!!e&&t;return R.jsxs("div",{style:oo,"aria-hidden":!0,children:[e?R.jsx("img",{src:e,alt:"",style:{...co,opacity:r?1:0,transition:"opacity 0.45s ease"},onLoad:()=>n(!0),onError:()=>n(!1)}):null,R.jsx("div",{style:{...lo,background:r?"rgba(0, 0, 0, 0.28)":"rgba(10, 10, 11, 0.92)"}})]})}let Xi=null;function zr(e){Xi=e}function at(){return Xi}function fo(e){return`${e.from}→${e.to}@${e.fromVtime}`}function Hr(){return{rafTicksSpeaking:0,rafTicksDeduped:0,drawsRequested:0,drawsDisplayed:0,queueSuperseded:0,workerStale:0,rifeFramesOmittedByGap:0,transitionFramesSampled:0,transitionFramesDisplayed:0,transitionFramesMissed:0,bufferTicks:0,bufferHits:0,bufferUnderruns:0,bufferPrefetched:0}}function mo(){let e=Hr();const t=new Set,n=new Set,r=new Set;let i="",s=-1,o="";const a=()=>{e=Hr(),t.clear(),n.clear(),r.clear(),i="",s=-1,o=""},u=l=>{t.add(l)},d=l=>{l&&r.add(l)};return{reset:a,onRafTickSpeaking(){e.rafTicksSpeaking+=1},onDrawDeduped(){e.rafTicksDeduped+=1},onDrawRequested(){e.drawsRequested+=1},onQueueSuperseded(){e.queueSuperseded+=1},onWorkerStale(){e.workerStale+=1},onTransitionSample(l,c){const m=fo(l);e.transitionFramesSampled+=1,m!==i&&(i=m,s=-1,o!==m&&(o=m,e.rifeFramesOmittedByGap+=l.omittedByGap)),c&&n.add(c),s>=0&&l.frameIdx>s+1&&(e.transitionFramesMissed+=l.frameIdx-s-1),s=l.frameIdx},onBufferTick(){e.bufferTicks+=1},onBufferHit(){e.bufferHits+=1},onBufferUnderrun(){e.bufferUnderruns+=1},onBufferPrefetched(){e.bufferPrefetched+=1},onBufferReset(){},onDrawDisplayed(l,c){if(e.drawsDisplayed+=1,l.transitionMeta){e.transitionFramesDisplayed+=1;const w=l.transitionMeta;u(w.fromVtime),u(w.toVtime),d(l.mouthPath);return}if(l.label.includes("→")){e.transitionFramesDisplayed+=1;return}const m=l.label.trim();if(!(!m||m==="sil")){for(const w of c)if(w.viseme===m&&l.elapsedMs>=w.vtime&&l.elapsedMs<w.vtime+w.vduration){u(w.vtime);break}}},snapshot(l,c){let m=0,w=0;for(const B of l)if(B.viseme!=="sil"){if(B.vtime>=c)break;m+=1,t.has(B.vtime)&&(w+=1)}const T=m>0?Math.round(w/m*100):100,f=e.queueSuperseded+e.workerStale+Math.max(0,e.drawsRequested-e.drawsDisplayed),E=m-w,D=e.bufferTicks>0?Math.round(e.bufferHits/e.bufferTicks*100):100;return{...e,bufferHitRate:D,renderLoss:f,visemeSlotsTotal:m,visemeSlotsCovered:w,visemeCoveragePct:T,transitionFramesUniqueSampled:n.size,transitionFramesUniquePainted:r.size,drawsDeduped:e.rafTicksDeduped,renderSkips:e.rafTicksDeduped+f,visemesShown:w,visemesSkipped:E,rifeTransitionFramesSkipped:e.transitionFramesMissed}}}}const Ji=jn,ho=200,$r=300,go=100,wo=600,Zi="__sil__";function jr(e){return e.lastDrawnKey?e.lastDrawnKey.split("|")[0]===Zi:!1}function ur(){return{lastDrawnKey:""}}function Be(e){e.lastDrawnKey="",e.transitionCache=void 0}function po(e,t){if(t?.transitionCache&&t.transitionCache.queueLength===e.length)return t.transitionCache.transitions;const n=Pi(e);return t&&(t.transitionCache={queueLength:e.length,transitions:n}),n}function yo(e,t){let n="sil";for(const r of e)r.viseme!=="sil"&&(t!=null&&r.vtime>t||(n=r.viseme));return n}function vo(e,t,n,r=120){if(n!=="sil")return n;const i=Oi(e,t,r);return i!=="sil"?i:yo(e,t)}function _o(e,t){return e==="sil"?!1:t?Sa(e,"sil",t):sr(e,"sil").length>0}function bo(){return Ji+wo}function ln(e){return e??Zi}function dr(e,t,n,r,i=go){if(e.length===0)return{diffPath:null,label:"sil"};if(t>=lt(e))return{diffPath:null,label:"sil"};const s=po(e,r),o=na(s,t);if(o){const d=Ci(o.fromVtime,o.toVtime,o.from,o.to);if(t>=d.transStart&&t<d.transEnd){let l=sr(o.from,o.to);n&&(l=ji(l,n));const c=ka(l,d.effectiveGapMs);if(c.length>0){const m=Ea(t,d.transStart,d.transEnd,c.length);return{diffPath:c[m]??c[c.length-1],label:`${o.from}→${o.to}`,transitionMeta:{from:o.from,to:o.to,fromVtime:o.fromVtime,toVtime:o.toVtime,frameIdx:m,frameCount:c.length,fullFrameCount:l.length,omittedByGap:Math.max(0,l.length-c.length)}}}return{diffPath:xt(o.to),label:o.to}}}const a=gn(e);let u=xi(a,t);return u==="sil"&&(u=Oi(e,t,i)),u==="sil"?{diffPath:null,label:"sil"}:{diffPath:xt(u),label:u}}function Ut(e,t){const n=t??ln(e.expressionPath);return`${ln(e.mouthPath)}|${n}`}function Kr(e,t,n,r,i,s,o,a,u,d){const l=dr(t,n,u,s),c={mouthPath:l.diffPath,expressionPath:r},m=Ut(c,i),w=at();if(l.transitionMeta&&w?.onTransitionSample(l.transitionMeta,l.diffPath),m===s.lastDrawnKey){w?.onDrawDeduped();return}w?.onDrawRequested(),a(l),s.lastDrawnKey=m,o(e,c,m,T=>{T===m&&(s.lastDrawnKey=m)})}function Pn(e,t,n,r,i,s,o=null,a=null){const u={mouthPath:a,expressionPath:t},d=o!=null?`|idle@${Math.round(o*1e3)}`:"",l=Ut(u,n)+d;!(o!=null)&&l===r.lastDrawnKey||(s(o!=null?t?"idle · blink":"idle":t?"blink":"sil"),i(e,u,l,m=>{m===l&&(r.lastDrawnKey=l)}))}function es(e,t,n,r,i=Ot,s){if(n<=t||e.length===0)return[];const o=s??ur(),a=[];let u="";for(let d=t;d<n;d+=i){const l=dr(e,d,r,o),c=ln(l.diffPath);c!==u&&(u=c,a.push({displayAtMs:d,mouthPath:l.diffPath,mouthKey:c,label:l.label}))}return a}const So=3;function fr(e){let t=0;const n=[];let r=!1,i=!1;const s=async()=>{if(!r){r=!0;try{for(;n.length>0;){const a=n.shift(),u=++t;await e(a.diffs,u,a)&&u===t&&a.onDisplayed?.(a.drawKey)}}finally{r=!1,n.length>0&&s()}}},o=()=>{i||(i=!0,queueMicrotask(()=>{i=!1,s()}))};return{enqueue(a,u,d){const l=n.findIndex(c=>c.drawKey===u);l>=0?n[l]={diffs:a,drawKey:u,onDisplayed:d}:(n.length>=So&&(n.shift(),at()?.onQueueSuperseded()),n.push({diffs:a,drawKey:u,onDisplayed:d})),o()},reset(){t+=1,n.length=0},isLatestSeq(a){return a===t},getLatestSeq(){return t}}}function To(e,t=2){const n=[],r=new Set;let i=0,s=!1,o=0;const a=(d,l)=>`${d}|${l}`,u=async()=>{if(!s){s=!0;try{for(;i<t&&n.length>0;){const d=n.shift(),l=a(d.displayAtMs,d.drawKey);if(r.has(l))continue;r.add(l),i+=1;const c=o;try{await e(d)}finally{if(r.delete(l),i-=1,c!==o)return}}}finally{s=!1,n.length>0&&i<t&&u()}}};return{enqueue(d){const l=a(d.displayAtMs,d.drawKey);r.has(l)||n.some(c=>a(c.displayAtMs,c.drawKey)===l)||(n.push(d),u())},isQueuedOrInflight(d,l){const c=a(d,l);return r.has(c)?!0:n.some(m=>a(m.displayAtMs,m.drawKey)===c)},reset(){o+=1,n.length=0,r.clear(),i=0},pendingCount(){return n.length+i}}}function ko(){const e=new Map,t=n=>{n.bitmap.close()};return{has(n,r){return e.has(r)},markRendered(n,r,i,s,o){const a=e.get(r);a&&t(a),e.set(r,{displayAtMs:n,mouthKey:r,label:i,mouthPath:s,bitmap:o})},findForMouthKey(n){return e.get(n)??null},removeThrough(n){},pruneBefore(n){},reset(){for(const n of e.values())t(n);e.clear()},size(){return e.size}}}function Eo(e,t,n,r,i,s){const o=es(t,n,r,i,Ot,s);if(o.length===0)return{ready:0,total:0};let a=0;for(const u of o)e.has(u.displayAtMs,u.mouthKey)&&(a+=1);return{ready:a,total:o.length}}function xo(e){const t=ko(),n=ur(),r=new Set;let i="",s=null;const o=To(async c=>{try{if(!e.supportsBufferedPlayback)return;const m=await e.compositePrefetchFrame(c.diffs,c.mouthKey);if(!m)return;t.markRendered(c.displayAtMs,c.mouthKey,c.label,c.mouthPath,m),at()?.onBufferPrefetched()}finally{r.delete(c.mouthKey)}},_s),a=c=>{for(const m of c)t.has(m.displayAtMs,m.mouthKey)||r.has(m.mouthKey)||o.isQueuedOrInflight(0,m.mouthKey)||(r.add(m.mouthKey),o.enqueue({...m,displayAtMs:0,drawKey:m.mouthKey,diffs:{mouthPath:m.mouthPath,expressionPath:null}}))},u=(c,m,w,T=In)=>{if(!e.supportsBufferedPlayback)return;const f=Math.max(0,m-Ot*4),E=es(c,f,m+T,w,Ot,n);a(E)},d=(c,m)=>{i=c,s=m},l=(c,m)=>!(i!==c||s!==m);return{reset(){t.reset(),o.reset(),r.clear(),Be(n),i="",s=null,at()?.onBufferReset()},markExternallyDisplayed(c,m){d(c.split("|")[0]??c,m)},warmupTick(c){e.supportsBufferedPlayback&&u(c.queue,0,c.availablePaths,Math.max(Er,In))},isWarmupReady(c,m=Er){if(!e.supportsBufferedPlayback)return!0;const{ready:w,total:T}=Eo(t,c.queue,0,m,c.availablePaths,n);return T===0?!1:w/T>=vs},getBufferedFrameCount:()=>t.size(),tick(c){const m=at();m?.onBufferTick(),u(c.queue,c.elapsedMs,c.availablePaths),t.pruneBefore(c.elapsedMs-In);const w=dr(c.queue,c.elapsedMs,c.availablePaths,n),T=ln(w.diffPath),f=Ut({mouthPath:w.diffPath,expressionPath:c.expressionPath},c.expressionDrawKey),E=()=>(d(T,c.expressionPath),m?.onBufferHit(),{usedBuffer:!0,underrun:!1,held:!0});if(l(T,c.expressionPath)||c.playbackState.lastDrawnKey===f)return E();const D=t.findForMouthKey(T,c.elapsedMs,Ot);return D&&c.expressionPath!=null?(m?.onBufferHit(),{usedBuffer:!1,underrun:!1,held:!1}):D?(e.blitBitmap(c.canvas,D.bitmap),d(D.mouthKey,c.expressionPath),c.playbackState.lastDrawnKey=f,c.onStatus({diffPath:D.mouthPath,label:D.label}),c.onDisplayed(f,D.mouthPath,D.label),m?.onBufferHit(),{usedBuffer:!0,underrun:!1,held:!1}):(m?.onBufferUnderrun(),{usedBuffer:!1,underrun:!0,held:!1})}}}const Io=`
|
|
5
|
+
`);We=Ce.pop()??"";for(const Re of Ce)await lt(Re);if(Ke){We.trim()&&await lt(We.trim()),xe===z&&!ue.signal.aborted&&C&&A.markStreamComplete(n);break}}}catch(Ve){if(ue.signal.aborted||!C)return;console.error("[realtimeVoice] avatar_speak failed:",Ve),e("error"),ie()}finally{M===ue&&(M=null)}},we=g=>{const B=ma(g);if(!B){console.warn("[realtimeVoice] server message with no payload",g);return}const ne=String(B.type??"unknown");switch(ne!=="avatar_metadata"&&ne!=="avatar_audio_chunk"&&ne!=="avatar_lipsync"&&ne!=="avatar_interrupt"&&ne!=="error"&&console.debug("[realtimeVoice] server message",ne,B),ne){case"avatar_metadata":S(B);break;case"avatar_audio_chunk":E(B);break;case"avatar_lipsync":K(B);break;case"avatar_interrupt":G(B);break;case"error":{const ue=String(B.message??"Voice session error");console.error("[realtimeVoice] server error:",ue),e("error"),ie();break}case"avatar_speak":J(B);break}},De=()=>p||(T=new ua,p=new us.PipecatClient({transport:new Kn.WebSocketTransport({mediaManager:T,serializer:new la,recorderSampleRate:ar,playerSampleRate:or}),enableCam:!1,enableMic:!0,callbacks:{onBotReady:()=>{m=!0,e("idle"),ie()},onDisconnected:()=>{m=!1,_()},onError:g=>{const B=typeof g=="object"&&g!==null&&"data"in g?String(g.data??g):String(g);console.error("[realtimeVoice]",B,g),e("error"),ie()},onTransportStateChanged:g=>{g==="error"&&(e("error"),ie())},onServerMessage:g=>{R(g)},onUserStartedSpeaking:()=>{},onBotStartedSpeaking:()=>{y(),se("bot_started")},onBotStoppedSpeaking:()=>{C&&pe()},onUserTranscript:g=>{String(g.text??""),f.onUserTranscript?.(g.text,!!g.final)},onBotOutput:g=>{f.onBotOutput?.(g.text)}}}),p);return{setDeveloperToken:g=>{},setTtsEngineId:g=>{c=g,A.setStreamTtsEngineId(g)},getTtsEngineId:()=>c,speak:async(g,B)=>{const ne=g.trim();if(ne){if(!p||!m)throw new Error("Realtime voice is not connected. Call connect() first.");ee(),await p.sendText(ne)}},speakWithReply:async(g,B)=>{throw new Error("speakWithReply is not available on the voice session; use AiTwin.speakWithReply()")},stop:()=>{M?.abort(),M=null,z+=1,y(),ee(),e("idle"),ie()},connect:async g=>{g&&(f={...f,...g});const B=tt(f.ttsEngineId,f.voiceId);if(B.ttsEngineId&&(c=B.ttsEngineId,A.setStreamTtsEngineId(c)),f={...f,ttsEngineId:c,...B.voiceId?{voiceId:B.voiceId}:{}},!f.authToken?.trim())throw new Error("Voice connect requires authToken (same JWT as SSE Authorization Bearer).");e("loading");const ne=De();await ne.initDevices();const ue=Ui({...f,ttsEngineId:c});console.info("[realtimeVoice] connecting (avatar_audio_chunk RTVI):",ue);try{await ne.connect({wsUrl:ue})}catch(xe){m=!1,e("error"),ie();const be=xe instanceof Error?xe.message:"Realtime voice connect failed (WebSocket 101 only means upgrade OK — check authToken/origin/RTVI handshake)";throw new Error(`${be} — ${ue}`)}m=!0,e("idle"),ie()},disconnect:async()=>{if(le(),Y=!1,ce=!1,b.length=0,k=!1,M?.abort(),M=null,z+=1,y(),p)try{await p.disconnect()}catch(g){console.error("[realtimeVoice] disconnect failed:",g)}m=!1,_()},isConnected:()=>m,unlockAudio:async()=>{await A.primeAudioContext()},getVisemeQueue:()=>n,getWordQueue:()=>r,getFullVisemeQueue:()=>i,getFullWordQueue:()=>s,getSentenceEmotions:()=>a,getStreamMood:()=>l,getPlaybackElapsedMs:H,isSpeaking:()=>A.isSpeaking(),isWarmingUp:()=>A.isWarmingUp(),releaseWarmupHold:()=>A.releaseWarmupHold(),setLipsyncWarmupHold:(g,B)=>{B&&(W=B),A.setLipsyncWarmupHoldEnabled(g)},getVoiceStream:()=>A.getVoiceStream(),setPlaybackSpeed:g=>{A.setPlaybackSpeed(g)},getPlaybackSpeed:()=>A.getPlaybackSpeed(),subscribe:g=>(L.add(g),()=>L.delete(g))}}function Wi(e,t,n){return{width:e.crop?.source_width??t,height:e.crop?.source_height??n}}function zi(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 Hi(e){return e?(e.w??0)>0&&(e.h??0)>0:!1}async function Ct(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 Bs(r,t)}async function $i(e,t){if(!t)throw new Error("Missing asset key for encrypted JSON");const n=await Ct(e,t),r=new TextDecoder().decode(n);return JSON.parse(r)}async function ga(e){const t=new Blob([e],{type:"image/webp"});return createImageBitmap(t)}async function pa(e){const t=new Blob([e],{type:"image/webp"}),n=URL.createObjectURL(t);return new Promise((r,i)=>{const s=new Image;s.decoding="async",s.onload=()=>{URL.revokeObjectURL(n),r(s)},s.onerror=()=>{URL.revokeObjectURL(n),i(new Error("Failed to decode decrypted image"))},s.src=n})}async function wa(e){const t=new Blob([e],{type:"image/png"});return createImageBitmap(t)}async function ya(e){const t=new Blob([e],{type:"image/png"}),n=URL.createObjectURL(t);return new Promise((r,i)=>{const s=new Image;s.decoding="async",s.onload=()=>{URL.revokeObjectURL(n),r(s)},s.onerror=()=>{URL.revokeObjectURL(n),i(new Error("Failed to decode decrypted PNG"))},s.src=n})}function va(e){const t=new Blob([e],{type:"video/mp4"});return URL.createObjectURL(t)}async function _a(e){const t=Ls();if(!Nt())return t;if(!e)throw new Error("Missing asset key for encrypted idle video");const n=await Ct(t,e);return va(n)}function xt(e,t){return`${e}/${t}_minus_sil.png`}const ji=5;function yn(e){const t=e?.composite_threshold;if(typeof t=="number"&&t>0)return t;const n=e?.crop?.content_threshold;return typeof n=="number"&&n>0?n:ji}const ba=["aa","E","I","O","U","PP","FF","DD","SS","TH","CH","RR","kk","nn"],zn=["t01_0.25","t02_0.50","t03_0.75"],Sa=zn.length,Fr=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 Lr(e,t){return`${e}__${t}`}function Or(e,t){return`pairs/${e}/${t}_minus_sil.png`}function At(e){return`${e}_minus_sil.png`}function cr(e,t){if(t.has(e))return e;const n=/^pairs\/([^/]+)\//.exec(e);if(!n)return null;const r=n[1].split("__")[1];if(!r||r==="sil")return null;const i=At(r);return t.has(i)?i:null}function Ki(e,t){return e.filter(n=>t.has(n))}function Ta(e,t,n){const r=lr(e,t);return Ki(r,n).length>0}function lr(e,t){if(e===t)return[];const n=[],r=Lr(e,t);if(Fr.has(r)){for(const s of zn)n.push(Or(r,s));return n}const i=Lr(t,e);if(Fr.has(i)){for(let s=Sa-1;s>=0;s--)n.push(Or(i,zn[s]));return n}return[]}function ka(e){return e<16?[1]:e<24?[1]:e<35?[0,1,2]:[0,1,2]}function Ea(e,t){return ka(t).map(r=>e[r]).filter(r=>r!=null)}function xa(e,t,n,r){if(r<=0)return 0;const s=Math.max(1,n-t)/r,o=e-t,a=Math.floor(o/s);return Math.min(r-1,Math.max(0,a))}function Gi(e,t,n){if(!n)return`${e}/${t}`;const r=t.split("/").pop()??t,i=r.includes(".")?r.slice(0,r.lastIndexOf(".")):r;return`${e}/${i}.bin`}const Ia=[.32,.24,.16,.08,0],Aa=Ia.map(e=>`eyes_${e.toFixed(2)}`),Ma=["eyes_0.32","eyes_0.16","eyes_0.00"],Ra=["eyes_0.32","eyes_0.16","eyes_0.08","eyes_0.00"],$e=2,Pa=-20,sn=16,qi={fear:-20,anger:-20,sad:-10,neutral:0,love:0,happy:0,disgust:10};function Lt(e){return`brow_${e}`}function gt(e){return qi[e]}function Xe(e){return Math.max(Pa,Math.min(sn,e))}function Ca(e,t){if(e===t)return[];const n=e<t,r=n?$e:-$e,i=[];let s=e;if(s%$e!==0){const o=n?Math.ceil(s/$e)*$e:Math.floor(s/$e)*$e,a=Xe(o);if(n?a>=t:a<=t)return[t];s=a,i.push(s)}for(;;){const o=s+r;if(n?o>=t:o<=t){t!==s&&i.push(t);break}s=o,i.push(s)}return i}function Nr(e){const t=Xe(e);if(t%$e===0)return[t];const n=Math.floor(t/$e)*$e,r=Math.min(sn,n+$e),i=Xe(n);return t-i<=r-t?i===r?[i]:[i,r]:i===r?[r]:[r,i]}const Da=["fear","anger","sad","neutral","love","happy","disgust"],Ba={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 et(e,t="neutral"){const n=String(e??"").trim().toLowerCase();return n?Ba[n]??t:t}function Yi(e){return e===0?null:xt(Lt(e),"eyes_standard")}function Qi(e){return Yi(gt(e))}const Fa={[-20]:"anger",[-10]:"sad",0:"neutral",10:"disgust"};function ur(e,t){if(!e)return null;if(t(e))return e;const n=e.match(/^brow_(-?\d+)\/(eyes_[^/]+)_minus_sil\.png$/);if(n){const i=Number(n[1]),s=n[2];for(const a of Nr(i)){if(a===i)continue;const u=xt(Lt(a),s);if(t(u))return u}const o=Fa[i];if(o){const a=xt(o,s);if(t(a))return a}return null}const r=e.match(/^(fear|anger|sad|neutral|love|happy|disgust)\/(eyes_[^/]+)_minus_sil\.png$/);if(r){const i=r[1],s=r[2],o=gt(i);for(const a of[o,...Nr(o)]){const u=xt(Lt(a),s);if(t(u))return u}}return null}function Ur(e,t){const n=Lt(gt(e));return!t||t==="eyes_standard"?Qi(e):e==="neutral"&&t==="eyes_standard"?null:xt(n,t)}function La(e,t){const n=[];for(const r of t)n.push(Ur(e,r));for(let r=t.length-2;r>=0;r--)n.push(Ur(e,t[r]));return n.push(Qi(e)),n}function Oa(e){return xt(Lt(e),"eyes_standard")}function Na(e,t){return Ca(e,t).map(Oa)}const Ua=6;function Va(e,t){for(const n of e)if(t>=n.wtime&&t<n.wtime+n.wduration)return n;return null}function Wa(e){const t=Xe(e);return t>=sn?sn:Xe(t+Ua)}function za(e,t,n){const r=Xe(n);return Va(t,e)?.emphasis?Wa(r):r}function Vr(e){if(!e)return 0;const t=e.match(/^brow_(-?\d+)\//);if(!t?.[1])return null;const n=Number.parseInt(t[1],10);return Number.isFinite(n)?Xe(n):null}function Qe(e,t){return e+Math.random()*(t-e)}function Wr(){return Qe(14,32)}function Ha(e){if(e)return{holdMinMs:10,holdMaxMs:18,closedExtraMs:0};const t=Math.random();return t<.18?{holdMinMs:38,holdMaxMs:62,closedExtraMs:Qe(40,90)}:t<.42?{holdMinMs:26,holdMaxMs:44,closedExtraMs:Qe(12,36)}:t<.82?{holdMinMs:14,holdMaxMs:28,closedExtraMs:Math.random()<.35?Qe(8,22):0}:{holdMinMs:10,holdMaxMs:18,closedExtraMs:0}}function zr(e,t){const n=Qe(e.holdMinMs,e.holdMaxMs);return t?n+e.closedExtraMs:n}function $a(e={}){const{initialDelayMs:t=800+Math.random()*1200,intervalMinMs:n=2200,intervalMaxMs:r=5800,doubleBlinkChance:i=.18,doubleBlinkGapMinMs:s=120,doubleBlinkGapMaxMs:o=220,fullBlinkChance:a=.75,postEmotionChangeDelayMs:u=380,minDwellMs:d=550}=e;let l="neutral",c="neutral",m=0,p=0,T=0,f={kind:"idle",nextBlinkAt:performance.now()+t},I=null,F="__eyes_open__|neutral|brow:0";function L(M=l){F=`${I??"__eyes_open__"}|${M}|brow:${p}`}function b(M,z=l){I=M;const Y=Vr(M);Y!=null?p=Y:M==null&&(p=0),L(z)}function k(M){return Yi(M)}function V(M,z,Y){const ce=Xe(z),oe=Xe(Y);if(m=oe,ce===oe){b(k(oe));return}const re=[...Na(ce,oe),k(oe)];f={kind:"browBlend",paths:re,index:0,holdUntil:M+Wr(),targetBrow:oe},b(re[0]??null)}function C(M,z){f={kind:"idle",nextBlinkAt:M+Qe(n,r)},c=z,b(k(m),z)}function ae(M,z,Y){const ce=Y?Ma:Math.random()<a?Aa:Ra,oe=Ha(Y),re=ce.length-1;f={kind:"playing",paths:La(z,ce),index:0,holdUntil:M+zr(oe,re===0),after:"idle",blinkEmotion:z,pace:oe,closedFrameIndex:re},c=z,b(f.paths[0]??null,z)}function fe(M){if(f.kind==="browBlend"){for(;M>=f.holdUntil&&f.index<f.paths.length-1;)f.index+=1,f.holdUntil=M+Wr();const z=f.paths[f.index]??null;b(z),M>=f.holdUntil&&f.index>=f.paths.length-1&&(p=f.targetBrow,m=f.targetBrow,b(k(f.targetBrow)),f={kind:"idle",nextBlinkAt:M+u});return}if(f.kind==="idle"){b(k(m),c),M>=f.nextBlinkAt&&ae(M,c,!1);return}if(f.kind==="doublePause"){b(k(m),f.blinkEmotion),M>=f.resumeAt&&ae(M,f.blinkEmotion,!0);return}if(f.kind==="playing"){for(;M>=f.holdUntil&&f.index<f.paths.length-1;)f.index+=1,f.holdUntil=M+zr(f.pace,f.index===f.closedFrameIndex);if(b(f.paths[f.index]??null,f.blinkEmotion),M>=f.holdUntil&&f.index>=f.paths.length-1){if(f.after==="resumeIdle"){C(M+u,l);return}if(f.after==="doublePause"){f={kind:"doublePause",resumeAt:M+Qe(s,o),blinkEmotion:f.blinkEmotion},b(k(m),f.blinkEmotion);return}if(f.after==="idle"&&Math.random()<i){f={kind:"doublePause",resumeAt:M+Qe(s,o),blinkEmotion:f.blinkEmotion},b(k(m),f.blinkEmotion);return}C(M,f.blinkEmotion)}}}return{advance:fe,setTargetEmotion(M,z){const Y=et(M,l);if(Y===l)return;const ce=performance.now();!z?.force&&d>0&&!(l==="neutral"&&Y!=="neutral")&&ce-T<d||(l=Y,c=Y,T=ce)},setTargetEyebrow(M){const z=Xe(M);if(z===m)return;const Y=performance.now(),ce=f.kind==="browBlend"?Vr(I)??p:p;m=z,!(z===ce&&f.kind!=="browBlend")&&(f.kind==="playing"||f.kind==="doublePause"||V(Y,ce,z))},snapToEmotion(M){const z=et(M),Y=gt(z);l=z,c=z,m=Y,p=Y,T=performance.now(),f={kind:"idle",nextBlinkAt:performance.now()+Qe(4e3,7e3)},b(k(Y),z)},getTargetEmotion:()=>l,getTargetEyebrow:()=>m,getExpressionPath:()=>I,getDrawKey:()=>F,reset(){l="neutral",c="neutral",m=0,p=0,T=0,C(performance.now()+Qe(n,r),"neutral")}}}function ja(){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 i=()=>{n&&(URL.revokeObjectURL(n),n=null)};return{async load(s){t&&r===s||(i(),t=!1,r=s,s.startsWith("blob:")&&(n=s),await new Promise((o,a)=>{const u=()=>{const d=e.duration;if(!Number.isFinite(d)||d<=0){a(new Error(`Idle video has invalid duration: ${s}`));return}t=!0,e.currentTime=0,o()};e.addEventListener("loadeddata",u,{once:!0}),e.addEventListener("error",()=>a(new Error(`Failed to load idle video: ${s}`)),{once:!0}),e.src=s,e.load()}))},isReady(){return t},getVideo(){return e},setActive(s){t&&(s?e.paused&&e.play().catch(()=>{}):e.paused||e.pause())},restart(){t&&(e.currentTime=0)},dispose(){e.pause(),e.removeAttribute("src"),e.load(),i(),t=!1,r=""}}}const Ka=50,Xi=400;function Ga(e,t,n){return e.filter(r=>{const i=r.queueIndex??-1;return i>=t&&i<=n})}function qa(e,t){const n=[];for(const r of e){const i=Ga(t,r.start_word,r.end_word);if(i.length===0)continue;const s=i[0],o=i[i.length-1];n.push({sentence:r,startMs:Math.max(0,s.wtime-Ka),endMs:o.wtime+o.wduration+Xi})}return n.sort((r,i)=>r.startMs-i.startMs)}function Ya(e,t,n,r="neutral"){const i=et(r);if(t.length===0)return i;if(n.length===0||e<n[0].wtime)return et(t[0]?.emotion,i);const s=qa(t,n);let o=null;for(const d of s)e>=d.startMs&&e<=d.endMs&&(o=d);if(o)return et(o.sentence.emotion,i);const a=n[n.length-1],u=a.wtime+a.wduration;return e>u+Xi?et(t[t.length-1]?.emotion,i):i}function dr(e,t,n,r,i=ji){const s=new OffscreenCanvas(n,r),o=s.getContext("2d",{willReadFrequently:!0});o.drawImage(e,0,0,n,r);const a=o.getImageData(0,0,n,r),u=o.createImageData(n,r);u.data.set(a.data);const l=new OffscreenCanvas(n,r).getContext("2d",{willReadFrequently:!0});for(const c of t){l.clearRect(0,0,n,r),l.drawImage(c,0,0,n,r);const m=l.getImageData(0,0,n,r);for(let p=0;p<u.data.length;p+=4){const T=m.data[p],f=m.data[p+1],I=m.data[p+2];Math.max(T,f,I)>i&&(u.data[p]=T,u.data[p+1]=f,u.data[p+2]=I,u.data[p+3]=255)}}return o.putImageData(u,0,0),s}let ft=null,Mt=null;const an=new Map;function Qa(){ft=null,Mt=null,an.clear()}mi(Qa);function Xa(e){return e??Mt??void 0}function fr(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 Ja(e){return Nt()?ya(await Ct(rn(),e??"")):fr(rn())}async function Hr(e,t,n,r){const i=n?await $i(e,r):await fetch(e).then(d=>{if(!d.ok)throw new Error(`Failed to load ${e}`);return d.json()}),s=i.sheets?.[0];if(!s?.path)throw new Error(`${e} has no sheets[0].path`);const o=n?await pa(await Ct(Gi(t,s.path,n),r??"")):await fr(`${t}/${s.path}`),a=new Map;for(const d of i.cells??[])d.path&&a.set(d.path,d);const u=new Map;for(const d of i.sheets??[])u.set(d.index,d);return{atlas:o,atlasMeta:i,cellByPath:a,sheetByIndex:u,diffBase:t}}async function Hn(e){const t=Xa(e),n=Nt();if(n&&!t)throw new Error("Encrypted assets enabled but no key provided");if(ft&&(!n||Mt===(t??null))){const s=await ft;return{...Rt(s),visemePaths:[...s.viseme.cellByPath.keys()]}}Mt=t??null,an.clear();const r=hi();ft=(async()=>{const s=await Ja(t),o=await Hr(gi(),r,n,t);let a=null;try{a=await Hr(pi(),r,n,t)}catch{a=null}return{sil:s,viseme:o,expression:a}})();const i=await ft;return{...Rt(i),visemePaths:[...i.viseme.cellByPath.keys()]}}async function mr(e){if(await Hn(e),!ft)throw new Error("Assets not loaded");return ft}function Rt(e){return Wi(e.viseme.atlasMeta,e.sil.naturalWidth,e.sil.naturalHeight)}function Za(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 on(e,t,n){const r=`${t.diffBase}::${n}`,i=an.get(r);if(i)return i;const s=(async()=>{const o=t.cellByPath.get(n);if(!o)throw new Error(`No atlas cell for path: ${n}`);const a=zi(t.atlasMeta,o),u=Rt(e);if(Hi(o)){const c=Za(t,o),m=document.createElement("canvas");m.width=u.width,m.height=u.height;const p=m.getContext("2d");return p.fillStyle="#000",p.fillRect(0,0,u.width,u.height),p.drawImage(c,a.x,a.y),m}const d=`${t.diffBase}/${n}`,l=await fr(d);if(l.naturalWidth===u.width&&l.naturalHeight===u.height)return l;throw new Error(`Diff PNG wrong size for ${n}`)})();return an.set(r,s),s}async function Pn(e,t,n,r,i,s){if(i){const{width:p,height:T}=i;if(s&&!s()||t.readyState<HTMLMediaElement.HAVE_CURRENT_DATA)return;const f=document.createElement("canvas");f.width=p,f.height=T;const I=f.getContext("2d");if(I.clearRect(0,0,p,T),I.drawImage(t,0,0,p,T),s&&!s())return;(e.width!==p||e.height!==T)&&(e.width=p,e.height=T);const F=e.getContext("2d");F.clearRect(0,0,p,T),F.drawImage(f,0,0);return}const o=await mr(),a=yn(o.viseme.atlasMeta),{width:u,height:d}=Rt(o);(e.width!==u||e.height!==d)&&(e.width=u,e.height=d);const l=[],c=e.getContext("2d");if(c.clearRect(0,0,u,d),t.readyState<HTMLMediaElement.HAVE_CURRENT_DATA){const p=o.sil;c.drawImage(p,0,0,u,d);return}if(l.length===0){c.drawImage(t,0,0,u,d);return}const m=dr(t,l,u,d,a);c.drawImage(m,0,0)}async function $n(e,t,n){const r=await mr(Mt??void 0),i=yn(r.viseme.atlasMeta),{width:s,height:o}=Rt(r);(e.width!==s||e.height!==o)&&(e.width=s,e.height=o);const a=[];if(t.mouthPath){const l=new Set(r.viseme.cellByPath.keys()),c=cr(t.mouthPath,l)??(l.has(t.mouthPath)?t.mouthPath:null);c&&a.push(await on(r,r.viseme,c))}if(t.expressionPath&&r.expression){const l=ur(t.expressionPath,c=>r.expression.cellByPath.has(c));l&&a.push(await on(r,r.expression,l))}const u=e.getContext("2d");if(u.clearRect(0,0,s,o),a.length===0){u.drawImage(r.sil,0,0,s,o);return}const d=dr(r.sil,a,s,o,i);u.drawImage(d,0,0)}async function eo(e,t){const n=await mr(Mt??void 0),r=yn(n.viseme.atlasMeta),{width:i,height:s}=Rt(n),o=[];if(e.mouthPath){const l=new Set(n.viseme.cellByPath.keys()),c=cr(e.mouthPath,l)??(l.has(e.mouthPath)?e.mouthPath:null);c&&o.push(await on(n,n.viseme,c))}if(e.expressionPath&&n.expression){const l=ur(e.expressionPath,c=>n.expression.cellByPath.has(c));l&&o.push(await on(n,n.expression,l))}const a=new OffscreenCanvas(i,s),u=a.getContext("2d");if(o.length===0)return u.drawImage(n.sil,0,0,i,s),a.transferToImageBitmap();const d=dr(n.sil,o,i,s,r);return u.drawImage(d,0,0),a.transferToImageBitmap()}async function to(e){await $n(e,{mouthPath:null,expressionPath:null})}const Jt={fontFamily:"system-ui, -apple-system, sans-serif",fontSize:"clamp(0.875rem, 2.5vw, 1.125rem)",color:"rgba(255,255,255,0.85)"};function no(e){return e.length===0?"":e.map(t=>t.word).join(" ")}function ro(e){if(!e)return{enabled:!1,style:Jt};const t=e===!0?{}:e;return{enabled:!0,style:{fontFamily:t.fontFamily??Jt.fontFamily,fontSize:t.fontSize??Jt.fontSize,color:t.color??Jt.color}}}const io={position:"absolute",bottom:0,left:0,right:0,display:"flex",justifyContent:"center",padding:"0.75rem 1rem",pointerEvents:"none"},so={display:"inline-block",maxWidth:"100%",padding:"0.45rem 0.85rem",borderRadius:"0.75rem",background:"rgba(0,0,0,0.55)",lineHeight:1.4,textAlign:"center"},ao={display:"-webkit-box",WebkitLineClamp:2,WebkitBoxOrient:"vertical",overflow:"hidden",maxWidth:"100%",margin:0};function oo({text:e,style:t}){return D.jsx("div",{style:io,"aria-live":"polite","aria-atomic":"true",children:D.jsx("div",{style:{...so,fontFamily:t.fontFamily,fontSize:t.fontSize,color:t.color},children:D.jsx("p",{style:ao,children:e})})})}const co={inset:0,overflow:"hidden",pointerEvents:"none",position:"absolute",zIndex:3},lo={filter:"blur(22px)",height:"100%",inset:0,objectFit:"cover",objectPosition:"top",position:"absolute",transform:"scale(1.08)",width:"100%"},uo={backdropFilter:"blur(10px)",WebkitBackdropFilter:"blur(10px)",inset:0,position:"absolute"};function fo({thumbnailUrl:e}){const[t,n]=h.useState(!1);h.useEffect(()=>{n(!1)},[e]);const r=!!e&&t;return D.jsxs("div",{style:co,"aria-hidden":!0,children:[e?D.jsx("img",{src:e,alt:"",style:{...lo,opacity:r?1:0,transition:"opacity 0.45s ease"},onLoad:()=>n(!0),onError:()=>n(!1)}):null,D.jsx("div",{style:{...uo,background:r?"rgba(0, 0, 0, 0.28)":"rgba(10, 10, 11, 0.92)"}})]})}let Ji=null;function $r(e){Ji=e}function at(){return Ji}function mo(e){return`${e.from}→${e.to}@${e.fromVtime}`}function jr(){return{rafTicksSpeaking:0,rafTicksDeduped:0,drawsRequested:0,drawsDisplayed:0,queueSuperseded:0,workerStale:0,rifeFramesOmittedByGap:0,transitionFramesSampled:0,transitionFramesDisplayed:0,transitionFramesMissed:0,bufferTicks:0,bufferHits:0,bufferUnderruns:0,bufferPrefetched:0}}function ho(){let e=jr();const t=new Set,n=new Set,r=new Set;let i="",s=-1,o="";const a=()=>{e=jr(),t.clear(),n.clear(),r.clear(),i="",s=-1,o=""},u=l=>{t.add(l)},d=l=>{l&&r.add(l)};return{reset:a,onRafTickSpeaking(){e.rafTicksSpeaking+=1},onDrawDeduped(){e.rafTicksDeduped+=1},onDrawRequested(){e.drawsRequested+=1},onQueueSuperseded(){e.queueSuperseded+=1},onWorkerStale(){e.workerStale+=1},onTransitionSample(l,c){const m=mo(l);e.transitionFramesSampled+=1,m!==i&&(i=m,s=-1,o!==m&&(o=m,e.rifeFramesOmittedByGap+=l.omittedByGap)),c&&n.add(c),s>=0&&l.frameIdx>s+1&&(e.transitionFramesMissed+=l.frameIdx-s-1),s=l.frameIdx},onBufferTick(){e.bufferTicks+=1},onBufferHit(){e.bufferHits+=1},onBufferUnderrun(){e.bufferUnderruns+=1},onBufferPrefetched(){e.bufferPrefetched+=1},onBufferReset(){},onDrawDisplayed(l,c){if(e.drawsDisplayed+=1,l.transitionMeta){e.transitionFramesDisplayed+=1;const p=l.transitionMeta;u(p.fromVtime),u(p.toVtime),d(l.mouthPath);return}if(l.label.includes("→")){e.transitionFramesDisplayed+=1;return}const m=l.label.trim();if(!(!m||m==="sil")){for(const p of c)if(p.viseme===m&&l.elapsedMs>=p.vtime&&l.elapsedMs<p.vtime+p.vduration){u(p.vtime);break}}},snapshot(l,c){let m=0,p=0;for(const L of l)if(L.viseme!=="sil"){if(L.vtime>=c)break;m+=1,t.has(L.vtime)&&(p+=1)}const T=m>0?Math.round(p/m*100):100,f=e.queueSuperseded+e.workerStale+Math.max(0,e.drawsRequested-e.drawsDisplayed),I=m-p,F=e.bufferTicks>0?Math.round(e.bufferHits/e.bufferTicks*100):100;return{...e,bufferHitRate:F,renderLoss:f,visemeSlotsTotal:m,visemeSlotsCovered:p,visemeCoveragePct:T,transitionFramesUniqueSampled:n.size,transitionFramesUniquePainted:r.size,drawsDeduped:e.rafTicksDeduped,renderSkips:e.rafTicksDeduped+f,visemesShown:p,visemesSkipped:I,rifeTransitionFramesSkipped:e.transitionFramesMissed}}}}const Zi=qn,go=200,Kr=300,po=100,wo=600,es="__sil__";function Gr(e){return e.lastDrawnKey?e.lastDrawnKey.split("|")[0]===es:!1}function hr(){return{lastDrawnKey:""}}function Ne(e){e.lastDrawnKey="",e.transitionCache=void 0}function yo(e,t){if(t?.transitionCache&&t.transitionCache.queueLength===e.length)return t.transitionCache.transitions;const n=Pi(e);return t&&(t.transitionCache={queueLength:e.length,transitions:n}),n}function vo(e,t){let n="sil";for(const r of e)r.viseme!=="sil"&&(t!=null&&r.vtime>t||(n=r.viseme));return n}function _o(e,t,n,r=120){if(n!=="sil")return n;const i=Ni(e,t,r);return i!=="sil"?i:vo(e,t)}function bo(e,t){return e==="sil"?!1:t?Ta(e,"sil",t):lr(e,"sil").length>0}function So(){return Zi+wo}function cn(e){return e??es}function gr(e,t,n,r,i=po){if(e.length===0)return{diffPath:null,label:"sil"};if(t>=dt(e))return{diffPath:null,label:"sil"};const s=yo(e,r),o=ra(s,t);if(o){const d=Ci(o.fromVtime,o.toVtime,o.from,o.to);if(t>=d.transStart&&t<d.transEnd){let l=lr(o.from,o.to);n&&(l=Ki(l,n));const c=Ea(l,d.effectiveGapMs);if(c.length>0){const m=xa(t,d.transStart,d.transEnd,c.length);return{diffPath:c[m]??c[c.length-1],label:`${o.from}→${o.to}`,transitionMeta:{from:o.from,to:o.to,fromVtime:o.fromVtime,toVtime:o.toVtime,frameIdx:m,frameCount:c.length,fullFrameCount:l.length,omittedByGap:Math.max(0,l.length-c.length)}}}return{diffPath:At(o.to),label:o.to}}}const a=hn(e);let u=Ii(a,t);return u==="sil"&&(u=Ni(e,t,i)),u==="sil"?{diffPath:null,label:"sil"}:{diffPath:At(u),label:u}}function Ot(e,t){const n=t??cn(e.expressionPath);return`${cn(e.mouthPath)}|${n}`}function qr(e,t,n,r,i,s,o,a,u,d){const l=gr(t,n,u,s),c={mouthPath:l.diffPath,expressionPath:r},m=Ot(c,i),p=at();if(l.transitionMeta&&p?.onTransitionSample(l.transitionMeta,l.diffPath),m===s.lastDrawnKey){p?.onDrawDeduped();return}p?.onDrawRequested(),a(l),s.lastDrawnKey=m,o(e,c,m,T=>{T===m&&(s.lastDrawnKey=m)})}function Cn(e,t,n,r,i,s,o=null,a=null){const u={mouthPath:a,expressionPath:t},d=o!=null?`|idle@${Math.round(o*1e3)}`:"",l=Ot(u,n)+d;!(o!=null)&&l===r.lastDrawnKey||(s(o!=null?t?"idle · blink":"idle":t?"blink":"sil"),i(e,u,l,m=>{m===l&&(r.lastDrawnKey=l)}))}function ts(e,t,n,r,i=Ft,s){if(n<=t||e.length===0)return[];const o=s??hr(),a=[];let u="";for(let d=t;d<n;d+=i){const l=gr(e,d,r,o),c=cn(l.diffPath);c!==u&&(u=c,a.push({displayAtMs:d,mouthPath:l.diffPath,mouthKey:c,label:l.label}))}return a}const To=3;function pr(e){let t=0;const n=[];let r=!1,i=!1;const s=async()=>{if(!r){r=!0;try{for(;n.length>0;){const a=n.shift(),u=++t;await e(a.diffs,u,a)&&u===t&&a.onDisplayed?.(a.drawKey)}}finally{r=!1,n.length>0&&s()}}},o=()=>{i||(i=!0,queueMicrotask(()=>{i=!1,s()}))};return{enqueue(a,u,d){const l=n.findIndex(c=>c.drawKey===u);l>=0?n[l]={diffs:a,drawKey:u,onDisplayed:d}:(n.length>=To&&(n.shift(),at()?.onQueueSuperseded()),n.push({diffs:a,drawKey:u,onDisplayed:d})),o()},reset(){t+=1,n.length=0},isLatestSeq(a){return a===t},getLatestSeq(){return t}}}function ko(e,t=2){const n=[],r=new Set;let i=0,s=!1,o=0;const a=(d,l)=>`${d}|${l}`,u=async()=>{if(!s){s=!0;try{for(;i<t&&n.length>0;){const d=n.shift(),l=a(d.displayAtMs,d.drawKey);if(r.has(l))continue;r.add(l),i+=1;const c=o;try{await e(d)}finally{if(r.delete(l),i-=1,c!==o)return}}}finally{s=!1,n.length>0&&i<t&&u()}}};return{enqueue(d){const l=a(d.displayAtMs,d.drawKey);r.has(l)||n.some(c=>a(c.displayAtMs,c.drawKey)===l)||(n.push(d),u())},isQueuedOrInflight(d,l){const c=a(d,l);return r.has(c)?!0:n.some(m=>a(m.displayAtMs,m.drawKey)===c)},reset(){o+=1,n.length=0,r.clear(),i=0},pendingCount(){return n.length+i}}}function Eo(){const e=new Map,t=n=>{n.bitmap.close()};return{has(n,r){return e.has(r)},markRendered(n,r,i,s,o){const a=e.get(r);a&&t(a),e.set(r,{displayAtMs:n,mouthKey:r,label:i,mouthPath:s,bitmap:o})},findForMouthKey(n){return e.get(n)??null},removeThrough(n){},pruneBefore(n){},reset(){for(const n of e.values())t(n);e.clear()},size(){return e.size}}}function xo(e,t,n,r,i,s){const o=ts(t,n,r,i,Ft,s);if(o.length===0)return{ready:0,total:0};let a=0;for(const u of o)e.has(u.displayAtMs,u.mouthKey)&&(a+=1);return{ready:a,total:o.length}}function Io(e){const t=Eo(),n=hr(),r=new Set;let i="",s=null;const o=ko(async c=>{try{if(!e.supportsBufferedPlayback)return;const m=await e.compositePrefetchFrame(c.diffs,c.mouthKey);if(!m)return;t.markRendered(c.displayAtMs,c.mouthKey,c.label,c.mouthPath,m),at()?.onBufferPrefetched()}finally{r.delete(c.mouthKey)}},_s),a=c=>{for(const m of c)t.has(m.displayAtMs,m.mouthKey)||r.has(m.mouthKey)||o.isQueuedOrInflight(0,m.mouthKey)||(r.add(m.mouthKey),o.enqueue({...m,displayAtMs:0,drawKey:m.mouthKey,diffs:{mouthPath:m.mouthPath,expressionPath:null}}))},u=(c,m,p,T=Mn)=>{if(!e.supportsBufferedPlayback)return;const f=Math.max(0,m-Ft*4),I=ts(c,f,m+T,p,Ft,n);a(I)},d=(c,m)=>{i=c,s=m},l=(c,m)=>!(i!==c||s!==m);return{reset(){t.reset(),o.reset(),r.clear(),Ne(n),i="",s=null,at()?.onBufferReset()},markExternallyDisplayed(c,m){d(c.split("|")[0]??c,m)},warmupTick(c){e.supportsBufferedPlayback&&u(c.queue,0,c.availablePaths,Math.max(Ir,Mn))},isWarmupReady(c,m=Ir){if(!e.supportsBufferedPlayback)return!0;const{ready:p,total:T}=xo(t,c.queue,0,m,c.availablePaths,n);return T===0?!1:p/T>=vs},getBufferedFrameCount:()=>t.size(),tick(c){const m=at();m?.onBufferTick(),u(c.queue,c.elapsedMs,c.availablePaths),t.pruneBefore(c.elapsedMs-Mn);const p=gr(c.queue,c.elapsedMs,c.availablePaths,n),T=cn(p.diffPath),f=Ot({mouthPath:p.diffPath,expressionPath:c.expressionPath},c.expressionDrawKey),I=()=>(d(T,c.expressionPath),m?.onBufferHit(),{usedBuffer:!0,underrun:!1,held:!0});if(l(T,c.expressionPath)||c.playbackState.lastDrawnKey===f)return I();const F=t.findForMouthKey(T,c.elapsedMs,Ft);return F&&c.expressionPath!=null?(m?.onBufferHit(),{usedBuffer:!1,underrun:!1,held:!1}):F?(e.blitBitmap(c.canvas,F.bitmap),d(F.mouthKey,c.expressionPath),c.playbackState.lastDrawnKey=f,c.onStatus({diffPath:F.mouthPath,label:F.label}),c.onDisplayed(f,F.mouthPath,F.label),m?.onBufferHit(),{usedBuffer:!0,underrun:!1,held:!1}):(m?.onBufferUnderrun(),{usedBuffer:!1,underrun:!0,held:!1})}}}const Ao=`
|
|
6
6
|
in vec2 aPosition;
|
|
7
7
|
out vec2 vTextureCoord;
|
|
8
8
|
|
|
@@ -30,7 +30,7 @@ void main(void)
|
|
|
30
30
|
gl_Position = filterVertexPosition();
|
|
31
31
|
vTextureCoord = filterTextureCoord();
|
|
32
32
|
}
|
|
33
|
-
`,
|
|
33
|
+
`,Mo=`
|
|
34
34
|
in vec2 vTextureCoord;
|
|
35
35
|
out vec4 finalColor;
|
|
36
36
|
|
|
@@ -44,5 +44,5 @@ void main(void)
|
|
|
44
44
|
float keep = step(uThreshold + 1e-6, peak);
|
|
45
45
|
finalColor = vec4(color.rgb, keep);
|
|
46
46
|
}
|
|
47
|
-
`;function Gr(e=5){const t=new we.Filter({glProgram:we.GlProgram.from({vertex:Io,fragment:Ao,name:"threshold-key-filter"}),resources:{thresholdUniforms:{uThreshold:{value:e/255,type:"f32"}}}});return t.setThreshold=n=>{t.resources.thresholdUniforms.uniforms.uThreshold=n/255},t.getThreshold=()=>Math.round(t.resources.thresholdUniforms.uniforms.uThreshold*255),t}function Mo(e,t,n){return e>n||t>n}function Po(e){return e?e.getParameter(e.MAX_TEXTURE_SIZE):4096}function Co(e,t){return t!=null&&t>0?Math.floor(t):Po(e)}function Ro(e,t){const n=document.createElement("canvas");n.width=t.w,n.height=t.h;const r=n.getContext("2d");if(!r)throw new Error("Failed to acquire 2d context for atlas cell crop");return r.drawImage(e,t.x,t.y,t.w,t.h,0,0,t.w,t.h),n}function ts(e){return fetch(e).then(t=>{if(!t.ok)throw new Error(`Failed to load image: ${e}`);return t.blob()}).then(t=>createImageBitmap(t))}async function qr(e,t,n,r,i){const s=n?await Hi(e,i):await fetch(e).then(c=>{if(!c.ok)throw new Error(`Failed to load ${e}`);return c.json()}),o=s.sheets?.[0];if(!o?.path)throw new Error(`${e} has no sheets[0].path`);const a=new Map,u=async(c,m)=>{const w=Ki(t,m,n),T=n?await ha(await Mt(w,i??"")):await ts(w);if(Mo(T.width,T.height,r))return console.info(`[PixiVisemeCompositor] Sheet ${m} (${T.width}x${T.height}) exceeds MAX_TEXTURE_SIZE=${r}; using per-cell crops.`),{mode:"cells",bitmap:T};const f=we.Texture.from(T);return f.source.scaleMode="nearest",{mode:"full",texture:f}};a.set(o.index,await u(o.index,o.path));for(const c of s.sheets??[])c.index!==o.index&&c.path&&a.set(c.index,await u(c.index,c.path));const d=new Map;for(const c of s.cells??[])c.path&&d.set(c.path,c);const l=new Map;for(const c of s.sheets??[])l.set(c.index,c);return{atlasMeta:s,cellByPath:d,sheetByIndex:l,diffBase:t,sheets:a}}async function Do(e,t={}){const n=new we.Application;try{await n.init({canvas:e,width:842,height:1264,preference:"webgl",autoStart:!1,antialias:!1,resolution:1,autoDensity:!1,backgroundAlpha:1,backgroundColor:0,powerPreference:"high-performance"})}catch(p){throw n.destroy({removeView:!1}),p}if(n.renderer.type!==we.RendererType.WEBGL)throw n.destroy({removeView:!1}),new Error("Pixi did not initialize a WebGL renderer");const r=Co(n.renderer.gl,t.maxTextureSize);let i=!1,s=!1,o=!1;const a=n.canvas,u=()=>{i=!0,!s&&!o&&(s=!0,t.onWebGlContextLost?.())};a.addEventListener("webglcontextlost",u);const d=new we.Sprite(we.Texture.EMPTY),l=new we.Sprite(we.Texture.EMPTY);l.visible=!1,l.alpha=0;const c=new we.Sprite(we.Texture.EMPTY),m=new we.Sprite(we.Texture.EMPTY),w=new we.Sprite(we.Texture.EMPTY);w.visible=!1;const T=Gr(5),f=Gr(5);c.filters=[T],m.filters=[f],n.stage.addChild(d),n.stage.addChild(l),n.stage.addChild(c),n.stage.addChild(m),n.stage.addChild(w);let E=null,D=null,B=null,v=null,k=null,L=null,A=null,ie=842,de=1264,I=null,V=5;const G=new Map;let ae=null,se=null,re=null;const O=fi(()=>{G.clear(),L=null,A=null,E=null,I=null}),J=(p,S)=>{ie=p,de=S,n.renderer.resize(p,S),(e.width!==p||e.height!==S)&&(e.width=p,e.height=S)},W=()=>{c.visible=!1,m.visible=!1,c.texture=we.Texture.EMPTY,m.texture=we.Texture.EMPTY,ae=null,se=null},he=()=>{k=null,l.visible=!1,l.alpha=0},K=()=>{d.visible=!0,d.width=ie,d.height=de,d.x=0,d.y=0},ee=()=>{l.width=ie,l.height=de,l.x=0,l.y=0},$=()=>{w.visible=!1,he(),E&&(d.texture=E,K())},X=()=>{!k&&!l.visible||$()},_e=p=>{if(o||i||!E){$();return}const S=Math.max(0,p);if(!D||S<=0){$();return}W(),w.visible=!1,d.texture=D,K(),l.texture=E,ee(),l.alpha=0,l.visible=!0,k={startMs:performance.now(),durationMs:S},q()},oe=(p=performance.now())=>{if(!k)return!1;if(o||i)return X(),!1;const S=(p-k.startMs)/Math.max(1,k.durationMs);if(S>=1)return $(),q(),!1;const x=Math.min(1,Math.max(0,S)),_=x*x*(3-2*x);return l.alpha=_,l.visible=!0,q(),!0},b=()=>{if(B){try{B.resource=null}catch{}B.destroy(),B=null}D&&(D.destroy(!1),D=null),v=null},P=(p,S)=>{const x=p.cellByPath.get(S);if(!x||!zi(x))return null;const _=`${p.diffBase}::${S}`;let U=G.get(_);if(!U){const Z=x.sheet??0,te=p.sheets.get(Z);if(!te)return null;let z,be=!1;if(te.mode==="full")z=new we.Texture({source:te.texture.source,frame:new we.Rectangle(x.x,x.y,x.w,x.h)});else{const Xe=Ro(te.bitmap,x);z=we.Texture.from(Xe),z.source.scaleMode="nearest",be=!0}U={texture:z,ownsSource:be},G.set(_,U)}return{texture:U.texture,cell:x}},H=(p,S,x,_)=>{if(!_||!x)return p.visible=!1,p.texture=we.Texture.EMPTY,!1;const U=P(x,_);if(!U)return p.visible=!1,p.texture=we.Texture.EMPTY,!1;const Z=Wi(x.atlasMeta,U.cell);return S.setThreshold(V),p.texture=U.texture,p.x=Z.x,p.y=Z.y,p.width=U.cell.w,p.height=U.cell.h,p.visible=!0,!0},le=p=>{if(!p||!L)return null;const S=I??new Set(L.cellByPath.keys());return ir(p,S)??(S.has(p)?p:null)},j=p=>{w.visible=!1,$();const S=le(p.mouthPath),x=p.expressionPath&&A?ar(p.expressionPath,_=>A.cellByPath.has(_)):null;S!==ae?(H(c,T,L,S),ae=S):S?c.visible=!0:c.visible=!1,x!==se?(H(m,f,A,x),se=x):x?m.visible=!0:m.visible=!1},q=()=>{if(!(o||i||document.hidden))try{n.render()}catch{}};return{async loadAssets(p){if(o)return{width:ie,height:de,visemePaths:[]};const S=Wt();if(S&&!p)throw new Error("Encrypted assets enabled but no key provided");const x=S?await wa(await Mt(sn(),p??"")):await ts(sn());E&&E.destroy(!0),E=we.Texture.from(x),E.source.scaleMode="linear";const _=mi();L=await qr(hi(),_,S,r,p);try{A=await qr(gi(),_,S,r,p)}catch(Z){console.warn("[PixiVisemeCompositor] expression atlas unavailable:",Z),A=null}const U=Ui(L.atlasMeta,x.width,x.height);return J(U.width,U.height),V=vn(L.atlasMeta),T.setThreshold(V),f.setThreshold(V),I=new Set(L.cellByPath.keys()),G.clear(),$(),W(),q(),{width:U.width,height:U.height,visemePaths:[...L.cellByPath.keys()]}},getVisemeAtlasPaths(){return I},drawLiveFrame(p){o||i||!E||(X(),j(p),q())},drawIdleVideo(p,S){o||i||document.hidden||S&&!S()||p.readyState<HTMLMediaElement.HAVE_CURRENT_DATA||(he(),W(),w.visible=!1,!D||v!==p?(b(),B=new we.VideoSource({resource:p,autoPlay:!1,updateFPS:0}),B.autoUpdate=!1,D=new we.Texture({source:B}),v=p):D.source.update(),d.texture=D,K(),q())},beginIdleToSilCrossfade:_e,tickIdleToSilCrossfade:oe,finishIdleToSilCrossfade:X,isIdleToSilCrossfading(){return k!=null},renderSilOnly(){o||i||!E||(W(),$(),q())},blitBitmap(p){o||i||(X(),W(),re&&(re.destroy(!0),re=null),re=we.Texture.from(p),w.texture=re,w.visible=!0,w.x=0,w.y=0,w.width=ie,w.height=de,d.visible=!1,q())},async compositePrefetchFrame(p){return null},renderFrame:q,isContextLost(){return i},dispose(){if(o)return;o=!0,a.removeEventListener("webglcontextlost",u),O(),b(),re&&(re.destroy(!0),re=null);for(const{texture:S,ownsSource:x}of G.values())S.destroy(x);G.clear(),E&&(E.destroy(!0),E=null);const p=S=>{S.mode==="full"?S.texture.destroy(!0):S.bitmap.close()};if(L)for(const S of L.sheets.values())p(S);if(A)for(const S of A.sheets.values())p(S);T.destroy(!0),f.destroy(!0),n.destroy({removeView:!1},{children:!0,texture:!0})}}}const Yr=-1,tn=1e5,Qr=new Map;async function Bo(e){let t=Qr.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),Qr.set(e,t)}return new Worker(t,{name:"visemeDiffPreview"})}function Fo(){return typeof Worker<"u"&&typeof OffscreenCanvas<"u"}function zn(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 Xr(e,t){let n=0,r=null;const i=fr(async(s,o)=>(await Un(),await Wn(e,s),i.isLatestSeq(o)));return{usesWorker:!1,usesPixi:!1,async loadAssets(s){const o=await Un(s);return r=o.visemePaths?new Set(o.visemePaths):null,o},getVisemeAtlasPaths(){return r},async renderSilOnly(){n+=1,i.reset(),await eo(e)},drawLiveFrame(s,o,a,u){i.enqueue(o,a,u)},async compositePrefetchFrame(s,o){try{return await Za(s)}catch{return null}},blitBitmap(s,o){zn(s,o)},drawIdleVideo(){},beginIdleToSilCrossfade(){},tickIdleToSilCrossfade(){return!1},finishIdleToSilCrossfade(){},isIdleToSilCrossfading(){return!1},supportsBufferedPlayback:!0,async renderViseme(s,o){n+=1;const a=n;t.onStatus?.(o),await Wn(s,{mouthPath:xt(o),expressionPath:null})},dispose(){n+=1,i.reset()}}}function Lo(e,t,n){let r=null,i=1,s=0,o=!1,a=!1,u=null;const d=new Map,l=new Map;let c=tn;const m=fr(async(B,v,k)=>(d.set(v,{drawKey:k.drawKey,onDisplayed:k.onDisplayed}),await E({type:"drawFrame",diffPath:B.mouthPath,expressionDiffPath:B.expressionPath,liveSeq:v},void 0,!0),!1)),w=B=>{if(B===Yr){let L=-1,A;for(const[ie,de]of d)ie>=L&&(L=ie,A=de);L>=0&&d.delete(L),A?.onDisplayed?.(A.drawKey);return}const v=-B,k=d.get(v);d.delete(v),k?.onDisplayed?.(k.drawKey)},T=new Map,f=(B,v)=>{a||!r||r.postMessage(B,[])},E=(B,v,k=!1)=>{if(a)return Promise.resolve();const L=i++;return new Promise((A,ie)=>{T.set(L,{resolve:de=>A(de),reject:ie,generation:typeof B.generation=="number"?B.generation:void 0,expectRenderDone:k}),f({...B,requestId:L})})},D=(async()=>{r=await Bo(n),r.onmessage=B=>{if(a)return;const v=B.data;if(v.type==="status"){t.onStatus?.(v.label);return}if(v.type==="frame"){if(v.generation<=-tn){const A=-v.generation,ie=l.get(A);l.delete(A),ie?.resolve(v.bitmap);return}const L=v.generation<0;if(!L&&v.generation!==s){v.bitmap.close();return}if(L&&!(v.generation===Yr)){const ie=-v.generation;if(!m.isLatestSeq(ie)){at()?.onWorkerStale(),v.bitmap.close();return}}if(L&&t.shouldAcceptLiveFrame&&!t.shouldAcceptLiveFrame()){at()?.onWorkerStale(),v.bitmap.close();return}zn(e,v.bitmap),v.bitmap.close(),L&&w(v.generation);return}const k=T.get(v.requestId);if(k)switch(v.type){case"ready":T.delete(v.requestId),k.resolve();break;case"loadAssetsDone":T.delete(v.requestId),u=v.visemePaths?.length?new Set(v.visemePaths):null,k.resolve({width:v.width,height:v.height,visemePaths:v.visemePaths});break;case"renderDone":if(k.expectRenderDone&&k.generation!=null&&v.generation!==k.generation)return;T.delete(v.requestId),k.resolve();break;case"renderAborted":T.delete(v.requestId),k.resolve();break;case"error":T.delete(v.requestId),t.onError?.(v.message),k.reject(new Error(v.message));break}},r.onerror=B=>{if(a)return;const v=B.message||"Worker error";t.onError?.(v);for(const[,k]of T)k.reject(new Error(v));T.clear()},await E({type:"init"}),o=!0})();return{usesWorker:!0,usesPixi:!1,async loadAssets(B){if(a)return{width:842,height:1264};if(await D,a)return{width:842,height:1264};if(!o)throw new Error("Worker init failed");return await E({type:"loadAssets",keyHex:B,urls:Bs(wt())})??{width:842,height:1264}},getVisemeAtlasPaths(){return u},async renderSilOnly(){if(a||(await D,a))return;s+=1,m.reset(),d.clear(),l.forEach(({resolve:v})=>v(null)),l.clear(),c=tn;const B=s;await E({type:"cancelLiveDraws"}),await E({type:"renderSil",generation:B},void 0,!0)},drawLiveFrame(B,v,k,L){a||D.then(()=>{a||m.enqueue(v,k,L)})},compositePrefetchFrame(B,v){return a?Promise.resolve(null):D.then(()=>{if(a)return null;const k=++c;return new Promise(L=>{l.set(k,{resolve:L}),E({type:"drawFrame",diffPath:B.mouthPath,expressionDiffPath:B.expressionPath,liveSeq:k},void 0,!0).catch(()=>{l.delete(k),L(null)})})})},blitBitmap(B,v){zn(B,v)},drawIdleVideo(){},beginIdleToSilCrossfade(){},tickIdleToSilCrossfade(){return!1},finishIdleToSilCrossfade(){},isIdleToSilCrossfading(){return!1},supportsBufferedPlayback:!0,async renderViseme(B,v,k={}){if(a||(await D,a))return;s+=1,m.reset(),d.clear();const L=s;try{await E({type:"cancelLiveDraws"}),await E({type:"renderViseme",generation:L,to:v,from:k.from,transitionDurationMs:k.transitionDurationMs,gapMs:k.gapMs,threshold:k.threshold},void 0,!0)}catch(A){if(A?.name==="AbortError")return;throw A}},dispose(){if(!a){a=!0,s+=1,m.reset(),d.clear(),l.forEach(({resolve:B})=>B(null)),l.clear(),c=tn;for(const[,B]of T)B.resolve();T.clear(),r?.terminate(),r=null}}}}async function Oo(e,t){const n=await Do(e,{onWebGlContextLost:t.onWebGlContextLost,maxTextureSize:t.pixiMaxTextureSize});let r=0,i=null,s=!1;const o=fr(async(a,u)=>s?!1:t.shouldAcceptLiveFrame&&!t.shouldAcceptLiveFrame()?(at()?.onWorkerStale(),!1):(n.drawLiveFrame(a),o.isLatestSeq(u)));return{usesWorker:!1,usesPixi:!0,async loadAssets(a){if(s)return{width:842,height:1264};const u=await n.loadAssets(a);return i=u.visemePaths?.length?new Set(u.visemePaths):null,u},getVisemeAtlasPaths(){return i},async renderSilOnly(){s||(r+=1,o.reset(),n.renderSilOnly())},drawLiveFrame(a,u,d,l){s||o.enqueue(u,d,l)},async compositePrefetchFrame(a,u){if(s)return null;try{return await n.compositePrefetchFrame(a)}catch{return null}},blitBitmap(a,u){s||t.shouldAcceptLiveFrame&&!t.shouldAcceptLiveFrame()||n.blitBitmap(u)},drawIdleVideo(a,u){s||n.drawIdleVideo(a,u)},beginIdleToSilCrossfade(a){s||n.beginIdleToSilCrossfade(a)},tickIdleToSilCrossfade(a){return s?!1:n.tickIdleToSilCrossfade(a)},finishIdleToSilCrossfade(){s||n.finishIdleToSilCrossfade()},isIdleToSilCrossfading(){return s?!1:n.isIdleToSilCrossfading()},supportsBufferedPlayback:!1,async renderViseme(a,u){if(s)return;r+=1;const d=r;o.reset(),t.onStatus?.(u),n.drawLiveFrame({mouthPath:xt(u),expressionPath:null})},dispose(){s||(s=!0,r+=1,o.reset(),n.dispose())}}}function Jr(e,t){if(!Fo())return Xr(e,t);const n=ws(t.workerScriptUrl);try{return Lo(e,t,n)}catch{return Xr(e,t)}}function No(e,t={}){if(t.preferLegacyRenderer)return Jr(e,t);let n=null,r=!1,i=null,s=!1;const o=()=>n?Promise.resolve(n):(i||(i=(async()=>{try{const a=await Oo(e,t);if(s)throw a.dispose(),new Error("Renderer disposed during Pixi init");return r=!0,n=a,a}catch(a){if(s)throw a instanceof Error?a:new Error(String(a));return console.warn("[AiTwin] Pixi WebGL renderer unavailable, using Canvas2D fallback:",a),n=Jr(e,t),r=!1,n}})()),i);return{get usesWorker(){return n?.usesWorker??!1},get usesPixi(){return r},async loadAssets(a){return(await o()).loadAssets(a)},getVisemeAtlasPaths(){return n?.getVisemeAtlasPaths()??null},async renderSilOnly(){return(await o()).renderSilOnly()},drawLiveFrame(a,u,d,l){o().then(c=>{s||c.drawLiveFrame(a,u,d,l)})},async compositePrefetchFrame(a,u){return(await o()).compositePrefetchFrame(a,u)},blitBitmap(a,u){n&&n.blitBitmap(a,u)},drawIdleVideo(a,u){n?.usesPixi&&n.drawIdleVideo(a,u)},beginIdleToSilCrossfade(a){n?.beginIdleToSilCrossfade(a)},tickIdleToSilCrossfade(a){return n?.tickIdleToSilCrossfade(a)??!1},finishIdleToSilCrossfade(){n?.finishIdleToSilCrossfade()},isIdleToSilCrossfading(){return n?.isIdleToSilCrossfading()??!1},get supportsBufferedPlayback(){return n?.supportsBufferedPlayback??!1},async renderViseme(a,u,d){return(await o()).renderViseme(a,u,d)},dispose(){s=!0,i=null,n?.dispose(),n=null}}}class Vo extends Error{constructor(t,n){super(`${t} timed out after ${Math.round(n/1e3)}s`),this.name="LoadTimeoutError"}}function Cn(e,t,n){return new Promise((r,i)=>{const s=globalThis.setTimeout(()=>{i(new Vo(n,t))},t);e.then(o=>{globalThis.clearTimeout(s),r(o)},o=>{globalThis.clearTimeout(s),i(o)})})}const Uo={overflow:"hidden",position:"relative",display:"inline-block",lineHeight:0},Wo={display:"block",maxWidth:"100%",height:"auto"},zo={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 Rn(e){return Ss(e)?tr:oi(e)?dn:er}function Je(e,t){return t?.isSpeaking()||t?.isWarmingUp()?t:e.isSpeaking()||e.isWarmingUp()?e:t?.isConnected()?t:e}const ns=h.forwardRef(function({id:t,avatarId:n,faceId:r,assets:i,authToken:s,apiBase:o,ttsEngineId:a,voiceId:u,language:d,speakingRate:l=Ht,className:c,style:m,canvasStyle:w,onStatusChange:T,onDisplayStatus:f,onError:E,onReady:D,showErrorOverlay:B=!0,loadingThumbnailUrl:v,onUserTranscript:k,onBotOutput:L,onRealtimeLipsyncDebug:A,onFrameRenderStats:ie,lipsyncBufferedPlayback:de=!0,lipsyncPlaybackWarmupMs:I=1500,idleHandoffHoldMs:V=ho,pixiMaxTextureSize:G,captions:ae},se){const re=h.useRef(null),O=h.useRef(null),J=h.useRef(null),W=h.useRef(de);W.current=de;const he=h.useRef(I);he.current=I;const K=h.useRef(V);K.current=V;const ee=h.useRef(0),$=h.useRef(ur()),X=h.useRef(Ha()),_e=h.useRef(!1),oe=h.useRef(null),b=h.useRef(null),P=h.useRef(0),H=h.useRef(0),le=h.useRef(0),j=h.useRef(null),q=h.useRef(null),p=h.useRef(!1),S=h.useRef(!1),x=h.useRef(!1),_=h.useRef(!1),U=h.useRef("sil"),Z=h.useRef(0),te=h.useRef(!1),z=h.useRef(null),be=h.useRef(!1),[Xe,Pt]=h.useState("idle"),[pt,Ct]=h.useState(null),[ot,_n]=h.useState(!1),[g,C]=h.useState(!1),[ne,ue]=h.useState(!1),[Te,ve]=h.useState(),[ke,We]=h.useState({width:842,height:1264}),[Fe,$t]=h.useState(null),[bn,Rt]=h.useState(0),yt=h.useRef(!1),Ce=h.useRef(s??null),He=o?.trim()||ht,vt=h.useRef(null),Ie=h.useRef(null),{ttsEngineId:xe,voiceId:$e}=h.useMemo(()=>{const y=et(a,u),M=y.ttsEngineId??dt;return{ttsEngineId:M,voiceId:y.voiceId??Rn(M)}},[a,u]),je=h.useRef(!1),rt=h.useRef({width:842,height:1264}),pe=h.useRef(null),Le=h.useRef("sil"),Pe=h.useRef(""),Oe=h.useMemo(()=>no(ae),[ae]),Ne=h.useCallback(()=>{Pe.current="",$t(null)},[]);h.useEffect(()=>{Oe.enabled||Ne()},[Oe.enabled,Ne]);const Dt=h.useCallback(y=>{if(!Oe.enabled)return;const M=y.isSpeaking(),N=y.isWarmingUp();if(!M||N){Pe.current&&Ne();return}const F=to(y.getWordQueue());if(!F){Pe.current&&Ne();return}F!==Pe.current&&(Pe.current=F,$t(F))},[Oe.enabled,Ne]),ct=h.useRef(void 0),Bt=h.useRef(new Map),mr=h.useRef(D),hr=h.useRef(T),ye=h.useRef(f),gr=h.useRef(E),wr=h.useRef(k),pr=h.useRef(L),jt=h.useRef(A),yr=h.useRef(ie),_t=h.useRef(mo());mr.current=D,hr.current=T,ye.current=f,gr.current=E,wr.current=k,pr.current=L,jt.current=A,yr.current=ie,h.useEffect(()=>{const y=_t.current;return zr(y),()=>zr(null)},[]);const vr=h.useCallback(y=>{const M=et(y?.ttsEngineId??a,y?.voiceId??u),N=M.ttsEngineId??Ie.current?.ttsEngineId??dt,F=M.voiceId??Ie.current?.voiceId??Rn(N);return{ttsEngineId:N,voiceId:F}},[a,u]),it=h.useCallback(y=>{Ct(y),ue(!0),gr.current?.(y)},[]),Ft=h.useCallback(y=>{Pt(y),hr.current?.(y)},[]),fe=h.useRef(Nn(Ft,He,{onLipsyncDebug:y=>jt.current?.(y)})),me=h.useRef(null),_r=h.useRef(()=>{});h.useEffect(()=>(fe.current=Nn(Ft,He,{onLipsyncDebug:y=>jt.current?.(y)}),s&&fe.current.setDeveloperToken(s),fe.current.setTtsEngineId(xe),()=>{fe.current.stop();const y=me.current;y&&(y.disconnect(),me.current=null)}),[Ft,He]);const br=h.useCallback(()=>(me.current||(me.current=Vi(Ft,{speakingRate:l,language:d,onUserTranscript:(y,M)=>wr.current?.(y,M),onBotOutput:y=>pr.current?.(y),onLipsyncDebug:y=>jt.current?.(y)}),me.current.setTtsEngineId(xe),_r.current(!0)),me.current),[Ft,l,d,xe]),Re=h.useCallback(()=>{j.current!=null&&(clearTimeout(j.current),j.current=null)},[]),De=h.useCallback(()=>{q.current!=null&&(clearTimeout(q.current),q.current=null),x.current=!1},[]),Kt=h.useCallback(()=>{if(_.current)return;const y=O.current;if(_.current=!0,De(),p.current=!1,S.current=!1,!be.current||!z.current){y?.renderSilOnly();return}z.current.setActive(!1);const M=z.current.getVideo();if(y?.usesPixi){y.drawIdleVideo(M),y.beginIdleToSilCrossfade($r);return}(async()=>{const N=re.current;N&&await Mn(N,M,null,void 0,rt.current).catch(()=>{}),await new Promise(F=>setTimeout(F,$r)),_.current&&await y?.renderSilOnly()})()},[De]),Sr=h.useCallback(()=>{!be.current||!z.current||(_.current=!1,O.current?.finishIdleToSilCrossfade(),De(),x.current=!0,q.current=setTimeout(()=>{if(q.current=null,Je(fe.current,me.current).isSpeaking()){x.current=!1;return}if(p.current){x.current=!1;return}const y=z.current;if(!y){x.current=!1;return}y.restart(),y.setActive(!0);const M=y.getVideo();let N=!1;const F=()=>{N||(N=!0,M.removeEventListener("playing",Q),x.current=!1)},Q=()=>{F()};if(M.addEventListener("playing",Q,{once:!0}),M.readyState>=HTMLMediaElement.HAVE_CURRENT_DATA&&!M.paused){F();return}setTimeout(F,300)},K.current))},[De]),bt=h.useCallback(()=>{if(Re(),ye.current?.("sil"),p.current=!1,_.current=!1,!be.current||!z.current){x.current=!1;return}Sr()},[Re,Sr]),Sn=h.useCallback(async y=>{const M=H.current,N=O.current,F=re.current,Q=()=>{y?.fallbackOnly||(p.current=!1)};if(!N||!F||!ot){Q();return}if(Je(fe.current,me.current).isSpeaking()){Q();return}if(y?.fallbackOnly){if(!p.current||(Be($.current),await N.renderSilOnly(),M!==H.current)||Je(fe.current,me.current).isSpeaking())return;bt();return}if(jr($.current)){Be($.current),bt();return}if(W.current&&N.supportsBufferedPlayback&&!y?.fallbackOnly){if(Be($.current),J.current?.reset(),await N.renderSilOnly(),M!==H.current||Je(fe.current,me.current).isSpeaking())return;bt();return}const Ee=vo(Je(fe.current,me.current).getVisemeQueue(),Z.current,U.current),Ve=_o(Ee,pe.current);if(Be($.current),!Ve){if(await N.renderSilOnly(),M!==H.current||Je(fe.current,me.current).isSpeaking())return;bt();return}try{await N.renderViseme(F,"sil",{from:Ee,transitionDurationMs:Ji})}catch(Me){if(Me?.name!=="AbortError")throw Me}if(M!==H.current){Q();return}if(Je(fe.current,me.current).isSpeaking()){Q();return}bt()},[ot,bt]),St=h.useCallback(()=>{if(S.current||p.current)return;S.current=!0,p.current=!0,Re();const y=H.current;Sn().finally(()=>{S.current=!1}),j.current=setTimeout(()=>{j.current=null,y===H.current&&Sn({fallbackOnly:!0})},bo())},[Re,Sn]),Tr=h.useCallback(async()=>{const y=Math.floor(Date.now()/1e3);if(vt.current&&y<vt.current.expiresAt-60)return vt.current.key;const M=Ce.current??await Nt();Ce.current=M,fe.current.setDeveloperToken(M);const N=await Ps(M,He);return vt.current={key:N.value,expiresAt:N.expiresAt},N.value},[He]);h.useEffect(()=>{s&&(Ce.current=s,fe.current.setDeveloperToken(s))},[s]),h.useEffect(()=>{fe.current.setTtsEngineId(xe),me.current?.setTtsEngineId(xe),Ie.current&&(Ie.current.ttsEngineId=xe)},[xe]),h.useEffect(()=>{Ie.current&&(Ie.current.voiceId=$e)},[$e]);const Ke=h.useMemo(()=>ui(n,r),[n,r]),os=h.useMemo(()=>i?JSON.stringify(i):Ke?`face:${Ke}`:`id:${t??""}`,[i,Ke,t]),cs=h.useMemo(()=>{const y=v?.trim();return y||(xr(Ke)??xr(Te)??ks(i))},[v,Ke,Te,i]);return h.useEffect(()=>{if(!t&&!i&&!Ke){it("AiTwin requires `assets`, `avatarId`/`faceId`, or `id`");return}let y=!1;je.current=!1,_n(!1),C(!1),ue(!1),ve(Ke),Ct(null),Ie.current=null,z.current=null,be.current=!1;const M=re.current;if(!M)return;let N=null;return(async()=>{try{let F,Q,Se,Ee;if(i)F=i,Q=xe,Se=$e;else if(Ke)ye.current?.("loadFace"),F=Ln(Ke),Q=xe,Se=$e;else{ye.current?.("getAiTwin");const Y=await Cn(ci(t),3e4,"getAiTwin");if(y)return;if(!Y.faceId?.trim())throw new Error("getAiTwin returned no faceId");ve(Y.faceId.trim());const ce=et(a,u);Q=ce.ttsEngineId??Y.ttsEngineId,Se=ce.voiceId??Y.voiceId??Rn(Q),Ee=qn(Y),F=Ln(Y.faceId)}Ie.current={ttsEngineId:Q,voiceId:Se,brainId:Ee},di(F),z.current=$a();const Ve=!!(i&&!gt(i));N=No(M,{preferLegacyRenderer:Ve,pixiMaxTextureSize:G,onStatus:Y=>{y||ye.current?.(Y)},onError:Y=>{y||it(Y)},shouldAcceptLiveFrame:()=>{if(_e.current)return!0;if(p.current)return!1;const Y=Je(fe.current,me.current);return Y.isSpeaking()||Y.isWarmingUp()},onWebGlContextLost:()=>{y||yt.current||(yt.current=!0,queueMicrotask(()=>{y||Rt(Y=>Y+1)}))}}),O.current=N,J.current=xo(N),yt.current=!1;const Me=Y=>{const ce=()=>{if(!Y||he.current<=0)return!1;const Ae=O.current;return Ae?W.current&&Ae.supportsBufferedPlayback?!0:Ae.usesPixi:!1};fe.current.setLipsyncWarmupHold(Y,ce),me.current?.setLipsyncWarmupHold(Y,ce)};_r.current=Me,Me(!0),ye.current?.("auth");const Ge=Ce.current??s??await Cn(Nt(),3e4,"getAuthToken");if(y)return;Ce.current=Ge,fe.current.setDeveloperToken(Ge),fe.current.setTtsEngineId(Q);const Gt=Wt()?await Tr():void 0;if(y)return;ye.current?.("loadAssets");const ge=await Cn(N.loadAssets(Gt),18e4,"load face assets");if(!y&&ge.width>0&&ge.height>0&&(rt.current=ge,We(ge)),y)return;pe.current=N.getVisemeAtlasPaths(),je.current=!0,_n(!0),mr.current?.(),N.renderSilOnly().then(()=>{y||ye.current?.("sil")}),(async()=>{try{const Y=await va(Gt);if(await z.current.load(Y),y)return;be.current=!0,C(!0),Be($.current),z.current.setActive(!0);const ce=z.current.getVideo();N.usesPixi?N.drawIdleVideo(ce):await Mn(M,ce,null,void 0,rt.current)}catch(Y){if(y)return;be.current=!1,C(!1),console.warn("[AiTwin] Idle video unavailable:",Y)}finally{y||(ue(!0),ye.current?.("idle"))}})()}catch(F){if(y)return;if(F instanceof nn){it(F.message);return}it(F instanceof Error?F.message:"Failed to load AI twin")}})(),()=>{y=!0,z.current?.dispose(),N?.dispose(),O.current=null}},[os,i,Ke,t,xe,$e,a,u,s,G,Tr,it,bn]),h.useEffect(()=>{const y={current:!1},M=()=>{const N=re.current,F=O.current,Q=Je(fe.current,me.current);if(!N||!F||!ot){P.current=requestAnimationFrame(M);return}if(document.hidden){z.current?.setActive(!1),P.current=requestAnimationFrame(M);return}const Se=Q.isSpeaking(),Ee=Q.isWarmingUp(),Ve=Se&&!te.current,Me=te.current&&!Se;Ve&&(Re(),De(),p.current=!1,S.current=!1,Be($.current),J.current?.reset(),_t.current.reset(),ct.current=void 0,le.current=0,U.current="sil",Z.current=0,Kt()),Me&&(X.current.reset(),z.current?.setActive(!1),J.current?.reset(),F.finishIdleToSilCrossfade(),Ne(),St());const Ge=Me||p.current||x.current||_.current,Gt=de&&F.supportsBufferedPlayback;if(Ee){if(Kt(),be.current&&z.current?.setActive(!1),F.usesPixi&&F.isIdleToSilCrossfading()){F.tickIdleToSilCrossfade(performance.now()),Q.getVisemeQueue().length>0&&ee.current===0&&(ee.current=performance.now()),te.current=Q.isSpeaking(),P.current=requestAnimationFrame(M);return}const ge=Q.getVisemeQueue();ge.length>0&&ee.current===0&&(ee.current=performance.now()),X.current.advance(performance.now());const Y=X.current.getExpressionPath(),ce=X.current.getDrawKey(),Ae={queue:ge,elapsedMs:0,expressionPath:Y,expressionDrawKey:ce,availablePaths:pe.current};let Ue=!1;Gt&&J.current?(J.current.warmupTick(Ae),Ue=J.current.isWarmupReady(Ae,he.current)):F.usesPixi&&Kr(N,ge,0,Y,ce,$.current,(Tt,qt,Tn,Yt)=>{F.drawLiveFrame(Tt,qt,Tn,qe=>{Yt?.(qe),Q.isWarmingUp()&&qe!==""&&!jr({lastDrawnKey:qe})&&(ee.current=0,Q.releaseWarmupHold())})},Tt=>{ye.current?.(Tt.label)},pe.current);const st=ee.current>0&&performance.now()-ee.current>ys;ye.current?.(Ue?"buffer ready":"buffering lipsync…"),(Ue||st)&&(ee.current=0,Q.releaseWarmupHold()),Dt(Q),te.current=Q.isSpeaking(),P.current=requestAnimationFrame(M);return}if(Se){Kt(),be.current&&z.current?.setActive(!1),F.usesPixi&&F.isIdleToSilCrossfading()&&F.finishIdleToSilCrossfade();const ge=Q.getVisemeQueue(),Y=Q.getPlaybackElapsedMs();aa(ge,Y),Z.current=Y;const ce=ge.length>0?zt(ge,Y):"sil";ce!=="sil"&&(U.current=ce);const Ae=qa(Y,Q.getSentenceEmotions(),Q.getWordQueue(),Q.getStreamMood());X.current.setTargetEmotion(Ae),X.current.setTargetEyebrow(Wa(Y,Q.getWordQueue(),mt(Ae))),X.current.advance(performance.now());const Ue=X.current.getExpressionPath(),st=X.current.getDrawKey(),Tt=(qe,kn,Lt,En)=>{const kr={label:Le.current,elapsedMs:Y,mouthPath:kn.mouthPath,transitionMeta:ct.current};Bt.current.set(Lt,kr),J.current?.markExternallyDisplayed(Lt,Ue),F.drawLiveFrame(qe,kn,Lt,Qt=>{const ls=Bt.current.get(Qt)??kr;Bt.current.delete(Qt),_t.current.onDrawDisplayed(ls,ge),J.current?.markExternallyDisplayed(Qt,Ue),En?.(Qt)})},qt=qe=>{Le.current=qe.label,ct.current=qe.transitionMeta,ye.current?.(qe.label)},Tn=de&&F.supportsBufferedPlayback;let Yt=!1;Tn&&J.current&&(Yt=J.current.tick({canvas:N,queue:ge,elapsedMs:Y,expressionPath:Ue,expressionDrawKey:st,playbackState:$.current,availablePaths:pe.current,onStatus:qt,onDisplayed:(kn,Lt,En)=>{_t.current.onDrawDisplayed({label:En,elapsedMs:Y,mouthPath:Lt,transitionMeta:ct.current},ge)}}).usedBuffer),Yt||Kr(N,ge,Y,Ue,st,$.current,Tt,qt,pe.current),_t.current.onRafTickSpeaking(),yr.current?.(_t.current.snapshot(ge,Y))}else if(!Ge&&_e.current){z.current?.setActive(!1),X.current.advance(performance.now());const ge=X.current.getExpressionPath(),Y=X.current.getDrawKey();Pn(N,ge,Y,$.current,(ce,Ae,Ue,st)=>F.drawLiveFrame(ce,Ae,Ue,st),ce=>{if(b.current){ye.current?.(b.current);return}const Ae=X.current.getTargetEmotion();ye.current?.(ce==="sil"||ce==="blink"?`${Ae}${ce==="blink"?" · blink":""}`:ce)},null,oe.current)}else if(!Ge&&be.current&&z.current){const ge=z.current,Y=ge.getVideo();if(Y.readyState>=HTMLMediaElement.HAVE_CURRENT_DATA){ge.setActive(!0);const ce=()=>!Q.isSpeaking()&&!p.current&&!x.current&&!_e.current;F.usesPixi?(F.drawIdleVideo(Y,ce),ce()&&ye.current?.("idle")):y.current||(y.current=!0,Mn(N,Y,null,void 0,rt.current,ce).then(()=>ye.current?.("idle")).finally(()=>{y.current=!1}))}else Pn(N,null,"__sil__",$.current,(ce,Ae,Ue,st)=>F.drawLiveFrame(ce,Ae,Ue,st),ce=>ye.current?.(ce))}else Ge||Pn(N,null,"__sil__",$.current,(ge,Y,ce,Ae)=>F.drawLiveFrame(ge,Y,ce,Ae),ge=>ye.current?.(ge));Oe.enabled&&Dt(Q),te.current=Se,P.current=requestAnimationFrame(M)};return P.current=requestAnimationFrame(M),()=>{cancelAnimationFrame(P.current),Re(),De(),fe.current.stop(),me.current?.stop()}},[ot,g,St,Re,De,Kt,Dt,Ne,Oe.enabled]),h.useImperativeHandle(se,()=>({speakText:async(y,M)=>{const N=y.trim();if(!N)return;const F=O.current;if(!F||!je.current&&!ot)throw new Error("AI twin is not ready");const{ttsEngineId:Q,voiceId:Se}=vr(M);Ct(null),Ne(),H.current+=1,Re(),De(),p.current=!1,S.current=!1,U.current="sil",Z.current=0,Be($.current),_e.current=!1,oe.current=null,b.current=null,X.current.reset(),te.current=!1,_.current=!1,F.finishIdleToSilCrossfade();try{await fe.current.speak(N,{voiceId:Se,speakingRate:M?.speakingRate??l,ttsEngineId:Q,language:M?.language??d})}catch(Ee){throw _.current=!1,F.finishIdleToSilCrossfade(),St(),it(Ee instanceof Error?Ee.message:"TTS failed"),Ee}},stop:()=>{H.current+=1,Re(),De(),p.current=!1,S.current=!1,_.current=!1,O.current?.finishIdleToSilCrossfade(),fe.current.stop(),me.current?.stop(),Be($.current),J.current?.reset(),ee.current=0,te.current=!1,Ne(),St()},setTtsEngineId:y=>{fe.current.setTtsEngineId(y),me.current?.setTtsEngineId(y),Ie.current&&(Ie.current.ttsEngineId=y)},renderViseme:async(y,M)=>{const N=O.current,F=re.current;if(!N||!F||!je.current)throw new Error("AI twin is not ready");await N.renderViseme(F,y,{from:M?.from,transitionDurationMs:M?.transitionDurationMs,gapMs:M?.gapMs,onStatus:Q=>ye.current?.(Q)})},setEmotion:y=>{if(!je.current)throw new Error("AI twin is not ready");const M=O.current,N=re.current;if(!M||!N)throw new Error("AI twin is not ready");H.current+=1,Re(),De(),p.current=!1,S.current=!1,x.current=!1,_.current=!1,fe.current.stop(),me.current?.stop(),Be($.current),J.current?.reset(),ee.current=0,te.current=!1,M.finishIdleToSilCrossfade(),z.current?.setActive(!1);const F=Ze(y);_e.current=!0,oe.current=null,b.current=null,X.current.snapToEmotion(F);const Q=X.current.getExpressionPath(),Se=X.current.getDrawKey(),Ee={mouthPath:null,expressionPath:Q},Ve=Ut(Ee,Se);$.current.lastDrawnKey="",M.drawLiveFrame(N,Ee,Ve,Ge=>{Ge===Ve&&($.current.lastDrawnKey=Ve)});const Me=mt(F);ye.current?.(Q?`${F} · brow ${Me>0?"+":""}${Me}`:`${F} · brow 0 (sil base)`)},getEmotion:()=>_e.current?X.current.getTargetEmotion():null,clearEmotionPreview:()=>{_e.current=!1,oe.current=null,b.current=null,X.current.reset(),Be($.current),ye.current?.("idle")},setViseme:y=>{if(!je.current)throw new Error("AI twin is not ready");const M=O.current,N=re.current;if(!M||!N)throw new Error("AI twin is not ready");H.current+=1,Re(),De(),p.current=!1,S.current=!1,x.current=!1,_.current=!1,fe.current.stop(),me.current?.stop(),Be($.current),J.current?.reset(),ee.current=0,te.current=!1,M.finishIdleToSilCrossfade(),z.current?.setActive(!1);const F=mn(y);_e.current=!0,b.current=F,oe.current=F==="sil"?null:xt(F),X.current.snapToEmotion("neutral");const Q=X.current.getExpressionPath(),Se=X.current.getDrawKey(),Ve={mouthPath:oe.current,expressionPath:Q},Me=Ut(Ve,Se);$.current.lastDrawnKey="",M.drawLiveFrame(N,Ve,Me,Ge=>{Ge===Me&&($.current.lastDrawnKey=Me)}),ye.current?.(F)},getViseme:()=>_e.current?b.current:null,isReady:()=>je.current,getStatus:()=>Xe,connect:async(y={})=>{Ct(null);try{let M=y.authToken?.trim();M||(M=Ce.current??s??await Nt(),Ce.current=M);const N=et(y.ttsEngineId??a,y.voiceId??u),F=N.voiceId??Ie.current?.voiceId,Q=y.brainId?.trim()||y.personaId?.trim()||Ie.current?.brainId,Se=N.ttsEngineId??Ie.current?.ttsEngineId??xe,Ee=br();Se&&Ee.setTtsEngineId(Se),await Ee.unlockAudio(),await Ee.connect({...y,apiBase:y.apiBase?.trim()||He,authToken:M,voiceId:F,brainId:Q,ttsEngineId:Se,speakingRate:y.speakingRate??l,language:y.language??d})}catch(M){throw it(M instanceof Error?M.message:"Voice connect failed"),M}},disconnect:async()=>{const y=me.current;y&&(H.current+=1,Re(),De(),p.current=!1,S.current=!1,_.current=!1,O.current?.finishIdleToSilCrossfade(),Be($.current),J.current?.reset(),ee.current=0,te.current=!1,await y.disconnect(),St())},isConnected:()=>me.current?.isConnected()??!1,getVoiceStream:()=>me.current?.getVoiceStream()??fe.current?.getVoiceStream()??null,setMuted:y=>{const M=fe.current,N=me.current;M?.setMuted?.(y),N?.setMuted?.(y)},isMuted:()=>{const y=me.current,M=fe.current;return y?.isMuted?.()??M?.isMuted?.()??!1},getBrainId:()=>Ie.current?.brainId?.trim()||null,getPersonaId:()=>Ie.current?.brainId?.trim()||null}),[ot,l,d,s,xe,$e,Re,De,St,it,vr,br,Xe,He]),R.jsxs("div",{className:c,style:{...Uo,...m},children:[R.jsx("canvas",{ref:re,width:ke.width,height:ke.height,style:{...Wo,...w},"aria-label":t?`AI twin ${t}`:"AI twin face"}),!ne&&!pt?R.jsx(uo,{thumbnailUrl:cs}):null,B&&pt?R.jsx("div",{style:zo,children:pt}):null,Oe.enabled&&Fe?R.jsx(ao,{text:Fe,style:Oe.style},Fe):null]})});async function Ho(e){try{const t=await e.json();if(typeof t.detail=="string"&&t.detail.trim())return t.detail;if(typeof t.error=="string"&&t.error.trim())return t.error}catch{}return`avatarReply failed (${e.status})`}async function rs(e){const t=e.message.trim();if(!t)throw new Error("Message is required");const n=e.authToken.trim();if(!n)throw new Error("Auth token is required");const r=(e.apiBase?.trim()||ht).replace(/\/$/,""),i=await fetch(`${r}/avatarReply`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n}`,Accept:"text/event-stream"},body:JSON.stringify({message:t,history:e.history??[],brainId:e.brainId?.trim()||e.personaId?.trim()||"",tenant:"aiTwin"})});if(!i.ok)throw new Error(await Ho(i));if(!i.body)throw new Error("avatarReply response body is empty");const s=i.body.getReader(),o=new TextDecoder;let a="",u="",d="",l="";for(;;){const{done:c,value:m}=await s.read();if(c)break;a+=o.decode(m,{stream:!0});const w=a.split(`
|
|
48
|
-
`);a=w.pop()||"";for(const T of w){if(T.startsWith("event: ")){l=T.slice(7).trim();continue}if(!T.startsWith("data: "))continue;const f=T.slice(6).trim();if(!f)continue;let E;try{E=JSON.parse(f)}catch{continue}if(l==="spokenText")u=E.text||"",e.onSpokenText?.(u);else if(l==="displayText")d=E.text||"";else if(l==="error")throw new Error(E.error||"avatarReply stream error")}}if(!u.trim()||!d.trim())throw new Error("avatarReply stream missing displayText or spokenText");return{displayText:d.trim(),spokenText:u.trim()}}function $o({muted:e}){return e?R.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none","aria-hidden":!0,children:[R.jsx("path",{d:"M11 5 6.5 9H3v6h3.5L11 19V5Z",fill:"currentColor"}),R.jsx("path",{d:"m16 9.5 5 5m0-5-5 5",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round"})]}):R.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none","aria-hidden":!0,children:[R.jsx("path",{d:"M11 5 6.5 9H3v6h3.5L11 19V5Z",fill:"currentColor"}),R.jsx("path",{d:"M15.5 8.5a4.5 4.5 0 0 1 0 7M18.5 6a8 8 0 0 1 0 12",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round"})]})}function jo(){return R.jsx("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"currentColor","aria-hidden":!0,children:R.jsx("path",{d:"M8 5.5v13l11-6.5L8 5.5Z"})})}function Ko(){return R.jsx("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"currentColor","aria-hidden":!0,children:R.jsx("rect",{x:"6",y:"6",width:"12",height:"12",rx:"1.5"})})}function Go(){return R.jsx("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none","aria-hidden":!0,children:R.jsx("path",{d:"M5 6.5A2.5 2.5 0 0 1 7.5 4h9A2.5 2.5 0 0 1 19 6.5v7A2.5 2.5 0 0 1 16.5 16H10l-4 3.5V16H7.5A2.5 2.5 0 0 1 5 13.5v-7Z",stroke:"currentColor",strokeWidth:"2",strokeLinejoin:"round"})})}function is({className:e}){return R.jsx("span",{className:e??"aitwin-widget__spinner","aria-hidden":!0,children:R.jsx("svg",{viewBox:"0 0 24 24",fill:"none",children:R.jsx("circle",{cx:"12",cy:"12",r:"9",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeDasharray:"40 20"})})})}function qo({muted:e,onToggle:t}){return R.jsx("button",{type:"button",className:"aitwin-widget__mute",onClick:t,"aria-label":e?"Unmute":"Mute","aria-pressed":e,children:R.jsx($o,{muted:e})})}function Yo(){return R.jsxs("div",{className:"aitwin-widget__connecting",role:"status","aria-live":"polite",children:[R.jsx(is,{className:"aitwin-widget__spinner aitwin-widget__spinner--accent"}),R.jsx("span",{children:"Connecting..."})]})}function Qo(e){const t=e.connecting||e.textSending||e.status==="loading"||e.status==="speaking",n=e.connecting?"Connecting...":e.connected?"End Talk":"Talk",r=["aitwin-widget__action",e.textMode&&!e.connecting?"":"aitwin-widget__action--primary",e.connecting?"aitwin-widget__action--connecting":""].filter(Boolean).join(" ");return R.jsxs("div",{className:"aitwin-widget__controls",children:[R.jsxs("div",{className:"aitwin-widget__actions",children:[R.jsxs("button",{type:"button",className:r,onClick:e.onTalk,disabled:!e.ready||e.connecting||e.textSending,"aria-busy":e.connecting,children:[e.connecting?R.jsx(is,{className:"aitwin-widget__spinner aitwin-widget__spinner--on-accent"}):e.connected?R.jsx(Ko,{}):R.jsx(jo,{}),R.jsx("span",{children:n})]}),R.jsxs("button",{type:"button",className:e.textMode?"aitwin-widget__action aitwin-widget__action--primary":"aitwin-widget__action",onClick:e.onTextMode,disabled:!e.ready||e.connecting||e.textSending,"aria-pressed":e.textMode,children:[R.jsx(Go,{}),R.jsx("span",{children:"Text"})]})]}),e.textMode?R.jsxs("form",{className:"aitwin-widget__composer",onSubmit:i=>{i.preventDefault(),e.onSendText()},children:[R.jsx("input",{type:"text",className:"aitwin-widget__composer-input",value:e.textDraft,onChange:i=>e.onTextDraftChange(i.target.value),placeholder:e.textSending?"Getting reply...":"Type a message…",autoComplete:"off",disabled:!e.ready||t}),R.jsx("button",{type:"submit",className:"aitwin-widget__composer-send",disabled:!e.ready||t||!e.textDraft.trim()&&!e.textSending,"aria-busy":e.textSending,children:e.textSending?"…":"Send"})]}):null,e.error?R.jsx("p",{className:"aitwin-widget__controls-error",role:"alert",children:e.error}):null]})}const Zr=97,Xo=3500;function Jo(e,t){const n=Math.max(0,e),r=1-Math.exp(-n/Xo);return Math.min(Zr,Math.round(r*Zr))}function Zo(e){const[t,n]=h.useState(null),[r,i]=h.useState(()=>Date.now());return h.useEffect(()=>{if(!e){n(null);return}const s=Date.now();n(s),i(s);let o=0;const a=()=>{i(Date.now()),o=window.requestAnimationFrame(a)};return o=window.requestAnimationFrame(a),()=>{window.cancelAnimationFrame(o)}},[e]),e?t==null?0:Jo(r-t):100}const ec="M259.01,593.87v-101.49c.33-6.31,4.94-11.26,10.21-11.88,6.42-.75,13.18,4.99,13.13,12.92-.42,45.09-.83,90.17-1.25,135.26.03,1.56.56,15.43,11.95,23.2,6.18,4.21,12.57,4.6,15.42,4.58-.42-112.77-.83-225.54-1.25-338.31-.08-2.55-1.03-46.36,21.17-55.34,2.05-.83,4.42-1.41,7.17-1.56v453.42c.07,12.06,1.98,37.84,19.03,62.73,7.01,10.23,14.79,17.71,21.4,22.99V222.42c-.01-3.72.48-11.67,5.35-19.87,7-11.77,18.13-15.82,21.4-16.95,10.42-3.61,19.49-2.06,23.48-1.11v684.96c.59,4.03,1.78,9.72,4.45,16.12,1.93,4.63,8.84,20.57,26.47,31.26,13.48,8.18,26.56,9.23,32.86,9.31-1.3-256.11-2.59-512.22-3.89-768.33.76-16.43,14.57-28.94,29.73-28.34,13.53.53,25.39,11.39,27.23,25.84-1.1,264.68-2.2,529.35-3.3,794.03,4.33.92,22.38,4.25,38.94-6.53,10.26-6.68,15.24-15.72,17.09-19.17,5.55-10.36,6.42-19.98,6.53-25.01-.72-246.99-1.43-493.97-2.15-740.96,2.27-.06,34.75-.44,48.29,22.68,3.41,5.83,4.87,11.86,5.34,17.19v674.68c5.92-2.16,39.19-14.94,50.16-47.79,3.12-9.34,3.68-18.03,3.33-25.01.03-193.22.06-386.43.09-579.65,4.12,1.18,28.28,8.48,36.17,30.08,1.64,4.49,2.32,8.88,2.43,12.92.02,146.42.05,292.84.07,439.25,3.82-1.71,19.51-9.22,25.56-26.47,2.15-6.12,2.48-11.73,2.29-15.89.01-114.91.03-229.81.04-344.72,2.36-.1,7.51.02,12.74,3.13,9.1,5.4,10.87,15.35,11.12,16.88.35,11.49.69,22.97,1.04,34.46.46,37.05.93,74.1,1.39,111.15v152.69c3.39-.72,9.77-2.67,14.31-8.34,3.62-4.52,4.51-9.46,5.56-15.28.91-5.04.95-9.31.83-12.23.02-38.81.03-77.62.05-116.43";function tc({className:e="aitwin-widget__logo",strokeWidth:t=15,durationMs:n=2600,delayMs:r=0,loop:i=!1}){return R.jsx("svg",{viewBox:"0 0 1080 1080",className:e,role:"img","aria-label":"AITWIN logo",children:R.jsx("path",{className:i?"aitwin-widget__logo-draw aitwin-widget__logo-draw--loop":"aitwin-widget__logo-draw",d:ec,fill:"none",stroke:"currentColor",strokeWidth:t,strokeMiterlimit:10,pathLength:1,style:{animationDuration:`${n}ms`,animationDelay:`${r}ms`}})})}function nc({progress:e}){const t=Math.max(0,Math.min(100,Math.round(e)));return R.jsx("div",{className:"aitwin-widget__face-loading","aria-live":"polite","aria-label":`Loading ${t} percent`,children:R.jsxs("div",{className:"aitwin-widget__face-loading-content",children:[R.jsx(tc,{className:"aitwin-widget__logo",loop:!0,durationMs:2600}),R.jsxs("div",{className:"aitwin-widget__face-loading-bar-wrap",children:[R.jsx("div",{role:"progressbar","aria-valuenow":t,"aria-valuemin":0,"aria-valuemax":100,className:"aitwin-widget__face-loading-track",children:R.jsx("div",{className:"aitwin-widget__face-loading-fill",style:{width:`${t}%`}})}),R.jsxs("p",{className:"aitwin-widget__face-loading-pct",children:[t,"%"]})]})]})})}function ei(e){const t=e.id?.trim()||void 0,n=e.faceId?.trim()||e.avatarId?.trim()||void 0;return{id:n?void 0:t,faceId:n,authToken:e.authToken?.trim()||void 0,apiBase:e.apiBase?.trim()||void 0,voiceId:e.voiceId?.trim()||void 0,speakingRate:e.speakingRate,language:e.language}}function rc(e){return[e.id??"",e.faceId??"",e.authToken?.slice(0,16)??"",e.voiceId??"",e.apiBase??"",String(e.speakingRate??"")].join("|")}const ti={display:"flex",alignItems:"center",justifyContent:"center",width:"100%",height:"100%",lineHeight:0},ic={display:"block",height:"100%",width:"100%",objectFit:"cover",objectPosition:"top"},sc=h.forwardRef(function({options:t},n){const r=h.useRef(null),i=h.useRef(t);i.current={...i.current,onReady:t.onReady,onStatusChange:t.onStatusChange,onError:t.onError,onUserTranscript:t.onUserTranscript,onBotOutput:t.onBotOutput};const[s,o]=h.useState(!!t.showControls),[a,u]=h.useState(()=>ei(t)),[d,l]=h.useState(!1),[c,m]=h.useState(!1),[w,T]=h.useState(!1),[f,E]=h.useState(!1),[D,B]=h.useState("idle"),[v,k]=h.useState(null),[L,A]=h.useState(!1),[ie,de]=h.useState(!1),[I,V]=h.useState(""),[G,ae]=h.useState(!1),[se,re]=h.useState([]),[O,J]=h.useState(t.brainId?.trim()||t.personaId?.trim()||void 0),W=h.useCallback(_=>{i.current={...i.current,..._},_.showControls!==void 0&&o(!!_.showControls),(_.brainId!==void 0||_.personaId!==void 0)&&J((_.brainId??_.personaId)?.trim()||void 0),u(U=>ei({id:_.id??U.id,faceId:_.faceId??_.avatarId??U.faceId,authToken:_.authToken??U.authToken,apiBase:_.apiBase??U.apiBase,voiceId:_.voiceId??U.voiceId,speakingRate:_.speakingRate??U.speakingRate,language:_.language??U.language}))},[]);h.useImperativeHandle(n,()=>({getTwin:()=>r.current,applyOptions:W}),[W]),h.useEffect(()=>{W(t)},[W,t.id,t.faceId,t.avatarId,t.authToken,t.apiBase,t.voiceId,t.speakingRate,t.showControls,t.brainId,t.personaId]);const he=h.useCallback(()=>{l(!0),k(null)},[]),K=h.useCallback(_=>{_==="idle"&&m(!0)},[]),ee=h.useCallback(_=>{B(_),i.current.onStatusChange?.(_)},[]),$=h.useCallback(_=>{k(_),l(!1),m(!1),E(!1),i.current.onError?.(_)},[]),X=h.useCallback((_,U)=>{i.current.onUserTranscript?.(_,U)},[]),_e=h.useCallback(_=>{i.current.onBotOutput?.(_)},[]);h.useEffect(()=>{if(!s)return;const _=window.setInterval(()=>{T(!!r.current?.isConnected())},400);return()=>window.clearInterval(_)},[s,a]);const oe=rc(a),b=!!(a.id||a.faceId),P=d&&c,H=b&&!P&&!v,le=Zo(H),j=h.useRef(oe);h.useEffect(()=>{P&&i.current.onReady?.()},[P]),h.useEffect(()=>{P&&r.current?.setMuted(L)},[P,L,a]),h.useEffect(()=>{re([])},[a.id,a.faceId]),h.useEffect(()=>{j.current!==oe&&(j.current=oe,l(!1),m(!1),k(null),E(!1),T(!1),B("idle"))},[oe]);const q=()=>{const _=r.current;if(!_?.isReady())return;if(k(null),de(!1),_.isConnected()){E(!1),_.disconnect().finally(()=>{T(!1)});return}E(!0);const U={authToken:a.authToken,voiceId:a.voiceId,speakingRate:a.speakingRate,language:a.language,apiBase:a.apiBase};_.connect(U).then(()=>{T(!!_.isConnected())}).catch(Z=>{const te=Z instanceof Error?Z.message:"Failed to connect voice.";k(te),i.current.onError?.(te)}).finally(()=>{E(!1)})},p=()=>{de(_=>!_),k(null)},S=()=>{const _=I.trim(),U=r.current;!_||!U?.isReady()||G||(k(null),V(""),ae(!0),i.current.onUserTranscript?.(_,!0),(async()=>{try{const Z=a.authToken?.trim()||await Nt(),te=O||U.getBrainId()?.trim()||void 0,z=await rs({message:_,authToken:Z,apiBase:a.apiBase||ht,brainId:te,history:se});re(be=>[...be,{role:"user",content:_},{role:"assistant",content:z.displayText}]),i.current.onBotOutput?.(z.displayText),await U.speakText(z.spokenText,{voiceId:a.voiceId,speakingRate:a.speakingRate,language:a.language})}catch(Z){const te=Z instanceof Error?Z.message:"Failed to get reply.";k(te),i.current.onError?.(te)}finally{ae(!1)}})())},x=()=>{const _=!L;A(_),r.current?.setMuted(_)};return R.jsxs("div",{className:"aitwin-widget__layout",children:[R.jsxs("div",{className:"aitwin-widget__stage",children:[b?R.jsx("div",{style:ti,children:R.jsx(ns,{ref:r,id:a.id,faceId:a.faceId,authToken:a.authToken,apiBase:a.apiBase,voiceId:a.voiceId,speakingRate:a.speakingRate,language:a.language,style:ti,canvasStyle:ic,onReady:he,onDisplayStatus:K,onStatusChange:ee,onError:$,onUserTranscript:X,onBotOutput:_e,loadingThumbnailUrl:t.loadingThumbnailUrl},oe)}):R.jsx("p",{className:"aitwin-widget__hint",style:{padding:16},children:"Pass id or faceId to load a twin."}),H?R.jsx(nc,{progress:le}):null,s?R.jsx(qo,{muted:L,onToggle:x}):null,s&&f?R.jsx(Yo,{}):null]}),s?R.jsx(Qo,{ready:P,connected:w,connecting:f,status:D,textMode:ie,textDraft:I,textSending:G,error:v,onTalk:q,onTextMode:p,onTextDraftChange:V,onSendText:S}):null]})}),ac=".aitwin-widget{--aitwin-border: rgba(255, 255, 255, .12);--aitwin-text: #f4f4f5;--aitwin-muted: #a1a1aa;--aitwin-accent: #f97316;--aitwin-accent-hover: #fb923c;--aitwin-font: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, sans-serif;--aitwin-size: 1;--aitwin-stage-width: calc(200px * var(--aitwin-size));--aitwin-stage-height: calc(267px * var(--aitwin-size));--aitwin-action-height: calc(40px * var(--aitwin-size));--aitwin-action-font: calc(13px * var(--aitwin-size));--aitwin-action-radius: calc(10px * var(--aitwin-size));--aitwin-action-gap: calc(6px * var(--aitwin-size));--aitwin-mute-size: calc(28px * var(--aitwin-size));--aitwin-layout-gap: calc(8px * var(--aitwin-size));box-sizing:border-box;color:var(--aitwin-text);font-family:var(--aitwin-font);font-size:calc(12px * var(--aitwin-size));line-height:1.45;width:fit-content;max-width:100%}.aitwin-widget *,.aitwin-widget *:before,.aitwin-widget *:after{box-sizing:border-box}.aitwin-widget__layout{display:flex;flex-direction:column;gap:var(--aitwin-layout-gap);width:fit-content;max-width:100%}.aitwin-widget__stage{align-items:center;background:#0a0a0b;border:1px solid var(--aitwin-border);border-radius:calc(10px * var(--aitwin-size));display:flex;flex-shrink:0;height:var(--aitwin-stage-height);justify-content:center;line-height:0;overflow:hidden;position:relative;width:var(--aitwin-stage-width)}.aitwin-widget__stage .aitwin-root,.aitwin-widget__stage canvas{display:block;height:100%;object-fit:cover;object-position:top;width:100%}.aitwin-widget__hint{color:var(--aitwin-muted);font-size:calc(11px * var(--aitwin-size));margin:0}.aitwin-widget__mute{align-items:center;background:#28282cb8;border:none;border-radius:999px;color:#fff;cursor:pointer;display:inline-flex;height:var(--aitwin-mute-size);justify-content:center;padding:0;position:absolute;right:calc(8px * var(--aitwin-size));top:calc(8px * var(--aitwin-size));width:var(--aitwin-mute-size);z-index:2}.aitwin-widget__mute:hover{background:#37373cd9}.aitwin-widget__mute svg{height:calc(15px * var(--aitwin-size));width:calc(15px * var(--aitwin-size))}.aitwin-widget__controls{display:flex;flex-direction:column;gap:var(--aitwin-action-gap);width:var(--aitwin-stage-width)}.aitwin-widget__actions{display:grid;gap:var(--aitwin-action-gap);grid-template-columns:1fr 1fr;width:100%}.aitwin-widget__action{align-items:center;background:transparent;border:1.5px solid var(--aitwin-accent);border-radius:999px;color:var(--aitwin-accent);cursor:pointer;display:inline-flex;font-family:inherit;font-size:var(--aitwin-action-font);font-weight:600;gap:calc(6px * var(--aitwin-size));height:var(--aitwin-action-height);justify-content:center;padding:0 calc(10px * var(--aitwin-size))}.aitwin-widget__action svg{flex-shrink:0;height:calc(12px * var(--aitwin-size));width:calc(12px * var(--aitwin-size))}.aitwin-widget__action:hover:not(:disabled){background:#f973161a}.aitwin-widget__action:disabled{cursor:not-allowed;opacity:.45}.aitwin-widget__action--primary{background:var(--aitwin-accent);border-color:transparent;color:#fff}.aitwin-widget__action--primary:hover:not(:disabled){background:var(--aitwin-accent-hover)}.aitwin-widget__action--connecting:disabled{cursor:progress;opacity:1}.aitwin-widget__spinner{display:inline-flex;flex-shrink:0;height:calc(14px * var(--aitwin-size));width:calc(14px * var(--aitwin-size))}.aitwin-widget__spinner svg{animation:aitwin-widget-spin .8s linear infinite;display:block;height:100%;width:100%}.aitwin-widget__spinner--accent{color:var(--aitwin-accent);height:calc(16px * var(--aitwin-size));width:calc(16px * var(--aitwin-size))}.aitwin-widget__spinner--on-accent{color:#fff}@keyframes aitwin-widget-spin{to{transform:rotate(360deg)}}.aitwin-widget__connecting{align-items:center;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);background:#ffffffe0;border-radius:999px;bottom:calc(14px * var(--aitwin-size));box-shadow:0 4px 16px #0000001f;color:#3f3f46;display:inline-flex;font-size:calc(12px * var(--aitwin-size));font-weight:600;gap:calc(8px * var(--aitwin-size));left:50%;line-height:1;padding:calc(8px * var(--aitwin-size)) calc(14px * var(--aitwin-size));pointer-events:none;position:absolute;transform:translate(-50%);z-index:3}.aitwin-widget__face-loading{background:transparent;inset:0;overflow:hidden;pointer-events:none;position:absolute;z-index:4}.aitwin-widget__face-loading-content{align-items:center;display:flex;flex-direction:column;gap:calc(12px * var(--aitwin-size));inset:0;justify-content:center;padding:calc(24px * var(--aitwin-size));position:absolute;z-index:1}.aitwin-widget__logo{color:#fff;display:block;flex-shrink:0;height:calc(64px * var(--aitwin-size));margin-bottom:calc(4px * var(--aitwin-size));width:calc(64px * var(--aitwin-size))}.aitwin-widget__logo-draw{stroke-dasharray:1;stroke-dashoffset:1;animation:aitwin-widget-logo-draw 2.6s ease-in-out forwards}.aitwin-widget__logo-draw--loop{animation:aitwin-widget-logo-draw-loop 2.6s ease-in-out infinite}@keyframes aitwin-widget-logo-draw{to{stroke-dashoffset:0}}@keyframes aitwin-widget-logo-draw-loop{0%{stroke-dashoffset:1}45%{stroke-dashoffset:0}55%{stroke-dashoffset:0}to{stroke-dashoffset:-1}}@media(prefers-reduced-motion:reduce){.aitwin-widget__logo-draw,.aitwin-widget__logo-draw--loop{animation:none;stroke-dashoffset:0}}.aitwin-widget__face-loading-bar-wrap{max-width:calc(220px * var(--aitwin-size));width:100%}.aitwin-widget__face-loading-track{background:#fff3;border-radius:999px;height:calc(4px * var(--aitwin-size));overflow:hidden;width:100%}.aitwin-widget__face-loading-fill{background:var(--aitwin-accent);border-radius:999px;height:100%;transition:width .3s ease-out}.aitwin-widget__face-loading-pct{color:#ffffffbf;font-size:calc(12px * var(--aitwin-size));margin:calc(8px * var(--aitwin-size)) 0 0;text-align:center}.aitwin-widget__composer{display:grid;gap:var(--aitwin-action-gap);grid-template-columns:1fr auto;width:100%}.aitwin-widget__composer-input{background:#ffffff0a;border:1px solid var(--aitwin-border);border-radius:var(--aitwin-action-radius);color:var(--aitwin-text);font-family:inherit;font-size:calc(12px * var(--aitwin-size));min-width:0;outline:none;padding:calc(8px * var(--aitwin-size)) calc(10px * var(--aitwin-size))}.aitwin-widget__composer-input:focus{border-color:#f973168c}.aitwin-widget__composer-send{background:var(--aitwin-accent);border:none;border-radius:var(--aitwin-action-radius);color:#fff;cursor:pointer;font-family:inherit;font-size:calc(12px * var(--aitwin-size));font-weight:600;padding:0 calc(12px * var(--aitwin-size))}.aitwin-widget__composer-send:disabled{cursor:not-allowed;opacity:.45}.aitwin-widget__controls-error{color:#fecaca;font-size:calc(11px * var(--aitwin-size));margin:0}.aitwin-widget--float{bottom:20px;filter:drop-shadow(0 12px 32px rgba(0,0,0,.45));height:fit-content;margin:0;max-width:calc(100vw - 40px);position:fixed;right:20px;width:fit-content;z-index:2147483000}",ni="data-aitwin-widget-style";function ss(){if(typeof document>"u")return;const e=ac.trim();if(!e){console.warn("[AiTwinWidget] styles.css?inline resolved empty — chrome will be unstyled");return}const t=document.querySelector(`style[${ni}]`);if(t){if((t.textContent??"").trim().length>0)return;t.textContent=e;return}const n=document.createElement("style");n.setAttribute(ni,"1"),n.textContent=e,(document.head??document.documentElement).appendChild(n)}typeof document<"u"&&ss();const oc=h.forwardRef(function(t,n){ss();const r=h.useRef(null);h.useImperativeHandle(n,()=>({speakText:async(s,o)=>{const a=r.current?.getTwin();if(!a)throw new Error("AiTwinWidget: twin is not mounted");return a.speakText(s,o)},connect:async s=>{const o=r.current?.getTwin();if(!o)throw new Error("AiTwinWidget: twin is not mounted");return o.connect(s)},disconnect:async()=>{const s=r.current?.getTwin();if(s)return s.disconnect()},stop:()=>{r.current?.getTwin()?.stop()},isReady:()=>!!r.current?.getTwin()?.isReady(),isConnected:()=>!!r.current?.getTwin()?.isConnected(),getTwin:()=>r.current?.getTwin()??null}),[]);const i=!!t.float;return R.jsx("div",{className:i?"aitwin-widget aitwin-widget--float":"aitwin-widget",children:R.jsx(sc,{ref:r,options:t})})}),cc=new Set([".png",".jpg",".jpeg",".webp"]);function as(e=".png"){const t=e.toLowerCase();return cc.has(t)?`source${t}`:"source.png"}function lc(e,t=$n,n=".png"){const r=e.trim();if(!r)throw new Error("faceId is required");return`${t.replace(/\/$/,"")}/${r}/${as(n)}`}exports.AI_TWIN_THUMBNAIL_FILENAME=Yn;exports.AiTwin=ns;exports.AiTwinNotFoundError=nn;exports.AiTwinWidget=oc;exports.CONSONANT_SKIP_GROUP=Ti;exports.DEFAULT_TTS_ENGINE_ID=dt;exports.DEFAULT_TTS_LANGUAGE=Vs;exports.EMOTION_TO_EYEBROW=Gi;exports.EXPRESSION_ATLAS_EMOTIONS=Ra;exports.MIC_SAMPLE_RATE=nr;exports.OCULUS_VISEME_IDS=vi;exports.PLAYBACK_SAMPLE_RATE=rr;exports.SPEAKING_RATE_MAX=yn;exports.SPEAKING_RATE_MIN=pn;exports.TTS_ENGINE_CARTESIA=tt;exports.TTS_ENGINE_GOOGLE=Kn;exports.TTS_ENGINE_INWORLD=un;exports.TTS_ENGINE_VISEMETTS=nt;exports.TTS_LANGUAGE_CATALOG=ft;exports.TTS_LANGUAGE_CODES=wi;exports.VISEME_IDS=_a;exports.VISEME_SKIP_GAP_MS=On;exports.VISEME_TEST_CARTESIA_VOICE_ID=tr;exports.VISEME_TEST_SPEAKING_RATE=Ht;exports.VISEME_TEST_VISEMETTS_VOICE_ID=dn;exports.VISEME_TEST_VOICE_ID=er;exports.VISEME_VTIME_GRID_MS=Qn;exports.VOWEL_SKIP_GROUP=Si;exports.aiTwinSourceFilename=as;exports.buildPlaybackTransitions=Pi;exports.buildPlaybackVisemeSeries=gn;exports.buildRawVisemeTransitions=Mi;exports.buildVoiceWebSocketUrl=Ni;exports.compactSkippableVisemes=Jn;exports.createAvatarTtsLipsyncController=Nn;exports.createRealtimeVoiceLipsyncController=Vi;exports.emotionToEyebrow=mt;exports.faceAssetUrls=Ln;exports.fetchAiTwin=ci;exports.fetchAvatarReply=rs;exports.fetchDevAuthToken=Nt;exports.getAiTwinSourceUrl=lc;exports.getAiTwinThumbnailUrl=li;exports.isTtsLanguageCode=pi;exports.isTtsLanguageSupported=Ws;exports.listSkippedVisemeEntries=wn;exports.listSkippedVisemes=Js;exports.normalizeOculusViseme=mn;exports.normalizeStreamEmotion=Ze;exports.normalizeTtsLanguage=fn;exports.parsePackedVoiceId=si;exports.resolveDirectFaceId=ui;exports.resolveTwinBrainId=qn;exports.resolveVisemeAtTime=zt;exports.resolveVisemeFromPlaybackSeries=xi;exports.resolveWordAtTime=oa;exports.setActiveTwinAssets=di;exports.snapVisemeQueueToGrid=Xn;exports.snapVisemeVtimeToGrid=ki;exports.splitVoiceIdSpec=et;exports.ttsLanguagesForEngine=Us;
|
|
47
|
+
`;function Yr(e=5){const t=new ge.Filter({glProgram:ge.GlProgram.from({vertex:Ao,fragment:Mo,name:"threshold-key-filter"}),resources:{thresholdUniforms:{uThreshold:{value:e/255,type:"f32"}}}});return t.setThreshold=n=>{t.resources.thresholdUniforms.uniforms.uThreshold=n/255},t.getThreshold=()=>Math.round(t.resources.thresholdUniforms.uniforms.uThreshold*255),t}function Ro(e,t,n){return e>n||t>n}function Po(e){return e?e.getParameter(e.MAX_TEXTURE_SIZE):4096}function Co(e,t){return t!=null&&t>0?Math.floor(t):Po(e)}function Do(e,t){const n=document.createElement("canvas");n.width=t.w,n.height=t.h;const r=n.getContext("2d");if(!r)throw new Error("Failed to acquire 2d context for atlas cell crop");return r.drawImage(e,t.x,t.y,t.w,t.h,0,0,t.w,t.h),n}function ns(e){return fetch(e).then(t=>{if(!t.ok)throw new Error(`Failed to load image: ${e}`);return t.blob()}).then(t=>createImageBitmap(t))}async function Qr(e,t,n,r,i){const s=n?await $i(e,i):await fetch(e).then(c=>{if(!c.ok)throw new Error(`Failed to load ${e}`);return c.json()}),o=s.sheets?.[0];if(!o?.path)throw new Error(`${e} has no sheets[0].path`);const a=new Map,u=async(c,m)=>{const p=Gi(t,m,n),T=n?await ga(await Ct(p,i??"")):await ns(p);if(Ro(T.width,T.height,r))return console.info(`[PixiVisemeCompositor] Sheet ${m} (${T.width}x${T.height}) exceeds MAX_TEXTURE_SIZE=${r}; using per-cell crops.`),{mode:"cells",bitmap:T};const f=ge.Texture.from(T);return f.source.scaleMode="nearest",{mode:"full",texture:f}};a.set(o.index,await u(o.index,o.path));for(const c of s.sheets??[])c.index!==o.index&&c.path&&a.set(c.index,await u(c.index,c.path));const d=new Map;for(const c of s.cells??[])c.path&&d.set(c.path,c);const l=new Map;for(const c of s.sheets??[])l.set(c.index,c);return{atlasMeta:s,cellByPath:d,sheetByIndex:l,diffBase:t,sheets:a}}async function Bo(e,t={}){const n=new ge.Application;try{await n.init({canvas:e,width:842,height:1264,preference:"webgl",autoStart:!1,antialias:!1,resolution:1,autoDensity:!1,backgroundAlpha:1,backgroundColor:0,powerPreference:"high-performance"})}catch(_){throw n.destroy({removeView:!1}),_}if(n.renderer.type!==ge.RendererType.WEBGL)throw n.destroy({removeView:!1}),new Error("Pixi did not initialize a WebGL renderer");const r=Co(n.renderer.gl,t.maxTextureSize);let i=!1,s=!1,o=!1;const a=n.canvas,u=()=>{i=!0,!s&&!o&&(s=!0,t.onWebGlContextLost?.())};a.addEventListener("webglcontextlost",u);const d=new ge.Sprite(ge.Texture.EMPTY),l=new ge.Sprite(ge.Texture.EMPTY);l.visible=!1,l.alpha=0;const c=new ge.Sprite(ge.Texture.EMPTY),m=new ge.Sprite(ge.Texture.EMPTY),p=new ge.Sprite(ge.Texture.EMPTY);p.visible=!1;const T=Yr(5),f=Yr(5);c.filters=[T],m.filters=[f],n.stage.addChild(d),n.stage.addChild(l),n.stage.addChild(c),n.stage.addChild(m),n.stage.addChild(p);let I=null,F=null,L=null,b=null,k=null,V=null,C=null,ae=842,fe=1264,M=null,z=5;const Y=new Map;let ce=null,oe=null,re=null;const le=mi(()=>{Y.clear(),V=null,C=null,I=null,M=null}),pe=(_,w)=>{ae=_,fe=w,n.renderer.resize(_,w),(e.width!==_||e.height!==w)&&(e.width=_,e.height=w)},ie=()=>{c.visible=!1,m.visible=!1,c.texture=ge.Texture.EMPTY,m.texture=ge.Texture.EMPTY,ce=null,oe=null},W=()=>{k=null,l.visible=!1,l.alpha=0},A=()=>{d.visible=!0,d.width=ae,d.height=fe,d.x=0,d.y=0},Q=()=>{l.width=ae,l.height=fe,l.x=0,l.y=0},R=()=>{p.visible=!1,W(),I&&(d.texture=I,A())},H=()=>{!k&&!l.visible||R()},Z=_=>{if(o||i||!I){R();return}const w=Math.max(0,_);if(!F||w<=0){R();return}ie(),p.visible=!1,d.texture=F,A(),l.texture=I,Q(),l.alpha=0,l.visible=!0,k={startMs:performance.now(),durationMs:w},ee()},se=(_=performance.now())=>{if(!k)return!1;if(o||i)return H(),!1;const w=(_-k.startMs)/Math.max(1,k.durationMs);if(w>=1)return R(),ee(),!1;const S=Math.min(1,Math.max(0,w)),j=S*S*(3-2*S);return l.alpha=j,l.visible=!0,ee(),!0},y=()=>{if(L){try{L.resource=null}catch{}L.destroy(),L=null}F&&(F.destroy(!1),F=null),b=null},O=(_,w)=>{const S=_.cellByPath.get(w);if(!S||!Hi(S))return null;const j=`${_.diffBase}::${w}`;let te=Y.get(j);if(!te){const E=S.sheet??0,K=_.sheets.get(E);if(!K)return null;let J,we=!1;if(K.mode==="full")J=new ge.Texture({source:K.texture.source,frame:new ge.Rectangle(S.x,S.y,S.w,S.h)});else{const De=Do(K.bitmap,S);J=ge.Texture.from(De),J.source.scaleMode="nearest",we=!0}te={texture:J,ownsSource:we},Y.set(j,te)}return{texture:te.texture,cell:S}},N=(_,w,S,j)=>{if(!j||!S)return _.visible=!1,_.texture=ge.Texture.EMPTY,!1;const te=O(S,j);if(!te)return _.visible=!1,_.texture=ge.Texture.EMPTY,!1;const E=zi(S.atlasMeta,te.cell);return w.setThreshold(z),_.texture=te.texture,_.x=E.x,_.y=E.y,_.width=te.cell.w,_.height=te.cell.h,_.visible=!0,!0},G=_=>{if(!_||!V)return null;const w=M??new Set(V.cellByPath.keys());return cr(_,w)??(w.has(_)?_:null)},$=_=>{p.visible=!1,R();const w=G(_.mouthPath),S=_.expressionPath&&C?ur(_.expressionPath,j=>C.cellByPath.has(j)):null;w!==ce?(N(c,T,V,w),ce=w):w?c.visible=!0:c.visible=!1,S!==oe?(N(m,f,C,S),oe=S):S?m.visible=!0:m.visible=!1},ee=()=>{if(!(o||i||document.hidden))try{n.render()}catch{}};return{async loadAssets(_){if(o)return{width:ae,height:fe,visemePaths:[]};const w=Nt();if(w&&!_)throw new Error("Encrypted assets enabled but no key provided");const S=w?await wa(await Ct(rn(),_??"")):await ns(rn());I&&I.destroy(!0),I=ge.Texture.from(S),I.source.scaleMode="linear";const j=hi();V=await Qr(gi(),j,w,r,_);try{C=await Qr(pi(),j,w,r,_)}catch(E){console.warn("[PixiVisemeCompositor] expression atlas unavailable:",E),C=null}const te=Wi(V.atlasMeta,S.width,S.height);return pe(te.width,te.height),z=yn(V.atlasMeta),T.setThreshold(z),f.setThreshold(z),M=new Set(V.cellByPath.keys()),Y.clear(),R(),ie(),ee(),{width:te.width,height:te.height,visemePaths:[...V.cellByPath.keys()]}},getVisemeAtlasPaths(){return M},drawLiveFrame(_){o||i||!I||(H(),$(_),ee())},drawIdleVideo(_,w){o||i||document.hidden||w&&!w()||_.readyState<HTMLMediaElement.HAVE_CURRENT_DATA||(W(),ie(),p.visible=!1,!F||b!==_?(y(),L=new ge.VideoSource({resource:_,autoPlay:!1,updateFPS:0}),L.autoUpdate=!1,F=new ge.Texture({source:L}),b=_):F.source.update(),d.texture=F,A(),ee())},beginIdleToSilCrossfade:Z,tickIdleToSilCrossfade:se,finishIdleToSilCrossfade:H,isIdleToSilCrossfading(){return k!=null},renderSilOnly(){o||i||!I||(ie(),R(),ee())},blitBitmap(_){o||i||(H(),ie(),re&&(re.destroy(!0),re=null),re=ge.Texture.from(_),p.texture=re,p.visible=!0,p.x=0,p.y=0,p.width=ae,p.height=fe,d.visible=!1,ee())},async compositePrefetchFrame(_){return null},renderFrame:ee,isContextLost(){return i},dispose(){if(o)return;o=!0,a.removeEventListener("webglcontextlost",u),le(),y(),re&&(re.destroy(!0),re=null);for(const{texture:w,ownsSource:S}of Y.values())w.destroy(S);Y.clear(),I&&(I.destroy(!0),I=null);const _=w=>{w.mode==="full"?w.texture.destroy(!0):w.bitmap.close()};if(V)for(const w of V.sheets.values())_(w);if(C)for(const w of C.sheets.values())_(w);T.destroy(!0),f.destroy(!0),n.destroy({removeView:!1},{children:!0,texture:!0})}}}const Xr=-1,Zt=1e5,Jr=new Map;async function Fo(e){let t=Jr.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),Jr.set(e,t)}return new Worker(t,{name:"visemeDiffPreview"})}function Lo(){return typeof Worker<"u"&&typeof OffscreenCanvas<"u"}function jn(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 Zr(e,t){let n=0,r=null;const i=pr(async(s,o)=>(await Hn(),await $n(e,s),i.isLatestSeq(o)));return{usesWorker:!1,usesPixi:!1,async loadAssets(s){const o=await Hn(s);return r=o.visemePaths?new Set(o.visemePaths):null,o},getVisemeAtlasPaths(){return r},async renderSilOnly(){n+=1,i.reset(),await to(e)},drawLiveFrame(s,o,a,u){i.enqueue(o,a,u)},async compositePrefetchFrame(s,o){try{return await eo(s)}catch{return null}},blitBitmap(s,o){jn(s,o)},drawIdleVideo(){},beginIdleToSilCrossfade(){},tickIdleToSilCrossfade(){return!1},finishIdleToSilCrossfade(){},isIdleToSilCrossfading(){return!1},supportsBufferedPlayback:!0,async renderViseme(s,o){n+=1;const a=n;t.onStatus?.(o),await $n(s,{mouthPath:At(o),expressionPath:null})},dispose(){n+=1,i.reset()}}}function Oo(e,t,n){let r=null,i=1,s=0,o=!1,a=!1,u=null;const d=new Map,l=new Map;let c=Zt;const m=pr(async(L,b,k)=>(d.set(b,{drawKey:k.drawKey,onDisplayed:k.onDisplayed}),await I({type:"drawFrame",diffPath:L.mouthPath,expressionDiffPath:L.expressionPath,liveSeq:b},void 0,!0),!1)),p=L=>{if(L===Xr){let V=-1,C;for(const[ae,fe]of d)ae>=V&&(V=ae,C=fe);V>=0&&d.delete(V),C?.onDisplayed?.(C.drawKey);return}const b=-L,k=d.get(b);d.delete(b),k?.onDisplayed?.(k.drawKey)},T=new Map,f=(L,b)=>{a||!r||r.postMessage(L,[])},I=(L,b,k=!1)=>{if(a)return Promise.resolve();const V=i++;return new Promise((C,ae)=>{T.set(V,{resolve:fe=>C(fe),reject:ae,generation:typeof L.generation=="number"?L.generation:void 0,expectRenderDone:k}),f({...L,requestId:V})})},F=(async()=>{r=await Fo(n),r.onmessage=L=>{if(a)return;const b=L.data;if(b.type==="status"){t.onStatus?.(b.label);return}if(b.type==="frame"){if(b.generation<=-Zt){const C=-b.generation,ae=l.get(C);l.delete(C),ae?.resolve(b.bitmap);return}const V=b.generation<0;if(!V&&b.generation!==s){b.bitmap.close();return}if(V&&!(b.generation===Xr)){const ae=-b.generation;if(!m.isLatestSeq(ae)){at()?.onWorkerStale(),b.bitmap.close();return}}if(V&&t.shouldAcceptLiveFrame&&!t.shouldAcceptLiveFrame()){at()?.onWorkerStale(),b.bitmap.close();return}jn(e,b.bitmap),b.bitmap.close(),V&&p(b.generation);return}const k=T.get(b.requestId);if(k)switch(b.type){case"ready":T.delete(b.requestId),k.resolve();break;case"loadAssetsDone":T.delete(b.requestId),u=b.visemePaths?.length?new Set(b.visemePaths):null,k.resolve({width:b.width,height:b.height,visemePaths:b.visemePaths});break;case"renderDone":if(k.expectRenderDone&&k.generation!=null&&b.generation!==k.generation)return;T.delete(b.requestId),k.resolve();break;case"renderAborted":T.delete(b.requestId),k.resolve();break;case"error":T.delete(b.requestId),t.onError?.(b.message),k.reject(new Error(b.message));break}},r.onerror=L=>{if(a)return;const b=L.message||"Worker error";t.onError?.(b);for(const[,k]of T)k.reject(new Error(b));T.clear()},await I({type:"init"}),o=!0})();return{usesWorker:!0,usesPixi:!1,async loadAssets(L){if(a)return{width:842,height:1264};if(await F,a)return{width:842,height:1264};if(!o)throw new Error("Worker init failed");return await I({type:"loadAssets",keyHex:L,urls:Fs(wt())})??{width:842,height:1264}},getVisemeAtlasPaths(){return u},async renderSilOnly(){if(a||(await F,a))return;s+=1,m.reset(),d.clear(),l.forEach(({resolve:b})=>b(null)),l.clear(),c=Zt;const L=s;await I({type:"cancelLiveDraws"}),await I({type:"renderSil",generation:L},void 0,!0)},drawLiveFrame(L,b,k,V){a||F.then(()=>{a||m.enqueue(b,k,V)})},compositePrefetchFrame(L,b){return a?Promise.resolve(null):F.then(()=>{if(a)return null;const k=++c;return new Promise(V=>{l.set(k,{resolve:V}),I({type:"drawFrame",diffPath:L.mouthPath,expressionDiffPath:L.expressionPath,liveSeq:k},void 0,!0).catch(()=>{l.delete(k),V(null)})})})},blitBitmap(L,b){jn(L,b)},drawIdleVideo(){},beginIdleToSilCrossfade(){},tickIdleToSilCrossfade(){return!1},finishIdleToSilCrossfade(){},isIdleToSilCrossfading(){return!1},supportsBufferedPlayback:!0,async renderViseme(L,b,k={}){if(a||(await F,a))return;s+=1,m.reset(),d.clear();const V=s;try{await I({type:"cancelLiveDraws"}),await I({type:"renderViseme",generation:V,to:b,from:k.from,transitionDurationMs:k.transitionDurationMs,gapMs:k.gapMs,threshold:k.threshold},void 0,!0)}catch(C){if(C?.name==="AbortError")return;throw C}},dispose(){if(!a){a=!0,s+=1,m.reset(),d.clear(),l.forEach(({resolve:L})=>L(null)),l.clear(),c=Zt;for(const[,L]of T)L.resolve();T.clear(),r?.terminate(),r=null}}}}async function No(e,t){const n=await Bo(e,{onWebGlContextLost:t.onWebGlContextLost,maxTextureSize:t.pixiMaxTextureSize});let r=0,i=null,s=!1;const o=pr(async(a,u)=>s?!1:t.shouldAcceptLiveFrame&&!t.shouldAcceptLiveFrame()?(at()?.onWorkerStale(),!1):(n.drawLiveFrame(a),o.isLatestSeq(u)));return{usesWorker:!1,usesPixi:!0,async loadAssets(a){if(s)return{width:842,height:1264};const u=await n.loadAssets(a);return i=u.visemePaths?.length?new Set(u.visemePaths):null,u},getVisemeAtlasPaths(){return i},async renderSilOnly(){s||(r+=1,o.reset(),n.renderSilOnly())},drawLiveFrame(a,u,d,l){s||o.enqueue(u,d,l)},async compositePrefetchFrame(a,u){if(s)return null;try{return await n.compositePrefetchFrame(a)}catch{return null}},blitBitmap(a,u){s||t.shouldAcceptLiveFrame&&!t.shouldAcceptLiveFrame()||n.blitBitmap(u)},drawIdleVideo(a,u){s||n.drawIdleVideo(a,u)},beginIdleToSilCrossfade(a){s||n.beginIdleToSilCrossfade(a)},tickIdleToSilCrossfade(a){return s?!1:n.tickIdleToSilCrossfade(a)},finishIdleToSilCrossfade(){s||n.finishIdleToSilCrossfade()},isIdleToSilCrossfading(){return s?!1:n.isIdleToSilCrossfading()},supportsBufferedPlayback:!1,async renderViseme(a,u){if(s)return;r+=1;const d=r;o.reset(),t.onStatus?.(u),n.drawLiveFrame({mouthPath:At(u),expressionPath:null})},dispose(){s||(s=!0,r+=1,o.reset(),n.dispose())}}}function ei(e,t){if(!Lo())return Zr(e,t);const n=ps(t.workerScriptUrl);try{return Oo(e,t,n)}catch{return Zr(e,t)}}function Uo(e,t={}){if(t.preferLegacyRenderer)return ei(e,t);let n=null,r=!1,i=null,s=!1;const o=()=>n?Promise.resolve(n):(i||(i=(async()=>{try{const a=await No(e,t);if(s)throw a.dispose(),new Error("Renderer disposed during Pixi init");return r=!0,n=a,a}catch(a){if(s)throw a instanceof Error?a:new Error(String(a));return console.warn("[AiTwin] Pixi WebGL renderer unavailable, using Canvas2D fallback:",a),n=ei(e,t),r=!1,n}})()),i);return{get usesWorker(){return n?.usesWorker??!1},get usesPixi(){return r},async loadAssets(a){return(await o()).loadAssets(a)},getVisemeAtlasPaths(){return n?.getVisemeAtlasPaths()??null},async renderSilOnly(){return(await o()).renderSilOnly()},drawLiveFrame(a,u,d,l){o().then(c=>{s||c.drawLiveFrame(a,u,d,l)})},async compositePrefetchFrame(a,u){return(await o()).compositePrefetchFrame(a,u)},blitBitmap(a,u){n&&n.blitBitmap(a,u)},drawIdleVideo(a,u){n?.usesPixi&&n.drawIdleVideo(a,u)},beginIdleToSilCrossfade(a){n?.beginIdleToSilCrossfade(a)},tickIdleToSilCrossfade(a){return n?.tickIdleToSilCrossfade(a)??!1},finishIdleToSilCrossfade(){n?.finishIdleToSilCrossfade()},isIdleToSilCrossfading(){return n?.isIdleToSilCrossfading()??!1},get supportsBufferedPlayback(){return n?.supportsBufferedPlayback??!1},async renderViseme(a,u,d){return(await o()).renderViseme(a,u,d)},dispose(){s=!0,i=null,n?.dispose(),n=null}}}class Vo extends Error{constructor(t,n){super(`${t} timed out after ${Math.round(n/1e3)}s`),this.name="LoadTimeoutError"}}function Dn(e,t,n){return new Promise((r,i)=>{const s=globalThis.setTimeout(()=>{i(new Vo(n,t))},t);e.then(o=>{globalThis.clearTimeout(s),r(o)},o=>{globalThis.clearTimeout(s),i(o)})})}const Wo={overflow:"hidden",position:"relative",display:"inline-block",lineHeight:0},zo={display:"block",maxWidth:"100%",height:"auto"},Ho={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 Bn(e){return Ss(e)?sr:ci(e)?un:ir}function Ze(e,t){return t?.isSpeaking()||t?.isWarmingUp()?t:e.isSpeaking()||e.isWarmingUp()?e:t?.isConnected()?t:e}const rs=h.forwardRef(function({id:t,avatarId:n,faceId:r,assets:i,authToken:s,apiBase:o,ttsEngineId:a,voiceId:u,language:d,speakingRate:l=Vt,className:c,style:m,canvasStyle:p,onStatusChange:T,onDisplayStatus:f,onError:I,onReady:F,showErrorOverlay:L=!0,loadingThumbnailUrl:b,onUserTranscript:k,onBotOutput:V,onRealtimeLipsyncDebug:C,onFrameRenderStats:ae,lipsyncBufferedPlayback:fe=!0,lipsyncPlaybackWarmupMs:M=1500,idleHandoffHoldMs:z=go,pixiMaxTextureSize:Y,captions:ce},oe){const re=h.useRef(null),le=h.useRef(null),pe=h.useRef(null),ie=h.useRef(fe);ie.current=fe;const W=h.useRef(M);W.current=M;const A=h.useRef(z);A.current=z;const Q=h.useRef(0),R=h.useRef(hr()),H=h.useRef($a()),Z=h.useRef(!1),se=h.useRef(null),y=h.useRef(null),O=h.useRef(0),N=h.useRef(0),G=h.useRef(0),$=h.useRef(null),ee=h.useRef(null),_=h.useRef(!1),w=h.useRef(!1),S=h.useRef(!1),j=h.useRef(!1),te=h.useRef("sil"),E=h.useRef(0),K=h.useRef(!1),J=h.useRef(null),we=h.useRef(!1),[De,yt]=h.useState("idle"),[Wt,vt]=h.useState(null),[it,vn]=h.useState(!1),[wr,g]=h.useState(!1),[B,ne]=h.useState(!1),[ue,xe]=h.useState(),[be,Me]=h.useState({width:842,height:1264}),[Ue,He]=h.useState(null),[_n,bn]=h.useState(0),ot=h.useRef(!1),je=h.useRef(s??null),Ve=o?.trim()||Pt,ct=h.useRef(null),Se=h.useRef(null),{ttsEngineId:Be,voiceId:We}=h.useMemo(()=>{const v=tt(a,u),x=v.ttsEngineId??mt;return{ttsEngineId:x,voiceId:v.voiceId??Bn(x)}},[a,u]),ze=h.useRef(!1),lt=h.useRef({width:842,height:1264}),Ke=h.useRef(null),Ie=h.useRef("sil"),Ce=h.useRef(""),Re=h.useMemo(()=>ro(ce),[ce]),Fe=h.useCallback(()=>{Ce.current="",He(null)},[]);h.useEffect(()=>{Re.enabled||Fe()},[Re.enabled,Fe]);const _t=h.useCallback(v=>{if(!Re.enabled)return;const x=v.isSpeaking(),U=v.isWarmingUp();if(!x||U){Ce.current&&Fe();return}const P=no(v.getWordQueue());if(!P){Ce.current&&Fe();return}P!==Ce.current&&(Ce.current=P,He(P))},[Re.enabled,Fe]),bt=h.useRef(void 0),St=h.useRef(new Map),zt=h.useRef(F),yr=h.useRef(T),ve=h.useRef(f),vr=h.useRef(I),_r=h.useRef(k),Sn=h.useRef(V),Ht=h.useRef(C),br=h.useRef(ae),Tt=h.useRef(ho());zt.current=F,yr.current=T,ve.current=f,vr.current=I,_r.current=k,Sn.current=V,Ht.current=C,br.current=ae,h.useEffect(()=>{const v=Tt.current;return $r(v),()=>$r(null)},[]);const Tn=h.useCallback(v=>{const x=tt(v?.ttsEngineId??a,v?.voiceId??u),U=x.ttsEngineId??Se.current?.ttsEngineId??mt,P=x.voiceId??Se.current?.voiceId??Bn(U);return{ttsEngineId:U,voiceId:P}},[a,u]),Je=h.useCallback(v=>{vt(v),ne(!0),vr.current?.(v)},[]),Dt=h.useCallback(v=>{yt(v),yr.current?.(v)},[]),de=h.useRef(Wn(Dt,Ve,{onLipsyncDebug:v=>Ht.current?.(v)})),me=h.useRef(null),Sr=h.useRef(()=>{});h.useEffect(()=>(de.current=Wn(Dt,Ve,{onLipsyncDebug:v=>Ht.current?.(v)}),s&&de.current.setDeveloperToken(s),de.current.setTtsEngineId(Be),()=>{de.current.stop();const v=me.current;v&&(v.disconnect(),me.current=null)}),[Dt,Ve]);const Tr=h.useCallback(()=>(me.current||(me.current=Vi(Dt,{speakingRate:l,language:d,onUserTranscript:(v,x)=>_r.current?.(v,x),onBotOutput:v=>Sn.current?.(v),onLipsyncDebug:v=>Ht.current?.(v)}),me.current.setTtsEngineId(Be),Sr.current(!0)),me.current),[Dt,l,d,Be]),Le=h.useCallback(()=>{$.current!=null&&(clearTimeout($.current),$.current=null)},[]),Oe=h.useCallback(()=>{ee.current!=null&&(clearTimeout(ee.current),ee.current=null),S.current=!1},[]),$t=h.useCallback(()=>{if(j.current)return;const v=le.current;if(j.current=!0,Oe(),_.current=!1,w.current=!1,!we.current||!J.current){v?.renderSilOnly();return}J.current.setActive(!1);const x=J.current.getVideo();if(v?.usesPixi){v.drawIdleVideo(x),v.beginIdleToSilCrossfade(Kr);return}(async()=>{const U=re.current;U&&await Pn(U,x,null,void 0,lt.current).catch(()=>{}),await new Promise(P=>setTimeout(P,Kr)),j.current&&await v?.renderSilOnly()})()},[Oe]),kr=h.useCallback(()=>{!we.current||!J.current||(j.current=!1,le.current?.finishIdleToSilCrossfade(),Oe(),S.current=!0,ee.current=setTimeout(()=>{if(ee.current=null,Ze(de.current,me.current).isSpeaking()){S.current=!1;return}if(_.current){S.current=!1;return}const v=J.current;if(!v){S.current=!1;return}v.restart(),v.setActive(!0);const x=v.getVideo();let U=!1;const P=()=>{U||(U=!0,x.removeEventListener("playing",X),S.current=!1)},X=()=>{P()};if(x.addEventListener("playing",X,{once:!0}),x.readyState>=HTMLMediaElement.HAVE_CURRENT_DATA&&!x.paused){P();return}setTimeout(P,300)},A.current))},[Oe]),kt=h.useCallback(()=>{if(Le(),ve.current?.("sil"),_.current=!1,j.current=!1,!we.current||!J.current){S.current=!1;return}kr()},[Le,kr]),kn=h.useCallback(async v=>{const x=N.current,U=le.current,P=re.current,X=()=>{v?.fallbackOnly||(_.current=!1)};if(!U||!P||!it){X();return}if(Ze(de.current,me.current).isSpeaking()){X();return}if(v?.fallbackOnly){if(!_.current||(Ne(R.current),await U.renderSilOnly(),x!==N.current)||Ze(de.current,me.current).isSpeaking())return;kt();return}if(Gr(R.current)){Ne(R.current),kt();return}if(ie.current&&U.supportsBufferedPlayback&&!v?.fallbackOnly){if(Ne(R.current),pe.current?.reset(),await U.renderSilOnly(),x!==N.current||Ze(de.current,me.current).isSpeaking())return;kt();return}const Te=_o(Ze(de.current,me.current).getVisemeQueue(),E.current,te.current),Ae=bo(Te,Ke.current);if(Ne(R.current),!Ae){if(await U.renderSilOnly(),x!==N.current||Ze(de.current,me.current).isSpeaking())return;kt();return}try{await U.renderViseme(P,"sil",{from:Te,transitionDurationMs:Zi})}catch(ke){if(ke?.name!=="AbortError")throw ke}if(x!==N.current){X();return}if(Ze(de.current,me.current).isSpeaking()){X();return}kt()},[it,kt]),ut=h.useCallback(()=>{if(w.current||_.current)return;w.current=!0,_.current=!0,Le();const v=N.current;kn().finally(()=>{w.current=!1}),$.current=setTimeout(()=>{$.current=null,v===N.current&&kn({fallbackOnly:!0})},So())},[Le,kn]),Er=h.useCallback(async()=>{const v=Math.floor(Date.now()/1e3);if(ct.current&&v<ct.current.expiresAt-60)return ct.current.key;const x=je.current??await en();je.current=x,de.current.setDeveloperToken(x);const U=await Ps(x,Ve);return ct.current={key:U.value,expiresAt:U.expiresAt},U.value},[Ve]);h.useEffect(()=>{s&&(je.current=s,de.current.setDeveloperToken(s))},[s]),h.useEffect(()=>{de.current.setTtsEngineId(Be),me.current?.setTtsEngineId(Be),Se.current&&(Se.current.ttsEngineId=Be)},[Be]),h.useEffect(()=>{Se.current&&(Se.current.voiceId=We)},[We]);const Ge=h.useMemo(()=>di(n,r),[n,r]),os=h.useMemo(()=>i?JSON.stringify(i):Ge?`face:${Ge}`:`id:${t??""}`,[i,Ge,t]),cs=h.useMemo(()=>{const v=b?.trim();return v||(Ar(Ge)??Ar(ue)??Es(i))},[b,Ge,ue,i]);return h.useEffect(()=>{if(!t&&!i&&!Ge){Je("AiTwin requires `assets`, `avatarId`/`faceId`, or `id`");return}let v=!1;ze.current=!1,vn(!1),g(!1),ne(!1),xe(Ge),vt(null),Se.current=null,J.current=null,we.current=!1;const x=re.current;if(!x)return;let U=null;return(async()=>{try{let P,X,Ee,Te,Ae;if(i)P=i,X=Be,Ee=We;else if(Ge)ve.current?.("loadFace"),P=Un(Ge),X=Be,Ee=We;else{ve.current?.("getAiTwin");const q=await Dn(li(t),3e4,"getAiTwin");if(v)return;if(!q.faceId?.trim())throw new Error("getAiTwin returned no faceId");xe(q.faceId.trim());const _e=tt(a,u);X=_e.ttsEngineId??q.ttsEngineId,Ee=_e.voiceId??q.voiceId??Bn(X),Te=Xn(q),Ae=Jn(q),P=Un(q.faceId)}Se.current={ttsEngineId:X,voiceId:Ee,brainId:Te,brainUrl:Ae},fi(P),J.current=ja();const ke=!!(i&&!pt(i));U=Uo(x,{preferLegacyRenderer:ke,pixiMaxTextureSize:Y,onStatus:q=>{v||ve.current?.(q)},onError:q=>{v||Je(q)},shouldAcceptLiveFrame:()=>{if(Z.current)return!0;if(_.current)return!1;const q=Ze(de.current,me.current);return q.isSpeaking()||q.isWarmingUp()},onWebGlContextLost:()=>{v||ot.current||(ot.current=!0,queueMicrotask(()=>{v||bn(q=>q+1)}))}}),le.current=U,pe.current=Io(U),ot.current=!1;const qe=q=>{const _e=()=>{if(!q||W.current<=0)return!1;const Pe=le.current;return Pe?ie.current&&Pe.supportsBufferedPlayback?!0:Pe.usesPixi:!1};de.current.setLipsyncWarmupHold(q,_e),me.current?.setLipsyncWarmupHold(q,_e)};Sr.current=qe,qe(!0),ve.current?.("auth");const jt=je.current??s??await Dn(en(),3e4,"getAuthToken");if(v)return;je.current=jt,de.current.setDeveloperToken(jt),de.current.setTtsEngineId(X);const ye=Nt()?await Er():void 0;if(v)return;ve.current?.("loadAssets");const he=await Dn(U.loadAssets(ye),18e4,"load face assets");if(!v&&he.width>0&&he.height>0&&(lt.current=he,Me(he)),v)return;Ke.current=U.getVisemeAtlasPaths(),ze.current=!0,vn(!0),zt.current?.(),U.renderSilOnly().then(()=>{v||ve.current?.("sil")}),(async()=>{try{const q=await _a(ye);if(await J.current.load(q),v)return;we.current=!0,g(!0),Ne(R.current),J.current.setActive(!0);const _e=J.current.getVideo();U.usesPixi?U.drawIdleVideo(_e):await Pn(x,_e,null,void 0,lt.current)}catch(q){if(v)return;we.current=!1,g(!1),console.warn("[AiTwin] Idle video unavailable:",q)}finally{v||(ne(!0),ve.current?.("idle"))}})()}catch(P){if(v)return;if(P instanceof tn){Je(P.message);return}Je(P instanceof Error?P.message:"Failed to load AI twin")}})(),()=>{v=!0,J.current?.dispose(),U?.dispose(),le.current=null}},[os,i,Ge,t,Be,We,a,u,s,Y,Er,Je,_n]),h.useEffect(()=>{const v={current:!1},x=()=>{const U=re.current,P=le.current,X=Ze(de.current,me.current);if(!U||!P||!it){O.current=requestAnimationFrame(x);return}if(document.hidden){J.current?.setActive(!1),O.current=requestAnimationFrame(x);return}const Ee=X.isSpeaking(),Te=X.isWarmingUp(),Ae=Ee&&!K.current,ke=K.current&&!Ee;Ae&&(Le(),Oe(),_.current=!1,w.current=!1,Ne(R.current),pe.current?.reset(),Tt.current.reset(),bt.current=void 0,G.current=0,te.current="sil",E.current=0,$t()),ke&&(H.current.reset(),J.current?.setActive(!1),pe.current?.reset(),P.finishIdleToSilCrossfade(),Fe(),ut());const qe=ke||_.current||S.current||j.current,jt=fe&&P.supportsBufferedPlayback;if(Te){if($t(),we.current&&J.current?.setActive(!1),P.usesPixi&&P.isIdleToSilCrossfading()){P.tickIdleToSilCrossfade(performance.now()),X.getVisemeQueue().length>0&&Q.current===0&&(Q.current=performance.now()),K.current=X.isSpeaking(),O.current=requestAnimationFrame(x);return}const ye=X.getVisemeQueue();ye.length>0&&Q.current===0&&(Q.current=performance.now()),H.current.advance(performance.now());const he=H.current.getExpressionPath(),q=H.current.getDrawKey(),_e={queue:ye,elapsedMs:0,expressionPath:he,expressionDrawKey:q,availablePaths:Ke.current};let Pe=!1;jt&&pe.current?(pe.current.warmupTick(_e),Pe=pe.current.isWarmupReady(_e,W.current)):P.usesPixi&&qr(U,ye,0,he,q,R.current,(Et,Kt,En,Gt)=>{P.drawLiveFrame(Et,Kt,En,Ye=>{Gt?.(Ye),X.isWarmingUp()&&Ye!==""&&!Gr({lastDrawnKey:Ye})&&(Q.current=0,X.releaseWarmupHold())})},Et=>{ve.current?.(Et.label)},Ke.current);const st=Q.current>0&&performance.now()-Q.current>ys;ve.current?.(Pe?"buffer ready":"buffering lipsync…"),(Pe||st)&&(Q.current=0,X.releaseWarmupHold()),_t(X),K.current=X.isSpeaking(),O.current=requestAnimationFrame(x);return}if(Ee){$t(),we.current&&J.current?.setActive(!1),P.usesPixi&&P.isIdleToSilCrossfading()&&P.finishIdleToSilCrossfade();const ye=X.getVisemeQueue(),he=X.getPlaybackElapsedMs();oa(ye,he),E.current=he;const q=ye.length>0?Ut(ye,he):"sil";q!=="sil"&&(te.current=q);const _e=Ya(he,X.getSentenceEmotions(),X.getWordQueue(),X.getStreamMood());H.current.setTargetEmotion(_e),H.current.setTargetEyebrow(za(he,X.getWordQueue(),gt(_e))),H.current.advance(performance.now());const Pe=H.current.getExpressionPath(),st=H.current.getDrawKey(),Et=(Ye,xn,Bt,In)=>{const xr={label:Ie.current,elapsedMs:he,mouthPath:xn.mouthPath,transitionMeta:bt.current};St.current.set(Bt,xr),pe.current?.markExternallyDisplayed(Bt,Pe),P.drawLiveFrame(Ye,xn,Bt,qt=>{const ls=St.current.get(qt)??xr;St.current.delete(qt),Tt.current.onDrawDisplayed(ls,ye),pe.current?.markExternallyDisplayed(qt,Pe),In?.(qt)})},Kt=Ye=>{Ie.current=Ye.label,bt.current=Ye.transitionMeta,ve.current?.(Ye.label)},En=fe&&P.supportsBufferedPlayback;let Gt=!1;En&&pe.current&&(Gt=pe.current.tick({canvas:U,queue:ye,elapsedMs:he,expressionPath:Pe,expressionDrawKey:st,playbackState:R.current,availablePaths:Ke.current,onStatus:Kt,onDisplayed:(xn,Bt,In)=>{Tt.current.onDrawDisplayed({label:In,elapsedMs:he,mouthPath:Bt,transitionMeta:bt.current},ye)}}).usedBuffer),Gt||qr(U,ye,he,Pe,st,R.current,Et,Kt,Ke.current),Tt.current.onRafTickSpeaking(),br.current?.(Tt.current.snapshot(ye,he))}else if(!qe&&Z.current){J.current?.setActive(!1),H.current.advance(performance.now());const ye=H.current.getExpressionPath(),he=H.current.getDrawKey();Cn(U,ye,he,R.current,(q,_e,Pe,st)=>P.drawLiveFrame(q,_e,Pe,st),q=>{if(y.current){ve.current?.(y.current);return}const _e=H.current.getTargetEmotion();ve.current?.(q==="sil"||q==="blink"?`${_e}${q==="blink"?" · blink":""}`:q)},null,se.current)}else if(!qe&&we.current&&J.current){const ye=J.current,he=ye.getVideo();if(he.readyState>=HTMLMediaElement.HAVE_CURRENT_DATA){ye.setActive(!0);const q=()=>!X.isSpeaking()&&!_.current&&!S.current&&!Z.current;P.usesPixi?(P.drawIdleVideo(he,q),q()&&ve.current?.("idle")):v.current||(v.current=!0,Pn(U,he,null,void 0,lt.current,q).then(()=>ve.current?.("idle")).finally(()=>{v.current=!1}))}else Cn(U,null,"__sil__",R.current,(q,_e,Pe,st)=>P.drawLiveFrame(q,_e,Pe,st),q=>ve.current?.(q))}else qe||Cn(U,null,"__sil__",R.current,(ye,he,q,_e)=>P.drawLiveFrame(ye,he,q,_e),ye=>ve.current?.(ye));Re.enabled&&_t(X),K.current=Ee,O.current=requestAnimationFrame(x)};return O.current=requestAnimationFrame(x),()=>{cancelAnimationFrame(O.current),Le(),Oe(),de.current.stop(),me.current?.stop()}},[it,wr,ut,Le,Oe,$t,_t,Fe,Re.enabled]),h.useImperativeHandle(oe,()=>({speakText:async(v,x)=>{const U=v.trim();if(!U)return;const P=le.current;if(!P||!ze.current&&!it)throw new Error("AI twin is not ready");const{ttsEngineId:X,voiceId:Ee}=Tn(x);vt(null),Fe(),N.current+=1,Le(),Oe(),_.current=!1,w.current=!1,te.current="sil",E.current=0,Ne(R.current),Z.current=!1,se.current=null,y.current=null,H.current.reset(),K.current=!1,j.current=!1,P.finishIdleToSilCrossfade();try{await de.current.speak(U,{voiceId:Ee,speakingRate:x?.speakingRate??l,ttsEngineId:X,language:x?.language??d})}catch(Te){throw j.current=!1,P.finishIdleToSilCrossfade(),ut(),Je(Te instanceof Error?Te.message:"TTS failed"),Te}},speakWithReply:async(v,x)=>{const U=v.trim();if(!U)return{displayText:"",spokenText:""};const P=le.current;if(!P||!ze.current&&!it)throw new Error("AI twin is not ready");const{ttsEngineId:X,voiceId:Ee}=Tn(x);vt(null),Fe(),N.current+=1,Le(),Oe(),_.current=!1,w.current=!1,te.current="sil",E.current=0,Ne(R.current),Z.current=!1,se.current=null,y.current=null,H.current.reset(),K.current=!1,j.current=!1,P.finishIdleToSilCrossfade();const Te=x?.brainId?.trim()||Se.current?.brainId?.trim()||void 0,Ae=x?.brainUrl?.trim()||Se.current?.brainUrl?.trim()||void 0;try{return await de.current.speakWithReply(U,{...x,voiceId:Ee,speakingRate:x?.speakingRate??l,ttsEngineId:X,language:x?.language??d,brainId:Te,brainUrl:Ae,onDisplayText:ke=>{x?.onDisplayText?.(ke),Sn.current?.(ke)}})}catch(ke){throw j.current=!1,P.finishIdleToSilCrossfade(),ut(),Je(ke instanceof Error?ke.message:"speakWithReply failed"),ke}},stop:()=>{N.current+=1,Le(),Oe(),_.current=!1,w.current=!1,j.current=!1,le.current?.finishIdleToSilCrossfade(),de.current.stop(),me.current?.stop(),Ne(R.current),pe.current?.reset(),Q.current=0,K.current=!1,Fe(),ut()},setTtsEngineId:v=>{de.current.setTtsEngineId(v),me.current?.setTtsEngineId(v),Se.current&&(Se.current.ttsEngineId=v)},renderViseme:async(v,x)=>{const U=le.current,P=re.current;if(!U||!P||!ze.current)throw new Error("AI twin is not ready");await U.renderViseme(P,v,{from:x?.from,transitionDurationMs:x?.transitionDurationMs,gapMs:x?.gapMs,onStatus:X=>ve.current?.(X)})},setEmotion:v=>{if(!ze.current)throw new Error("AI twin is not ready");const x=le.current,U=re.current;if(!x||!U)throw new Error("AI twin is not ready");N.current+=1,Le(),Oe(),_.current=!1,w.current=!1,S.current=!1,j.current=!1,de.current.stop(),me.current?.stop(),Ne(R.current),pe.current?.reset(),Q.current=0,K.current=!1,x.finishIdleToSilCrossfade(),J.current?.setActive(!1);const P=et(v);Z.current=!0,se.current=null,y.current=null,H.current.snapToEmotion(P);const X=H.current.getExpressionPath(),Ee=H.current.getDrawKey(),Te={mouthPath:null,expressionPath:X},Ae=Ot(Te,Ee);R.current.lastDrawnKey="",x.drawLiveFrame(U,Te,Ae,qe=>{qe===Ae&&(R.current.lastDrawnKey=Ae)});const ke=gt(P);ve.current?.(X?`${P} · brow ${ke>0?"+":""}${ke}`:`${P} · brow 0 (sil base)`)},getEmotion:()=>Z.current?H.current.getTargetEmotion():null,clearEmotionPreview:()=>{Z.current=!1,se.current=null,y.current=null,H.current.reset(),Ne(R.current),ve.current?.("idle")},setViseme:v=>{if(!ze.current)throw new Error("AI twin is not ready");const x=le.current,U=re.current;if(!x||!U)throw new Error("AI twin is not ready");N.current+=1,Le(),Oe(),_.current=!1,w.current=!1,S.current=!1,j.current=!1,de.current.stop(),me.current?.stop(),Ne(R.current),pe.current?.reset(),Q.current=0,K.current=!1,x.finishIdleToSilCrossfade(),J.current?.setActive(!1);const P=fn(v);Z.current=!0,y.current=P,se.current=P==="sil"?null:At(P),H.current.snapToEmotion("neutral");const X=H.current.getExpressionPath(),Ee=H.current.getDrawKey(),Ae={mouthPath:se.current,expressionPath:X},ke=Ot(Ae,Ee);R.current.lastDrawnKey="",x.drawLiveFrame(U,Ae,ke,qe=>{qe===ke&&(R.current.lastDrawnKey=ke)}),ve.current?.(P)},getViseme:()=>Z.current?y.current:null,isReady:()=>ze.current,getStatus:()=>De,connect:async(v={})=>{vt(null);try{let x=v.authToken?.trim();x||(x=je.current??s??await en(),je.current=x);const U=tt(v.ttsEngineId??a,v.voiceId??u),P=U.voiceId??Se.current?.voiceId,X=v.brainId?.trim()||v.personaId?.trim()||Se.current?.brainId,Ee=v.brainUrl?.trim()||Se.current?.brainUrl,Te=U.ttsEngineId??Se.current?.ttsEngineId??Be,Ae=Tr();Te&&Ae.setTtsEngineId(Te),await Ae.unlockAudio(),await Ae.connect({...v,apiBase:v.apiBase?.trim()||Ve,authToken:x,voiceId:P,brainId:X,brainUrl:Ee,ttsEngineId:Te,speakingRate:v.speakingRate??l,language:v.language??d})}catch(x){throw Je(x instanceof Error?x.message:"Voice connect failed"),x}},disconnect:async()=>{const v=me.current;v&&(N.current+=1,Le(),Oe(),_.current=!1,w.current=!1,j.current=!1,le.current?.finishIdleToSilCrossfade(),Ne(R.current),pe.current?.reset(),Q.current=0,K.current=!1,await v.disconnect(),ut())},isConnected:()=>me.current?.isConnected()??!1,getVoiceStream:()=>me.current?.getVoiceStream()??de.current?.getVoiceStream()??null,setMuted:v=>{const x=de.current,U=me.current;x?.setMuted?.(v),U?.setMuted?.(v)},isMuted:()=>{const v=me.current,x=de.current;return v?.isMuted?.()??x?.isMuted?.()??!1},getBrainId:()=>Se.current?.brainId?.trim()||null,getPersonaId:()=>Se.current?.brainId?.trim()||null,getBrainUrl:()=>Se.current?.brainUrl?.trim()||null}),[it,l,d,s,Be,We,Le,Oe,ut,Je,Tn,Tr,De,Ve]),D.jsxs("div",{className:c,style:{...Wo,...m},children:[D.jsx("canvas",{ref:re,width:be.width,height:be.height,style:{...zo,...p},"aria-label":t?`AI twin ${t}`:"AI twin face"}),!B&&!Wt?D.jsx(fo,{thumbnailUrl:cs}):null,L&&Wt?D.jsx("div",{style:Ho,children:Wt}):null,Re.enabled&&Ue?D.jsx(oo,{text:Ue,style:Re.style},Ue):null]})});function $o({muted:e}){return e?D.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none","aria-hidden":!0,children:[D.jsx("path",{d:"M11 5 6.5 9H3v6h3.5L11 19V5Z",fill:"currentColor"}),D.jsx("path",{d:"m16 9.5 5 5m0-5-5 5",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round"})]}):D.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none","aria-hidden":!0,children:[D.jsx("path",{d:"M11 5 6.5 9H3v6h3.5L11 19V5Z",fill:"currentColor"}),D.jsx("path",{d:"M15.5 8.5a4.5 4.5 0 0 1 0 7M18.5 6a8 8 0 0 1 0 12",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round"})]})}function jo(){return D.jsx("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"currentColor","aria-hidden":!0,children:D.jsx("path",{d:"M8 5.5v13l11-6.5L8 5.5Z"})})}function Ko(){return D.jsx("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"currentColor","aria-hidden":!0,children:D.jsx("rect",{x:"6",y:"6",width:"12",height:"12",rx:"1.5"})})}function Go(){return D.jsx("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none","aria-hidden":!0,children:D.jsx("path",{d:"M5 6.5A2.5 2.5 0 0 1 7.5 4h9A2.5 2.5 0 0 1 19 6.5v7A2.5 2.5 0 0 1 16.5 16H10l-4 3.5V16H7.5A2.5 2.5 0 0 1 5 13.5v-7Z",stroke:"currentColor",strokeWidth:"2",strokeLinejoin:"round"})})}function is({className:e}){return D.jsx("span",{className:e??"aitwin-widget__spinner","aria-hidden":!0,children:D.jsx("svg",{viewBox:"0 0 24 24",fill:"none",children:D.jsx("circle",{cx:"12",cy:"12",r:"9",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeDasharray:"40 20"})})})}function qo({muted:e,onToggle:t}){return D.jsx("button",{type:"button",className:"aitwin-widget__mute",onClick:t,"aria-label":e?"Unmute":"Mute","aria-pressed":e,children:D.jsx($o,{muted:e})})}function Yo(){return D.jsxs("div",{className:"aitwin-widget__connecting",role:"status","aria-live":"polite",children:[D.jsx(is,{className:"aitwin-widget__spinner aitwin-widget__spinner--accent"}),D.jsx("span",{children:"Connecting..."})]})}function Qo(e){const t=e.connecting||e.textSending||e.status==="loading"||e.status==="speaking",n=e.connecting?"Connecting...":e.connected?"End Talk":"Talk",r=["aitwin-widget__action",e.textMode&&!e.connecting?"":"aitwin-widget__action--primary",e.connecting?"aitwin-widget__action--connecting":""].filter(Boolean).join(" ");return D.jsxs("div",{className:"aitwin-widget__controls",children:[D.jsxs("div",{className:"aitwin-widget__actions",children:[D.jsxs("button",{type:"button",className:r,onClick:e.onTalk,disabled:!e.ready||e.connecting||e.textSending,"aria-busy":e.connecting,children:[e.connecting?D.jsx(is,{className:"aitwin-widget__spinner aitwin-widget__spinner--on-accent"}):e.connected?D.jsx(Ko,{}):D.jsx(jo,{}),D.jsx("span",{children:n})]}),D.jsxs("button",{type:"button",className:e.textMode?"aitwin-widget__action aitwin-widget__action--primary":"aitwin-widget__action",onClick:e.onTextMode,disabled:!e.ready||e.connecting||e.textSending,"aria-pressed":e.textMode,children:[D.jsx(Go,{}),D.jsx("span",{children:"Text"})]})]}),e.textMode?D.jsxs("form",{className:"aitwin-widget__composer",onSubmit:i=>{i.preventDefault(),e.onSendText()},children:[D.jsx("input",{type:"text",className:"aitwin-widget__composer-input",value:e.textDraft,onChange:i=>e.onTextDraftChange(i.target.value),placeholder:e.textSending?"Getting reply...":"Type a message…",autoComplete:"off",disabled:!e.ready||t}),D.jsx("button",{type:"submit",className:"aitwin-widget__composer-send",disabled:!e.ready||t||!e.textDraft.trim()&&!e.textSending,"aria-busy":e.textSending,children:e.textSending?"…":"Send"})]}):null,e.error?D.jsx("p",{className:"aitwin-widget__controls-error",role:"alert",children:e.error}):null]})}const ti=97,Xo=3500;function Jo(e,t){const n=Math.max(0,e),r=1-Math.exp(-n/Xo);return Math.min(ti,Math.round(r*ti))}function Zo(e){const[t,n]=h.useState(null),[r,i]=h.useState(()=>Date.now());return h.useEffect(()=>{if(!e){n(null);return}const s=Date.now();n(s),i(s);let o=0;const a=()=>{i(Date.now()),o=window.requestAnimationFrame(a)};return o=window.requestAnimationFrame(a),()=>{window.cancelAnimationFrame(o)}},[e]),e?t==null?0:Jo(r-t):100}const ec="M259.01,593.87v-101.49c.33-6.31,4.94-11.26,10.21-11.88,6.42-.75,13.18,4.99,13.13,12.92-.42,45.09-.83,90.17-1.25,135.26.03,1.56.56,15.43,11.95,23.2,6.18,4.21,12.57,4.6,15.42,4.58-.42-112.77-.83-225.54-1.25-338.31-.08-2.55-1.03-46.36,21.17-55.34,2.05-.83,4.42-1.41,7.17-1.56v453.42c.07,12.06,1.98,37.84,19.03,62.73,7.01,10.23,14.79,17.71,21.4,22.99V222.42c-.01-3.72.48-11.67,5.35-19.87,7-11.77,18.13-15.82,21.4-16.95,10.42-3.61,19.49-2.06,23.48-1.11v684.96c.59,4.03,1.78,9.72,4.45,16.12,1.93,4.63,8.84,20.57,26.47,31.26,13.48,8.18,26.56,9.23,32.86,9.31-1.3-256.11-2.59-512.22-3.89-768.33.76-16.43,14.57-28.94,29.73-28.34,13.53.53,25.39,11.39,27.23,25.84-1.1,264.68-2.2,529.35-3.3,794.03,4.33.92,22.38,4.25,38.94-6.53,10.26-6.68,15.24-15.72,17.09-19.17,5.55-10.36,6.42-19.98,6.53-25.01-.72-246.99-1.43-493.97-2.15-740.96,2.27-.06,34.75-.44,48.29,22.68,3.41,5.83,4.87,11.86,5.34,17.19v674.68c5.92-2.16,39.19-14.94,50.16-47.79,3.12-9.34,3.68-18.03,3.33-25.01.03-193.22.06-386.43.09-579.65,4.12,1.18,28.28,8.48,36.17,30.08,1.64,4.49,2.32,8.88,2.43,12.92.02,146.42.05,292.84.07,439.25,3.82-1.71,19.51-9.22,25.56-26.47,2.15-6.12,2.48-11.73,2.29-15.89.01-114.91.03-229.81.04-344.72,2.36-.1,7.51.02,12.74,3.13,9.1,5.4,10.87,15.35,11.12,16.88.35,11.49.69,22.97,1.04,34.46.46,37.05.93,74.1,1.39,111.15v152.69c3.39-.72,9.77-2.67,14.31-8.34,3.62-4.52,4.51-9.46,5.56-15.28.91-5.04.95-9.31.83-12.23.02-38.81.03-77.62.05-116.43";function tc({className:e="aitwin-widget__logo",strokeWidth:t=15,durationMs:n=2600,delayMs:r=0,loop:i=!1}){return D.jsx("svg",{viewBox:"0 0 1080 1080",className:e,role:"img","aria-label":"AITWIN logo",children:D.jsx("path",{className:i?"aitwin-widget__logo-draw aitwin-widget__logo-draw--loop":"aitwin-widget__logo-draw",d:ec,fill:"none",stroke:"currentColor",strokeWidth:t,strokeMiterlimit:10,pathLength:1,style:{animationDuration:`${n}ms`,animationDelay:`${r}ms`}})})}function nc({progress:e}){const t=Math.max(0,Math.min(100,Math.round(e)));return D.jsx("div",{className:"aitwin-widget__face-loading","aria-live":"polite","aria-label":`Loading ${t} percent`,children:D.jsxs("div",{className:"aitwin-widget__face-loading-content",children:[D.jsx(tc,{className:"aitwin-widget__logo",loop:!0,durationMs:2600}),D.jsxs("div",{className:"aitwin-widget__face-loading-bar-wrap",children:[D.jsx("div",{role:"progressbar","aria-valuenow":t,"aria-valuemin":0,"aria-valuemax":100,className:"aitwin-widget__face-loading-track",children:D.jsx("div",{className:"aitwin-widget__face-loading-fill",style:{width:`${t}%`}})}),D.jsxs("p",{className:"aitwin-widget__face-loading-pct",children:[t,"%"]})]})]})})}function ni(e){const t=e.id?.trim()||void 0,n=e.faceId?.trim()||e.avatarId?.trim()||void 0;return{id:n?void 0:t,faceId:n,authToken:e.authToken?.trim()||void 0,apiBase:e.apiBase?.trim()||void 0,voiceId:e.voiceId?.trim()||void 0,speakingRate:e.speakingRate,language:e.language}}function rc(e){return[e.id??"",e.faceId??"",e.authToken?.slice(0,16)??"",e.voiceId??"",e.apiBase??"",String(e.speakingRate??"")].join("|")}const ri={display:"flex",alignItems:"center",justifyContent:"center",width:"100%",height:"100%",lineHeight:0},ic={display:"block",height:"100%",width:"100%",objectFit:"cover",objectPosition:"top"},sc=h.forwardRef(function({options:t},n){const r=h.useRef(null),i=h.useRef(t);i.current={...i.current,onReady:t.onReady,onStatusChange:t.onStatusChange,onError:t.onError,onUserTranscript:t.onUserTranscript,onBotOutput:t.onBotOutput};const[s,o]=h.useState(!!t.showControls),[a,u]=h.useState(()=>ni(t)),[d,l]=h.useState(!1),[c,m]=h.useState(!1),[p,T]=h.useState(!1),[f,I]=h.useState(!1),[F,L]=h.useState("idle"),[b,k]=h.useState(null),[V,C]=h.useState(!1),[ae,fe]=h.useState(!1),[M,z]=h.useState(""),[Y,ce]=h.useState(!1),[oe,re]=h.useState([]),[le,pe]=h.useState(t.brainId?.trim()||t.personaId?.trim()||void 0),[ie,W]=h.useState(t.brainUrl?.trim()||void 0),A=h.useCallback(E=>{i.current={...i.current,...E},E.showControls!==void 0&&o(!!E.showControls),(E.brainId!==void 0||E.personaId!==void 0)&&pe((E.brainId??E.personaId)?.trim()||void 0),E.brainUrl!==void 0&&W(E.brainUrl.trim()||void 0),u(K=>ni({id:E.id??K.id,faceId:E.faceId??E.avatarId??K.faceId,authToken:E.authToken??K.authToken,apiBase:E.apiBase??K.apiBase,voiceId:E.voiceId??K.voiceId,speakingRate:E.speakingRate??K.speakingRate,language:E.language??K.language}))},[]);h.useImperativeHandle(n,()=>({getTwin:()=>r.current,applyOptions:A}),[A]),h.useEffect(()=>{A(t)},[A,t.id,t.faceId,t.avatarId,t.authToken,t.apiBase,t.voiceId,t.speakingRate,t.showControls,t.brainId,t.personaId,t.brainUrl]);const Q=h.useCallback(()=>{l(!0),k(null)},[]),R=h.useCallback(E=>{E==="idle"&&m(!0)},[]),H=h.useCallback(E=>{L(E),i.current.onStatusChange?.(E)},[]),Z=h.useCallback(E=>{k(E),l(!1),m(!1),I(!1),i.current.onError?.(E)},[]),se=h.useCallback((E,K)=>{i.current.onUserTranscript?.(E,K)},[]),y=h.useCallback(E=>{i.current.onBotOutput?.(E)},[]);h.useEffect(()=>{if(!s)return;const E=window.setInterval(()=>{T(!!r.current?.isConnected())},400);return()=>window.clearInterval(E)},[s,a]);const O=rc(a),N=!!(a.id||a.faceId),G=d&&c,$=N&&!G&&!b,ee=Zo($),_=h.useRef(O);h.useEffect(()=>{G&&i.current.onReady?.()},[G]),h.useEffect(()=>{G&&r.current?.setMuted(V)},[G,V,a]),h.useEffect(()=>{re([])},[a.id,a.faceId]),h.useEffect(()=>{_.current!==O&&(_.current=O,l(!1),m(!1),k(null),I(!1),T(!1),L("idle"))},[O]);const w=()=>{const E=r.current;if(!E?.isReady())return;if(k(null),fe(!1),E.isConnected()){I(!1),E.disconnect().finally(()=>{T(!1)});return}I(!0);const K={authToken:a.authToken,voiceId:a.voiceId,speakingRate:a.speakingRate,language:a.language,apiBase:a.apiBase,...le?{brainId:le}:{},...ie?{brainUrl:ie}:{}};E.connect(K).then(()=>{T(!!E.isConnected())}).catch(J=>{const we=J instanceof Error?J.message:"Failed to connect voice.";k(we),i.current.onError?.(we)}).finally(()=>{I(!1)})},S=()=>{fe(E=>!E),k(null)},j=()=>{const E=M.trim(),K=r.current;!E||!K?.isReady()||Y||(k(null),z(""),ce(!0),i.current.onUserTranscript?.(E,!0),(async()=>{try{const J=le||K.getBrainId()?.trim()||void 0,we=ie||K.getBrainUrl()?.trim()||void 0,De=await K.speakWithReply(E,{brainId:J,brainUrl:we,history:oe,voiceId:a.voiceId,speakingRate:a.speakingRate,language:a.language});De.displayText&&re(yt=>[...yt,{role:"user",content:E},{role:"assistant",content:De.displayText}])}catch(J){const we=J instanceof Error?J.message:"Failed to get reply.";k(we),i.current.onError?.(we)}finally{ce(!1)}})())},te=()=>{const E=!V;C(E),r.current?.setMuted(E)};return D.jsxs("div",{className:"aitwin-widget__layout",children:[D.jsxs("div",{className:"aitwin-widget__stage",children:[N?D.jsx("div",{style:ri,children:D.jsx(rs,{ref:r,id:a.id,faceId:a.faceId,authToken:a.authToken,apiBase:a.apiBase,voiceId:a.voiceId,speakingRate:a.speakingRate,language:a.language,style:ri,canvasStyle:ic,onReady:Q,onDisplayStatus:R,onStatusChange:H,onError:Z,onUserTranscript:se,onBotOutput:y,loadingThumbnailUrl:t.loadingThumbnailUrl},O)}):D.jsx("p",{className:"aitwin-widget__hint",style:{padding:16},children:"Pass id or faceId to load a twin."}),$?D.jsx(nc,{progress:ee}):null,s?D.jsx(qo,{muted:V,onToggle:te}):null,s&&f?D.jsx(Yo,{}):null]}),s?D.jsx(Qo,{ready:G,connected:p,connecting:f,status:F,textMode:ae,textDraft:M,textSending:Y,error:b,onTalk:w,onTextMode:S,onTextDraftChange:z,onSendText:j}):null]})}),ac=".aitwin-widget{--aitwin-border: rgba(255, 255, 255, .12);--aitwin-text: #f4f4f5;--aitwin-muted: #a1a1aa;--aitwin-accent: #f97316;--aitwin-accent-hover: #fb923c;--aitwin-font: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, sans-serif;--aitwin-size: 1;--aitwin-stage-width: calc(200px * var(--aitwin-size));--aitwin-stage-height: calc(267px * var(--aitwin-size));--aitwin-action-height: calc(40px * var(--aitwin-size));--aitwin-action-font: calc(13px * var(--aitwin-size));--aitwin-action-radius: calc(10px * var(--aitwin-size));--aitwin-action-gap: calc(6px * var(--aitwin-size));--aitwin-mute-size: calc(28px * var(--aitwin-size));--aitwin-layout-gap: calc(8px * var(--aitwin-size));box-sizing:border-box;color:var(--aitwin-text);font-family:var(--aitwin-font);font-size:calc(12px * var(--aitwin-size));line-height:1.45;width:fit-content;max-width:100%}.aitwin-widget *,.aitwin-widget *:before,.aitwin-widget *:after{box-sizing:border-box}.aitwin-widget__layout{display:flex;flex-direction:column;gap:var(--aitwin-layout-gap);width:fit-content;max-width:100%}.aitwin-widget__stage{align-items:center;background:#0a0a0b;border:1px solid var(--aitwin-border);border-radius:calc(10px * var(--aitwin-size));display:flex;flex-shrink:0;height:var(--aitwin-stage-height);justify-content:center;line-height:0;overflow:hidden;position:relative;width:var(--aitwin-stage-width)}.aitwin-widget__stage .aitwin-root,.aitwin-widget__stage canvas{display:block;height:100%;object-fit:cover;object-position:top;width:100%}.aitwin-widget__hint{color:var(--aitwin-muted);font-size:calc(11px * var(--aitwin-size));margin:0}.aitwin-widget__mute{align-items:center;background:#28282cb8;border:none;border-radius:999px;color:#fff;cursor:pointer;display:inline-flex;height:var(--aitwin-mute-size);justify-content:center;padding:0;position:absolute;right:calc(8px * var(--aitwin-size));top:calc(8px * var(--aitwin-size));width:var(--aitwin-mute-size);z-index:2}.aitwin-widget__mute:hover{background:#37373cd9}.aitwin-widget__mute svg{height:calc(15px * var(--aitwin-size));width:calc(15px * var(--aitwin-size))}.aitwin-widget__controls{display:flex;flex-direction:column;gap:var(--aitwin-action-gap);width:var(--aitwin-stage-width)}.aitwin-widget__actions{display:grid;gap:var(--aitwin-action-gap);grid-template-columns:1fr 1fr;width:100%}.aitwin-widget__action{align-items:center;background:transparent;border:1.5px solid var(--aitwin-accent);border-radius:999px;color:var(--aitwin-accent);cursor:pointer;display:inline-flex;font-family:inherit;font-size:var(--aitwin-action-font);font-weight:600;gap:calc(6px * var(--aitwin-size));height:var(--aitwin-action-height);justify-content:center;padding:0 calc(10px * var(--aitwin-size))}.aitwin-widget__action svg{flex-shrink:0;height:calc(12px * var(--aitwin-size));width:calc(12px * var(--aitwin-size))}.aitwin-widget__action:hover:not(:disabled){background:#f973161a}.aitwin-widget__action:disabled{cursor:not-allowed;opacity:.45}.aitwin-widget__action--primary{background:var(--aitwin-accent);border-color:transparent;color:#fff}.aitwin-widget__action--primary:hover:not(:disabled){background:var(--aitwin-accent-hover)}.aitwin-widget__action--connecting:disabled{cursor:progress;opacity:1}.aitwin-widget__spinner{display:inline-flex;flex-shrink:0;height:calc(14px * var(--aitwin-size));width:calc(14px * var(--aitwin-size))}.aitwin-widget__spinner svg{animation:aitwin-widget-spin .8s linear infinite;display:block;height:100%;width:100%}.aitwin-widget__spinner--accent{color:var(--aitwin-accent);height:calc(16px * var(--aitwin-size));width:calc(16px * var(--aitwin-size))}.aitwin-widget__spinner--on-accent{color:#fff}@keyframes aitwin-widget-spin{to{transform:rotate(360deg)}}.aitwin-widget__connecting{align-items:center;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);background:#ffffffe0;border-radius:999px;bottom:calc(14px * var(--aitwin-size));box-shadow:0 4px 16px #0000001f;color:#3f3f46;display:inline-flex;font-size:calc(12px * var(--aitwin-size));font-weight:600;gap:calc(8px * var(--aitwin-size));left:50%;line-height:1;padding:calc(8px * var(--aitwin-size)) calc(14px * var(--aitwin-size));pointer-events:none;position:absolute;transform:translate(-50%);z-index:3}.aitwin-widget__face-loading{background:transparent;inset:0;overflow:hidden;pointer-events:none;position:absolute;z-index:4}.aitwin-widget__face-loading-content{align-items:center;display:flex;flex-direction:column;gap:calc(12px * var(--aitwin-size));inset:0;justify-content:center;padding:calc(24px * var(--aitwin-size));position:absolute;z-index:1}.aitwin-widget__logo{color:#fff;display:block;flex-shrink:0;height:calc(64px * var(--aitwin-size));margin-bottom:calc(4px * var(--aitwin-size));width:calc(64px * var(--aitwin-size))}.aitwin-widget__logo-draw{stroke-dasharray:1;stroke-dashoffset:1;animation:aitwin-widget-logo-draw 2.6s ease-in-out forwards}.aitwin-widget__logo-draw--loop{animation:aitwin-widget-logo-draw-loop 2.6s ease-in-out infinite}@keyframes aitwin-widget-logo-draw{to{stroke-dashoffset:0}}@keyframes aitwin-widget-logo-draw-loop{0%{stroke-dashoffset:1}45%{stroke-dashoffset:0}55%{stroke-dashoffset:0}to{stroke-dashoffset:-1}}@media(prefers-reduced-motion:reduce){.aitwin-widget__logo-draw,.aitwin-widget__logo-draw--loop{animation:none;stroke-dashoffset:0}}.aitwin-widget__face-loading-bar-wrap{max-width:calc(220px * var(--aitwin-size));width:100%}.aitwin-widget__face-loading-track{background:#fff3;border-radius:999px;height:calc(4px * var(--aitwin-size));overflow:hidden;width:100%}.aitwin-widget__face-loading-fill{background:var(--aitwin-accent);border-radius:999px;height:100%;transition:width .3s ease-out}.aitwin-widget__face-loading-pct{color:#ffffffbf;font-size:calc(12px * var(--aitwin-size));margin:calc(8px * var(--aitwin-size)) 0 0;text-align:center}.aitwin-widget__composer{display:grid;gap:var(--aitwin-action-gap);grid-template-columns:1fr auto;width:100%}.aitwin-widget__composer-input{background:#ffffff0a;border:1px solid var(--aitwin-border);border-radius:var(--aitwin-action-radius);color:var(--aitwin-text);font-family:inherit;font-size:calc(12px * var(--aitwin-size));min-width:0;outline:none;padding:calc(8px * var(--aitwin-size)) calc(10px * var(--aitwin-size))}.aitwin-widget__composer-input:focus{border-color:#f973168c}.aitwin-widget__composer-send{background:var(--aitwin-accent);border:none;border-radius:var(--aitwin-action-radius);color:#fff;cursor:pointer;font-family:inherit;font-size:calc(12px * var(--aitwin-size));font-weight:600;padding:0 calc(12px * var(--aitwin-size))}.aitwin-widget__composer-send:disabled{cursor:not-allowed;opacity:.45}.aitwin-widget__controls-error{color:#fecaca;font-size:calc(11px * var(--aitwin-size));margin:0}.aitwin-widget--float{bottom:20px;filter:drop-shadow(0 12px 32px rgba(0,0,0,.45));height:fit-content;margin:0;max-width:calc(100vw - 40px);position:fixed;right:20px;width:fit-content;z-index:2147483000}",ii="data-aitwin-widget-style";function ss(){if(typeof document>"u")return;const e=ac.trim();if(!e){console.warn("[AiTwinWidget] styles.css?inline resolved empty — chrome will be unstyled");return}const t=document.querySelector(`style[${ii}]`);if(t){if((t.textContent??"").trim().length>0)return;t.textContent=e;return}const n=document.createElement("style");n.setAttribute(ii,"1"),n.textContent=e,(document.head??document.documentElement).appendChild(n)}typeof document<"u"&&ss();const oc=h.forwardRef(function(t,n){ss();const r=h.useRef(null);h.useImperativeHandle(n,()=>({speakText:async(s,o)=>{const a=r.current?.getTwin();if(!a)throw new Error("AiTwinWidget: twin is not mounted");return a.speakText(s,o)},speakWithReply:async(s,o)=>{const a=r.current?.getTwin();if(!a)throw new Error("AiTwinWidget: twin is not mounted");return a.speakWithReply(s,o)},connect:async s=>{const o=r.current?.getTwin();if(!o)throw new Error("AiTwinWidget: twin is not mounted");return o.connect(s)},disconnect:async()=>{const s=r.current?.getTwin();if(s)return s.disconnect()},stop:()=>{r.current?.getTwin()?.stop()},isReady:()=>!!r.current?.getTwin()?.isReady(),isConnected:()=>!!r.current?.getTwin()?.isConnected(),getTwin:()=>r.current?.getTwin()??null}),[]);const i=!!t.float;return D.jsx("div",{className:i?"aitwin-widget aitwin-widget--float":"aitwin-widget",children:D.jsx(sc,{ref:r,options:t})})}),cc=new Set([".png",".jpg",".jpeg",".webp"]);function as(e=".png"){const t=e.toLowerCase();return cc.has(t)?`source${t}`:"source.png"}function lc(e,t=Gn,n=".png"){const r=e.trim();if(!r)throw new Error("faceId is required");return`${t.replace(/\/$/,"")}/${r}/${as(n)}`}async function uc(e){try{const t=await e.json();if(typeof t.detail=="string"&&t.detail.trim())return t.detail;if(typeof t.error=="string"&&t.error.trim())return t.error}catch{}return`avatarReply failed (${e.status})`}async function dc(e){const t=e.message.trim();if(!t)throw new Error("Message is required");const n=e.authToken.trim();if(!n)throw new Error("Auth token is required");const r=(e.apiBase?.trim()||Pt).replace(/\/$/,""),i=await fetch(`${r}/avatarReply`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n}`,Accept:"text/event-stream"},body:JSON.stringify({message:t,history:e.history??[],brainId:e.brainId?.trim()||e.personaId?.trim()||"",tenant:"aiTwin"})});if(!i.ok)throw new Error(await uc(i));if(!i.body)throw new Error("avatarReply response body is empty");const s=i.body.getReader(),o=new TextDecoder;let a="",u="",d="",l="";for(;;){const{done:c,value:m}=await s.read();if(c)break;a+=o.decode(m,{stream:!0});const p=a.split(`
|
|
48
|
+
`);a=p.pop()||"";for(const T of p){if(T.startsWith("event: ")){l=T.slice(7).trim();continue}if(!T.startsWith("data: "))continue;const f=T.slice(6).trim();if(!f)continue;let I;try{I=JSON.parse(f)}catch{continue}if(l==="spokenText")u=I.text||"",e.onSpokenText?.(u);else if(l==="displayText")d=I.text||"";else if(l==="error")throw new Error(I.error||"avatarReply stream error")}}if(!u.trim()||!d.trim())throw new Error("avatarReply stream missing displayText or spokenText");return{displayText:d.trim(),spokenText:u.trim()}}exports.AI_TWIN_THUMBNAIL_FILENAME=Zn;exports.AiTwin=rs;exports.AiTwinNotFoundError=tn;exports.AiTwinWidget=oc;exports.CONSONANT_SKIP_GROUP=ki;exports.DEFAULT_TTS_ENGINE_ID=mt;exports.DEFAULT_TTS_LANGUAGE=Vs;exports.EMOTION_TO_EYEBROW=qi;exports.EXPRESSION_ATLAS_EMOTIONS=Da;exports.MIC_SAMPLE_RATE=ar;exports.OCULUS_VISEME_IDS=_i;exports.PLAYBACK_SAMPLE_RATE=or;exports.SPEAKING_RATE_MAX=wn;exports.SPEAKING_RATE_MIN=pn;exports.TTS_ENGINE_CARTESIA=nt;exports.TTS_ENGINE_GOOGLE=Yn;exports.TTS_ENGINE_INWORLD=ln;exports.TTS_ENGINE_VISEMETTS=rt;exports.TTS_LANGUAGE_CATALOG=ht;exports.TTS_LANGUAGE_CODES=wi;exports.VISEME_IDS=ba;exports.VISEME_SKIP_GAP_MS=Vn;exports.VISEME_TEST_CARTESIA_VOICE_ID=sr;exports.VISEME_TEST_SPEAKING_RATE=Vt;exports.VISEME_TEST_VISEMETTS_VOICE_ID=un;exports.VISEME_TEST_VOICE_ID=ir;exports.VISEME_VTIME_GRID_MS=er;exports.VOWEL_SKIP_GROUP=Ti;exports.aiTwinSourceFilename=as;exports.buildPlaybackTransitions=Pi;exports.buildPlaybackVisemeSeries=hn;exports.buildRawVisemeTransitions=Ri;exports.buildVoiceWebSocketUrl=Ui;exports.compactSkippableVisemes=nr;exports.createAvatarTtsLipsyncController=Wn;exports.createRealtimeVoiceLipsyncController=Vi;exports.emotionToEyebrow=gt;exports.faceAssetUrls=Un;exports.fetchAiTwin=li;exports.fetchAvatarReply=dc;exports.fetchDevAuthToken=en;exports.getAiTwinSourceUrl=lc;exports.getAiTwinThumbnailUrl=ui;exports.isTtsLanguageCode=yi;exports.isTtsLanguageSupported=zs;exports.listSkippedVisemeEntries=gn;exports.listSkippedVisemes=Zs;exports.normalizeOculusViseme=fn;exports.normalizeStreamEmotion=et;exports.normalizeTtsLanguage=dn;exports.parsePackedVoiceId=ai;exports.parseTwinBrainUrl=ks;exports.resolveDirectFaceId=di;exports.resolveTwinBrainId=Xn;exports.resolveTwinBrainUrl=Jn;exports.resolveVisemeAtTime=Ut;exports.resolveVisemeFromPlaybackSeries=Ii;exports.resolveWordAtTime=ca;exports.setActiveTwinAssets=fi;exports.snapVisemeQueueToGrid=tr;exports.snapVisemeVtimeToGrid=Ei;exports.splitVoiceIdSpec=tt;exports.ttsLanguagesForEngine=Ws;
|