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

Android中WebRTC传输MP4转文件异常:字节数组列表生成文件无法播放

问题分析与修复方案

你的问题根源出在文件分块存储和DataChannel发送逻辑的两个细节错误,导致最终合并的文件虽然大小一致,但混入了多余的无效字节,破坏了MP4的文件结构,所以无法正常播放。下面逐一拆解问题并给出修复代码:

核心问题1:分块存储时未保留实际读取长度

你用固定大小的byte[] chunk = new byte[260000]读取文件,但最后一次读取的字节数大概率小于260000。直接把整个chunk数组存入sentFileByte,会把数组中未被填充的默认0字节也存进去,这些多余的无效字节写入最终文件后,会彻底打乱MP4的格式结构。

核心问题2:DataChannel发送时ByteBuffer操作错误

你写了ByteBuffer bb = ByteBuffer.wrap(b); bb.put(b);,这里wrap(b)已经把b数组完整包装进ByteBuffer了,再调用put(b)会尝试把b数组再次写入缓冲区——但此时缓冲区的容量刚好等于b的长度,执行这个操作要么直接抛出BufferOverflowException,要么发送重复的错误数据,导致接收的块内容和原文件不符。


修复后的完整代码

1. 发送端:正确分块存储文件

FileInputStream is = new FileInputStream(file);
byte[] chunk = new byte[260000];
int chunkLen = 0;
sentFileByte = new ArrayList<>();
while ((chunkLen = is.read(chunk)) != -1) {
    // 关键:只保留实际读取到的字节,丢弃数组中未被使用的部分
    byte[] actualChunk = new byte[chunkLen];
    System.arraycopy(chunk, 0, actualChunk, 0, chunkLen);
    sentFileByte.add(actualChunk);
}
is.close(); // 务必关闭输入流,避免资源泄漏

2. 发送端:正确的DataChannel发送逻辑

byte[] b = sentFileByte.get(index);
// 直接用wrap包装数组即可,无需额外执行put操作
ByteBuffer bb = ByteBuffer.wrap(b);
dataChannel.send(new DataChannel.Buffer(bb, true));

3. 接收端:更严谨的文件合并逻辑

接收端的核心逻辑没问题,但建议用finally块确保流的关闭,避免异常导致资源泄漏:

String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath() + "/" + fileName;
File file = new File(path);
FileOutputStream fileOutputStream = null;
try {
    fileOutputStream = new FileOutputStream(file);
    for (byte[] chunk : receivedFileByteArr) {
        fileOutputStream.write(chunk);
    }
} catch (FileNotFoundException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
} finally {
    if (fileOutputStream != null) {
        try {
            fileOutputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

额外优化建议

  • 发送文件前,先把文件总块数和文件名通过DataChannel发送给接收端,让接收端明确知道需要接收的块数量,避免漏接或多接。
  • 给每个块加上序号标识,接收端按序号排序后再合并——因为WebRTC DataChannel默认是不可靠无序的,如果需要可靠有序传输,初始化DataChannel时要设置ordered: true参数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 15:37:29