Почему прослушиватель событий Sourceopen выполняется в конце сценария? - PullRequest
0 голосов
/ 27 апреля 2018

Я пытаюсь создать Media Player с использованием Media Source Extension API. Медиаплеер работает отлично, но я не могу понять конкретное событие. sourceopen addEventListner MediaSource объявлен в строке 20. sourceopen добавляет исходный буфер в MediaSource и затем добавляет к исходному буферу. В строке 21 и 13 я включил журналы консоли. Когда веб-сайт выполняется, консоль сначала выводит журнал консоли в строке 13. Когда, с моей точки зрения, сначала должен быть показан консольный журнал строки 21. Я считаю, что не могу понять, как работает sourceopen Event Listener. Может кто-то, пожалуйста, объясните, почему sourceopen прослушиватель событий превышен после строки 13. Спасибо

Если кто-то не может понять мой вопрос, пожалуйста, прокомментируйте ниже.

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>

1 Ответ

0 голосов
/ 27 апреля 2018

Правильная функция 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, который является экземпляром MediaSource, который является одним из моих ( браузеров ) API, сообщит вам повышение события 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
...