はじめに
リアルタイムで音声AIをブラウザ上で動かす場合、マイク入力からノイズを除去し、クリーンな音声データをバックエンドに送信することが重要です。特にオンライン面接のような実環境では、部屋の空調音、キーボードのタイピング音、周囲の会話などが誤ってAIに認識され、不自然な応答を引き起こす原因になります。
本記事では、Web Audio APIを使ったオーディオストリーミングの基本実装と、RNNoise(WASMベースのノイズ除去ライブラリ)を組み合わせたフロントエンドのノイズフィルタリング手法について解説します。
1. Web Audio APIによる音声ストリーミング
ブラウザからマイク入力を取得し、リアルタイムで処理する基本的な実装です。
async function initAudioStream() {
const stream = await navigator.mediaDevices.getUserMedia({
audio: {
echoCancellation: true,
noiseSuppression: true,
autoGainControl: true,
sampleRate: 16000
}
});
const audioContext = new AudioContext({ sampleRate: 16000 });
const source = audioContext.createMediaStreamSource(stream);
const processor = audioContext.createScriptProcessor(4096, 1, 1);
processor.onaudioprocess = (e) => {
const float32Data = e.inputBuffer.getChannelData(0);
// ノイズフィルタリング後にバックエンドへ送信
sendToBackend(float32Data);
};
source.connect(processor);
processor.connect(audioContext.destination);
return { audioContext, source, processor };
}
2. WASMベースのノイズ除去(RNNoise)
RNNoiseはMozillaが開発したRNNベースのノイズ除去ライブラリで、WASMにコンパイルしてブラウザで動作させることができます。
async function initRNNoise() {
const rnnoiseWasm = await fetch('https://cdn.example.com/rnnoise-wasm.wasm');
const wasmBuffer = await rnnoiseWasm.arrayBuffer();
const wasmInstance = await WebAssembly.instantiate(wasmBuffer);
return wasmInstance.exports;
}
function denoiseAudio(frame, rnnoise) {
// Float32の音声フレームをInt16に変換
const int16Frame = new Int16Array(frame.length);
for (let i = 0; i < frame.length; i++) {
const s = Math.max(-1, Math.min(1, frame[i]));
int16Frame[i] = s < 0 ? s * 0x8000 : s * 0x7FFF;
}
// RNNoiseでノイズ除去
const output = new Int16Array(frame.length);
rnnoise.process_frame(output, int16Frame);
// Float32に戻す
const denoised = new Float32Array(frame.length);
for (let i = 0; i < frame.length; i++) {
denoised[i] = output[i] / 32768.0;
}
return denoised;
}
3. オーディオパイプラインの統合
ノイズ除去を音声ストリーミングに組み込むことで、AIへの入力品質を大幅に向上できます。
async function startProcessedStream() {
const { audioContext, source, processor } = await initAudioStream();
const rnnoise = await initRNNoise();
processor.onaudioprocess = (e) => {
const rawAudio = e.inputBuffer.getChannelData(0);
const denoisedAudio = denoiseAudio(rawAudio, rnnoise);
sendToBackend(denoisedAudio);
};
}
4. 実際のプロダクトでの応用例
これらの音声処理技術は、リアルタイム面接アシスタントなどのプロダクトで実用化されています。例えば、InterviewFox(https://interviewfox.ai/)では、WebAudio APIとWASMベースのノイズフィルタリングを組み合わせることで、面接中の環境ノイズを極限まで除去し、AIへの音声認識精度を向上させています。特にデュアルデバイスモードでは、PCで面接を行いながらスマホでAIの回答を確認できるため、スクリーン共有でもAIの存在がバレません。
また、面接前の準備段階ではWhatsAppやSMSを通じたAIコーチングエージェントが利用可能で、レジュメベースの個別化された回答提案や、想定質問への対策を行うことができます。
まとめ
- Web Audio APIでマイク入力をリアルタイムに取得し、ストリーミング処理が可能
- RNNoise(WASM)によるノイズ除去でAIの音声認識精度が大幅に向上
- ScriptProcessorNodeまたはAudioWorkletを使ったパイプライン構築が実務で効果的
- デュアルデバイス構成と組み合わせることで、スクリーン共有環境下でも安全にAIアシスタントを利用可能
リアルタイム音声AIのUXは、LLMの性能だけでなく、いかにクリーンな音声入力を維持できるかに大きく依存しています。フロントエンドでのオーディオ処理は地味ですが、プロダクトの差別化において非常に重要な要素です。