Media Source 系列 - 结合 range 控制媒体请求缓存大小

上一篇写了 Media Source 系列 - 播放 m3u8 文件 , 写了使用 MSE 来播放一个包含分片内容的资源。同样除此之外,我们可以借助 MSE 来进行更加 细粒 的缓存控制调度。

HTTP Range

HTTP Range ,HTTP 协议范围请求允许服务器只发送 HTTP 消息的一部分到客户端。范围请求在传送大的媒体文件,或者与文件下载的断点续传功能搭配使用时非常有用。假如在响应中存在 Accept-Ranges 首部(并且它的值不为 “none”),那么表示该服务器支持范围请求。

比如我们请求一个视频的一部分:

$ curl http://localhost:8000/media-source/vdeoplayback.mp4 -i -H "Range: bytes=0-1023"

使用 fetch 请求 视频的一部分内容

正如前面提到了,如果服务器支持请求 range 的内容,我们可以使用 Fetch 来设置 header 中 range 的值。

 fetch('your_file.mp4', { headers: { range: 'bytes=0-567139' } })
    .then(response => response.arrayBuffer())
    .then(data => {
      // source buffer
    });

这样我们就可以尽量控制我们才开始请求的媒体资源的缓存量大小了。

使用 MSE 播放

当然这样还不能完全播放,因为我们需要通过 MSE 来播放我们缓存的内容。

var mime = 'video/webm; codecs="vorbis, vp8"';
        var mediaSource = e.target;
        sourceBuffer = mediaSource.addSourceBuffer(mime);
        sourceBuffer.addEventListener('updateend', updateEnd);
        log('.js-log-m3u8', 'Fetch Segment ~' + videoUrl);
        var ranges = 'bytes=' + (500000 * index) + '-' + (500000 * (index+1))
        fetch(videoUrl, {
            headers: { range: ranges } 
        }).then(function (response) {
            return response.arrayBuffer();
        })
        .then(function (data) {
            sourceBuffer.appendBuffer(data);
        });

随后我们在播放的过程中再控制下面的分片的添加:

function fetchNextSegment() {
        index += 1;
        var ranges = 'bytes=' + (500000 * index + 1) + '-' + (500000 * (index+1))
        fetch(videoUrl, {
            headers: { range: ranges }
        })
        .then(response => response.arrayBuffer())
        .then(data => {
            var sourceBuffer = mediaSource.sourceBuffers[index-1];
            sourceBuffer.appendBuffer(data);
        });
    }

这样我们就有足够的能力进行缓存的控制了。

Github