使 MKV 文件适合使用 ffmpeg(或 avconv)进行流式传输 - 如何将所有元数据移动到文件开头?

使 MKV 文件适合使用 ffmpeg(或 avconv)进行流式传输 - 如何将所有元数据移动到文件开头?

我认为我的问题非常简单......

有时我喜欢从我的网络服务器下载大型 MKV 文件,并在下载时播放它们。但是,如果我对已转码的 MKV 文件执行此操作,文件通常会显示比实际短得多,并且在到达结尾后它会继续播放并显示错误的时间...例如它会显示 2:50/2:50 但继续播放,但是如果我尝试使用箭头键向后搜索,播放器会崩溃或跳回到文件的开头。

那么,如何在编码时将所有元数据移动到文件的开头,以便播放器无需了解整个文件就知道文件的长度?您可以mp4使用以下格式执行此操作-movflags faststart,但该怎么办呢mkv

如果这个问题已经在其他地方问过并得到回答,我很抱歉,我想不出比我使用的更好的关键词,而我使用的关键词没有产生任何结果。

答案1

Matroska 基金会提供了一个工具,清理,其执行的任务与 qt-faststart 对 MOV/MP4 执行的任务类似。

句法:

mkclean in.mkv out.mkv

这将重新生成提示索引。要保留原始提示,

mkclean --keep-cues in.mkv out.mkv

FFmpeg 也可以做到,用户需要进行一些猜测。

ffmpeg -i in.mkv -c copy -reserve_index_space 50k out.mkv 

其中,reserve_index_space以字节为单位的值是索引所需的大小。50k字节是 1 小时媒体的建议大小。

答案2

建在……之上Gyan 的回答,mkclean 是优化 MKV 以进行流式传输的正确工具。但是,我注意到 mkclean 生成文件的方式有些怪异,因此我创建了一个分支:https://github.com/XMB5/mkclean-pragmatic

使用示例:mkclean test.mkv test_streaming_optimized.mkv

以下是自述文件的一些摘录:

背景(为什么我们首先需要 mkclean)

为了播放 mkv 文件,视频播放器需要读取提示元素,是将视频时间戳映射到字节偏移量的文件的一部分。这些偏移量允许视频播放器在整个视频中查找时间戳,而无需猜测文件中的字节位置。

通常,cues 元素位于 matroska 文件的末尾(参见matroska结构图)。这是因为创建 mkv 的应用程序首先写入所有视频数据,然后才知道视频内容的确切字节位置。

但是,将提示元素放在文件末尾并不理想:视频播放器必须读取文件开头的搜索头,然后搜索文件末尾以读取提示信息,然后搜索回来读取视频内容。使用 HTTP 流式传输,这相当于 3 个单独的请求,与 1 个请求相比,这会增加几秒钟的延迟。

mkclean重组 mkv 文件,使提示元素位于开头,从而允许视频更快地开始播放。

fork 中的技术变化(与原始 mkclean 相比)

  • matroska v4默认 将 doctype 版本设置为
    • 将文档读取版本设置为 2(为了兼容性,否则它将无法与 vlc、mpv、ffmpeg 等一起使用)
  • 默认禁用优化(相当于正常的 mkclean--no-optimize标志)
  • 当集群时间戳不按时间顺序排列时忽略
    • 强制更改时间戳会导致 mpv 警告“视频时间戳无效:10.085000 -> 10.060000”

相关内容