【问题标题】:Can't seek video when playing from MediaSource从 MediaSource 播放时无法搜索视频
【发布时间】:2020-09-26 22:00:58
【问题描述】:

我可以通过使用 GET 请求和 Range 标头请求数据块来播放 mp4 视频。

var FILE = 'Momokuri_Ep_09-10_SUB_ITA_dashinit.mp4';
var NUM_CHUNKS = 10;
var chunk_size = 256 * 1024; // 2Kb
var current_chunk = 0;
var file_size = 1;

window.MediaSource = window.MediaSource || window.WebKitMediaSource;
if (!!!window.MediaSource) {
  alert('MediaSource API is not available');
}

var mediaSource = new MediaSource();
var sourceBuffer;

video.src = window.URL.createObjectURL(mediaSource);

function callback(e) {
    sourceBuffer = mediaSource.addSourceBuffer('video/mp4; codecs="avc1.640029, mp4a.40.5"');

    console.log('mediaSource readyState: ' + this.readyState);

    var readChunk = function() {
        GET(FILE, current_chunk, function(uInt8Array) {
            sourceBuffer.appendBuffer(uInt8Array);
        });
    };

    sourceBuffer.addEventListener('update', function(e) {
        if (!sourceBuffer.updating) {
            if (current_chunk == Math.ceil(file_size/chunk_size)-1) {
                if ( mediaSource.readyState!='ended' )
                    mediaSource.endOfStream();
            } else {
                current_chunk++;
                readChunk();
                if (video.paused) {
                    video.play();
                }
            }
        }
    });
    readChunk();
}

mediaSource.addEventListener('sourceopen', callback, false);
mediaSource.addEventListener('webkitsourceopen', callback, false);

mediaSource.addEventListener('webkitsourceended', function(e) {
  console.log('mediaSource readyState: ' + this.readyState);
}, false);

function GET(url, chunk_index, callback) {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', url, true);
    xhr.setRequestHeader('Range', 'bytes='+(chunk_index*chunk_size)+'-'+(++chunk_index*chunk_size-1));
    xhr.responseType = 'arraybuffer';
    xhr.send();

    xhr.onload = function(e) {
        if (xhr.status != 200 && xhr.status != 206) {
            alert("Unexpected status code " + xhr.status + " for " + url);
            return false;
        }

        file_size = parseInt(this.getResponseHeader('content-range').split("/").pop());
        callback(new Uint8Array(xhr.response));
    };
}

但我找不到视频。所以任何人都可以告诉我如何解决这些问题:

  1. 当我寻找视频时,我可以得到 video.currentTime(比如说 2.5),如何将其转换为字节范围请求(如何获取字节偏移量)
  2. 当我得到正确的偏移量并从 Range GET 请求中加载正确的数据时,如何在正确的偏移量处附加到 sourceBuffer

谢谢

【问题讨论】:

  • 呃,你不需要 FileReader...
  • 谢谢。我更新了我的代码
  • 你发现这个问题了吗?用户搜索时可以给我怎么做吗?

标签: javascript html video streaming


【解决方案1】:

我自己一直在寻找解决方案,我想我找到了。

看看这个example

每当从视频元素发出 seeking event 时,表明用户已请求搜索,旧的源缓冲区将使用 sourceBuffer.abort(); 关闭。

然后媒体源会发出一个新的sourceopen 事件,它允许您像第一次一样创建一个新的源缓冲区,但这次不是从文件开头追加数据,而是从偏移量追加数据对应videoElem.currentTime

如何将时间偏移量转换为字节偏移量似乎取决于您自己,因为这取决于您正在播放的媒体格式。

在一个恒定比特率的文件中,您基本上可以将文件长度(以字节为单位)除以以秒为单位的视频长度(并增加一点安全余量)。对于其他任何事情,您可能需要解析文件并获取关键帧的时间戳和字节偏移量。

【讨论】:

  • 在调用abort() 后,我没有收到新的sourceopen 事件。就我而言,重播刚刚停止。知道我错过了什么吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-06
  • 2015-11-11
相关资源
最近更新 更多