首页 > 解决方案 > 以 HTML 格式加载大型视频文件

问题描述

这是我的问题:我想播放存储在 S3 存储桶中的大型视频文件(3.6Gb),但文件似乎太大,加载 30 秒后页面崩溃。

这是我播放视频的代码:

var video = document.getElementById("video");
const mediaSource = new MediaSource();
video.src = URL.createObjectURL(mediaSource);
mediaSource.addEventListener('sourceopen', sourceOpen, { once: true });

function sourceOpen() {
    URL.revokeObjectURL(video.src);
    const sourceBuffer = mediaSource.addSourceBuffer('video/mp4; codecs="avc1.f40028"');

    fetch('URL_TO_VIDEO_IN_S3')
        .then(response => response.arrayBuffer())
        .then(data => {
            // Append the data into the new sourceBuffer.
            sourceBuffer.appendBuffer(data);    
        })
        .catch(error => {

        });
}

我看到 blob URL 可能是一个解决方案,但它不适用于我的 URL。

标签: javascripthtmlvideomedia-source

解决方案


因为我不是专家,所以对我的回答持保留态度。但是,我目前正在做一些非常相似的事情。

我怀疑您的问题是您试图一次将整个资源(视频文件)加载到浏览器中。超过 1 GB 的文件大小的对象 URL 非常大。

您需要做的是使用获取请求正文中的可读流来逐块处理视频文件。因此,只要您不局限于在 safari 浏览器中工作,您就应该在浏览器中本地使用 Readable 和 Writeable Stream 类。

这两个类允许您形成所谓的管道。在这种情况下,您将 fetch 请求中的可读流中的数据“管道”到您创建的可写流,然后将其用作媒体源扩展及其各自源缓冲区的底层数据源。

流管非常特殊,因为它表现出所谓的背压。您绝对应该查一下这个术语,并了解它的含义。在这种情况下,这意味着一旦浏览器有足够的数据来满足其视频播放的需求,它就不会请求更多的数据,它一次可以容纳的确切数量是由程序员通过称为“高水位标记”的东西指定的(你应该也读过这个)。

这使您可以控制浏览器何时以及从您的(正在进行的)获取请求中请求多少数据。

注意:当您使用时,.then(response => response.arrayBuffer())您是在告诉浏览器等待整个资源返回,然后将响应转换为数组缓冲区。


推荐阅读