如何将React Native流式音频数据拼接并保存为可读取音频文件?
如何将react-native-live-audio-stream的流式音频数据保存为可读取的WAV文件
你需要收集流式PCM数据、生成标准WAV文件头,再将两者合并后写入文件系统。以下是完整实现步骤:
1. 安装依赖
除了buffer,还需要文件系统库来写入文件,以及权限库处理系统权限:
yarn add react-native-fs react-native-permissions
(注:需按两个库的官方文档完成原生端配置,比如iOS Info.plist、Android AndroidManifest.xml的权限声明)
2. 初始化音频数据存储
在组件中定义全局变量存储所有音频片段:
import { Buffer } from 'buffer'; import RNFS from 'react-native-fs'; import { check, request, PERMISSIONS, RESULTS } from 'react-native-permissions'; // 全局存储流式音频chunk let audioChunks = [];
3. 收集流式音频数据
修改data事件回调,将解码后的PCM片段存入数组:
LiveAudioStream.on('data', data => { const pcmChunk = Buffer.from(data, 'base64'); audioChunks.push(pcmChunk); });
4. 实现WAV文件头生成函数
WAV文件需要标准头信息才能被播放器识别,根据你的初始化配置生成对应头:
/** * 生成WAV文件头 * @param {number} sampleRate - 采样率(如32000) * @param {number} channels - 声道数(1或2) * @param {number} bitsPerSample - 位深度(8或16) * @param {number} dataLength - PCM数据总字节数 * @returns {Buffer} WAV头Buffer */ function createWavHeader(sampleRate, channels, bitsPerSample, dataLength) { const header = Buffer.alloc(44); // RIFF块 header.write('RIFF', 0); header.writeUInt32LE(44 + dataLength, 4); header.write('WAVE', 8); // fmt子块 header.write('fmt ', 12); header.writeUInt32LE(16, 16); // PCM格式子块长度固定16 header.writeUInt16LE(1, 20); // PCM音频格式标识 header.writeUInt16LE(channels, 22); header.writeUInt32LE(sampleRate, 24); const byteRate = sampleRate * channels * (bitsPerSample / 8); header.writeUInt32LE(byteRate, 28); const blockAlign = channels * (bitsPerSample / 8); header.writeUInt16LE(blockAlign, 32); header.writeUInt16LE(bitsPerSample, 34); // data子块 header.write('data', 36); header.writeUInt32LE(dataLength, 40); return header; }
5. 停止录音并保存文件
实现停止录音、合并数据、生成完整WAV文件的逻辑:
async function stopRecordingAndSave() { // 检查并请求文件读写权限(Android端) if (Platform.OS === 'android') { const writePerm = await check(PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE); if (writePerm !== RESULTS.GRANTED) { await request(PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE); } } // 停止录音 LiveAudioStream.stop(); // 合并所有PCM片段 const pcmData = Buffer.concat(audioChunks); const dataLength = pcmData.length; // 生成对应配置的WAV头 const wavHeader = createWavHeader(32000, 1, 16, dataLength); // 合并头和PCM数据 const fullWavBuffer = Buffer.concat([wavHeader, pcmData]); // 定义保存路径(示例:文档目录下的recorded_audio.wav) const savePath = `${RNFS.DocumentDirectoryPath}/recorded_audio.wav`; try { // 将Buffer以base64格式写入文件 await RNFS.writeFile(savePath, fullWavBuffer.toString('base64'), 'base64'); console.log('音频文件已保存:', savePath); // 重置片段数组,准备下次录音 audioChunks = []; } catch (err) { console.error('保存失败:', err); } }
注意事项
- 录音前必须获取麦克风权限,可通过
react-native-permissions请求PERMISSIONS.IOS.MICROPHONE或PERMISSIONS.ANDROID.RECORD_AUDIO - Android 13+需请求
READ_MEDIA_AUDIO权限替代旧的存储权限 - 初始化配置中的
wavFile参数可忽略,因为我们手动生成完整WAV文件
内容的提问来源于stack exchange,提问作者Shawn
相关产品推荐
相关产品推荐

