我正在摄取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.
这导致我在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
我在原子解析文件中打开了我创建的MP4和ffmpeg
的MP4输出,并将两者进行了比较:
跳出来的第一件事是ffmpeg
生成的文件每个moof
有多个视频样本。具体来说,每个moof
都以1个关键帧开始,然后包含所有差异帧,直到下一个关键帧(用作以下moof
原子的开头)
将此与我生成MP4的方式进行对比。每当FLV moof
数据包到达时,我创建一个VIDEODATA
原子。这意味着我的moof
可能不包含关键帧(通常不包含)
这可能就是我遇到麻烦的原因吗?或者还有其他我想念的东西?
有问题的视频文件可以在这里下载:
我注意到的另一个问题是ffmpeg
在base_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
,它太大而不是有效大小。