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

React Native使用Expo File System实时发送录音Socket数据损坏问题

React Native 实时录音分片发送数据损坏问题修复

核心问题分析

你的代码存在两个关键错误,导致实时录音时分片数据损坏:

  1. 分片读取逻辑错误:调用FileSystem.readAsStringAsync时未指定position和length参数,每次都会读取整个音频文件,而非从currentPosition开始的指定大小分片。服务器收到重复的完整文件片段,拼接后自然无法正常解码。
  2. 录音文件写入未同步:录音过程中系统可能缓存写入数据,直接读取可能获取到未完全写入的不完整数据,导致开头部分数据异常。

修复后的代码

export async function uploadChunksToServer(recordingInstance, chunkSize, delayBetweenChunks) {
  let info = await FileSystem.getInfoAsync(recordingInstance.getURI());
  let uri = info.uri;
  let currentPosition = 0;
  let prevFileSize = info.size;

  await sleep(delayBetweenChunks);

  while (true) {
    try {
      // 获取当前文件最新信息
      const info = await FileSystem.getInfoAsync(recordingInstance.getURI());
      const currentFileSize = info.size;

      // 文件无新增数据且录音未完成时,等待下一轮检查
      if (currentFileSize === prevFileSize && !recordingInstance._isDoneRecording) {
        await sleep(delayBetweenChunks);
        continue;
      }

      // 计算当前可读取的最大分片长度
      const availableBytes = currentFileSize - currentPosition;
      if (availableBytes <= 0) {
        if (recordingInstance._isDoneRecording) break;
        await sleep(delayBetweenChunks);
        continue;
      }
      const readLength = Math.min(chunkSize, availableBytes);

      // 读取指定位置和长度的分片
      const fileChunk = await FileSystem.readAsStringAsync(uri, {
        encoding: FileSystem.EncodingType.Base64,
        position: currentPosition,
        length: readLength,
        cache: false // 禁用缓存,确保读取最新写入的数据
      });

      // 发送分片并更新状态
      socket.emit('audioData', fileChunk);
      currentPosition += readLength;
      prevFileSize = currentFileSize;

      // 录音完成且数据已全部发送时退出
      if (recordingInstance._isDoneRecording && currentPosition >= currentFileSize) {
        break;
      }

      await sleep(delayBetweenChunks);
    } catch (e) {
      console.error('分片读取/发送失败:', e);
    }
  }

  console.log('所有分片发送完成 >> 已发送字节:', currentPosition, '文件总大小:', prevFileSize);
  socket.emit('done_recording'); // 仅发送结束信号,无需重复发送全文件
}

关键修复点说明

  • 明确分片读取范围:每次读取时指定position和length参数,确保只读取未发送的分片数据,避免重复发送完整文件。
  • 优化文件变化检测:仅在文件大小新增时读取数据,避免无效循环,同时处理录音未完成时的等待逻辑。
  • 禁用读取缓存:添加cache: false参数,确保读取录音过程中实时写入的最新数据,避免读取到缓存的旧数据。
  • 移除冗余操作:done_recording仅发送结束信号,无需重复发送整个音频文件,减少带宽浪费。

额外注意事项

  • 确保录音格式(如AAC、MP3)与服务器解码格式兼容,避免因格式不兼容导致无法播放。
  • 实时发送时,建议在audioData事件中附带分片序号,服务器按序号拼接数据,避免网络乱序导致拼接错误。

内容的提问来源于stack exchange,提问作者cbum_299

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 21:22:18