前言
提到短视频修正,咱们或许会第一时刻想到FFmpeg
、OpenGL ES
这些让人望而生畏的庞大结构,固然音视频开发的入门的确需求一定的根底,可是只是依托于苹果为咱们供给的AVFoundation
结构,咱们依然能够在短视频修正范畴做许多作业。本系列文章围绕iOS平台上短视频修正功用中AVFoundation扮演的人物展开讨论,本篇首要介绍学习AVFoundation结构需求了解的根底模块和相关的数据类型及注意事项。
一、 AVFouondation结构概述
AVFoundation 是在 iOS、macOS、watchOS 和 tvOS 上处理多媒体数据的功用齐全的结构。运用AVFoundation,咱们能够播映、创立和修正 QuickTime movie和 MPEG-4 文件,播映 HLS 流,并将强壮的媒体修正功用构建到咱们的应用程序中。
1.1 iOS多媒体结构系统
咱们首要来看AVFouondation结构在苹果的多媒体结构系统中的方位。在iOS的多媒系统统中,高层级的AVKit供给了 高度封装的播映器操控类AVPlayerViewController
、用于切换播映路由(投屏)的AVRoutePickerView
,以及完成画中画播映作用的AVPictureInPictureController
。低层级的结构首要以C接口为主,其间:
- Core Audio 最底层的音频处理接口,直接驱动设备的音频硬件,对音乐游戏或专业的音频修正软件供给了全面的支撑。Audio Unit供给了包括组成乐器声响、回声消除、混音、声响均衡等相关接口。
Audio Unit现已迁移到 Audio Toolbox Framework了。
-
Core Video 为其相对的Core Media供给图片缓存(
CVPixelBuffer
)和缓存池(CVPixelBufferPool
)支撑,供给了一个能够对数字视频逐帧拜访的接口,以及对Metal(CVMetalTexture
) 、OpenGL(CVOpenGLTexture
) 以及OpenGLES(CVOpenGLESTexture
)的支撑。 -
Core Media 界说和封装了AVFoundation等更上层的媒体结构需求的媒体处理流水线(包括时刻信息)以及其间运用的接口和数据类型(
CMSampleBuffer
、CMTime
)。运用 Core Media 层的接口和数据类型能够高效的处理媒体采样数据、办理采样数据队列(CMSimpleQueue
、CMBufferQueue
)。 - Core Animation 是iOS中动画相关的结构,AVFoundation结合Core Animation让开发者能够在视频修正和播映进程中增加动画和贴纸作用。
而AVFoundation位于高层级结构和低层级结构之间,封装了低层级结构才能完成的功用,供给了OC和Swift语言的接口,同时苹果在迭代进程中不断优化AVFoundation这种中间层结构的性能,很好地支撑了新的设备和视频格局。
1.2 AVFoundation各模块简介
AVFoundation官方文档介绍:AVFoundation结构结合了六个首要技术范畴,这些范畴覆盖了在Apple平台上录制、处理、组成、操控、导入和导出视听媒体的首要功用。而API官方文档将AVFoundation分成了Assets
媒体资源、Playback
播映、Capture
录制、Editing
修正、Audio
音频、Speech
(语音播报)六个功用模块。
-
Assets:供给加载、查看和导出媒体资源和元数据信息的功用,也能够运用
AVAssetReader
和AVAssetWriter
对媒体样本数据进行样本级读写,运用AVAssetImageGenerator
获取视频缩略图,运用AVCaption
进行字幕创作(mac os)等。 -
Playback:供给对
AVAsset
的播映和播映操控的功用,能够运用AVPlayer
播映一个项目,也能够运用AVQueuePlayer
播映多个项目,AVSynchronizedLayer
能够让咱们结合Core Animation
将动画层与播映视图层进行同步,完成播映中的诸如贴纸、文字等作用。 - Capture:用于拍照相片、录制音频和视频,经过装备内置摄像头和麦克风或外部录制设备,能够构建自界说相机功用,操控相片和视频拍照的输出格局,或许直接修正音视频数据流作为自界说输出。
-
Editing:用于将来自多个来源的音频和视频轨迹组合、修正和从头混合到一个
AVMutableComposition
中,能够运用AVAudioMix
和AVVideoComposition
别离操控音频混合和视频组成的细节。 -
Audio:播映、录制和处理音频;装备应用程序的系统音频行为。苹果又在iOS14.5整合了一个
AVFAudio
结构,内容与这部分完全相同,或许未来会把音频部分单独处理。 - Speech:将文本转化为语音音频进行朗读。
在短视频修正中,无论是修正所用的素材仍是修正中处理的半成品亦或是最终导出的成品,咱们都在跟AVAsset
或其子类打交道,其所在的Assets
模块作为AVFoundation媒体处理的根底是需求首要学习的内容。
二、 根底模块-Assets
2.1 AVAsset & AVAssetTrack
AVAsset
是一个笼统类和不可变类,界说了媒体资源混合出现的方式,将媒体资源的静态特点模块化成一个整体。它供给了对基本媒体格局的笼统,这意味着无论是处理Quick Time Movie仍是MP3音频,对开发者和对结构其余部分而言,面临的只要资源这个概念。
AVAsset一般经过其子类AVURLAsset
实例化,其间的参数”URL”能够来自远程或许本地甚至是流媒体,使咱们无须重视其来源,只须专注于处理AVAsset
本身。
运用下面代码示例中的办法创立回来的都是AVURLAsset
的实例。办法二中的options
能够用来来自界说AVURLAsset的初始化以满意特定需求。例如,经过HLS流创立AVURLAsset,运用{AVURLAssetAllowsCellularAccessKey: @NO}
作为options的参数,能够阻止在运用蜂窝网络时检索其媒体数据。而与视频修正密切相关的是AVURLAssetPreferPreciseDurationAndTimingKey
,用于指示资源是否供给准确的”duration”值和准确的随机拜访,视频修正需求准确的值,建议运用”YES”,不过这种精度或许需求进行额定的解析而导致更长的加载时刻。
许多容器格局为准确计时供给了足够的摘要信息,并不需求额定的解析来预备,例如QuickTime Movie和MPEG-4文件。
AVAsset *asset = [AVAsset assetWithURL:url];
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:url options:@{AVURLAssetPreferPreciseDurationAndTimingKey: @YES}];
一个AVAsset
实例是一个或多个AVAssetTrack
实例的容器,该实例是对媒体的共同类型”轨迹”进行的建模。一个简单的视频文件一般包括一个音频轨迹和一个视频轨迹,也或许包括一些补充内容,如隐藏式字幕、字幕,也或许包括描绘媒体内容的元数据(AVMetadataItem
)。
隐藏式字幕即“Closed Caption”,简称CC字幕。大多数CC字幕和剧本是一样的,里边除了对白之外,还有场景中发生的声响和配乐等的描绘,首要是为了听障人士所设置的,“Closed”一词也阐明了并不是默许开启的状况,与之相对的是“Open Caption”,也便是一般所说的字幕,而与对话语言相同的字幕称为”Caption“,不同的(即翻译)称为“Subtitle”。
创立一个AVAsset是一个轻量级操作,由于AVAsset的底层媒体数据采用了推迟加载的设计,直到获取时才会进行加载,并且特点的获取是同步进行的,假如没有进行提前进行异步加载直接去拜访它的特点会堵塞调用线程,不过这也要取决于要拜访的媒体数据的巨细和方位。为了防止堵塞线程,咱们最好在运用之前进行异步加载特点。AVAsset和AVAssetTrack都遵循了AVAsynchronousKeyValueLoading
协议,能够进行异步加载特点和获取加载状况。
@protocol AVAsynchronousKeyValueLoading
// 异步加载包括在keys数组中的特点,在handler中运用statusOfValueForKey:error:办法判别加载是否完成。
- (void)loadValuesAsynchronouslyForKeys:(NSArray<NSString *> *)keys completionHandler:(nullable void (^)(void))handler;
// 获取key特点加载的状况,status为AVKeyValueStatusLoaded为加载完成。
- (AVKeyValueStatus)statusOfValueForKey:(NSString *)key error:(NSError * _Nullable * _Nullable)outError;
WWDC2021What’s new in AVFoundation提到,针对swift API引入了async
/await
,让咱们得以运用与同步编程类似的操控流来进行异步编程。
let asset = AVAsset (url: assetURL)
let duration = trv await asset.load(.duration)
// 咱们也能够加载多个特点,运用元组接纳回来值:
let (duration, tracks) = try await asset.load(.duration, .tracks)
AVAsset的特点:
代码示例中tracks
特点回来的是一个AVAsset实例包括的所有AVAssetTrack
实例的数组,苹果也供给了依据特定标准(如轨迹ID、媒体类型和特征)检索轨迹子集的办法如下,这也是修正模块中取出某种类型的轨迹常用的办法。
// 依据TrackID检索轨迹
- (void)loadTrackWithTrackID:(CMPersistentTrackID)trackID completionHandler:(void (^)(AVAssetTrack * _Nullable_result, NSError * _Nullable))completionHandler;
// 依据媒体类型检索轨迹子集
- (voidloadTracksWithMediaType:(AVMediaType)mediaType completionHandler:(void (^)(NSArray<AVAssetTrack *> * _Nullable NSError * _Nullable))completionHandler;
// 依据媒体特征检索轨迹子集
- (void)loadTracksWithMediaCharacteristic:(AVMediaCharacteristic)mediaCharacteristic completionHandler:(void (^)(NSArray<AVAssetTrack *> * _Nullable, NSError * _Nullable))completionHandler;
其间AVMediaType常用的有:音频AVMediaTypeAudio
、视频AVMediaTypeVideo
、字幕AVMediaTypeSubtitle
、元数据AVMediaTypeMetadata
等。
AVMediaCharacteristic用于界说媒体数据特征,例如是否包括HDR视频轨迹AVMediaCharacteristicContainsHDRVideo
,是否包括可听内容AVMediaCharacteristicAudible
等。
2.2 元数据
媒体容器格局存储关于其媒体的描绘性元数据,每种容器格局都有自己共同的元数据格局,AVFoundation经过运用其AVMetadataItem
类简化了对元数据的处理,在最基本的方式中,AVMetadataItem
的实例是一个键值对,表明单个元数据值,比方电影的标题或专辑的插图。
要高效地运用AVMetadataItem
,咱们需求了解AVFoundation是怎么安排元数据的。为了简化元数据项的查找和过滤,AVFoundation结构将相关元数据分组到键空间中:
- 特定格局的键空间。AVFoundation结构界说了几个特定格局的键空间,它们大致与特定容器或文件格局相关,例如 QuickTime(QuickTime 元数据和用户数据)或 MP3 (ID3)。可是,单个资源或许包括跨多个键空间的元数据值。要检索资源的特定格局元数据的完好调集,能够运用
metadata
特点。 - Common键空间。有几个常见的元数据值,例如电影的创立日期或描绘,能够存在于多个键空间中。为了帮助规范化对这个公共元数据的拜访,该结构供给了一个common键空间,它答应拜访几个键空间共有的一组有限元数据值。要检索资源的公共元数据调集,能够直接运用
commonMetadata
特点。
除此之外,咱们还能够经过调用AVAsset
的availableMetadataFormats
特点来确认资源包括哪些元数据格局。此特点回来包括每个元数据格局的字符串标识符数组。然后运用它的metadataForFormat:
办法,经过传递恰当的格局标识符来检索特定于格局的元数据值。
一个iPhone13 Pro拍照的HDR视频文件的元数据:
creationDate : 2022-03-01T18:16:17+0800
location : +39.9950+116.4749+044.903/
make: Apple
model: iPhone 13 Pro
software: 15.3.1
尽管本系列文章旨在不过多重视音视频编解码格局,可是拿到一个视频文件(.mov),假如依然想获取视频样本的编码类型(h264
/hevc
)、转化函数(ITU_R_709_2
/ITU_R_2100_HLG
)等,获取音频样本的采样率、通道数、位深等格局信息,咱们应该从哪里入手呢?前面咱们介绍了在一个AVAsset资源中以轨迹(track
)的方式把音频、视频等数据别离进行了单独的建模,假如要获取视频样本格局的信息,只要依据媒体类型检索相应的视频轨迹,获取assetTrack的formatDescriptions
特点,即可拿到视频样本的格局信息CMVideoFormatDescription
的调集,相同还有CMAudioFormatDescription
、CMClosedCaptionFormatDescription
等用于描绘各自轨迹样本的数据格局。
// 获取数据样本格局信息
AVAssetTrack *videoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] firstObject];
NSArray *videoFormats = VideoTrack.formatDescriptions;
上述视频文件中的视频轨迹格局描绘信息如下:
"<CMVideoFormatDescription 0x2834305a0 [0x1dbce41b8]> {
mediaType:'vide'
mediaSubType:'hvc1'
mediaSpecific: {
codecType: 'hvc1'
dimensions: 1920 x 1080
}
extensions: {{
AmbientViewingEnvironment = {length = 8, bytes = 0x002fe9a03d134042};
BitsPerComponent = 10;
CVFieldCount = 1;
CVImageBufferChromaLocationBottomField = Left;
CVImageBufferChromaLocationTopField = Left;
CVImageBufferColorPrimaries = \"ITU_R_2020\";
CVImageBufferTransferFunction = \"ITU_R_2100_HLG\";
CVImageBufferYCbCrMatrix = \"ITU_R_2020\";
Depth = 24;
FormatName = HEVC;
FullRangeVideo = 0;
RevisionLevel = 0;
SampleDescriptionExtensionAtoms = {
dvvC = {
length = 24,
bytes = 0x010010254000000000000000000000000000000000000000
};
hvcC = {
length = 125,
bytes = 0x01022000 0000b000 00000000 78f000fc ... 2fe9a03d 13404280 };
};
SpatialQuality = 512;
TemporalQuality = 512;
VerbatimSampleDescription = {
length = 289,
bytes = 0x00000121 68766331 00000000 00000001 ... 3d134042 00000000 };
Version = 0;
}}
}"
2.3 视频预览
在短视频修正中将播映导出前的视频资源称为预览,实际上播映归于AVFoundation中Playback
模块的内容,可是本系列文章要点不在播映器上,咱们简单介绍一下预览AVAsset运用的类AVPlayer
。
AVPlayer的初始化需求一个AVPlayerItem
目标,它用来办理资源目标,供给播映数据源的类,要播映一个视频,只运用AVPlayer的话,只要声响没有画面,要显现画面咱们还需求AVPlayerLayer
。
// 1.实例化AVAsset
AVAsset *asset = [AVAsset assetWithURL:url];
// 2.经过asset创立AVPlayerItem
AVPlayerItem* item = [[AVPlayerItem alloc] initWithAsset:asset];
// 3.创立AVPlayer
AVPlayer* player = [AVPlayer playerWithPlayerItem:item];
// 4.创立AVPlayerLayer用来显现视频
AVPlayerLayer* playerLayer = [AVPlayerLayer playerLayerWithPlayer:player];
// 5.将AVPlayerLayer增加到视图层级中
[self.view.layer addSublayer:playerLayer];
// 6.播映
[player play];
2.4 获取视频缩略图
一般在视频导出前会有一个选择视频封面的功用,该功用需求供给视频缩略图的列表,要获取视频的缩略图需求运用AVAssetImageGenerator
,运用AVAsset
实例创立 AVAssetImageGenerator
目标的办法如下:
+ (instancetype)assetImageGeneratorWithAsset:(AVAsset *)asset;
- (instancetype)initWithAsset:(AVAsset *)asset;
假如需求准确时刻截图,能够运用按照如下办法将前后时刻容忍度设为kCMTimeZero
,设置maximumSize
特点能够指定截取画面的巨细。
// 准确时刻获取缩略图
imageGenerator.requestedTimeToleranceBefore = kCMTimeZero;
imageGenerator.requestedTimeToleranceAfter = kCMTimeZero;
// 指定缩略图画面的巨细
imageGenerator.maximumSize = CGSizeMake(100, 100);
然后调用如下办法来获取某个时刻的缩略图,或许多个时刻的缩略图:
// 获取指定时刻requestedTime的视频缩略图
- (nullable CGImageRef)copyCGImageAtTime:(CMTime)requestedTime actualTime:(nullable CMTime *)actualTime error:(NSError * _Nullable * _Nullable)outError;
// 获取多个时刻的缩略图,每生成一张图片,都会调用一次handler
- (void)generateCGImagesAsynchronouslyForTimes:(NSArray<NSValue *> *)requestedTimes completionHandler:(AVAssetImageGeneratorCompletionHandler)handler;
// 上述办法的handler的类型界说,actualTime为缩略图所处的真实时刻
typedef void (^AVAssetImageGeneratorCompletionHandler)(CMTime requestedTime, CGImageRef _Nullable image, CMTime actualTime, AVAssetImageGeneratorResult result, NSError * _Nullable error);
三、 常用数据类型
3.1 CMTime & CMTimeRange
在获取视频缩略图中咱们需求传入一个用于表明某个时刻的类型CMTime
,一般咱们以为用于表明时刻的一般是NSTimeInterval
(double类型),在AVFoundation中的AVAudioPlayer
和AVAudioRecorder
处理时刻能够运用,可是浮点型的不准确性(简单的舍入就会导致丢帧),无法用于更多的高级时基媒体的开发中,所以Core Media
供给了这样一个结构体来表明时刻:
typedef struct
{
CMTimeValue value;
CMTimeScale timescale;
CMTimeFlags flags;
CMTimeEpoch epoch;
} CMTime;
其间CMTimeFlags是一个位掩码用于表明时刻的指定状况,例如判别数据是否有效,CMTimeEpoch表明纪元,一般是0。咱们要点重视表明时刻的CMTimeValue和CMTimeScale,一个CMTime表明的时刻 = value / timescale,timescale表明将时刻划分了多少份,value表明该时刻含有多少份,为满意大部分常用的视频频率24FPS、25FPS、30FPS,一般咱们会将timescale设为他们的公倍数600。
咱们能够运用如下办法创立一个CMTime:
CMTime time1 = CMTimeMake(3, 1); // 3 / 1 = 3s
CMTime time2 = CMTimeMakeWithSeconds(5, 1); 5s timescale = 1
NSDictionary *timeData = @{(id)kCMTimeValueKey : @2,
(id)kCMTimeScaleKey : @1,
(id)kCMTimeFlagsKey : @1,
(id)kCMTimeEpochKey : @0};
CMTime time3 = CMTimeMakeFromDictionary((__bridge CFDictionaryRef)timeData);
// 特殊值
// 表明0时刻
CMTime time4 = kCMTimeZero;
// 表明时刻不合法
CMTime time5 = kCMTimeInvalid;
CMTime的运算:
// 加
CMTimeAdd(<#CMTime lhs#>, <#CMTime rhs#>)
// 减
CMTimeSubtract(<#CMTime lhs#>, <#CMTime rhs#>)
// 比较
CMTimeCompare(<#CMTime time1#>, <#CMTime time2#>)
// 校验
CMTIME_IS_VALID(<#time#>)
CMTIME_IS_INVALID(<#time#>)
// print
CMTimeShow(<#CMTime time#>)
CMTimeRange
用于表明一个时刻规模,由两个CMTime
值组成,第一个界说时刻规模的开始时刻,第二个界说时刻规模的持续时刻。
typedef struct
{
CMTime start;
CMTime duration;
} CMTimeRange;
咱们能够运用如下办法创立一个CMTimeRange:
CMTime beginTime = CMTimeMake(5, 1);
CMTime endTime = CMTimeMake(12, 1);
CMTimeRange timeRange1 = CMTimeRangeMake(beginTime, endTime);
CMTimeRange timeRange2 = CMTimeRangeFromTimeToTime(beginTime, endTime);
// 特殊值
// 表明0长度的时刻规模
CMTimeRange timeRange3 = kCMTimeRangeZero;
// 表明时刻规模不合法
CMTimeRange timeRange4 = kCMTimeRangeInvalid;
CMTimeRange的运算:
// 取两个CMTimeRange的交集
CMTimeRangeGetIntersection(<#CMTimeRange range#>, <#CMTimeRange otherRange#>)
// 取两个CMTimeRange的并集
CMTimeRangeGetUnion(<#CMTimeRange range#>, <#CMTimeRange otherRange#>)
// 是否包括某个时刻CMTime
CMTimeRangeContainsTime(<#CMTimeRange range#>, <#CMTime time#>)
// 是否包括某个时刻规模
CMTimeRangeContainsTimeRange(<#CMTimeRange range#>, <#CMTimeRange otherRange#>)
// 校验
CMTIMERANGE_IS_VALID(<#range#>)
CMTIMERANGE_IS_INVALID(<#range#>)
// print
CMTimeRangeShow(<#CMTimeRange range#>)
3.2 CMSampleBuffer
运用AVFoundation处理样本级的数据时要经常跟CMSampleBuffer
打交道,例如AVFoundation的Capture模块相机采集的数据输出类型、AVAssetReader
和AVAssetWriter
读取和写入进程中操作的数据类型等。
CMSampleBuffer
相同来自Core Media
结构,它是系统用来经过媒体管道移动媒体样本数据的中心根底目标,CMSampleBuffer
的人物是将根底的样本数据进行封装并供给格局描绘和时刻信息。
官方的文档介绍,它包括0个或多个特定媒体类型(音频、视频、混合等)的紧缩(或未紧缩)样本,CMSampleBuffer
能够包括:
-
样本数据。包括以下两者中的一个:
- 一个或多个媒体样本的
CMBlockBuffer
,CMBlockBuffer
为编码的数据,并未进行解码。 - 一个或多个媒体样本的
CVPixelBuffer
,CVPixelBuffer
为编码前或解码后的数据。
- 一个或多个媒体样本的
-
时刻信息。CMSampleBuffer还包括表明当时样本的显现时刻(
Presentation Time Stamp
)的pts,表明样本的编码时刻(Decode Time Stamp
)的dts,dts首要用于视频的解码,假如解码时刻与显现时刻顺序共同,其值能够设置为kCMTimeInvalid
。能够别离运用CMSampleBufferGetPresentationTimeStamp
和CMSampleBufferGetDecodeTimeStamp
获取pts和dts。 -
格局信息。格局信息封装在
CMFormatDescription
目标中。能够别离运用CMVideoFormatDescriptionGetCodecType
和CMVideoFormatDescriptionGetDimensions
获取编码类型和视频尺寸。除此之外还能够运用CMGetAttachment
检索字典获取元数据:
CFDictionaryRef metadataDictionary = CMGetAttachment(sampleBuffer, CFSTR("MetadataDictionary", NULL);
3.3 CVPixelBuffer
CVPixelBufferRef
是像素缓冲区类型,像素缓冲区类型基于图画缓冲区类型,归于Core Video结构的数据类型。
typedef CVImageBufferRef CVPixelBufferRef;
CVPixelBufferRef
里包括许多图片相关特点,比较重要的有width
、height
、PixelFormatType
等。除了常见的RGB32以外,还能够支撑比方 kCVPixelFormatType_420YpCbCr8BiPlanarFullRange
这种YUV多平面的数据格局,经过CVPixelBufferGetBaseAddressOfPlane
能够得到每个平面的数据指针。假如运用CPU拜访像素数据,在获取Address之前需求调用CVPixelBufferLockBaseAddress
。
CMSampleBuffer
的一个实例在对应的CVPixelBuffer
中包括了视频帧的数据。咱们能够运用CMSampleBufferGetImageBuffer
获取:
CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(<#A CMSampleBuffer#>);
四、 注意事项
4.1 隐私权限
AVFoundation中的Capture模块触及运用设备的相机和麦克风,对图片与视频文件的读取与保存触及对用户相册的拜访,这些都被苹果列为用户的隐私权限,咱们需求在Xcode的info.plist增加响应的申请拜访权限阐明。下面列举了部分权限与其对应的key值。
隐私数据 | key |
---|---|
相册(读权限) | Privacy – Photo Library Usage Description |
相册(写权限) | Privacy – Photo Library Additions Usage Description |
麦克风 | Privacy – Microphone Usage Description |
相机 | Privacy – Camera Usage Description |
4.2 装备AVAudioSession
iOS设备的音频环境相对mac os较为杂乱,苹果供给了AVAudioSession
音频会话,在应用程序和操作系统之间扮演中间人的人物,咱们只需指明应用程序的音频行为即可将对音频行为的办理托付给AVAudioSession
。默许的音频会话预装备了以下行为:
- 支撑音频播映,但不答应录制音频。
- 静音形式会使应用程序播映的任何音频静音。
- 锁定设备会使app的音频静音。
- 当应用程序播映音频时,它会使任何其他背景音频静音。 iOS供给六个Category可供选择:
AVAudioSessionCategoryAudioProcessing
在iOS10.0现已抛弃。
Category | 播映/录制 | 是否中止其他音频 | 静音或锁屏形式是否静音 |
---|---|---|---|
SoloAmbient | 仅播映 | 是 | 是 |
Ambient | 仅播映 | 否 | 是 |
MultiRoute | 播映和录制 | 是 | 否 |
PlayAndRecord | 播映和录制 | 默许YES,能够重写为NO | 否 |
Playback | 仅播映 | 默许YES,能够重写为NO | 否 |
Record | 仅录制 | 是 | 否(锁屏下仍可录制,需求装备后台形式UIBackgroundModes) |
除此之外,音频会话还供给了用于监听如电话呼入、闹钟响起引起的音频中止的通知AVAudioSessionInterruptionNotification
,以及例如耳机插入造成的路由线路变更的通知AVAudioSessionRouteChangeReason
。
4.3 多线程
AVFoundation的构建考虑到了当时的硬件环境和应用程序,其设计进程高度依靠多线程机制。咱们在运用的进程中,要清晰所调用的API默许作业在哪个线程,或许需求作业在哪个线程,保证对UI的处理及时回到主线程来进行,防止耗时的操作堵塞主线程。
总结
本篇作为AVFoundation系列文章的开篇,首要介绍了AVFoundation的概述和各模块的基本功用,之后经过AVAssets模块的学习咱们建立了一个从轨迹(track)的视点看待音视频文件的视界,了解了常用的数据类型以及运用AVFoundation的注意事项。下一篇咱们将从短视频修正第一步素材的增加与处理方面介绍AVFoundation结构供给的支撑。
参考链接
AVFoundation AVAudioSession音频会话 CMSampleBuffer