【问题标题】:How do i append two video files data to a source buffer using media source api?如何使用媒体源 API 将两个视频文件数据附加到源缓冲区?
【发布时间】:2012-12-16 00:32:21
【问题描述】:

我有两个视频名称 v11.webm 和 v12.webm。

我想要的是这两个视频应该无缝地运行,没有任何间隙。

我正在遵循将数据附加到源缓冲区的媒体源 api 方法。

我指的是link上给出的演示

我已经修改了该示例并删除了对视频进行分块的部分,并且还尝试将数据附加到源缓冲区文件中。

我的代码如下:

<script>

var video = document.querySelector('video');

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

var mediaSource = new MediaSource();

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

mediaSource.addEventListener('webkitsourceopen', function(e) {

    var sourceBuffer = mediaSource.addSourceBuffer('video/webm; codecs="vorbis,vp8"');  

    for(i=1;i<=2;i++)
    {
        (function(i){

          GET('v1'+i+'.webm', function(uInt8Array) {
              var file = new Blob([uInt8Array], {type: 'video/webm'});

              var reader = new FileReader();
              reader.onload = function(e) {
                sourceBuffer.append(new Uint8Array(e.target.result));            
              };
              reader.readAsArrayBuffer(file);

          });
        })(i);
    }

}, false);

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

function GET(url, callback) {
 // alert(url);
  var xhr = new XMLHttpRequest();
  xhr.open('GET', url, true);
  xhr.responseType = 'arraybuffer';
  xhr.send();

  xhr.onload = function(e) {
    if (xhr.status != 200) {
      alert("Unexpected status code " + xhr.status + " for " + url);
      return false;
    }
    callback(new Uint8Array(xhr.response));
  };
}
</script>

现在代码无法按预期工作。

v11.webm 和 v12.webm 文件数据混合不一致。

它没有无缝运行。

【问题讨论】:

标签: javascript html api video streaming


【解决方案1】:

也许有点晚了,但我能够弄清楚这一点。您的新视频将覆盖旧视频,因为它们都从时间 0 开始。您必须在附加之前指定新视频从时间 X 开始,因此您的 'webkitsourceopen' 事件函数应该是:

/* forget the sourcebuffer variable, we'll just manipulate mediaSource */
mediaSource.addSourceBuffer('video/webm; codecs="vorbis,vp8"');

/* it seems ok to set initial duration 0 */
var duration = 0;
var totalVideos = 2;

/* use this type of loop to ensure that that a single video
   is downloaded and appended before moving on to the next video,
   mediasource seems picky about these being in order */
var i = 0;
(function readChunk_(i){

    /* the GET function already returns a Uint8Array.
       the demo you linked reads it in filereader in order to manipulate it;
       you just want to immediately append it */
    GET('v1' + (i + 1) + '.webm', function(uint8Array){

        if(i == totalVideos) {
            mediaSource.endOfStream();
        } else {

            /* assuming your videos are put together correctly
               (i.e. duration is correct), set the timestamp offset
               to the length of the total video */
            mediaSource.sourceBuffers[0].timestampOffset = duration;

            mediaSource.sourceBuffers[0].append(uint8Array);

            /* set new total length */
            duration = mediaSource.duration;

            readChunk(++i);
        }
    });
})(i);

现在,如果 MediaSource 对其接受的视频的结构不那么挑剔的话。除了您链接的Eric Bidelman's Demo 中使用的那个之外,我还没有找到一个可以工作的示例 .webm。

编辑:在进行更多测试后,我设置持续时间的方式可能不正确。如果您似乎在每次追加后获得指数持续时间增长,请尝试将 timestampoffset 设置为 0 并且不更改它。我不知道为什么这似乎可以解决它,这可能是我如何生成 webm 文件的问题。

【讨论】:

  • 如果您使用 ffprobe 查看视频,您可以看到视频被拒绝的原因,正确的编解码器不匹配
【解决方案2】:

只需将sourceBuffer的模式设置为'sequence'(默认似乎是'segments')

来自文档:https://developer.mozilla.org/en-US/docs/Web/API/SourceBuffer/mode

sequence:将片段附加到 SourceBuffer 的顺序决定了它们的播放顺序。为遵守此顺序的段自动生成段时间戳。

在我的应用程序中,我只是在将源缓冲区添加到媒体源之后设置它:

// Create media source for the stream, and create the source buffer when ready
let self = this;
this._mediaSource = new MediaSource();
this._mediaSource.addEventListener('sourceopen', function () {
  self._sourceBuffer = self.mediaSource.addSourceBuffer(environment.recordingMimeType);
  self._sourceBuffer.mode = 'sequence'; // This is the relevant part
  self._sourceBuffer.addEventListener('error', function (ev) {
    console.error("Source buffer error ??");
    console.error(ev);
  });
});

【讨论】:

    【解决方案3】:

    我在您的代码中缺少的是:mediaSource.endOfStream();

    您能否详细说明混合不一致的问题?

    【讨论】:

    • 感谢 nir 的回复。我不确定我应该在哪里检查 mediaSource.endofStream()?不一致的混合意味着 video12.webm 声音会持续几秒钟,然后 video11.webm 声音开始出现,更重要的是视频卡住了。理想情况下,应该先播放 video11.webm,然后再播放 video12.webm。
    • 在您提供的演示中,他们调用 endofStream()。我认为他们在函数 readChunk_(i) 中提到了同样的问题,看看他们的 cmets。
    • 我查看了那里的代码并在 reader.onload 函数中添加了类似的条件: if(i==2) { mediaSource.endOfStream(); } else { if (video.paused) { video.play();但是现在只有第二个视频是 v12.webm 被播放,v11.webm 被转义
    猜你喜欢
    • 2013-07-15
    • 2014-04-03
    • 1970-01-01
    • 1970-01-01
    • 2023-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多