Ffmpeg 在片段化MP4中的轨道运行是否必须从关键帧开始?

Ffmpeg 在片段化MP4中的轨道运行是否必须从关键帧开始?,ffmpeg,mp4,h.264,media-source,Ffmpeg,Mp4,H.264,Media Source,我正在摄取一个RTMP流,并将其转换为JavaScript中的一个片段MP4文件。这项工作花了一周时间,但我几乎完成了这项任务。我正在生成一个有效的ftypatom、moovatom和moofatom,视频的第一帧在进入无限缓冲区之前实际播放(带有音频),没有出现chrome://media-internals 将视频插入ffprobe,我得到一个类似以下的错误: [mov,mp4,m4a,3gp,3g2,mj2 @ 0x558559198080] Failed to add index ent

我正在摄取一个RTMP流,并将其转换为JavaScript中的一个片段MP4文件。这项工作花了一周时间,但我几乎完成了这项任务。我正在生成一个有效的
ftyp
atom、
moov
atom和
moof
atom,视频的第一帧在进入无限缓冲区之前实际播放(带有音频),没有出现
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.
这导致我在
tfhd
trun
原子中大量查找数据对齐问题或无效字节偏移量,但是无论我在哪里查看或如何切片数据,我都无法在
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
我在atom解析文件中通过
ffmpeg
打开了我正在创建的MP4和MP4输出,并对两者进行了比较:

我首先想到的是
ffmpeg
——生成的文件每个
moof
都有多个视频样本。具体地说,每个
moof
都从一个关键帧开始,然后包含所有差异帧,直到下一个关键帧(它被用作以下
moof
atom的开始)

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

这就是我遇到麻烦的原因吗?还是我还遗漏了什么

有关视频文件可在此处下载:

我注意到的另一个问题是
ffmpeg
tfhd
atom中大量使用
base\u data\u offset
。然而,当我尝试跟踪附加的总字节数并自行设置
base\u data\u offset
时,我在Chrome中遇到了一个错误:“MSE不支持base\u data\u offset”。根据ISO/IEC 14996-10规范:

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


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

否,moof不需要以关键帧开始。您正在生成的文件产生无效的NALUs大小错误,因为它具有无效的nal大小。每个nal(在mdat中)必须在其前面加上大小。查看您的文件,mdat后的前4个字节是
0x21180C68
,太大了,无法成为有效大小。

我先有音频曲目,然后是视频曲目
0x21180C68
是AAC数据,而不是H.264数据。要将其标记为正确,因为“不,moof不需要从关键帧开始。”准确回答了问题。但以下句子不正确(我的NAL大小是有效的,
0x21180C68
不是NAL大小,因为它是音频数据而不是视频数据)。我的视频没有播放的原因是我的
traf
的持续时间为0。误导性错误消息是由FFMPEG中的错误引起的。最后,我阅读了整个FFMPEG源代码,找出了其中的一个。