You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 03:12:04