Интересное поведение в Media Source Extensions - PullRequest
0 голосов
/ 26 апреля 2020

Я пытаюсь построить довольно стандартный видеоплеер, используя Media Source Extensions; однако я хочу, чтобы пользователь мог контролировать, когда проигрыватель переходит к новому сегменту видео. Например, мы можем увидеть следующее поведение:

  1. Видеопроигрыватель воспроизводит 1-й сегмент
  2. В исходном буфере заканчиваются данные, из-за чего видео останавливается
  3. Когда пользователь готов, они нажимают кнопку, которая добавляет 2-й сегмент к исходному буферу
  4. Видео продолжается, воспроизводя 2-й сегмент

Это работает хорошо, за исключением того, что когда видео появляется приостановлено во время шага 2, оно не останавливается на последнем кадре 1-го сегмента. Вместо этого он останавливает два кадра до конца 1-го сегмента. Эти последние два кадра не пропускаются, они просто воспроизводятся после , когда пользователь нажимает кнопку для продвижения видео. Это проблема для моего приложения, и Я пытаюсь найти способ убедиться, что все кадры из 1-го сегмента воспроизводятся до конца шага 2 .

Я подозреваю, что эти два последних кадра задерживаются в буфере видеодекодера. Тем более, что вызов метода endOfStream () на моем источнике мультимедиа после добавления 1-го сегмента в буфер источника приводит к тому, что 1-й сегмент воспроизводится полностью без кадров.

Дополнительная информация

  • Я создал каждый файл видеофрагмента из серии PNG с помощью следующей команды ffmpeg

ffmpeg -i %04d.png -movflags frag_keyframe+empty_moov+default_base_moof video_segment.mp4

  • Может быть, это ключ? Ситуации конца потока не обрабатываются правильно (последние кадры отбрасываются)
  • Еще одна интересная вещь, которую стоит отметить, - если видео содержит только 2 кадра или меньше, MSE не воспроизводит его вообще .
  • Используемый мной браузер - Chrome. Код для моего MSE-плеера только что взят из примера разработчиков Google, но я опубликую его здесь для полноты. Этот код распространяется только на шаг 2, поскольку именно в этом проблема.
<script>
const mediaSource = new MediaSource();
video.src = URL.createObjectURL(mediaSource);
mediaSource.addEventListener('sourceopen', sourceOpen, { once: true });

function sourceOpen() {
  URL.revokeObjectURL(video.src);
  const sourceBuffer = mediaSource.addSourceBuffer('video/mp4; codecs="avc1.64001f"');
  sourceBuffer.mode = 'sequence';

  // Fetch the video and add it to the Source Buffer
  fetch('https://s3.amazonaws.com/bucket_name/video_file.mp4')
  .then(response => response.arrayBuffer())
  .then(data => sourceBuffer.appendBuffer(data));
}

...