美文网首页iOS程序猿程序员
短视频从无到有 (六)视频合成及压缩、转换格式

短视频从无到有 (六)视频合成及压缩、转换格式

作者: 卢叁 | 来源:发表于2018-07-23 16:52 被阅读4次

视频合成

视频合成中依然用到了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;
                }
                    
            };
            
        });
        
    }];

注:导出过程中设置exporterpresetName(分辨率)outputFileType(视频封装格式)即可完成视频转换和压缩。当然,更深层次的处理靠这些是远远不够的,还要依靠更多的框架来处理,譬如ffmpeg等,这些以后再做讨论,今儿就先到这。

相关文章

网友评论

    本文标题:短视频从无到有 (六)视频合成及压缩、转换格式

    本文链接:https://www.haomeiwen.com/subject/exyjmftx.html