@burdenoff/website-sdk 2026.1105.2 → 2026.1105.3
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 +54 -0
- package/dist/avatar-live-view/index.d.mts +1 -1
- package/dist/avatar-live-view/index.d.ts +1 -1
- package/dist/avatar-live-view/index.js +269 -78
- package/dist/avatar-live-view/index.js.map +1 -1
- package/dist/avatar-live-view/index.mjs +262 -71
- package/dist/avatar-live-view/index.mjs.map +1 -1
- package/dist/avatar-mic/index.d.mts +187 -62
- package/dist/avatar-mic/index.d.ts +187 -62
- package/dist/avatar-mic/index.js +457 -5
- package/dist/avatar-mic/index.js.map +1 -1
- package/dist/avatar-mic/index.mjs +457 -6
- package/dist/avatar-mic/index.mjs.map +1 -1
- package/dist/{chunk-XIZE37IB.js → chunk-3AIAJ2L4.js} +2 -2
- package/dist/chunk-3AIAJ2L4.js.map +1 -0
- package/dist/{chunk-MVNN6LLO.mjs → chunk-JGU6JW4N.mjs} +2 -2
- package/dist/chunk-JGU6JW4N.mjs.map +1 -0
- package/dist/{explore-avatar-live-config-auLKxSzx.d.ts → explore-avatar-live-config-1zeXdMer.d.ts} +6 -3
- package/dist/{explore-avatar-live-config-BL8FTm0I.d.mts → explore-avatar-live-config-BxiE66Im.d.mts} +6 -3
- package/dist/index.d.mts +6 -5
- package/dist/index.d.ts +6 -5
- package/dist/index.js +5 -5
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-MVNN6LLO.mjs.map +0 -1
- package/dist/chunk-XIZE37IB.js.map +0 -1
|
@@ -1,5 +1,456 @@
|
|
|
1
1
|
import { __publicField } from '../chunk-VNS5WDWO.mjs';
|
|
2
2
|
|
|
3
|
+
// src/avatar-mic/browser-press.ts
|
|
4
|
+
var BROWSER_START_WAIT_MS = 15e3;
|
|
5
|
+
var BROWSER_FINAL_WAIT_MS = 3e3;
|
|
6
|
+
var BROWSER_RESTART_COOLDOWN_MS = 2e3;
|
|
7
|
+
var BROWSER_TOUCH_RESTART_MS = 120;
|
|
8
|
+
var BROWSER_MAX_QUICK_ENDS = 8;
|
|
9
|
+
var BROWSER_MAX_RESTARTS = 60;
|
|
10
|
+
var BROWSER_PRIME_SETTLE_MS = 250;
|
|
11
|
+
var BROWSER_GRANT_RETRY_MS = 350;
|
|
12
|
+
var QUICK_END_MS = 1e3;
|
|
13
|
+
var NETWORK_FAILURES_FOR_GOOD = 2;
|
|
14
|
+
var IDLE = { name: "idle" };
|
|
15
|
+
function isRecognitionConstructor(value) {
|
|
16
|
+
return typeof value === "function";
|
|
17
|
+
}
|
|
18
|
+
function newBrowserRecognition() {
|
|
19
|
+
const found = Reflect.get(globalThis, "SpeechRecognition") ?? Reflect.get(globalThis, "webkitSpeechRecognition");
|
|
20
|
+
return isRecognitionConstructor(found) ? new found() : null;
|
|
21
|
+
}
|
|
22
|
+
function primeBrowserMicrophone() {
|
|
23
|
+
const media = typeof navigator === "undefined" ? void 0 : navigator.mediaDevices;
|
|
24
|
+
if (typeof media?.getUserMedia !== "function") return null;
|
|
25
|
+
return media.getUserMedia({ audio: true }).then((stream) => {
|
|
26
|
+
for (const track of stream.getTracks()) track.stop();
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
function watchBrowserMicPermission(onState) {
|
|
30
|
+
const permissions = typeof navigator === "undefined" ? void 0 : navigator.permissions;
|
|
31
|
+
if (typeof permissions?.query !== "function") return;
|
|
32
|
+
try {
|
|
33
|
+
void permissions.query({ name: "microphone" }).then(
|
|
34
|
+
(status) => {
|
|
35
|
+
onState(status.state);
|
|
36
|
+
status.addEventListener("change", () => onState(status.state));
|
|
37
|
+
},
|
|
38
|
+
() => void 0
|
|
39
|
+
);
|
|
40
|
+
} catch {
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function hasCoarsePointer() {
|
|
44
|
+
if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
return window.matchMedia("(pointer: coarse)").matches;
|
|
49
|
+
} catch {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
var BROWSER = {
|
|
54
|
+
createRecognition: newBrowserRecognition,
|
|
55
|
+
now: () => typeof performance !== "undefined" ? performance.now() : Date.now(),
|
|
56
|
+
primeMicrophone: primeBrowserMicrophone,
|
|
57
|
+
watchMicPermission: watchBrowserMicPermission,
|
|
58
|
+
touch: hasCoarsePointer
|
|
59
|
+
};
|
|
60
|
+
function primeFailure(error) {
|
|
61
|
+
const name = typeof error === "object" && error !== null && "name" in error ? String(error.name) : "";
|
|
62
|
+
if (name === "NotAllowedError" || name === "SecurityError") return "denied";
|
|
63
|
+
if (name === "NotFoundError" || name === "DevicesNotFoundError") {
|
|
64
|
+
return "unsupported";
|
|
65
|
+
}
|
|
66
|
+
return "failed";
|
|
67
|
+
}
|
|
68
|
+
function tidy(text) {
|
|
69
|
+
return text.replace(/\s+/g, " ").trim();
|
|
70
|
+
}
|
|
71
|
+
function readRecognitionResults(results) {
|
|
72
|
+
const finals = [];
|
|
73
|
+
const interim = [];
|
|
74
|
+
for (let index = 0; index < results.length; index += 1) {
|
|
75
|
+
const result = results[index];
|
|
76
|
+
const text = tidy(result?.[0]?.transcript ?? "");
|
|
77
|
+
if (result === void 0 || text === "") continue;
|
|
78
|
+
if (!result.isFinal) {
|
|
79
|
+
interim.push(text);
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
const last = finals.length > 0 ? finals[finals.length - 1] : void 0;
|
|
83
|
+
const lower = text.toLowerCase();
|
|
84
|
+
if (last !== void 0 && (lower === last.toLowerCase() || lower.startsWith(`${last.toLowerCase()} `))) {
|
|
85
|
+
finals[finals.length - 1] = text;
|
|
86
|
+
} else {
|
|
87
|
+
finals.push(text);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return { finals, interim: interim.join(" ") };
|
|
91
|
+
}
|
|
92
|
+
function createBrowserAvatarMic(options, seams = {}) {
|
|
93
|
+
const { createRecognition, now, primeMicrophone, watchMicPermission, touch } = { ...BROWSER, ...seams };
|
|
94
|
+
let press = null;
|
|
95
|
+
let epoch = 0;
|
|
96
|
+
let state = IDLE;
|
|
97
|
+
let networkFailures = 0;
|
|
98
|
+
let permission = null;
|
|
99
|
+
let hadMicrophone = false;
|
|
100
|
+
watchMicPermission((next) => {
|
|
101
|
+
permission = next;
|
|
102
|
+
});
|
|
103
|
+
const report = (next) => {
|
|
104
|
+
state = next;
|
|
105
|
+
options.onState(next);
|
|
106
|
+
};
|
|
107
|
+
const heard = (p) => [...p.earlier, ...p.instance?.finals ?? [], p.instance?.interim ?? ""].filter((part) => part !== "").join(" ");
|
|
108
|
+
const show = (p) => {
|
|
109
|
+
if (p.stage === "listening") {
|
|
110
|
+
report({
|
|
111
|
+
name: "listening",
|
|
112
|
+
epoch: p.epoch,
|
|
113
|
+
startedAt: p.startedAt,
|
|
114
|
+
text: heard(p)
|
|
115
|
+
});
|
|
116
|
+
} else if (p.stage === "finishing") {
|
|
117
|
+
report({
|
|
118
|
+
name: "finishing",
|
|
119
|
+
epoch: p.epoch,
|
|
120
|
+
text: heard(p),
|
|
121
|
+
limit: p.limit
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
const release = (instance) => {
|
|
126
|
+
const { recognition } = instance;
|
|
127
|
+
recognition.onstart = null;
|
|
128
|
+
recognition.onresult = null;
|
|
129
|
+
recognition.onerror = null;
|
|
130
|
+
recognition.onend = null;
|
|
131
|
+
try {
|
|
132
|
+
recognition.abort();
|
|
133
|
+
} catch {
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
const clearTimers = (p) => {
|
|
137
|
+
for (const timer of [
|
|
138
|
+
p.startTimer,
|
|
139
|
+
p.limitTimer,
|
|
140
|
+
p.finalTimer,
|
|
141
|
+
p.launchTimer
|
|
142
|
+
]) {
|
|
143
|
+
if (timer !== null) clearTimeout(timer);
|
|
144
|
+
}
|
|
145
|
+
p.startTimer = null;
|
|
146
|
+
p.limitTimer = null;
|
|
147
|
+
p.finalTimer = null;
|
|
148
|
+
p.launchTimer = null;
|
|
149
|
+
};
|
|
150
|
+
const settle = (p, next) => {
|
|
151
|
+
if (p.stage === "ended") return;
|
|
152
|
+
p.stage = "ended";
|
|
153
|
+
clearTimers(p);
|
|
154
|
+
const instance = p.instance;
|
|
155
|
+
p.instance = null;
|
|
156
|
+
if (instance !== null) release(instance);
|
|
157
|
+
if (press === p) press = null;
|
|
158
|
+
report(next);
|
|
159
|
+
};
|
|
160
|
+
const complete = (p) => {
|
|
161
|
+
const text = heard(p);
|
|
162
|
+
if (text !== "") networkFailures = 0;
|
|
163
|
+
settle(p, { name: "done", epoch: p.epoch, text, limit: p.limit });
|
|
164
|
+
};
|
|
165
|
+
const fail = (p, reason) => settle(p, { name: "failed", epoch: p.epoch, reason, text: heard(p) });
|
|
166
|
+
const current = (p, instance) => press === p && p.stage !== "ended" && p.instance === instance;
|
|
167
|
+
const began = (p, instance) => {
|
|
168
|
+
instance.started = true;
|
|
169
|
+
instance.startedAt = now();
|
|
170
|
+
hadMicrophone = true;
|
|
171
|
+
if (p.stage !== "starting") return;
|
|
172
|
+
if (p.startTimer !== null) clearTimeout(p.startTimer);
|
|
173
|
+
p.startTimer = null;
|
|
174
|
+
p.stage = "listening";
|
|
175
|
+
p.startedAt = Date.now();
|
|
176
|
+
p.limitTimer = setTimeout(() => {
|
|
177
|
+
p.limitTimer = null;
|
|
178
|
+
if (press === p) stopRecording(p, true);
|
|
179
|
+
}, options.maxPressMs);
|
|
180
|
+
};
|
|
181
|
+
const launchIn = (p, delay) => {
|
|
182
|
+
if (delay <= 0) {
|
|
183
|
+
launch(p);
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
const stage = p.stage;
|
|
187
|
+
p.launchTimer = setTimeout(() => {
|
|
188
|
+
p.launchTimer = null;
|
|
189
|
+
if (press === p && p.stage === stage) launch(p);
|
|
190
|
+
}, delay);
|
|
191
|
+
};
|
|
192
|
+
const restart = (p, end) => {
|
|
193
|
+
p.quickEnds = end === "listened" ? 0 : p.quickEnds + 1;
|
|
194
|
+
if (p.restarts >= BROWSER_MAX_RESTARTS || p.quickEnds >= BROWSER_MAX_QUICK_ENDS) {
|
|
195
|
+
complete(p);
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
p.restarts += 1;
|
|
199
|
+
launchIn(
|
|
200
|
+
p,
|
|
201
|
+
end === "threw" || end === "quick" && !p.touch ? BROWSER_RESTART_COOLDOWN_MS : p.touch ? BROWSER_TOUCH_RESTART_MS : 0
|
|
202
|
+
);
|
|
203
|
+
};
|
|
204
|
+
const keep = (p, instance) => {
|
|
205
|
+
for (const text of [...instance.finals, instance.interim]) {
|
|
206
|
+
if (text !== "") p.earlier.push(text);
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
const onError = (p, instance, code) => {
|
|
210
|
+
if (code === "no-speech") {
|
|
211
|
+
instance.noSpeech = true;
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
const going = p.stage === "starting" || p.stage === "listening";
|
|
215
|
+
if (code === "language-not-supported" && going && !p.langRetried) {
|
|
216
|
+
p.langRetried = true;
|
|
217
|
+
if (options.fallbackLang !== p.lang) {
|
|
218
|
+
p.lang = options.fallbackLang;
|
|
219
|
+
keep(p, instance);
|
|
220
|
+
p.instance = null;
|
|
221
|
+
release(instance);
|
|
222
|
+
launch(p);
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
const refused = code === "not-allowed" || code === "service-not-allowed";
|
|
227
|
+
if (refused && going && p.confirmed && !p.grantRetried) {
|
|
228
|
+
p.grantRetried = true;
|
|
229
|
+
keep(p, instance);
|
|
230
|
+
p.instance = null;
|
|
231
|
+
release(instance);
|
|
232
|
+
launchIn(p, BROWSER_GRANT_RETRY_MS);
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
if (refused && !p.confirmed) hadMicrophone = false;
|
|
236
|
+
if (heard(p) !== "") {
|
|
237
|
+
complete(p);
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
switch (code) {
|
|
241
|
+
case "not-allowed":
|
|
242
|
+
fail(p, p.confirmed ? "unsupported" : "denied");
|
|
243
|
+
return;
|
|
244
|
+
case "service-not-allowed":
|
|
245
|
+
case "audio-capture":
|
|
246
|
+
case "language-not-supported":
|
|
247
|
+
fail(p, "unsupported");
|
|
248
|
+
return;
|
|
249
|
+
case "network":
|
|
250
|
+
networkFailures += 1;
|
|
251
|
+
fail(
|
|
252
|
+
p,
|
|
253
|
+
networkFailures >= NETWORK_FAILURES_FOR_GOOD ? "unsupported" : "failed"
|
|
254
|
+
);
|
|
255
|
+
return;
|
|
256
|
+
default:
|
|
257
|
+
fail(p, "failed");
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
const onEnd = (p, instance) => {
|
|
261
|
+
keep(p, instance);
|
|
262
|
+
p.instance = null;
|
|
263
|
+
instance.recognition.onstart = null;
|
|
264
|
+
instance.recognition.onresult = null;
|
|
265
|
+
instance.recognition.onerror = null;
|
|
266
|
+
instance.recognition.onend = null;
|
|
267
|
+
switch (p.stage) {
|
|
268
|
+
case "starting":
|
|
269
|
+
if (instance.noSpeech) complete(p);
|
|
270
|
+
else fail(p, "failed");
|
|
271
|
+
return;
|
|
272
|
+
case "listening": {
|
|
273
|
+
const quick = !instance.started || now() - instance.startedAt < QUICK_END_MS && instance.finals.length === 0 && instance.interim === "";
|
|
274
|
+
restart(p, quick ? "quick" : "listened");
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
case "finishing":
|
|
278
|
+
complete(p);
|
|
279
|
+
return;
|
|
280
|
+
default:
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
};
|
|
284
|
+
function launch(p) {
|
|
285
|
+
let recognition;
|
|
286
|
+
try {
|
|
287
|
+
recognition = createRecognition();
|
|
288
|
+
} catch {
|
|
289
|
+
recognition = null;
|
|
290
|
+
}
|
|
291
|
+
if (recognition === null) {
|
|
292
|
+
if (p.stage === "starting") fail(p, "unsupported");
|
|
293
|
+
else complete(p);
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
const instance = {
|
|
297
|
+
recognition,
|
|
298
|
+
started: false,
|
|
299
|
+
startedAt: 0,
|
|
300
|
+
finals: [],
|
|
301
|
+
interim: "",
|
|
302
|
+
noSpeech: false
|
|
303
|
+
};
|
|
304
|
+
recognition.lang = p.lang;
|
|
305
|
+
recognition.continuous = !p.touch;
|
|
306
|
+
recognition.interimResults = true;
|
|
307
|
+
recognition.maxAlternatives = 1;
|
|
308
|
+
recognition.onstart = () => {
|
|
309
|
+
if (!current(p, instance)) return;
|
|
310
|
+
began(p, instance);
|
|
311
|
+
show(p);
|
|
312
|
+
};
|
|
313
|
+
recognition.onresult = (event) => {
|
|
314
|
+
if (!current(p, instance)) return;
|
|
315
|
+
if (!instance.started) began(p, instance);
|
|
316
|
+
const read = readRecognitionResults(event.results);
|
|
317
|
+
instance.finals = read.finals;
|
|
318
|
+
instance.interim = read.interim;
|
|
319
|
+
show(p);
|
|
320
|
+
};
|
|
321
|
+
recognition.onerror = (event) => {
|
|
322
|
+
if (current(p, instance)) onError(p, instance, event.error);
|
|
323
|
+
};
|
|
324
|
+
recognition.onend = () => {
|
|
325
|
+
if (current(p, instance)) onEnd(p, instance);
|
|
326
|
+
};
|
|
327
|
+
p.instance = instance;
|
|
328
|
+
try {
|
|
329
|
+
recognition.start();
|
|
330
|
+
} catch {
|
|
331
|
+
p.instance = null;
|
|
332
|
+
release(instance);
|
|
333
|
+
if (p.stage === "starting") fail(p, "failed");
|
|
334
|
+
else if (p.stage === "listening") restart(p, "threw");
|
|
335
|
+
else complete(p);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
function prime(p) {
|
|
339
|
+
let opening;
|
|
340
|
+
try {
|
|
341
|
+
opening = primeMicrophone();
|
|
342
|
+
} catch (error) {
|
|
343
|
+
fail(p, primeFailure(error));
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
if (opening === null) {
|
|
347
|
+
launch(p);
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
void opening.then(
|
|
351
|
+
() => {
|
|
352
|
+
hadMicrophone = true;
|
|
353
|
+
if (press !== p || p.stage !== "starting") return;
|
|
354
|
+
p.confirmed = true;
|
|
355
|
+
launchIn(p, BROWSER_PRIME_SETTLE_MS);
|
|
356
|
+
},
|
|
357
|
+
(error) => {
|
|
358
|
+
if (press === p && p.stage === "starting") fail(p, primeFailure(error));
|
|
359
|
+
}
|
|
360
|
+
);
|
|
361
|
+
}
|
|
362
|
+
function stopRecording(p, limit) {
|
|
363
|
+
if (p.stage !== "listening") return;
|
|
364
|
+
if (p.limitTimer !== null) clearTimeout(p.limitTimer);
|
|
365
|
+
if (p.launchTimer !== null) clearTimeout(p.launchTimer);
|
|
366
|
+
p.limitTimer = null;
|
|
367
|
+
p.launchTimer = null;
|
|
368
|
+
p.stage = "finishing";
|
|
369
|
+
p.limit = limit;
|
|
370
|
+
const instance = p.instance;
|
|
371
|
+
if (instance === null || !instance.started) {
|
|
372
|
+
complete(p);
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
try {
|
|
376
|
+
instance.recognition.stop();
|
|
377
|
+
} catch {
|
|
378
|
+
complete(p);
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
p.finalTimer = setTimeout(() => {
|
|
382
|
+
p.finalTimer = null;
|
|
383
|
+
if (press === p && p.stage === "finishing") complete(p);
|
|
384
|
+
}, BROWSER_FINAL_WAIT_MS);
|
|
385
|
+
show(p);
|
|
386
|
+
}
|
|
387
|
+
const cancel = () => {
|
|
388
|
+
const p = press;
|
|
389
|
+
press = null;
|
|
390
|
+
if (p !== null && p.stage !== "ended") {
|
|
391
|
+
p.stage = "ended";
|
|
392
|
+
clearTimers(p);
|
|
393
|
+
const instance = p.instance;
|
|
394
|
+
p.instance = null;
|
|
395
|
+
if (instance !== null) release(instance);
|
|
396
|
+
}
|
|
397
|
+
if (state.name !== "idle") report(IDLE);
|
|
398
|
+
};
|
|
399
|
+
const start = () => {
|
|
400
|
+
const held = press;
|
|
401
|
+
if (held !== null && (held.stage === "starting" || held.stage === "listening")) {
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
if (held !== null && held.stage === "finishing") {
|
|
405
|
+
held.stage = "ended";
|
|
406
|
+
clearTimers(held);
|
|
407
|
+
const instance = held.instance;
|
|
408
|
+
held.instance = null;
|
|
409
|
+
if (instance !== null) release(instance);
|
|
410
|
+
press = null;
|
|
411
|
+
}
|
|
412
|
+
epoch += 1;
|
|
413
|
+
const p = {
|
|
414
|
+
epoch,
|
|
415
|
+
stage: "starting",
|
|
416
|
+
instance: null,
|
|
417
|
+
earlier: [],
|
|
418
|
+
lang: options.lang,
|
|
419
|
+
langRetried: false,
|
|
420
|
+
restarts: 0,
|
|
421
|
+
quickEnds: 0,
|
|
422
|
+
confirmed: permission === "granted",
|
|
423
|
+
grantRetried: false,
|
|
424
|
+
touch: touch(),
|
|
425
|
+
startedAt: 0,
|
|
426
|
+
limit: false,
|
|
427
|
+
startTimer: null,
|
|
428
|
+
limitTimer: null,
|
|
429
|
+
finalTimer: null,
|
|
430
|
+
launchTimer: null
|
|
431
|
+
};
|
|
432
|
+
press = p;
|
|
433
|
+
report({ name: "starting", epoch });
|
|
434
|
+
p.startTimer = setTimeout(() => {
|
|
435
|
+
p.startTimer = null;
|
|
436
|
+
if (press === p && p.stage === "starting") fail(p, "failed");
|
|
437
|
+
}, BROWSER_START_WAIT_MS);
|
|
438
|
+
if (p.confirmed || permission === null && hadMicrophone) launch(p);
|
|
439
|
+
else prime(p);
|
|
440
|
+
};
|
|
441
|
+
return {
|
|
442
|
+
start,
|
|
443
|
+
stop() {
|
|
444
|
+
const p = press;
|
|
445
|
+
if (p === null) return;
|
|
446
|
+
if (p.stage === "starting") cancel();
|
|
447
|
+
else stopRecording(p, false);
|
|
448
|
+
},
|
|
449
|
+
cancel,
|
|
450
|
+
state: () => state
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
|
|
3
454
|
// src/avatar-mic/capture-worklet.ts
|
|
4
455
|
var CAPTURE_FRAME_SAMPLES = 320;
|
|
5
456
|
var CAPTURE_SAMPLE_RATE = 16e3;
|
|
@@ -322,7 +773,7 @@ var FINAL_WAIT_MS = 12e3;
|
|
|
322
773
|
var OFFER_TTL_MS = 12e4;
|
|
323
774
|
var OFFER_MARGIN_MS = 5e3;
|
|
324
775
|
var CLOCK_TOLERANCE_MS = 5e3;
|
|
325
|
-
var
|
|
776
|
+
var IDLE2 = { name: "idle" };
|
|
326
777
|
function offerFreshUntil(offer) {
|
|
327
778
|
const ahead = offer.expiresAt - offer.receivedAt;
|
|
328
779
|
const life = ahead > 0 && ahead <= OFFER_TTL_MS + CLOCK_TOLERANCE_MS ? Math.min(ahead, OFFER_TTL_MS) : OFFER_TTL_MS;
|
|
@@ -355,20 +806,20 @@ function randomUtteranceId() {
|
|
|
355
806
|
const bytes = crypto.getRandomValues(new Uint8Array(16));
|
|
356
807
|
return `web-${Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("")}`;
|
|
357
808
|
}
|
|
358
|
-
var
|
|
809
|
+
var BROWSER2 = {
|
|
359
810
|
createSocket: openBrowserSocket,
|
|
360
811
|
startCapture: startMicCapture,
|
|
361
812
|
newUtteranceId: randomUtteranceId
|
|
362
813
|
};
|
|
363
814
|
function createAvatarMic(options, seams = {}) {
|
|
364
815
|
const { createSocket, startCapture, newUtteranceId } = {
|
|
365
|
-
...
|
|
816
|
+
...BROWSER2,
|
|
366
817
|
...seams
|
|
367
818
|
};
|
|
368
819
|
let press = null;
|
|
369
820
|
let connection = null;
|
|
370
821
|
let epoch = 0;
|
|
371
|
-
let state =
|
|
822
|
+
let state = IDLE2;
|
|
372
823
|
const report = (next) => {
|
|
373
824
|
state = next;
|
|
374
825
|
options.onState(next);
|
|
@@ -650,7 +1101,7 @@ function createAvatarMic(options, seams = {}) {
|
|
|
650
1101
|
clearTimers(p);
|
|
651
1102
|
}
|
|
652
1103
|
closeConnection();
|
|
653
|
-
if (state.name !== "idle") report(
|
|
1104
|
+
if (state.name !== "idle") report(IDLE2);
|
|
654
1105
|
};
|
|
655
1106
|
const start = () => {
|
|
656
1107
|
const current = press;
|
|
@@ -731,6 +1182,6 @@ function createAvatarMic(options, seams = {}) {
|
|
|
731
1182
|
};
|
|
732
1183
|
}
|
|
733
1184
|
|
|
734
|
-
export { createAvatarMic };
|
|
1185
|
+
export { createAvatarMic, createBrowserAvatarMic };
|
|
735
1186
|
//# sourceMappingURL=index.mjs.map
|
|
736
1187
|
//# sourceMappingURL=index.mjs.map
|