feat: room-based calls + AudioWorklet for capture and playback
Rooms: - URL-based: open /myroom to join a room - Two clients in same room get bridged through relay - Input field for room name, also supports URL path and hash - Each room creates independent relay connections AudioWorklet (replaces deprecated ScriptProcessorNode): - capture-processor.js: accumulates mic samples, sends 960-sample frames - playback-processor.js: pull-based output with 200ms buffer cap - Falls back to ScriptProcessor if AudioWorklet unavailable - Eliminates drift: worklet runs on audio thread, not main thread Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
39
crates/wzp-web/static/audio-processor.js
Normal file
39
crates/wzp-web/static/audio-processor.js
Normal file
@@ -0,0 +1,39 @@
|
||||
// AudioWorklet processor for capturing microphone audio.
|
||||
// Accumulates samples and posts 960-sample (20ms @ 48kHz) frames to the main thread.
|
||||
|
||||
class CaptureProcessor extends AudioWorkletProcessor {
|
||||
constructor() {
|
||||
super();
|
||||
this.buffer = new Float32Array(0);
|
||||
}
|
||||
|
||||
process(inputs, outputs, parameters) {
|
||||
const input = inputs[0];
|
||||
if (!input || !input[0]) return true;
|
||||
|
||||
const samples = input[0]; // Float32Array, typically 128 samples
|
||||
|
||||
// Accumulate
|
||||
const newBuf = new Float32Array(this.buffer.length + samples.length);
|
||||
newBuf.set(this.buffer);
|
||||
newBuf.set(samples, this.buffer.length);
|
||||
this.buffer = newBuf;
|
||||
|
||||
// Send complete 960-sample frames
|
||||
while (this.buffer.length >= 960) {
|
||||
const frame = this.buffer.slice(0, 960);
|
||||
this.buffer = this.buffer.slice(960);
|
||||
|
||||
// Convert to Int16
|
||||
const pcm = new Int16Array(960);
|
||||
for (let i = 0; i < 960; i++) {
|
||||
pcm[i] = Math.max(-32768, Math.min(32767, Math.round(frame[i] * 32767)));
|
||||
}
|
||||
this.port.postMessage(pcm.buffer, [pcm.buffer]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
registerProcessor('capture-processor', CaptureProcessor);
|
||||
Reference in New Issue
Block a user