javascript 如何使用 HTML5 视频标签捕获 NETWORK_NO_SOURCE 错误

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9175415/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 05:49:49  来源:igfitidea点击:

How to Catch NETWORK_NO_SOURCE Errors with an HTML5 Video Tag

javascripthtml5-video

提问by voidstate

If none of the < source > tags provided for an HTML5 < video > tag are playable, I want to display an error.

如果为 HTML5 <video> 标签提供的 <source> 标签均不可播放,我想显示错误。

According to this page on the Mozilla Developer Network, it seems I have to check the networkState property of the video element to see if any sources loaded, as each seperate source tag throws its own error when it fails to load.

根据Mozilla Developer Network 上的这个页面,似乎我必须检查视频元素的 networkState 属性以查看是否加载了任何源,因为每个单独的源标记在加载失败时都会抛出自己的错误。

To detect that all child elements have failed to load, check the value of the media element's networkState attribute. If this is HTMLMediaElement.NETWORK_NO_SOURCE, you know that all the sources failed to load.

要检测所有子元素都未能加载,请检查媒体元素的 networkState 属性的值。如果这是 HTMLMediaElement.NETWORK_NO_SOURCE,则您知道所有源都无法加载。

But at what point should I check the networkState? If I check immediately on calling video_tag.load(), it always tells me the networkState is NETWORK_NO_SOURCE even if the source elements are valid and the video plays fine. Therefore, I assume I hvae to wait until the source tags have been tried by the browser.

但是我应该在什么时候检查 networkState?如果我在调用 video_tag.load() 时立即检查,它总是告诉我 networkState 是 NETWORK_NO_SOURCE,即使源元素有效并且视频播放正常。因此,我假设我一直等到浏览器尝试过源标签。

Here's the test:

这是测试:

var state = this._video_tag.networkState;       
console.log( 'networkState', state );
if( state == this._video_tag.NETWORK_NO_SOURCE )
{
    throw new Error( 'No valid sources' );
}

I have tried all of the following video element events with invalid source tags: loadstart, loadedmetadata, loadeddata & error with the following results (in Firefox):

我已经尝试了以下所有带有无效源标记的视频元素事件:loadstart、loadedmetadata、loadeddata 和错误,结果如下(在 Firefox 中):

  • loadstart: called but networkState is NETWORK_LOADING
  • loadedmetadata: not called
  • loadeddata: not called
  • error: not called
  • loadstart: 被调用但 networkState 是 NETWORK_LOADING
  • 加载元数据:未调用
  • 加载数据:未调用
  • 错误:未调用

However, if I check out the video tag in Firebug, the networkState is NETWORK_NO_SOURCE just as expected.

但是,如果我在 Firebug 中查看 video 标签,则 networkState 和预期的一样是 NETWORK_NO_SOURCE。

What event should I be using to control when to check the video tag, or is there a better way of doing this?

我应该使用什么事件来控制何时检查视频标签,或者有​​更好的方法吗?

回答by longi

i used sth this to check network status of the videos. this is taken from official w3c html5 page ( http://dev.w3.org/html5/spec/Overview.html#the-video-element)

我用这个来检查视频的网络状态。这是取自官方 w3c html5 页面(http://dev.w3.org/html5/spec/Overview.html#the-video-element

<script>
 function failed(e) {
   // video playback failed - show a message saying why
   switch (e.target.error.code) {
     case e.target.error.MEDIA_ERR_ABORTED:
       alert('You aborted the video playback.');
       break;
     case e.target.error.MEDIA_ERR_NETWORK:
       alert('A network error caused the video download to fail part-way.');
       break;
     case e.target.error.MEDIA_ERR_DECODE:
       alert('The video playback was aborted due to a corruption problem or because the video used features your browser did not support.');
       break;
     case e.target.error.MEDIA_ERR_SRC_NOT_SUPPORTED:
       alert('The video could not be loaded, either because the server or network failed or because the format is not supported.');
       break;
     default:
       alert('An unknown error occurred.');
       break;
   }
 }
</script>
<video src="tgif.vid" autoplay controls onerror="failed(event)"></video>

回答by radicaledward101

If you are using source tags you can set the onerror attribute on the last source tag in the list instead. See the bottom of section 4.8.8 on this pagefor more details.

如果您使用源标签,您可以在列表中的最后一个源标签上设置 onerror 属性。有关更多详细信息,请参阅本页第 4.8.8 节的底部

Quote from that reference:

引用该参考文献:

If the author isn't sure if user agents will all be able to render the media resources provided, the author can listen to the error event on the last source element and trigger fallback behavior:

<script>
 function fallback(video) {
   // replace <video> with its contents
   while (video.hasChildNodes()) {
     if (video.firstChild instanceof HTMLSourceElement)
       video.removeChild(video.firstChild);
     else
       video.parentNode.insertBefore(video.firstChild, video);
   }
   video.parentNode.removeChild(video);
 }
</script>
<video controls autoplay>
 <source src='video.mp4' type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"'>
 <source src='video.ogv' type='video/ogg; codecs="theora, vorbis"'
         onerror="fallback(parentNode)">
 ...
</video>

如果作者不确定用户代理是否都能够渲染提供的媒体资源,作者可以监听最后一个源元素上的错误事件并触发回退行为:

<script>
 function fallback(video) {
   // replace <video> with its contents
   while (video.hasChildNodes()) {
     if (video.firstChild instanceof HTMLSourceElement)
       video.removeChild(video.firstChild);
     else
       video.parentNode.insertBefore(video.firstChild, video);
   }
   video.parentNode.removeChild(video);
 }
</script>
<video controls autoplay>
 <source src='video.mp4' type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"'>
 <source src='video.ogv' type='video/ogg; codecs="theora, vorbis"'
         onerror="fallback(parentNode)">
 ...
</video>

This example isn't perfect because you don't get the event object like you do when the onerror attribute is on the video tag (which only works if you have a src attribute in the video tag instead of in a series of tags. However, I believe you can then retrieve the error state from the video tag with the networkState JS variable on that tag. I haven't tested that though. So it is up to you at that point. It sounds like what I have here might be satisfactory for your needs.

这个例子并不完美,因为当 onerror 属性在 video 标签上时,你不会像你那样获得事件对象(只有当你在 video 标签中有一个 src 属性而不是在一系列标签中时才有效。但是, 我相信你可以从视频标签中检索错误状态,并使用该标签上的 networkState JS 变量。不过我还没有测试过。所以这取决于你。听起来我在这里可能是满足您的需求。

Notes:

笔记:

While you can instead listen for an "error" event on the last source tag, I found that this was unreliable. In cases where the preload attribute is not set to none, I could not find a way to reliably add a listener for the event before the event fired. This forced me to use the onerror attribute.

虽然您可以在最后一个源标记上监听“错误”事件,但我发现这是不可靠的。在 preload 属性未设置为 none 的情况下,我找不到在事件触发之前可靠地为事件添加侦听器的方法。这迫使我使用 onerror 属性。

If you do find a way to reliably listen for the event I wanted to add this note. According to this Chromium issuethe error event on the source tag does NOT bubble which means that you have to listen to it on that specific tag.

如果您确实找到了一种可靠地侦听事件的方法,我想添加此注释。根据这个 Chromium 问题,源标签上的错误事件不会冒泡,这意味着您必须在该特定标签上收听它。

回答by Tiborg

The 'error' event is not called because it is triggered by the elements inside, and to make the event be triggered also on the element, you have to use the addEventListener method with the useCapture parameter set to true, like this:

'error' 事件未被调用,因为它是由内部元素触发的,并且要使事件也在元素上触发,您必须使用 addEventListener 方法并将 useCapture 参数设置为 true,如下所示:

video.addEventListener('error', callback, true);

And then inside the callback you can check the networkState property, which is going to be NETWORK_NO_SOURCE if the video cannot play the sources.

然后在回调中,您可以检查 networkState 属性,如果视频无法播放源,它将是 NETWORK_NO_SOURCE。

Check out the docs from MDN about addEventListener and the useCapture parameter https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener

查看来自 MDN 的关于 addEventListener 和 useCapture 参数的文档 https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener