feat(voice): wake-word «Космо» в браузере (Шаг 3)
All checks were successful
Deploy / deploy (push) Successful in 6m33s
All checks were successful
Deploy / deploy (push) Successful in 6m33s
openWakeWord pipeline на onnxruntime-web прямо на планшете. Цепочка: mic (16kHz, AudioWorklet) → melspectrogram.onnx → embedding_model.onnx (sliding 76-frame window, stride 8) → cosmo.onnx → score 0..1. Триггер при score≥0.5 → запускается тот же VAD-flow что и push-to-talk. - public/wake/ — cosmo.onnx (custom-trained на голос Даниила) + melspectrogram.onnx + embedding_model.onnx (~2.9MB вместе). - lib/wake-word.ts — WakeWordDetector class. ort грузится через <script src=/vad/ort.wasm.min.js> на клиенте — обход проблемы next-swc с парсингом import.meta.url в onnxruntime-web .mjs билдах. - VoiceController: тап = активация (нужен для AudioContext user-gesture), далее непрерывное слушание wake-word; на детект → MicVAD флоу. Долгий тап = выкл. Ручной тап остаётся как fallback. После деплоя Python-агент на .103 не нужен — можно архивировать home-voice-assistant. На .103 остаётся только ElevenLabs прокси :8888.
This commit is contained in:
BIN
public/wake/cosmo.onnx
Normal file
BIN
public/wake/cosmo.onnx
Normal file
Binary file not shown.
BIN
public/wake/embedding_model.onnx
Normal file
BIN
public/wake/embedding_model.onnx
Normal file
Binary file not shown.
BIN
public/wake/melspectrogram.onnx
Normal file
BIN
public/wake/melspectrogram.onnx
Normal file
Binary file not shown.
23
public/wake/wake-capture-worklet.js
Normal file
23
public/wake/wake-capture-worklet.js
Normal file
@@ -0,0 +1,23 @@
|
||||
// AudioWorklet, который буферизует входной поток и шлёт чанки по 1280 семплов
|
||||
// (80 мс при 16kHz) в main thread. Любая входная длина допустима — буферизуется.
|
||||
class WakeCaptureProcessor extends AudioWorkletProcessor {
|
||||
constructor() {
|
||||
super()
|
||||
this.buf = new Float32Array(0)
|
||||
this.target = 1280
|
||||
}
|
||||
process(inputs) {
|
||||
const ch = inputs[0] && inputs[0][0]
|
||||
if (!ch || ch.length === 0) return true
|
||||
const merged = new Float32Array(this.buf.length + ch.length)
|
||||
merged.set(this.buf)
|
||||
merged.set(ch, this.buf.length)
|
||||
this.buf = merged
|
||||
while (this.buf.length >= this.target) {
|
||||
this.port.postMessage(this.buf.slice(0, this.target))
|
||||
this.buf = this.buf.slice(this.target)
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
registerProcessor('wake-capture', WakeCaptureProcessor)
|
||||
Reference in New Issue
Block a user