我试图使用Media Source Extensions构建一个相当标准的视频播放器;然而,我希望用户能够控制播放器何时移动到一个新的视频片段。例如,我们可能会看到以下行为。
这很好用,只是当视频出现在步骤2中暂停时,它并没有停止在第一段的最后一帧。相反,它停止在第一段结束前两帧。这最后两帧并没有被丢弃,只是被播放了。之后 用户点击按钮来推进视频。这是我的应用程序的一个问题,并且 我正在想办法确保在步骤2结束前播放第一段的所有帧。.
我怀疑这最后两帧在视频解码器缓冲区中被卡住了。尤其是在我的媒体源上调用endOfStream(),在将第1个片段添加到源缓冲区后,会导致第1个片段一直播放,没有任何帧遗留。
其他信息
ffmpeg -i %04d.png -movflags frag_keyframe+empty_moov+default_base_moof video_segment.mp4
<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));
}
这很好用,只是当视频在步骤2中出现暂停时,它并没有停止在第一段的最后一帧。取而代之的是,它停止在第1个片段结束前的两帧。这最后两帧并没有被丢弃,只是在之后播放......
这种行为取决于浏览器。让我们从以下几个方面开始 规范报价:
当媒体元素需要更多的数据时,用户代理应该尽早将其从HAVE_ENOUGH_DATA过渡到HAVE_FUTURE_DATA,以便网络应用能够在不造成播放中断的情况下做出响应。例如,当当前回放位置在缓冲数据结束前500ms时进行过渡,使应用程序在回放停顿前有大约500ms的时间来追加更多的数据。
你所看到的行为是MSE兼容的浏览器意识到数据流还没有结束,但它也意识到它的数据正在耗尽。它通过改变它的 准备就绪状态 但它没有义务播放它已经持有的每一帧。它根据当前播放的时钟时间与可用数据的结束时间进入缓冲状态。
尽管上面的链接说...
例如,在视频中,这对应的是用户代理有当前帧的数据,但没有下一帧的数据。
......实际的实现可能会有不同的解释,并改用 HAVE_CURRENT_DATA
有点太早了,那就是多保留了几个视频帧,但知道它还没有结束流和进一步的帧丢失。这是一种浏览器实现的特殊性,你只能忍受。