在使用react-mic进行录音时,遇到一个需求:需要将录音的blob流切分成多个5秒的wav文件。然而,尝试之后发现只有第一个切分的wav文件能够正常播放,其余文件均提示文件损坏。
在前端实现这个需求时,主要面临两个挑战:一是如何正确切分blob流,二是如何确保每个切分后的片段能够正确生成并播放wav文件。以下是代码示例和解决思路:
import React, { useRef, useState } from 'react'
import { ReactMic, ReactMicStopEvent } from 'react-mic'
import { Button } from 'antd'
const AudioRecorder = () => {
const [record, setRecord] = useState(false)
const resRef = useRef<Blob[]>([])
const audioChunksRef = useRef<Blob[]>([])
const intervalRef = useRef<NodeJS.Timer | null>(null)
const firstBlob = useRef<Blob | undefined>(undefined)
const createWavHeader = (numChannels, sampleRate, byteLength) => {
const header = new ArrayBuffer(44);
const view = new DataView(header);
view.setUint32(0, 1380533830, false); // "RIFF"
view.setUint32(4, byteLength + 36, false);
view.setUint32(8, 1718449184, false); // "WAVE"
view.setUint32(12, 1684108385, false); // "fmt "
view.setUint32(16, 16, true); // 16 for PCM
view.setUint16(20, 1, true); // PCM
view.setUint16(22, numChannels, true);
view.setUint32(24, sampleRate, true);
view.setUint32(28, sampleRate * numChannels * 2, true);
view.setUint16(32, numChannels * 2, true);
view.setUint16(34, 16, true); // 16 bits
view.setUint32(36, 1684108385, false); // "data"
view.setUint32(40, byteLength, true);
return header;
};
const saveFile = async () => {
const chunksList = resRef.current;
for (let i = 0; i < chunksList.length; i++) {
const audioBuffer = new Uint8Array(await chunksList[i].arrayBuffer());
const header = createWavHeader(1, 44100, audioBuffer.length); // 假设单声道和 44100Hz
const wavBlob = new Blob([header, audioBuffer], { type: 'audio/wav' });
const url = URL.createObjectURL(wavBlob);
const a = document.createElement('a');
a.href = url;
a.download = `recording${i}.wav`;
a.click();
URL.revokeObjectURL(url);
}
};
const startRecording = () => {
setRecord(true)
audioChunksRef.current = [] // 清空之前的录音数据
// 每5秒分割一次录音
intervalRef.current = setInterval(() => {
const curBlob = new Blob(audioChunksRef.current, { type: 'audio/wav' })
const startIndex = audioChunksRef.current.indexOf(firstBlob.current as Blob)
const blob = curBlob.slice(startIndex === -1 ? 0 : startIndex, -1, 'audio/wav')
firstBlob.current = audioChunksRef.current.at(-1)
// 处理当前录音数据
console.log('分割当前录音数据:', blob)
resRef.current.push(blob)
}, 5000)
}
const stopRecording = () => {
setRecord(false)
intervalRef.current && clearInterval(intervalRef.current) // 清除定时器
}
const onData = (recordedBlob: Blob) => {
audioChunksRef.current.push(recordedBlob) // 保存录音数据
}
const onStop = (recordedBlob: ReactMicStopEvent) => {
console.log('录音完成:', recordedBlob)
}
const saveFile1 = () => {
const chunksList = resRef.current
chunksList.map(async (v, i) => {
const fileName = 'aaa.wav'
const file: File = new File([v], fileName, { type: 'audio/wav' })
const fileSize = file.size
console.log('fileSize', fileSize)
// 创建下载链接
const url = URL.createObjectURL(file)
const a = document.createElement('a')
a.href = url
a.download = `recording${i}.wav` // 设置下载文件的名称
a.click() // 触发下载
// 释放URL资源
URL.revokeObjectURL(url)
})
}
const saveFinalResult = () => {
const fileName = 'aaa.wav'
const file: File = new File(audioChunksRef.current, fileName, { type: 'audio/wav' })
const fileSize = file.size
console.log('fileSize', fileSize)
// 创建下载链接
const url = URL.createObjectURL(file)
const a = document.createElement('a')
a.href = url
a.download = `recording${Date.now()}.wav` // 设置下载文件的名称
a.click() // 触发下载
// 释放URL资源
URL.revokeObjectURL(url)
}
return (
<div>
<ReactMic record={record} onStop={onStop} onData={onData} mimeType="audio/wav" />
<Button onClick={startRecording}>开始录音</Button>
<Button onClick={stopRecording}>停止录音</Button>
<Button onClick={saveFile}>下载</Button>
<Button onClick={saveFinalResult}>下载Final</Button>
</div>
)
}
export default AudioRecorder在尝试切分blob流和生成wav文件的过程中,发现手动添加wav头信息并不能解决问题。其原因在于wav文件的结构比较严格,切分后如果不正确地添加头部信息,文件可能会损坏。
解决这个问题的一个建议是使用ffmpeg的wasm版本,这是一个可以在浏览器中运行的音视频处理库。通过它,你可以轻松地对音频进行切分并生成正确的wav文件格式。可以考虑使用ffmpeg.wasm项目来实现这个功能。
以上就是如何使用JavaScript将录音的Blob流切分成多个5秒的WAV文件并确保其正常播放?的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号