Download ctc-capture-worklet.js from RobinsAIWorld/granite-speech-streaming-webgpu: direct link, hf CLI and curl.
- Browser
- Download file 1.24 kB
-
https://huggingface.co/spaces/RobinsAIWorld/granite-speech-streaming-webgpu/resolve/main/ctc-capture-worklet.js
- Command line
-
hf download hf://spaces/RobinsAIWorld/granite-speech-streaming-webgpu/ctc-capture-worklet.js
-
curl -L -o ctc-capture-worklet.js https://huggingface.co/spaces/RobinsAIWorld/granite-speech-streaming-webgpu/resolve/main/ctc-capture-worklet.js
1.24 kB
| /** | |
| * Continuous mic capture for streaming dictation. | |
| * | |
| * The AudioContext is created at 16 kHz so no resampling is needed here. Frames | |
| * arrive 128 samples at a time (8 ms), which would be ~125 postMessage calls per | |
| * second; they are batched to 480 samples (30 ms) instead -- the same frame size | |
| * the energy gate measures RMS over, so the gate never has to re-frame a partial | |
| * block. | |
| */ | |
| const BATCH = 480; // 30 ms at 16 kHz | |
| class CaptureProcessor extends AudioWorkletProcessor { | |
| constructor() { | |
| super(); | |
| this.buf = new Float32Array(BATCH); | |
| this.at = 0; | |
| } | |
| process(inputs) { | |
| const channel = inputs[0]?.[0]; | |
| if (!channel) return true; | |
| for (let i = 0; i < channel.length; i++) { | |
| this.buf[this.at++] = channel[i]; | |
| if (this.at === BATCH) { | |
| // Transfer a copy: `buf` is reused, and the render quantum's own | |
| // input buffer is recycled by the engine after process() returns. | |
| const out = this.buf.slice(); | |
| this.port.postMessage(out, [out.buffer]); | |
| this.at = 0; | |
| } | |
| } | |
| return true; | |
| } | |
| } | |
| registerProcessor('ctc-capture', CaptureProcessor); | |