解决ffmpeg生成mp3在ios上时长不对的问题

最近发现一个问题,ffmpeg生成的mp3文件,在ios上会出现时长不对的情况。

转换命令如下

文件实际时间是00:19:14,用windows和android播放时间长度显示都没问题,而ios的safari浏览器总是读出00:10:59这样的时间长度。神了。百思不得其解。

究竟是什么原因呢?

上网搜了一下CBR的mp3的长度计算,看了下和mp3音频帧的帧头有关。那我们就来详细看看文件到底发生了什么。使用hexdump来一步步的查看文件结构吧,首先是ID3的头,一共10字节,第四个字节值是04,看出ffmpeg3.2.4默认使用的是id3 v2.4。id3最后四个字节是00 00 00 23,根据标准里的算法,得知ID3不包含头的长度是35字节,所以总共是45字节。

接下来查看第一个mp3帧的头的内容,从第45字节偏移处数4个字节

使用一个网站来查询Mp3文件的第一个音频帧,得到如下内容

有点意思!居然不是我设定的码率!那接下来看看这个音频帧的内容

看起来好像是些乱七八糟的东西。接着往下看看下一个音频帧吧

和第一帧的头不一样,解码一下看看内容是什么意思

这次是对的。再看看第三帧的头

解码一下内容

虽然和第二帧不一样,但是看起来采样率和码率一样的。接下来看了几帧

都是交替的ff fb 10 c4和ff fb 12 c4

所以其实时间算不对和第一个音频帧是不是有关系?为了验证,我从网上随便下载了一首歌,ios可以正常识别其长度。看了下正常文件的结构,发现从第一个音频帧开始,标记的采样率和码率都是对的。真相大白了。

那么如何解决这个问题?得想办法让ffmpeg生成正确的首个音频包。先看看ffmpeg是否有相关的选项吧,于是打开了ffmpeg的官方文档,搜索和mp3相关的部分,在mp3 muxer部分找到了下面的内容

The MP3 muxer writes a raw MP3 stream with the following optional features:

  • An ID3v2 metadata header at the beginning (enabled by default). Versions 2.3 and 2.4 are supported, the id3v2_version private option controls which one is used (3 or 4). Setting id3v2_version to 0 disables the ID3v2 header completely.The muxer supports writing attached pictures (APIC frames) to the ID3v2 header. The pictures are supplied to the muxer in form of a video stream with a single packet. There can be any number of those streams, each will correspond to a single APIC frame. The stream metadata tags title and comment map to APIC description and picture type respectively. See http://id3.org/id3v2.4.0-frames for allowed picture types.Note that the APIC frames must be written at the beginning, so the muxer will buffer the audio frames until it gets all the pictures. It is therefore advised to provide the pictures as soon as possible to avoid excessive buffering.
  • A Xing/LAME frame right after the ID3v2 header (if present). It is enabled by default, but will be written only if the output is seekable. The write_xing private option can be used to disable it. The frame contains various information that may be useful to the decoder, like the audio duration or encoder delay.
  • A legacy ID3v1 tag at the end of the file (disabled by default). It may be enabled with the write_id3v1 private option, but as its capabilities are very limited, its usage is not recommended.

Examples:

Write an mp3 with an ID3v2.3 header and an ID3v1 footer:

To attach a picture to an mp3 file select both the audio and the picture stream with map:

Write a “clean” MP3 without any extra features:

所以说可以试试生成一个clean的mp3? 试了下,果然从第一个字节开始就是正确的码率和采样率了。解决方案如下:

所以还是要多看看官方文档。。。

另外继续搜了下ffmpeg的tickets,发现这是个陈年bug,但是被标记为wontfix。。。