React Native使用Expo File System实时发送录音Socket数据损坏问题
React Native 实时录音分片发送数据损坏问题修复
核心问题分析
你的代码存在两个关键错误,导致实时录音时分片数据损坏:
- 分片读取逻辑错误:调用
FileSystem.readAsStringAsync时未指定position和length参数,每次都会读取整个音频文件,而非从currentPosition开始的指定大小分片。服务器收到重复的完整文件片段,拼接后自然无法正常解码。 - 录音文件写入未同步:录音过程中系统可能缓存写入数据,直接读取可能获取到未完全写入的不完整数据,导致开头部分数据异常。
修复后的代码
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
相关产品推荐
相关产品推荐

