@streamoji/aitwin 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/aitwin.js ADDED
@@ -0,0 +1,1779 @@
1
+ import { jsxs as ft, jsx as We } from "react/jsx-runtime";
2
+ import { forwardRef as dt, useRef as M, useState as _e, useCallback as ee, useEffect as le, useMemo as ht, useImperativeHandle as mt } from "react";
3
+ const $e = "https://ai.streamoji.com", tt = "https://pub-607ad1fc22e2400eb57d17240aab857c.r2.dev/custom-faces", _t = "https://us-central1-streamoji-265f4.cloudfunctions.net/getAiTwin";
4
+ class Pe extends Error {
5
+ constructor(e = "AI twin not found") {
6
+ super(e), this.name = "AiTwinNotFoundError";
7
+ }
8
+ }
9
+ async function wt(t, e = _t) {
10
+ const n = new URL(e);
11
+ n.searchParams.set("id", t);
12
+ const r = await fetch(n.toString());
13
+ if (r.status === 404)
14
+ throw new Pe();
15
+ if (!r.ok)
16
+ throw new Error(`getAiTwin failed (${r.status})`);
17
+ const i = await r.json();
18
+ if (!i.success)
19
+ throw new Pe(i.error ?? "AI twin not found");
20
+ return i.data;
21
+ }
22
+ const pt = "https://us-central1-streamoji-265f4.cloudfunctions.net/getAuthToken", gt = "client_6TNvp3SCs4Og0a1ijm9TommXLql1", yt = "kk8Fq8EmexzP10jMIEwY3R44M5RKUEm1", kt = "6TNvp3SCs4Og0a1ijm9TommXLql1", Et = "Swaraj Mali";
23
+ async function Ke() {
24
+ const t = await fetch(pt, {
25
+ method: "POST",
26
+ headers: {
27
+ "Content-Type": "application/json",
28
+ "Client-Id": gt,
29
+ "Client-Secret": yt
30
+ },
31
+ body: JSON.stringify({
32
+ userId: kt,
33
+ userName: Et
34
+ })
35
+ });
36
+ if (!t.ok)
37
+ throw new Error(`getAuthToken failed (${t.status})`);
38
+ const e = await t.json(), n = e.authToken ?? e.token ?? "";
39
+ if (!n.trim())
40
+ throw new Error("getAuthToken returned no token");
41
+ return n;
42
+ }
43
+ async function St(t, e = $e) {
44
+ const n = await fetch(`${e.replace(/\/$/, "")}/api/session-value`, {
45
+ headers: { Authorization: `Bearer ${t}` }
46
+ });
47
+ if (!n.ok)
48
+ throw new Error(`/api/session-value failed (${n.status})`);
49
+ const r = await n.json();
50
+ if (!r.value) throw new Error("Session value response missing value");
51
+ return r;
52
+ }
53
+ function vt(t) {
54
+ const e = t.trim();
55
+ if (e.length % 2 !== 0) throw new Error("Invalid hex key");
56
+ const n = new Uint8Array(e.length / 2);
57
+ for (let r = 0; r < e.length; r += 2)
58
+ n[r / 2] = Number.parseInt(e.slice(r, r + 2), 16);
59
+ return n;
60
+ }
61
+ function ve(t) {
62
+ return Uint8Array.from(t);
63
+ }
64
+ function At(t, e) {
65
+ const n = new Uint8Array(t.length + e.length);
66
+ return n.set(t, 0), n.set(e, t.length), n;
67
+ }
68
+ async function Tt(t, e) {
69
+ if (!e) throw new Error("Asset key is required for encrypted assets");
70
+ if (t.byteLength < 28)
71
+ throw new Error("Encrypted payload too small");
72
+ const n = new Uint8Array(t), r = ve(n.subarray(0, 12)), i = ve(n.subarray(12, 28)), a = ve(n.subarray(28)), s = ve(At(a, i)), c = await crypto.subtle.importKey(
73
+ "raw",
74
+ vt(e),
75
+ { name: "AES-GCM" },
76
+ !1,
77
+ ["decrypt"]
78
+ );
79
+ return crypto.subtle.decrypt(
80
+ { name: "AES-GCM", iv: r, tagLength: 128 },
81
+ c,
82
+ s
83
+ );
84
+ }
85
+ let Ce = null;
86
+ const Fe = /* @__PURE__ */ new Set();
87
+ function It(t, e = tt) {
88
+ const n = `${e.replace(/\/$/, "")}/${t}`;
89
+ return { twinBase: n, binBase: n, encrypted: !0 };
90
+ }
91
+ function Rt(t) {
92
+ Ce = t;
93
+ for (const e of Fe) e();
94
+ }
95
+ function re() {
96
+ if (!Ce)
97
+ throw new Error("Twin assets not configured; call setActiveTwinAssets first");
98
+ return Ce;
99
+ }
100
+ function bt(t) {
101
+ return Fe.add(t), () => Fe.delete(t);
102
+ }
103
+ function xt() {
104
+ return `${re().twinBase}/sil.png`;
105
+ }
106
+ function Dt() {
107
+ return `${re().twinBase}/idle.mp4`;
108
+ }
109
+ function Pt() {
110
+ const { encrypted: t, binBase: e, twinBase: n } = re();
111
+ return t ? e : n;
112
+ }
113
+ function ne() {
114
+ return re().encrypted;
115
+ }
116
+ function nt() {
117
+ const { binBase: t, twinBase: e, encrypted: n } = re();
118
+ return n ? `${t}/atlas.bin` : `${e}/atlas.json`;
119
+ }
120
+ function Ct() {
121
+ const { binBase: t, twinBase: e, encrypted: n } = re();
122
+ return n ? `${t}/expression_atlas.bin` : `${e}/expression_atlas.json`;
123
+ }
124
+ function Ft(t) {
125
+ const e = t.split(/\r?\n/);
126
+ let n = "", r = "";
127
+ for (const a of e)
128
+ a.startsWith("event:") ? n = a.slice(6).trim() : a.startsWith("data:") && (r = a.slice(5).trim());
129
+ if (!n) return null;
130
+ let i = {};
131
+ if (r)
132
+ try {
133
+ i = JSON.parse(r);
134
+ } catch {
135
+ i = { raw: r };
136
+ }
137
+ return { event: n, data: i };
138
+ }
139
+ const Mt = [
140
+ "aa",
141
+ "CH",
142
+ "DD",
143
+ "E",
144
+ "FF",
145
+ "I",
146
+ "O",
147
+ "PP",
148
+ "RR",
149
+ "SS",
150
+ "TH",
151
+ "U",
152
+ "kk",
153
+ "nn",
154
+ "sil"
155
+ ], Ot = new Map(
156
+ Mt.map((t) => [t.toLowerCase(), t])
157
+ );
158
+ function Ut(t) {
159
+ const e = (t ?? "").trim();
160
+ return e ? Ot.get(e.toLowerCase()) ?? "sil" : "sil";
161
+ }
162
+ const Lt = {
163
+ aei: ["aa", "E", "I"],
164
+ o: ["O", "U"],
165
+ ee: ["I"],
166
+ bmp: ["PP"],
167
+ fv: ["FF"],
168
+ l: ["nn"],
169
+ r: ["RR"],
170
+ th: ["TH"],
171
+ qw: ["U", "O"],
172
+ cdgknstxyz: ["DD", "SS", "kk", "CH"]
173
+ };
174
+ function $t(t) {
175
+ if (!t) return ["sil"];
176
+ const e = t.toLowerCase();
177
+ return Lt[e] ?? ["sil"];
178
+ }
179
+ function Bt(t, e) {
180
+ const n = t.word.length;
181
+ if (n <= 0) return 0;
182
+ const r = t.wduration;
183
+ if (r <= 0) return 0;
184
+ const i = Math.max(0, Math.min(1, (e - t.wtime) / r));
185
+ return Math.min(n - 1, Math.floor(i * n));
186
+ }
187
+ function xe(t, e) {
188
+ const n = Math.max(0, Math.min(t.length - 1, e));
189
+ return t[n] ?? "";
190
+ }
191
+ function Vt(t, e) {
192
+ const n = t.toLowerCase(), r = xe(n, e), i = n.slice(Math.max(0, e - 1), e + 2);
193
+ return r === "i" || r === "y" ? "I" : i.includes("ee") || r === "e" || n.includes("ea") ? "E" : "aa";
194
+ }
195
+ function Ht(t, e) {
196
+ const n = t.toLowerCase(), r = n.slice(
197
+ Math.max(0, e - 1),
198
+ Math.min(n.length, e + 3)
199
+ );
200
+ if (/oo|ou|uw/.test(r)) return "U";
201
+ const i = xe(n, e);
202
+ return i === "u" || i === "w" ? "U" : "O";
203
+ }
204
+ function Nt(t, e) {
205
+ const n = t.toLowerCase(), r = n.slice(Math.max(0, e - 2), e + 1);
206
+ if (/qu/.test(r)) return "U";
207
+ const i = n.slice(
208
+ Math.max(0, e - 1),
209
+ Math.min(n.length, e + 3)
210
+ );
211
+ return /wo|wh/.test(i) || xe(n, e) === "o" ? "O" : "U";
212
+ }
213
+ const Ae = {
214
+ d: "DD",
215
+ t: "DD",
216
+ n: "DD",
217
+ s: "SS",
218
+ z: "SS",
219
+ k: "kk",
220
+ g: "kk",
221
+ c: "CH",
222
+ x: "CH",
223
+ j: "CH"
224
+ };
225
+ function Wt(t, e) {
226
+ const n = t.toLowerCase(), r = xe(n, e);
227
+ if (Ae[r]) return Ae[r];
228
+ for (let i = 0; i < n.length; i++) {
229
+ const a = n[i];
230
+ if (Ae[a]) return Ae[a];
231
+ }
232
+ return "DD";
233
+ }
234
+ function Kt(t, e, n) {
235
+ const r = $t(t);
236
+ if (r.length === 1) return r[0];
237
+ const i = e.trim();
238
+ if (!i) return r[0];
239
+ const a = (t ?? "").toLowerCase(), s = Math.max(0, n);
240
+ switch (a) {
241
+ case "aei":
242
+ return Vt(i, s);
243
+ case "o":
244
+ return Ht(i, s);
245
+ case "qw":
246
+ return Nt(i, s);
247
+ case "cdgknstxyz":
248
+ return Wt(i, s);
249
+ default:
250
+ return r[0];
251
+ }
252
+ }
253
+ function qt(t) {
254
+ let e = t.trim();
255
+ const n = e.indexOf(",");
256
+ e.startsWith("data:") && n >= 0 && (e = e.slice(n + 1)), e = e.replace(/\s+/g, "").replace(/-/g, "+").replace(/_/g, "/");
257
+ const r = e.length % 4;
258
+ return r !== 0 && (e += "=".repeat(4 - r)), e;
259
+ }
260
+ const jt = 24e3;
261
+ function zt(t) {
262
+ return t.length >= 4 && t[0] === 82 && t[1] === 73 && t[2] === 70 && t[3] === 70;
263
+ }
264
+ function qe(t, e, n = jt) {
265
+ const r = e.byteOffset % 2 === 0 ? e : e.slice(), i = new Int16Array(
266
+ r.buffer,
267
+ r.byteOffset,
268
+ r.byteLength / 2
269
+ ), a = new Float32Array(i.length);
270
+ for (let c = 0; c < i.length; c++)
271
+ a[c] = i[c] >= 32768 ? -(65536 - i[c]) / 32768 : i[c] / 32767;
272
+ const s = t.createBuffer(1, a.length, n);
273
+ return s.copyToChannel(a, 0), s;
274
+ }
275
+ function Gt(t) {
276
+ const e = qt(t), n = window.atob(e), r = new Uint8Array(n.length);
277
+ for (let i = 0; i < n.length; i++)
278
+ r[i] = n.charCodeAt(i);
279
+ return r;
280
+ }
281
+ async function Qt(t, e) {
282
+ const n = Gt(e);
283
+ if (zt(n)) {
284
+ const r = n.buffer.slice(
285
+ n.byteOffset,
286
+ n.byteOffset + n.byteLength
287
+ );
288
+ return t.decodeAudioData(r);
289
+ }
290
+ if (n.length >= 2 && n.length % 2 === 0)
291
+ return qe(t, n);
292
+ try {
293
+ const r = n.buffer.slice(
294
+ n.byteOffset,
295
+ n.byteOffset + n.byteLength
296
+ );
297
+ return await t.decodeAudioData(r);
298
+ } catch {
299
+ return qe(t, n);
300
+ }
301
+ }
302
+ function Jt(t, e) {
303
+ let n = null;
304
+ for (const r of t)
305
+ e < r.vtime || e >= r.vtime + r.vduration || (!n || r.vtime >= n.vtime) && (n = r);
306
+ return n ? n.viseme : "sil";
307
+ }
308
+ function Xt(t, e) {
309
+ for (const n of t)
310
+ if (e >= n.wtime && e < n.wtime + n.wduration)
311
+ return n;
312
+ return null;
313
+ }
314
+ function je(t) {
315
+ let e = 0;
316
+ for (const n of t)
317
+ e = Math.max(e, n.vtime + n.vduration);
318
+ return e;
319
+ }
320
+ const Yt = 0.5, Zt = 1.5, rt = "Olivia", en = "f786b574-daa5-4673-aa0c-cbe3e8534c02", it = 0.85;
321
+ function tn(t, e = $e) {
322
+ const n = `${e.replace(/\/$/, "")}/avatar_ttsWithPoses`, r = [], i = [], a = [];
323
+ let s = "neutral";
324
+ const c = [], u = [];
325
+ let p = null, _ = !1, o = !1, f = !1, d = !1, k = 0, x = 0, F = 0, Z = 0, H = null, h = 1, g = "", P = "google", O = "google", C = !1;
326
+ const K = /* @__PURE__ */ new Set(), ie = () => {
327
+ for (const m of u)
328
+ m.playbackRate.value = h;
329
+ }, D = () => K.forEach((m) => m()), N = () => {
330
+ H != null && (clearTimeout(H), H = null);
331
+ }, se = () => {
332
+ for (const m of u)
333
+ try {
334
+ m.stop();
335
+ } catch {
336
+ }
337
+ u.length = 0;
338
+ }, fe = () => {
339
+ C = !0, N(), se(), c.length = 0, _ = !1, o = !1, f = !1, d = !1, r.length = 0, i.length = 0, a.length = 0, s = "neutral", F = 0, Z = 0, x = 0, t("idle"), D();
340
+ }, oe = () => {
341
+ !d || _ || u.length > 0 || c.length > 0 || (o = !1, N(), t("done"), D());
342
+ }, de = () => {
343
+ const m = je(r);
344
+ if (m <= 0) {
345
+ t("done"), D();
346
+ return;
347
+ }
348
+ o = !0, k = performance.now(), t("speaking"), D(), N();
349
+ const R = h > 0 ? m / h : m;
350
+ H = setTimeout(() => {
351
+ C || (o = !1, H = null, t("done"), D());
352
+ }, R);
353
+ }, z = (m, R, A) => {
354
+ m.length !== 0 && (A && (F = R), m.forEach((T) => {
355
+ const I = String(T.word ?? "").trim();
356
+ if (!I) return;
357
+ const q = Math.round((T.start ?? 0) * 1e3), B = Math.round((T.duration ?? 0) * 1e3);
358
+ i.push({
359
+ word: I,
360
+ wtime: F + q,
361
+ wduration: B,
362
+ queueIndex: i.length
363
+ });
364
+ }));
365
+ }, ke = (m, R, A, T) => {
366
+ m.length !== 0 && (A && (F = R), m.forEach((b) => {
367
+ const I = String(b.symbol ?? "").trim();
368
+ if (!I) return;
369
+ const q = Math.round((b.start ?? 0) * 1e3), B = Math.max(
370
+ 1,
371
+ Math.round((b.duration ?? 0) * 1e3)
372
+ ), v = F + q;
373
+ let G;
374
+ if (T === "google" || T === "cartesia")
375
+ G = Ut(I);
376
+ else {
377
+ const S = Xt(i, v), V = S ? Bt(S, v) : 0;
378
+ G = Kt(
379
+ I,
380
+ S?.word ?? "",
381
+ V
382
+ );
383
+ }
384
+ r.push({
385
+ viseme: G,
386
+ weight: 1,
387
+ vtime: v,
388
+ vduration: B
389
+ });
390
+ }), D());
391
+ }, he = (m, R, A, T, b) => {
392
+ z(R, A, T), ke(m, A, T, b);
393
+ }, ae = async (m, R, A, T) => {
394
+ if (C || !m?.trim()) {
395
+ (R.length > 0 || A.length > 0) && !f && he(
396
+ R,
397
+ A,
398
+ F,
399
+ T,
400
+ O
401
+ );
402
+ return;
403
+ }
404
+ if (_) {
405
+ c.push({
406
+ audio: m,
407
+ visemes: R,
408
+ words: A,
409
+ isNewSegment: T
410
+ });
411
+ return;
412
+ }
413
+ _ = !0;
414
+ try {
415
+ const b = window.AudioContext || window.webkitAudioContext, I = p ?? new b();
416
+ I.state === "suspended" && await I.resume(), p = I;
417
+ const q = await Qt(I, m);
418
+ f = !0;
419
+ const B = I.currentTime;
420
+ let v = Z;
421
+ const G = !o;
422
+ v < B && (v = B + 0.1), Z = v + q.duration;
423
+ const S = I.createBufferSource();
424
+ if (S.buffer = q, S.playbackRate.value = h, S.connect(I.destination), u.push(S), C) {
425
+ u.pop();
426
+ return;
427
+ }
428
+ if (G) {
429
+ o = !0, t("speaking"), x = v, F = 0, r.length = 0, i.length = 0;
430
+ const $ = (v - B) * 1e3;
431
+ k = performance.now() + $;
432
+ }
433
+ S.onended = () => {
434
+ const $ = u.indexOf(S);
435
+ $ >= 0 && u.splice($, 1), oe(), D();
436
+ }, S.start(v);
437
+ const V = (v - x) * 1e3;
438
+ he(
439
+ R,
440
+ A,
441
+ V,
442
+ T,
443
+ O
444
+ );
445
+ } catch (b) {
446
+ console.error("[avatarTtsLipsync] audio chunk failed:", b);
447
+ } finally {
448
+ _ = !1;
449
+ const b = c.shift();
450
+ b ? await ae(
451
+ b.audio,
452
+ b.visemes,
453
+ b.words,
454
+ b.isNewSegment
455
+ ) : oe();
456
+ }
457
+ }, Ee = () => {
458
+ if (d = !0, !f && r.length > 0) {
459
+ de();
460
+ return;
461
+ }
462
+ oe();
463
+ };
464
+ return {
465
+ setDeveloperToken: (m) => {
466
+ g = m;
467
+ },
468
+ setTtsProvider: (m) => {
469
+ P = m;
470
+ },
471
+ getTtsProvider: () => P,
472
+ speak: async (m, R) => {
473
+ fe(), C = !1, t("loading");
474
+ const A = g.trim();
475
+ if (!A)
476
+ throw new Error("Developer token required for avatar_ttsWithPoses");
477
+ const T = R?.tts ?? P;
478
+ O = T;
479
+ const b = R?.voiceId ?? rt, I = R?.speakingRate ?? it, q = Math.max(
480
+ Yt,
481
+ Math.min(Zt, I)
482
+ ), B = {
483
+ user_query: m,
484
+ tts: T,
485
+ speakingRate: q
486
+ };
487
+ (T === "inworld" || T === "cartesia") && (B.voice_id = b);
488
+ try {
489
+ const v = await fetch(n, {
490
+ method: "POST",
491
+ headers: {
492
+ "Content-Type": "application/json",
493
+ Authorization: `Bearer ${A}`
494
+ },
495
+ body: JSON.stringify(B)
496
+ });
497
+ if (!v.ok)
498
+ throw new Error(`avatar_ttsWithPoses failed (${v.status})`);
499
+ const G = v.body;
500
+ if (!G) throw new Error("No response body");
501
+ const S = G.getReader(), V = new TextDecoder();
502
+ let $ = "";
503
+ const J = async (ce) => {
504
+ const U = Ft(ce);
505
+ if (U) {
506
+ if (U.event === "audio") {
507
+ const l = U.data.chunk, y = U.data.visemes ?? [], E = U.data.words ?? [], w = U.data.is_new_segment ?? !1;
508
+ if (l)
509
+ await ae(l, y, E, w);
510
+ else if (y.length > 0 || E.length > 0) {
511
+ const L = w && r.length > 0 ? je(r) : F;
512
+ he(y, E, L, w, T);
513
+ }
514
+ } else if (U.event === "metadata") {
515
+ const l = U.data.mood;
516
+ typeof l == "string" && l.trim() && (s = l.trim());
517
+ const y = U.data.sentence_emotions;
518
+ if (Array.isArray(y)) {
519
+ a.length = 0;
520
+ for (const E of y) {
521
+ if (!E || typeof E != "object") continue;
522
+ const w = E;
523
+ a.push({
524
+ sentence_index: Number(w.sentence_index ?? 0),
525
+ text: String(w.text ?? ""),
526
+ sentiment: typeof w.sentiment == "string" ? w.sentiment : void 0,
527
+ emotion: String(w.emotion ?? s),
528
+ start_word: Number(w.start_word ?? 0),
529
+ end_word: Number(w.end_word ?? 0)
530
+ });
531
+ }
532
+ }
533
+ D();
534
+ } else if (U.event === "error")
535
+ throw new Error(
536
+ String(U.data.message ?? "avatar_ttsWithPoses stream error")
537
+ );
538
+ }
539
+ };
540
+ for (; ; ) {
541
+ const { done: ce, value: U } = await S.read();
542
+ U && ($ += V.decode(U, { stream: !0 }));
543
+ const l = $.split(`
544
+
545
+ `);
546
+ $ = l.pop() ?? "";
547
+ for (const y of l) await J(y);
548
+ if (ce) {
549
+ $.trim() && await J($.trim()), C || Ee();
550
+ break;
551
+ }
552
+ }
553
+ } catch (v) {
554
+ throw console.error("[avatarTtsLipsync]", v), fe(), t("error"), v;
555
+ }
556
+ },
557
+ stop: fe,
558
+ getVisemeQueue: () => r,
559
+ getWordQueue: () => i,
560
+ getSentenceEmotions: () => a,
561
+ getStreamMood: () => s,
562
+ getPlaybackElapsedMs: () => o ? f && p && x > 0 ? Math.max(
563
+ 0,
564
+ (p.currentTime - x) * 1e3
565
+ ) : Math.max(0, (performance.now() - k) * h) : 0,
566
+ isSpeaking: () => o,
567
+ setPlaybackSpeed: (m) => {
568
+ h = Math.max(0.1, Math.min(1, m)), ie();
569
+ },
570
+ getPlaybackSpeed: () => h,
571
+ subscribe: (m) => (K.add(m), () => K.delete(m))
572
+ };
573
+ }
574
+ function nn(t, e, n) {
575
+ return {
576
+ width: t.crop?.source_width ?? e,
577
+ height: t.crop?.source_height ?? n
578
+ };
579
+ }
580
+ function rn(t, e) {
581
+ const n = t.crop;
582
+ return {
583
+ x: e?.source_x ?? n?.x ?? 0,
584
+ y: e?.source_y ?? n?.y ?? 0,
585
+ width: e?.source_w ?? n?.width ?? t.frame_width ?? 0,
586
+ height: e?.source_h ?? n?.height ?? t.frame_height ?? 0
587
+ };
588
+ }
589
+ function sn(t) {
590
+ return t ? (t.w ?? 0) > 0 && (t.h ?? 0) > 0 : !1;
591
+ }
592
+ async function st(t, e) {
593
+ const n = await fetch(t);
594
+ if (!n.ok) throw new Error(`Failed to load encrypted asset: ${t}`);
595
+ const r = await n.arrayBuffer();
596
+ return Tt(r, e);
597
+ }
598
+ async function ot(t, e) {
599
+ if (!e) throw new Error("Missing asset key for encrypted JSON");
600
+ const n = await st(t, e), r = new TextDecoder().decode(n);
601
+ return JSON.parse(r);
602
+ }
603
+ async function on(t) {
604
+ const e = new Blob([t], { type: "image/webp" }), n = URL.createObjectURL(e);
605
+ return new Promise((r, i) => {
606
+ const a = new Image();
607
+ a.decoding = "async", a.onload = () => {
608
+ URL.revokeObjectURL(n), r(a);
609
+ }, a.onerror = () => {
610
+ URL.revokeObjectURL(n), i(new Error("Failed to decode decrypted image"));
611
+ }, a.src = n;
612
+ });
613
+ }
614
+ function at(t, e) {
615
+ return `${t}/${e}_minus_sil.png`;
616
+ }
617
+ const Be = 15, er = [
618
+ "aa",
619
+ "E",
620
+ "I",
621
+ "O",
622
+ "U",
623
+ "PP",
624
+ "FF",
625
+ "DD",
626
+ "SS",
627
+ "TH",
628
+ "CH",
629
+ "RR",
630
+ "kk",
631
+ "nn"
632
+ ], Me = [
633
+ "t01_0.17",
634
+ "t02_0.33",
635
+ "t03_0.50",
636
+ "t04_0.67",
637
+ "t05_0.83"
638
+ ], an = Me.length, ze = /* @__PURE__ */ new Set([
639
+ "aa__kk",
640
+ "aa__nn",
641
+ "aa__sil",
642
+ "CH__aa",
643
+ "CH__DD",
644
+ "CH__E",
645
+ "CH__FF",
646
+ "CH__I",
647
+ "CH__kk",
648
+ "CH__nn",
649
+ "CH__O",
650
+ "CH__PP",
651
+ "CH__RR",
652
+ "CH__sil",
653
+ "CH__SS",
654
+ "CH__TH",
655
+ "CH__U",
656
+ "DD__aa",
657
+ "DD__E",
658
+ "DD__FF",
659
+ "DD__I",
660
+ "DD__kk",
661
+ "DD__nn",
662
+ "DD__O",
663
+ "DD__PP",
664
+ "DD__RR",
665
+ "DD__sil",
666
+ "DD__SS",
667
+ "DD__TH",
668
+ "DD__U",
669
+ "E__aa",
670
+ "E__FF",
671
+ "E__I",
672
+ "E__kk",
673
+ "E__nn",
674
+ "E__O",
675
+ "E__PP",
676
+ "E__RR",
677
+ "E__sil",
678
+ "E__SS",
679
+ "E__TH",
680
+ "E__U",
681
+ "FF__aa",
682
+ "FF__I",
683
+ "FF__kk",
684
+ "FF__nn",
685
+ "FF__O",
686
+ "FF__PP",
687
+ "FF__RR",
688
+ "FF__sil",
689
+ "FF__SS",
690
+ "FF__TH",
691
+ "FF__U",
692
+ "I__aa",
693
+ "I__kk",
694
+ "I__nn",
695
+ "I__O",
696
+ "I__PP",
697
+ "I__RR",
698
+ "I__sil",
699
+ "I__SS",
700
+ "I__TH",
701
+ "I__U",
702
+ "kk__nn",
703
+ "kk__sil",
704
+ "nn__sil",
705
+ "O__aa",
706
+ "O__kk",
707
+ "O__nn",
708
+ "O__PP",
709
+ "O__RR",
710
+ "O__sil",
711
+ "O__SS",
712
+ "O__TH",
713
+ "O__U",
714
+ "PP__aa",
715
+ "PP__kk",
716
+ "PP__nn",
717
+ "PP__RR",
718
+ "PP__sil",
719
+ "PP__SS",
720
+ "PP__TH",
721
+ "PP__U",
722
+ "RR__aa",
723
+ "RR__kk",
724
+ "RR__nn",
725
+ "RR__sil",
726
+ "RR__SS",
727
+ "RR__TH",
728
+ "RR__U",
729
+ "SS__aa",
730
+ "SS__kk",
731
+ "SS__nn",
732
+ "SS__sil",
733
+ "SS__TH",
734
+ "SS__U",
735
+ "TH__aa",
736
+ "TH__kk",
737
+ "TH__nn",
738
+ "TH__sil",
739
+ "TH__U",
740
+ "U__aa",
741
+ "U__kk",
742
+ "U__nn",
743
+ "U__sil"
744
+ ]);
745
+ function Ge(t, e) {
746
+ return `${t}__${e}`;
747
+ }
748
+ function Qe(t, e) {
749
+ return `pairs/${t}/${e}_minus_sil.png`;
750
+ }
751
+ function Oe(t) {
752
+ return `${t}_minus_sil.png`;
753
+ }
754
+ function cn(t, e) {
755
+ if (t === e) return [];
756
+ const n = [], r = Ge(t, e);
757
+ if (ze.has(r)) {
758
+ for (const a of Me)
759
+ n.push(Qe(r, a));
760
+ return n;
761
+ }
762
+ const i = Ge(e, t);
763
+ if (ze.has(i)) {
764
+ for (let a = an - 1; a >= 0; a--)
765
+ n.push(Qe(i, Me[a]));
766
+ return n;
767
+ }
768
+ return [];
769
+ }
770
+ function un(t) {
771
+ return t < 16 ? [] : t < 35 ? [2] : t < 51 ? [0, 4] : t < 67 ? [0, 2, 4] : t < 83 ? [0, 1, 2, 3] : [0, 1, 2, 3, 4];
772
+ }
773
+ function ln(t, e) {
774
+ return un(e).map((r) => t[r]).filter((r) => r != null);
775
+ }
776
+ function fn(t, e, n, r) {
777
+ if (r <= 0) return 0;
778
+ const a = Math.max(1, n - e) / r, s = t - e, c = Math.floor(s / a);
779
+ return Math.min(r - 1, Math.max(0, c));
780
+ }
781
+ function dn(t, e) {
782
+ if (!ne()) return `${t}/${e}`;
783
+ const n = e.split("/").pop() ?? e, r = n.includes(".") ? n.slice(0, n.lastIndexOf(".")) : n;
784
+ return `${t}/${r}.bin`;
785
+ }
786
+ async function hn(t) {
787
+ const e = nt(), n = ne() ? await ot(e, t) : await fetch(e).then((r) => {
788
+ if (!r.ok) throw new Error(`Failed to load ${e}`);
789
+ return r.json();
790
+ });
791
+ return {
792
+ width: n.crop?.source_width ?? n.frame_width ?? 842,
793
+ height: n.crop?.source_height ?? n.frame_height ?? 1264
794
+ };
795
+ }
796
+ const mn = [0.32, 0.24, 0.16, 0.08, 0], De = mn.map(
797
+ (t) => `eyes_${t.toFixed(2)}`
798
+ ), _n = [
799
+ "eyes_0.32",
800
+ "eyes_0.16",
801
+ "eyes_0.00"
802
+ ], wn = [
803
+ "eyes_0.32",
804
+ "eyes_0.16",
805
+ "eyes_0.08",
806
+ "eyes_0.00"
807
+ ], pn = {
808
+ fear: "fear",
809
+ afraid: "fear",
810
+ anxiety: "fear",
811
+ anger: "anger",
812
+ angry: "anger",
813
+ mad: "anger",
814
+ sad: "sad",
815
+ sadness: "sad",
816
+ sorrow: "sad",
817
+ neutral: "neutral",
818
+ calm: "neutral",
819
+ love: "love",
820
+ loving: "love",
821
+ affection: "love",
822
+ happy: "happy",
823
+ happiness: "happy",
824
+ joy: "happy",
825
+ joyful: "happy",
826
+ excited: "happy",
827
+ disgust: "disgust",
828
+ disgusted: "disgust"
829
+ };
830
+ function te(t, e = "neutral") {
831
+ const n = String(t ?? "").trim().toLowerCase();
832
+ return n ? pn[n] ?? e : e;
833
+ }
834
+ function W(t) {
835
+ return t === "neutral" ? null : at(t, "eyes_standard");
836
+ }
837
+ function Ue(t, e) {
838
+ return !e || e === "eyes_standard" ? W(t) : t === "neutral" && e === "eyes_standard" ? null : at(t, e);
839
+ }
840
+ function gn(t) {
841
+ if (!t) return "open";
842
+ const e = t.match(/\/(eyes_[^/]+)_minus_sil\.png$/);
843
+ if (!e?.[1]) return "open";
844
+ const n = e[1];
845
+ return De.includes(n) ? n : "open";
846
+ }
847
+ function yn(t) {
848
+ return t === "open" ? -1 : De.indexOf(t);
849
+ }
850
+ function kn(t, e) {
851
+ const n = [];
852
+ for (const r of e)
853
+ n.push(Ue(t, r));
854
+ for (let r = e.length - 2; r >= 0; r--)
855
+ n.push(Ue(t, e[r]));
856
+ return n.push(W(t)), n;
857
+ }
858
+ function En(t, e) {
859
+ if (e === "open") return [W(t)];
860
+ const n = yn(e);
861
+ if (n < 0) return [W(t)];
862
+ const r = [];
863
+ for (let i = n; i >= 0; i--)
864
+ r.push(Ue(t, De[i]));
865
+ return r.push(W(t)), r;
866
+ }
867
+ const Sn = [
868
+ "t01_0.20",
869
+ "t02_0.40",
870
+ "t03_0.60",
871
+ "t04_0.80"
872
+ ];
873
+ function vn(t, e) {
874
+ return `${t}__${e}`;
875
+ }
876
+ function An(t, e, n) {
877
+ return `pairs/${vn(t, e)}/${n}_minus_sil.png`;
878
+ }
879
+ function Tn(t, e) {
880
+ return Sn.map(
881
+ (n) => An(t, e, n)
882
+ );
883
+ }
884
+ function pe(t, e) {
885
+ return t + Math.random() * (e - t);
886
+ }
887
+ function Te() {
888
+ return pe(14, 32);
889
+ }
890
+ function In(t = {}) {
891
+ const {
892
+ initialDelayMs: e = 800 + Math.random() * 1200,
893
+ intervalMinMs: n = 2200,
894
+ intervalMaxMs: r = 5800,
895
+ doubleBlinkChance: i = 0.18,
896
+ doubleBlinkGapMinMs: a = 120,
897
+ doubleBlinkGapMaxMs: s = 220,
898
+ fullBlinkChance: c = 0.75,
899
+ postEmotionChangeDelayMs: u = 380
900
+ } = t;
901
+ let p = "neutral", _ = "neutral", o = {
902
+ kind: "idle",
903
+ nextBlinkAt: performance.now() + e
904
+ }, f = null, d = "__eyes_open__|neutral";
905
+ function k(h, g) {
906
+ f = h, d = `${h ?? "__eyes_open__"}|${g}`;
907
+ }
908
+ function x(h, g) {
909
+ o = {
910
+ kind: "idle",
911
+ nextBlinkAt: h + pe(n, r)
912
+ }, _ = g, k(W(g), g);
913
+ }
914
+ function F(h, g, P) {
915
+ const O = P ? _n : Math.random() < c ? De : wn;
916
+ o = {
917
+ kind: "playing",
918
+ paths: kn(g, O),
919
+ index: 0,
920
+ holdUntil: h + Te(),
921
+ after: "idle",
922
+ blinkEmotion: g
923
+ }, _ = g, k(o.paths[0] ?? null, g);
924
+ }
925
+ function Z(h, g, P) {
926
+ const O = gn(f), C = [];
927
+ if (O !== "open") {
928
+ const K = En(g, O);
929
+ C.push(...K.slice(0, -1));
930
+ }
931
+ C.push(...Tn(g, P)), C.push(W(P)), o = {
932
+ kind: "emotionBlend",
933
+ paths: C,
934
+ index: 0,
935
+ holdUntil: h + Te(),
936
+ thenEmotion: P
937
+ }, k(C[0] ?? null, g);
938
+ }
939
+ function H(h) {
940
+ if (o.kind === "emotionBlend") {
941
+ for (; h >= o.holdUntil && o.index < o.paths.length - 1; )
942
+ o.index += 1, o.holdUntil = h + Te();
943
+ const g = o.paths[o.index] ?? null;
944
+ k(g, o.thenEmotion), h >= o.holdUntil && o.index >= o.paths.length - 1 && (p = o.thenEmotion, _ = o.thenEmotion, k(W(o.thenEmotion), o.thenEmotion), o = {
945
+ kind: "idle",
946
+ nextBlinkAt: h + u
947
+ });
948
+ return;
949
+ }
950
+ if (o.kind === "idle") {
951
+ k(W(_), _), h >= o.nextBlinkAt && F(h, _, !1);
952
+ return;
953
+ }
954
+ if (o.kind === "doublePause") {
955
+ k(W(o.blinkEmotion), o.blinkEmotion), h >= o.resumeAt && F(h, o.blinkEmotion, !0);
956
+ return;
957
+ }
958
+ if (o.kind === "playing") {
959
+ for (; h >= o.holdUntil && o.index < o.paths.length - 1; )
960
+ o.index += 1, o.holdUntil = h + Te();
961
+ if (k(o.paths[o.index] ?? null, o.blinkEmotion), h >= o.holdUntil && o.index >= o.paths.length - 1) {
962
+ if (o.after === "resumeIdle") {
963
+ x(h + u, p);
964
+ return;
965
+ }
966
+ if (o.after === "doublePause") {
967
+ o = {
968
+ kind: "doublePause",
969
+ resumeAt: h + pe(a, s),
970
+ blinkEmotion: o.blinkEmotion
971
+ }, k(W(o.blinkEmotion), o.blinkEmotion);
972
+ return;
973
+ }
974
+ if (o.after === "idle" && Math.random() < i) {
975
+ o = {
976
+ kind: "doublePause",
977
+ resumeAt: h + pe(a, s),
978
+ blinkEmotion: o.blinkEmotion
979
+ }, k(W(o.blinkEmotion), o.blinkEmotion);
980
+ return;
981
+ }
982
+ x(h, o.blinkEmotion);
983
+ }
984
+ }
985
+ }
986
+ return {
987
+ advance: H,
988
+ setTargetEmotion(h) {
989
+ const g = te(h, p);
990
+ if (g === p && o.kind !== "emotionBlend") return;
991
+ const P = performance.now(), O = p;
992
+ if (p = g, o.kind === "playing") {
993
+ Z(P, _, g);
994
+ return;
995
+ }
996
+ if (o.kind === "emotionBlend") {
997
+ o = {
998
+ ...o,
999
+ thenEmotion: g
1000
+ };
1001
+ return;
1002
+ }
1003
+ Z(P, O, g);
1004
+ },
1005
+ getTargetEmotion: () => p,
1006
+ getExpressionPath: () => f,
1007
+ getDrawKey: () => d,
1008
+ reset() {
1009
+ p = "neutral", _ = "neutral", x(
1010
+ performance.now() + pe(n, r),
1011
+ "neutral"
1012
+ );
1013
+ }
1014
+ };
1015
+ }
1016
+ function Rn(t) {
1017
+ const e = document.createElement("video");
1018
+ e.muted = !0, e.playsInline = !0, e.preload = "auto", e.setAttribute("playsinline", ""), e.loop = !0;
1019
+ let n = !1;
1020
+ return {
1021
+ async load() {
1022
+ n || await new Promise((r, i) => {
1023
+ const a = () => {
1024
+ const s = e.duration;
1025
+ if (!Number.isFinite(s) || s <= 0) {
1026
+ i(new Error(`Idle video has invalid duration: ${t}`));
1027
+ return;
1028
+ }
1029
+ n = !0, e.currentTime = 0, r();
1030
+ };
1031
+ e.addEventListener("loadeddata", a, { once: !0 }), e.addEventListener(
1032
+ "error",
1033
+ () => i(new Error(`Failed to load idle video: ${t}`)),
1034
+ { once: !0 }
1035
+ ), e.src = t, e.load();
1036
+ });
1037
+ },
1038
+ isReady() {
1039
+ return n;
1040
+ },
1041
+ getVideo() {
1042
+ return e;
1043
+ },
1044
+ setActive(r) {
1045
+ n && (r ? e.paused && e.play().catch(() => {
1046
+ }) : e.paused || e.pause());
1047
+ },
1048
+ restart() {
1049
+ n && (e.currentTime = 0);
1050
+ }
1051
+ };
1052
+ }
1053
+ function bn(t, e) {
1054
+ for (const n of t)
1055
+ if (e >= n.wtime && e < n.wtime + n.wduration)
1056
+ return n;
1057
+ return null;
1058
+ }
1059
+ function xn(t, e, n, r = "neutral") {
1060
+ const i = te(r);
1061
+ if (e.length === 0) return i;
1062
+ if (n.length === 0)
1063
+ return te(e[0]?.emotion, i);
1064
+ const a = bn(n, t);
1065
+ let s;
1066
+ if (a)
1067
+ s = a.queueIndex ?? n.findIndex((c) => c === a), s < 0 && (s = 0);
1068
+ else {
1069
+ if (t < n[0].wtime)
1070
+ return te(e[0]?.emotion, i);
1071
+ s = n[n.length - 1].queueIndex ?? n.length - 1;
1072
+ }
1073
+ for (const c of e)
1074
+ if (s >= c.start_word && s <= c.end_word)
1075
+ return te(c.emotion, i);
1076
+ for (const c of e)
1077
+ if (s < c.start_word)
1078
+ return te(c.emotion, i);
1079
+ return te(
1080
+ e[e.length - 1]?.emotion,
1081
+ i
1082
+ );
1083
+ }
1084
+ function ct(t, e, n, r, i = Be) {
1085
+ const a = new OffscreenCanvas(n, r), s = a.getContext("2d", { willReadFrequently: !0 });
1086
+ s.drawImage(t, 0, 0, n, r);
1087
+ const c = s.getImageData(0, 0, n, r), u = s.createImageData(n, r);
1088
+ u.data.set(c.data);
1089
+ const _ = new OffscreenCanvas(n, r).getContext("2d", { willReadFrequently: !0 });
1090
+ for (const o of e) {
1091
+ _.clearRect(0, 0, n, r), _.drawImage(o, 0, 0, n, r);
1092
+ const f = _.getImageData(0, 0, n, r);
1093
+ for (let d = 0; d < u.data.length; d += 4) {
1094
+ const k = f.data[d], x = f.data[d + 1], F = f.data[d + 2];
1095
+ Math.max(k, x, F) > i && (u.data[d] = k, u.data[d + 1] = x, u.data[d + 2] = F, u.data[d + 3] = 255);
1096
+ }
1097
+ }
1098
+ return s.putImageData(u, 0, 0), a;
1099
+ }
1100
+ let ge = null, ye = null;
1101
+ const Re = /* @__PURE__ */ new Map();
1102
+ function Dn() {
1103
+ ge = null, ye = null, Re.clear();
1104
+ }
1105
+ bt(Dn);
1106
+ function Pn(t) {
1107
+ return t ?? ye ?? void 0;
1108
+ }
1109
+ function Ve(t) {
1110
+ return new Promise((e, n) => {
1111
+ const r = new Image();
1112
+ r.decoding = "async", r.onload = () => e(r), r.onerror = () => n(new Error(`Failed to load image: ${t}`)), r.src = t;
1113
+ });
1114
+ }
1115
+ async function Je(t, e, n) {
1116
+ const r = ne() ? await ot(t, n) : await fetch(t).then((u) => {
1117
+ if (!u.ok) throw new Error(`Failed to load ${t}`);
1118
+ return u.json();
1119
+ }), i = r.sheets?.[0];
1120
+ if (!i?.path) throw new Error(`${t} has no sheets[0].path`);
1121
+ const a = ne() ? await on(
1122
+ await st(dn(e, i.path), n ?? "")
1123
+ ) : await Ve(`${e}/${i.path}`), s = /* @__PURE__ */ new Map();
1124
+ for (const u of r.cells ?? [])
1125
+ u.path && s.set(u.path, u);
1126
+ const c = /* @__PURE__ */ new Map();
1127
+ for (const u of r.sheets ?? [])
1128
+ c.set(u.index, u);
1129
+ return { atlas: a, atlasMeta: r, cellByPath: s, sheetByIndex: c, diffBase: e };
1130
+ }
1131
+ async function be(t) {
1132
+ const e = Pn(t);
1133
+ if (ne() && !e)
1134
+ throw new Error("Encrypted assets enabled but no key provided");
1135
+ if (ge && (!ne() || ye === (e ?? null)))
1136
+ return ge;
1137
+ ye = e ?? null, Re.clear();
1138
+ const n = Pt();
1139
+ return ge = (async () => {
1140
+ const r = await Ve(xt()), i = await Je(
1141
+ nt(),
1142
+ n,
1143
+ e
1144
+ );
1145
+ let a = null;
1146
+ try {
1147
+ a = await Je(
1148
+ Ct(),
1149
+ n,
1150
+ e
1151
+ );
1152
+ } catch {
1153
+ a = null;
1154
+ }
1155
+ return { sil: r, viseme: i, expression: a };
1156
+ })(), ge;
1157
+ }
1158
+ function He(t) {
1159
+ return nn(
1160
+ t.viseme.atlasMeta,
1161
+ t.sil.naturalWidth,
1162
+ t.sil.naturalHeight
1163
+ );
1164
+ }
1165
+ function Cn(t, e) {
1166
+ const n = document.createElement("canvas");
1167
+ return n.width = e.w, n.height = e.h, n.getContext("2d", { willReadFrequently: !0 }).drawImage(t.atlas, e.x, e.y, e.w, e.h, 0, 0, e.w, e.h), n;
1168
+ }
1169
+ async function Xe(t, e, n) {
1170
+ const r = `${e.diffBase}::${n}`, i = Re.get(r);
1171
+ if (i) return i;
1172
+ const a = (async () => {
1173
+ const s = e.cellByPath.get(n);
1174
+ if (!s) throw new Error(`No atlas cell for path: ${n}`);
1175
+ const c = rn(e.atlasMeta, s), u = He(t);
1176
+ if (sn(s)) {
1177
+ const o = Cn(e, s), f = document.createElement("canvas");
1178
+ f.width = u.width, f.height = u.height;
1179
+ const d = f.getContext("2d");
1180
+ return d.fillStyle = "#000", d.fillRect(0, 0, u.width, u.height), d.drawImage(o, c.x, c.y), f;
1181
+ }
1182
+ const p = `${e.diffBase}/${n}`, _ = await Ve(p);
1183
+ if (_.naturalWidth === u.width && _.naturalHeight === u.height)
1184
+ return _;
1185
+ throw new Error(`Diff PNG wrong size for ${n}`);
1186
+ })();
1187
+ return Re.set(r, a), a;
1188
+ }
1189
+ async function Ye(t, e, n, r = Be) {
1190
+ const i = await be(), { width: a, height: s } = He(i);
1191
+ (t.width !== a || t.height !== s) && (t.width = a, t.height = s);
1192
+ const c = [], u = t.getContext("2d");
1193
+ if (u.clearRect(0, 0, a, s), e.readyState < HTMLMediaElement.HAVE_CURRENT_DATA) {
1194
+ const _ = i.sil;
1195
+ u.drawImage(_, 0, 0, a, s);
1196
+ return;
1197
+ }
1198
+ if (c.length === 0) {
1199
+ u.drawImage(e, 0, 0, a, s);
1200
+ return;
1201
+ }
1202
+ const p = ct(e, c, a, s, r);
1203
+ u.drawImage(p, 0, 0);
1204
+ }
1205
+ async function Le(t, e, n = Be) {
1206
+ const r = await be(ye ?? void 0), { width: i, height: a } = He(r);
1207
+ (t.width !== i || t.height !== a) && (t.width = i, t.height = a);
1208
+ const s = [];
1209
+ e.mouthPath && s.push(await Xe(r, r.viseme, e.mouthPath)), e.expressionPath && r.expression && s.push(
1210
+ await Xe(r, r.expression, e.expressionPath)
1211
+ );
1212
+ const c = t.getContext("2d");
1213
+ if (c.clearRect(0, 0, i, a), s.length === 0) {
1214
+ c.drawImage(r.sil, 0, 0, i, a);
1215
+ return;
1216
+ }
1217
+ const u = ct(
1218
+ r.sil,
1219
+ s,
1220
+ i,
1221
+ a,
1222
+ n
1223
+ );
1224
+ c.drawImage(u, 0, 0);
1225
+ }
1226
+ async function Fn(t) {
1227
+ await Le(t, { mouthPath: null, expressionPath: null });
1228
+ }
1229
+ function Mn(t) {
1230
+ const e = /* @__PURE__ */ new Map();
1231
+ for (const n of t)
1232
+ e.has(n.vtime) || e.set(n.vtime, n);
1233
+ return [...e.values()].sort((n, r) => n.vtime - r.vtime);
1234
+ }
1235
+ function On(t) {
1236
+ const e = Mn(t), n = [];
1237
+ for (let r = 0; r < e.length - 1; r++) {
1238
+ const i = e[r].viseme, a = e[r + 1].viseme, s = e[r].vtime, c = e[r + 1].vtime;
1239
+ i === a || c <= s || n.push({ from: i, to: a, fromVtime: s, toVtime: c });
1240
+ }
1241
+ return n;
1242
+ }
1243
+ function Un(t, e) {
1244
+ let n = null;
1245
+ for (const r of t)
1246
+ e >= r.fromVtime && e < r.toVtime && (n = r);
1247
+ return n;
1248
+ }
1249
+ function Ln(t, e) {
1250
+ return { gapMs: Math.max(0, e - t), holdEnd: t, transStart: t };
1251
+ }
1252
+ const $n = 500, Bn = "__sil__";
1253
+ function Vn() {
1254
+ return { lastDrawnKey: "" };
1255
+ }
1256
+ function we(t) {
1257
+ t.lastDrawnKey = "";
1258
+ }
1259
+ function Ze(t) {
1260
+ return t ?? Bn;
1261
+ }
1262
+ function Hn(t, e) {
1263
+ if (t.length === 0)
1264
+ return { diffPath: null, label: "sil" };
1265
+ const n = On(t), r = Un(n, e);
1266
+ if (r) {
1267
+ const a = r.toVtime - r.fromVtime, s = Ln(r.fromVtime, r.toVtime);
1268
+ if (e >= s.transStart && e < r.toVtime) {
1269
+ const c = cn(r.from, r.to), u = ln(c, a);
1270
+ if (u.length > 0) {
1271
+ const p = fn(
1272
+ e,
1273
+ s.transStart,
1274
+ r.toVtime,
1275
+ u.length
1276
+ );
1277
+ return { diffPath: u[p] ?? u[u.length - 1], label: `${r.from}→${r.to}` };
1278
+ }
1279
+ return { diffPath: Oe(r.to), label: r.to };
1280
+ }
1281
+ }
1282
+ const i = Jt(t, e);
1283
+ return i === "sil" ? { diffPath: null, label: "sil" } : { diffPath: Oe(i), label: i };
1284
+ }
1285
+ function ut(t, e) {
1286
+ const n = e ?? Ze(t.expressionPath);
1287
+ return `${Ze(t.mouthPath)}|${n}`;
1288
+ }
1289
+ function Nn(t, e, n, r, i, a, s, c) {
1290
+ const u = Hn(e, n), p = {
1291
+ mouthPath: u.diffPath,
1292
+ expressionPath: r
1293
+ }, _ = ut(p, i);
1294
+ _ !== a.lastDrawnKey && (a.lastDrawnKey = _, c(u.label), s(t, p));
1295
+ }
1296
+ function Wn(t, e, n, r, i, a, s = null) {
1297
+ const c = { mouthPath: null, expressionPath: e }, u = s != null ? `|idle@${Math.round(s * 1e3)}` : "", p = ut(c, n) + u;
1298
+ !(s != null) && p === r.lastDrawnKey || (r.lastDrawnKey = p, a(
1299
+ s != null ? "idle" : "sil"
1300
+ ), i(t, c));
1301
+ }
1302
+ function Kn(t) {
1303
+ return new Worker(
1304
+ "/assets/visemeDiffPreview.worker-B8Juk7ys.js",
1305
+ {
1306
+ name: t?.name
1307
+ }
1308
+ );
1309
+ }
1310
+ function qn() {
1311
+ return typeof Worker < "u" && typeof OffscreenCanvas < "u";
1312
+ }
1313
+ function jn(t, e) {
1314
+ (t.width !== e.width || t.height !== e.height) && (t.width = e.width, t.height = e.height);
1315
+ const n = t.getContext("2d");
1316
+ n && n.drawImage(e, 0, 0);
1317
+ }
1318
+ function et(t, e) {
1319
+ let n = 0;
1320
+ return {
1321
+ usesWorker: !1,
1322
+ async loadAssets(r) {
1323
+ await be(r);
1324
+ },
1325
+ async renderSilOnly() {
1326
+ n += 1, await Fn(t);
1327
+ },
1328
+ async drawLiveFrame(r, i) {
1329
+ await be(), await Le(r, i);
1330
+ },
1331
+ async renderViseme(r, i) {
1332
+ n += 1;
1333
+ const a = n;
1334
+ e.onStatus?.(i), await Le(r, {
1335
+ mouthPath: Oe(i),
1336
+ expressionPath: null
1337
+ });
1338
+ },
1339
+ dispose() {
1340
+ n += 1;
1341
+ }
1342
+ };
1343
+ }
1344
+ function zn(t, e) {
1345
+ const n = new Kn();
1346
+ let r = 1, i = 0, a = !1, s = !1;
1347
+ const c = /* @__PURE__ */ new Map(), u = (o, f) => {
1348
+ s || n.postMessage(o, []);
1349
+ }, p = (o, f, d = !1) => {
1350
+ if (s) return Promise.resolve();
1351
+ const k = r++;
1352
+ return new Promise((x, F) => {
1353
+ c.set(k, {
1354
+ resolve: () => x(),
1355
+ reject: F,
1356
+ generation: typeof o.generation == "number" ? o.generation : void 0,
1357
+ expectRenderDone: d
1358
+ }), u({ ...o, requestId: k });
1359
+ });
1360
+ };
1361
+ n.onmessage = (o) => {
1362
+ if (s) return;
1363
+ const f = o.data;
1364
+ if (f.type === "status") {
1365
+ e.onStatus?.(f.label);
1366
+ return;
1367
+ }
1368
+ if (f.type === "frame") {
1369
+ const k = f.generation < 0;
1370
+ if (!k && f.generation !== i) {
1371
+ f.bitmap.close();
1372
+ return;
1373
+ }
1374
+ if (k && e.shouldAcceptLiveFrame && !e.shouldAcceptLiveFrame()) {
1375
+ f.bitmap.close();
1376
+ return;
1377
+ }
1378
+ jn(t, f.bitmap), f.bitmap.close();
1379
+ return;
1380
+ }
1381
+ const d = c.get(f.requestId);
1382
+ if (d)
1383
+ switch (f.type) {
1384
+ case "ready":
1385
+ case "loadAssetsDone":
1386
+ c.delete(f.requestId), d.resolve();
1387
+ break;
1388
+ case "renderDone":
1389
+ if (d.expectRenderDone && d.generation != null && f.generation !== d.generation)
1390
+ return;
1391
+ c.delete(f.requestId), d.resolve();
1392
+ break;
1393
+ case "renderAborted":
1394
+ c.delete(f.requestId), d.resolve();
1395
+ break;
1396
+ case "error":
1397
+ c.delete(f.requestId), e.onError?.(f.message), d.reject(new Error(f.message));
1398
+ break;
1399
+ }
1400
+ }, n.onerror = (o) => {
1401
+ if (s) return;
1402
+ const f = o.message || "Worker error";
1403
+ e.onError?.(f);
1404
+ for (const [, d] of c)
1405
+ d.reject(new Error(f));
1406
+ c.clear();
1407
+ };
1408
+ const _ = (async () => {
1409
+ await p({ type: "init" }), a = !0;
1410
+ })();
1411
+ return {
1412
+ usesWorker: !0,
1413
+ async loadAssets(o) {
1414
+ if (!s && (await _, !s)) {
1415
+ if (!a) throw new Error("Worker init failed");
1416
+ await p({
1417
+ type: "loadAssets",
1418
+ keyHex: o,
1419
+ urls: re()
1420
+ });
1421
+ }
1422
+ },
1423
+ async renderSilOnly() {
1424
+ if (s || (await _, s)) return;
1425
+ i += 1;
1426
+ const o = i;
1427
+ await p(
1428
+ { type: "renderSil", generation: o },
1429
+ void 0,
1430
+ !0
1431
+ );
1432
+ },
1433
+ async drawLiveFrame(o, f) {
1434
+ s || (await _, !s && await p(
1435
+ {
1436
+ type: "drawFrame",
1437
+ diffPath: f.mouthPath,
1438
+ expressionDiffPath: f.expressionPath
1439
+ },
1440
+ void 0,
1441
+ !0
1442
+ ));
1443
+ },
1444
+ async renderViseme(o, f, d = {}) {
1445
+ if (s || (await _, s)) return;
1446
+ i += 1;
1447
+ const k = i;
1448
+ try {
1449
+ await p(
1450
+ {
1451
+ type: "renderViseme",
1452
+ generation: k,
1453
+ to: f,
1454
+ from: d.from,
1455
+ transitionDurationMs: d.transitionDurationMs,
1456
+ gapMs: d.gapMs,
1457
+ threshold: d.threshold
1458
+ },
1459
+ void 0,
1460
+ !0
1461
+ );
1462
+ } catch (x) {
1463
+ if (x?.name === "AbortError") return;
1464
+ throw x;
1465
+ }
1466
+ },
1467
+ dispose() {
1468
+ if (!s) {
1469
+ s = !0, i += 1;
1470
+ for (const [, o] of c)
1471
+ o.resolve();
1472
+ c.clear(), n.terminate();
1473
+ }
1474
+ }
1475
+ };
1476
+ }
1477
+ function Gn(t, e = {}) {
1478
+ if (!qn())
1479
+ return et(t, e);
1480
+ try {
1481
+ return zn(t, e);
1482
+ } catch {
1483
+ return et(t, e);
1484
+ }
1485
+ }
1486
+ const Qn = {
1487
+ position: "relative",
1488
+ display: "inline-block",
1489
+ lineHeight: 0
1490
+ }, Jn = {
1491
+ display: "block",
1492
+ maxWidth: "100%",
1493
+ height: "auto"
1494
+ }, Xn = {
1495
+ position: "absolute",
1496
+ inset: 0,
1497
+ display: "flex",
1498
+ alignItems: "center",
1499
+ justifyContent: "center",
1500
+ padding: "1rem",
1501
+ background: "rgba(0,0,0,0.55)",
1502
+ color: "#fff",
1503
+ fontSize: "0.875rem",
1504
+ textAlign: "center"
1505
+ };
1506
+ function Ie(t) {
1507
+ return t === "cartesia" ? en : rt;
1508
+ }
1509
+ const tr = dt(function({
1510
+ id: e,
1511
+ assets: n,
1512
+ authToken: r,
1513
+ apiBase: i = $e,
1514
+ facesCdnBase: a = tt,
1515
+ tts: s = "google",
1516
+ voiceId: c,
1517
+ speakingRate: u = it,
1518
+ className: p,
1519
+ style: _,
1520
+ canvasStyle: o,
1521
+ onStatusChange: f,
1522
+ onDisplayStatus: d,
1523
+ onError: k,
1524
+ onReady: x,
1525
+ showErrorOverlay: F = !0
1526
+ }, Z) {
1527
+ const H = M(null), h = M(null), g = M(Vn()), P = M(In()), O = M(0), C = M(0), K = M(null), ie = M(!1), D = M(
1528
+ null
1529
+ ), N = M(!1), [se, fe] = _e("idle"), [oe, de] = _e(null), [z, ke] = _e(!1), [he, ae] = _e(!1), [Ee, Ne] = _e({ width: 842, height: 1264 }), m = M(r ?? null), R = M(null), A = M(null), T = M(!1), b = M(x), I = M(d), q = M(k);
1530
+ b.current = x, I.current = d, q.current = k;
1531
+ const B = ee(
1532
+ (l) => {
1533
+ const y = l?.tts ?? s ?? A.current?.tts ?? "google", E = l?.voiceId ?? c ?? A.current?.voiceId ?? Ie(y);
1534
+ return { tts: y, voiceId: E };
1535
+ },
1536
+ [s, c]
1537
+ ), v = ee((l) => {
1538
+ de(l), q.current?.(l);
1539
+ }, []), G = ee(
1540
+ (l) => {
1541
+ fe(l), f?.(l);
1542
+ },
1543
+ [f]
1544
+ ), S = M(tn(G, i)), V = ee(() => {
1545
+ K.current != null && (clearTimeout(K.current), K.current = null);
1546
+ }, []), $ = ee(async () => {
1547
+ const l = C.current, y = h.current;
1548
+ !y || !z || S.current.isSpeaking() || (we(g.current), !N.current && (await y.renderSilOnly(), l !== C.current || S.current.isSpeaking()));
1549
+ }, [z]), J = ee(() => {
1550
+ V();
1551
+ const l = C.current;
1552
+ $(), K.current = setTimeout(() => {
1553
+ K.current = null, l === C.current && $();
1554
+ }, $n);
1555
+ }, [V, $]), ce = ee(async () => {
1556
+ const l = Math.floor(Date.now() / 1e3);
1557
+ if (R.current && l < R.current.expiresAt - 60)
1558
+ return R.current.key;
1559
+ const y = m.current ?? await Ke();
1560
+ m.current = y, S.current.setDeveloperToken(y);
1561
+ const E = await St(y, i);
1562
+ return R.current = {
1563
+ key: E.value,
1564
+ expiresAt: E.expiresAt
1565
+ }, E.value;
1566
+ }, [i]);
1567
+ le(() => {
1568
+ r && (m.current = r, S.current.setDeveloperToken(r));
1569
+ }, [r]), le(() => {
1570
+ S.current.setTtsProvider(s), A.current && (A.current.tts = s);
1571
+ }, [s]), le(() => {
1572
+ const l = c ?? Ie(s);
1573
+ A.current && (A.current.voiceId = l);
1574
+ }, [c, s]);
1575
+ const U = ht(
1576
+ () => n ? JSON.stringify(n) : `id:${e ?? ""}:${a}`,
1577
+ [n, e, a]
1578
+ );
1579
+ return le(() => {
1580
+ if (!e && !n) {
1581
+ v("AiTwin requires either `id` or `assets`");
1582
+ return;
1583
+ }
1584
+ let l = !1;
1585
+ T.current = !1, ke(!1), ae(!1), de(null), A.current = null, D.current = null, N.current = !1;
1586
+ const y = H.current;
1587
+ if (!y) return;
1588
+ const E = Gn(y, {
1589
+ onStatus: (w) => {
1590
+ l || I.current?.(w);
1591
+ },
1592
+ onError: (w) => {
1593
+ l || v(w);
1594
+ },
1595
+ shouldAcceptLiveFrame: () => S.current.isSpeaking()
1596
+ });
1597
+ return h.current = E, (async () => {
1598
+ try {
1599
+ let w, L, Q;
1600
+ if (n)
1601
+ w = n, L = s, Q = c ?? Ie(L);
1602
+ else {
1603
+ const Y = await wt(e);
1604
+ if (l) return;
1605
+ L = Y.tts, Q = c ?? Y.voiceId ?? Ie(L), w = It(Y.faceId, a);
1606
+ }
1607
+ A.current = { tts: L, voiceId: Q }, Rt(w), D.current = Rn(Dt());
1608
+ const X = m.current ?? r ?? await Ke();
1609
+ if (l) return;
1610
+ m.current = X, S.current.setDeveloperToken(X), S.current.setTtsProvider(L);
1611
+ const Se = ne() ? await ce() : void 0;
1612
+ if (l) return;
1613
+ const j = await hn(Se);
1614
+ if (!l && j.width > 0 && j.height > 0 && Ne(j), await E.loadAssets(Se), l) return;
1615
+ let ue = !1;
1616
+ try {
1617
+ await D.current.load(), ue = !0, N.current = !0, ae(!0);
1618
+ } catch (Y) {
1619
+ N.current = !1, ae(!1), console.warn("[AiTwin] Idle video unavailable:", Y);
1620
+ }
1621
+ if (!ue)
1622
+ await E.renderSilOnly(), I.current?.("sil");
1623
+ else {
1624
+ we(g.current);
1625
+ const Y = D.current.getVideo();
1626
+ D.current.setActive(!0);
1627
+ try {
1628
+ await Ye(y, Y, null), I.current?.("idle");
1629
+ } catch (me) {
1630
+ console.warn("[AiTwin] Initial idle frame paint failed:", me);
1631
+ }
1632
+ }
1633
+ if (l) return;
1634
+ T.current = !0, ke(!0), b.current?.();
1635
+ } catch (w) {
1636
+ if (l) return;
1637
+ if (w instanceof Pe) {
1638
+ v(w.message);
1639
+ return;
1640
+ }
1641
+ v(w instanceof Error ? w.message : "Failed to load AI twin");
1642
+ }
1643
+ })(), () => {
1644
+ l = !0, E.dispose(), h.current = null;
1645
+ };
1646
+ }, [U, e, a, r, i, ce, v]), le(() => {
1647
+ se === "done" && z && !S.current.isSpeaking() && J();
1648
+ }, [se, z, J]), le(() => {
1649
+ const l = S.current, y = { current: !1 }, E = () => {
1650
+ const w = H.current, L = h.current;
1651
+ if (!w || !L || !z) {
1652
+ O.current = requestAnimationFrame(E);
1653
+ return;
1654
+ }
1655
+ const Q = l.isSpeaking(), X = l.getPlaybackElapsedMs(), Se = Q ? xn(
1656
+ X,
1657
+ l.getSentenceEmotions(),
1658
+ l.getWordQueue(),
1659
+ l.getStreamMood()
1660
+ ) : l.getStreamMood();
1661
+ if (Q) {
1662
+ if (N.current && D.current?.setActive(!1), l.getVisemeQueue().length === 0) {
1663
+ O.current = requestAnimationFrame(E);
1664
+ return;
1665
+ }
1666
+ P.current.setTargetEmotion(Se), P.current.advance(performance.now());
1667
+ const ue = P.current.getExpressionPath(), Y = P.current.getDrawKey();
1668
+ Nn(
1669
+ w,
1670
+ l.getVisemeQueue(),
1671
+ X,
1672
+ ue,
1673
+ Y,
1674
+ g.current,
1675
+ (me, lt) => L.drawLiveFrame(me, lt),
1676
+ (me) => I.current?.(me)
1677
+ );
1678
+ } else if (N.current && D.current) {
1679
+ const j = D.current;
1680
+ j.setActive(!0), y.current || (y.current = !0, Ye(w, j.getVideo()).then(() => I.current?.("idle")).finally(() => {
1681
+ y.current = !1;
1682
+ }));
1683
+ } else
1684
+ Wn(
1685
+ w,
1686
+ null,
1687
+ "__sil__",
1688
+ g.current,
1689
+ (j, ue) => L.drawLiveFrame(j, ue),
1690
+ (j) => I.current?.(j)
1691
+ );
1692
+ ie.current && !Q && (P.current.reset(), N.current && D.current?.restart(), J()), ie.current = Q, O.current = requestAnimationFrame(E);
1693
+ };
1694
+ return O.current = requestAnimationFrame(E), () => {
1695
+ cancelAnimationFrame(O.current), V(), l.stop();
1696
+ };
1697
+ }, [z, he, J, V]), mt(
1698
+ Z,
1699
+ () => ({
1700
+ speakText: async (l, y) => {
1701
+ const E = l.trim();
1702
+ if (!E) return;
1703
+ const w = h.current;
1704
+ if (!w || !T.current && !z)
1705
+ throw new Error("AI twin is not ready");
1706
+ const { tts: L, voiceId: Q } = B(y);
1707
+ de(null), C.current += 1, V(), we(g.current), P.current.reset(), ie.current = !1;
1708
+ try {
1709
+ N.current ? (D.current?.setActive(!1), D.current?.restart(), we(g.current)) : await w.renderSilOnly(), await S.current.speak(E, {
1710
+ voiceId: Q,
1711
+ speakingRate: y?.speakingRate ?? u,
1712
+ tts: L
1713
+ });
1714
+ } catch (X) {
1715
+ throw v(X instanceof Error ? X.message : "TTS failed"), X;
1716
+ }
1717
+ },
1718
+ stop: () => {
1719
+ C.current += 1, V(), S.current.stop(), we(g.current), ie.current = !1, J();
1720
+ },
1721
+ setTtsProvider: (l) => {
1722
+ S.current.setTtsProvider(l), A.current && (A.current.tts = l);
1723
+ },
1724
+ renderViseme: async (l, y) => {
1725
+ const E = h.current, w = H.current;
1726
+ if (!E || !w || !T.current)
1727
+ throw new Error("AI twin is not ready");
1728
+ await E.renderViseme(w, l, {
1729
+ from: y?.from,
1730
+ transitionDurationMs: y?.transitionDurationMs,
1731
+ gapMs: y?.gapMs,
1732
+ onStatus: (L) => I.current?.(L)
1733
+ });
1734
+ },
1735
+ isReady: () => T.current,
1736
+ getStatus: () => se
1737
+ }),
1738
+ [
1739
+ z,
1740
+ u,
1741
+ V,
1742
+ J,
1743
+ v,
1744
+ B,
1745
+ se
1746
+ ]
1747
+ ), /* @__PURE__ */ ft("div", { className: p, style: { ...Qn, ..._ }, children: [
1748
+ /* @__PURE__ */ We(
1749
+ "canvas",
1750
+ {
1751
+ ref: H,
1752
+ width: Ee.width,
1753
+ height: Ee.height,
1754
+ style: { ...Jn, ...o },
1755
+ "aria-label": e ? `AI twin ${e}` : "AI twin face"
1756
+ }
1757
+ ),
1758
+ F && oe ? /* @__PURE__ */ We("div", { style: Xn, children: oe }) : null
1759
+ ] });
1760
+ });
1761
+ export {
1762
+ tr as AiTwin,
1763
+ Pe as AiTwinNotFoundError,
1764
+ $e as DEFAULT_API_BASE,
1765
+ tt as DEFAULT_FACES_CDN_BASE,
1766
+ Mt as OCULUS_VISEME_IDS,
1767
+ Zt as SPEAKING_RATE_MAX,
1768
+ Yt as SPEAKING_RATE_MIN,
1769
+ er as VISEME_IDS,
1770
+ en as VISEME_TEST_CARTESIA_VOICE_ID,
1771
+ it as VISEME_TEST_SPEAKING_RATE,
1772
+ rt as VISEME_TEST_VOICE_ID,
1773
+ tn as createAvatarTtsLipsyncController,
1774
+ wt as fetchAiTwin,
1775
+ Ke as fetchDevAuthToken,
1776
+ Ut as normalizeOculusViseme,
1777
+ Jt as resolveVisemeAtTime,
1778
+ Xt as resolveWordAtTime
1779
+ };