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