@omote/core 0.5.4 → 0.5.6
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/index.d.mts +26 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.js +146 -68
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +146 -68
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -584,6 +584,14 @@ interface FullFacePipelineOptions {
|
|
|
584
584
|
chunkSize?: number;
|
|
585
585
|
/** A2E inference engine */
|
|
586
586
|
lam: A2EBackend;
|
|
587
|
+
/**
|
|
588
|
+
* Identity/style index for the A2E model (default: 0).
|
|
589
|
+
*
|
|
590
|
+
* The LAM model uses a 12-class one-hot identity vector as style conditioning.
|
|
591
|
+
* Different indices produce different expression intensity across face regions.
|
|
592
|
+
* Only affects Wav2Vec2Inference (GPU). Wav2ArkitCpuInference has identity 11 baked in.
|
|
593
|
+
*/
|
|
594
|
+
identityIndex?: number;
|
|
587
595
|
/** Per-character expression weight scaling */
|
|
588
596
|
profile?: ExpressionProfile;
|
|
589
597
|
/**
|
|
@@ -2259,6 +2267,17 @@ interface A2EProcessorConfig {
|
|
|
2259
2267
|
sampleRate?: number;
|
|
2260
2268
|
/** Samples per inference chunk (default: 16000 = 1s) */
|
|
2261
2269
|
chunkSize?: number;
|
|
2270
|
+
/**
|
|
2271
|
+
* Identity/style index for the A2E model (default: 0).
|
|
2272
|
+
*
|
|
2273
|
+
* The LAM model uses a one-hot identity vector (12 classes, indices 0-11) as
|
|
2274
|
+
* style conditioning alongside audio features. Different indices produce
|
|
2275
|
+
* different expression intensity across face regions (brows, eyes, cheeks).
|
|
2276
|
+
*
|
|
2277
|
+
* Only affects Wav2Vec2Inference (GPU model). Wav2ArkitCpuInference has
|
|
2278
|
+
* identity 11 baked into the model weights.
|
|
2279
|
+
*/
|
|
2280
|
+
identityIndex?: number;
|
|
2262
2281
|
/** Callback fired with each blendshape frame (push mode) */
|
|
2263
2282
|
onFrame?: (frame: Float32Array) => void;
|
|
2264
2283
|
/** Error callback */
|
|
@@ -2268,6 +2287,7 @@ declare class A2EProcessor {
|
|
|
2268
2287
|
private readonly backend;
|
|
2269
2288
|
private readonly sampleRate;
|
|
2270
2289
|
private readonly chunkSize;
|
|
2290
|
+
private readonly identityIndex;
|
|
2271
2291
|
private readonly onFrame?;
|
|
2272
2292
|
private readonly onError?;
|
|
2273
2293
|
private bufferCapacity;
|
|
@@ -3110,6 +3130,12 @@ interface FetchWithCacheOptions {
|
|
|
3110
3130
|
validateStale?: boolean;
|
|
3111
3131
|
/** Progress callback during download */
|
|
3112
3132
|
onProgress?: (loaded: number, total: number) => void;
|
|
3133
|
+
/** Timeout per fetch attempt in ms. Default: 120_000 (2 min) */
|
|
3134
|
+
timeoutMs?: number;
|
|
3135
|
+
/** Max retry attempts on failure. Default: 2 (3 total attempts) */
|
|
3136
|
+
maxRetries?: number;
|
|
3137
|
+
/** AbortSignal to cancel the entire operation */
|
|
3138
|
+
signal?: AbortSignal;
|
|
3113
3139
|
}
|
|
3114
3140
|
/**
|
|
3115
3141
|
* Fetch a model with caching
|
package/dist/index.d.ts
CHANGED
|
@@ -584,6 +584,14 @@ interface FullFacePipelineOptions {
|
|
|
584
584
|
chunkSize?: number;
|
|
585
585
|
/** A2E inference engine */
|
|
586
586
|
lam: A2EBackend;
|
|
587
|
+
/**
|
|
588
|
+
* Identity/style index for the A2E model (default: 0).
|
|
589
|
+
*
|
|
590
|
+
* The LAM model uses a 12-class one-hot identity vector as style conditioning.
|
|
591
|
+
* Different indices produce different expression intensity across face regions.
|
|
592
|
+
* Only affects Wav2Vec2Inference (GPU). Wav2ArkitCpuInference has identity 11 baked in.
|
|
593
|
+
*/
|
|
594
|
+
identityIndex?: number;
|
|
587
595
|
/** Per-character expression weight scaling */
|
|
588
596
|
profile?: ExpressionProfile;
|
|
589
597
|
/**
|
|
@@ -2259,6 +2267,17 @@ interface A2EProcessorConfig {
|
|
|
2259
2267
|
sampleRate?: number;
|
|
2260
2268
|
/** Samples per inference chunk (default: 16000 = 1s) */
|
|
2261
2269
|
chunkSize?: number;
|
|
2270
|
+
/**
|
|
2271
|
+
* Identity/style index for the A2E model (default: 0).
|
|
2272
|
+
*
|
|
2273
|
+
* The LAM model uses a one-hot identity vector (12 classes, indices 0-11) as
|
|
2274
|
+
* style conditioning alongside audio features. Different indices produce
|
|
2275
|
+
* different expression intensity across face regions (brows, eyes, cheeks).
|
|
2276
|
+
*
|
|
2277
|
+
* Only affects Wav2Vec2Inference (GPU model). Wav2ArkitCpuInference has
|
|
2278
|
+
* identity 11 baked into the model weights.
|
|
2279
|
+
*/
|
|
2280
|
+
identityIndex?: number;
|
|
2262
2281
|
/** Callback fired with each blendshape frame (push mode) */
|
|
2263
2282
|
onFrame?: (frame: Float32Array) => void;
|
|
2264
2283
|
/** Error callback */
|
|
@@ -2268,6 +2287,7 @@ declare class A2EProcessor {
|
|
|
2268
2287
|
private readonly backend;
|
|
2269
2288
|
private readonly sampleRate;
|
|
2270
2289
|
private readonly chunkSize;
|
|
2290
|
+
private readonly identityIndex;
|
|
2271
2291
|
private readonly onFrame?;
|
|
2272
2292
|
private readonly onError?;
|
|
2273
2293
|
private bufferCapacity;
|
|
@@ -3110,6 +3130,12 @@ interface FetchWithCacheOptions {
|
|
|
3110
3130
|
validateStale?: boolean;
|
|
3111
3131
|
/** Progress callback during download */
|
|
3112
3132
|
onProgress?: (loaded: number, total: number) => void;
|
|
3133
|
+
/** Timeout per fetch attempt in ms. Default: 120_000 (2 min) */
|
|
3134
|
+
timeoutMs?: number;
|
|
3135
|
+
/** Max retry attempts on failure. Default: 2 (3 total attempts) */
|
|
3136
|
+
maxRetries?: number;
|
|
3137
|
+
/** AbortSignal to cancel the entire operation */
|
|
3138
|
+
signal?: AbortSignal;
|
|
3113
3139
|
}
|
|
3114
3140
|
/**
|
|
3115
3141
|
* Fetch a model with caching
|
package/dist/index.js
CHANGED
|
@@ -916,6 +916,7 @@ var A2EProcessor = class {
|
|
|
916
916
|
this.backend = config.backend;
|
|
917
917
|
this.sampleRate = config.sampleRate ?? 16e3;
|
|
918
918
|
this.chunkSize = config.chunkSize ?? config.backend.chunkSize ?? 16e3;
|
|
919
|
+
this.identityIndex = config.identityIndex ?? 0;
|
|
919
920
|
this.onFrame = config.onFrame;
|
|
920
921
|
this.onError = config.onError;
|
|
921
922
|
this.bufferCapacity = this.chunkSize * 2;
|
|
@@ -1123,7 +1124,7 @@ var A2EProcessor = class {
|
|
|
1123
1124
|
const { chunk, timestamp } = this.pendingChunks.shift();
|
|
1124
1125
|
try {
|
|
1125
1126
|
const t0 = performance.now();
|
|
1126
|
-
const result = await this.backend.infer(chunk);
|
|
1127
|
+
const result = await this.backend.infer(chunk, this.identityIndex);
|
|
1127
1128
|
const inferMs = Math.round(performance.now() - t0);
|
|
1128
1129
|
const actualDuration = chunk.length / this.sampleRate;
|
|
1129
1130
|
const actualFrameCount = Math.ceil(actualDuration * FRAME_RATE);
|
|
@@ -2218,6 +2219,16 @@ function getModelCache() {
|
|
|
2218
2219
|
return cacheInstance;
|
|
2219
2220
|
}
|
|
2220
2221
|
var MAX_CACHE_SIZE_BYTES = 500 * 1024 * 1024;
|
|
2222
|
+
function fetchWithTimeout(url, timeoutMs, signal) {
|
|
2223
|
+
const controller = new AbortController();
|
|
2224
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
2225
|
+
const onCallerAbort = () => controller.abort();
|
|
2226
|
+
signal?.addEventListener("abort", onCallerAbort, { once: true });
|
|
2227
|
+
return fetch(url, { signal: controller.signal }).finally(() => {
|
|
2228
|
+
clearTimeout(timer);
|
|
2229
|
+
signal?.removeEventListener("abort", onCallerAbort);
|
|
2230
|
+
});
|
|
2231
|
+
}
|
|
2221
2232
|
async function fetchWithCache(url, optionsOrProgress) {
|
|
2222
2233
|
let options = {};
|
|
2223
2234
|
if (typeof optionsOrProgress === "function") {
|
|
@@ -2271,61 +2282,84 @@ async function fetchWithCache(url, optionsOrProgress) {
|
|
|
2271
2282
|
}
|
|
2272
2283
|
span?.setAttributes({ "fetch.cache_hit": false });
|
|
2273
2284
|
console.log(`[ModelCache] Cache miss, fetching: ${url}`);
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
}
|
|
2286
|
-
|
|
2287
|
-
const
|
|
2285
|
+
const timeout = options.timeoutMs ?? 12e4;
|
|
2286
|
+
const maxRetries = options.maxRetries ?? 2;
|
|
2287
|
+
let lastError = null;
|
|
2288
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
2289
|
+
if (options.signal?.aborted) {
|
|
2290
|
+
throw new Error(`Fetch aborted for ${url}`);
|
|
2291
|
+
}
|
|
2292
|
+
if (attempt > 0) {
|
|
2293
|
+
const backoff = Math.min(2e3 * Math.pow(2, attempt - 1), 16e3);
|
|
2294
|
+
console.log(`[ModelCache] Retry ${attempt}/${maxRetries} after ${backoff}ms: ${url}`);
|
|
2295
|
+
await new Promise((r) => setTimeout(r, backoff));
|
|
2296
|
+
}
|
|
2297
|
+
try {
|
|
2298
|
+
const response = await fetchWithTimeout(url, timeout, options.signal);
|
|
2299
|
+
if (!response.ok) {
|
|
2300
|
+
throw new Error(`Failed to fetch ${url}: ${response.status}`);
|
|
2301
|
+
}
|
|
2302
|
+
const contentLength = response.headers.get("content-length");
|
|
2303
|
+
const total = contentLength ? parseInt(contentLength, 10) : 0;
|
|
2304
|
+
const etag = response.headers.get("etag") ?? void 0;
|
|
2305
|
+
const tooLargeForCache = total > MAX_CACHE_SIZE_BYTES;
|
|
2306
|
+
if (tooLargeForCache) {
|
|
2307
|
+
console.log(`[ModelCache] File too large for IndexedDB (${(total / 1024 / 1024).toFixed(0)}MB > 500MB), using HTTP cache only`);
|
|
2308
|
+
}
|
|
2309
|
+
if (!response.body) {
|
|
2310
|
+
const data2 = await response.arrayBuffer();
|
|
2311
|
+
if (!tooLargeForCache) {
|
|
2312
|
+
await cache.set(cacheKey, data2, etag, version);
|
|
2313
|
+
}
|
|
2314
|
+
span?.setAttributes({
|
|
2315
|
+
"fetch.size_bytes": data2.byteLength,
|
|
2316
|
+
"fetch.cached_to_indexeddb": !tooLargeForCache,
|
|
2317
|
+
...attempt > 0 && { "fetch.retry_count": attempt }
|
|
2318
|
+
});
|
|
2319
|
+
span?.end();
|
|
2320
|
+
return data2;
|
|
2321
|
+
}
|
|
2322
|
+
const reader = response.body.getReader();
|
|
2323
|
+
const chunks = [];
|
|
2324
|
+
let loaded = 0;
|
|
2325
|
+
while (true) {
|
|
2326
|
+
const { done, value } = await reader.read();
|
|
2327
|
+
if (done) break;
|
|
2328
|
+
chunks.push(value);
|
|
2329
|
+
loaded += value.length;
|
|
2330
|
+
onProgress?.(loaded, total || loaded);
|
|
2331
|
+
}
|
|
2332
|
+
const data = new Uint8Array(loaded);
|
|
2333
|
+
let offset = 0;
|
|
2334
|
+
for (const chunk of chunks) {
|
|
2335
|
+
data.set(chunk, offset);
|
|
2336
|
+
offset += chunk.length;
|
|
2337
|
+
}
|
|
2338
|
+
const buffer = data.buffer;
|
|
2288
2339
|
if (!tooLargeForCache) {
|
|
2289
|
-
await cache.set(cacheKey,
|
|
2340
|
+
await cache.set(cacheKey, buffer, etag, version);
|
|
2341
|
+
console.log(`[ModelCache] Cached: ${url} (${(buffer.byteLength / 1024 / 1024).toFixed(1)}MB)`);
|
|
2290
2342
|
}
|
|
2291
2343
|
span?.setAttributes({
|
|
2292
|
-
"fetch.size_bytes":
|
|
2293
|
-
"fetch.cached_to_indexeddb": !tooLargeForCache
|
|
2344
|
+
"fetch.size_bytes": buffer.byteLength,
|
|
2345
|
+
"fetch.cached_to_indexeddb": !tooLargeForCache,
|
|
2346
|
+
...attempt > 0 && { "fetch.retry_count": attempt }
|
|
2294
2347
|
});
|
|
2295
2348
|
span?.end();
|
|
2296
|
-
return
|
|
2297
|
-
}
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
if (
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
onProgress?.(loaded, total || loaded);
|
|
2307
|
-
}
|
|
2308
|
-
const data = new Uint8Array(loaded);
|
|
2309
|
-
let offset = 0;
|
|
2310
|
-
for (const chunk of chunks) {
|
|
2311
|
-
data.set(chunk, offset);
|
|
2312
|
-
offset += chunk.length;
|
|
2313
|
-
}
|
|
2314
|
-
const buffer = data.buffer;
|
|
2315
|
-
if (!tooLargeForCache) {
|
|
2316
|
-
await cache.set(cacheKey, buffer, etag, version);
|
|
2317
|
-
console.log(`[ModelCache] Cached: ${url} (${(buffer.byteLength / 1024 / 1024).toFixed(1)}MB)`);
|
|
2349
|
+
return buffer;
|
|
2350
|
+
} catch (error) {
|
|
2351
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
2352
|
+
if (options.signal?.aborted) {
|
|
2353
|
+
span?.endWithError(lastError);
|
|
2354
|
+
throw lastError;
|
|
2355
|
+
}
|
|
2356
|
+
if (attempt < maxRetries) {
|
|
2357
|
+
console.warn(`[ModelCache] Attempt ${attempt + 1} failed for ${url}: ${lastError.message}`);
|
|
2358
|
+
}
|
|
2318
2359
|
}
|
|
2319
|
-
span?.setAttributes({
|
|
2320
|
-
"fetch.size_bytes": buffer.byteLength,
|
|
2321
|
-
"fetch.cached_to_indexeddb": !tooLargeForCache
|
|
2322
|
-
});
|
|
2323
|
-
span?.end();
|
|
2324
|
-
return buffer;
|
|
2325
|
-
} catch (error) {
|
|
2326
|
-
span?.endWithError(error instanceof Error ? error : new Error(String(error)));
|
|
2327
|
-
throw error;
|
|
2328
2360
|
}
|
|
2361
|
+
span?.endWithError(lastError);
|
|
2362
|
+
throw lastError;
|
|
2329
2363
|
}
|
|
2330
2364
|
async function preloadModels(urls, onProgress) {
|
|
2331
2365
|
const cache = getModelCache();
|
|
@@ -2574,6 +2608,15 @@ function getSessionOptions(backend) {
|
|
|
2574
2608
|
graphOptimizationLevel: "all"
|
|
2575
2609
|
};
|
|
2576
2610
|
}
|
|
2611
|
+
function withTimeout(promise, ms, label) {
|
|
2612
|
+
return new Promise((resolve, reject) => {
|
|
2613
|
+
const timer = setTimeout(
|
|
2614
|
+
() => reject(new Error(`${label} timed out after ${ms}ms`)),
|
|
2615
|
+
ms
|
|
2616
|
+
);
|
|
2617
|
+
promise.then(resolve, reject).finally(() => clearTimeout(timer));
|
|
2618
|
+
});
|
|
2619
|
+
}
|
|
2577
2620
|
|
|
2578
2621
|
// src/inference/blendshapeUtils.ts
|
|
2579
2622
|
var LAM_BLENDSHAPES = [
|
|
@@ -2846,7 +2889,11 @@ var _Wav2Vec2Inference = class _Wav2Vec2Inference {
|
|
|
2846
2889
|
)
|
|
2847
2890
|
});
|
|
2848
2891
|
try {
|
|
2849
|
-
this.session = await
|
|
2892
|
+
this.session = await withTimeout(
|
|
2893
|
+
this.ort.InferenceSession.create(modelUrl, sessionOptions),
|
|
2894
|
+
18e4,
|
|
2895
|
+
"Wav2Vec2 InferenceSession.create (iOS URL pass-through)"
|
|
2896
|
+
);
|
|
2850
2897
|
} catch (sessionErr) {
|
|
2851
2898
|
logger3.error("iOS: InferenceSession.create() failed", {
|
|
2852
2899
|
error: sessionErr instanceof Error ? sessionErr.message : String(sessionErr),
|
|
@@ -3247,6 +3294,7 @@ var FullFacePipeline = class extends EventEmitter {
|
|
|
3247
3294
|
backend: options.lam,
|
|
3248
3295
|
sampleRate,
|
|
3249
3296
|
chunkSize,
|
|
3297
|
+
identityIndex: options.identityIndex,
|
|
3250
3298
|
onError: (error) => {
|
|
3251
3299
|
logger4.error("A2E inference error", { message: error.message, stack: error.stack });
|
|
3252
3300
|
this.emit("error", error);
|
|
@@ -3933,9 +3981,10 @@ var _SenseVoiceInference = class _SenseVoiceInference {
|
|
|
3933
3981
|
logger5.info("iOS: passing model URL directly to ORT (low-memory path)", {
|
|
3934
3982
|
modelUrl: this.config.modelUrl
|
|
3935
3983
|
});
|
|
3936
|
-
this.session = await
|
|
3937
|
-
this.config.modelUrl,
|
|
3938
|
-
|
|
3984
|
+
this.session = await withTimeout(
|
|
3985
|
+
this.ort.InferenceSession.create(this.config.modelUrl, sessionOptions),
|
|
3986
|
+
18e4,
|
|
3987
|
+
"SenseVoice InferenceSession.create (iOS URL pass-through)"
|
|
3939
3988
|
);
|
|
3940
3989
|
} else {
|
|
3941
3990
|
const cache = getModelCache();
|
|
@@ -4188,6 +4237,12 @@ var WORKER_SCRIPT = `
|
|
|
4188
4237
|
var ort = null;
|
|
4189
4238
|
var session = null;
|
|
4190
4239
|
var tokenMap = null;
|
|
4240
|
+
|
|
4241
|
+
function fetchWithTimeout(url, timeoutMs) {
|
|
4242
|
+
var controller = new AbortController();
|
|
4243
|
+
var timer = setTimeout(function() { controller.abort(); }, timeoutMs);
|
|
4244
|
+
return fetch(url, { signal: controller.signal }).finally(function() { clearTimeout(timer); });
|
|
4245
|
+
}
|
|
4191
4246
|
var negMean = null;
|
|
4192
4247
|
var invStddev = null;
|
|
4193
4248
|
var languageId = 0;
|
|
@@ -4631,7 +4686,7 @@ async function loadOrt(wasmPaths) {
|
|
|
4631
4686
|
var ortUrl = wasmPaths + 'ort.wasm.min.js';
|
|
4632
4687
|
|
|
4633
4688
|
// Load the script by fetching and executing it
|
|
4634
|
-
var response = await
|
|
4689
|
+
var response = await fetchWithTimeout(ortUrl, 30000);
|
|
4635
4690
|
var scriptText = await response.text();
|
|
4636
4691
|
|
|
4637
4692
|
// Create a blob URL for the script
|
|
@@ -4657,7 +4712,7 @@ async function loadOrt(wasmPaths) {
|
|
|
4657
4712
|
*/
|
|
4658
4713
|
async function loadModel(modelUrl, tokensUrl, isIOSDevice, lang, textNorm) {
|
|
4659
4714
|
// 1. Fetch and parse tokens.txt
|
|
4660
|
-
var tokensResponse = await
|
|
4715
|
+
var tokensResponse = await fetchWithTimeout(tokensUrl, 30000);
|
|
4661
4716
|
if (!tokensResponse.ok) {
|
|
4662
4717
|
throw new Error('Failed to fetch tokens.txt: ' + tokensResponse.status + ' ' + tokensResponse.statusText);
|
|
4663
4718
|
}
|
|
@@ -4680,7 +4735,7 @@ async function loadModel(modelUrl, tokensUrl, isIOSDevice, lang, textNorm) {
|
|
|
4680
4735
|
session = await ort.InferenceSession.create(modelUrl, sessionOptions);
|
|
4681
4736
|
} else {
|
|
4682
4737
|
// Desktop: fetch ArrayBuffer for potential caching
|
|
4683
|
-
var modelResponse = await
|
|
4738
|
+
var modelResponse = await fetchWithTimeout(modelUrl, 120000);
|
|
4684
4739
|
if (!modelResponse.ok) {
|
|
4685
4740
|
throw new Error('Failed to fetch model: ' + modelResponse.status + ' ' + modelResponse.statusText);
|
|
4686
4741
|
}
|
|
@@ -5191,6 +5246,12 @@ var WORKER_SCRIPT2 = `
|
|
|
5191
5246
|
|
|
5192
5247
|
var ort = null;
|
|
5193
5248
|
|
|
5249
|
+
function fetchWithTimeout(url, timeoutMs) {
|
|
5250
|
+
var controller = new AbortController();
|
|
5251
|
+
var timer = setTimeout(function() { controller.abort(); }, timeoutMs);
|
|
5252
|
+
return fetch(url, { signal: controller.signal }).finally(function() { clearTimeout(timer); });
|
|
5253
|
+
}
|
|
5254
|
+
|
|
5194
5255
|
// SenseVoice state
|
|
5195
5256
|
var svSession = null;
|
|
5196
5257
|
var svTokenMap = null;
|
|
@@ -5505,7 +5566,7 @@ function symmetrizeBlendshapes(frame) {
|
|
|
5505
5566
|
async function loadOrt(wasmPaths, isIOSDevice) {
|
|
5506
5567
|
if (ort) return;
|
|
5507
5568
|
var ortUrl = wasmPaths + 'ort.wasm.min.js';
|
|
5508
|
-
var response = await
|
|
5569
|
+
var response = await fetchWithTimeout(ortUrl, 30000);
|
|
5509
5570
|
var scriptText = await response.text();
|
|
5510
5571
|
var blob = new Blob([scriptText], { type: 'application/javascript' });
|
|
5511
5572
|
var blobUrl = URL.createObjectURL(blob);
|
|
@@ -5523,7 +5584,7 @@ async function loadOrt(wasmPaths, isIOSDevice) {
|
|
|
5523
5584
|
// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
|
|
5524
5585
|
|
|
5525
5586
|
async function svLoad(msg) {
|
|
5526
|
-
var tokensResponse = await
|
|
5587
|
+
var tokensResponse = await fetchWithTimeout(msg.tokensUrl, 30000);
|
|
5527
5588
|
if (!tokensResponse.ok) throw new Error('Failed to fetch tokens.txt: ' + tokensResponse.status);
|
|
5528
5589
|
var tokensText = await tokensResponse.text();
|
|
5529
5590
|
svTokenMap = parseTokensFile(tokensText);
|
|
@@ -5534,7 +5595,7 @@ async function svLoad(msg) {
|
|
|
5534
5595
|
if (msg.isIOS) {
|
|
5535
5596
|
svSession = await ort.InferenceSession.create(msg.modelUrl, sessionOptions);
|
|
5536
5597
|
} else {
|
|
5537
|
-
var modelResponse = await
|
|
5598
|
+
var modelResponse = await fetchWithTimeout(msg.modelUrl, 120000);
|
|
5538
5599
|
if (!modelResponse.ok) throw new Error('Failed to fetch model: ' + modelResponse.status);
|
|
5539
5600
|
var modelBuffer = await modelResponse.arrayBuffer();
|
|
5540
5601
|
svSession = await ort.InferenceSession.create(new Uint8Array(modelBuffer), sessionOptions);
|
|
@@ -5609,11 +5670,11 @@ async function cpuLoad(msg) {
|
|
|
5609
5670
|
}
|
|
5610
5671
|
cpuSession = await ort.InferenceSession.create(msg.modelUrl, sessionOptions);
|
|
5611
5672
|
} else {
|
|
5612
|
-
var graphResponse = await
|
|
5673
|
+
var graphResponse = await fetchWithTimeout(msg.modelUrl, 120000);
|
|
5613
5674
|
if (!graphResponse.ok) throw new Error('Failed to fetch model graph: ' + graphResponse.status);
|
|
5614
5675
|
var graphBuffer = await graphResponse.arrayBuffer();
|
|
5615
5676
|
if (msg.externalDataUrl && dataFilename) {
|
|
5616
|
-
var dataResponse = await
|
|
5677
|
+
var dataResponse = await fetchWithTimeout(msg.externalDataUrl, 120000);
|
|
5617
5678
|
if (!dataResponse.ok) throw new Error('Failed to fetch external data: ' + dataResponse.status);
|
|
5618
5679
|
var dataBuffer = await dataResponse.arrayBuffer();
|
|
5619
5680
|
sessionOptions.externalData = [{ path: dataFilename, data: new Uint8Array(dataBuffer) }];
|
|
@@ -5665,7 +5726,7 @@ async function vadLoad(msg) {
|
|
|
5665
5726
|
vadChunkSize = vadSampleRate === 16000 ? 512 : 256;
|
|
5666
5727
|
vadContextSize = vadSampleRate === 16000 ? 64 : 32;
|
|
5667
5728
|
|
|
5668
|
-
var response = await
|
|
5729
|
+
var response = await fetchWithTimeout(msg.modelUrl, 60000);
|
|
5669
5730
|
if (!response.ok) throw new Error('Failed to fetch VAD model: ' + response.status);
|
|
5670
5731
|
var modelBuffer = await response.arrayBuffer();
|
|
5671
5732
|
vadSession = await ort.InferenceSession.create(new Uint8Array(modelBuffer), {
|
|
@@ -6513,7 +6574,11 @@ var _Wav2ArkitCpuInference = class _Wav2ArkitCpuInference {
|
|
|
6513
6574
|
// URL string — ORT fetches directly into WASM
|
|
6514
6575
|
}];
|
|
6515
6576
|
}
|
|
6516
|
-
this.session = await
|
|
6577
|
+
this.session = await withTimeout(
|
|
6578
|
+
this.ort.InferenceSession.create(modelUrl, sessionOptions),
|
|
6579
|
+
18e4,
|
|
6580
|
+
"Wav2ArkitCpu InferenceSession.create (iOS URL pass-through)"
|
|
6581
|
+
);
|
|
6517
6582
|
} else {
|
|
6518
6583
|
const cache = getModelCache();
|
|
6519
6584
|
const isCached = await cache.has(modelUrl);
|
|
@@ -6781,6 +6846,12 @@ var WORKER_SCRIPT3 = `
|
|
|
6781
6846
|
var ort = null;
|
|
6782
6847
|
var session = null;
|
|
6783
6848
|
|
|
6849
|
+
function fetchWithTimeout(url, timeoutMs) {
|
|
6850
|
+
var controller = new AbortController();
|
|
6851
|
+
var timer = setTimeout(function() { controller.abort(); }, timeoutMs);
|
|
6852
|
+
return fetch(url, { signal: controller.signal }).finally(function() { clearTimeout(timer); });
|
|
6853
|
+
}
|
|
6854
|
+
|
|
6784
6855
|
// Precomputed symmetric index pairs from LAM_BLENDSHAPES alphabetical ordering
|
|
6785
6856
|
// Used to average left/right blendshape pairs for symmetrized output
|
|
6786
6857
|
const SYMMETRIC_INDEX_PAIRS = [
|
|
@@ -6830,7 +6901,7 @@ async function loadOrt(wasmPaths) {
|
|
|
6830
6901
|
const ortUrl = wasmPaths + 'ort.wasm.min.js';
|
|
6831
6902
|
|
|
6832
6903
|
// Load the script by fetching and executing it
|
|
6833
|
-
const response = await
|
|
6904
|
+
const response = await fetchWithTimeout(ortUrl, 30000);
|
|
6834
6905
|
const scriptText = await response.text();
|
|
6835
6906
|
|
|
6836
6907
|
// Create a blob URL for the script
|
|
@@ -6872,7 +6943,7 @@ async function loadModel(modelUrl, externalDataUrl, isIOS) {
|
|
|
6872
6943
|
session = await ort.InferenceSession.create(modelUrl, sessionOptions);
|
|
6873
6944
|
} else {
|
|
6874
6945
|
// Desktop: fetch model graph as ArrayBuffer
|
|
6875
|
-
const graphResponse = await
|
|
6946
|
+
const graphResponse = await fetchWithTimeout(modelUrl, 120000);
|
|
6876
6947
|
if (!graphResponse.ok) {
|
|
6877
6948
|
throw new Error('Failed to fetch model graph: ' + graphResponse.status + ' ' + graphResponse.statusText);
|
|
6878
6949
|
}
|
|
@@ -6880,7 +6951,7 @@ async function loadModel(modelUrl, externalDataUrl, isIOS) {
|
|
|
6880
6951
|
|
|
6881
6952
|
// Fetch external data file if present
|
|
6882
6953
|
if (externalDataUrl && dataFilename) {
|
|
6883
|
-
const dataResponse = await
|
|
6954
|
+
const dataResponse = await fetchWithTimeout(externalDataUrl, 120000);
|
|
6884
6955
|
if (!dataResponse.ok) {
|
|
6885
6956
|
throw new Error('Failed to fetch external data: ' + dataResponse.status + ' ' + dataResponse.statusText);
|
|
6886
6957
|
}
|
|
@@ -8015,6 +8086,13 @@ var WORKER_SCRIPT4 = `
|
|
|
8015
8086
|
|
|
8016
8087
|
var ort = null;
|
|
8017
8088
|
var session = null;
|
|
8089
|
+
|
|
8090
|
+
function fetchWithTimeout(url, timeoutMs) {
|
|
8091
|
+
var controller = new AbortController();
|
|
8092
|
+
var timer = setTimeout(function() { controller.abort(); }, timeoutMs);
|
|
8093
|
+
return fetch(url, { signal: controller.signal }).finally(function() { clearTimeout(timer); });
|
|
8094
|
+
}
|
|
8095
|
+
|
|
8018
8096
|
var sampleRate = 16000;
|
|
8019
8097
|
var chunkSize = 512;
|
|
8020
8098
|
var contextSize = 64;
|
|
@@ -8030,7 +8108,7 @@ async function loadOrt(wasmPaths) {
|
|
|
8030
8108
|
const ortUrl = wasmPaths + 'ort.wasm.min.js';
|
|
8031
8109
|
|
|
8032
8110
|
// Load the script by fetching and executing it
|
|
8033
|
-
const response = await
|
|
8111
|
+
const response = await fetchWithTimeout(ortUrl, 30000);
|
|
8034
8112
|
const scriptText = await response.text();
|
|
8035
8113
|
|
|
8036
8114
|
// Create a blob URL for the script
|
|
@@ -8060,7 +8138,7 @@ async function loadModel(modelUrl, sr) {
|
|
|
8060
8138
|
contextSize = sr === 16000 ? 64 : 32;
|
|
8061
8139
|
|
|
8062
8140
|
// Fetch model data
|
|
8063
|
-
const response = await
|
|
8141
|
+
const response = await fetchWithTimeout(modelUrl, 60000);
|
|
8064
8142
|
if (!response.ok) {
|
|
8065
8143
|
throw new Error('Failed to fetch model: ' + response.status + ' ' + response.statusText);
|
|
8066
8144
|
}
|