AVAssetExportSession 音视频的剪辑,以及格式的装换

Stella981
• 阅读 166

//第一种方式

//asset生成必须为文件的url,而且是本地

AVAsset *mediaAsset = _player.currentItem.asset;

//AVMutableComposition 可以进行音视频的组合

AVAssetExportSession *es = [[AVAssetExportSession alloc] initWithAsset:mediaAsset presetName:AVAssetExportPresetPassthrough];

NSString *outPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"out.mov"];

NSFileManager *fileManager = [NSFileManager defaultManager];

[fileManager removeItemAtPath:outPath error:NULL];

//格式的转换

es.outputFileType = AVFileTypeQuickTimeMovie;

es.outputURL = [[NSURL alloc] initFileURLWithPath:outPath];

es.shouldOptimizeForNetworkUse=NO;

CMTime start = CMTimeMakeWithSeconds(1.0, 600);

CMTime duration = CMTimeMakeWithSeconds(3.0, 600);

CMTimeRange range = CMTimeRangeMake(start, duration);

//音频的时间范围

es.timeRange = range;

NSLog(@"exporting to %@",outPath);

//异步输出完成后调用

[es exportAsynchronouslyWithCompletionHandler:^{

NSString *status = @"" ;

if( es.status == AVAssetExportSessionStatusCompleted ) status = @"AVAssetExportSessionStatusCompleted";

else if( es.status == AVAssetExportSessionStatusFailed ) status = @"AVAssetExportSessionStatusFailed";

NSLog(@"done exporting to %@ status %d = %@ (%@)",outPath,es.status, status,[es error]);

}];

//第二种方式读取本地到另外一个地方

NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];

NSString *audioPath = [documentPath stringByAppendingPathComponent:[NSString stringWithFormat:@"audio"]];

NSURL *fileUrl = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/1141.mp3",audioPath]];

AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:fileUrl options:nil];

NSError *error = nil;

NSArray *array=[_player.currentItem.asset tracksWithMediaType:AVMediaTypeAudio];

AVAssetTrack *track=[[_player.currentItem.asset tracksWithMediaType:AVMediaTypeAudio]firstObject];

NSLog(@"%@",_player.currentItem.asset);

assetReader=[[AVAssetReader alloc]initWithAsset:_player.currentItem.asset error:&error];

NSDictionary *readerOutputSettings=@{(id)AVFormatIDKey:@(kAudioFormatLinearPCM)};

//如果读取失败接下来的代码不会执行。

AVAssetReaderTrackOutput *trackOutput=[[AVAssetReaderTrackOutput alloc]initWithTrack:track outputSettings:readerOutputSettings];

[assetReader addOutput:trackOutput];

//先判断read为YES

BOOL read= [assetReader startReading];

NSString *userPath = [audioPath stringByAppendingPathComponent:[NSString stringWithFormat:@"/writer1.wav"]];

NSURL *outputURL=[NSURL fileURLWithPath:userPath];

assetWriter=[[AVAssetWriter alloc]initWithURL:outputURL fileType:AVFileTypeWAVE error:nil];

AudioChannelLayout channelLayout;

memset(&channelLayout, 0, sizeof(AudioChannelLayout));

channelLayout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;

//lin PCM需要设置PCM一些相关的属性

NSDictionary *writerOutputSetting=@{(id)AVFormatIDKey:@(kAudioFormatLinearPCM),(id)AVSampleRateKey:[NSNumber numberWithFloat:44100.0],AVNumberOfChannelsKey:[NSNumber numberWithInt: 2],AVLinearPCMBitDepthKey:[NSNumber numberWithInt:16],

AVLinearPCMIsNonInterleaved:[NSNumber numberWithBool:NO],

AVLinearPCMIsFloatKey:[NSNumber numberWithBool:NO],

AVLinearPCMIsBigEndianKey:[NSNumber numberWithBool:NO],AVChannelLayoutKey:[ NSData dataWithBytes:&channelLayout length: sizeof( AudioChannelLayout ) ]};

AVAssetWriterInput *writerInput=[[AVAssetWriterInput alloc]initWithMediaType:AVMediaTypeAudio outputSettings:writerOutputSetting];

[assetWriter addInput:writerInput];

BOOL writer=[assetWriter startWriting];

dispatch_queue_t dispatchQueue=dispatch_queue_create("com/tapharmonic.WriterQueue", NULL);

[assetWriter startSessionAtSourceTime:kCMTimeZero];

[writerInput requestMediaDataWhenReadyOnQueue:dispatchQueue usingBlock:^{

bool complete=NO;

while ([writerInput isReadyForMoreMediaData]&& !complete) {

NSLog(@"%@",assetWriter.error);

CMSampleBufferRef sampleBuffer=[trackOutput copyNextSampleBuffer];

if(sampleBuffer){

BOOL result=[writerInput appendSampleBuffer:sampleBuffer];

CFRelease(sampleBuffer);

complete=!result;

}else{

[writerInput markAsFinished];

complete=YES;

}

}

if(complete){

[assetWriter finishWritingWithCompletionHandler:^{

AVAssetWriterStatus status=assetWriter.status;

NSLog(@"%@",assetWriter.error);

if(status==AVAssetWriterStatusCompleted){

NSLog(@"AVAssetWriterStatusCompleted");

}else{

NSLog(@"AVAssetWriterStatusFailed");

}

}];

}

}];

AVAssetExportSession你可以取消这个生成操作,通过给session发送 cancelExport 消息。

失败原因:
· 如果导出的文件存在,或者导出的url在沙盒之外,这个导出操作会失败。
· 来了一个电话
· 你的程序在后台运行并且其他的应用开始播放。
这种情况下,你应该通知用户export失败,并且重新export。

点赞
收藏
评论区
推荐文章
秃头王路飞 秃头王路飞
4个月前
webpack5手撸vue2脚手架
webpack5手撸vue相信工作个12年的小伙伴们在面试的时候多多少少怕被问到关于webpack方面的知识,本菜鸟最近闲来无事,就尝试了手撸了下vue2的脚手架,第一次发帖实在是没有经验,望海涵。languageJavaScript"name":"vuecliversion2","version":"1.0.0","desc
光头强的博客 光头强的博客
4个月前
Java面向对象试题
1、请创建一个Animal动物类,要求有方法eat()方法,方法输出一条语句“吃东西”。创建一个接口A,接口里有一个抽象方法fly()。创建一个Bird类继承Animal类并实现接口A里的方法输出一条有语句“鸟儿飞翔”,重写eat()方法输出一条语句“鸟儿吃虫”。在Test类中向上转型创建b对象,调用eat方法。然后向下转型调用eat()方
刚刚好 刚刚好
4个月前
css问题
1、在IOS中图片不显示(给图片加了圆角或者img没有父级)<div<imgsrc""/</divdiv{width:20px;height:20px;borderradius:20px;overflow:h
blmius blmius
1年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
小森森 小森森
4个月前
校园表白墙微信小程序V1.0 SayLove -基于微信云开发-一键快速搭建,开箱即用
后续会继续更新,敬请期待2.0全新版本欢迎添加左边的微信一起探讨!项目地址:(https://www.aliyun.com/activity/daily/bestoffer?userCodesskuuw5n)\2.Bug修复更新日历2.情侣脸功能大家不要使用了,现在阿里云的接口已经要收费了(土豪请随意),\\和注意
晴空闲云 晴空闲云
4个月前
css中box-sizing解放盒子实际宽高计算
我们知道传统的盒子模型,如果增加内边距padding和边框border,那么会撑大整个盒子,造成盒子的宽度不好计算,在实务中特别不方便。boxsizing可以设置盒模型的方式,可以很好的设置固定宽高的盒模型。盒子宽高计算假如我们设置如下盒子:宽度和高度均为200px,那么这会这个盒子实际的宽高就都是200px。但是当我们设置这个盒子的边框和内间距的时候,那
艾木酱 艾木酱
3个月前
快速入门|使用MemFire Cloud构建React Native应用程序
MemFireCloud是一款提供云数据库,用户可以创建云数据库,并对数据库进行管理,还可以对数据库进行备份操作。它还提供后端即服务,用户可以在1分钟内新建一个应用,使用自动生成的API和SDK,访问云数据库、对象存储、用户认证与授权等功能,可专
NVIDIA安培架构下MIG技术分析
关键词:NVIDIA、MIG、安培一什么是MIG2020年5月,NVIDIA发布了最新的GPU架构:安培,以及基于安培架构的最新的GPU:A100。安培提供了许多新的特性,MIG是其中一项非常重要的新特性。MIG的全名是MultiInstanceGPU。NVIDIA安培架构中的MIG模式可以在A100GPU上并行运行七个作业。多实
helloworld_34035044 helloworld_34035044
7个月前
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
helloworld_28799839 helloworld_28799839
4个月前
常用知识整理
Javascript判断对象是否为空jsObject.keys(myObject).length0经常使用的三元运算我们经常遇到处理表格列状态字段如status的时候可以用到vue