@runanywhere/web 0.1.0-beta.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/README.md +795 -0
- package/dist/Foundation/ErrorTypes.d.ts +61 -0
- package/dist/Foundation/ErrorTypes.d.ts.map +1 -0
- package/dist/Foundation/ErrorTypes.js +90 -0
- package/dist/Foundation/ErrorTypes.js.map +1 -0
- package/dist/Foundation/EventBus.d.ts +171 -0
- package/dist/Foundation/EventBus.d.ts.map +1 -0
- package/dist/Foundation/EventBus.js +113 -0
- package/dist/Foundation/EventBus.js.map +1 -0
- package/dist/Foundation/PlatformAdapter.d.ts +101 -0
- package/dist/Foundation/PlatformAdapter.d.ts.map +1 -0
- package/dist/Foundation/PlatformAdapter.js +417 -0
- package/dist/Foundation/PlatformAdapter.js.map +1 -0
- package/dist/Foundation/SDKLogger.d.ts +33 -0
- package/dist/Foundation/SDKLogger.d.ts.map +1 -0
- package/dist/Foundation/SDKLogger.js +82 -0
- package/dist/Foundation/SDKLogger.js.map +1 -0
- package/dist/Foundation/SherpaONNXBridge.d.ts +134 -0
- package/dist/Foundation/SherpaONNXBridge.d.ts.map +1 -0
- package/dist/Foundation/SherpaONNXBridge.js +332 -0
- package/dist/Foundation/SherpaONNXBridge.js.map +1 -0
- package/dist/Foundation/StructOffsets.d.ts +147 -0
- package/dist/Foundation/StructOffsets.d.ts.map +1 -0
- package/dist/Foundation/StructOffsets.js +161 -0
- package/dist/Foundation/StructOffsets.js.map +1 -0
- package/dist/Foundation/WASMBridge.d.ts +241 -0
- package/dist/Foundation/WASMBridge.d.ts.map +1 -0
- package/dist/Foundation/WASMBridge.js +393 -0
- package/dist/Foundation/WASMBridge.js.map +1 -0
- package/dist/Infrastructure/ArchiveUtility.d.ts +25 -0
- package/dist/Infrastructure/ArchiveUtility.d.ts.map +1 -0
- package/dist/Infrastructure/ArchiveUtility.js +139 -0
- package/dist/Infrastructure/ArchiveUtility.js.map +1 -0
- package/dist/Infrastructure/AudioCapture.d.ts +87 -0
- package/dist/Infrastructure/AudioCapture.d.ts.map +1 -0
- package/dist/Infrastructure/AudioCapture.js +231 -0
- package/dist/Infrastructure/AudioCapture.js.map +1 -0
- package/dist/Infrastructure/AudioPlayback.d.ts +53 -0
- package/dist/Infrastructure/AudioPlayback.d.ts.map +1 -0
- package/dist/Infrastructure/AudioPlayback.js +117 -0
- package/dist/Infrastructure/AudioPlayback.js.map +1 -0
- package/dist/Infrastructure/DeviceCapabilities.d.ts +39 -0
- package/dist/Infrastructure/DeviceCapabilities.d.ts.map +1 -0
- package/dist/Infrastructure/DeviceCapabilities.js +111 -0
- package/dist/Infrastructure/DeviceCapabilities.js.map +1 -0
- package/dist/Infrastructure/ExtensionRegistry.d.ts +30 -0
- package/dist/Infrastructure/ExtensionRegistry.d.ts.map +1 -0
- package/dist/Infrastructure/ExtensionRegistry.js +41 -0
- package/dist/Infrastructure/ExtensionRegistry.js.map +1 -0
- package/dist/Infrastructure/ModelDownloader.d.ts +98 -0
- package/dist/Infrastructure/ModelDownloader.d.ts.map +1 -0
- package/dist/Infrastructure/ModelDownloader.js +431 -0
- package/dist/Infrastructure/ModelDownloader.js.map +1 -0
- package/dist/Infrastructure/ModelLoaderTypes.d.ts +34 -0
- package/dist/Infrastructure/ModelLoaderTypes.d.ts.map +1 -0
- package/dist/Infrastructure/ModelLoaderTypes.js +12 -0
- package/dist/Infrastructure/ModelLoaderTypes.js.map +1 -0
- package/dist/Infrastructure/ModelManager.d.ts +219 -0
- package/dist/Infrastructure/ModelManager.d.ts.map +1 -0
- package/dist/Infrastructure/ModelManager.js +885 -0
- package/dist/Infrastructure/ModelManager.js.map +1 -0
- package/dist/Infrastructure/ModelRegistry.d.ts +131 -0
- package/dist/Infrastructure/ModelRegistry.d.ts.map +1 -0
- package/dist/Infrastructure/ModelRegistry.js +122 -0
- package/dist/Infrastructure/ModelRegistry.js.map +1 -0
- package/dist/Infrastructure/OPFSStorage.d.ts +143 -0
- package/dist/Infrastructure/OPFSStorage.d.ts.map +1 -0
- package/dist/Infrastructure/OPFSStorage.js +330 -0
- package/dist/Infrastructure/OPFSStorage.js.map +1 -0
- package/dist/Infrastructure/VLMWorkerBridge.d.ts +211 -0
- package/dist/Infrastructure/VLMWorkerBridge.d.ts.map +1 -0
- package/dist/Infrastructure/VLMWorkerBridge.js +264 -0
- package/dist/Infrastructure/VLMWorkerBridge.js.map +1 -0
- package/dist/Infrastructure/VLMWorkerRuntime.d.ts +38 -0
- package/dist/Infrastructure/VLMWorkerRuntime.d.ts.map +1 -0
- package/dist/Infrastructure/VLMWorkerRuntime.js +503 -0
- package/dist/Infrastructure/VLMWorkerRuntime.js.map +1 -0
- package/dist/Infrastructure/VideoCapture.d.ts +118 -0
- package/dist/Infrastructure/VideoCapture.d.ts.map +1 -0
- package/dist/Infrastructure/VideoCapture.js +207 -0
- package/dist/Infrastructure/VideoCapture.js.map +1 -0
- package/dist/Public/Extensions/DiffusionTypes.d.ts +64 -0
- package/dist/Public/Extensions/DiffusionTypes.d.ts.map +1 -0
- package/dist/Public/Extensions/DiffusionTypes.js +28 -0
- package/dist/Public/Extensions/DiffusionTypes.js.map +1 -0
- package/dist/Public/Extensions/EmbeddingsTypes.d.ts +33 -0
- package/dist/Public/Extensions/EmbeddingsTypes.d.ts.map +1 -0
- package/dist/Public/Extensions/EmbeddingsTypes.js +13 -0
- package/dist/Public/Extensions/EmbeddingsTypes.js.map +1 -0
- package/dist/Public/Extensions/RunAnywhere+Diffusion.d.ts +44 -0
- package/dist/Public/Extensions/RunAnywhere+Diffusion.d.ts.map +1 -0
- package/dist/Public/Extensions/RunAnywhere+Diffusion.js +189 -0
- package/dist/Public/Extensions/RunAnywhere+Diffusion.js.map +1 -0
- package/dist/Public/Extensions/RunAnywhere+Embeddings.d.ts +56 -0
- package/dist/Public/Extensions/RunAnywhere+Embeddings.d.ts.map +1 -0
- package/dist/Public/Extensions/RunAnywhere+Embeddings.js +240 -0
- package/dist/Public/Extensions/RunAnywhere+Embeddings.js.map +1 -0
- package/dist/Public/Extensions/RunAnywhere+ModelManagement.d.ts +53 -0
- package/dist/Public/Extensions/RunAnywhere+ModelManagement.d.ts.map +1 -0
- package/dist/Public/Extensions/RunAnywhere+ModelManagement.js +153 -0
- package/dist/Public/Extensions/RunAnywhere+ModelManagement.js.map +1 -0
- package/dist/Public/Extensions/RunAnywhere+STT.d.ts +95 -0
- package/dist/Public/Extensions/RunAnywhere+STT.d.ts.map +1 -0
- package/dist/Public/Extensions/RunAnywhere+STT.js +417 -0
- package/dist/Public/Extensions/RunAnywhere+STT.js.map +1 -0
- package/dist/Public/Extensions/RunAnywhere+StructuredOutput.d.ts +69 -0
- package/dist/Public/Extensions/RunAnywhere+StructuredOutput.d.ts.map +1 -0
- package/dist/Public/Extensions/RunAnywhere+StructuredOutput.js +196 -0
- package/dist/Public/Extensions/RunAnywhere+StructuredOutput.js.map +1 -0
- package/dist/Public/Extensions/RunAnywhere+TTS.d.ts +55 -0
- package/dist/Public/Extensions/RunAnywhere+TTS.d.ts.map +1 -0
- package/dist/Public/Extensions/RunAnywhere+TTS.js +253 -0
- package/dist/Public/Extensions/RunAnywhere+TTS.js.map +1 -0
- package/dist/Public/Extensions/RunAnywhere+TextGeneration.d.ts +80 -0
- package/dist/Public/Extensions/RunAnywhere+TextGeneration.d.ts.map +1 -0
- package/dist/Public/Extensions/RunAnywhere+TextGeneration.js +436 -0
- package/dist/Public/Extensions/RunAnywhere+TextGeneration.js.map +1 -0
- package/dist/Public/Extensions/RunAnywhere+ToolCalling.d.ts +82 -0
- package/dist/Public/Extensions/RunAnywhere+ToolCalling.d.ts.map +1 -0
- package/dist/Public/Extensions/RunAnywhere+ToolCalling.js +576 -0
- package/dist/Public/Extensions/RunAnywhere+ToolCalling.js.map +1 -0
- package/dist/Public/Extensions/RunAnywhere+VAD.d.ts +70 -0
- package/dist/Public/Extensions/RunAnywhere+VAD.d.ts.map +1 -0
- package/dist/Public/Extensions/RunAnywhere+VAD.js +231 -0
- package/dist/Public/Extensions/RunAnywhere+VAD.js.map +1 -0
- package/dist/Public/Extensions/RunAnywhere+VLM.d.ts +58 -0
- package/dist/Public/Extensions/RunAnywhere+VLM.d.ts.map +1 -0
- package/dist/Public/Extensions/RunAnywhere+VLM.js +262 -0
- package/dist/Public/Extensions/RunAnywhere+VLM.js.map +1 -0
- package/dist/Public/Extensions/RunAnywhere+VoiceAgent.d.ts +49 -0
- package/dist/Public/Extensions/RunAnywhere+VoiceAgent.d.ts.map +1 -0
- package/dist/Public/Extensions/RunAnywhere+VoiceAgent.js +222 -0
- package/dist/Public/Extensions/RunAnywhere+VoiceAgent.js.map +1 -0
- package/dist/Public/Extensions/RunAnywhere+VoicePipeline.d.ts +63 -0
- package/dist/Public/Extensions/RunAnywhere+VoicePipeline.d.ts.map +1 -0
- package/dist/Public/Extensions/RunAnywhere+VoicePipeline.js +168 -0
- package/dist/Public/Extensions/RunAnywhere+VoicePipeline.js.map +1 -0
- package/dist/Public/Extensions/STTTypes.d.ts +53 -0
- package/dist/Public/Extensions/STTTypes.d.ts.map +1 -0
- package/dist/Public/Extensions/STTTypes.js +16 -0
- package/dist/Public/Extensions/STTTypes.js.map +1 -0
- package/dist/Public/Extensions/TTSTypes.d.ts +31 -0
- package/dist/Public/Extensions/TTSTypes.d.ts.map +1 -0
- package/dist/Public/Extensions/TTSTypes.js +3 -0
- package/dist/Public/Extensions/TTSTypes.js.map +1 -0
- package/dist/Public/Extensions/ToolCallingTypes.d.ts +78 -0
- package/dist/Public/Extensions/ToolCallingTypes.d.ts.map +1 -0
- package/dist/Public/Extensions/ToolCallingTypes.js +8 -0
- package/dist/Public/Extensions/ToolCallingTypes.js.map +1 -0
- package/dist/Public/Extensions/VADTypes.d.ts +30 -0
- package/dist/Public/Extensions/VADTypes.d.ts.map +1 -0
- package/dist/Public/Extensions/VADTypes.js +8 -0
- package/dist/Public/Extensions/VADTypes.js.map +1 -0
- package/dist/Public/Extensions/VLMTypes.d.ts +56 -0
- package/dist/Public/Extensions/VLMTypes.d.ts.map +1 -0
- package/dist/Public/Extensions/VLMTypes.js +24 -0
- package/dist/Public/Extensions/VLMTypes.js.map +1 -0
- package/dist/Public/Extensions/VoiceAgentTypes.d.ts +42 -0
- package/dist/Public/Extensions/VoiceAgentTypes.d.ts.map +1 -0
- package/dist/Public/Extensions/VoiceAgentTypes.js +12 -0
- package/dist/Public/Extensions/VoiceAgentTypes.js.map +1 -0
- package/dist/Public/Extensions/VoicePipelineTypes.d.ts +69 -0
- package/dist/Public/Extensions/VoicePipelineTypes.d.ts.map +1 -0
- package/dist/Public/Extensions/VoicePipelineTypes.js +9 -0
- package/dist/Public/Extensions/VoicePipelineTypes.js.map +1 -0
- package/dist/Public/RunAnywhere.d.ts +121 -0
- package/dist/Public/RunAnywhere.d.ts.map +1 -0
- package/dist/Public/RunAnywhere.js +332 -0
- package/dist/Public/RunAnywhere.js.map +1 -0
- package/dist/index.d.ts +67 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +53 -0
- package/dist/index.js.map +1 -0
- package/dist/types/LLMTypes.d.ts +48 -0
- package/dist/types/LLMTypes.d.ts.map +1 -0
- package/dist/types/LLMTypes.js +8 -0
- package/dist/types/LLMTypes.js.map +1 -0
- package/dist/types/enums.d.ts +144 -0
- package/dist/types/enums.d.ts.map +1 -0
- package/dist/types/enums.js +159 -0
- package/dist/types/enums.js.map +1 -0
- package/dist/types/index.d.ts +9 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +8 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/models.d.ts +154 -0
- package/dist/types/models.d.ts.map +1 -0
- package/dist/types/models.js +8 -0
- package/dist/types/models.js.map +1 -0
- package/dist/workers/vlm-worker.d.ts +9 -0
- package/dist/workers/vlm-worker.d.ts.map +1 -0
- package/dist/workers/vlm-worker.js +10 -0
- package/dist/workers/vlm-worker.js.map +1 -0
- package/package.json +62 -0
- package/wasm/racommons-webgpu.js +156 -0
- package/wasm/racommons-webgpu.wasm +0 -0
- package/wasm/racommons.js +126 -0
- package/wasm/racommons.wasm +0 -0
- package/wasm/sherpa/sherpa-onnx-asr.js +1538 -0
- package/wasm/sherpa/sherpa-onnx-glue-original.js +19 -0
- package/wasm/sherpa/sherpa-onnx-glue.js +17 -0
- package/wasm/sherpa/sherpa-onnx-tts.js +657 -0
- package/wasm/sherpa/sherpa-onnx-vad.js +337 -0
- package/wasm/sherpa/sherpa-onnx-wave.js +88 -0
- package/wasm/sherpa/sherpa-onnx.wasm +0 -0
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RunAnywhere Web SDK - WASM Bridge
|
|
3
|
+
*
|
|
4
|
+
* Loads the RACommons WASM module and provides typed wrappers
|
|
5
|
+
* around the C API functions. This is the web equivalent of:
|
|
6
|
+
* - CppBridge.swift (iOS)
|
|
7
|
+
* - CppBridge.kt (Kotlin/Android)
|
|
8
|
+
* - dart_bridge.dart (Flutter)
|
|
9
|
+
* - HybridRunAnywhereCore.cpp (React Native)
|
|
10
|
+
*/
|
|
11
|
+
import { SDKError, SDKErrorCode } from './ErrorTypes';
|
|
12
|
+
import { SDKLogger } from './SDKLogger';
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
// WASM Bridge
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
const logger = new SDKLogger('WASMBridge');
|
|
17
|
+
/**
|
|
18
|
+
* WASMBridge - Loads and manages the RACommons WASM module.
|
|
19
|
+
*
|
|
20
|
+
* Singleton that provides access to all RACommons C API functions
|
|
21
|
+
* compiled to WebAssembly. This is the central point through which
|
|
22
|
+
* all SDK operations flow, identical to CppBridge on mobile platforms.
|
|
23
|
+
*/
|
|
24
|
+
export class WASMBridge {
|
|
25
|
+
static _instance = null;
|
|
26
|
+
_module = null;
|
|
27
|
+
_loaded = false;
|
|
28
|
+
_loading = null;
|
|
29
|
+
_accelerationMode = 'cpu';
|
|
30
|
+
/** The URL that was used to load the WASM glue JS (for worker reuse). */
|
|
31
|
+
_loadedModuleUrl = null;
|
|
32
|
+
static get shared() {
|
|
33
|
+
if (!WASMBridge._instance) {
|
|
34
|
+
WASMBridge._instance = new WASMBridge();
|
|
35
|
+
}
|
|
36
|
+
return WASMBridge._instance;
|
|
37
|
+
}
|
|
38
|
+
/** Whether the WASM module is loaded */
|
|
39
|
+
get isLoaded() {
|
|
40
|
+
return this._loaded && this._module !== null;
|
|
41
|
+
}
|
|
42
|
+
/** Get the raw Emscripten module (throws if not loaded) */
|
|
43
|
+
get module() {
|
|
44
|
+
if (!this._module) {
|
|
45
|
+
throw SDKError.wasmNotLoaded();
|
|
46
|
+
}
|
|
47
|
+
return this._module;
|
|
48
|
+
}
|
|
49
|
+
/** The hardware acceleration mode in use (webgpu or cpu). */
|
|
50
|
+
get accelerationMode() {
|
|
51
|
+
return this._accelerationMode;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* The URL of the WASM glue JS that was successfully loaded.
|
|
55
|
+
* Web Workers should use this URL to load the same WASM variant
|
|
56
|
+
* (WebGPU or CPU) that the main thread is using.
|
|
57
|
+
*
|
|
58
|
+
* Returns `null` if `load()` has not been called yet.
|
|
59
|
+
*/
|
|
60
|
+
get workerWasmUrl() {
|
|
61
|
+
return this._loadedModuleUrl;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Load the RACommons WASM module.
|
|
65
|
+
*
|
|
66
|
+
* Detects WebGPU at init time and loads the appropriate build variant:
|
|
67
|
+
* - `racommons-webgpu.js` when WebGPU + JSPI are available
|
|
68
|
+
* - `racommons.js` as the CPU-only fallback
|
|
69
|
+
*
|
|
70
|
+
* Safe to call concurrently -- only the first caller triggers the actual
|
|
71
|
+
* load; subsequent callers await the same in-flight promise.
|
|
72
|
+
*
|
|
73
|
+
* @param wasmUrl - URL to the CPU-only racommons.js glue file.
|
|
74
|
+
* @param webgpuWasmUrl - URL to the WebGPU racommons-webgpu.js glue file.
|
|
75
|
+
* @param acceleration - Force a specific mode ('auto' detects, 'webgpu' forces GPU, 'cpu' forces CPU).
|
|
76
|
+
*/
|
|
77
|
+
async load(wasmUrl, webgpuWasmUrl, acceleration = 'auto') {
|
|
78
|
+
if (this._loaded) {
|
|
79
|
+
logger.debug('WASM module already loaded');
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
// Prevent duplicate loading -- return the in-flight promise
|
|
83
|
+
if (this._loading) {
|
|
84
|
+
await this._loading;
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
this._loading = this._doLoad(wasmUrl, webgpuWasmUrl, acceleration);
|
|
88
|
+
try {
|
|
89
|
+
await this._loading;
|
|
90
|
+
}
|
|
91
|
+
finally {
|
|
92
|
+
this._loading = null;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Internal load implementation.
|
|
97
|
+
* Separated from `load()` so the concurrent-load guard can wrap it.
|
|
98
|
+
*/
|
|
99
|
+
async _doLoad(wasmUrl, webgpuWasmUrl, acceleration = 'auto') {
|
|
100
|
+
logger.info('Loading RACommons WASM module...');
|
|
101
|
+
try {
|
|
102
|
+
// Determine whether to use the WebGPU variant
|
|
103
|
+
const useWebGPU = await this.resolveAcceleration(acceleration);
|
|
104
|
+
this._accelerationMode = useWebGPU ? 'webgpu' : 'cpu';
|
|
105
|
+
// Select the correct module URL
|
|
106
|
+
const moduleUrl = useWebGPU
|
|
107
|
+
? (webgpuWasmUrl ?? new URL('../../wasm/racommons-webgpu.js', import.meta.url).href)
|
|
108
|
+
: (wasmUrl ?? new URL('../../wasm/racommons.js', import.meta.url).href);
|
|
109
|
+
this._loadedModuleUrl = moduleUrl;
|
|
110
|
+
logger.info(`Acceleration mode: ${this._accelerationMode} (loading ${useWebGPU ? 'racommons-webgpu' : 'racommons'})`);
|
|
111
|
+
// Safety-net probe: verify the WebGPU glue JS was compiled with
|
|
112
|
+
// JSPI support. A JSPI-enabled build contains "WebAssembly.promising"
|
|
113
|
+
// which wraps exported WASM functions so they can suspend during
|
|
114
|
+
// async WebGPU operations. If the marker is absent the build is
|
|
115
|
+
// either outdated or misconfigured and generation would crash with
|
|
116
|
+
// "RuntimeError: unreachable". Fall back to CPU in that case.
|
|
117
|
+
if (useWebGPU && acceleration === 'auto') {
|
|
118
|
+
try {
|
|
119
|
+
const probeResp = await fetch(moduleUrl);
|
|
120
|
+
const probeText = await probeResp.text();
|
|
121
|
+
if (!probeText.includes('WebAssembly.promising')) {
|
|
122
|
+
logger.warning('WebGPU WASM build lacks JSPI support (WebAssembly.promising not found). Falling back to CPU.');
|
|
123
|
+
return this._doLoad(wasmUrl, undefined, 'cpu');
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
// If the probe fails, proceed with WebGPU and let runtime errors
|
|
128
|
+
// surface normally.
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
// Dynamic import of the Emscripten glue JS
|
|
132
|
+
// The glue file exports a factory function: createRACommonsModule()
|
|
133
|
+
const { default: createModule } = await import(/* @vite-ignore */ moduleUrl);
|
|
134
|
+
// Instantiate the WASM module
|
|
135
|
+
this._module = await createModule({
|
|
136
|
+
// Emscripten module overrides
|
|
137
|
+
print: (text) => logger.info(text),
|
|
138
|
+
printErr: (text) => logger.error(text),
|
|
139
|
+
});
|
|
140
|
+
// Verify module loaded correctly.
|
|
141
|
+
// With JSPI builds some exports may return Promises, so await just
|
|
142
|
+
// in case _rac_wasm_ping was wrapped with WebAssembly.promising.
|
|
143
|
+
const pingRaw = this._module._rac_wasm_ping();
|
|
144
|
+
const pingResult = (typeof pingRaw === 'object' && pingRaw !== null && 'then' in pingRaw)
|
|
145
|
+
? await pingRaw
|
|
146
|
+
: pingRaw;
|
|
147
|
+
if (pingResult !== 42) {
|
|
148
|
+
throw new Error(`WASM ping failed: expected 42, got ${pingResult}`);
|
|
149
|
+
}
|
|
150
|
+
this._loaded = true;
|
|
151
|
+
logger.info(`RACommons WASM module loaded successfully (${this._accelerationMode})`);
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
// If WebGPU load failed, fall back to CPU automatically
|
|
155
|
+
if (this._accelerationMode === 'webgpu' && acceleration === 'auto') {
|
|
156
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
157
|
+
logger.warning(`WebGPU WASM module failed to load (${reason}), falling back to CPU`);
|
|
158
|
+
this._accelerationMode = 'cpu';
|
|
159
|
+
this._module = null;
|
|
160
|
+
this._loaded = false;
|
|
161
|
+
return this._doLoad(wasmUrl, undefined, 'cpu');
|
|
162
|
+
}
|
|
163
|
+
this._module = null;
|
|
164
|
+
this._loaded = false;
|
|
165
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
166
|
+
logger.error(`Failed to load WASM module: ${message}`);
|
|
167
|
+
throw new SDKError(SDKErrorCode.WASMLoadFailed, `Failed to load WASM module: ${message}`);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
// -----------------------------------------------------------------------
|
|
171
|
+
// WebGPU Detection
|
|
172
|
+
// -----------------------------------------------------------------------
|
|
173
|
+
/**
|
|
174
|
+
* Determine whether to use WebGPU based on the acceleration preference
|
|
175
|
+
* and actual browser capability.
|
|
176
|
+
*/
|
|
177
|
+
async resolveAcceleration(preference) {
|
|
178
|
+
if (preference === 'cpu')
|
|
179
|
+
return false;
|
|
180
|
+
const hasWebGPU = await WASMBridge.detectWebGPU();
|
|
181
|
+
if (preference === 'webgpu' && !hasWebGPU) {
|
|
182
|
+
logger.warning('WebGPU requested but not available; falling back to CPU');
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
if (!hasWebGPU)
|
|
186
|
+
return false;
|
|
187
|
+
// The WebGPU WASM module is compiled with JSPI (WebAssembly JavaScript
|
|
188
|
+
// Promise Integration). If the browser doesn't expose the JSPI APIs
|
|
189
|
+
// the module will fail to instantiate.
|
|
190
|
+
const hasJSPI = WASMBridge.detectJSPI();
|
|
191
|
+
if (!hasJSPI) {
|
|
192
|
+
logger.warning('WebGPU available but browser lacks JSPI support (WebAssembly.promising). ' +
|
|
193
|
+
'Update Chrome to 128+ or enable chrome://flags/#experimental-wasm-jspi. Falling back to CPU.');
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Probe for a functional WebGPU adapter.
|
|
200
|
+
* Returns true only when the browser exposes navigator.gpu AND
|
|
201
|
+
* a valid adapter can be obtained.
|
|
202
|
+
*/
|
|
203
|
+
static async detectWebGPU() {
|
|
204
|
+
if (typeof navigator === 'undefined' || !('gpu' in navigator))
|
|
205
|
+
return false;
|
|
206
|
+
try {
|
|
207
|
+
const gpu = navigator.gpu;
|
|
208
|
+
const adapter = await gpu?.requestAdapter();
|
|
209
|
+
return adapter !== null;
|
|
210
|
+
}
|
|
211
|
+
catch {
|
|
212
|
+
return false;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Detect JSPI (JavaScript Promise Integration) support.
|
|
217
|
+
* The WebGPU WASM module requires WebAssembly.promising and
|
|
218
|
+
* WebAssembly.Suspending to suspend during async GPU operations.
|
|
219
|
+
*/
|
|
220
|
+
static detectJSPI() {
|
|
221
|
+
try {
|
|
222
|
+
return (typeof WebAssembly !== 'undefined' &&
|
|
223
|
+
'promising' in WebAssembly &&
|
|
224
|
+
'Suspending' in WebAssembly);
|
|
225
|
+
}
|
|
226
|
+
catch {
|
|
227
|
+
return false;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
// -----------------------------------------------------------------------
|
|
231
|
+
// String Helpers
|
|
232
|
+
// -----------------------------------------------------------------------
|
|
233
|
+
/** Allocate a C string in WASM memory. Caller must free. */
|
|
234
|
+
allocString(str) {
|
|
235
|
+
const m = this.module;
|
|
236
|
+
const len = m.lengthBytesUTF8(str) + 1;
|
|
237
|
+
const ptr = m._malloc(len);
|
|
238
|
+
m.stringToUTF8(str, ptr, len);
|
|
239
|
+
return ptr;
|
|
240
|
+
}
|
|
241
|
+
/** Read a C string from WASM memory */
|
|
242
|
+
readString(ptr) {
|
|
243
|
+
if (ptr === 0)
|
|
244
|
+
return '';
|
|
245
|
+
return this.module.UTF8ToString(ptr);
|
|
246
|
+
}
|
|
247
|
+
/** Free WASM memory */
|
|
248
|
+
free(ptr) {
|
|
249
|
+
if (ptr !== 0) {
|
|
250
|
+
this.module._free(ptr);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
// -----------------------------------------------------------------------
|
|
254
|
+
// Binary Data Helpers
|
|
255
|
+
//
|
|
256
|
+
// HEAPU8 / HEAPF32 may not be exported by the Emscripten module.
|
|
257
|
+
// These helpers try the fast HEAPU8/HEAPF32 path first, then fall
|
|
258
|
+
// back to byte-by-byte setValue/getValue which is always available.
|
|
259
|
+
// -----------------------------------------------------------------------
|
|
260
|
+
/**
|
|
261
|
+
* Write a Uint8Array into WASM linear memory at `destPtr`.
|
|
262
|
+
*
|
|
263
|
+
* Fast path uses `HEAPU8.set()` when available (after WASM rebuild).
|
|
264
|
+
* Fallback uses `setValue` byte-by-byte (works with any build).
|
|
265
|
+
*/
|
|
266
|
+
writeBytes(src, destPtr) {
|
|
267
|
+
const m = this.module;
|
|
268
|
+
if (m.HEAPU8) {
|
|
269
|
+
m.HEAPU8.set(src, destPtr);
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
for (let i = 0; i < src.length; i++) {
|
|
273
|
+
m.setValue(destPtr + i, src[i], 'i8');
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Read `length` bytes from WASM linear memory starting at `srcPtr`.
|
|
278
|
+
*
|
|
279
|
+
* Fast path uses `HEAPU8.slice()` when available.
|
|
280
|
+
* Fallback uses `getValue` byte-by-byte.
|
|
281
|
+
*/
|
|
282
|
+
readBytes(srcPtr, length) {
|
|
283
|
+
const m = this.module;
|
|
284
|
+
if (m.HEAPU8) {
|
|
285
|
+
return m.HEAPU8.slice(srcPtr, srcPtr + length);
|
|
286
|
+
}
|
|
287
|
+
const result = new Uint8Array(length);
|
|
288
|
+
for (let i = 0; i < length; i++) {
|
|
289
|
+
result[i] = m.getValue(srcPtr + i, 'i8') & 0xFF;
|
|
290
|
+
}
|
|
291
|
+
return result;
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Read `count` float32 values from WASM linear memory starting at `srcPtr`.
|
|
295
|
+
*
|
|
296
|
+
* Fast path uses `HEAPF32` when available.
|
|
297
|
+
* Fallback reads 4 bytes at a time via getValue('float').
|
|
298
|
+
*/
|
|
299
|
+
readFloat32Array(srcPtr, count) {
|
|
300
|
+
const m = this.module;
|
|
301
|
+
if (m.HEAPF32) {
|
|
302
|
+
const startIndex = srcPtr >> 2; // byte offset → float32 index
|
|
303
|
+
return m.HEAPF32.slice(startIndex, startIndex + count);
|
|
304
|
+
}
|
|
305
|
+
const result = new Float32Array(count);
|
|
306
|
+
for (let i = 0; i < count; i++) {
|
|
307
|
+
result[i] = m.getValue(srcPtr + i * 4, 'float');
|
|
308
|
+
}
|
|
309
|
+
return result;
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Write a Float32Array into WASM linear memory at `destPtr`.
|
|
313
|
+
* `destPtr` must be 4-byte aligned.
|
|
314
|
+
*
|
|
315
|
+
* Fast path uses `HEAPF32.set()` when available.
|
|
316
|
+
* Fallback uses `setValue` with 'float'.
|
|
317
|
+
*/
|
|
318
|
+
writeFloat32Array(src, destPtr) {
|
|
319
|
+
const m = this.module;
|
|
320
|
+
if (m.HEAPF32) {
|
|
321
|
+
m.HEAPF32.set(src, destPtr >> 2);
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
for (let i = 0; i < src.length; i++) {
|
|
325
|
+
m.setValue(destPtr + i * 4, src[i], 'float');
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Read a single float32 value from WASM linear memory.
|
|
330
|
+
*/
|
|
331
|
+
readFloat32(ptr) {
|
|
332
|
+
const m = this.module;
|
|
333
|
+
if (m.HEAPF32) {
|
|
334
|
+
return m.HEAPF32[ptr >> 2];
|
|
335
|
+
}
|
|
336
|
+
return m.getValue(ptr, 'float');
|
|
337
|
+
}
|
|
338
|
+
// -----------------------------------------------------------------------
|
|
339
|
+
// C API Wrappers
|
|
340
|
+
// -----------------------------------------------------------------------
|
|
341
|
+
/** Check a rac_result_t and throw SDKError if not success */
|
|
342
|
+
checkResult(result, operation) {
|
|
343
|
+
if (result !== 0) {
|
|
344
|
+
const errMsgPtr = this.module._rac_error_message(result);
|
|
345
|
+
const errMsg = this.readString(errMsgPtr);
|
|
346
|
+
throw SDKError.fromRACResult(result, `${operation}: ${errMsg}`);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
/** Get RACommons error message for a result code */
|
|
350
|
+
getErrorMessage(resultCode) {
|
|
351
|
+
const ptr = this.module._rac_error_message(resultCode);
|
|
352
|
+
return this.readString(ptr);
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Type-safe wrapper around Emscripten ccall().
|
|
356
|
+
* Centralizes all dynamic WASM function calls through the bridge.
|
|
357
|
+
*/
|
|
358
|
+
callFunction(funcName, returnType, argTypes, args, opts) {
|
|
359
|
+
if (!this._module)
|
|
360
|
+
throw SDKError.wasmNotLoaded();
|
|
361
|
+
return this._module.ccall(funcName, returnType, argTypes, args, opts);
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Call a WASM function that returns rac_result_t and throw SDKError if
|
|
365
|
+
* the result is non-zero.
|
|
366
|
+
*/
|
|
367
|
+
callWithCheck(funcName, argTypes, args) {
|
|
368
|
+
const result = this.callFunction(funcName, 'number', argTypes, args);
|
|
369
|
+
this.checkResult(result, funcName);
|
|
370
|
+
}
|
|
371
|
+
// -----------------------------------------------------------------------
|
|
372
|
+
// Cleanup
|
|
373
|
+
// -----------------------------------------------------------------------
|
|
374
|
+
/** Shutdown the WASM module */
|
|
375
|
+
shutdown() {
|
|
376
|
+
if (this._module && this._loaded) {
|
|
377
|
+
try {
|
|
378
|
+
this._module._rac_shutdown();
|
|
379
|
+
}
|
|
380
|
+
catch {
|
|
381
|
+
// Ignore shutdown errors
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
this._module = null;
|
|
385
|
+
this._loaded = false;
|
|
386
|
+
this._loading = null;
|
|
387
|
+
this._accelerationMode = 'cpu';
|
|
388
|
+
this._loadedModuleUrl = null;
|
|
389
|
+
WASMBridge._instance = null;
|
|
390
|
+
logger.info('WASM bridge shut down');
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
//# sourceMappingURL=WASMBridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WASMBridge.js","sourceRoot":"","sources":["../../src/Foundation/WASMBridge.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Archive Utility - Tar.gz extraction for model archives
|
|
3
|
+
*
|
|
4
|
+
* Provides browser-native tar.gz extraction using DecompressionStream (gzip)
|
|
5
|
+
* and a minimal tar parser. This matches the Swift SDK approach where Piper TTS
|
|
6
|
+
* models are distributed as .tar.gz archives bundling model files + espeak-ng-data.
|
|
7
|
+
*/
|
|
8
|
+
/** A single entry extracted from a tar archive. */
|
|
9
|
+
export interface TarEntry {
|
|
10
|
+
/** Relative path within the archive (e.g., 'espeak-ng-data/phondata') */
|
|
11
|
+
path: string;
|
|
12
|
+
/** File contents */
|
|
13
|
+
data: Uint8Array;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Extract a .tar.gz archive into an array of file entries.
|
|
17
|
+
*
|
|
18
|
+
* Uses the browser-native DecompressionStream for gzip decompression,
|
|
19
|
+
* then parses the tar format (512-byte header blocks).
|
|
20
|
+
*
|
|
21
|
+
* @param tarGzData - The raw tar.gz bytes
|
|
22
|
+
* @returns Array of extracted files (directories are skipped)
|
|
23
|
+
*/
|
|
24
|
+
export declare function extractTarGz(tarGzData: Uint8Array): Promise<TarEntry[]>;
|
|
25
|
+
//# sourceMappingURL=ArchiveUtility.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ArchiveUtility.d.ts","sourceRoot":"","sources":["../../src/Infrastructure/ArchiveUtility.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,mDAAmD;AACnD,MAAM,WAAW,QAAQ;IACvB,yEAAyE;IACzE,IAAI,EAAE,MAAM,CAAC;IACb,oBAAoB;IACpB,IAAI,EAAE,UAAU,CAAC;CAClB;AAoBD;;;;;;;;GAQG;AACH,wBAAsB,YAAY,CAAC,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAG7E"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Archive Utility - Tar.gz extraction for model archives
|
|
3
|
+
*
|
|
4
|
+
* Provides browser-native tar.gz extraction using DecompressionStream (gzip)
|
|
5
|
+
* and a minimal tar parser. This matches the Swift SDK approach where Piper TTS
|
|
6
|
+
* models are distributed as .tar.gz archives bundling model files + espeak-ng-data.
|
|
7
|
+
*/
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// Constants
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
/** Tar header block size */
|
|
12
|
+
const TAR_BLOCK_SIZE = 512;
|
|
13
|
+
/** Tar file type flags */
|
|
14
|
+
var TarFileType;
|
|
15
|
+
(function (TarFileType) {
|
|
16
|
+
TarFileType[TarFileType["Regular"] = 48] = "Regular";
|
|
17
|
+
TarFileType[TarFileType["RegularAlt"] = 0] = "RegularAlt";
|
|
18
|
+
TarFileType[TarFileType["Directory"] = 53] = "Directory";
|
|
19
|
+
})(TarFileType || (TarFileType = {}));
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
// Public API
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
/**
|
|
24
|
+
* Extract a .tar.gz archive into an array of file entries.
|
|
25
|
+
*
|
|
26
|
+
* Uses the browser-native DecompressionStream for gzip decompression,
|
|
27
|
+
* then parses the tar format (512-byte header blocks).
|
|
28
|
+
*
|
|
29
|
+
* @param tarGzData - The raw tar.gz bytes
|
|
30
|
+
* @returns Array of extracted files (directories are skipped)
|
|
31
|
+
*/
|
|
32
|
+
export async function extractTarGz(tarGzData) {
|
|
33
|
+
const tarData = await decompressGzip(tarGzData);
|
|
34
|
+
return parseTar(tarData);
|
|
35
|
+
}
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
// Gzip Decompression (browser-native)
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
/**
|
|
40
|
+
* Decompress gzip data using the browser's native DecompressionStream API.
|
|
41
|
+
* Supported in Chrome 80+, Firefox 113+, Safari 16.4+.
|
|
42
|
+
*/
|
|
43
|
+
async function decompressGzip(compressed) {
|
|
44
|
+
const ds = new DecompressionStream('gzip');
|
|
45
|
+
const writer = ds.writable.getWriter();
|
|
46
|
+
const reader = ds.readable.getReader();
|
|
47
|
+
// Write compressed data and close the stream
|
|
48
|
+
writer.write(compressed);
|
|
49
|
+
writer.close();
|
|
50
|
+
// Read all decompressed chunks
|
|
51
|
+
const chunks = [];
|
|
52
|
+
let totalLength = 0;
|
|
53
|
+
while (true) {
|
|
54
|
+
const { done, value } = await reader.read();
|
|
55
|
+
if (done)
|
|
56
|
+
break;
|
|
57
|
+
chunks.push(value);
|
|
58
|
+
totalLength += value.length;
|
|
59
|
+
}
|
|
60
|
+
// Concatenate into a single buffer
|
|
61
|
+
const result = new Uint8Array(totalLength);
|
|
62
|
+
let offset = 0;
|
|
63
|
+
for (const chunk of chunks) {
|
|
64
|
+
result.set(chunk, offset);
|
|
65
|
+
offset += chunk.length;
|
|
66
|
+
}
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
69
|
+
// ---------------------------------------------------------------------------
|
|
70
|
+
// Tar Parser
|
|
71
|
+
// ---------------------------------------------------------------------------
|
|
72
|
+
/**
|
|
73
|
+
* Parse a tar archive and return all regular file entries.
|
|
74
|
+
* Directories and special entries are skipped.
|
|
75
|
+
*
|
|
76
|
+
* Tar format:
|
|
77
|
+
* - Each entry = 512-byte header + ceil(fileSize/512)*512 bytes of data
|
|
78
|
+
* - Header contains filename (0-100), size (124-136 octal), type (156)
|
|
79
|
+
* - Archive ends with two consecutive zero-filled 512-byte blocks
|
|
80
|
+
*/
|
|
81
|
+
function parseTar(tarData) {
|
|
82
|
+
const entries = [];
|
|
83
|
+
let offset = 0;
|
|
84
|
+
while (offset + TAR_BLOCK_SIZE <= tarData.length) {
|
|
85
|
+
const header = tarData.subarray(offset, offset + TAR_BLOCK_SIZE);
|
|
86
|
+
// End of archive: two zero-filled blocks
|
|
87
|
+
if (isZeroBlock(header))
|
|
88
|
+
break;
|
|
89
|
+
const name = readString(header, 0, 100);
|
|
90
|
+
const size = readOctal(header, 124, 12);
|
|
91
|
+
const typeFlag = header[156];
|
|
92
|
+
// UStar prefix (for paths longer than 100 chars)
|
|
93
|
+
const prefix = readString(header, 345, 155);
|
|
94
|
+
const fullPath = prefix ? `${prefix}/${name}` : name;
|
|
95
|
+
// Normalise: strip leading './' or '/'
|
|
96
|
+
const normalisedPath = fullPath.replace(/^\.\//, '').replace(/^\//, '');
|
|
97
|
+
offset += TAR_BLOCK_SIZE;
|
|
98
|
+
if (size > 0) {
|
|
99
|
+
const dataStart = offset;
|
|
100
|
+
const dataEnd = dataStart + size;
|
|
101
|
+
// Only include regular files (skip directories, symlinks, etc.)
|
|
102
|
+
if (typeFlag === TarFileType.Regular || typeFlag === TarFileType.RegularAlt) {
|
|
103
|
+
entries.push({
|
|
104
|
+
path: normalisedPath,
|
|
105
|
+
data: tarData.slice(dataStart, dataEnd),
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
// Advance past data blocks (padded to 512-byte boundary)
|
|
109
|
+
offset += Math.ceil(size / TAR_BLOCK_SIZE) * TAR_BLOCK_SIZE;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return entries;
|
|
113
|
+
}
|
|
114
|
+
// ---------------------------------------------------------------------------
|
|
115
|
+
// Helpers
|
|
116
|
+
// ---------------------------------------------------------------------------
|
|
117
|
+
/** Read a null-terminated ASCII string from a tar header field. */
|
|
118
|
+
function readString(header, offset, length) {
|
|
119
|
+
let end = offset;
|
|
120
|
+
const limit = offset + length;
|
|
121
|
+
while (end < limit && header[end] !== 0)
|
|
122
|
+
end++;
|
|
123
|
+
const decoder = new TextDecoder('ascii');
|
|
124
|
+
return decoder.decode(header.subarray(offset, end));
|
|
125
|
+
}
|
|
126
|
+
/** Read an octal number from a tar header field. */
|
|
127
|
+
function readOctal(header, offset, length) {
|
|
128
|
+
const str = readString(header, offset, length).trim();
|
|
129
|
+
return str ? parseInt(str, 8) : 0;
|
|
130
|
+
}
|
|
131
|
+
/** Check if a 512-byte block is all zeros (end-of-archive marker). */
|
|
132
|
+
function isZeroBlock(block) {
|
|
133
|
+
for (let i = 0; i < block.length; i++) {
|
|
134
|
+
if (block[i] !== 0)
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=ArchiveUtility.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ArchiveUtility.js","sourceRoot":"","sources":["../../src/Infrastructure/ArchiveUtility.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RunAnywhere Web SDK - Audio Capture
|
|
3
|
+
*
|
|
4
|
+
* Captures microphone audio using Web Audio API and provides
|
|
5
|
+
* Float32Array PCM samples suitable for STT and VAD processing.
|
|
6
|
+
*
|
|
7
|
+
* Supports:
|
|
8
|
+
* - Real-time microphone capture via getUserMedia
|
|
9
|
+
* - Configurable sample rate (resampling via AudioContext)
|
|
10
|
+
* - Chunk-based callbacks for streaming STT/VAD
|
|
11
|
+
* - Buffer accumulation (getAudioBuffer, drainBuffer, clearBuffer)
|
|
12
|
+
* - Audio level monitoring via AnalyserNode (currentLevel getter)
|
|
13
|
+
*/
|
|
14
|
+
export type AudioChunkCallback = (samples: Float32Array) => void;
|
|
15
|
+
export type AudioLevelCallback = (level: number) => void;
|
|
16
|
+
export interface AudioCaptureConfig {
|
|
17
|
+
/** Target sample rate (default: 16000 for STT) */
|
|
18
|
+
sampleRate?: number;
|
|
19
|
+
/** Chunk size in samples (default: 1600 = 100ms at 16kHz) */
|
|
20
|
+
chunkSize?: number;
|
|
21
|
+
/** Number of audio channels (default: 1, mono) */
|
|
22
|
+
channels?: number;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* AudioCapture - Captures microphone audio for STT/VAD processing.
|
|
26
|
+
*
|
|
27
|
+
* Uses Web Audio API (AudioContext + ScriptProcessorNode) to capture
|
|
28
|
+
* microphone audio, resample to target rate, and deliver Float32Array
|
|
29
|
+
* PCM chunks to the consumer.
|
|
30
|
+
*
|
|
31
|
+
* Includes buffer accumulation for batch STT and an AnalyserNode for
|
|
32
|
+
* real-time audio level metering (0-1 range).
|
|
33
|
+
*/
|
|
34
|
+
export declare class AudioCapture {
|
|
35
|
+
private audioContext;
|
|
36
|
+
private mediaStream;
|
|
37
|
+
private sourceNode;
|
|
38
|
+
private processorNode;
|
|
39
|
+
private _analyser;
|
|
40
|
+
private _animFrameId;
|
|
41
|
+
private _isCapturing;
|
|
42
|
+
private _currentLevel;
|
|
43
|
+
private _pcmChunks;
|
|
44
|
+
private readonly config;
|
|
45
|
+
private chunkCallback;
|
|
46
|
+
private levelCallback;
|
|
47
|
+
constructor(config?: AudioCaptureConfig);
|
|
48
|
+
get isCapturing(): boolean;
|
|
49
|
+
/** Current normalized audio level (0..1), updated per animation frame. */
|
|
50
|
+
get currentLevel(): number;
|
|
51
|
+
/**
|
|
52
|
+
* Get the actual sample rate of the audio context.
|
|
53
|
+
* May differ from requested rate if browser doesn't support it.
|
|
54
|
+
*/
|
|
55
|
+
get actualSampleRate(): number;
|
|
56
|
+
/** Duration of collected audio in seconds based on configured sample rate. */
|
|
57
|
+
get bufferDurationSeconds(): number;
|
|
58
|
+
/**
|
|
59
|
+
* Start capturing microphone audio.
|
|
60
|
+
*
|
|
61
|
+
* @param onChunk - Optional callback receiving Float32Array chunks of PCM audio (streaming)
|
|
62
|
+
* @param onLevel - Optional callback invoked per animation frame with audio level 0..1
|
|
63
|
+
* @throws If microphone permission is denied
|
|
64
|
+
*/
|
|
65
|
+
start(onChunk?: AudioChunkCallback, onLevel?: AudioLevelCallback): Promise<void>;
|
|
66
|
+
/**
|
|
67
|
+
* Stop capturing audio and release resources.
|
|
68
|
+
*/
|
|
69
|
+
stop(): void;
|
|
70
|
+
/**
|
|
71
|
+
* Get all collected PCM audio as a single Float32Array.
|
|
72
|
+
* Does NOT clear the buffer — call `clearBuffer()` separately.
|
|
73
|
+
*/
|
|
74
|
+
getAudioBuffer(): Float32Array;
|
|
75
|
+
/**
|
|
76
|
+
* Drain: return the current buffer and clear it for the next segment.
|
|
77
|
+
* Useful for live mode where we transcribe segments incrementally.
|
|
78
|
+
*/
|
|
79
|
+
drainBuffer(): Float32Array;
|
|
80
|
+
/** Clear collected PCM data without stopping capture. */
|
|
81
|
+
clearBuffer(): void;
|
|
82
|
+
/** Start the requestAnimationFrame loop that reads the AnalyserNode. */
|
|
83
|
+
private startLevelMonitoring;
|
|
84
|
+
private cleanupResources;
|
|
85
|
+
private nearestPowerOf2;
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=AudioCapture.d.ts.map
|