AVFoundation – AVAssetImageGenerator 获取多帧图片

AVAssetImageGenerator 获取多帧图片

零基础 Object-C 学习路线推荐 : Object-C 学习目录 >> Object-C 基础

零基础 Object-C 学习路线推荐 : Object-C 学习目录 >> Object-C 线程

零基础 Object-C 学习路线推荐 : Object-C 学习目录 >> OpenGL ES

零基础 Object-C 学习路线推荐 : Object-C 学习目录 >> GPUImage

零基础 Object-C 学习路线推荐 : Object-C 学习目录 >> AVFoundation

零基础 Object-C 学习路线推荐 : Object-C 学习目录 >> CocoaPods


一.前言

1.AVAsset

Assets 可以来自一个文件或用户的相册,可以理解为多媒体资源,通过 URL 作为一个 asset 对象的标识. 这个 URL 可以是本地文件路径或网络流;


2.AVAssetTrack

AVAsset 包含很多轨道 AVAssetTrack 的结合,如 audio, video, text, closed captions, subtitles…


3.AVComposition / AVMutableComposition

使用 AVMutableComposition 类可以增删 AVAsset 来将单个或者多个 AVAsset 集合到一起,用来合成新视频。除此之外,若想将集合到一起的视听资源以自定义的方式进行播放,需要使用 AVMutableAudioMix 和 AVMutableVideoComposition 类对其中的资源进行协调管理;


4.AVMutableVideoComposition

AVFoundation 类 API 中最核心的类是 AVVideoComposition / AVMutableVideoComposition 。

AVVideoComposition / AVMutableVideoComposition 对两个或多个视频轨道组合在一起的方法给出了一个总体描述。它由一组时间范围和描述组合行为的介绍内容组成。这些信息出现在组合资源内的任意时间点。

AVVideoComposition / AVMutableVideoComposition 管理所有视频轨道,可以决定最终视频的尺寸,裁剪需要在这里进行;


5.AVMutableCompositionTrack

多个 AVAsset 集合到一起合成新视频中轨道信息,有音频轨、视频轨等,里面可以插入各种对应的素材(画中画,水印等);


6.AVMutableVideoCompositionLayerInstruction

AVMutableVideoCompositionLayerInstruction 主要用于对视频轨道中的一个视频处理缩放、模糊、裁剪、旋转等;


7.AVMutableVideoCompositionInstruction

表示一个指令,决定一个 timeRange 内每个轨道的状态,每一个指令包含多个 AVMutableVideoCompositionLayerInstruction ;而 AVVideoComposition 由多个 AVVideoCompositionInstruction 构成;

AVVideoCompositionInstruction 所提供的最关键的一段数据是组合对象时间轴内的时间范围信息。这一时间范围是在某一组合形式出现时的时间范围。要执行的组全特质是通过其 AVMutableVideoCompositionLayerInstruction 集合定义的。


8.AVAssetExportSession

AVAssetExportSession 主要用于导出视频;


二.AVAssetImageGenerator 简介

AVAssetImageGenerator 是用来提供视频的缩略图或预览视频的帧的类.可以用AVAsset 来初始化,例如:


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

注意 NSURL 的使用:

[NSURL URLWithString:@"网络路径"]
[NSURL fileURLWithPath:@"本地路径"]
如果读取的是本地文件,那么请用第二个方法,第一个会出错,读取不到URL.

1.精确时间截图

生成图片的真正时间可能在 requestedTimeToleranceBefore  和 requestedTimeToleranceAfter 之间,也可能和请求时间无关,需要做如下设置:

//防止时间出现偏差

imageGenerator.requestedTimeToleranceBefore = kCMTimeZero;

imageGenerator.requestedTimeToleranceAfter = kCMTimeZero;

2.指定截图尺寸

通过 maximumSize 指定截图画面的大小,如果不设置,默认就是原始视频画面大小

/* Specifies the maximum dimensions for generated image.  Default (CGSizeZero) is the asset's unscaled dimensions.
   AVAssetImageGenerator will scale images such that they fit within the defined bounding box.
   Images will never be scaled up.  The aspect ratio of the scaled image will be defined by the apertureMode property. */

@property (nonatomic) CGSize maximumSize;

三.AVAssetImageGenerator 截图

/******************************************************************************************/
//@Author:猿说编程
//@Blog(个人博客地址): www.codersrc.com
//@File:C语言教程 - AVAssetImageGenerator截图
//@Time:2021/07/29 07:30
//@Motto:不积跬步无以至千里,不积小流无以成江海,程序人生的精彩需要坚持不懈地积累!
/******************************************************************************************/ 


#pragma mark - 获取指定时间画面
- (CGImageRef)loadVideoImage:(NSURL*)path startTime:(CMTime) startTime
{
    NSError *error=nil;
    AVURLAsset *urlAsset=[AVURLAsset assetWithURL:path];
    
    if (!urlAsset)
        return FALSE;
    
    AVAssetImageGenerator *imageGenerator=[AVAssetImageGenerator assetImageGeneratorWithAsset:urlAsset];
    
    //指定截图画面的大小
    //imageGenerator.maximumSize = CGSizeMake(100, 100);
    
    //精确时间获取画面
    imageGenerator.requestedTimeToleranceAfter = kCMTimeZero;
    imageGenerator.requestedTimeToleranceBefore = kCMTimeZero;
    
    CMTime actualTime;
    CGImageRef cgImage = [imageGenerator copyCGImageAtTime:startTime actualTime:&actualTime error:&error];
    if (error)
    {
        return FALSE;
    }
    return cgImage;
}

//调用
NSURL* url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"123.mp4" ofType:nil]];
CGImageRef image = [self loadVideoImage:url startTime:CMTimeMake(600, 60)];     //第10秒
CGImageRef image2 = [self loadVideoImage:url startTime:CMTimeMake(36000, 60)];  //第600秒

CMTime可以这么理解:CMTimeMake(a ,b),其中 a / b 就是当前的秒数

CMTime CMTimeMake(
	int64_t value,		// 值
	int32_t timescale, 	/// 时间刻度
)

四.AVAssetImageGenerator 获取多帧图片

AVAssetImageGenerator 根据多个 CMTime 对象转化为 NSValue, 用数组包装传进去,然后根据传进去的NSValue个数进行回调, 回调的次数等于 NSValue 的个数;

/******************************************************************************************/
//@Author:猿说编程
//@Blog(个人博客地址): www.codersrc.com
//@File:C语言教程 - AVAssetImageGenerator 获取多帧图片
//@Time:2021/07/29 07:30
//@Motto:不积跬步无以至千里,不积小流无以成江海,程序人生的精彩需要坚持不懈地积累!
/******************************************************************************************/ 


- (BOOL)useAVAssetImageGenerator
{
    NSURL* url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"123.mp4" ofType:nil]];
    
    AVURLAsset* asset = [[AVURLAsset alloc] initWithURL:url options:nil];
    
    //获取媒体时间
    CMTime duration = asset.duration;
    
    //创建 AVAssetImageGenerator
    AVAssetImageGenerator* imageGenerator = [AVAssetImageGenerator assetImageGeneratorWithAsset:asset];
    
    NSMutableArray *times = [NSMutableArray array];
    CMTimeValue increment = duration.value / 20;
    CMTimeValue currentValue = 2.0 * duration.timescale;
    
    //构造时间数组
    while (currentValue <= duration.value) {
        CMTime time = CMTimeMake(currentValue, duration.timescale);
        [times addObject:[NSValue valueWithCMTime:time]];
            currentValue += increment;
    }
        
    __block NSUInteger imageCount = times.count;                            
    __block NSMutableArray *images = [NSMutableArray array];
    
    //保存截图后的数据
    AVAssetImageGeneratorCompletionHandler handler = ^(CMTime requestedTime,
                    CGImageRef imageRef,
                    CMTime actualTime,
                    AVAssetImageGeneratorResult result,
                    NSError *error) {
            
            if (result == AVAssetImageGeneratorSucceeded) {                     
                UIImage *image = [UIImage imageWithCGImage:imageRef];
                
                [images addObject:image];
                NSLog(@"%@", image);
            } else {
                NSLog(@"Error: %@", [error localizedDescription]);
            }
            
            // If the decremented image count is at 0, we're all done.
            if (--imageCount == 0) {                                            
                dispatch_async(dispatch_get_main_queue(), ^{
                    //获取完毕, 作出相应的操作
                    NSLog(@"截图完成....");
                });
            }
        };
        
    //异步处理截图
    [imageGenerator generateCGImagesAsynchronouslyForTimes:times       
                                                  completionHandler:handler];
    return YES;
}


五.猜你喜欢


推荐文章

发表评论