【问题标题】:AVFoundation concatenating videosAVFoundation 连接视频
【发布时间】:2015-04-24 21:46:00
【问题描述】:

我正在为此拉头发。

我尝试连接视频,但它不会做我想做的事。 具体来说,我的视频具有不同的方向,我尝试使用图层指令对其进行设置。唉,不管我怎么试,都没有效果……

我阅读了每个教程,尝试实现 Apple 提供的 APLCompositionDebugView(基本上看起来还可以),但无济于事...我准备把所有东西都扔掉...

这是我的代码:

self.videoComposition = [AVMutableVideoComposition videoComposition];
self.videoComposition.renderSize = CGSizeMake(480, 320);
self.videoComposition.frameDuration = CMTimeMake(1, 30);

NSMutableArray *videoCompositionInstructions = [[NSMutableArray alloc] init];

AVMutableComposition *theMutableComposition = [AVMutableComposition composition];

AVMutableCompositionTrack *compositionVideoTrack = [theMutableComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
AVMutableCompositionTrack *compositionAudioTrack = [theMutableComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
AVMutableVideoCompositionLayerInstruction *passThroughLayer = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:compositionVideoTrack];

CMTime titleDuration = CMTimeMakeWithSeconds(5, 600);

CMTimeRange titleRange = CMTimeRangeMake(kCMTimeZero, titleDuration);

[compositionVideoTrack insertEmptyTimeRange:titleRange];
[compositionAudioTrack insertEmptyTimeRange:titleRange];

CMTime insertPoint = [[transitionTimes lastObject] CMTimeValue];

CMTime totalTime = CMTimeMakeWithSeconds(5, 600);

for(NSDictionary *clip in collection[@"clips"]){

    NSString *movieName = [NSString stringWithFormat:@"collection_%li/recording_%li_%li.MOV", (long)editCollection, editCollection, [clip[@"clipID"] longValue]];

    NSURL *assetUrl = [NSURL fileURLWithPath:[usefulStuff pathForFile: movieName]];

    AVURLAsset *videoAsset = [AVURLAsset URLAssetWithURL:assetUrl options:nil];

    totalTime = CMTimeAdd(totalTime, videoAsset.duration);

    AVAssetTrack *clipVideoTrack = [[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
    AVAssetTrack *clipAudioTrack = [[videoAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];

    NSError *error;

    [compositionVideoTrack insertTimeRange:clipVideoTrack.timeRange ofTrack:clipVideoTrack atTime:insertPoint error:&error];    // Add video
    [compositionAudioTrack insertTimeRange:clipVideoTrack.timeRange ofTrack:clipAudioTrack atTime:insertPoint error:&error];    // Add audio

    [passThroughLayer setTransform:clipVideoTrack.preferredTransform atTime:insertPoint]; ////// This should supposedly set the video in the right orientation at the given time... 

    insertPoint = CMTimeAdd(insertPoint, videoAsset.duration);

}

AVMutableVideoCompositionInstruction *passThroughInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
passThroughInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, totalTime);

NSLog(@"Total time b %f", CMTimeGetSeconds(totalTime));

passThroughInstruction.layerInstructions = [NSArray arrayWithObject:passThroughLayer];
[videoCompositionInstructions addObject:passThroughInstruction];

self.videoComposition.instructions = videoCompositionInstructions;

嘻嘻嘻! :)

【问题讨论】:

    标签: avfoundation avmutablecomposition


    【解决方案1】:

    我在您发布的代码中没有看到任何处理您的方向问题的内容。您需要在layerInstruction 中进行一些转换以使所有方向相同。

    试试这样的:

    AVMutableComposition *composition = [AVMutableComposition composition];
    AVMutableCompositionTrack *compositionVideoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
    
    AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition];
    
    videoComposition.frameDuration = CMTimeMake(1,30);
    
    videoComposition.renderScale = 1.0;
    
    AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
    
    AVMutableVideoCompositionLayerInstruction *layerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:compositionVideoTrack];
    
    // Get only paths the user selected
    NSMutableArray *array = [NSMutableArray array];
    for(NSString* string in videoPathArray){
        if(![string isEqualToString:@""]){
            [array addObject:string];
        }
    }
    self.videoPathArray = array;
    float time = 0;
    
    for (int i = 0; i<self.videoPathArray.count; i++) {
    
        AVURLAsset *sourceAsset = [AVURLAsset URLAssetWithURL:[NSURL fileURLWithPath:[videoPathArray objectAtIndex:i]] options:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:AVURLAssetPreferPreciseDurationAndTimingKey]];
    
        NSError *error = nil;
    
        BOOL ok = NO;
        AVAssetTrack *sourceVideoTrack = [[sourceAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
    
      CGSize temp = CGSizeApplyAffineTransform(sourceVideoTrack.naturalSize, sourceVideoTrack.preferredTransform);
        CGSize size = CGSizeMake(fabsf(temp.width), fabsf(temp.height));
        CGAffineTransform transform = sourceVideoTrack.preferredTransform;
    
        videoComposition.renderSize = sourceVideoTrack.naturalSize;
        if (size.width > size.height) {
    
            [layerInstruction setTransform:transform atTime:CMTimeMakeWithSeconds(time, 30)];
        } else {
            float s = size.width/size.height;
    
            CGAffineTransform new = CGAffineTransformConcat(transform, CGAffineTransformMakeScale(s,s));
    
            float x = (size.height - size.width*s)/2;
    
            CGAffineTransform newer = CGAffineTransformConcat(new, CGAffineTransformMakeTranslation(x, 0));
    
            [layerInstruction setTransform:newer atTime:CMTimeMakeWithSeconds(time, 30)];
        }
        ok = [compositionVideoTrack insertTimeRange:sourceVideoTrack.timeRange ofTrack:sourceVideoTrack atTime:[composition duration] error:&error];
    
        if (!ok) {
                // Deal with the error.
            NSLog(@"something went wrong");
        }
    
        NSLog(@"\n source asset duration is %f \n source vid track timerange is %f %f \n composition duration is %f \n composition vid track time range is %f %f",CMTimeGetSeconds([sourceAsset duration]), CMTimeGetSeconds(sourceVideoTrack.timeRange.start),CMTimeGetSeconds(sourceVideoTrack.timeRange.duration),CMTimeGetSeconds([composition duration]), CMTimeGetSeconds(compositionVideoTrack.timeRange.start),CMTimeGetSeconds(compositionVideoTrack.timeRange.duration));
    
        time += CMTimeGetSeconds(sourceVideoTrack.timeRange.duration);
    
    }
    
    instruction.layerInstructions = [NSArray arrayWithObject:layerInstruction];
    instruction.timeRange = compositionVideoTrack.timeRange;
    
    
    videoComposition.instructions = [NSArray arrayWithObject:instruction];
    

    我从here 获取了代码,因为它每次都对我有用。您所要做的就是根据您的要求进行结果转换。

    【讨论】:

    • 嗨 blancos - 感谢您的回复...我已经尝试了所有这些...没有运气...猜我的时间线有问题...至少,这是我调试的结果所以远...
    • 看来你确实给了我最后的提示!谢谢!有一件事很重要:我试图在模拟器上播放作曲——结果它崩溃了。它仅适用于真实设备! (我花了好几个小时才弄明白……)
    猜你喜欢
    • 2018-04-03
    • 2015-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-18
    • 2015-05-16
    • 1970-01-01
    • 2011-11-14
    相关资源
    最近更新 更多