Я пытаюсь построить довольно стандартный видеоплеер, используя Media Source Extensions; однако я хочу, чтобы пользователь мог контролировать, когда проигрыватель переходит к новому сегменту видео. Например, мы можем увидеть следующее поведение:
- Видеопроигрыватель воспроизводит 1-й сегмент
- В исходном буфере заканчиваются данные, из-за чего видео останавливается
- Когда пользователь готов, они нажимают кнопку, которая добавляет 2-й сегмент к исходному буферу
- Видео продолжается, воспроизводя 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));
}