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.
24 lines
893 B
JavaScript
24 lines
893 B
JavaScript
// 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)
|