零基础 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
AVMutableCompositionTrack 是将多个 AVAsset 集合到一起合成新视频中轨道信息,有音频轨、视频轨等,里面可以插入各种对应的素材(画中画,水印等);
6.AVMutableVideoCompositionLayerInstruction
AVMutableVideoCompositionLayerInstruction 主要用于对视频轨道中的一个视频处理缩放、模糊、裁剪、旋转等;
7.AVMutableVideoCompositionInstruction
表示一个指令,决定一个 timeRange 内每个轨道的状态,每一个指令包含多个 AVMutableVideoCompositionLayerInstruction ;而 AVVideoComposition 由多个 AVVideoCompositionInstruction 构成;
AVVideoCompositionInstruction 所提供的最关键的一段数据是组合对象时间轴内的时间范围信息。这一时间范围是在某一组合形式出现时的时间范围。要执行的组全特质是通过其 AVMutableVideoCompositionLayerInstruction 集合定义的。
8.AVAssetExportSession
AVAssetExportSession 主要用于导出视频;
9.AVAssetTrackSegment
AVAssetTrackSegment 不可变轨道片段;
10.AVCompositionTrackSegment
AVCompositionTrackSegment 可变轨道片段,继承自 AVAssetTrackSegment;
二.AVFoundation指定时间截取音视频
为了避免导出失败,解决方案是提取视频资源 AVURLAsset 音频轨道和视频轨道,重新构建 AVComposition ,然后在使用 AVAssetExportSession 导出;
1.音视频截取流程
AVMutableComposition *mutableComposition = [AVMutableComposition composition];//进行添加资源等操作//1.添加媒体1的视频轨道(设置需要截取的时间段)//2.添加媒体1的音频轨道(设置需要截取的时间段)//.....//使用可变的 composition 生成一个不可变的 composition 以供使用AVComposition *composition = [myMutableComposition copy];//导出AVMutableComposition *mutableComposition = [AVMutableComposition composition]; //进行添加资源等操作 //1.添加媒体1的视频轨道(设置需要截取的时间段) //2.添加媒体1的音频轨道(设置需要截取的时间段) //..... //使用可变的 composition 生成一个不可变的 composition 以供使用 AVComposition *composition = [myMutableComposition copy]; //导出AVMutableComposition *mutableComposition = [AVMutableComposition composition]; //进行添加资源等操作 //1.添加媒体1的视频轨道(设置需要截取的时间段) //2.添加媒体1的音频轨道(设置需要截取的时间段) //..... //使用可变的 composition 生成一个不可变的 composition 以供使用 AVComposition *composition = [myMutableComposition copy]; //导出
2.音视频截取实战
![图片[1]-AVFoundation – 指定时间截取音视频-猿说编程](https://www.codersrc.com/wp-content/uploads/2021/09/0bc7d3b783c12d7.png)
举个栗子:一个21秒的视频,我们截取5-15秒,并导出这个10秒的视频,示例代码如下:
/******************************************************************************************///@Author:猿说编程//@Blog(个人博客地址): www.codersrc.com//@File:AVFoundation - 指定时间截取音视频//@Time:2021/09/05 07:30//@Motto:不积跬步无以至千里,不积小流无以成江海,程序人生的精彩需要坚持不懈地积累!/******************************************************************************************/#import "ViewController.h"#import <AVFoundation/AVFoundation.h>#import <AVKit/AVKit.h>#pragma mark - 截取视频-(void)cutVideo:(NSString*)srcPath outPath:(NSString*)outPath timeRange:(CMTimeRange)timeRange{AVAsset* asset = [AVAsset assetWithURL:[NSURL URLWithString:srcPath]];[asset loadValuesAsynchronouslyForKeys:@[@"tracks"] completionHandler:^{NSError *error = nil;AVKeyValueStatus status = [asset statusOfValueForKey:@"tracks" error:&error];if (status != AVKeyValueStatusLoaded) {NSLog(@"loaded error %@",error);return;}// 获取容器中的音视频轨道对象AVAssetTrack* videoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];AVAssetTrack* audioTrack = [[asset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];// 划定要截取的时间;这里选择的时间为5-15秒的视频CMTimeRange range = timeRange;// 创建组合对象AVMutableComposition *compostion = [AVMutableComposition composition];if (audioTrack) {// 添加组合音频轨道AVMutableCompositionTrack *audiocomtrack = [compostion addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];NSError *error = nil;// 在音频轨道中选取指定的时间范围的音频插入到组合音频轨道中[audiocomtrack insertTimeRange:range ofTrack:audioTrack atTime:kCMTimeZero error:&error];}if (videoTrack) {AVMutableCompositionTrack *videocomtrack = [compostion addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];NSError *error = nil;[videocomtrack insertTimeRange:range ofTrack:videoTrack atTime:kCMTimeZero error:&error];}// 执行合并if ([[NSFileManager defaultManager] fileExistsAtPath:outPath]) {[[NSFileManager defaultManager] removeItemAtURL:[NSURL fileURLWithPath:outPath] error:nil];}// 执行组合对象中组合轨道的编辑任务AVAssetExportSession *extSession = [[AVAssetExportSession alloc] initWithAsset:compostion presetName:AVAssetExportPresetHighestQuality];extSession.outputURL = [NSURL fileURLWithPath:outPath];extSession.outputFileType = AVFileTypeMPEG4;NSLog(@"开始编辑");[extSession exportAsynchronouslyWithCompletionHandler:^{if (extSession.status != AVAssetExportSessionStatusCompleted) {NSLog(@"编辑 error %@",extSession.error);}NSLog(@"编辑完毕");[self performSelectorOnMainThread:@selector(playVideoWithUrl:) withObject:[NSURL fileURLWithPath:outPath] waitUntilDone:NO];// [self playVideoWithUrl:[NSURL fileURLWithPath:outPath]];}];}];}#pragma mark - 获取Documents目录-(NSString *)dirDoc{return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];}#pragma mark - 播放导出的视频-(void)playVideoWithUrl:(NSURL *)url{AVPlayerViewController *playerViewController = [[AVPlayerViewController alloc]init];playerViewController.player = [[AVPlayer alloc]initWithURL:url];playerViewController.view.frame = self.view.frame;playerViewController.view.layer.backgroundColor = [UIColor redColor].CGColor;[playerViewController.player play];[self presentViewController:playerViewController animated:YES completion:nil];}@end/******************************************************************************************/ //@Author:猿说编程 //@Blog(个人博客地址): www.codersrc.com //@File:AVFoundation - 指定时间截取音视频 //@Time:2021/09/05 07:30 //@Motto:不积跬步无以至千里,不积小流无以成江海,程序人生的精彩需要坚持不懈地积累! /******************************************************************************************/ #import "ViewController.h" #import <AVFoundation/AVFoundation.h> #import <AVKit/AVKit.h> #pragma mark - 截取视频 -(void)cutVideo:(NSString*)srcPath outPath:(NSString*)outPath timeRange:(CMTimeRange)timeRange { AVAsset* asset = [AVAsset assetWithURL:[NSURL URLWithString:srcPath]]; [asset loadValuesAsynchronouslyForKeys:@[@"tracks"] completionHandler:^{ NSError *error = nil; AVKeyValueStatus status = [asset statusOfValueForKey:@"tracks" error:&error]; if (status != AVKeyValueStatusLoaded) { NSLog(@"loaded error %@",error); return; } // 获取容器中的音视频轨道对象 AVAssetTrack* videoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; AVAssetTrack* audioTrack = [[asset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0]; // 划定要截取的时间;这里选择的时间为5-15秒的视频 CMTimeRange range = timeRange; // 创建组合对象 AVMutableComposition *compostion = [AVMutableComposition composition]; if (audioTrack) { // 添加组合音频轨道 AVMutableCompositionTrack *audiocomtrack = [compostion addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid]; NSError *error = nil; // 在音频轨道中选取指定的时间范围的音频插入到组合音频轨道中 [audiocomtrack insertTimeRange:range ofTrack:audioTrack atTime:kCMTimeZero error:&error]; } if (videoTrack) { AVMutableCompositionTrack *videocomtrack = [compostion addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; NSError *error = nil; [videocomtrack insertTimeRange:range ofTrack:videoTrack atTime:kCMTimeZero error:&error]; } // 执行合并 if ([[NSFileManager defaultManager] fileExistsAtPath:outPath]) { [[NSFileManager defaultManager] removeItemAtURL:[NSURL fileURLWithPath:outPath] error:nil]; } // 执行组合对象中组合轨道的编辑任务 AVAssetExportSession *extSession = [[AVAssetExportSession alloc] initWithAsset:compostion presetName:AVAssetExportPresetHighestQuality]; extSession.outputURL = [NSURL fileURLWithPath:outPath]; extSession.outputFileType = AVFileTypeMPEG4; NSLog(@"开始编辑"); [extSession exportAsynchronouslyWithCompletionHandler:^{ if (extSession.status != AVAssetExportSessionStatusCompleted) { NSLog(@"编辑 error %@",extSession.error); } NSLog(@"编辑完毕"); [self performSelectorOnMainThread:@selector(playVideoWithUrl:) withObject:[NSURL fileURLWithPath:outPath] waitUntilDone:NO]; // [self playVideoWithUrl:[NSURL fileURLWithPath:outPath]]; }]; }]; } #pragma mark - 获取Documents目录 -(NSString *)dirDoc{ return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]; } #pragma mark - 播放导出的视频 -(void)playVideoWithUrl:(NSURL *)url{ AVPlayerViewController *playerViewController = [[AVPlayerViewController alloc]init]; playerViewController.player = [[AVPlayer alloc]initWithURL:url]; playerViewController.view.frame = self.view.frame; playerViewController.view.layer.backgroundColor = [UIColor redColor].CGColor; [playerViewController.player play]; [self presentViewController:playerViewController animated:YES completion:nil]; } @end/******************************************************************************************/ //@Author:猿说编程 //@Blog(个人博客地址): www.codersrc.com //@File:AVFoundation - 指定时间截取音视频 //@Time:2021/09/05 07:30 //@Motto:不积跬步无以至千里,不积小流无以成江海,程序人生的精彩需要坚持不懈地积累! /******************************************************************************************/ #import "ViewController.h" #import <AVFoundation/AVFoundation.h> #import <AVKit/AVKit.h> #pragma mark - 截取视频 -(void)cutVideo:(NSString*)srcPath outPath:(NSString*)outPath timeRange:(CMTimeRange)timeRange { AVAsset* asset = [AVAsset assetWithURL:[NSURL URLWithString:srcPath]]; [asset loadValuesAsynchronouslyForKeys:@[@"tracks"] completionHandler:^{ NSError *error = nil; AVKeyValueStatus status = [asset statusOfValueForKey:@"tracks" error:&error]; if (status != AVKeyValueStatusLoaded) { NSLog(@"loaded error %@",error); return; } // 获取容器中的音视频轨道对象 AVAssetTrack* videoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; AVAssetTrack* audioTrack = [[asset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0]; // 划定要截取的时间;这里选择的时间为5-15秒的视频 CMTimeRange range = timeRange; // 创建组合对象 AVMutableComposition *compostion = [AVMutableComposition composition]; if (audioTrack) { // 添加组合音频轨道 AVMutableCompositionTrack *audiocomtrack = [compostion addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid]; NSError *error = nil; // 在音频轨道中选取指定的时间范围的音频插入到组合音频轨道中 [audiocomtrack insertTimeRange:range ofTrack:audioTrack atTime:kCMTimeZero error:&error]; } if (videoTrack) { AVMutableCompositionTrack *videocomtrack = [compostion addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; NSError *error = nil; [videocomtrack insertTimeRange:range ofTrack:videoTrack atTime:kCMTimeZero error:&error]; } // 执行合并 if ([[NSFileManager defaultManager] fileExistsAtPath:outPath]) { [[NSFileManager defaultManager] removeItemAtURL:[NSURL fileURLWithPath:outPath] error:nil]; } // 执行组合对象中组合轨道的编辑任务 AVAssetExportSession *extSession = [[AVAssetExportSession alloc] initWithAsset:compostion presetName:AVAssetExportPresetHighestQuality]; extSession.outputURL = [NSURL fileURLWithPath:outPath]; extSession.outputFileType = AVFileTypeMPEG4; NSLog(@"开始编辑"); [extSession exportAsynchronouslyWithCompletionHandler:^{ if (extSession.status != AVAssetExportSessionStatusCompleted) { NSLog(@"编辑 error %@",extSession.error); } NSLog(@"编辑完毕"); [self performSelectorOnMainThread:@selector(playVideoWithUrl:) withObject:[NSURL fileURLWithPath:outPath] waitUntilDone:NO]; // [self playVideoWithUrl:[NSURL fileURLWithPath:outPath]]; }]; }]; } #pragma mark - 获取Documents目录 -(NSString *)dirDoc{ return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]; } #pragma mark - 播放导出的视频 -(void)playVideoWithUrl:(NSURL *)url{ AVPlayerViewController *playerViewController = [[AVPlayerViewController alloc]init]; playerViewController.player = [[AVPlayer alloc]initWithURL:url]; playerViewController.view.frame = self.view.frame; playerViewController.view.layer.backgroundColor = [UIColor redColor].CGColor; [playerViewController.player play]; [self presentViewController:playerViewController animated:YES completion:nil]; } @end
![图片[2]-AVFoundation – 指定时间截取音视频-猿说编程](https://www.codersrc.com/wp-content/uploads/2021/09/c68271a63ddbc43.gif)
温馨提示:上面工程源码可通过网站右上角《立即购买》获取下载地址即可!
三.猜你喜欢
- AVAsset 加载媒体
- AVAssetTrack 获取视频 音频信息
- AVMetadataItem 获取媒体属性元数据
- AVAssetImageGenerator 截图
- AVAssetImageGenerator 获取多帧图片
- AVAssetExportSession 裁剪/转码
- AVPlayer 播放视频
- AVPlayerItem 管理资源对象
- AVPlayerLayer 显示视频
- AVQueuePlayer 播放多个媒体文件
- AVComposition AVMutableComposition 将多个媒体合并
- AVVideoComposition AVMutableVideoComposition 管理所有视频轨道
- AVCompositionTrack AVMutableCompositionTrack 添加移除缩放媒体音视频轨道信息
- AVAssetTrackSegment 不可变轨道片段
- AVCompositionTrackSegment 可变轨道片段
- AVVideoCompositionInstruction AVMutableVideoCompositionInstruction 操作指令
- AVMutableVideoCompositionLayerInstruction 视频轨道操作指令
- AVFoundation – 将多个媒体合并(二) – 一个轨道多个视频无缝衔接
- AVFoundation – 将多个媒体合并(三) – 多个轨道,每个轨道对应一个单独的音频或者视频
- AVFoundation – 将多个媒体合并(四) – 不同分辨率媒体合成并自定义分辨率
- AVFoundation – 指定时间截取音视频
ChatGPT 3.5 国内中文镜像站免费使用啦
暂无评论内容