You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

Android版Edge中通过Blob URL加载本地MP4至video元素时出现错误码4,同设备Chrome可正常播放

Android版Edge中通过Blob URL加载本地MP4至video元素时出现错误码4,同设备Chrome可正常播放

问题描述

我在三星S21 FE(Android 14)设备上做了一个本地MP4播放测试:通过文件选择器选取本地MP4,用URL.createObjectURL生成Blob URL赋值给<video>元素。这个逻辑在Chrome和三星互联网浏览器里完全正常,但在Android版Microsoft Edge里总是触发error事件,错误码为4(对应MEDIA_ERR_SRC_NOT_SUPPORTED),错误信息显示PipelineStatus::DEMUXER_ERROR_DETECTED_AAC

以下是最小可复现的测试代码:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<input type="file" id="pick" accept="video/mp4">
<pre id="log">Pick a file…</pre>
<video id="v" controls playsinline width="320" style="background:#000;display:block"></video>
<script>
const pre = document.getElementById('log');
const v   = document.getElementById('v');
const log = (msg) => pre.textContent += '\n' + msg;

document.getElementById('pick').addEventListener('change', function () {
    const file = this.files[0];
    if (!file) return;
    pre.textContent = '';
    log('name : ' + file.name);
    log('size : ' + file.size + ' bytes');
    log('type : ' + file.type);
    log('canPlayType("video/mp4")                     : ' + v.canPlayType('video/mp4'));
    log('canPlayType("video/mp4; codecs=avc1.640033") : ' + v.canPlayType('video/mp4; codecs="avc1.640033"'));
    
    const url = URL.createObjectURL(file);
    log('\nblobUrl: ' + url);
    
    v.addEventListener('loadstart',      () => log('EVENT loadstart'),      { once: true });
    v.addEventListener('loadedmetadata', () => log('EVENT loadedmetadata'), { once: true });
    v.addEventListener('canplay',        () => log('EVENT canplay'),        { once: true });
    v.addEventListener('playing',        () => log('EVENT playing'),        { once: true });
    v.addEventListener('error', () => {
      const e = v.error;
      log('EVENT error  code=' + (e && e.code) + '  message=' + (e && e.message));
    }, { once: true });
    
    v.src = url;
  });
</script>
</body>
</html>

在Android版Edge上的输出日志:

name : 1000015422.mp4
size : 9604041 bytes
type : video/mp4
canPlayType("video/mp4") : maybe
canPlayType("video/mp4; codecs=avc1.640033") : probably

blobUrl: blob:http://172.20.10.9:8080/50c4918e-...
EVENT loadstart
EVENT error code=4 message=PipelineStatus::DEMUXER_ERROR_DETECTED_AAC

问题分析

从日志和现象能拆解出几个关键点:

  1. Edge通过canPlayType判断MP4格式是支持的,但实际解析时却失败,说明格式检测和实际解码逻辑存在不一致;
  2. 错误提示指向AAC音频流的解封装错误,且仅在Edge中出现,排除了文件本身或系统解码库的问题;
  3. 仅触发loadstart就报错,说明Edge在处理Blob URL指向的文件时,在解封装阶段就出现了兼容性bug。

可行的解决办法

针对Edge Android的这个兼容性问题,可以尝试以下几种方案:

方案1:改用srcObject直接绑定File对象

现代浏览器已经支持直接将File对象赋值给video.srcObject,跳过Blob URL的创建步骤,这能绕开Edge对Blob URL的处理bug:

// 替换原代码中创建Blob URL和赋值的部分
// const url = URL.createObjectURL(file);
// log('\nblobUrl: ' + url);
// v.src = url;

v.srcObject = file;
log('Using srcObject instead of blob URL');

注意:在不需要播放时,记得调用v.srcObject = null释放资源,避免内存泄漏。

方案2:通过FileReader中转生成新Blob

如果必须使用Blob URL,可以通过FileReader将File转为ArrayBuffer,再重新创建Blob,绕开Edge对原始File生成Blob的处理逻辑:

document.getElementById('pick').addEventListener('change', function () {
    const file = this.files[0];
    if (!file) return;
    pre.textContent = '';
    // 保留原有的log逻辑...

    const reader = new FileReader();
    reader.onload = function(e) {
        const arrayBuffer = e.target.result;
        const newBlob = new Blob([arrayBuffer], { type: file.type });
        const url = URL.createObjectURL(newBlob);
        log('\nblobUrl (from ArrayBuffer): ' + url);
        
        // 绑定事件并赋值
        // 原有的事件监听逻辑保持不变
        v.src = url;
    };
    reader.onerror = () => log('FileReader error: ' + reader.error);
    reader.readAsArrayBuffer(file);
});

方案3:更新Edge版本并反馈问题

  1. 先确认你的Edge是最新版本,尝试更新后再测试,可能该bug已在新版本中修复;
  2. 如果更新后问题依旧,可通过Edge内的「反馈」功能提交问题,附上测试代码、设备信息和错误日志,帮助微软修复兼容性问题。

生产环境兼容提示

如果是面向用户的生产环境代码,建议做降级处理:

  • 优先使用srcObject,通过特性检测判断浏览器支持情况;
  • 在触发error事件时,提示用户切换浏览器,或提供下载文件的备选方案;
  • 记得在所有场景下清理资源:使用Blob URL时调用URL.revokeObjectURL,使用srcObject时及时置空。

火山引擎 最新活动