今回は動画をクリッピングしてみる。
元動画のサイズは1080x1920なので、その中から360x640の範囲で切り出してみる。
イメージとしては以下のようになる。
movie_clip_ss1

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

- (void)clipMovie
{
    NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    NSString *inputPath = [[path stringByAppendingPathComponent:@"portrait1"] stringByAppendingPathExtension:@"mov"];
    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;
    
    NSURL *inputURL = [NSURL fileURLWithPath:inputPath];
    AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:inputURL options:nil];
    
    CMTimeRange range = CMTimeRangeMake(kCMTimeZero, asset.duration);
    
    AVAssetTrack *videoTrack = [asset tracksWithMediaType:AVMediaTypeVideo][0];
    AVAssetTrack *audioTrack = [asset tracksWithMediaType:AVMediaTypeAudio][0];
    
    [compositionVideoTrack insertTimeRange:range ofTrack:videoTrack atTime:kCMTimeZero error:&error];
    [compositionAudioTrack insertTimeRange:range ofTrack:audioTrack atTime:kCMTimeZero error:&error];
    
    AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
    instruction.timeRange = range;
    
    AVMutableVideoCompositionLayerInstruction *layerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:compositionVideoTrack];
    
    CGSize videoSize = videoTrack.naturalSize;
    CGAffineTransform 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);
    }
    
    // 1
    videoSize = CGSizeMake(360, 640);
    transform = CGAffineTransformConcat(transform, CGAffineTransformMakeTranslation(-100, -600));
    
    [layerInstruction setTransform:transform atTime:kCMTimeZero];
    instruction.layerInstructions = @[layerInstruction];
    
    AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition];
    videoComposition.renderSize = videoSize;
    videoComposition.instructions = @[instruction];
    videoComposition.frameDuration = CMTimeMake(1, kVideoFPS);
    
    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.videoSizeの値を出力したい動画サイズである360x640に設定する。
たったこれだけで、出力する解像度を変えることが出来る。

その下の行では何をやっているか。
左上を切り出すのではなく、もっと別の場所を切り出したいので、行列に対して移動を加えている。
値がマイナスになっているのは、この行列は動画に影響するものなので、こうすることによって切り出し開始位置を動画の(100, 600)に設定することができる。

以下にイメージを用意した。
movie_clip_ss2
さあ実行してみよう。
元動画の(100, 600)を開始位置として360x640の動画が出力されたはずだ。

出力結果イメージ
movie_clip_ss3


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