视频合成
视频合成中依然用到了AVMutableComposition,思路依然很简单,取出视频轨和音频轨数据加入到可变轨道之中。不多说,还是贴代码吧:
NSArray *videosPathArray =@[@"",
@""];
AVMutableComposition *mixComposition = [[AVMutableComposition alloc] init];
AVMutableCompositionTrack *audioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio
preferredTrackID:kCMPersistentTrackID_Invalid];
AVMutableCompositionTrack *videoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo
preferredTrackID:kCMPersistentTrackID_Invalid];
CMTime totalDuration = kCMTimeZero;
for (int i = 0; i < videosPathArray.count; i++) {
NSDictionary* options = @{AVURLAssetPreferPreciseDurationAndTimingKey:@YES
};
//网络视频 URLWithString: 本地视频 fileURLWithPath:
AVURLAsset *asset =[AVURLAsset URLAssetWithURL:[NSURL URLWithString:videosPathArray[i]] options:options];
NSError *erroraudio = nil;
//获取AVAsset中的音频 或者视频
AVAssetTrack *assetAudioTrack = [[asset tracksWithMediaType:AVMediaTypeAudio] firstObject];
//向通道内加入音频或者视频
BOOL ba = [audioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration)
ofTrack:assetAudioTrack
atTime:totalDuration
error:&erroraudio];
NSLog(@"erroraudio:%@%d",erroraudio,ba);
NSError *errorVideo = nil;
AVAssetTrack *assetVideoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] firstObject];
BOOL bl = [videoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration)
ofTrack:assetVideoTrack
atTime:totalDuration
error:&errorVideo];
NSLog(@"errorVideo:%@%d",errorVideo,bl);
totalDuration = CMTimeAdd(totalDuration, asset.duration);
}
LYAVPlayerView *playerView =[[LYAVPlayerView alloc]init];
// CGFloat scale =_composition.naturalSize.width/_composition.naturalSize.height;
playerView.frame =CGRectMake(0,100,ScreenWidth,ScreenHeight-160);
playerView.videoGravity =AVLayerVideoGravityResizeAspect;
[playerView setPlayerItem:[[AVPlayerItem alloc]initWithAsset:mixComposition]];
[self.view addSubview:playerView];
[playerView play];
注:创建AVURLAsset时,如果是本地视频则用fileURLWithPath:
函数,如果是网络视频,则调用URLWithString
函数。多个网络视频合成后,效果就跟播放一个视频一样,用户体验非常不错。CMTimeAdd的用法参考另一篇文章短视频从无到有 (三)CMTime详解。
视频压缩和转换
视频合成后即可导出到本地或者手机相册,思路依然很简单,使用AVAssetExportSession即可。代码如下:
unlink([outPath UTF8String]);
NSURL *compressionFileURL = [NSURL fileURLWithPath:outPath];
if ([[NSFileManager defaultManager] fileExistsAtPath:outPath]) {
[[NSFileManager defaultManager] removeItemAtPath:outPath error:nil];
}
// 创建AVAsset对象
AVAsset* asset = [AVAsset assetWithURL:[NSURL fileURLWithPath:videoPath]];
// 创建AVAssetExportSession对象
AVAssetExportSession * exporter = [[AVAssetExportSession alloc] initWithAsset:asset presetName:presetName];
//优化网络
exporter.shouldOptimizeForNetworkUse = YES;
//设置输出路径
exporter.outputURL =compressionFileURL;
//设置输出类型
exporter.outputFileType = outputFileType;
[exporter exportAsynchronouslyWithCompletionHandler:^{
dispatch_async(dispatch_get_main_queue(), ^{
switch (exporter.status) {
case AVAssetExportSessionStatusFailed:{
if (completeBlock) {
completeBlock(exporter.error,compressionFileURL);
}
break;
}
case AVAssetExportSessionStatusCancelled:{
NSLog(@"Export Status: Cancell");
break;
}
case AVAssetExportSessionStatusCompleted: {
if (completeBlock) {
completeBlock(nil,compressionFileURL);
}
break;
}
case AVAssetExportSessionStatusUnknown: {
NSLog(@"Export Status: Unknown");
break;
}
case AVAssetExportSessionStatusExporting : {
NSLog(@"Export Status: Exporting");
break;
}
case AVAssetExportSessionStatusWaiting: {
NSLog(@"Export Status: Wating");
break;
}
};
});
}];
注:导出过程中设置exporter
的presetName(分辨率)
和outputFileType(视频封装格式)
即可完成视频转换和压缩。当然,更深层次的处理靠这些是远远不够的,还要依靠更多的框架来处理,譬如ffmpeg
等,这些以后再做讨论,今儿就先到这。