如何正确捕获HTML5 Video对象的错误消息?
视频URL过期后error事件无响应问题排查
问题现象
- 视频URL有效时可正常播放
- URL过期后控制台可看到资源加载报错,但绑定在
<video>元素上的各类error事件完全不触发 - 已验证jQuery的
.on()绑定机制本身正常,同元素绑定的loadstart事件可正常触发

现有实现代码
<video id="product_video" data-able-player playsinline preload="auto"> <source type="video/mp4" src="https://xxxx.yyy.com/xxx/SH/SH-001.mp4?Policy=eyJTdGF0...X1dfQ__&Signature=MsO...A__&Key-Pair-Id=xxx" /> <track kind="captions" src="https://xxxx.yyy.com/SH-001_captions.vtt"/> <track kind="chapters" src="https://xxxx.yy.com/SH-001_chapters.vtt"/> </video>
var video = $('#product_video'); // 可正常触发 video.on('loadstart', function(event) { console.debug('video.on.loadstart'); }); // 完全不触发 video.on('error', function() { console.debug('video.on.error'); alert('video: uh oh'); }); // 完全不触发 video.last().on('error', function() { console.debug('player.last.on.error'); alert('player uh oh'); }); // 完全不触发 var vid = document.getElementById("product_video"); vid.onerror = function() { alert("Error! Something went wrong"); }; vid.addEventListener("error", function(e) { console.log("<video> error"); console.log(e.target.error); });
问题根因
事件绑定的层级和目标完全错误:
- 按照HTML媒体元素规范,当
<source>标签指定的媒体资源加载失败时,对应的错误事件会直接派发在<source>元素上,且不参与冒泡流程,事件不会向上传递到父级的<video>元素,所有直接绑定在<video>上的error监听器都无法捕获到这类错误。 - 代码中
video.last().on('error')存在选择器误区:video变量是通过$('#product_video')选中的单个<video>元素,调用.last()返回的还是这个<video>元素本身,不会自动选中其子元素,本质和前面直接给video绑error的逻辑完全一致。 - 控制台看到的资源4xx/加载失败报错,正是
<source>节点抛出的网络层错误,因为事件不冒泡,父级video元素无法感知。 - 部分场景下使用第三方视频封装库时,需要额外确认库本身是否对资源错误事件做了拦截,但本案例中的失效场景,核心问题是原生事件的绑定位置错误,和播放器逻辑无关。
修复方案
- 直接给页面内所有
<source>元素绑定error事件,即可拿到实际的视频资源加载失败通知 - 若不想单独给每个source节点绑定监听,也可以在
<video>元素上通过捕获模式监听error事件,就能捕获到source节点抛出的不冒泡错误 - 监听时可过滤
<track>字幕、章节元素抛出的错误,避免误触发提示
可参考的正确代码
// 方式1:直接给source元素绑定error监听 $('#product_video source').on('error', function() { console.log('视频资源加载失败,对应地址:', this.src); alert('视频加载失败,请刷新重试'); }); // 方式2:在video元素上用捕获模式统一监听 vid.addEventListener("error", function(e) { // 仅处理source元素抛出的错误,过滤track类元素的错误 if (e.target.tagName === 'SOURCE') { console.log('资源加载失败详情:', e.target.error); } }, true); // 第三个参数传入true,代表在捕获阶段监听
内容的提问来源于stack exchange,提问作者GDP
相关产品推荐
相关产品推荐

