iOS音视频开发

IOS音视频(一)AVFoundation核心类

2020-01-27  本文已影响0人  孔雨露

1. AVFoundation框架架构简介

iOS系统上的AVFoundation框架架构 Mac OS X系统上的AVFoundation框架架构

Core Audio是OS X和IOS系统上处理所有音频 事件的框架。Core Audio是有多高框架整合在一起的总称,为音频和MIDI内容的录制,播放和处理提供相应的接口。Core Audio也提供高级的接口,比如通过Audio Queue Services框架所提供的那些接口,主要处理基本的音频播放和录音相关功能。同时还会提供相对低层级的接口,尤其是Audio Units接口,它们提供了针对音频信号进行完全控制的功能,并通过Audio Units让你能够构建一些复杂的音频处理模式,就像通过苹果公司的Logic Pro X和Avid's Pro Tolls工具所实现的功能一样。

Core Video是OS X 和IOS系统上针对数字视频所提供的管道模式。Core Video为其相对的Core Media提供图片缓存和缓存支持,提供了一个能够对数字视频逐帧访问的接口。该框架通过像素格式之间的转换并管理同步事项时的复杂的工作得到了有效简化。

Core Media 是AV Foundation所用到的低层级媒体管道的一部分。它提供针对音频样本和视频帧处理所需的低层级数据类型和接口。Core Media还提供了AV Foundation用的的基于CMTime数据类型的时间模型。CMTime及其相关数据类型一般在AV Foundation处理基于时间的操作时使用。

Core Animation时OS X和 iOS 提供的合成及动画相关框架。主要功能就是提供苹果平台所具有的美观,流畅的动画效果。提供了一个简单,声明行的编程模式,并已经封装了支持OpenGL 和OpenGL ES 功能的基于Object-C的各种类。使用Core Animation时,对于食品内容的播放和视频捕获这两个动作,AVFoundation 提供了硬件加速机制来对整个流程进行优化。AVFoundation 还可以利用Core Animation让开发者能够在视频编辑和播放过程中添加动画标题和图片效果。

  1. 如果只是简单播放视频文件,使用AVKit框架即可。
  2. 如果只是想简单录制视频,使用UIKit框架里的UIImagePickerController既可以实现。

1.1 AVFoundation框架

AVFoundation 提供的核心功能如下所示

AVFoundation框架1

1.2 AVFoundation 之 Assets

Assets AVAssetTrack结构
CMTime time1 = CMTimeMake(200, 2); // 200 half-seconds
CMTime time2 = CMTimeMake(400, 4); // 400 quarter-seconds
 
// time1 and time2 both represent 100 seconds, but using different timescales.
if (CMTimeCompare(time1, time2) == 0) {
    NSLog(@"time1 and time2 are the same");
}
 
Float64 float64Seconds = 200.0 / 3;
CMTime time3 = CMTimeMakeWithSeconds(float64Seconds , 3); // 66.66... third-seconds
time3 = CMTimeMultiply(time3, 3);
// time3 now represents 200 seconds; next subtract time1 (100 seconds).
time3 = CMTimeSubtract(time3, time1);
CMTimeShow(time3);
 
if (CMTIME_COMPARE_INLINE(time2, ==, time3)) {
    NSLog(@"time2 and time3 are the same");
}


NSURL *url = <#视听资源的 URL ,可以是本地文件地址,也可以是网页媒体链接#>;
AVURLAsset *anAsset = [[AVURLAsset alloc] initWithURL:url options:nil];

AVURLAssetPreferPreciseDurationAndTimingKey 是否需要资源的准确时长,及访问资源各个准确的时间点
AVURLAssetReferenceRestrictionsKey 链接其他资源的约束
AVURLAssetHTTPCookiesKey 添加资源能够访问的 HTTP cookies
AVURLAssetAllowsCellularAccessKey 是否能够使用蜂窝网络

//获取指定属性的状态
- (AVKeyValueStatus)statusOfValueForKey:(NSString *)key error:(NSError * _Nullable * _Nullable)outError;

//异步加载指定的属性集合
- (void)loadValuesAsynchronouslyForKeys:(NSArray<NSString *> *)keys completionHandler:(nullable void (^)(void))handler;
NSURL *url = <#资源路径#>;
AVURLAsset *anAsset = [[AVURLAsset alloc] initWithURL:url options:nil];
NSArray *keys = @[@"duration",@"tracks"];

[asset loadValuesAsynchronouslyForKeys:keys completionHandler:^() {

    NSError *error = nil;
    AVKeyValueStatus tracksStatus = [asset statusOfValueForKey:@"tracks" error:&error];
    //根据相应的属性状态进行对应的处理
    switch (tracksStatus) {
        case AVKeyValueStatusUnknown:
                //TODO
            break;
        case AVKeyValueStatusLoading:
                //TODO
            break;
        case AVKeyValueStatusLoaded:
                //TODO
            break;
        case AVKeyValueStatusFailed:
                //TODO
            break;
        case AVKeyValueStatusCancelled:
                //TODO
            break;
   }
}];

1.3 AVFoundation 之 视频播放

AVFoundation Player1
AVFoundation Player2

1.3.1 AVPlayer

+ (instancetype)playerWithURL:(NSURL *)URL;
+ (instancetype)playerWithPlayerItem:(nullable AVPlayerItem *)item;
- (instancetype)initWithURL:(NSURL *)URL;
- (instancetype)initWithPlayerItem:(nullable AVPlayerItem *)item;

1.3.2 播放不同类型的资源

1.3.3 播放控制

  1. AVPlayerTimeControlStatusPaused 暂停
  2. AVPlayerTimeControlStatusPlaying 播放
  3. AVPlayerTimeControlStatusWaitingToPlayAtSpecifiedRate 等待按指定速率播放状态,该状态是当 rate 的值设置为非 0 值时,而 item 因某些原因还无法播放的情况,而无法播放的原因,可依通过 item 的 reasonForWaitingToPlay 属性值查看。
  1. AVPlayerActionAtItemEndAdvance 只适用于 AVQueuePlayer 类,表示播放队列中的下一个 item
  2. AVPlayerActionAtItemEndPause 表示暂停
  3. AVPlayerActionAtItemEndNone 表示无操作,当前 item 的 currentTime 属性值仍然按 rate 的值改变
    item 的 currentTime 属性值表示当前 item 的播放时间,可以调用下面的方法指定 item 从何处进行播放。
//第二个方法能够进行更准确的跳转,但是需要进行额外的计算
- (void)seekToDate:(NSDate *)date;
- (void)seekToTime:(CMTime)time toleranceBefore:(CMTime)toleranceBefore toleranceAfter:(CMTime)toleranceAfter; (tolerance: 公差,前后公差)

//这两个方法传入了一个回调,当一个时间跳转请求被新的请求或其他操作打断时,回调也会被执行但是此时 finished 参数值为 NO
- (void)seekToTime:(CMTime)time completionHandler:(void (^)(BOOL finished))completionHandler NS_AVAILABLE(10_7, 5_0);
- (void)seekToTime:(CMTime)time toleranceBefore:(CMTime)toleranceBefore toleranceAfter:(CMTime)toleranceAfter completionHandler:(void (^)(BOOL finished))completionHandler NS_AVAILABLE(10_7, 5_0);
- (BOOL)canInsertItem:(AVPlayerItem *)item afterItem:(nullable AVPlayerItem *)afterItem;
- (void)insertItem:(AVPlayerItem *)item afterItem:(nullable AVPlayerItem *)afterItem;
- (void)removeItem:(AVPlayerItem *)item;
- (void)removeAllItems;
- (id)addPeriodicTimeObserverForInterval:(CMTime)interval queue:(nullable dispatch_queue_t)queue usingBlock:(void (^)(CMTime time))block;
- (id)addBoundaryTimeObserverForTimes:(NSArray<NSValue *> *)times queue:(nullable dispatch_queue_t)queue usingBlock:(void (^)(void))block;

1.3.4 自定义播放--音频

AVMutableAudioMix *mutableAudioMix = [AVMutableAudioMix audioMix];

AVMutableAudioMixInputParameters *mixParameters1 = [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:compositionAudioTrack1];
[mixParameters1 setVolumeRampFromStartVolume:1.f toEndVolume:0.f timeRange:CMTimeRangeMake(kCMTimeZero, mutableComposition.duration/2)];
[mixParameters1 setVolumeRampFromStartVolume:0.f toEndVolume:1.f timeRange:CMTimeRangeMake(mutableComposition.duration/2, mutableComposition.duration)];

AVMutableAudioMixInputParameters *mixParameters2 = [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:compositionAudioTrack2];
[mixParameters2 setVolumeRampFromStartVolume:1.f toEndVolume:0.f timeRange:CMTimeRangeMake(kCMTimeZero, mutableComposition.duration)];

mutableAudioMix.inputParameters = @[mixParameters1, mixParameters2];

1.3.4.1 AVAudioMix

1.3.4.2 AVMutableAudioMix

1.3.4.3 AVAudioMixInputParameters

//获取的音量变化范围 timeRange 应包含指定的时刻 time 否则最终返回 NO
//startVolume 获取音量开始变化时的初始音量
//endVolume 获取音量变化结束时的音量
//timeRang 是实际音量变化的范围,它应该包含指定的 time
- (BOOL)getVolumeRampForTime:(CMTime)time startVolume:(nullable float *)startVolume endVolume:(nullable float *)endVolume timeRange:(nullable CMTimeRange *)timeRange;

1.3.4.4 AVMutableAudioMixInputParameters

//根据提供的 track 创建一个实例,此时的音量描述数据为空
+ (instancetype)audioMixInputParametersWithTrack:(nullable AVAssetTrack *)track;

//创建一个实例,此时的音量变化描述是空的,且 trackID 为 kCMPersistentTrackID_Invalid
+ (instancetype)audioMixInputParameters;

//设置某个时间范围内的初始音量及结束音量
- (void)setVolumeRampFromStartVolume:(float)startVolume toEndVolume:(float)endVolume timeRange:(CMTimeRange)timeRange;

//设置某个时刻的音量
- (void)setVolume:(float)volume atTime:(CMTime)time;

1.3.5 自定义播放--视频

1.3.5.1 AVVideoComposition

//该类的构造类,提供自定义的构造类时,提供的类要遵守 AVVideoCompositing 协议
@property (nonatomic, readonly, nullable) Class<AVVideoCompositing> customVideoCompositorClass NS_AVAILABLE(10_9, 7_0);

//视频每一帧的刷新时间
@property (nonatomic, readonly) CMTime frameDuration;

//视频显示时的大小范围
@property (nonatomic, readonly) CGSize renderSize;

//视频显示范围大小的缩放比例(仅仅对 iOS 有效)
@property (nonatomic, readonly) float renderScale;

//描述视频集合中具体视频播放方式信息的集合,其是遵循 AVVideoCompositionInstruction 协议的类实例对象
//这些视频播放信息构成一个完整的时间线,不能重叠,不能间断,并且在数组中的顺序即为相应视频的播放顺序
@property (nonatomic, readonly, copy) NSArray<id <AVVideoCompositionInstruction>> *instructions;

//用于组合视频帧与动态图层的 Core Animation 的工具对象,可以为 nil 
@property (nonatomic, readonly, retain, nullable) AVVideoCompositionCoreAnimationTool *animationTool;

//直接使用一个 asset 创建一个实例,创建的实例的各个属性会根据 asset 中的所有的 video tracks 的属性进行计算并适配,所以在调用该方法之前,确保 asset 中的属性已经加载
//返回的实例对象的属性 instructions 中的对象会对应每个 asset 中的 track 中属性要求
//返回的实例对象的属性 frameDuration 的值是 asset 中 所有 track 的 nominalFrameRate 属性值最大的,如果这些值都为 0 ,默认为 30fps
//返回的实例对象的属性 renderSize 的值是 asset 的 naturalSize 属性值,如果 asset 是 AVComposition 类的实例。否则,renderSize 的值将包含每个 track 的 naturalSize 属性值
+ (AVVideoComposition *)videoCompositionWithPropertiesOfAsset:(AVAsset *)asset NS_AVAILABLE(10_9, 6_0);

//这三个属性设置了渲染帧时的颜色空间、矩阵、颜色转换函数,可能的值都在 AVVideoSetting.h 文件中定义
@property (nonatomic, readonly, nullable) NSString *colorPrimaries NS_AVAILABLE(10_12, 10_0);
@property (nonatomic, readonly, nullable) NSString *colorYCbCrMatrix NS_AVAILABLE(10_12, 10_0);
@property (nonatomic, readonly, nullable) NSString *colorTransferFunction NS_AVAILABLE(10_12, 10_0);

//该方法返回一个实例,它指定的 block 会对 asset 中每一个有效的 track 的每一帧进行渲染得到 CIImage 实例对象
//在 block 中进行每一帧的渲染,成功后应调用 request 的方法 finishWithImage:context: 并将得到的 CIImage 对象作为参数
//若是渲染失败,则应调用 finishWithError: 方法并传递错误信息

+ (AVVideoComposition *)videoCompositionWithAsset:(AVAsset *)asset
             applyingCIFiltersWithHandler:(void (^)(AVAsynchronousCIImageFilteringRequest *request))applier NS_AVAILABLE(10_11, 9_0);

1.3.5.2 AVMutableVideoComposition

//这个方法创建的实例对象的属性的值都是 nil 或 0,但是它的属性都是可以进行修改的
+ (AVMutableVideoComposition *)videoComposition;

1.3.5.3 AVVideoCompositionInstruction

//表示该 instruction 生效的时间范围
@property (nonatomic, readonly) CMTimeRange timeRange;

//指定当前时间段的 composition 的背景色
//如果没有指定,那么使用默认的黑色
//如果渲染的像素没有透明度通道,那么这个颜色也会忽略透明度
@property (nonatomic, readonly, retain, nullable) __attribute__((NSObject)) CGColorRef backgroundColor;

//AVVideoCompositionLayerInstruction 类实例对象的集合,描述各个视频资源帧的层级及组合关系
//按这个数组的顺序,第一个显示在第一层,第二个在第一层下面显示,以此类推
@property (nonatomic, readonly, copy) NSArray<AVVideoCompositionLayerInstruction *> *layerInstructions;

//表明该时间段的视频帧是否需要后期处理
//若为 NO,后期图层的处理将跳过该时间段,这样能够提高效率
//为 YES 则按默认操作处理(参考 AVVideoCompositionCoreAnimationTool 类)
@property (nonatomic, readonly) BOOL enablePostProcessing;

//当前 instruction 中需要进行帧组合的所有的 track ID 的集合,由属性 layerInstructions 计算得到
@property (nonatomic, readonly) NSArray<NSValue *> *requiredSourceTrackIDs NS_AVAILABLE(10_9, 7_0);

//如果当前的 instruction 在该时间段内的视频帧组合后,实质得到的是某个源视频的帧,那么就返回这个视频资源的 ID
@property (nonatomic, readonly) CMPersistentTrackID passthroughTrackID NS_AVAILABLE(10_9, 7_0); 

1.3.5.4 AVMutableVideoCompositionInstruction

+ (instancetype)videoCompositionInstruction;

1.3.5.5 AVVideoCompositionLayerInstruction

//获取包含指定时间的仿射变化梯度信息
//startTransform、endTransform 用来接收变化过程的起始值与结束值
//timeRange 用来接收变化的持续时间范围
//返回值表示指定的时间 time 是否在变化时间 timeRange 内
- (BOOL)getTransformRampForTime:(CMTime)time startTransform:(nullable CGAffineTransform *)startTransform endTransform:(nullable CGAffineTransform *)endTransform timeRange:(nullable CMTimeRange *)timeRange;

//获取包含指定时间的透明度变化梯度信息
//startOpacity、endOpacity 用来接收透明度变化过程的起始值与结束值
//timeRange 用来接收变化的持续时间范围
//返回值表示指定的时间 time 是否在变化时间 timeRange 内
- (BOOL)getOpacityRampForTime:(CMTime)time startOpacity:(nullable float *)startOpacity endOpacity:(nullable float *)endOpacity timeRange:(nullable CMTimeRange *)timeRange;

//获取包含指定时间的裁剪区域的变化梯度信息
//startCropRectangle、endCropRectangle 用来接收变化过程的起始值与结束值
//timeRange 用来接收变化的持续时间范围
//返回值表示指定的时间 time 是否在变化时间 timeRange 内
- (BOOL)getCropRectangleRampForTime:(CMTime)time startCropRectangle:(nullable CGRect *)startCropRectangle endCropRectangle:(nullable CGRect *)endCropRectangle timeRange:(nullable CMTimeRange *)timeRange NS_AVAILABLE(10_9, 7_0);

1.3.5.6 AVMutableVideoCompositionLayerInstruction

//这两个方法的区别在于,前者返回的实例对象的属性 trackID 的值是 track 的 trackID 值
//而第二个方法的返回的实例对象的属性 trackID 的值为 kCMPersistentTrackID_Invalid
+ (instancetype)videoCompositionLayerInstructionWithAssetTrack:(AVAssetTrack *)track;
+ (instancetype)videoCompositionLayerInstruction;

@property (nonatomic, assign) CMPersistentTrackID trackID;
//设置视频中帧的仿射变化信息
//指定了变化的时间范围、起始值和结束值,其中坐标系的原点为左上角,向下向右为正方向
- (void)setTransformRampFromStartTransform:(CGAffineTransform)startTransform toEndTransform:(CGAffineTransform)endTransform timeRange:(CMTimeRange)timeRange;

//设置 instruction 的 timeRange 范围内指定时间的仿射变换,该值会一直保持,直到被再次设置
- (void)setTransform:(CGAffineTransform)transform atTime:(CMTime)time;

//设置透明度的梯度信息,提供的透明度初始值和结束值应在0~1之间
//变化的过程是线形的
- (void)setOpacityRampFromStartOpacity:(float)startOpacity toEndOpacity:(float)endOpacity timeRange:(CMTimeRange)timeRange;

//设置指定时间的透明度,该透明度会一直持续到下一个值被设置
- (void)setOpacity:(float)opacity atTime:(CMTime)time;

//设置裁剪矩形的变化信息
- (void)setCropRectangleRampFromStartCropRectangle:(CGRect)startCropRectangle toEndCropRectangle:(CGRect)endCropRectangle timeRange:(CMTimeRange)timeRange NS_AVAILABLE(10_9, 7_0);

//设置指定时间的裁剪矩形
- (void)setCropRectangle:(CGRect)cropRectangle atTime:(CMTime)time NS_AVAILABLE(10_9, 7_0);

1.3.5.7 AVVideoCompositionCoreAnimationTool

//向视频组合中添加一个动画图层,这个图层不能在任何图层树中
//提供的参数 trackID 应由方法 [AVAsset unusedTrackID] 得到,它不与任何视频资源的 trackID 相关
//AVVideoCompositionInstruction 的属性 layerInstructions 包含的 AVVideoCompositionLayerInstruction 实例对象中应该有
//该 trackID 一致的 AVVideoCompositionLayerInstruction 实例对象,并且为性能考虑,不应使用该对象设置 transform 的变化
//在 iOS 中,CALayer 作为 UIView 的背景图层,其内容的是否能够翻转,由方法 contentsAreFlipped 决定(如果所有的图层包括子图层,该方法返回的值为 YES 的个数为奇数个,表示可以图层中内容可以垂直翻转)
//所以这里的 layer 若用来设置 UIView 的 layer 属性,或作为其中的子图层,其属性值 geometryFlipped 应设置为 YES ,这样则能够保持是否能够翻转的结果一致
+ (instancetype)videoCompositionCoreAnimationToolWithAdditionalLayer:(CALayer *)layer asTrackID:(CMPersistentTrackID)trackID;

//将放在图层 videoLayer 中的组合视频帧同动画图层 animationLayer 中的内容一起进行渲染,得到最终的视频帧
//通常,videoLayer 是 animationLayer 的子图层,而 animationLayer 则不在任何图层树中
+ (instancetype)videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:(CALayer *)videoLayer inLayer:(CALayer *)animationLayer;

//复制 videoLayers 中的每一个图层,与 animationLayer一起渲染得到最中的帧
////通常,videoLayers 中的图层都在 animationLayer 的图层树中,而 animationLayer 则不属于任何图层树
+ (instancetype)videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayers:(NSArray<CALayer *> *)videoLayers inLayer:(CALayer *)animationLayer NS_AVAILABLE(10_9, 7_0);

1.3.5.8 AVVideoCompositionValidationHandling

/*
@param asset 
设置第一个参数的校验内容,设置 nil 忽略这些校验
1. 该方法可以校验 AVVideoComposition 的属性 instructions 是否符合要求
2. 校验 instructions 中的每个 AVVideoCompositionInstruction 对象的 layerInstructions 属性中的
每一个 AVVideoCompositionLayerInstruction 对象 trackID 值是否对应 asset 中 track 的 ID 
或 AVVideoComposition 的 animationTool 实例
3. 校验时间 asset 的时长是否与 instructions 中的时间范围相悖

@param timeRange 
设置第二个参数的校验内容
1. 校验 instructions 的所有的时间范围是否在提供的 timeRange 的范围内,
若要忽略该校验,可以传参数 CMTimeRangeMake(kCMTimeZero, kCMTimePositiveInfinity)

@param validationDelegate 
设置遵循 AVVideoCompositionValidationHandling 协议的代理类,用来处理校验过程中的报错,可以为 nil 
*/
- (BOOL)isValidForAsset:(nullable AVAsset *)asset timeRange:(CMTimeRange)timeRange validationDelegate:(nullable id<AVVideoCompositionValidationHandling>)validationDelegate NS_AVAILABLE(10_8, 5_0);
//报告 videoComposition 中有无效的值
- (BOOL)videoComposition:(AVVideoComposition *)videoComposition shouldContinueValidatingAfterFindingInvalidValueForKey:(NSString *)key NS_AVAILABLE(10_8, 5_0);

//报告 videoComposition 中有时间段没有相对应的 instruction
- (BOOL)videoComposition:(AVVideoComposition *)videoComposition shouldContinueValidatingAfterFindingEmptyTimeRange:(CMTimeRange)timeRange NS_AVAILABLE(10_8, 5_0);

//报告 videoComposition 中的 instructions 中 timeRange 无效的实例对象
//可能是 timeRange 本身为 CMTIMERANGE_IS_INVALID 
//或者是该时间段同上一个的 instruction 的 timeRange 重叠
//也可能是其开始时间比上一个的 instruction 的 timeRange 的开始时间要早
- (BOOL)videoComposition:(AVVideoComposition *)videoComposition shouldContinueValidatingAfterFindingInvalidTimeRangeInInstruction:(id<AVVideoCompositionInstruction>)videoCompositionInstruction NS_AVAILABLE(10_8, 5_0);

//报告 videoComposition 中的 layer instruction 同调用校验方法时指定的 asset 中 track 的 trackID 不一致
//也不与 composition 使用的 animationTool 的trackID 一致
- (BOOL)videoComposition:(AVVideoComposition *)videoComposition shouldContinueValidatingAfterFindingInvalidTrackIDInInstruction:(id<AVVideoCompositionInstruction>)videoCompositionInstruction layerInstruction:(AVVideoCompositionLayerInstruction *)layerInstruction asset:(AVAsset *)asset NS_AVAILABLE(10_8, 5_0);

1.3.5.9 AVVideoCompositionValidationHandling

1.4 AVFoundation 之 视音频编辑

AVFoundation 编辑视频1 AVFoundation 编辑视2 将现有资产组合拼凑成新资产 视频合成 音视频组合

1.4.1 AVAssetExportSession

//获取与 asset 兼容的预设置
+ (NSArray<NSString *> *)exportPresetsCompatibleWithAsset:(AVAsset *)asset;

//判断提供的预设置和输出的文件类型是否与 asset 相兼容
+ (void)determineCompatibilityOfExportPreset:(NSString *)presetName withAsset:(AVAsset *)asset outputFileType:(nullable NSString *)outputFileType completionHandler:(void (^)(BOOL compatible))handler NS_AVAILABLE(10_9, 6_0);
- (void)exportVideo:(NSURL *)url {
    AVAsset *anAsset = [AVAsset assetWithURL:url];

    [AVAssetExportSession determineCompatibilityOfExportPreset:AVAssetExportPresetHighestQuality
                                                     withAsset:anAsset
                                                outputFileType:AVFileTypeMPEG4
                                             completionHandler:^(BOOL compatible) {
        if (compatible){
            AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:anAsset
                                                                                   presetName:AVAssetExportPresetHighestQuality];

            exportSession.outputFileType = AVFileTypeMPEG4;

            CMTime start = CMTimeMakeWithSeconds(1.0, 600);
            CMTime duration = CMTimeMakeWithSeconds(3.0, 600);
            CMTimeRange range = CMTimeRangeMake(start, duration);
            exportSession.timeRange = range;
            [exportSession exportAsynchronouslyWithCompletionHandler:^{

                switch ([exportSession status]) {
                    case AVAssetExportSessionStatusCompleted:
                        NSLog(@"completed");
                        break;
                    case AVAssetExportSessionStatusFailed:
                        NSLog(@"failed");
                        break;
                    case AVAssetExportSessionStatusCancelled:
                        NSLog(@"canceled");
                        break;
                    default:
                        break;
                }
            }];
        }
    }];
}

1.4.2 AVComposition

//获取 composition 中包含的 tracks
@property (nonatomic, readonly) NSArray<AVCompositionTrack *> *tracks;

//获取 composition 中可视媒体资源播放时在屏幕上显示的大小
@property (nonatomic, readonly) CGSize naturalSize;

//获取 composition 生成 asset 时的指定配置
@property (nonatomic, readonly, copy) NSDictionary<NSString *, id> *URLAssetInitializationOptions NS_AVAILABLE(10_11, 9_0);

//根据不同的参数,获取 composition 中的 track
- (nullable AVCompositionTrack *)trackWithTrackID:(CMPersistentTrackID)trackID;
- (NSArray<AVCompositionTrack *> *)tracksWithMediaType:(NSString *)mediaType;
- (NSArray<AVCompositionTrack *> *)tracksWithMediaCharacteristic:(NSString *)mediaCharacteristic;
AVMutableComposition *mutableComposition = [AVMutableComposition composition];

//进行添加资源等操作
<#····#>

//使用可变的 composition 生成一个不可变的 composition 以供使用
AVComposition *composition = [myMutableComposition copy];
AVPlayerItem *playerItem = [[AVPlayerItem alloc] initWithAsset:composition];

1.4.3 AVMutableComposition

+ (instancetype)composition;
+ (instancetype)compositionWithURLAssetInitializationOptions:(nullable NSDictionary<NSString *, id> *)URLAssetInitializationOptions NS_AVAILABLE(10_11, 9_0);
//将指定时间段的 asset 中的所有的 tracks 添加到 composition 中 startTime 处
//该方法可能会在 composition 中添加新的 track 以便 asset 中 timeRange 范围中的所有 tracks 都添加到 composition 中
- (BOOL)insertTimeRange:(CMTimeRange)timeRange ofAsset:(AVAsset *)asset atTime:(CMTime)startTime error:(NSError * _Nullable * _Nullable)outError;

//向 composition 中的所有 tracks 添加空的时间范围
- (void)insertEmptyTimeRange:(CMTimeRange)timeRange;

//从 composition 的所有 tracks 中删除一段时间,该操作不会删除 track ,而是会删除与该时间段相交的 track segment
- (void)removeTimeRange:(CMTimeRange)timeRange;

//改变 composition 中的所有的 tracks 的指定时间范围的时长,该操作会改变 asset 的播放速度
- (void)scaleTimeRange:(CMTimeRange)timeRange toDuration:(CMTime)duration;
//向 composition 中添加一个空的 track ,并且指定媒体资源类型及 trackID 属性值
//若提供的参数 preferredTrackID 无效或为 kCMPersistentTrackID_Invalid ,那么唯一的 trackID 会自动生成
- (AVMutableCompositionTrack *)addMutableTrackWithMediaType:(NSString *)mediaType preferredTrackID:(CMPersistentTrackID)preferredTrackID;

//从 composition 中删除一个指定的 track
- (void)removeTrack:(AVCompositionTrack *)track;

//获取一个与 asset track 相兼容的 composition track 
//为了更好的性能,composition track 的数量应保持最小,这个数量与必需并行播放的媒体数据段数量以及媒体数据的类型相关
//对于能够线性执行且类型相同的媒体数据应使用同一个 composition track ,即使这些数据来自不同的 asset
- (nullable AVMutableCompositionTrack *)mutableTrackCompatibleWithTrack:(AVAssetTrack *)track;
- (nullable AVMutableCompositionTrack *)trackWithTrackID:(CMPersistentTrackID)trackID;
- (NSArray<AVMutableCompositionTrack *> *)tracksWithMediaType:(NSString *)mediaType;
- (NSArray<AVMutableCompositionTrack *> *)tracksWithMediaCharacteristic:(NSString *)mediaCharacteristic;

1.4.4 AVCompositionTrack

1.4.5 AVMutableCompositionTrack

//没有外部数值指定时,媒体1秒钟时间的粒度
@property (nonatomic) CMTimeScale naturalTimeScale;

//当前 track 相关联的语言编码
@property (nonatomic, copy, nullable) NSString *languageCode;

//当前 track 相关联的额外语言编码
@property (nonatomic, copy, nullable) NSString *extendedLanguageTag;

//对于可显示的媒体数据应优先选择的仿射变换设置,默认值为 CGAffineTransformIdentity
@property (nonatomic) CGAffineTransform preferredTransform;

//应优先选择的音量,默认值为 1
@property (nonatomic) float preferredVolume;

//当前track 所包含的所有的媒体数据片段,对于这些片段,它们构成了 track 的完整时间线,
//所以他们的时间线不可以重叠,并且第一个数据片段的时间从 kCMTimeZero 开始,依次往后的时间必须连续不间断、不重叠
@property (nonatomic, copy, null_resettable) NSArray<AVCompositionTrackSegment *> *segments;
//将已存在的资源文件指定时间范围的媒体数据插入到当前 composition 的指定时间处
//如果 startTime 为 kCMTimeInvalid 值,那么数据被添加到 composition 的最后
- (BOOL)insertTimeRange:(CMTimeRange)timeRange ofTrack:(AVAssetTrack *)track atTime:(CMTime)startTime error:(NSError * _Nullable * _Nullable)outError;

//这个方法与上述方法类似,只是可以批量操作,但是注意提供的时间范围不能重叠
- (BOOL)insertTimeRanges:(NSArray<NSValue *> *)timeRanges ofTracks:(NSArray<AVAssetTrack *> *)tracks atTime:(CMTime)startTime error:(NSError * _Nullable * _Nullable)outError NS_AVAILABLE(10_8, 5_0);

//插入一个没有媒体数据的时间段,当这个范围之前的媒体资源播放结束后,不会立刻播放之后的媒体数据,而是会静默一段时间
- (void)insertEmptyTimeRange:(CMTimeRange)timeRange;

//移除一段时间范围的媒体数据,该方法不会导致该 track 从 composition 中移除,只是移除与时间范围相交的数据片段
- (void)removeTimeRange:(CMTimeRange)timeRange;

//改变某个时间范围内的时间的时长,实质是改变了媒体数据的播放速率
//其速率是原时长与现时长的比值,总之,媒体数据是要按时长播放的
- (void)scaleTimeRange:(CMTimeRange)timeRange toDuration:(CMTime)duration;

//判断数据片段的时间线是否重叠
- (BOOL)validateTrackSegments:(NSArray<AVCompositionTrackSegment *> *)trackSegments error:(NSError * _Nullable * _Nullable)outError;

1.4.6 AVAssetTrackSegment

  1. timeMapping 描述的是数据片段在整个媒体文件中所处的时间范围.timeMapping 是一个结构体,拥有两个成员,对于编辑中的媒体数据片段,它们分别表示数据在源文件中的位置和目标文件中的位置.
  2. empty 描述该数据片段是否为空,如果为空,其 timeMapping.source.start 为 kCMTimeInvalid

1.4.7 AVCompositionTrackSegment

//判断数据片段是否为空,若为空 timeMapping.target 可为有效值,其他为未定义值
@property (nonatomic, readonly, getter=isEmpty) BOOL empty;

//片段数据所处的文件的地址
@property (nonatomic, readonly, nullable) NSURL *sourceURL;

//片段数据所处文件的描述 asset track 的 ID
@property (nonatomic, readonly) CMPersistentTrackID sourceTrackID;

//创建对象,提供了数据片段所在的文件、文件的描述 asset track 的 ID 、源文件中的数据时间范围、目标文件中所处的时间范围
//sourceTimeRange 与 targetTimeRange 的时间长度如果不一致,那么播放的速率会改变
+ (instancetype)compositionTrackSegmentWithURL:(NSURL *)URL trackID:(CMPersistentTrackID)trackID sourceTimeRange:(CMTimeRange)sourceTimeRange targetTimeRange:(CMTimeRange)targetTimeRange;
- (instancetype)initWithURL:(NSURL *)URL trackID:(CMPersistentTrackID)trackID sourceTimeRange:(CMTimeRange)sourceTimeRange targetTimeRange:(CMTimeRange)targetTimeRange NS_DESIGNATED_INITIALIZER;

//创建仅有时间范围而无实际媒体数据的实例
+ (instancetype)compositionTrackSegmentWithTimeRange:(CMTimeRange)timeRange;
- (instancetype)initWithTimeRange:(CMTimeRange)timeRange NS_DESIGNATED_INITIALIZER; 

1.5 AVFoundation 之 视音频媒体捕获

AVFoundation 媒体捕捉1 AVFoundation 媒体捕捉2 AVFoundation 媒体捕捉3
  1. 表示输入设备的AVCaptureDevice实例,如摄像机或麦克风
  2. AVCaptureInput的一个具体子类的实例,用于配置来自输入设备的端口
  3. AVCaptureOutput的一个具体子类的实例,用于管理电影文件或静态图像的输出
  4. AVCaptureSession的一个实例,用于协调从输入到输出的数据流
AVCaptureConnection表示输入和输出之间的连接

1.5.1 AVCaptureSession

- (BOOL)canSetSessionPreset:(NSString*)preset;
- (BOOL)canAddInput:(AVCaptureInput *)input;
- (void)addInput:(AVCaptureInput *)input;
- (void)removeInput:(AVCaptureInput *)input;

- (BOOL)canAddOutput:(AVCaptureOutput *)output;
- (void)addOutput:(AVCaptureOutput *)output;
- (void)removeOutput:(AVCaptureOutput *)output;

- (void)addInputWithNoConnections:(AVCaptureInput *)input NS_AVAILABLE(10_7, 8_0);
- (void)addOutputWithNoConnections:(AVCaptureOutput *)output NS_AVAILABLE(10_7, 8_0);

- (BOOL)canAddConnection:(AVCaptureConnection *)connection NS_AVAILABLE(10_7, 8_0);
- (void)addConnection:(AVCaptureConnection *)connection NS_AVAILABLE(10_7, 8_0);
- (void)removeConnection:(AVCaptureConnection *)connection NS_AVAILABLE(10_7, 8_0);
- (void)startRunning;
- (void)stopRunning;
- (void)beginConfiguration;
- (void)commitConfiguration;
  1. VCaptureSessionRuntimeErrorNotification 通过 AVCaptureSessionErrorKey 可以获取出错的原因
  2. AVCaptureSessionDidStartRunningNotification 开始 session
  3. AVCaptureSessionDidStopRunningNotification 结束 session
  4. AVCaptureSessionWasInterruptedNotification 通过 AVCaptureSessionInterruptionReasonKey 可以获取被打断的原因
  5. AVCaptureSessionInterruptionEndedNotification 打断结束,session 重新开始

1.5.2 AVCaptureDevice

+ (NSArray *)devices;
+ (NSArray *)devicesWithMediaType:(NSString *)mediaType;
+ (AVCaptureDevice *)defaultDeviceWithMediaType:(NSString *)mediaType;
+ (AVCaptureDevice *)deviceWithUniqueID:(NSString *)deviceUniqueID;

@property(nonatomic, readonly) NSString *uniqueID;
@property(nonatomic, readonly) NSString *modelID;
@property(nonatomic, readonly) NSString *localizedName;

//校验获得的设备能否提供相应的媒体数据类型
- (BOOL)hasMediaType:(NSString *)mediaType;

//校验获得的设备能否支持相应的配置
- (BOOL)supportsAVCaptureSessionPreset:(NSString *)preset;

  1. flashMode 闪光灯的模式(AVCaptureFlashModeOff 、AVCaptureFlashModeOn 、AVCaptureFlashModeAuto)
  2. torchMode 手电筒的模式(AVCaptureTorchModeOff 、AVCaptureTorchModeOn 、AVCaptureTorchModeAuto)
    torchLevel 手电筒的亮度(0~1)
  3. focusMode 聚焦模式(AVCaptureFocusModeLocked 、AVCaptureFocusModeAutoFocus 、AVCaptureFocusModeContinuousAutoFocus)
  4. exposureMode 曝光模式(AVCaptureExposureModeLocked 、AVCaptureExposureModeAutoExpose 、AVCaptureExposureModeContinuousAutoExposure 、AVCaptureExposureModeCustom)
  5. whiteBalanceMode 白平衡模式(AVCaptureWhiteBalanceModeLocked 、AVCaptureWhiteBalanceModeAutoWhiteBalance 、AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance)
- (BOOL)lockForConfiguration:(NSError **)outError;
- (void)unlockForConfiguration;
  1. AVAuthorizationStatusNotDetermined 未定义
  2. AVAuthorizationStatusRestricted 无权限(因某些原因,系统拒绝权限)
  3. AVAuthorizationStatusDenied 无权限(用户拒绝)
  4. AVAuthorizationStatusAuthorized 有权限
//校验权限
+ (AVAuthorizationStatus)authorizationStatusForMediaType:(NSString *)mediaType NS_AVAILABLE_IOS(7_0);

//请求权限,handler 处理会在任意线程中执行,所以需要在主线程中执行的处理由用户负责指定
+ (void)requestAccessForMediaType:(NSString *)mediaType completionHandler:(void (^)(BOOL granted))handler NS_AVAILABLE_IOS(7_0);

1.5.3 AVCaptureDeviceInput

NSError *error;
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
if (input && [session canAddInput:input]) {
    [captureSession addInput:captureDeviceInput];
}

1.5.4 AVCaptureOutput

  1. AVCaptureMovieFileOutput 用来生成一个影视文件
  2. AVCaptureVideoDataOutput 用来处理输入的视频的帧
  3. AVCaptureAudioDataOutput 用来处理音频数据
  4. AVCaptureStillImageOutput 用来获取图片
AVCaptureMovieFileOutput *movieOutput = [[AVCaptureMovieFileOutput alloc] init];
if ([session canAddOutput:movieOutput]) {
    [session addOutput:movieOutput];
}

1.5.5 AVCaptureFileOutput

//当前记录的数据的文件的地址
@property(nonatomic, readonly) NSURL *outputFileURL;

//开始文件的记录,指定文件的地址,以及记录过程中或结束时要通知的代理对象
//指定的 outputFileURL 必需是有效的且没有文件占用
- (void)startRecordingToOutputFileURL:(NSURL*)outputFileURL recordingDelegate:(id<AVCaptureFileOutputRecordingDelegate>)delegate;

//该方法可以停止数据向文件中写入
//如果要停止一个文件的写入转而指定另一个文件的写入,不应调用该方法,只需直接调用上面的方法
//当因该方法的调用、出错、或写入文件的变更导致当前文件开始停止写入时,最后传入的缓存数据仍会在后台被写入
//无论何时,要使用文件,都需要等指定的代理对象被告知文件的写入已经结束之后进行
- (void)stopRecording;

//判断当前是否有数据被写入文件
@property(nonatomic, readonly, getter=isRecording) BOOL recording;

//表示到目前为止,当前文件已经记录了多长时间
@property(nonatomic, readonly) CMTime recordedDuration;

//表示到目前为止,当前文件已经记录了多少个字节
@property(nonatomic, readonly) int64_t recordedFileSize;    
/**
下面三个值对文件的记录进行了限制,若果达到限制,则会在回调方法 captureOutput:didFinishRecordingToOutputFileAtURL:fromConnections:error: 中传递相应的错误
*/
//表示当前文件能够记录的最长时间,kCMTimeInvalid 表示无时间限制
@property(nonatomic) CMTime maxRecordedDuration;

//表示当前文件能够记录的最大字节数,0 表示无大小限制
@property(nonatomic) int64_t maxRecordedFileSize;

//表示记录当前文件时需要保留的最小字节数
@property(nonatomic) int64_t minFreeDiskSpaceLimit;

//在 Mac OS X 系统下,通过指定遵循 AVCaptureFileOutputDelegate 协议的代理对象,来实现缓存数据的精确记录
@property(nonatomic, assign) id<AVCaptureFileOutputDelegate> delegate NS_AVAILABLE(10_7, NA);

/**
在 Mac OS X 系统下,这个属性和方法可以判断记录是否停止,以及控制数据向文件中的停止写入和重新开始写入
*/
@property(nonatomic, readonly, getter=isRecordingPaused) BOOL recordingPaused NS_AVAILABLE(10_7, NA);
- (void)pauseRecording NS_AVAILABLE(10_7, NA);
- (void)resumeRecording NS_AVAILABLE(10_7, NA);

1.5.6 AVCaptureFileOutputRecordingDelegate

//这个代理方法是遵循该协议的代理对象必须要实现的方法
//每一个文件记录请求,最终都会调用这个方法,即使没有数据成功写入文件
//当 error 返回时,文件也可能成功保存了,应检查 error 中的 AVErrorRecordingSuccessfullyFinishedKey 信息,查看具体错误
- (void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error;

//当数据写入文件后调用,如果数据写入失败,该方法可能不会被调用
- (void)captureOutput:(AVCaptureFileOutput *)captureOutput didStartRecordingToOutputFileAtURL:(NSURL *)fileURL fromConnections:(NSArray *)connections;

/**
在 Mac OS X 系统下,当文件的记录被暂停或重新开始,会调用下面的方法,如果记录被终止,不会调用下面的方法
*/
- (void)captureOutput:(AVCaptureFileOutput *)captureOutput didPauseRecordingToOutputFileAtURL:(NSURL *)fileURL fromConnections:(NSArray *)connections NS_AVAILABLE(10_7, NA);
- (void)captureOutput:(AVCaptureFileOutput *)captureOutput didResumeRecordingToOutputFileAtURL:(NSURL *)fileURL fromConnections:(NSArray *)connections NS_AVAILABLE(10_7, NA);

//在 Mac OS X 系统下,当记录将被停止,无论是主动的还是被动的,都会调用下面的方法
- (void)captureOutput:(AVCaptureFileOutput *)captureOutput willFinishRecordingToOutputFileAtURL:(NSURL *)fileURL fromConnections:(NSArray *)connections error:(NSError *)error NS_AVAILABLE(10_7, NA);

1.5.7 AVCaptureFileOutputDelegate

/**
在 Mac OS X 10.8 系统之前,实现代理方法 captureOutput:didOutputSampleBuffer:fromConnection:
后便可以在该方法中实现数据记录的准确开始或结束,而要实现在任一一个画面帧处开始或停止数据的记录,要对每收到的
帧数据进行预先处理,这个过程消耗电能、产生热量、占用 CPU 资源,所以在 Mac OS X 10.8 及其之后的系统,提供了
下面的代理方法,来确定客户端需不需要随时进行记录的开始或停止。
如果这个方法返回 NO ,对数据记录的设置将在开启记录之后进行。
*/
- (BOOL)captureOutputShouldProvideSampleAccurateRecordingStart:(AVCaptureOutput *)captureOutput NS_AVAILABLE(10_8, NA);

/**
如果上面的方法返回了 YES ,那么客户端便可以使用下面的方法对每一个视频帧数据或音频数据进行操作
为了提高性能,缓存池中的缓存变量的内存通常会被复用,如果长时间使用缓存变量,那么新的缓存数据无法复制到
相应的内存中便会被废弃,所以若需要长时间使用缓存数据 sampleBuffer ,应复制一份,使其本身能够被系统复用
*/
- (void)captureOutput:(AVCaptureFileOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection NS_AVAILABLE(10_7, NA);

1.5.8 AVCaptureAudioFileOutput

//返回该类支持的音频文件类型
+ (NSArray *)availableOutputFileTypes;

//开始记录音频文件
- (void)startRecordingToOutputFileURL:(NSURL*)outputFileURL outputFileType:(NSString *)fileType recordingDelegate:(id<AVCaptureFileOutputRecordingDelegate>)delegate;

//要写入音频文件中的元数据 AVMetadataItem 集合
@property(nonatomic, copy) NSArray *metadata; 

//写入的音频文件的设置 AVAudioSettings.h
@property(nonatomic, copy) NSDictionary *audioSettings;

1.5.9 AVCaptureVideoDataOutput

- (void)setSampleBufferDelegate:(id<AVCaptureVideoDataOutputSampleBufferDelegate>)sampleBufferDelegate queue:(dispatch_queue_t)sampleBufferCallbackQueue;
//设置输出的视频要进行怎样的格式处理
//设置为空([NSDictionary dictionary])表示不改变输入时的视频格式
//设置为 nil 表示未压缩格式
@property(nonatomic, copy) NSDictionary *videoSettings;

//获取 kCVPixelBufferPixelFormatTypeKey 的有效值
@property(nonatomic, readonly) NSArray *availableVideoCVPixelFormatTypes NS_AVAILABLE(10_7, 5_0);

//获取 AVVideoCodecKey 的有效值
@property(nonatomic, readonly) NSArray *availableVideoCodecTypes NS_AVAILABLE(10_7, 5_0);

//表示当回调队列阻塞时,是否立刻丢弃新接收的帧数据
@property(nonatomic) BOOL alwaysDiscardsLateVideoFrames;

1.5.10 AVCaptureVideoDataOutputSampleBufferDelegate

//接收到一个帧数据时,在指定的串行队列中调用该方法,携带帧数据并包含有其他帧信息
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection;

//丢弃一个帧数据时,在指定的串行队列中调用该方法,sampleBuffer 只携带帧信息,具体帧数据并未携带
- (void)captureOutput:(AVCaptureOutput *)captureOutput didDropSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection NS_AVAILABLE(10_7, 6_0);

1.5.11 AVCaptureVideoPreviewLayer

//创建方法
+ (instancetype)layerWithSession:(AVCaptureSession *)session;
- (instancetype)initWithSession:(AVCaptureSession *)session;
  1. AVLayerVideoGravityResize 默认值,直接铺满屏幕,及时画面变形
  2. AVLayerVideoGravityResizeAspect 保持画面的横纵比,不铺满屏幕,多余的空间显示黑色
  3. AVLayerVideoGravityResizeAspectFill 保持画面的横纵比,铺满屏幕,多余的画面进行裁剪

1.5.12 AVCaptureAudioDataOutput

- (void)setSampleBufferDelegate:(id<AVCaptureAudioDataOutputSampleBufferDelegate>)sampleBufferDelegate queue:(dispatch_queue_t)sampleBufferCallbackQueue;

1.5.13 AVCaptureAudioDataOutputSampleBufferDelegate

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection;

1.5.14 AVAssetImageGenerator

+ (instancetype)assetImageGeneratorWithAsset:(AVAsset *)asset;
- (instancetype)initWithAsset:(AVAsset *)asset NS_DESIGNATED_INITIALIZER;

//获取一张图片,requestedTime 指定要获取视频中哪个时刻的图片,actualTime 返回图片实际是视频的哪个时刻,outError 返回错误信息
- (nullable CGImageRef)copyCGImageAtTime:(CMTime)requestedTime actualTime:(nullable CMTime *)actualTime error:(NSError * _Nullable * _Nullable)outError CF_RETURNS_RETAINED;

//获取多张图片,每一次图片生成后,都会调用一次 handler
- (void)generateCGImagesAsynchronouslyForTimes:(NSArray<NSValue *> *)requestedTimes completionHandler:(AVAssetImageGeneratorCompletionHandler)handler;

//上述 handler 的类型如下,回调中的参数有图片的请求时刻和实际时刻,图片,状态(成功、失败、取消),错误信息
typedef void (^AVAssetImageGeneratorCompletionHandler)(CMTime requestedTime, CGImageRef _Nullable image, CMTime actualTime, AVAssetImageGeneratorResult result, NSError * _Nullable error);

1.6 AVFoundation 之媒体流输出

AVFoundation 视频音频输出

1.6.1 AVAssetReader

//对于提供的参数 asset ,如果是可被修改的,那么在开始读取操作后,对其进行了修改,之后的读取操作都是无效的
+ (nullable instancetype)assetReaderWithAsset:(AVAsset *)asset error:(NSError * _Nullable * _Nullable)outError;
- (nullable instancetype)initWithAsset:(AVAsset *)asset error:(NSError * _Nullable * _Nullable)outError NS_DESIGNATED_INITIALIZER;

//当前读取操作的状态,可取值有 AVAssetReaderStatusUnknown 、AVAssetReaderStatusReading 、
AVAssetReaderStatusCompleted 、AVAssetReaderStatusFailed 、AVAssetReaderStatusCancelled
@property (readonly) AVAssetReaderStatus status;
//当 status 的值为 AVAssetReaderStatusFailed 时,描述错误信息
@property (readonly, nullable) NSError *error;


//限制可读取的资源的时间范围
@property (nonatomic) CMTimeRange timeRange;

//判断能否添加该数据源
- (BOOL)canAddOutput:(AVAssetReaderOutput *)output;
//添加数据源
- (void)addOutput:(AVAssetReaderOutput *)output;

//开始读取
- (BOOL)startReading;
//结束读取
- (void)cancelReading;

1.6.2 AVAssetReaderOutput

//获取的媒体数据的类型
@property (nonatomic, readonly) NSString *mediaType;

//是否拷贝缓存中的数据到客户端,默认 YES ,客户端可以随意修改数据,但是为优化性能,通常设为 NO
@property (nonatomic) BOOL alwaysCopiesSampleData NS_AVAILABLE(10_8, 5_0);

//同步获取下一个缓存数据,使用返回的数据结束后,应使用 CFRelease 函数将其释放
//当错误或没有数据可读取时,返回 NULL ,返回空后,应检查相关联的 reader 的状态
- (nullable CMSampleBufferRef)copyNextSampleBuffer CF_RETURNS_RETAINED;

//是否支持重新设置数据的读取时间范围,即能否修改 reader 的 timeRange 属性
@property (nonatomic) BOOL supportsRandomAccess NS_AVAILABLE(10_10, 8_0);
//设置重新读取的时间范围,这个时间范围集合中的每一个时间范围的开始时间必需是增长的且各个时间范围不能重叠
//应在 reader 调用 copyNextSampleBuffer 方法返回 NULL 之后才可调用
- (void)resetForReadingTimeRanges:(NSArray<NSValue *> *)timeRanges NS_AVAILABLE(10_10, 8_0);
//该方法调用后,上面的方法即不可再调用,同时 reader 的状态也不会被阻止变为 AVAssetReaderStatusCompleted 了
- (void)markConfigurationAsFinal NS_AVAILABLE(10_10, 8_0);

1.6.3 AVAssetReaderTrackOutput

//初始化方法,参数中指定了 track 和 媒体的格式
//指定的 track 应在 reader 的 asset 中
+ (instancetype)assetReaderTrackOutputWithTrack:(AVAssetTrack *)track outputSettings:(nullable NSDictionary<NSString *, id> *)outputSettings;
- (instancetype)initWithTrack:(AVAssetTrack *)track outputSettings:(nullable NSDictionary<NSString *, id> *)outputSettings NS_DESIGNATED_INITIALIZER;

//指定音频处理时的算法
@property (nonatomic, copy) NSString *audioTimePitchAlgorithm NS_AVAILABLE(10_9, 7_0);

1.6.4 AVAssetReaderAudioMixOutput

+ (instancetype)assetReaderAudioMixOutputWithAudioTracks:(NSArray<AVAssetTrack *> *)audioTracks audioSettings:(nullable NSDictionary<NSString *, id> *)audioSettings;
- (instancetype)initWithAudioTracks:(NSArray<AVAssetTrack *> *)audioTracks audioSettings:(nullable NSDictionary<NSString *, id> *)audioSettings NS_DESIGNATED_INITIALIZER

1.6.5 AVAssetReaderVideoCompositionOutput

+ (instancetype)assetReaderVideoCompositionOutputWithVideoTracks:(NSArray<AVAssetTrack *> *)videoTracks videoSettings:(nullable NSDictionary<NSString *, id> *)videoSettings;
- (instancetype)initWithVideoTracks:(NSArray<AVAssetTrack *> *)videoTracks videoSettings:(nullable NSDictionary<NSString *, id> *)videoSettings NS_DESIGNATED_INITIALIZER;
@property (nonatomic, copy, nullable) AVVideoComposition *videoComposition;

1.7 AVFoundation 之媒体的时间和数据

AVFoundation 媒体的时间与数据
上一篇 下一篇

猜你喜欢

热点阅读