在碎片MP4中运行的轨道是否必须以关键帧开始?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在碎片MP4中运行的轨道是否必须以关键帧开始?相关的知识,希望对你有一定的参考价值。

我正在摄取RTMP流并将其转换为javascript中的碎片化MP4文件。这花了一个星期的工作,但我差不多完成了这项任务。我正在生成一个有效的ftyp原子,moov原子和moof原子,视频的第一帧实际播放(带音频),然后进入无限缓冲,没有错误列在chrome://media-internals

将视频插入ffprobe,我得到类似于的错误:

[mov,mp4,m4a,3gp,3g2,mj2 @ 0x558559198080] Failed to add index entry
    Last message repeated 368 times
[h264 @ 0x55855919b300] Invalid NAL unit size (-619501801 > 966).
[h264 @ 0x55855919b300] Error splitting the input into NAL units.

这导致我在tfhdtrun原子中大量寻找数据对齐问题或无效字节偏移,但无论我在哪里查看或如何切片数据,我都无法在moof原子中找到任何问题。

然后,我使用以下命令获取原始FLV文件并将其转换为ffmpeg中的MP4:

ffmpeg -i ~/Videos/rtmp/big_buck_bunny.flv -c copy -ss 5 -t 10 -movflags frag_keyframe+empty_moov+faststart test.mp4

我在原子解析文件中打开了我创建的MP4和ffmpeg的MP4输出,并将两者进行了比较:

Comparing MP4 files with MP4A

跳出来的第一件事是ffmpeg生成的文件每个moof有多个视频样本。具体来说,每个moof都以1个关键帧开始,然后包含所有差异帧,直到下一个关键帧(用作以下moof原子的开头)

将此与我生成MP4的方式进行对比。每当FLV moof数据包到达时,我创建一个VIDEODATA原子。这意味着我的moof可能不包含关键帧(通常不包含)

这可能就是我遇到麻烦的原因吗?或者还有其他我想念的东西?

有问题的视频文件可以在这里下载:

我注意到的另一个问题是ffmpegbase_data_offset原子中大量使用tfhd。但是,当我尝试跟踪附加的总字节数并自己设置base_data_offset时,我在Chrome中遇到错误:“MSE不支持base_data_offset”。根据ISO / IEC 14996-10规范:

如果未提供,则电影片段中第一个轨道的基础数据偏移量是封闭的电影片段框的第一个字节的位置,对于第二个和后续的轨道片段,默认值是由定义的数据的结尾。前面的片段。

这个措辞让我相信第一个data_offset原子中的trun应该等于moof原子的大小,而第二个data_offset原子中的trun应该是0(从前面片段定义的数据末尾开始的0个字节) 。但是,当我尝试这个时,我得到一个错误,无法解析视频数据。导致可以解析的数据的原因是moof原子的长度加上第一个轨道的总长度(好像基本偏移是封闭的moof框的第一个字节,与第一个轨道相同)

答案

不,moof不需要从关键帧开始。您生成的文件会产生无效的NALU大小错误,因为它具有无效的nal大小。即使是nal(在mdat中)也必须具有前置的大小。查看你的文件,mdat之后的前4个字节是0x21180C68,它太大而不是有效大小。

以上是关于在碎片MP4中运行的轨道是否必须以关键帧开始?的主要内容,如果未能解决你的问题,请参考以下文章

AEJoy —— 表达式之速度和频率控制JS

是否可以以编程方式构造 Python 堆栈帧并在代码中的任意点开始执行?

从 MP4/FLV 中提取帧?

视频转码成mp4格式,添加关键帧,添加元数据,把元数据放在第一帧

视频转码成mp4格式,添加关键帧,添加元数据,把元数据放在第一帧,可拖动

FFmpeg 常用指令集合