美文网首页
视频合成、拼接(尚未整理版,不过感觉这个写的不错,先拿过来,后续

视频合成、拼接(尚未整理版,不过感觉这个写的不错,先拿过来,后续

作者: coding_Liu | 来源:发表于2016-12-30 10:10 被阅读272次
    798158-20160613162318635-2146741413.png

    上面的图说明的是这个混合的过程,下面放代码:

    - (void)mergeAndExportVideos:(NSArray*)videosPathArray withOutPath:(NSString*)outpath{
        if (videosPathArray.count == 0) {
            return;
        }
        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++) {
            AVURLAsset *asset = [AVURLAsset assetWithURL:[NSURL fileURLWithPath:videosPathArray[i]]];
            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);
        }
        NSLog(@"%@",NSHomeDirectory());
        
            NSURL *mergeFileURL = [NSURL fileURLWithPath:outpath];
        AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:mixComposition
                                                                          presetName:AVAssetExportPreset640x480];
        exporter.outputURL = mergeFileURL;
        exporter.outputFileType = AVFileTypeMPEG4;
        exporter.shouldOptimizeForNetworkUse = YES;
        [exporter exportAsynchronouslyWithCompletionHandler:^{
            NSLog(@"exporter%@",exporter.error);
        }];
    

    下面是方法详解:

    - (AVMutableCompositionTrack *)addMutableTrackWithMediaType:(NSString *)mediaType preferredTrackID:(CMPersistentTrackID)preferredTrackID;```
    参数:
    
    mediaType          :数据类型  AVMediaTypeVideo 视频   AVMediaTypeAudio  音频
    
    preferredTrackID :可自由设定 但建议kCMPersistentTrackID_Invalid也就是0
    

    //向通道内加入音频或者视频

    • (BOOL)insertTimeRange:(CMTimeRange)timeRange ofTrack:(AVAssetTrack *)track atTime:(CMTime)startTime error:(NSError * __nullable * __nullable)outError;```
      参数:

    timeRange: 插入视频/音频的的时间段

    track :插入的视频/音频

    - (void)startExportVideoWithVideoAsset:(AVURLAsset *)videoAsset completion:(void (^)(NSString *outputPath))completion {
        // Find compatible presets by video asset.
    //    NSArray *presets = [AVAssetExportSession exportPresetsCompatibleWithAsset:videoAsset];
        
        // Begin to compress video
        // Now we just compress to low resolution if it supports
        // If you need to upload to the server, but server does't support to upload by streaming,
        // You can compress the resolution to lower. Or you can support more higher resolution.
    //    if ([presets containsObject:AVAssetExportPreset640x480]) {
        // 新增
        int degress = [self degressFromVideoFileWithAsset:videoAsset];
        AVAssetExportSession *session = nil;
        if (degress != 0) {
            AVMutableComposition* composition = [AVMutableComposition composition];
            
            AVAssetTrack *sourceAudioTrack = [[videoAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
            AVMutableCompositionTrack *compositionAudioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio
                                                                                        preferredTrackID:kCMPersistentTrackID_Invalid];
            
            [compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration)
                                           ofTrack:sourceAudioTrack
                                            atTime:kCMTimeZero error:nil];
            
            session = [[AVAssetExportSession alloc]initWithAsset:composition presetName:AVAssetExportPresetHighestQuality];
            // 修正视频转向
            BOOL isPortrait_ = [self isVideoPortrait:videoAsset];
            session.videoComposition = [self getVideoComposition:videoAsset composition:composition withisPortrait:isPortrait_];
        }else{
            session = [[AVAssetExportSession alloc]initWithAsset:videoAsset presetName:AVAssetExportPresetPassthrough];
            
        }
        //
        NSDateFormatter *formater = [[NSDateFormatter alloc] init];
        [formater setDateFormat:@"yyyy-MM-dd-HH:mm:ss"];
        NSString *outputPath = [NSHomeDirectory() stringByAppendingFormat:@"/tmp/output-%@.mp4", [formater stringFromDate:[NSDate date]]];
        session.outputURL = [NSURL fileURLWithPath:outputPath];
        
        // Optimize for network use.
        session.shouldOptimizeForNetworkUse = true;
        
        NSArray *supportedTypeArray = session.supportedFileTypes;
        if ([supportedTypeArray containsObject:AVFileTypeMPEG4]) {
            session.outputFileType = AVFileTypeMPEG4;
        } else if (supportedTypeArray.count == 0) {
            NSLog(@"No supported file types 视频类型暂不支持导出");
            return;
        } else {
            session.outputFileType = [supportedTypeArray objectAtIndex:0];
        }
        
        if (![[NSFileManager defaultManager] fileExistsAtPath:[NSHomeDirectory() stringByAppendingFormat:@"/tmp"]]) {
            [[NSFileManager defaultManager] createDirectoryAtPath:[NSHomeDirectory() stringByAppendingFormat:@"/tmp"] withIntermediateDirectories:YES attributes:nil error:nil];
        }
        // Begin to export video to the output path asynchronously.
        [session exportAsynchronouslyWithCompletionHandler:^(void) {
            switch (session.status) {
                case AVAssetExportSessionStatusUnknown:
                    NSLog(@"AVAssetExportSessionStatusUnknown"); break;
                case AVAssetExportSessionStatusWaiting:
                    NSLog(@"AVAssetExportSessionStatusWaiting"); break;
                case AVAssetExportSessionStatusExporting:
                    NSLog(@"AVAssetExportSessionStatusExporting"); break;
                case AVAssetExportSessionStatusCompleted: {
                    NSLog(@"AVAssetExportSessionStatusCompleted");
                    dispatch_async(dispatch_get_main_queue(), ^{
                        if (completion) {
                            completion(outputPath);
                        }
                    });
                }  break;
                case AVAssetExportSessionStatusFailed:{
                    dispatch_async(dispatch_get_main_queue(), ^{
                        if (completion) {
                            completion(nil);
                        }
                    });
                    NSLog(@"AVAssetExportSessionStatusFailed"); break;
                }
                default: break;
            }
        }];
    //    }
    }
    -(AVMutableVideoComposition *) getVideoComposition:(AVAsset *)asset composition:( AVMutableComposition*)composition withisPortrait:(BOOL) isPortrait{
        BOOL isPortrait_ = isPortrait;
        
        
        AVMutableCompositionTrack *compositionVideoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
        
        
        AVAssetTrack *videoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
        [compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration) ofTrack:videoTrack atTime:kCMTimeZero error:nil];
        
        AVMutableVideoCompositionLayerInstruction *layerInst = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:compositionVideoTrack];
        
        CGAffineTransform transform = videoTrack.preferredTransform;
        [layerInst setTransform:transform atTime:kCMTimeZero];
        
        
        AVMutableVideoCompositionInstruction *inst = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
        inst.timeRange = CMTimeRangeMake(kCMTimeZero, asset.duration);
        inst.layerInstructions = [NSArray arrayWithObject:layerInst];
        
        
        AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition];
        videoComposition.instructions = [NSArray arrayWithObject:inst];
        
        CGSize videoSize = videoTrack.naturalSize;
        if(isPortrait_) {
            NSLog(@"video is portrait ");
            videoSize = CGSizeMake(videoSize.height, videoSize.width);
        }
        videoComposition.renderSize = videoSize;
        videoComposition.frameDuration = CMTimeMake(1,30);
        videoComposition.renderScale = 1.0;
        return videoComposition;
    }
    
    -(BOOL) isVideoPortrait:(AVAsset *)asset{
        BOOL isPortrait = FALSE;
        NSArray *tracks = [asset tracksWithMediaType:AVMediaTypeVideo];
        if([tracks    count] > 0) {
            AVAssetTrack *videoTrack = [tracks objectAtIndex:0];
            
            CGAffineTransform t = videoTrack.preferredTransform;
            // Portrait
            if(t.a == 0 && t.b == 1.0 && t.c == -1.0 && t.d == 0)
            {
                isPortrait = YES;
            }
            // PortraitUpsideDown
            if(t.a == 0 && t.b == -1.0 && t.c == 1.0 && t.d == 0)  {
                
                isPortrait = YES;
            }
            // LandscapeRight
            if(t.a == 1.0 && t.b == 0 && t.c == 0 && t.d == 1.0)
            {
                isPortrait = FALSE;
            }
            // LandscapeLeft
            if(t.a == -1.0 && t.b == 0 && t.c == 0 && t.d == -1.0)
            {
                isPortrait = FALSE;
            }
        }
        return isPortrait;
    }
    /// 获取视频角度
    - (int)degressFromVideoFileWithAsset:(AVAsset *)asset {
        int degress = 0;
        NSArray *tracks = [asset tracksWithMediaType:AVMediaTypeVideo];
        if([tracks count] > 0) {
            AVAssetTrack *videoTrack = [tracks objectAtIndex:0];
            CGAffineTransform t = videoTrack.preferredTransform;
            if(t.a == 0 && t.b == 1.0 && t.c == -1.0 && t.d == 0){
                // Portrait
                degress = 90;
            } else if(t.a == 0 && t.b == -1.0 && t.c == 1.0 && t.d == 0){
                // PortraitUpsideDown
                degress = 270;
            } else if(t.a == 1.0 && t.b == 0 && t.c == 0 && t.d == 1.0){
                // LandscapeRight
                degress = 0;
            } else if(t.a == -1.0 && t.b == 0 && t.c == 0 && t.d == -1.0){
                // LandscapeLeft
                degress = 180;
            }
        }
        return degress;
    }```

    相关文章

      网友评论

          本文标题:视频合成、拼接(尚未整理版,不过感觉这个写的不错,先拿过来,后续

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