做了几年的视频相关项目,一直没有系统的对所涉技术进行整理,趁着最近有点事情,整理归纳一下。多媒体技术还是一个相当大而全的领域,我是做视频的,只谈一下视频所涉的一些技术点的理解,平台是基于Android的。
视频所涉的多媒体技术也是非常庞大的,从哪入手呢,先来看一下图吧:
上图显示了一个视频从产生到展示到用户面前所涉的各个环节,封装格式直接使用了当前主流的mp4,编解码协议为H264/AAC。
按上图所示的流程,逐步看一下都有那些技术,并谈一下自己对该方面技术的概括性理解。
一、拍摄
所有视频都是拍出来的,即使是已有视频,也是前人拍出来的,合成视频,是用别人拍出来的视频合成的。在Android平台上,与拍摄有关的技术涉及摄像头及音频采集(一般是MIC)。Android系统提供了录制的Api:MediaRecorder,以及摄像头相关的Camera,与音频录制相关的api:AudioRecord。在我们的项目中,有两种方式的录制:其一是直接使用MediaRecorder直接录制带有音频数据的视频文件,这种做法的好处是实现简单,在定制化不强的业务场景,直接使用该方法即可;其二是分开使用Camera录制视频,使用AudioRecorder录制音频,后期生成视频文件时进行音视频合成,这种实现方法比第一种要复杂很多,但可以获得到单独的音频及视频数据,可以二次加工(比如加水印、人脸识别),当前我们项目所采用的录制方式是第二种。
与拍摄有关的技术还包括:拍摄之前或拍摄中的摄像头预览,什么意思呢,没有预览,拍摄就是黑盒的,也是说设备是在录制,但操作者看不到录制过程,就像十几年前的机械相机一样。Android平台,预览可以使用GLSurfaceView来做,网上资料也是比较多的,感兴趣的可以参考下。有一个注意点,摄像头支持的尺寸及比例是有定值的,当前Android屏幕设备尺寸多种多样,比如18.5:9的屏幕,其摄像头不一定有这个比值,因此预览的界面展示要有取舍,或者裁剪边缘,或者要留一些黑边。另外,输出的视频格式一般场景也不要太大,比如,用于短视频的,最大取至720p即可,宽高比太大,意味着生成的视频在编辑处理时给设备造成很大的压力,当前大部分手机设备的处理性能并没有想象中那么给力。
二、A/D转换
拍摄过程在硬件及系统层面包含了采集、抽样、量化。采集就是通过硬件设备获取外界信息,其输出为一些模似信号。模拟信号要进行处理前要进行抽样,以音频信号为例,一般采用8kHz抽样即可得到可接受的人的语音信号(电话的抽样频率),通俗的说,就是每秒均分成8千次从模拟信号中获取声音的当时值。抽到的样本要经过量化,仍以音频为例,抽样得到的样本,要用数值来表示,PCM算法中,使用8位二进制制表示该值,即有2^8=256个样本值表述样本的大小。PCM算法所得到的音频文件码率为:8kHz*8bit=64kbit/s,也就是说一秒钟的该音频,文件大小为8KB。此处提到一个码率的概念,稍后会详细讨论一下。抽样量化编码合并称为模数转换(也叫A/D转换)。视频的A/D转换转为复杂,不做该方面工作的不需要对其间的算法进行深究,只要了解输入及输出即可。经过A/D转换后,视频文件输出格式为YUV或RGB(二者只是存储格式有所差异,可相互转换),音频为PCM格式文件。
三、音视频编码
为什么要进行编码呢?一个字概括就是;大。量化后的文件格式非常的大,直接存储耗费大量的存储空间,在网络中传输更是不可想象的。我们可以折算一下,以RGB888格式的720*1080的视频为例,一帧图像的大小为:3*8*720*1080=18.7Mb,每秒30帧的话30*18.7Mb=560Mbit=70MB,一个两小时的视频70MB*60*120=500G,可以看出,的确是太大了。视频的编码格式非常的多,在Android平台上,目前主流为H264(MPEG公司的),音频为AAC,相对于视频文件,音频文件较小,因此编码技术差点也没关系,最近几年基本没什么新的音频编码协议出现。有关视频编码格式的具体实现是一个非常大的领域,本文不再展开了,感兴趣的同学可以看一下相关文档,推荐雷神所写的:https://blog.csdn.net/leixiaohua1020/article/details/28114081,之后为加深理解,我也准备写一篇学习笔记。
四、封装格式
经过编码之后的视频及音频文件大小达到可接受的范围,下一步要进行格式封装。以当前最主流的封装格式为mp4为例说明下。先简单说一下什么是mp4,有几种:首先:mp4是一种文件格式,可以是视频,也可以是音频,以.mp4为后缀; 其次:mp4往往来替代性的描述MPEG-4,MPEG-4是一种多媒体规范,可以是音视频,也可以表示别的,只要满足该规范的定义即可;第三:mp4也被用于口头说视频编码算法,即好多人口中所说的mp4编码算法,这种说法其实相当的不准确,mp4只是一个容器,单说mp4不能说明任何的编解码规则,里面的视频(音频同理)可以采用各种不同的压缩编码算法,当前用的最多的是H264(视频)/AAC(音频)这个算法。
mp4文件的格式还是相当复杂的,想要了解内部原理的可以看一下官方文档,希望简单了解一下的可以看一下这篇文章:https://www.cnblogs.com/ranson7zop/p/7889272.html,其实不作音视频编解码的同学可以不用理解这么深入,只需要知道一些基本结构:mp4是由多个Box组成的,每个Box含有播放相关的各种信息,对于视频来讲,最重要的Box是(1)moov--存储着该视频的各种信息,包括但不限于:编码算法信息、宽高、码率、帧率、时长、各种分块时长对应关系等。(2)mdat--存储着视频帧数据和音频通道数据。经过格式封装之后,音视频合并成了一个文件,可以直接放入本地等待播放。也可以是上传至云端,供别的用户在线播放或下载播放。
五、播放
简单来讲,播放的过程就是视频生成过程的一个逆向。
1.云端视频先要解协议,去除网络协议层
2.然后是解封装,拿掉格式,解出mp4头,得到各帧的数据
3.对应于编码格式,执行解码程序,比如视频通道使用H264解码,音频通道使用AAC解码
4.解码之后得到了帧数据及音频数据,视频帧数据的播放在Android上是由OpenGL实现的,音频的不太了解
5.最终的数据被送入显卡驱动及声卡驱动中,由硬件输出给用户
在Android中,最简单的播放实现即调用系统所提供的MediaPlayer,上述五个过程均由系统封装实现了。
六、一些特殊处理
如果有功能需要单独定制,比如在我们的项目中,要在视频帧中加入水印,这就需要以下过程:
1.分离音视频通道,系统的接口为:MediaExtractor
2.视频解码,系统接口为MediaCodec,输出视频内容至GLSurfaceView
3.使用OpenGL绘制水印
4.获取到GLSurfaceView的数据然后进行编码,系统接口为MediaCodec
5.合并音视频通道,系统接口为MediaMuxer
上述的编解码过程为硬编码过程,在部分机型上有适配问题,还有一种编码方式为FFMPEG,使用软编码方式,缺点是要编码效率低,耗时长,但适配性好。
本文中从大面上总结一下与视频相关的多媒体技术,主要是疏理其脉络,理清其骨架,对内部的技术实现只是简单提及,对于上层app开发者来讲,有这些也基本够了,对于需要定制视频功能的开发者来讲,要针对具体模块重点突破。多媒体技术范围太大,要做到面面俱到,基本是不可能的,当前技术的行业分工精细,每个人基本是负责一块,要做到自身所做某块的融汇贯通,比每一块都会一点更为重要。