我正在使用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");
});


但这似乎并没有抓住错误。
我能做什么?

最佳答案

您的主要问题是由于您取消了canplaythrough事件中的blobURI而引起的。

canplaythrough事件只是浏览器发送的一个通知,让我们知道它认为它将能够加载和播放整个媒体而不会中断;这并不意味着它已经加载了所有内容。

对于BlobURI,连接速度是如此之快(它来自内存),以至于浏览器可能认为它能够瞬间获取4k的StarWars传奇。
因此,您确实很早就获得了该canplaythrough事件,但浏览器尚未真正解压缩所有数据。尽管如此,您还是撤消了BlobURI,并且当浏览器再次尝试获取数据以使其能够解压缩和读取数据时,BlobURI指针的末尾不再有任何内容。

因此,对于您的问题,您有两种解决方案:


如果您只需要播放一次媒体:
URL.revokeObjectURL(blobURI)事件中调用ended。视频的currentTime第一次结束时会触发。
如果您需要多次播放视频:
撤消页面beforeunload事件中的blobURI。这样,只要页面处于活动状态,您的BlobURI指针就始终处于活动状态,但是不会阻塞整个Blob在内存中的时间超过页面寿命(如果您根本不撤消BlobURI,就会发生这种情况)。




关于如何在视频blob:https来源上检测404的方法,我真的不知道一种好方法,除了侦听意外跳到末尾,但是无论如何bbloURI都不需要这样做。

09-19 13:48