我正在尝试使用Media Source Extension API创建一个Media Player。媒体播放器工作正常,但我无法理解特定事件。 sourceopenMediaSource addEventListner在第20行声明。sourceopen将源缓冲区添加到MediaSource,然后追加到源缓冲区。在第21和13行,我包括了控制台日志记录。执行网站后,控制台将首先输出第13行的控制台日志。从我的角度来看,应该首先显示第21行的控制台日志。我相信我无法理解sourceopen事件监听器的工作方式。有人可以解释一下为什么在第13行之后执行sourceopen事件监听器吗?

如果有人听不懂我的问题,请在下方评论。

01| <!DOCTYPE html>
02| <html>
03|   <head>
04|     <meta charset="utf-8"/>
05|   </head>
06|   <body>
07|     <video controls></video>
08|     <script>
09|       var video = document.querySelector('video');
10|       var assetURL = 'frag_bunny.mp4';
11|       var mimeCodec = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"';
12|       start();
13|       console.log('2');
14|
15|       function start()
16|       {
17|         var mediaSource = new MediaSource;
18|         video.src = URL.createObjectURL(mediaSource);
19|
20|         mediaSource.addEventListener('sourceopen', function () {
21|           console.log('1');
22|           var sourceBuffer = mediaSource.addSourceBuffer(mimeCodec);
23|           fetchAB(assetURL, function (buf)
24|           {
25|             sourceBuffer.appendBuffer(buf);
26|           });
27|         });
28|       }
29|
30|       function fetchAB (url, cb)
31|       {
32|         var xhr = new XMLHttpRequest;
33|         xhr.open('get', url);
34|         xhr.responseType = 'arraybuffer';
35|         xhr.onload = function ()
36|         {
37|           cb(xhr.response);
38|         };
39|         xhr.send();
40|       };
41|     </script>
42|   </body>
43| </html>

最佳答案

正确的start()函数将如下所示:

function start() {

    // create an object, an instance of the MediaSource
    var mediaSource = new MediaSource;

    // to this `mediaSource` object add an event listener for the `sourceopen` event
    // and run the code inside the function when `sourceopen` happens
    mediaSource.addEventListener('sourceopen', function () {
        console.log('1');
        var sourceBuffer = mediaSource.addSourceBuffer(mimeCodec);
        fetchAB(assetURL, function (buf) {
            sourceBuffer.appendBuffer(buf);
        });
    });

    // hey, `video` element, here is the source of the media I'd like you to play
    // it's not a simple url, is something more complex
    // , a `MediaSource` kind of thing
    // and it might take you some time to be ready
    video.src = URL.createObjectURL(mediaSource);

}


现在,回到整个代码...,如果您告诉浏览器执行如下代码:

console.log('2');

,浏览器可以立即完成操作,您将立即在控制台中看到2

但是,这件事:

video.src = URL.createObjectURL(mediaSource);

对于浏览器来说不是那么简单。

当您要求浏览器执行此操作时,浏览器会说:“好的,您要我执行,我现在就开始,您可以继续其余代码,但是,这不是那个对我来说很容易...,我需要开始旋转一些轮子...,这将花费我一些时间...,而且,我不想出去准备视频之前就去取视频准备好时,我会通知您。

实际上,不是直接对我来说,浏览器,而是mediaSource对象(它是我的(浏览器)API之一的MediaSource的实例)将通过引发sourceopen事件来通知您。

所以...,当您将此代码放在页面上时:

mediaSource.addEventListener('sourceopen', function () {
  // do things
});


您是在告诉浏览器准备就绪且sourceopen已触发时该做什么。

让我们总结一下:

12| start();

// start() is called and starts to execute but it has something inside that
// will take some time before ready
// as consequence `console.log('1')` does not happen yet




13| console.log('2');

// runs imediatelly
// you see "2" in the console




...经过一段时间,start()中的代码正在准备就绪



// the `sourceopen` event fires and a `function ()`
// the callback of `mediaSource.addEventListener('sourceopen'`
// starts to execute


21| console.log('1');

// gets executed
// you see "1" in the console

关于javascript - 为什么在脚本末尾执行Sourceopen事件监听器?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/50053560/

10-09 18:21