ffmpeg

FFmpeg操作音视频
1、发展历史及它用来解决什么问题
FFmpeg项目最初是由Fabrice Bellard发起的,从2004年起由Michael Niedermayer领导进行维护。许多FFmpeg的开发者同时也是MPlayer项目的成员,FFmpeg在MPlayer项目中是被设计为服务器版本进行开发。
2011年3月13日,FFmpeg部分开发人员决定另组Libav,同时制定了一套关于项目继续发展和维护的规则。
FFmpeg的名称来自MPEG视频编码标准,前面的“FF”代表“Fast Forward”,FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。可以轻易地实现多种视频格式之间的相互转换,还有流媒体服务等诸多功能,可以说涵盖了音视频开发中绝大多数的领域。

2、介绍 FFmpeg 主要模块和基础知识简介
ffmpeg_第1张图片
基础知识,容器一种文件格式,例如flv,mkv,mp4等,是传输视频信息的一种方式。它包括五种流:音频,视频,字幕,附件,数据帧。帧代表静止的图像,分别有I帧,P帧,B帧。
编解码器,对视频进行压缩,解压缩。复用/解复用,它的本质就是把不同的流按照某种容器规则放入容器中,这种行为叫做复用。把不同的流从容器中解析出来叫做解复用。
音视频常用网络协议有rtsp,rtp,rtcp,http,rtmp等。
音频常用封装格式AVI,RMVB,MKV,ASF,WMV,MP4,3GP,FLV等。
视频常用编解码格式有H.264,MPEG-4,MPEG-2,VP8,VP9,VC-1等。
音频常用的编码格式有AAC,AC-3, MP3的,WMA等。

3、音视频解码,音视频重采样
视频一般都是经过打包和编码的视频文件,需要解复用和解码得到原始数据。下面一起来看音视频解码以及重采样的过程。
ffmpeg_第2张图片
上图是对音视频解码和重采样过程,里面的函数是ffmpeg提供的一些API。按照图中的顺序调用API就可以对音视频进行解码和重采样。后面会介绍里面一些API的含义和作用。
首先介绍图中第一个API它的定义如下:
int avformat_open_input(AVFormatContext **ps, const char *filename,
AVInputFormat *fmt, AVDictionary **options);
它的作用是用来打开一个音视频文件,第一个参数是一个AVFormatContext指针变量的地址,它会根据打开的文件信息填充AVFormatContext,这里的ps必须初始化为NULL,不然后面会有问题。第二个参数是文件的位置或者网络地址。后两个参数分别用于指定特定的输入格式以及指定文件打开额外参数的AVDictionary结构,这里均留作NULL。
API内部主要函数调用关系如图所示:
ffmpeg_第3张图片
从上图可以清晰的的看出在内部函数的调用关系,在API内部他对 AVFormatContext进行了初始化,之后是调用init_input()函数。绝大部分初始化的工作由init_input()完成,read_header()是用来读取多媒体数据,文件头,根据视音频流创建相应的AVStream。
av_probe_input_format2()根据输入数据查找合适的AVInputFormat。 av_probe_input_buffer2()根据输入的媒体数据推测该媒体数据的AVInputFormat。这里需要说明AVInputFormat,它表示输入文件容器封装格式。
av_open2()内部主要函数调用关系如图所示:

ffmpeg_第4张图片
根据上图可知内部函数调用的关系,简单的来说av_open2()就是完成具体协议的读写任务。
接下来说一下音频解码APIavcodec_decode_audio4 ,在解码之前需要找音频流,找到对应的解码器,打开解码器这些操作。讲解音频解码API的定义和参数的意义。
定义:int avcodec_decode_audio4 (AVCodecContext * ps, AVFrame * frame, int * got_frame_ptr, const AVPacket * avpkt)
首先第一个参数是上下文,第二个参数是用于存储解码音频样本的AVFrame,由av_frame_alloc()初始化,第三个参数含义是如果有音频帧解码值为非零否则值为零,最后一个参数是输入缓存区的输入AVPacket。返回数据,解码失败返回错误信息,解码成功返回AVPacket被消耗的字节数。解码后得到PCM格式的音频数据。
得到数据后对音频数据重采样,首先需要调用swr_alloc_set_opts()设置采样的参数,最后调用swr_convert()完成对音频的重采样。
设置参数并不能直接对音频直接转换它是转换的规则定义如下:
swr_alloc_set_opts(struct SwrContext *s,
int64_t out_ch_layout,
enum AVSampleFormat out_sample_fmt,
int out_sample_rate,
int64_t in_ch_layout,
enum AVSampleFormat out_sample_fmt,
int in_sample_rate,
int log_offset,
void *log_ctx);
第一个参数是定义的SwrContext,第二到第三个参数分别是输出音频的声道,采样格式,采样率,第四到第五个参数分别是输入音频的声道,采样格式,采样率,两个参数设置为NULL。设置完之后调用swr_init()初始化。
真正重采样是重复调用swr_convert实现,swr_convert的定义如下:
swr_convert(struct SwrContext *s,
uint8_t **out,
int out_count,
const uint8_t **in ,
int in_count);
第一个参数是上下文定义的SwrContext,第二个参数是输出缓冲区,只有在打包音频的情况下才需要设置第一个,第三个参数是每个通道中可用于输出的样本数,第四个参数是输入的缓冲区,只有在打包音频的情况下才需要设置第一个,最后一个参数是每个通道的中可用的输入样本数。如果提供的输入出空间比输出空间大,输入将被缓冲,可以提供比输入更大的空间来避免出现缓冲的情况。
完整的示例demo:enter link description here
4、在 C++ 中使用 FFmpeg 集成腾讯云直播和阿里语音识别

ffmpeg_第5张图片
上图是对集成过程的一个大概表示,通过ffmpeg把从用户麦克风采集到的音频和摄像头采集到的视频推流到腾讯云直播上,此时我们在网页上打开直播的播放地址就可以看见用户的视频,服务器再通过ffmpeg把用户的音视频数据解析到服务器本地进行解码重采样,最后把经过处理的音频数据来调用语音识别的接口,最后我们可以在服务器上看到打印的语音识别结果。
从服务器到用户一种是ffmpeg直接在命令行中执行推流的命令:ffmpeg -re -i “文件地址” -c copy -f flv “推流地址”。
另一种是用C++调用ffmpeg的API。示例程序:enter link description here
阿里智能语音识别的C++ sdk demo文件:enter link description here

5、使用 FFmpeg 的总结和心得体会
这里主要用到的是ffmpeg解码,推流,重采样。除了这些功能它还有很多别功能,视频的裁剪,拼接,转码,转录等等。希望以后能和大家一道一起学习,相互交流,共同进步。

你可能感兴趣的:(ffmpeg)