需要实现录音采集到片段录音ArrayBuffer数据,要求采样率为16000hz,并发送给后端进行翻译,已走通createScriptProcessor但是该api将被弃用,因此需要找其他方案,以此记录解决的思考过程。
| 知识名称 | 解释 |
|---|---|
| MediaRecorder | 在浏览器javascript中,默认的采样率可能是48000 |
| AudioWorklet | 可以自定义音频数据处理 |
| createMediaElementSource | 将音频流引入到Web Audio上下文中,使得音频可以被进一步处理 |
| MediaStreamAudioSourceNode | 用于从MediaStream中创建音频源,用于实时音频处理 |
| audioContext.destination | 用户的音频输出设备 |
| navigator.mediaDevices.getUserMedia({ audio: true }) | 请求麦克风权限,并获取到音频的MediaStream |
AudioWorklet使用示例
AudioWorklet 是Web Audio API中的一个高级特性,它允许开发者编写自定义音频处理节点,这些节点在浏览器的音频线程上运行,从而提供低延迟和高性能的音频处理能力。以下是一个简单的AudioWorklet使用示例,我们将创建一个简单的音频处理工作线程,该工作线程将输入音频的音量放大两倍。
第一步:定义AudioWorklet Processor 首先,你需要定义你的AudioWorklet Processor。这通常在一个.js文件中完成,比如我们创建一个名为volume-processor.js的文件:
class VolumeProcessor extends AudioWorkletProcessor {
process(inputs, outputs, parameters) {
// 获取第一个输出通道
const output = outputs[0];
// 遍历当前音频块的每个样本
for (let channel = 0; channel < output.length; channel++) {
const inputChannel = inputs[0][channel];
for (let i = 0; i < inputChannel.length; i++) {
// 将输入音频的音量放大两倍
output[channel][i] = inputChannel[i] * 2;
}
}
// 表示处理器需要继续被调用
return true;
}
}
registerProcessor('volume-processor', VolumeProcessor);
registerProcessor('volume-processor', VolumeProcessor); 这段代码定义了一个名为VolumeProcessor的类,继承自AudioWorkletProcessor。process方法是必须重写的,它接收输入音频数据、输出音频数据以及可能的参数,并在此方法内执行音频处理逻辑。在这个例子中,我们将每个输入样本的值乘以2来实现音量放大。
第二步:注册AudioWorklet Processor 在主JavaScript文件中(例如你的网页的脚本),你需要确保AudioWorklet已经被注册并初始化:
(async function() {
// 确保AudioContext构造函数可用
if (typeof AudioWorklet !== 'undefined') {
// 等待AudioWorklet被初始化
await AudioWorklet.registerProcessor('volume-processor', '/path/to/volume-processor.js');
// 创建AudioContext实例
const audioContext = new AudioContext();
// ... 其他音频处理逻辑,如创建MediaElementSource、连接AudioWorklet等
} else {
console.error('AudioWorklet is not supported in this browser.');
}
})();
这段代码首先检查浏览器是否支持AudioWorklet,然后等待volume-processor通过其路径被注册。注意,你需要将'/path/to/volume-processor.js'替换为实际的文件路径。
第三步:使用AudioWorklet Node 一旦AudioWorklet被注册,你就可以在音频图中使用它了。这里是一个简化的例子,展示如何创建一个source节点并将它与我们的AudioWorklet节点连接起来:
// 假设有一个HTML的<audio>元素
const audioElement = document.querySelector('audio');
// 创建MediaElementAudioSourceNode
const source = audioContext.createMediaElementSource(audioElement);
// 创建AudioWorkletNode
const volumeWorklet = new AudioWorkletNode(audioContext, 'volume-processor');
// 连接音频节点
source.connect(volumeWorklet);
volumeWorklet.connect(audioContext.destination);
这段代码从HTML中的音频元素创建了一个源节点,然后创建了一个指向我们之前注册的volume-processor的AudioWorkletNode,并将其连接到音频上下文的destination,即扬声器。
以上就是使用AudioWorklet创建一个简单音量放大的音频处理节点的基本步骤。根据具体需求,你可以扩展VolumeProcessor类来实现更复杂的音频处理算法。
实时录音获取数据主要思路
- 用户访问麦克风权限获取stream。
- 使用MediaStreamAudioSourceNode,stream作为入参生成音频源sourceNode。
- volume-process.js创建音频处理类,并使用registerProcessor进行注册。
- 在主线程使用audioContext.audioWorklet.addModule加载volume-process.js
- 创建volumeWorklet,volumeWorklet = new AudioWorkletNode(audioContext, 'volume-processor')
- 音频源连接volumeWorklet,sourceNode.connect(volumeWorklet)
- 创建MediaRecorder,以sourceNode.mediaStream作为入参
- 通过MediaRecorder.start,数据开始经过volumeWorklet进行处理。
- volumeWorklet有两个作用,收集x秒的音频数据进行重采样后发送到主线程,或者将收到主线程结束录音信息,将剩余数据处理后发送到主线程。
主线程与AudioWorkletProcessor线程之间的数据传输
1.主线程向processor发送数据,可通过AudioParams 2.processsor向主线程发送数据,可通过port.postMessage