iOS视频开发经验
手机比PC的优势除了便携外,我认为最重要的就是可以快速方便的创作多媒体作品。照片分享,语音输入,视频录制,地理位置。一个成功的手机APP从产品形态上都有这其中的一项或多项,比如instagram,微信。如果把Web2.0的交互体验照搬到手机上就是死路一条。 当智能手机遇上视频就像潘金莲遇上西门庆,各取所需一拍即合,想不发生点事情都难。他们的结晶就是微视频。微视频可以说把手机的视频录制和碎片时间两个特点发挥到了极致,视频相关的APP现在无温不火的原因我认为跟坑爹的运营商有关。虽然现在移动网络流量小速度慢,但是不妨碍我们先把技术积累做起来。
这篇文章主要介绍本人在iOS视频开发中的一点经验。
视频实质:
纯粹的视频(不包括音频)实质上就是一组帧图片,经过视频编码成为视频(video)文件再把音频(audio)文件有些还有字幕文件组装在一起成为我们看到的视频(movie)文件。1秒内出现的图片数就是帧率,图片间隔越小画面就越流畅,所以帧率越高效果就越好,需要的存储空间也就越多。
视频编码:
因为不进行编码的视频数据量非常大,会造成存储和传输上的困难,所以视频文件都需要在录制完成后进行编码。视频编码主要从两个维度压缩数据。
1、单张图像某一区域相邻像素相似,比如一片红色只记录红色色值和区域,不用记录这个区域的每一个像素点。
2、相邻图像之间内容相似,因为相邻两帧要制造连续的效果,所以两帧之间的内容一般非常接近。目前主流的视频编码技术都是用图像编码方法对第一帧进行编码,然后用某种方式描述接下来的帧相对于附近的帧有什么区别。
视频格式:
MP4、MOV、AVI、RMVB这些播放格式其实都是封装格式,除了RMVB比较特殊外,其他格式内封装的视频编码格式都是H264,H264以高压缩率闻名于世,压缩效率比MEPG-2提升一倍多,但是世上没有两全其美的事,H264的解码难度提高了3倍多。
视频码率:
视频文件的大小除以是视频的时长定义为码率。
码率和分辨率跟视频质量的关系:
码率可以理解为取样率,单位时间内取样率越大,精度就越高,同时体积也越大。
当视频没有经过编码时,如果分辨率越高,那么视频图像的细节越清晰。
但如果视频经过编码,被限制在一定码率内,编码器就必须舍弃掉一部分细节。
所以分辨率和码率都同清晰度有关。
软解码和硬解码:
对H264的视频解码给CPU造成了很大负担,所以手机工程师把这部分工作交给了更善于进行处理简单工作但是数据量较大的GPU。
GPU解码就是所谓的硬解码
CPU解码就是软解码。
iOS提供的播放器类使用的是硬解码,所以视频播放对CPU不会有很大的压力,但是支持的播放格式比较单一,一般就是MP4、MOV、M4V这几个。
HTTP Live Streaming
HLS简介
HTTP Live Streaming(缩写是 HLS)是一个由苹果公司提出的基于HTTP的流媒体网络传输协议。它的工作原理是把整个流分成一个个小的基于HTTP的文件来下载,每次只下载一些。当媒体流正在播放时,客户端可以选择从许多不同的备用源中以不同的速率下载同样的资源,允许流媒体会话适应不同的数据速率。支持的视频流编码为H.264。我们在视频网站上看到的M3U8后缀的播放链接就是使用HLS协议的视频。
HLS优点
1、看完一段缓存一段,防止只看一段视频但是把整个视频文件都缓存下来的用户,减少服务器压力和节省流量。
2、根据用户网速切换不同的码率,兼顾流程性和清晰度。
HLS支持情况
iOS 3.0及之后的版本
Android 3.0及之后的版本
HTML5。
终端播放格式的选取
Android由于3.0之后才支持HLS,所以Android2.3只能用MP4。
Android3.0及之后支持HLS。可以用m3u8、mp4格式
iOS支持HLS,但不支持flash。可以用m3u8、mp4格式
支持HTML5的浏览器 可以用m3u8。
不支持HTML5的浏览器只能用flash播放swf。
由于以上原因,目前无法实现一个播放地址在所有的平台都通用。
iOS视频播放:
iOS提供MPMoviePlayerController类进行播放,支持流媒体和文件播放。视频内容会渲染到他的View上,可以放在你想放的任何地方,用起来比较方便。这个类设计上不合理的是视频播放状态和视频加载状态都是通过Notification通知的,而不是通过block或者delegate。
iOS视频录制:
同拍照一样视频录制功能有两种实现方式
1、UIImagePickerViewController
2、AVFoundation。
这里只讨论AVFoundation框架,这个框架是苹果提供的底层多媒体框架,用于音视频采集、音视频解码、视频编辑等,多媒体基本上都依赖AVFoundation框架。
视频录制和拍照需要做的工作差不多,主要有以下5步:
1、创建会话AVCaptureSession,用于控制input到output的流向。
2、获取设备AVCaptureDevice,摄像头用于视频采集,话筒用于音频采集。
3、创建输入设备AVCaptureDeviceInput,将设备绑定到input口中,并添加到session上
4、创建输出AVCaptureOutput,可以输出到文件和屏幕上。 AVCaptureMovieFileOutput 输出一个电影文件 AVCaptureVideoDataOutput 输出处理视频帧,用于显示正在录制的视频 AVCaptureAudioDataOutput 输出音频数据
5、音视频合成到一个文件中
iOS对视频实时处理:
如果需要对视频进行实时处理(当然需要否则看不到正在录制的内容),则需要直接对相机缓冲区(camera buffer)中的视频流进行处理。
1、定义一个视频数据输出(AVCaptureVideoDataOutput), 并将其添加到session上。
2、设置接受的controller作为视频数据输出缓冲区(sample buffer)的代理。
3、实现代理方法
-(void)captureOutput:(AVCaptureOutput )captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection )connection
当数据缓冲区(data buffer)一有数据时,AVFoundation就调用该方法。在该代理方法中,我们可以获取视频帧、处理视频帧、显示视频帧。实时滤镜就是在这里进行处理的。在这个方法中将缓冲区中的视频数据(就是帧图片)输出到要显示的layer上。