使用JavaScript和ffmpeg.wasm将录音Blob流切分成5秒WAV文件
实现思路
要实现录音Blob流的切割,我们需要完成以下步骤:
- 获取录音数据并转换为适合处理的格式
- 使用ffmpeg.wasm加载音频数据
- 计算切割时间点并将音频分割成多个5秒片段
- 将每个片段导出为WAV格式文件
完整实现代码
// 初始化ffmpeg.wasm
const { createFFmpeg, fetchFile } = FFmpeg;
const ffmpeg = createFFmpeg({ log: true });
// 录音数据切割函数
async function splitRecordingIntoChunks(recordingBlob, chunkDuration = 5) {
// 确保ffmpeg已加载
if (!ffmpeg.isLoaded()) {
await ffmpeg.load();
}
// 将Blob转换为Uint8Array
const arrayBuffer = await recordingBlob.arrayBuffer();
const uint8Array = new Uint8Array(arrayBuffer);
// 写入输入文件到ffmpeg文件系统
ffmpeg.FS('writeFile', 'input.webm', uint8Array);
// 获取音频时长
await ffmpeg.run('-i', 'input.webm', '-f', 'null', '-');
const durationOutput = ffmpeg.FS('readFile', 'stderr').toString();
const durationMatch = durationOutput.match(/Duration: (\d+):(\d+):(\d+\.\d+)/);
if (!durationMatch) {
throw new Error('无法获取音频时长');
}
const hours = parseInt(durationMatch[1]);
const minutes = parseInt(durationMatch[2]);
const seconds = parseFloat(durationMatch[3]);
const totalDuration = hours * 3600 + minutes * 60 + seconds;
console.log(`总时长: ${totalDuration}秒`);
// 计算切割数量
const numChunks = Math.ceil(totalDuration / chunkDuration);
const chunks = [];
// 切割音频
for (let i = 0; i < numChunks; i++) {
const startTime = i * chunkDuration;
const outputFileName = `output_${i}.wav`;
// 使用ffmpeg切割音频
await ffmpeg.run(
'-i', 'input.webm',
'-ss', startTime.toString(),
'-t', chunkDuration.toString(),
'-acodec', 'pcm_s16le',
'-ar', '44100',
'-ac', '2',
outputFileName
);
// 读取切割后的文件
const data = ffmpeg.FS('readFile', outputFileName);
// 创建Blob对象
const blob = new Blob([data.buffer], { type: 'audio/wav' });
chunks.push({
index: i,
startTime: startTime,
endTime: Math.min(startTime + chunkDuration, totalDuration),
blob: blob,
url: URL.createObjectURL(blob)
});
}
return chunks;
}
// 使用示例
async function processRecording(recordingBlob) {
try {
const chunks = await splitRecordingIntoChunks(recordingBlob, 5);
// 处理每个切割后的音频块
chunks.forEach(chunk => {
console.log(`片段 ${chunk.index}: ${chunk.startTime}s - ${chunk.endTime}s`);
// 可以在这里添加下载或其他处理逻辑
// 例如:创建一个下载链接
const a = document.createElement('a');
a.href = chunk.url;
a.download = `recording_part_${chunk.index}.wav`;
a.textContent = `下载片段 ${chunk.index}`;
document.body.appendChild(a);
});
return chunks;
} catch (error) {
console.error('处理录音时出错:', error);
}
}关键步骤解析
1. 初始化ffmpeg.wasm
首先需要加载ffmpeg.wasm库,这是处理音频的核心工具。
2. 音频数据处理
将录音得到的Blob对象转换为Uint8Array,然后写入ffmpeg的文件系统中,以便后续处理。
3. 获取音频时长
通过ffmpeg分析音频文件,提取出总时长信息,这是计算切割点的基础。
4. 切割逻辑
根据指定的片段时长(默认5秒),计算每个片段的起始时间,然后使用ffmpeg的-ss和-t参数进行精确切割。
5. 输出WAV文件
设置音频编码参数为pcm_s16le,采样率44100Hz,双声道,确保输出为标准WAV格式。
注意事项
- ffmpeg.wasm加载可能需要一些时间,建议在应用初始化时提前加载
- 处理大型音频文件时可能会消耗较多内存和时间
- 切割点可能不是精确的5秒,因为音频编码的关系
- 记得在使用完毕后释放创建的URL对象,避免内存泄漏
浏览器兼容性
此方案基于WebAssembly,现代浏览器基本都支持,但需要注意ffmpeg.wasm的文件大小可能影响初始加载时间。