01 前言
大家好,从今天开始我们正式进入 iOS 专题。
本文是 iOS/Android 音视频开发专题 第九篇,该专题中项目代码将在 Github 进行托管,你可在微信公众号(GeekDev)后台回复 资料 获取项目地址。
本期内容:
- AVFoundation 概述
- AVFoundation 中的常用类
- AVFoundation 采集设备
- 结束语
02 AVFoundation 概述
AVFoundation 是 iOS 中多媒体框架之一,基于 Object-C/Swift 接口,可以用来播放,编辑,重新编码音视频文件。我们可以通过 AVCaptureSession 输入设备实时捕捉处理图像信息。下面是 iOS 系统中的 AVFoundation 媒体架构:
通常,我们使用高级接口就可以满足我们的大部分需求。
- 如果你简单的播放一个视频,可以使用 AVKit 框架
- 在 iOS 系统中如果你不关心格式的情况下录制视频,可以使用 UIKit 框架
另外,你可能还听说过 VideoToolbox , AudioToolbox ,CoreMedia , CoreVideo, 这些框架是 iOS 为开发提供的 C 语言接口,AVFoundation 底层技术就是使用的这些 C 语言框架。
像 VideoToolbox 我们做直播类项目时,通常会使用 VideoToolbox 对视频流进行 h264 编码。使用 VideoToolbox 我们可以更加精细的控制编码数。AVFoundation 一般用于对媒体文件(Asset)进行编辑,在短视频场景下用的较多。
03 AVFoundation 常用类
AVAsset 是一个抽象类,定义了一个资产文件的抽象接口
AVURLAsset 通过 URL 创建,URL 可以是本地资源,也可以是网络资源
-
AVComposition 可以将多个基于本地文件的媒体数据以自定义的时间安排组合在一起,
用以呈现或处理多个源的媒体数据
AVAssetReader 用以读取 AVAsset 的媒体数据,可以直接将未解码的媒体数据解码为可用数据
-
AVAssetReaderOutput 有多个子类,例如 AVAssetReaderTrackOutput 或 AVAssetReaderVideoCompositionOtput。
你可以使用 addOutput: 将一个或多个 AVAssetReaderOutput 添加到 AVAssetReader
对象中来读取资产的媒体数据
AVAssetTrack 媒体资产轨道对象
-
AVAssetImageGenerator 提供获取视频资产缩图的功能。如果你需要获取多张缩略图建议
使用 generateCGImageesAsynchronouslyForTimes:completionHandler:
AVAssetExportSession 可以将 AVAsset 媒体文件内容由指定的预设格式进行输出
-
AVAssetWriter 可以将媒体数据 CMSampleBuffer 写入指定的文件中。相比 AVAssetExportSession
AVAssetReader + AVAssetWriter 可以有更细粒度的配置,比如我们可以将 CMSampleBuffer
经过特效处理后写入文件
-
CMSampleBuffer 是 Core Foundation 对象,是音频, 视频的压缩或未压缩数据样本。
AVAssetReaderOutput 输出的媒体数据就是该对象
-
CMTime 一个表示时间的结构体。以分数的形式表示时间,value 表示分子,timescale
表示分母。一般我们使用 timescale 表示每秒钟帧率,value 表示当前第几帧。
例如,timescale 为 30fps ,value 为 60 时,当前时间为 60/30 = 2s .
CMTime 定义在 Core Media 框架中,我们可以通过 CMTimeMake(int64_t value,int32_t timescale)
快速创建一个 CMTime 。你可以通过 CMTimeMakeWithSeconds(Float64 seconds,int32_t preferredTimescale)
,将 seconds 转为 CMTime. preferredTimescale 建议我们使用的有 NSEC_PER_SEC(一秒钟纳秒数),
NSEC_PER_MSEC(一毫秒纳秒数), USEC_PER_SEC(一秒钟微妙数), NESC_PER_USEC(一微妙纳秒数)。
1秒 = 1000000000 纳秒 (10亿)
1毫秒 = 1000000 纳秒 (100万)
1秒 = 1000000 微妙 (100万)
1微妙 = 1000 纳秒(1000)
-
CMTimeRange 标识一个时间范围的结构体,同样定义在 Core Media 框架中。
start 表示开始时间,duration 表示持续时间,类型都是 CMTime。
CMTimeRange 的创建方式与 CMTime 类似都提供了一个 C 语言函数。
通过 CMTimeRangeMake(CMTime start, CMTime duration) 可以快速创建一个时间范围。
另外,Core Media 也为我们提供了很多实用的工具方法
-
CMTimeRangeEqual (CMTimeRange range1,CMTimeRnage range2)
比较 range1 与 range2 时间范围是否相同
-
CMTimeRangeContainsTime(CMTimeRange range,CMTime time)
判断 time 是否在 range 范围内
-
CMTimeRangeGetEnd(CMTimeRange range)
获取 range 的结束时间 (start + duration)
-
CMTimeRangeGetUnion(CMTimeRange range,CMTimeRange otherRange)
计算 range 与 otherRange 的并集
-
CMTimeRangeGetIintersection(CMTimeRange range,CMTimeRange otherRange)
计算 range 与 otherRange 的交集
-
04 AVFoundation 采集设备
在 03 AVFoundation 常用类 章节中,我们并没有提到 iOS 中的相机采集,因为相机采集足够复杂,
我们将相机采集独立成章,足够我们使用一篇文章单独讲解。这里我们姑且抛砖引玉,
在以后的文章中我们将开放一款 相机 APP。
AVFoundation Capture 子系统为 iOS 的视频,照片和音频捕获服务提供了通用的高级体系架构。
如果你要执行以下操作,你应该使用该系统API:
- 构建自定义的相机用户界面,将拍照或视频录制集成到应用中
- 为用户提供对照片和视频捕获更直接的控制,例如焦点,曝光等增强选项。
- 与系统相机 UI 产生不同的结果,例如 RAW 格式的照片,深度图或需要自定义视频元数据
- 从采集设备 (Capture device) 实时获取视频像素或音频数据。
Capture 系统体系结构主要部分是会话,输入和输出,Capture 会话将一个或多个输入连接到一个或多个
输出。输入是媒体的来源,包括捕获设备相机和麦克风。输出是从输入中获取媒体数据,例如写入磁盘文件并产生一个电影文件。
-
AVCaptureSession 采集会话,用于管理并协调输入设备(AVCaptureDeviceInput)和输出设备
(AVCatureoutput)。要开启实时捕获,需要实例化 AVCaptureSession 对象并添加合适的输入和输出。
下面是如何配置捕获设备用以录制音频。
/ Create the capture session.AVCaptureSession *captureSession = [[AVCaptureSession alloc] init];
// Lookup the default audio device.
AVCaptureDevice *audioDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
// Wrap the audio device in a capture device input.
NSError *error = nil;
AVCaptureDeviceInput *audioInput = [AVCaptureDeviceInput deviceInputWithDevice:audioDevice error:&error];
if (audioInput)
{
// If the input can be added, add it to the session.
if ([captureSession canAddInput:audioInput]) {
[captureSession addInput:audioInput];
}
} else {
// Configuration failed. Handle error.
}
-
AVCaptureInput 为 AVCaptureSession 提供输入数据,是所有输入设备的超类。
需要将 AVCaptureInput 与 AVCaptureSession 相关联,在 AVCaptureSession 上调用addInput:
-
AVCaptureDeviceInput 捕获输入对象,用于从 AVCaptureDevice 捕获设备中获取数据
并提供给 AVCaptureSession 。创建 AVCaptureInput 时需要指定 AVCaptureDevice,
AVCaptureDevice 决定了捕获的数据类型
AVCaptureScreenInput 提供录屏捕获输入
AVCaptureMetadataInput 元数据输入 (没用过)
-
AVCaptureOutput 捕获输出
- AVCaptureAudioDataOutput 记录音频输出,提供对音频样本缓冲区的访问
- AVCaptureAudioPreviewOutput 音频输出,与音频输出设备相关联,可用于播放
由 AVCaptureSession 捕获的音频数据
AVCaptureDepthDataOutput 输出相机画面的场景深度信息,只有双摄像头或以上才支持深度信息
-
AVCapturePhotoOutput 相机照片输出,可以从相机中捕获一张照片。在 iOS10.0 之前使用
AVCaptureStillImageOutput
AVCaptureVideoDataOutput 记录视频并提供视频帧输出
AVCaptureFileOutput 捕获文件输出超类
AVCaptureMovieFileOutput 将音频和视频数据输出到文件中
AVCaptureAudioFileOutput 记录音频数据输出到文件中
-
AVCaptureMetadataOutput 元数据捕获输出
该 Output 比较牛逼,可以用来扫描条形码,人脸,二维码,UPC-E 商品条形码等信息。
下期预告:
使用 AVFoundation 开发一款相机 APP