今回は複数の動画を連結する。
動画の数は2つでもいいし、10個でもいい。
要するに何個でもいいということだ。

ここでは3つの動画を連結する。 
イメージはこのようになる。
movie_concat_ss1

ソースコードはこうなる。
const int kVideoFPS = 30;

- (void)concatMovies{
    // 1
    NSArray *files = @[@"portrait1", @"portrait2", @"portrait3"];
    NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    NSString *outputPath = [[path stringByAppendingPathComponent:@"result"] stringByAppendingPathExtension:@"mov"];
    
    AVMutableComposition *composition = [AVMutableComposition composition];
    AVMutableCompositionTrack *compositionVideoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
    AVMutableCompositionTrack *compositionAudioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
    NSError *error = nil;
    
    // 2
    CGSize videoSize;
    CGAffineTransform transform;
    CMTime totalDuration = kCMTimeZero;
    for (NSString *file in files)
    {
        NSString *inputPath = [[path stringByAppendingPathComponent:file] stringByAppendingPathExtension:@"mov"];
        NSURL *videoURL = [NSURL fileURLWithPath:inputPath];
        AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:videoURL options:nil];
        
        AVAssetTrack *videoTrack = [asset tracksWithMediaType:AVMediaTypeVideo][0];
        AVAssetTrack *audioTrack = [asset tracksWithMediaType:AVMediaTypeAudio][0];
        
        CMTimeRange videoRange = CMTimeRangeMake(kCMTimeZero, asset.duration);
        
        // 3
        [compositionVideoTrack insertTimeRange:videoRange ofTrack:videoTrack atTime:totalDuration error:&error];
        [compositionAudioTrack insertTimeRange:videoRange ofTrack:audioTrack atTime:totalDuration error:&error];
        
        // 4
        totalDuration = CMTimeAdd(totalDuration, asset.duration);
        
        videoSize = videoTrack.naturalSize;
        transform = videoTrack.preferredTransform;
    }
    
    if (transform.a == 0 && transform.d == 0 && (transform.b == 1.0 || transform.b == -1.0) && (transform.c == 1.0 || transform.c == -1.0))
    {
        videoSize = CGSizeMake(videoSize.height, videoSize.width);
    }
    
    AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition];
    videoComposition.renderSize = videoSize;
    videoComposition.frameDuration = CMTimeMake(1, kVideoFPS);
    
    AVMutableVideoCompositionLayerInstruction *layerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:compositionVideoTrack];
    [layerInstruction setTransform:transform atTime:kCMTimeZero];
    
    AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
    instruction.timeRange = CMTimeRangeMake(kCMTimeZero, totalDuration);
    instruction.layerInstructions = @[layerInstruction];
    
    videoComposition.instructions = @[instruction];
    
    NSFileManager *fm = [NSFileManager defaultManager];
    if ([fm fileExistsAtPath:outputPath])
    {
        [fm removeItemAtPath:outputPath error:&error];
    }
    
    AVAssetExportSession *session = [[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPresetHighestQuality];
    session.outputURL = [NSURL fileURLWithPath:outputPath];
    session.outputFileType = AVFileTypeQuickTimeMovie;
    session.videoComposition = videoComposition;
    
    [session exportAsynchronouslyWithCompletionHandler:^{
        if (session.status == AVAssetExportSessionStatusCompleted)
        {
            NSLog(@"output complete!");
        }
        else
        {
            NSLog(@"output error! : %@", session.error);
        }
    }];
}
基本的な考え方はこれまで扱ってきたものと同じだ。
異なる箇所を順に見ていこう。

1.3つのファイル名を決め打ちで配列に入れておく

2.配列の数だけ処理をループさせる。
totalDurationという変数は3つの動画の長さを保持しておく変数だ。

3.トラックにアセットを設定する。
注目すべきなのはatTimeだ。
これまでここにはkCMTimeZeroを指定していたが、今回は後ろにドンドン動画を追加していくため、一つ前の動画の最後尾を指定してやらなければならない。

4.一つ前の動画の最後尾を保持するためにも、ここでtotalDurationの値を更新しておく。
ループから抜けた後は、totalDurationは全動画を連結した場合の長さになる。

さあ実行してみよう。
3つの動画が連結された動画が出力されたはずだ。

 関連記事
[iOS] 動画を加工・編集する(1) 指定した時間の範囲を切り出す
[iOS] 動画を加工・編集する(2) エラーコード-11841に気をつける
[iOS] 動画を加工・編集する(3) 動画に音を合成する
[iOS] 動画を加工・編集する(4) 動画をクリッピングする
[iOS] 動画を加工・編集する(5) 動画を拡大縮小する