Javascript 如何使用媒体源api将两个视频文件数据附加到源缓冲区?

Javascript 如何使用媒体源api将两个视频文件数据附加到源缓冲区?,javascript,html,api,video,streaming,Javascript,Html,Api,Video,Streaming,我有两个视频名为v11.webm和v12.webm 我想要的是,这两个视频应该无缝运行,没有任何差距 我遵循媒体源api将数据附加到源缓冲区的方法 我指的是这个演示 我修改了这个示例,删除了视频分块的部分,并尝试将数据添加到源缓冲区文件中 我的代码如下: <script> var video = document.querySelector('video'); window.MediaSource = window.MediaSource || window.WebKitMedi

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

我想要的是,这两个视频应该无缝运行,没有任何差距

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

我指的是这个演示

我修改了这个示例,删除了视频分块的部分,并尝试将数据添加到源缓冲区文件中

我的代码如下:

<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>

var video=document.querySelector('video');
window.MediaSource=window.MediaSource | | window.WebKitMediaSource;
如果(!!!window.MediaSource){
警报(“MediaSource API不可用”);
}
var mediaSource=新的mediaSource();
video.src=window.URL.createObjectURL(mediaSource);
mediaSource.addEventListener('webkitsourceopen',函数(e){
var sourceBuffer=mediaSource.addSourceBuffer('video/webm;codecs=“vorbis,vp8”);

对于(i=1;i您的代码中缺少的是:mediaSource.endOfStream()


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

可能有点晚了,但我能够解决这个问题。您的新视频正在覆盖旧视频,因为它们都在时间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对它所接受的视频的结构不那么挑剔就好了。我还没有找到一个示例.webm,除了在您链接中使用的相同示例之外,它还能工作


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

我获得了完美的exa把这个问题分为简单的方法和简单的方法

我使用三个静态文件,但您也可以从套接字或任何api附加数据



(异步()=>{ const mediaSource=new mediaSource(); const video=document.querySelector(“视频”); //video.oncanplay=e=>video.play(); 常量URL=[”https://nickdesaulniers.github.io/netfix/demo/frag_bunny.mp4", "https://raw.githubusercontent.com/w3c/web-platform-tests/master/media-source/mp4/test.mp4","https://nickdesaulniers.github.io/netfix/demo/frag_bunny.mp4"]; const request=url=>fetch(url).then(response=>response.arrayBuffer()); //`url.reverse()`在`currentTime`:`9停止` const files=wait Promise.all(url.map(request)); /* `.webm`文件 未捕获的DomeException:未能对“SourceBuffer”执行“appendBuffer”:此SourceBuffer已从父媒体源中删除。 未捕获的DomeException:未能在“SourceBuffer”上设置“timestampOffset”属性:此SourceBuffer已从父媒体源中删除。 */ //const mimeCodec=“视频/webm;编解码器=作品”; // https://stackoverflow.com/questions/14108536/how-do-i-append-two-video-files-data-to-a-source-buffer-using-media-source-api/ const mimeCodec=“视频/mp4;编解码器=avc1.42E01E,mp4a.40.2”; const media=wait Promise.all(files.map)(file=>{ 返回新承诺(解决=>{ 让媒体=document.createElement(“视频”); 让blobURL=URL.createObjectURL(新Blob([file]); media.onloadedmetadata=异步e=>{ 决心({ mediaDuration:media.duration, 媒体缓冲区:文件 }) } media.src=blobURL; }) })); 控制台日志(媒体); mediaSource.addEventListener(“sourceopen”,sourceopen); video.src=URL.createObjectURL(mediaSource); 异步函数sourceOpen(事件){ if(MediaSource.isTypeSupported(mimeCodec)){ const sourceBuffer=mediaSource.addSourceBuffer(mimeCodec); 对于(让媒体块){ 等待新的承诺(解决=>{ sourceBuffer.appendBuffer(chunk.mediaBuffer); sourceBuffer.onupdateend=e=>{ sourceBuffer.onupdateend=null; sourceBuffer.timestampOffset+=chunk.mediaDuration; console.log(mediaSource.duration); 解决() } }) } mediaSource.endOfStream(); } 否则{ console.warn(mimeCodec+“不支持”); } }; })()
只需将sourceBuffer的模式设置为
'sequence'
(默认值似乎是
'segments'

从文档:

顺序:片段附加到源缓冲区的顺序决定了它们的播放顺序。片段时间戳会自动为遵守此顺序的片段生成

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

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

感谢nir的回复。我不确定应该在哪里检查mediaSource.endofStream()?不一致的混音意味着video12.webm声音出现几秒钟,然后video11.webm声音开始出现,更重要的是视频被卡住。理想情况下,video11.webm应该先播放,然后再播放video12.webm。在您提供的演示中,他们调用endofStream()。我认为他们在函数readChunk_I中提到了相同的问题,查看他们的评论。我查看了这些代码,并在reader.onload函数中添加了类似的条件:if(i==2){mediaSource.endOfStream();}else{if(video.paused){video.play();}但是现在只有第二个视频,即v12.webm被播放,v11.webm被转义。你有没有弄明白这一点?MediaSource规范说这样的事情是不可能的