web-asr-core
Version:
WebASR Core - Browser-based speech processing with VAD, WakeWord and Whisper - Unified all-in-one version
867 lines • 26.7 kB
JavaScript
/**
* 配置管理器
*
* 集中管理 WebASRCore 所有服務的配置參數,提供統一的配置介面。
* 所有配置項都使用公開屬性,方便直接存取和修改。
*
* @fileoverview 配置管理器實現
* @author WebASRCore Team
*/
/**
* 配置管理器類
*
* @description 提供 VAD、喚醒詞和 Whisper 服務的集中配置管理
* @class ConfigManager
*
* @example
* ```typescript
* // 創建配置管理器實例
* const config = new ConfigManager();
*
* // 修改 VAD 配置
* config.vad.threshold = 0.6;
* config.vad.hangoverFrames = 15;
*
* // 修改喚醒詞配置
* config.wakeword.hey_jarvis.threshold = 0.6;
*
* // 修改 Whisper 配置
* config.whisper.language = 'zh';
* ```
*/
export class ConfigManager {
/**
* 單例實例(如需全域共用,請使用 ConfigManager.getInstance())
*
* 使用 null 初始值以清楚表示尚未建立實例
*/
static _instance = null;
/**
* 取得或建立單例配置管理器
* @param overrides - 選擇性的覆蓋配置(只在首次建立時應用,或傳入時會合併到現有實例)
*/
static getInstance(overrides) {
if (!ConfigManager._instance) {
ConfigManager._instance = new ConfigManager(overrides);
}
else if (overrides) {
// 若已存在實例且提供 overrides,合併覆蓋到現有單例
ConfigManager._instance.applyOverrides(overrides);
}
return ConfigManager._instance;
}
/**
* VAD(語音活動檢測)配置
*
* @description Silero VAD v6 模型的配置參數
*/
vad = {
/**
* VAD 模型檔案路徑
* @default './models/silero_vad_v6.onnx'
*/
modelPath: './models/github/snakers4/silero-vad/silero_vad_v6.onnx',
/**
* 語音檢測閾值(0-1)
* @description 高於此值判定為語音,低於此值判定為靜音
* @default 0.5
*/
threshold: 0.5,
/**
* 語音結束後的延遲幀數
* @description 檢測到靜音後繼續保持活動狀態的幀數,防止語音過早截斷
* @default 12
*/
hangoverFrames: 12,
/**
* 音訊採樣率(Hz)
* @description VAD 模型預期的輸入音訊採樣率
* @default 16000
*/
sampleRate: 16000,
/**
* 每個音訊塊的樣本數
* @description 對應 32ms 的音訊(16kHz * 0.032)
* @default 512
*/
windowSize: 512,
/**
* 上下文樣本數
* @description 前一塊的尾部樣本數,用於平滑處理
* @default 64
*/
contextSize: 64,
};
/**
* 喚醒詞檢測配置
*
* @description OpenWakeWord 模型的配置參數,支援多個喚醒詞
*/
wakeword = {
/**
* Hey Jarvis 喚醒詞配置
*/
hey_jarvis: {
/**
* 檢測器模型路徑
* @default './models/github/dscripka/openWakeWord/hey_jarvis_v0.1.onnx'
*/
detectorPath: './models/github/dscripka/openWakeWord/hey_jarvis_v0.1.onnx',
/**
* 梅爾頻譜圖模型路徑
* @default './models/github/dscripka/openWakeWord/melspectrogram.onnx'
*/
melspecPath: './models/github/dscripka/openWakeWord/melspectrogram.onnx',
/**
* 嵌入模型路徑
* @default './models/github/dscripka/openWakeWord/embedding_model.onnx'
*/
embeddingPath: './models/github/dscripka/openWakeWord/embedding_model.onnx',
/**
* 喚醒詞觸發閾值(0-1)
* @description 高於此值觸發喚醒詞檢測
* @default 0.3
*/
threshold: 0.3,
/**
* 是否啟用此喚醒詞
* @default true
*/
enabled: true,
},
/**
* Hey Mycroft 喚醒詞配置
*/
hey_mycroft: {
/**
* 檢測器模型路徑
* @default './models/github/dscripka/openWakeWord/hey_mycroft_v0.1.onnx'
*/
detectorPath: './models/github/dscripka/openWakeWord/hey_mycroft_v0.1.onnx',
/**
* 梅爾頻譜圖模型路徑(共用)
* @default './models/github/dscripka/openWakeWord/melspectrogram.onnx'
*/
melspecPath: './models/github/dscripka/openWakeWord/melspectrogram.onnx',
/**
* 嵌入模型路徑(共用)
* @default './models/github/dscripka/openWakeWord/embedding_model.onnx'
*/
embeddingPath: './models/github/dscripka/openWakeWord/embedding_model.onnx',
/**
* 喚醒詞觸發閾值(0-1)
* @default 0.5
*/
threshold: 0.5,
/**
* 是否啟用此喚醒詞
* @default false
*/
enabled: false,
},
/**
* Alexa 喚醒詞配置
*/
alexa: {
/**
* 檢測器模型路徑
* @default './models/github/dscripka/openWakeWord/alexa_v0.1.onnx'
*/
detectorPath: './models/github/dscripka/openWakeWord/alexa_v0.1.onnx',
/**
* 梅爾頻譜圖模型路徑(共用)
* @default './models/github/dscripka/openWakeWord/melspectrogram.onnx'
*/
melspecPath: './models/github/dscripka/openWakeWord/melspectrogram.onnx',
/**
* 嵌入模型路徑(共用)
* @default './models/github/dscripka/openWakeWord/embedding_model.onnx'
*/
embeddingPath: './models/github/dscripka/openWakeWord/embedding_model.onnx',
/**
* 喚醒詞觸發閾值(0-1)
* @default 0.5
*/
threshold: 0.5,
/**
* 是否啟用此喚醒詞
* @default false
*/
enabled: false,
},
/**
* 通用喚醒詞處理參數
*/
common: {
/**
* 每個音訊塊的梅爾幀數
* @description 每個 80ms 音訊塊產生的梅爾頻譜圖幀數
* @default 5
*/
melFramesPerChunk: 5,
/**
* 嵌入所需的梅爾幀數
* @description 進行嵌入計算所需的最小梅爾幀數
* @default 76
*/
requiredMelFrames: 76,
/**
* 滑動窗口步長
* @description 梅爾緩衝區的滑動步長
* @default 8
*/
melStride: 8,
/**
* 音訊塊大小(樣本數)
* @description 對應 80ms 的音訊(16kHz * 0.08)
* @default 1280
*/
chunkSize: 1280,
/**
* 嵌入緩衝區大小
* @description 嵌入向量的時間步數
* @default 16
*/
embeddingBufferSize: 16,
/**
* 嵌入向量維度
* @description 每個嵌入向量的特徵維度
* @default 96
*/
embeddingDimension: 96,
},
};
/**
* Whisper 語音辨識配置
*
* @description Whisper 模型的配置參數,使用 transformers.js
*/
whisper = {
/**
* 模型識別符或路徑
* @description HuggingFace 模型 ID 或本地模型路徑
* @default 'Xenova/whisper-tiny'
*/
modelPath: 'Xenova/whisper-tiny',
/**
* 是否使用量化模型
* @description 量化模型檔案較小但精度略低
* @default true
*/
quantized: true,
/**
* 執行裝置
* @description 選擇模型執行的裝置
* @default 'auto'
* @options 'webgpu' - 使用 GPU 加速(需要瀏覽器支援 WebGPU)
* @options 'wasm' - 使用 CPU(通過 WebAssembly)
* @options 'auto' - 自動選擇最佳可用裝置
*/
device: 'auto',
/**
* 資料類型(量化程度)
* @description 控制模型精度和大小的權衡
* @default 'q8'
* @options 'fp32' - 32位浮點數(最高精度,WebGPU 預設)
* @options 'fp16' - 16位浮點數(中等精度)
* @options 'q8' - 8位量化(平衡精度和大小,WASM 預設)
* @options 'q4' - 4位量化(最小檔案大小)
*/
dtype: 'q8',
/**
* 預設語言代碼
* @description ISO 639-1 語言代碼,如 'en', 'zh', 'ja'
* @default 'zh'
*/
language: 'zh',
/**
* 預設任務類型
* @description 'transcribe' 轉錄原語言,'translate' 翻譯成英文
* @default 'transcribe'
*/
task: 'transcribe',
/**
* 是否返回時間戳片段
* @description 啟用後返回每個片段的開始和結束時間
* @default false
*/
returnSegments: false,
/**
* 本地模型基礎路徑
* @description 如果使用本地模型,指定模型檔案的基礎路徑
* @default undefined
*/
localBasePath: undefined,
/**
* ONNX Runtime WASM 檔案路徑
* @description 可選的 WASM 檔案路徑配置
* @default undefined
*/
wasmPaths: undefined,
/**
* 音訊分塊設定
*/
chunking: {
/**
* 每個音訊塊的長度(秒)
* @description 用於長音訊的分塊處理
* @default 30
*/
chunkSizeSeconds: 30,
/**
* 塊間重疊長度(秒)
* @description 防止邊界處的語音被截斷
* @default 5
*/
overlapSeconds: 5,
},
/**
* 串流轉錄設定
* @description 控制 Whisper 的串流轉錄行為
*/
streaming: {
/**
* 是否啟用串流模式
* @description 啟用後會使用 WhisperTextStreamer 進行增量轉錄
* @default true
*/
enabled: true,
/**
* 串流塊長度(秒)
* @description 每個串流塊的音訊長度
* @default 20
*/
chunkLengthSeconds: 20,
/**
* 串流步長(秒)
* @description 串流塊之間的重疊長度
* @default 5
*/
strideLengthSeconds: 5,
},
};
/**
* ONNX Runtime 配置
*
* @description ONNX Runtime Web 的執行配置
*/
onnx = {
/**
* 執行提供者優先順序
* @description 按優先順序嘗試的執行提供者
* @default ['webgpu', 'wasm']
*/
executionProviders: ['webgpu', 'wasm'],
/**
* 模型特定的執行提供者配置
* @description 為不同模型類型指定特定的執行提供者
*/
modelSpecificProviders: {
/**
* 喚醒詞模型執行提供者
* @description 使用 WASM 以降低延遲(避免 GPU 記憶體傳輸開銷)
* @default ['wasm']
*/
wakeword: ['wasm'],
/**
* VAD 模型執行提供者
* @description 優先使用 WebGPU 以提高吞吐量
* @default ['webgpu', 'wasm']
*/
vad: ['webgpu', 'wasm'],
/**
* Whisper 模型執行提供者
* @description 優先使用 WebGPU 以提高處理速度
* @default ['webgpu', 'wasm']
*/
whisper: ['webgpu', 'wasm'],
},
/**
* 是否使用 Web Worker
* @description 在 Web Worker 中執行模型推論以避免阻塞主執行緒
* @default true
*/
useWebWorker: true,
/**
* WebGPU 配置
*/
webgpu: {
/**
* 是否啟用 WebGPU
* @description 當瀏覽器支援時使用 GPU 加速
* @default true
*/
enabled: true,
/**
* 裝置偏好
* @description 'high-performance' 或 'low-power'
* @default 'high-performance'
*/
powerPreference: 'high-performance',
/**
* 強制使用回退
* @description 當 WebGPU 不可用時是否強制使用 WASM
* @default false
*/
forceFallback: false,
},
/**
* WASM 配置
*/
wasm: {
/**
* SIMD 支援
* @description 使用 SIMD 指令集加速(如果支援)
* @default true
*/
simd: true,
/**
* 執行緒數
* @description Web Worker 執行緒數(0 = 自動)
* @default 0
*/
numThreads: 0,
/**
* WASM 檔案路徑
* @description 自訂 WASM 檔案位置
* @default undefined
*/
wasmPaths: undefined,
},
/**
* 圖優化選項
*/
graphOptimization: {
/**
* 優化等級
* @description 'disabled' | 'basic' | 'extended' | 'all'
* @default 'all'
*/
level: 'all',
/**
* 是否啟用記憶體模式優化
* @description 減少記憶體使用但可能影響速度
* @default false
*/
enableMemPattern: false,
/**
* 是否啟用 CPU 記憶體區域
* @description 在 CPU 和 GPU 之間共享記憶體
* @default false
*/
enableCpuMemArena: false,
},
/**
* 模型快取配置
*/
modelCache: {
/**
* 是否啟用模型快取
* @description 快取已載入的模型以加快後續載入
* @default true
*/
enabled: true,
/**
* 快取大小限制(MB)
* @description 最大快取大小
* @default 100
*/
maxSize: 100,
},
};
/**
* 全域音訊處理配置
*
* @description 適用於所有服務的通用音訊參數
*/
audio = {
/**
* 全域採樣率(Hz)
* @description 所有音訊處理的標準採樣率
* @default 16000
*/
sampleRate: 16000,
/**
* 音訊通道數
* @description 1 為單聲道,2 為立體聲
* @default 1
*/
channels: 1,
/**
* 音訊位元深度
* @description 每個樣本的位元數
* @default 32
*/
bitDepth: 32,
/**
* 環形緩衝區配置
* @description AudioRingBuffer 的配置參數
*/
ringBuffer: {
/**
* 緩衝區容量(樣本數)
* @description 預設為 10 秒的音訊 (16000 * 10)
* @default 160000
*/
capacity: 160000,
/**
* 是否使用 SharedArrayBuffer
* @description 用於 Web Worker 共享記憶體
* @default false
*/
useSharedArrayBuffer: false,
},
/**
* 音訊分塊配置
* @description AudioChunker 的配置參數
*/
chunker: {
/**
* VAD 音訊塊配置
*/
vad: {
/**
* 塊大小(樣本數)
* @description 32ms @ 16kHz
* @default 512
*/
chunkSize: 512,
/**
* 重疊樣本數
* @description 用於保持連續性的上下文
* @default 64
*/
overlap: 64,
},
/**
* 喚醒詞音訊塊配置
*/
wakeword: {
/**
* 塊大小(樣本數)
* @description 80ms @ 16kHz
* @default 1280
*/
chunkSize: 1280,
/**
* 重疊樣本數
* @description 喚醒詞通常不需要重疊
* @default 0
*/
overlap: 0,
},
/**
* Whisper 音訊塊配置
*/
whisper: {
/**
* 塊大小(樣本數)
* @description 30 秒 @ 16kHz
* @default 480000
*/
chunkSize: 480000,
/**
* 重疊樣本數
* @description 5 秒重疊防止邊界語音被截斷
* @default 80000
*/
overlap: 80000,
},
},
/**
* 計時器配置
*/
timer: {
/**
* VAD 靜音超時時間(毫秒)
* @description 檢測到靜音後等待的時間,用於判斷使用者是否結束說話
* @default 1500
*/
vadSilenceTimeout: 1500,
/**
* 喚醒詞等待超時(毫秒)
* @description 檢測到喚醒詞後等待使用者說話的最長時間
* @default 5000
*/
wakewordTimeout: 5000,
/**
* 錄音最大時長(毫秒)
* @description 單次錄音的最大時長限制
* @default 30000
*/
maxRecordingDuration: 30000,
/**
* Tick 間隔(毫秒)
* @description 計時器更新間隔
* @default 100
*/
tickInterval: 100,
},
};
/**
* Speech API 配置
*
* @description Web Speech API (TTS/STT) 相關設定
*/
speech = {
/**
* TTS(文字轉語音)設定
*/
tts: {
/**
* 預設語速
* @description 範圍 0.1-10,預設 1
* @default 1
*/
defaultRate: 1,
/**
* 預設音調
* @description 範圍 0-2,預設 1
* @default 1
*/
defaultPitch: 1,
/**
* 預設音量
* @description 範圍 0-1,預設 1
* @default 1
*/
defaultVolume: 1,
/**
* 預設語音
* @description 語音名稱或語言代碼,null 表示使用系統預設
* @default null
*/
defaultVoice: null,
/**
* 優先語言
* @description 優先選擇的語言列表
* @default ['zh-TW', 'zh-CN', 'en-US']
*/
preferredLanguages: ['zh-TW', 'zh-CN', 'en-US'],
},
/**
* STT(語音轉文字)設定
*/
stt: {
/**
* 預設語言
* @description 識別語言代碼
* @default 'zh-TW'
*/
defaultLanguage: 'zh-TW',
/**
* 是否連續識別
* @description 是否持續監聽直到手動停止
* @default false
*/
continuous: false,
/**
* 是否返回暫時結果
* @description 是否在識別過程中返回暫時結果
* @default true
*/
interimResults: true,
/**
* 最大替代結果數
* @description 返回的最大替代識別結果數量
* @default 3
*/
maxAlternatives: 3,
/**
* 無語音超時
* @description 無語音輸入超時時間(毫秒)
* @default 5000
*/
noSpeechTimeout: 5000,
/**
* 最大無語音重試次數
* @description 連續無語音的最大重試次數
* @default 3
*/
maxNoSpeechRetries: 3,
},
};
/**
* 效能與資源配置
*
* @description 控制資源使用和效能優化的參數
*/
performance = {
/**
* 是否啟用 WebWorker
* @description 在背景執行緒執行推論以避免阻塞主執行緒
* @default true
*/
useWebWorker: true,
/**
* 最大並行推論數
* @description 同時執行的最大推論任務數
* @default 2
*/
maxConcurrentInferences: 2,
/**
* 是否啟用模型快取
* @description 快取載入的模型以加快後續使用
* @default true
*/
enableModelCaching: true,
/**
* ONNX Runtime 執行提供者
* @description 優先順序列表,如 ['wasm', 'webgl']
* @default ['wasm']
*/
executionProviders: ['wasm'],
/**
* 圖優化級別
* @description ONNX Runtime 圖優化級別:'disabled', 'basic', 'extended', 'all'
* @default 'all'
*/
graphOptimizationLevel: 'all',
};
/**
* 建構函數
*
* @description 創建配置管理器實例,可選擇性覆蓋預設配置
* @param overrides - 要覆蓋的配置項
*
* @example
* ```typescript
* // 使用預設配置
* const config = new ConfigManager();
*
* // 覆蓋部分配置
* const config = new ConfigManager({
* vad: { threshold: 0.6 },
* whisper: { language: 'en' }
* });
* ```
*/
constructor(overrides) {
if (overrides) {
this.applyOverrides(overrides);
}
}
/**
* 應用配置覆蓋
*
* @description 深度合併覆蓋配置到當前配置
* @param overrides - 要覆蓋的配置項
* @private
*/
applyOverrides(overrides) {
if (overrides.vad) {
Object.assign(this.vad, overrides.vad);
}
if (overrides.wakeword) {
if (overrides.wakeword.hey_jarvis) {
Object.assign(this.wakeword.hey_jarvis, overrides.wakeword.hey_jarvis);
}
if (overrides.wakeword.hey_mycroft) {
Object.assign(this.wakeword.hey_mycroft, overrides.wakeword.hey_mycroft);
}
if (overrides.wakeword.alexa) {
Object.assign(this.wakeword.alexa, overrides.wakeword.alexa);
}
if (overrides.wakeword.common) {
Object.assign(this.wakeword.common, overrides.wakeword.common);
}
}
if (overrides.whisper) {
Object.assign(this.whisper, overrides.whisper);
if (overrides.whisper.chunking) {
Object.assign(this.whisper.chunking, overrides.whisper.chunking);
}
if (overrides.whisper.streaming) {
Object.assign(this.whisper.streaming, overrides.whisper.streaming);
}
}
if (overrides.audio) {
Object.assign(this.audio, overrides.audio);
}
if (overrides.performance) {
Object.assign(this.performance, overrides.performance);
}
}
/**
* 獲取當前配置的 JSON 表示
*
* @description 將配置對象轉換為 JSON 字符串,便於儲存或傳輸
* @returns 配置的 JSON 字符串
*
* @example
* ```typescript
* const config = new ConfigManager();
* const json = config.toJSON();
* console.log(json);
* ```
*/
toJSON() {
return JSON.stringify({
vad: this.vad,
wakeword: this.wakeword,
whisper: this.whisper,
audio: this.audio,
performance: this.performance,
}, null, 2);
}
/**
* 從 JSON 載入配置
*
* @description 從 JSON 字符串載入配置並覆蓋當前設定
* @param json - 配置的 JSON 字符串
*
* @example
* ```typescript
* const config = new ConfigManager();
* const savedConfig = localStorage.getItem('webASRConfig');
* if (savedConfig) {
* config.fromJSON(savedConfig);
* }
* ```
*/
fromJSON(json) {
try {
const parsed = JSON.parse(json);
this.applyOverrides(parsed);
}
catch (error) {
console.error('無法解析配置 JSON:', error);
}
}
/**
* 重設為預設配置
*
* @description 將所有配置項重設為預設值
*
* @example
* ```typescript
* const config = new ConfigManager();
* config.vad.threshold = 0.8; // 修改配置
* config.reset(); // 重設為預設值
* console.log(config.vad.threshold); // 0.5
* ```
*/
reset() {
const defaultConfig = new ConfigManager();
this.vad = defaultConfig.vad;
this.wakeword = defaultConfig.wakeword;
this.whisper = defaultConfig.whisper;
this.audio = defaultConfig.audio;
this.speech = defaultConfig.speech;
this.performance = defaultConfig.performance;
}
}
/**
* 預設配置管理器實例
*
* @description 提供一個全域共用的預設配置實例
* @example
* ```typescript
* import { defaultConfig } from './config-manager';
*
* // 使用預設配置
* const threshold = defaultConfig.vad.threshold;
* ```
*/
export const defaultConfig = ConfigManager.getInstance();
//# sourceMappingURL=config-manager.js.map