我已经编写了一个MP4解析器,可以很好地读取MP4中的原子,并将它们拼接在一起 - 结果是一个技术上有效的MP4文件,Quicktime可以打开等等,但它不能播放任何音频,因为我相信时间/采样信息全部关闭。我应该提一下,我只对音频感兴趣。
我正在做的是尝试从现有的MP4中取出moov原子/ etc,然后只取一个文件中mdat原子的子集来创建一个新的,更小的MP4。这样做,我改变了duration
原子中的mvhd
,以及mdia
标题中的持续时间。此文件中没有tkhd
个原子进行编辑,所以我相信我不需要改变那里的持续时间 - 我错过了什么?
在创建新的MP4时,我正确地使用宽盒子对mdat
块进行切片,并保留“mdat”#39;标题/大小在正确的位置 - 我确保使用新内容更新大小。
现在它完全有110%可能我错过了关于这种格式的重要内容,但如果可能的话,我很想得到最后一块。有人有任何意见吗?
代码可以在以下链接找到:
答案 0 :(得分:26)
我将在黑暗中捅一下并说你没有正确更新你的stbl
补偿。至少我没有(乍一看)看到你的python在任何地方都这样做。
让我们从数据的位置开始。数据包以块的形式写入文件中,标题告诉解码器这些块的每个“块”存在于何处。 stsc
表说明每个块存在多少项。 first chunk
表示新块开始的位置。这有点令人困惑,但看看我的例子。这就是说每个chunkk有100个样本,直到第8个块。在第8个块有98个样本。
那就是说,你还必须追踪这些块的偏移量。这是stco
表的工作。因此,文件中的块偏移量为1,或者块偏移量为2等。
如果修改mdat
中的任何数据,则必须维护这些表。您不能只将mdat
数据删除,并希望解码器知道该怎么做。
好像这还不够,现在您还必须维护样本时间表(stts
)样本大小表(stsz
),如果这是视频,则同步样本表( stss
)。
stts
表示样本应按时间单位播放多长时间。如果你正在做音频,时间刻度可能是44100或48000(kHz)。
如果您丢失了一些数据,现在一切都可能不同步。如果这里的所有值都具有完全相同的持续时间,尽管你没事。
stsz
表示每个样本的大小(以字节为单位)。这对于解码器能够从一个块开始,然后按其大小遍历每个样本很重要。
同样,如果所有样本大小完全相同,那么你就可以了。音频往往几乎相同,但视频内容变化很大(关键帧等等)
最后但并非最不重要的是,我们有stss
表,其中说明了哪些帧是关键帧。我只有AAC经验,但每个音频帧都被认为是一个关键帧。在这种情况下,您可以有一个描述所有数据包的条目。
关于您的原始问题,时间显示在每个玩家中并不总是以同样的方式表现出来。最准确的方法是总结标题中所有帧的持续时间,并将其用作总时间。其他玩家使用轨道标题中的元数据。我发现最好保持所有的价值相同然后玩家很开心。
如果您正在做所有这些并且我在脚本中错过了它,那么您可以发布样本mp4和独立应用程序,我可以尝试帮助您。