HTML5 Video Blob 初探

转自
https://creamidea.github.io/static/html/articles/HTML5-Video-Blob.html

Video-Blob题图来自网络

1 前言

现在看到任何我感兴趣的网页都会习惯性的打开调试工具,看看其代码写的怎么样。 有一天,看到了这句 HTML。

<video src="blob:http://www.bilibili.com/d0823f0f-2b2a-4fd6-a93a-e4c82173c107"></video>

为何会有一个 blob?这个是什么?然后我点击这个链接,被返回了 404!什么情况?用了什么黑科技?一个个问题从脑海中蹦出来。

于是对此做了一番探索。

2 答案

直到我找到这个问题的回答 Display a video from a Blob Javascript 。才开始明白这是怎么一回事。

直接上代码:

var video = document.querySelector('video');
var mediaSource = new MediaSource;
video.src = URL.createObjectURL(mediaSource);
mediaSource.addEventListener('sourceopen', sourceOpen)

function sourceOpen () {
  var mediaSource = this;
  var sourceBuffer = mediaSource.addSourceBuffer('video/mp4; codecs="avc1.42E01E, mp4a.40.2"');
  sourceBuffer.addEventListener('updateend', function () {
    mediaSource.endOfStream();
    video.play();
  });
  sourceBuffer.appendBuffer(buf); // buf is the arraybuffer to store the video data
};

首先创建变量名为 video 的 DOM 对象。之后,创建变量名为 mediaSource 的MediaSource 对象。 通过函数 createObjecturl 来将 DOM::Video 对象的属性src 和 mediaSource 进行“连接”。 接下来,通过注册事件 Event::sourceopen来触发当上述“连接”结束之后的回调处理。回调处理就是需要赋值 视频数据 的地方。 调用 MediaSource::addSourceBuffer 方法来构建一个存放视屏数据的 Buffer。 在往 Buffer 中存放数据结束之后会触发事件 Event::updateend 。 通过注册这个事件的回调,可以知晓数据已经加载完毕,然后调用 Video::play 函数通知浏览器播放视频。 至此,整个 Blob 运行机制讲解完毕。详细的技术细节需要花一段时间来查看,暂时停止在这里。我们先知道这个是什么东西。<( ̄3 ̄)>

通过查看 B 站的前端代码,发现其 HTML5 播放器实现原理和这个差不多,主要使用 new MediaSource 和 createObjectURL 这2个函数。(当然实现不会这么简单,比如异常处理,用户交互等都是需要巨量的代码来覆盖。)

HTML
<video controls id="video-bg"></video>

JS
getBlobURL("http://meteor.local/videos/intro.mp4", "video/mp4", function(url, blob) {
    var source = $("<source>");
    source[0].src = url;

    $("#video-bg").append(source);
});

function getBlobURL(url, mime, callback) {
  var xhr = new XMLHttpRequest();
  xhr.open("get", url);
  xhr.responseType = "arraybuffer";

  xhr.addEventListener("load", function() {

    var arrayBufferView = new Uint8Array( this.response );
    var blob = new Blob( [ arrayBufferView ], { type: mime } );
    var url = null;

    if ( window.webkitURL ) {
        url = window.webkitURL.createObjectURL(blob);
    } else if ( window.URL && window.URL.createObjectURL ) {
        url = window.URL.createObjectURL(blob);
    }

    callback(url, blob);
  });
  xhr.send();
}
点赞

发表回复

电子邮件地址不会被公开。必填项已用 * 标注