FFMPEG指令 基本概念 获得音视频信息

FFmpeg是一个用于音视频处理的*软件,被广泛用于音视频开发。FFmpeg功能强大,本文主要介绍如何使用FFmpeg命令行工具进行简单的视频处理。

安装FFmpeg可以在官网下载各平台软件包或者静态编译版本,也可以使用包管理工具安装。

容器

我们熟悉的mp4,rmvb,mkv,avi是多媒体容器文件格式(或称多媒体封装格式),所谓容器是指将不同的数据流(视频流,音频流,字幕流等)封装在一个文件(载体)中。

播放时各种流分别进行解码等处理后,然后输出到显示器和音响等设备进行播放。多媒体容器格式不同于编码格式,一个容器中可以封装多种编码格式的媒体流。

流封装了实际的媒体数据,如视频流,音频流和字幕流等。一般情况下,流中的数据只能使用一种编码格式。

帧率

帧率(frames per second, fps)是每秒画面刷新的次数,帧率越高视频越流畅。一般来说30fps就是可以接受的,60fps则可以明显提升交互感和逼真感,但是一般超过75fps一般就不容易察觉到有明显的流畅度提升了。

分辨率

分辨率表示画面的精细程度,通常用像素密度来表示,常用的单位为ppi(像素每英寸)。通常像素密度越高画面越精细,模糊程度越低。

对于视频文件而言,像素密度是无法控制的(由播放器和显示设备决定)。我们通常用视频的像素数来表示它的分辨率如1080x640, 640x320等。

比特率

比特率(bit rate)又称码率,表示多媒体流每秒输出的字节数,单位为KB/s, Kbps等。同样的压缩算法下,比特率越高音视频的质量越好。

可变码率(Variable Bitrate, VBR)指的是编码器的输出码率可以根据输入源信号的复杂度进行自适应调整,以在输出质量保持不变的条件下尽可能减少数据量。VBR适用于存储,不太适用流式传输。

固定码率(Constant Bitrate, CBR)指的是编码器输出码率固定,CBR不适合存储,对于复杂内容可能没有足够码率进行编码,从而导致质量下降,同时会在简单内容部分浪费一些码率。

采样率

每秒钟对音频信号的采样次数,采样频率越高声音还原度越高,声音更加自然,单位是赫兹 Hz。

音频文件一般使用的采样率是 44.1 kHz,也就是一秒钟采样44100次,实验发现低于这个值就会有较明显的损失,而高于这个值人的耳朵已经很难分辨,而且增大了数字音频所占用的空间。

视频编码

视频流可以看做图片的序列,我们把这个序列中的一张图片称为一帧。若存储视频中所有帧则会数据量过大,不便于存储和传输。

所幸统计表明大多数视频相邻帧之间的区别并不大,所以对于一段变化不大的视频,我们可以先完整编码帧A,其后的B帧只需要编码与A帧不同的部分,B帧后的C帧则只编码与B帧的差异。如此递推,将一段视频编码为一个序列。

当某个图像与之前的图像变化很大无法参考前面的帧来生成,我们就结束上一个序列将该帧完整编码开始一个新的序列。

H264是目前流行的一种视频编码算法,它定义了三种帧:完整编码的I帧,参考I帧生成只包含差异的P帧,以及以及参考前后帧编码的B帧。

H264采用的核心算法是帧内压缩和帧间压缩,帧内压缩是生成I帧的算法,帧间压缩是生成B帧和P帧的算法。

通常,我们也把完整编码的I帧称为关键帧。因为解码非关键帧需要解码其参考的帧,因此在截图等不需要全部解码的操作中,经常截取关键帧以提升性能。

获得音视频信息

ffprobe是FFmpeg项目提供的用于分析视频信息的命令行工具。

随意下载一个测试视频testmp4, 然后终端中输入指令:

ffprobe -v quiet -print_format json -show_format -show_streams test.mp4

可以获得json格式输出的视频信息:

{
    "streams": [ // 文件中包含的流
        {
            "index": 0,  // 流的序号
            "codec_name": "h264", // 流的编码格式
            "codec_long_name": "H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10", // 编码格式的全名
            "profile": "High", 
            "codec_type": "video", // video表示这是一个视频流
            "codec_time_base": "1/60",
            "codec_tag_string": "avc1",
            "codec_tag": "0x31637661",
            "width": 1080, // 视频宽为1080像素
            "height": 614, // 视频高为614像素
            "coded_width": 1080,
            "coded_height": 614,
            "has_b_frames": 2,
            "sample_aspect_ratio": "0:1",
            "display_aspect_ratio": "0:1",
            "pix_fmt": "yuv420p",
            "level": 31,
            "chroma_location": "left",
            "refs": 1,
            "is_avc": "true",
            "nal_length_size": "4",
            "r_frame_rate": "30/1", // 实际帧率
            "avg_frame_rate": "30/1",
            "time_base": "1/15360",
            "start_pts": 0,
            "start_time": "0.000000",
            "duration_ts": 153093,  
            "duration": "9.966992",  // 以秒为单位的视频时间
            "bit_rate": "2077265",  // 视频的比特率
            "bits_per_raw_sample": "8",
            "nb_frames": "299",
            "tags": {  // 流中的附加信息,其中的字段可能为空
                "rotate": 90, // 视频旋转的角度
                "language": "und",
                "handler_name": "VideoHandler"
            }
        },
        {
            "index": 1, // 流编号
            "codec_name": "aac", // 流的编码格式