本文介绍了从MediaSource播放时找不到视频的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I can play a mp4 video by requesting chunk of data using GET request and Range header.

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));
    };
}

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

But I can't seek the video. So anyone can tell me how to solve these problems :

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

谢谢

推荐答案

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

I've been looking for the solution to this myself, and I think I found it.

看看这个示例.

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

Whenever a seeking event is emitted from the video element, indicating the user has requested a seek, the old sourcebuffer is closed using sourceBuffer.abort();.

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

The mediasource then emits a new sourceopen event which allows you to create a new sourcebuffer the same way you did the first time, but this time instead of appending data from the start of the file, you append data from an offset corresponding to the videoElem.currentTime.

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

How you turn a time offset into a byte offset seems to be left up to you, as it depends on the format of the media you're playing.

在恒定比特率的文件中,您基本上可以将文件长度(以字节为单位)除以视频长度(以秒为单位)(并增加一点安全裕度)而摆脱困境.除此之外,您可能需要解析文件并获取时间戳和关键帧的字节偏移.

In a constant bitrate file, you might be able to get away with basically dividing the file length in bytes by the video length in seconds (and adding a little safety margin). For anything else, you will probably need to parse the file and get timestamps and byte offsets of keyframes.

这篇关于从MediaSource播放时找不到视频的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-26 05:49