获取 PCM 数据
处理 PCM 数据
Float32 转 Int16
ArrayBuffer 转 Base64
PCM 文件播放
重采样
PCM 转 MP3
PCM 转 WAV
短时能量计算
Web Worker优化性能
音频存储(IndexedDB)
WebView 开启 WebRTC
获取 PCM 数据
样例代码:
const mediaStream = await window.navigator.mediaDevices.getUserMedia({
audio: {
// sampleRate: 44100, // 采样率 不生效需要手动重采样
channelCount: 1, // 声道
// echoCancellation: true,
// noiseSuppression: true, // 降噪 实测效果不错
},
})
const audioContext = new window.AudioContext()
const inputSampleRate = audioContext.sampleRate
const mediaNode = audioContext.createMediaStreamSource(mediaStream)
if (!audioContext.createScriptProcessor) {
audioContext.createScriptProcessor = audioContext.createJavaScriptNode
}
// 创建一个jsNode
const jsNode = audioContext.createScriptProcessor(4096, 1, 1)
jsNode.connect(audioContext.destination)
jsNode.onaudioprocess = (e) => {
// e.inputBuffer.getChannelData(0) (left)
// 双通道通过e.inputBuffer.getChannelData(1)获取 (right)
}
mediaNode.connect(jsNode)
简要流程如下:
start=>start: 开始
getUserMedia=>operation: 获取MediaStream
audioContext=>operation: 创建AudioContext
scriptNode=>operation: 创建scriptNode并关联AudioContext
onaudioprocess=>operation: 设置onaudioprocess并处理数据
end=>end: 结束
start->getUserMedia->audioContext->scriptNode->onaudioprocess->end
停止录制只需要把 audioContext 挂在的 node 卸载即可,然后把存储的每一帧数据合并即可产出 PCM 数据
jsNode.disconnect()
mediaNode.disconnect()
jsNode.onaudioprocess = null
PCM 数据处理
通过 WebRTC 获取的 PCM 数据格式是 Float32 的, 如果是双通道录音的话, 还需要增加合并通道
const leftDataList = [];
const rightDataList = [];
function onAudioProcess(event) {
// 一帧的音频PCM数据
let audioBuffer = event.inputBuffer;
leftDataList.push(audioBuffer.getChannelData(0).slice(0));
rightDataList.push(audioBuffer.getChannelData(1).slice(0));
}
// 交叉合并左右声道的数据
function interleaveLeftAndRight(left, right) {
let totalLength = left.length + right.length;
let data = new Float32Array(totalLength);
for (let i = 0; i < left.length; i++) {
let k = i * 2;
data[k] = left[i];
data[k + 1] = right[i];
}
return data;
}
Float32 转 Int16
const float32 = new Float32Array(1)
const int16 = Int16Array.from(
float32.map(x => (x > 0 ? x * 0x7fff : x * 0x8000)),
)
arrayBuffe