在视频blob上检测404:https source

时间:2017-08-16 23:00:26

标签: javascript html5 html5-video webrtc

我正在使用blob:https作为我的视频标签的来源,如下所示:

function mk_bloburl(source_id, url) {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', url, true);
    xhr.responseType = 'blob'; //important
    xhr.onload = function(e) {
        if (this.status == 200) {
            var blob = this.response;
            var source = document.getElementById(source_id);
            var video = source;
            if (video.tagName=="SOURCE") {
                video = source.parentNode;
            }
            video.oncanplaythrough = function() {
                URL.revokeObjectURL(source.src);
            };
            source.src = URL.createObjectURL(blob);
            video.load();
        }
    };
    xhr.send();
}

mk_bloburl('review-video-source', my_video_url );

像这样的HTML:

<video id="review-video" controls="" width="100%">
    <source id="review-video-source" />
</video>

现在,如果我重新加载页面并开始播放,它就可以了。如果我玩,让它播放,然后重播没有等待时间,它的工作原理。 但是,如果我重新加载页面然后等待一段时间(比如1-2分钟),然后按播放,则会失败。

我在Chrome浏览器中收到的消息如下所示:

GET blob:https://example.com/debeecfe-49b0-4c98-87d6-8ead325b2d75 404 (Not Found)

所以,就像一段时间后blob会自动从浏览器内存中删除一样。我希望在事件被删除时或当我通过开始播放获得404时捕获事件,因此我可以刷新blob。

我试过了:

var source = document.querySelector("#review-video-source");
source.addEventListener("error", function(event) {
    console.debug("An error accoured");
});

但这似乎没有发现错误。 我该怎么办?

2 个答案:

答案 0 :(得分:1)

您的主要问题是由于您在canplaythrough事件中撤消了blobURI。

canplaythrough事件只是浏览器发出的通知,让我们知道它可以在不中断的情况下加载和播放整个媒体;这并不意味着它已经装载了所有东西。

在BlobURI的情况下,连接速度非常快(它来自内存)浏览器可以认为它能够在瞬间获取4k的StarWars传奇。
所以你很早就得到了这个canplaythrough事件,但浏览器实际上还没有解压缩所有数据。仍然,你撤销BlobURI,当浏览器再次尝试获取数据以便它可以解压缩并读取它时,BlobURI指针的末尾就没有任何东西了。

所以对于你的问题,你有两个解决方案:

  • 如果您需要播放媒体一次
    ended活动中致电URL.revokeObjectURL(blobURI)。这将触发,第一次视频的当前时间到达终点。

  • 如果您需要多次播放视频
    撤消页面beforeunload事件中的blobURI。这样,只要页面处于活动状态,BlobURI指针就会始终处于活动状态,但不会阻止整个Blob在内存中的持续时间超过页面生命周期(如果您根本不撤消BlobURI,则会发生这种情况)。 / p>

关于如何在视频blob上检测404:https源,我真的不知道一个好方法,除了听到意外跳到最后,但这不应该是无论如何,还是有点。

答案 1 :(得分:0)

解决问题的一种方法是使用fetch API,如下所示:

function mk_bloburl(source_id, url){
  fetch(url)//usual get
  .then(response=>{
    if(response.status == 404)
    //Should set here what is an error (ex: x>299)
      Promise.reject("Error 404!");
    return response.blob();
  })//get blob
  .then(blobObj=>{//use blob
    var blob = blobObj;
    var source = focument.getElementById(source_id);
    var video = source;
    if(video.tagName === "SOURCE")
      video = source.parentNode;
    video.oncanplaythrough = ()=>{
      URL.revokeObjectUrl(source.src);
    };
    source.src = URL.revokeObjectURL(blob);
    video.load();
  })
  .catch(error=>{
    //There has been an error,
    //do something about it
    //here
  });
}