本文章是阅读《音视频开发进阶指南基于android与ios平台的实践》一书的学习笔记。
http://ffmpeg.org
若要讲解音视频的开发,首先不得不提开源框架 FFmpeg。该开源框架为音视频开发者们提供了非常大的帮助,其也是全世界的音视频开发工程师都应该掌握的工具。
FFmpeg 是一套可以用来记录、处理数字音频、视频,并将其转换为流的开源框架,提供了录制、转换以及流化音视频的完整解决方案。
它的可移植性或者说跨平台特性非常强大,可以用在 Linux 服务器、PC (包括 Windows、Mac OS X 等)、移动端设备 (Android、iOS 等移动设备) 等平台。
名称中的 mpeg 来自视频编码标准 MPEG,而前缀 FF 是 Fast Forward 的首字母缩写。本章会从编译开始讲解,然后介绍命令行工具的使用,接着会介绍 FFmpeg 在代码层面提供给开发者的 API,最后会从源码的角度分析一下整个 FFmpeg 框架。
FFmpeg github 上已经有现成编译好的 android 库:https://github.com/xufuji456/FFmpegAndroid,简介如下:
android 端基于 FFmpeg 库的使用,添加编译 ffmpeg、shine、mp3lame、x264 源码的参考脚本,目前音视频相关处理:
默认的编译会生成 4 个可执行文件和 8 个静态库。可执行文件包括用于转码、推流、Dump 媒体文件的 ffmpeg、用于播放媒体文件的ffplay、用于获取媒体文件信息的 ffprobe,以及作为简单流媒体服务器的 ffserver。8 个静态库其实就是 FFmpeg 的 8 个模块,具体包括如下内容:
如何为 FFmpeg 平台引入第三方编解码库呢?下面就以最常用的 LAME、X264、FDK-AAC 进行举例。前面的章节中已经介绍了这三个库在 Android 和 iOS 平台上的交叉编译,现在就假设已经交叉编译出了 LAME、X264、FDK-AAC 的静态库与头文件,并且在 FFmpeg 的源码目录下建立了 external-libs 目录,还在其中建立了 LAME、X264、FDK-AAC 三个目录,每个目录中的结构都包含了 include 和 lib两个目录,并且将编译出来的头文件和静态库文件分别都放到了这两个目录下面。
现在修改编译脚本如下:
新增 X264 编码器需要新增以下脚本:
--enable-muxer=h264 \
--enable-encoder=libx264 \
--enable-libx264 \
--extra-cflags=”-Iexternal-libs/x264/include” \
--extra-ldflags=”-Lexternal-libs/x264/lib” \
新增 LAME 编码器需要新增以下脚本:
--enable-muxer=mp3 \
--enable-encoder=libmp3lame \
--enable-libmp3lame \
--extra-cflags=”-Iexternal-libs/lame/include” \
--extra-ldflags=”-Lexternal-libs/lame/lib” \
新增FDK-AAC编码器需要新增以下脚本:
--enable-encoder=libfdk_aac \
--enable-libfdk_aac \
--extra-cflags=”-Iexternal-libs/fdk-aac/include” \
--extra-ldflags=”-Lexternal-libs/fdk-aac/lib” \
可以按照自己的应用场景,把需要编译进来的第三方库以修改脚本文件的方式进行编译,然后以命令行模式或者以API调用的方式进行使用。
FFmpeg 中有 ffmpeg、ffprobe、ffplay以及 ffserver 等命令行工具,这边将重点介绍 ffmpeg、ffprobe 与 ffplay 这三个命令行工具,而ffserver 则是作为简单的流媒体服务器存在的,与客户端开发关系不大。
4.1 ffprobe
先来测试一个音频文件:
ffprobe /Users/kuangzhongwen/Desktop/my\ documents/kuang\ Music/繁星-阿文.mp3
输出:
# 时长 03:51.80,开始播放时间为 0,比特率是 128 kb/s
Duration: 00:03:51.80, start: 0.000000, bitrate: 128 kb/s
# 第一个流是音频流,编码格式是 mp3,采样率为 44100,声道是立体声,采样表示格式是 fltp,路流比特了是 128 kb/s
Stream #0:0: Audio: mp3, 44100 Hz, stereo, fltp, 128 kb/s
再来测试一个视频文件:
ffprobe /Users/kuangzhongwen/Desktop/my\ documents/视频/女生节.mpg
输出:
# 时长,开始播放时间,比特率
Duration: 00:04:47.48, start: 0.220000, bitrate: 8381 kb/s
Stream #0:0[0x1bf]: Data: dvd_nav_packet
# stream,视频流,格式为 mpeg2video,每一帧的数据表示为 yuv420P,分辨率为 720x576,fps 为 25
Stream #0:1[0x1e0]: Video: mpeg2video (Main), yuv420p(tv, top first), 720x576 [SAR 64:45 DAR 16:9], 25 fps, 25 tbr, 90k tbn, 50 tbc
# stream 音频流,格式为 pcm_dvd,采样率为 48000 Hz,2 个声道,音频流比特率为 1536 kb/s
Stream #0:2[0xa0]: Audio: pcm_dvd, 48000 Hz, 2 channels, s16, 1536 kb/s
格式化输出:
ffprobe -show_format /Users/kuangzhongwen/Desktop/my\ documents/视频/女生节.mpg
输出:
[FORMAT]
filename=/Users/kuangzhongwen/Desktop/my documents/视频/女生节.mpg
nb_streams=3
nb_programs=0
format_name=mpeg
format_long_name=MPEG-PS (MPEG-2 Program Stream)
start_time=0.220000
duration=287.480000
size=301199360
bit_rate=8381782
probe_score=26
[/FORMAT]
JSON 格式输出:
ffprobe -print_format json -show_streams /Users/kuangzhongwen/Desktop/my\ documents/视频/女生节.mpg
输出:
{
Input #0, mpeg, from '/Users/kuangzhongwen/Desktop/my documents/视频/女生节.mpg':
Duration: 00:04:47.48, start: 0.220000, bitrate: 8381 kb/s
Stream #0:0[0x1bf]: Data: dvd_nav_packet
Stream #0:1[0x1e0]: Video: mpeg2video (Main), yuv420p(tv, top first), 720x576 [SAR 64:45 DAR 16:9], 25 fps, 25 tbr, 90k tbn, 50 tbc
Stream #0:2[0xa0]: Audio: pcm_dvd, 48000 Hz, 2 channels, s16, 1536 kb/s
Unsupported codec with id 100357 for input stream 0
"streams": [
{
"index": 0,
"codec_name": "dvd_nav_packet",
"codec_long_name": "DVD Nav packet",
"codec_type": "data",
"codec_tag_string": "[0][0][0][0]",
"codec_tag": "0x0000",
"id": "0x1bf",
"r_frame_rate": "0/0",
"avg_frame_rate": "0/0",
"time_base": "1/90000",
"start_pts": 19800,
"start_time": "0.220000",
"disposition": {
"default": 0,
"dub": 0,
"original": 0,
"comment": 0,
"lyrics": 0,
"karaoke": 0,
"forced": 0,
"hearing_impaired": 0,
"visual_impaired": 0,
"clean_effects": 0,
"attached_pic": 0,
"timed_thumbnails": 0
}
},
{
"index": 1,
"codec_name": "mpeg2video",
"codec_long_name": "MPEG-2 video",
"profile": "Main",
"codec_type": "video",
"codec_time_base": "1/25",
"codec_tag_string": "[0][0][0][0]",
"codec_tag": "0x0000",
"width": 720,
"height": 576,
"coded_width": 0,
"coded_height": 0,
"has_b_frames": 1,
"sample_aspect_ratio": "64:45",
"display_aspect_ratio": "16:9",
"pix_fmt": "yuv420p",
"level": 8,
"color_range": "tv",
"chroma_location": "left",
"field_order": "tt",
"refs": 1,
"id": "0x1e0",
"r_frame_rate": "25/1",
"avg_frame_rate": "25/1",
"time_base": "1/90000",
"start_pts": 19800,
"start_time": "0.220000",
"duration_ts": 25873200,
"duration": "287.480000",
"disposition": {
"default": 0,
"dub": 0,
"original": 0,
"comment": 0,
"lyrics": 0,
"karaoke": 0,
"forced": 0,
"hearing_impaired": 0,
"visual_impaired": 0,
"clean_effects": 0,
"attached_pic": 0,
"timed_thumbnails": 0
}
},
{
"index": 2,
"codec_name": "pcm_dvd",
"codec_long_name": "PCM signed 20|24-bit big-endian",
"codec_type": "audio",
"codec_time_base": "1/48000",
"codec_tag_string": "[0][0][0][0]",
"codec_tag": "0x0000",
"sample_fmt": "s16",
"sample_rate": "48000",
"channels": 2,
"bits_per_sample": 0,
"id": "0xa0",
"r_frame_rate": "0/0",
"avg_frame_rate": "0/0",
"time_base": "1/90000",
"start_pts": 19800,
"start_time": "0.220000",
"duration_ts": 25873091,
"duration": "287.478789",
"bit_rate": "1536000",
"bits_per_raw_sample": "16",
"disposition": {
"default": 0,
"dub": 0,
"original": 0,
"comment": 0,
"lyrics": 0,
"karaoke": 0,
"forced": 0,
"hearing_impaired": 0,
"visual_impaired": 0,
"clean_effects": 0,
"attached_pic": 0,
"timed_thumbnails": 0
}
}
]
}
显示帧信息的命令如下:
ffprobe -show_frames sample.mp4
查看包信息的命令如下:
ffprobe -show_packets sample.mp4
4.2 ffplay
ffplay 是以 FFmpeg 框架为基础,外加渲染音视频的库 libSDL 来构建的媒体文件播放器。它所依赖的 libSDL 是1.2版本的,所以在安装ffplay 之前也要安装对应版本的 libSDL 作为其依赖的组件。之后使用 ffplay 就非常简单了,比如我们要播放一个音频文件。
ffplay /Users/kuangzhongwen/Desktop/my\ documents/kuang\ Music/繁星-阿文.mp3
或者视频文件:
ffplay /Users/kuangzhongwen/Desktop/my\ documents/视频/女生节.mpg
会打开 ffmpeg 自带的播放器播放。
业界内开源的 ijkPlayer 其实就是基于 ffplay 进行改造的播放器,当然其做了硬件解码以及很多兼容性的工作。ijkPlayer 是一款非常优秀的播放器,作为开发者的我们需要很多优秀的开源项目。
4.3 ffmpeg
ffmpeg 其实是这三个命令行工具里最强大的一个工具,如果说 ffprobe 是用于探测媒体文件的格式以及详细信息,ffplay 是一个播放媒体文件的工具,那么 ffmpeg 就是强大的媒体文件转换工具。它可以转换任何格式的媒体文件,并且还可以用自己的 AudioFilter 以及VideoFilter 进行处理和编辑,总之一句话,有了它,进行离线处理视频时可以做任何你想做的事情了。