所有类型都不受支持的HTML5视频回退

时间:2015-09-07 02:19:19

标签: html5 html5-video

在HTML5规范中,它建议您将后备材料放在<video>标记中,以用于不支持它的旧版浏览器。

<video width="400" controls>
    <source src="mov_bbb.mp4" type="video/mp4">
    <source src="mov_bbb.ogg" type="video/ogg">
    Your browser does not support HTML5 video.
</video>

但是,当不支持所有源类型时,我找不到任何回退的内容。例如,我的Chromium浏览器无法播放video/mp4,但可以播放video/ogg。所以我希望这会渲染后备文本。

<video width="400" controls>
    <source src="mov_bbb.mp4" type="video/mp4">
    Your browser does not support HTML5 video.
</video>

相反,我只是得到一个没有任何内容的视频播放器,因为它无法加载mp4文件。

如果没有可用的视频源,是否有办法在HTML 5视频中进行回退?我知道我尝试的后备版仅适用于旧浏览器,但我仍然需要一个没有可用来源的后备。

3 个答案:

答案 0 :(得分:5)

实际上,当您尝试在console.log()元素中加载不支持的媒体类型时,会触发<source>个事件。
然后,您可以收听这些事件,如果没有识别出任何来源,则触发回退:

error
var sources = document.querySelectorAll('source');
var source_errors = 0;
for (var i = 0; i < sources.length; i++) {
  sources[i].addEventListener('error', function(e) {
    if (++source_errors >= sources.length)
      fallBack();
  });
}

function fallBack() {
  document.body.removeChild(document.querySelector('video'));
  document.body.appendChild(document.createTextNode('No video with supported media and MIME type found'));
}

答案 1 :(得分:0)

@ Jaw.sh有两种常用的后备选项。

  1. Fallback to Flash version of the video.
  2. Fallback to a direct download of the video.
  3. 今天的浏览器(Opera我不确定而且并不关心),都能够播放MP4 H.264。因此,除非您的大多数观众都住在中国,否则您不应过分担心不兼容问题。

答案 2 :(得分:0)

这没有HTML行为,因此我们必须使用JavaScript添加自己的行为。

(function() {
  "use strict";

  function insertAfter(newNode, referenceNode) {
    referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
  }

  function setVideoFallback(lazyArea) {
    var lowData = false;
    if ("connection" in navigator) {
      lowData = navigator.connection.saveData === true ||
        navigator.connection.effectiveType === "slow-2g" ||
        navigator.connection.effectiveType === "2g";
    }
    //DocumentFragments don't support getElementsByTagName
    //oldIE doesn't support querySelectorAll
    var lazyVideos = lazyArea.querySelectorAll ?
      lazyArea.querySelectorAll("video") :
      lazyArea.getElementsByTagName("video");
    for (var i = lazyVideos.length; i--;) {
      var lazyVideo = lazyVideos[i];
      var cantPlay = true;
      if (lazyVideo.canPlayType) {
        //Loop through the various source elements, and check if
        //the browser thinks it can play them
        //This works better if we specify the codec along with
        //the MIME type
        var sources = lazyVideo.getElementsByTagName("source");
        for (var i2 = sources.length; i2--;) {
          if (lazyVideo.canPlayType(sources[i2].type)) {
            cantPlay = false;
            break;
          }
        }
      }
      //If on a low-data connection, remove the autoplay attribute
      //(it's only polite)
      if (lowData) {
        lazyVideo.removeAttribute("autoplay");
        lazyVideo.setAttribute("controls", "");
      }
      //If you can't play any of the available formats, skip straight to fallback content
      if (cantPlay) {
        //Extract the fallback and replace the video with it
        var children = lazyVideo.childNodes;
        for (var i3 = children.length; i3--;) {
          var childNode = children[i3];
          if (childNode.tagName !== "TRACK" && childNode.tagName !== "SOURCE") {
            insertAfter(childNode, lazyVideo);
          }
        }
        lazyVideo.parentNode.removeChild(lazyVideo);
      }
    }
  }
  /**
   * Retrieve the elements from the 'lazy load' noscript tags and prepare them for display
   */
  function setUp() {
    //Get all the noscript tags on the page
    var lazyLoadAreas = document.getElementsByTagName("noscript");
    var supportsTemplates = typeof HTMLTemplateElement === "function";
    for (var i = lazyLoadAreas.length; i--;) {
      var noScriptTag = lazyLoadAreas[i];
      //only process the ones marked for lazy loading
      if (!noScriptTag.hasAttribute("data-lazy-load")) continue;
      // The contents of a noscript tag are treated as text to JavaScript
      var lazyAreaHtml = noScriptTag.textContent || noScriptTag.innerHTML;
      // So we stick them in the innerHTML of a new div tag to 'load' them
      var lazyArea;
      if (supportsTemplates) {
        //(if possible, templates are better as they won't start any network calls)
        var lazyTemplate = document.createElement("template");
        lazyTemplate.innerHTML = lazyAreaHtml;
        lazyArea = lazyTemplate.content;
      } else {
        lazyArea = document.createElement("div");
        lazyArea.innerHTML = lazyAreaHtml;
      }
      setVideoFallback(lazyArea);
      noScriptTag.parentNode.replaceChild(lazyArea, noScriptTag);
    }
  }
  //If the page has loaded already, run setup - if it hasn't, run as soon as it has.
  if (document.readyState !== "loading") {
    setUp();
  } else {
    document.addEventListener("DOMContentLoaded", setUp);
  }
})();
<main>
  <figure>
    <!--[if !IE]><!-->
    <noscript data-lazy-load>
			<video height="338" width="600" autoplay loop muted>
				<!--<source src="./Sample.mp4"	type="video/mp4; codecs=avc1.42E01E,mp4a.40.2">-->
				<source src="http://dl3.webmfiles.org/big-buck-bunny_trailer.webm" type="video/webm; codecs=vp8,vorbis">
				<source src="https://upload.wikimedia.org/wikipedia/commons/0/07/Backgammon_example.ogv"	type="video/ogg; codecs=theora,vorbis">
				<!--<![endif]-->
				<img src="https://media2.giphy.com/media/BfbUe877N4xsUhpcPc/giphy.gif?cid=790b76115cadcffa59306b73776453f3" height="360" width="480"/>
				<!--[if !IE]><!-->
			</video>
		</noscript>
    <!--<![endif]-->
    <figcaption>
      A bunny emerging from his den and stretching.
      <!--[if !IE]><!-->
      <noscript aria-hidden="true"><p>
        Note: Without JavaScript, the above animation might not play. In that case, the animation can be directly accessed
			  <a href="./giphy.gif">here</a>.
      </p></noscript>
      <!--<![endif]-->
    </figcaption>
  </figure>
</main>

使用canPlayType函数,我们询问浏览器是否认为它可以播放任何一种源类型。如果没有,我们将提取回退内容。

我们将视频包含在noscript标签中,以便在运行脚本之前不会开始加载视频(除非禁用了脚本,这是您所希望的行为)。

我们还使用IE条件标签,因为oldIE无法使用脚本读取noscript标签的内容。

(在Edge,Firefox,Chrome和IE具有的每种兼容模式下进行测试。Webm在所有浏览器栏中显示IE,并在每种兼容模式下显示GIF。)