iOS开发

iOS 本地多个短视频合成

2019-12-21  本文已影响0人  神奇李白

自己遇到的坑:

1.视频和音频需要分开合成;

2.竖屏拍摄的视频,合成后改变了方向, 只好自己更改方向

实现步骤:
在.h中添加合成时需要调用的方法

//多个分段视频合成 
/*
array为本地保存的短视频数组,元素为NSURL类型 比如:

file:///var/mobile/Containers/Data/Application/BBF38CEF-BB5D-40BA-82D5-4A9508BEA4F9/Library/Caches/我的短视频/video_0.mov,

file:///var/mobile/Containers/Data/Application/BBF38CEF-BB5D-40BA-82D5-4A9508BEA4F9/Library/Caches/我的短视频/video_1.mov
*/
- (void)synthesisMedia:(NSMutableArray *)array;

在.m中添加

#import <AVFoundation/AVFoundation.h>
#define ShootVideoPath @"录制视频"
#define ShootVideoName @"我的短视频"
-(AVMutableComposition *)mergeVideostoOnevideo:(NSArray*)array{
    AVMutableComposition* mixComposition = [AVMutableComposition composition];
    //视频通道
    AVMutableCompositionTrack *compositionVideoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
    //音频通道
    AVMutableCompositionTrack *compositionAudioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
    Float64 tmpDuration =0.0f;
    //合成视频
    for (NSInteger i=0; i<array.count; i++){
        AVURLAsset *videoAsset = [[AVURLAsset alloc]initWithURL:array[i] options:nil];
        CMTime time = [videoAsset duration];
        NSInteger seconds = ceil(time.value/time.timescale);
        NSLog(@"第%ld个视频时长 = %ld",i,seconds);
        //视频采集
        CMTimeRange timeRange = CMTimeRangeMake(kCMTimeZero,videoAsset.duration);
        NSError *error;
        //合成视频
        [compositionVideoTrack insertTimeRange:timeRange ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] atTime:CMTimeMakeWithSeconds(tmpDuration, 0) error:&error];
        //合成音频
        [compositionAudioTrack insertTimeRange:timeRange ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] atTime:CMTimeMakeWithSeconds(tmpDuration, 0) error:&error];
        
        tmpDuration = CMTimeGetSeconds(videoAsset.duration) + tmpDuration;
    }
    
    
    //竖屏录制的视频,合成后会改变方向。所以手动转了一下
    compositionVideoTrack.preferredTransform =  CGAffineTransformMakeRotation(M_PI/2);
     
    return mixComposition;
//分段多个视频 进行合成
- (void)synthesisMedia:(NSMutableArray *)array{
    AVMutableComposition *mixComposition = [self mergeVideostoOnevideo:array];
    AVAssetExportSession* assetExport = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetMediumQuality];
    assetExport.outputFileType = AVFileTypeMPEG4;
    NSURL *filUrl = [self getVideosURLPath:ShootVideoName];//自定义的输出路径
    assetExport.outputURL = filUrl;//视频的输出路径
    assetExport.shouldOptimizeForNetworkUse = YES;
    //视频合成
    [assetExport exportAsynchronouslyWithCompletionHandler:^{
        //回到主线程
        dispatch_async(dispatch_get_main_queue(), ^{
            AVURLAsset *videoAsset = [[AVURLAsset alloc]initWithURL:filUrl options:nil];
            CMTime time = [videoAsset duration];
            NSInteger seconds = ceil(time.value/time.timescale);
    
            //在系统相册存储一份(需要开启相册的权限,不然闪退)
            //UISaveVideoAtPathToSavedPhotosAlbum([filUrl path], nil, nil, nil);
           //!!filUrl为视频的输出路径!!
        });
      
    }];
}
//拼接输出路径
- (NSURL *)getVideosURLPath:(NSString *)videoName{
    NSString *documents = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];
    documents = [documents stringByAppendingPathComponent:ShootVideoPath];
    documents = [self action_addFiles:documents];//新建文件并返回地址
    NSString *failPath = [documents stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.mp4",videoName]];
    NSURL *filUrl = [NSURL fileURLWithPath:failPath];
    return filUrl;
}
//新建文件并返回地址
- (NSString *)action_addFiles:(NSString *)path{
    if ([[NSFileManager defaultManager] fileExistsAtPath:path]) {
        //文件夹已存在
    } else {
        //创建文件夹
        [[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil];
    }
    return path;
}

上一篇下一篇

猜你喜欢

热点阅读