网页Flash播放器不能直接播放Mp4问题 & isom、mp42 & vbr、cbr

最近碰到网页播放视频的问题,其中有一部分是Mp4视频需要缓冲完才能播放。

经过查找,主要与视频文件有关,如果视频的元数据(即记录视频原始的宽度和高度,视频总时长,编码格式等信息的一段数据)在视频文件的头部,播放器可以直接获取视频信息,进行加载播放,但是如果元数据在视频末尾,那么浏览器需要一直加载视频,直到找到元数据为止才能播放。

由于对视频的格式以及编码不甚了解,本文只讲如何在Linux下修复这些文件。

在修复之前,有一种方案就是h5的video标签,如果只有Mp4的视频文件,那么推荐使用这种方法,最简单,并且顺应时势。

MP4box

安装MP4Box:

1
git clone https://github.com/gpac/gpac.git

如果是Ubuntu也可以下载官网的deb包安装,安装完成后执行如下命令即可:

1
MP4Box -isma test.mp4

注:安装MP4box需要安装许多依赖包,这个就不重点介绍了,详细看这里

qt-faststart

如果只需要解决这一个问题,可以直接安装这个工具。

把文件复制到自己的机器上,编译生成可执行命令:

1
gcc qt-faststart.c -o qt-faststart

什么都不加执行下这个命令:

1
2
Usage: qt-faststart <infile.mov> <outfile.mov>
Note: alternatively you can use -movflags +faststart in ffmpeg

非常简单,可以用下面的命令执行:

1
qt-faststart input.mp4 output.mp4

这样生成的output.mp4就是正常的了。

通过qt-faststart命令的输出提示Note: alternatively you can use -movflags +faststart in ffmpeg可以引出下面第三种方法。

FFmpeg

这个工具非常强大,例如截取视频缩略图,具体可看官方文档,他解决了我们日常涉及到的所有的视频相关的需求。

安装完成后执行:

1
ffmpeg -i input.mp4 -movflags faststart output.mp4

这三种方法我都简单测试过,针对300M以上的MP4Box速度相对慢很多,而使用FFmpeg可能会引入问题,因为我在测试的时候处理了一个不能直接播放的文件,处理之后不但不能播放,连图像都没了。而对同样的文件使用qt-faststart会给出相应的提示。

还有一点是为了让Mp4文件有更好的质量,一般在上传的时候都会转格式为H264视频编码 + AAC音频编码

针对这个问题可以使用安装简单的qt-faststart进行解决,如果有精力学习一下其它两个工具还是很有用的。

2018.5.1 update

最近碰到一些视频与音频兼容性的问题,主要集中在ios设备,分别是:

  1. 视频在ios手机上不能播放,或者有声音没有图像。
  2. ios10系统的手机mp3时间轴不准确,ios11没有这个问题。

isom、mp42

isom是ISO base media file format,MPEG-4的第十二部分。是基于ISO的媒体文件格式,定义一个存储媒体内容的文件格式。而mp42是MPEG-4的第十四部分,定义基于第十二部分的用于存储MPEG-4内容的视频文件格式,面向网络和移动设备。h264和MPEG-4第十部分是等价的。

上面的解释是在维基百科查到的,说明的有些抽象。

但是应该可以判断出来,mp42是在isom之后出现的,ios系统不能播放的原因可能是还没有更好的支持这种编解码器id。在工作场景下,当我们使用软件转换了视频文件,默认可能会使用mp42编码器,由于手机不支持,可能在播放的时候会出现问题。

通过下面的命令可以简单处理视频的编解码器:

1
2
3
4
5
6
#查看支持的编解码器id
ffmpeg -codecs
# 转换为h264编码
ffmpeg i input.mp4 -vcodec libx264 output.mp4
# 由于文件质量不同,可能会报错,添加下面的参数(音频的参数可以根据需要设置 -acodec libfaac)
ffmpeg -i input.mp4 -vcodec libx264 -vpre fast -acodec libfaac output.mp4

cbr、vbr

cbr是constant bitrate,代表恒定比特率,vbr是variable bitrate,代表可变比特率。
当我们用类似MediaInfo的这样工具查看mp3的属性信息的时候,会发现vbr编码的音频是没有比特率的,因为它是可变的,所以没有固定的比特率。cbr则是具有固定比特率的。

根据搜索,vbr相对上更节省空间,音质更好。比如mp3中某一段基本没什么声音,比特率会变低,当音频更复杂的时候,比特率增加。

但是,对于上面第二个问题,猜测问题的原因就是vbr,在查询过程中有网友回答iphone并不喜欢vbr音频。对于ios开发的AVFoundation框架,主要处理基于时间的媒体数据,它内部隐含的假设可能是比特率是恒定的,但是vbr音频的比特率本身就不是恒定的,所以就会出现问题。

比如,当我们需要播放1000ms - 2000ms的音频时,ios代码获取到开始时间和结束时间,通过时间与比特率计算字节偏移量,获取到内容进行播放,如果vbr编码的mp3这段音频的比特率是8kbps,但是ios框架认为是16kbps(平均的),那么字节偏移量与实际想要的就会出现偏差,播放出来的内容就会有差别。

可以通过下面的命令进行转换,指定固定的比特率就能转换成cbr:

1
ffmpeg -i input.mp3 -ab 16k output.mp3

上面ios相关的资源问题,均出自google与自己的理解,并没有严谨的理论验证,请根据实际情况进行测试。包括ios系统版本,ios开发使用的框架版本等等。

2018.6.15 update

添加一些ffmpeg的常用命令,下面两个命令与版本有关系,并不适用于所有的版本。

截取视频20秒处的帧作为缩略图:

1
ffmpeg -i input.mp4 -y -loglevel quiet -f image2 -ss 20 -vframes 1 output.jpg

多线程视频质量压缩,其中crf的参数为0-51,越小质量越高:

1
ffmpeg -threads 8 -y -i input.mp4 -vcodec libx264 -crf 28 -vpre fast -acodec libfaac output.mp4

(完)