3

指定された時間範囲に基づいてビデオをトリミングおよびエクスポートするメソッドを作成しました。また、ビデオを横向きに回転させます。

ただし、何らかの理由で、UIVideoEditorControllerを使用して以前にトリミングされたビデオを処理しようとすると、AVAssetExportSessionが失敗します。

以前にこの問題に遭遇した人はいますか?

このエラーが発生します:

AVAssetExportSessionStatusFailed: Error Domain=AVFoundationErrorDomain Code=-11841 "The operation couldn’t be completed. (AVFoundationErrorDomain error -11841.)"

この方法の場合:

    - (void) trimVideoWithRange: (CMTimeRange)range fromInputURL: (NSURL *)inputURL withCompletionHandler:(void (^)(BOOL success, NSURL *outputURL))handler;
{
    AVAsset *asset = [AVURLAsset assetWithURL:inputURL];

    AVAssetTrack *videoTrack = [asset tracksWithMediaType:AVMediaTypeVideo][0];

    AVAssetTrack *audioTrack = [asset tracksWithMediaType:AVMediaTypeAudio][0];


    NSLog(@"%@, %@, %@", asset, videoTrack, audioTrack);



    NSError *error;

    //  Create a video composition
    AVMutableComposition *composition = [AVMutableComposition composition];

    AVMutableCompositionTrack *videoCompositionTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];

    error = nil;

    [videoCompositionTrack insertTimeRange:videoTrack.timeRange ofTrack:videoTrack atTime:CMTimeMakeWithSeconds(0, NSEC_PER_SEC) error:&error];

    NSLog(@"videoCompositionTrack timeRange: %lld, %lld", videoCompositionTrack.timeRange.start.value, videoCompositionTrack.timeRange.duration.value);


    if(error)
        NSLog(@"videoCompositionTrack error: %@", error);

    AVMutableCompositionTrack *audioCompositionTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];




    error = nil;

    [audioCompositionTrack insertTimeRange:audioTrack.timeRange ofTrack:audioTrack atTime:CMTimeMakeWithSeconds(0, NSEC_PER_SEC) error:&error];

    NSLog(@"audioCompositionTrack timeRange: %lld, %lld", audioCompositionTrack.timeRange.start.value, audioCompositionTrack.timeRange.duration.value);

    if(error)
        NSLog(@"audioCompositionTrack error: %@", error);


    //  Rotate video if needed
    CGAffineTransform rotationTransform = videoTrack.preferredTransform;


    //  Create video composition
    AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition];

    videoComposition.renderScale = 1.0;

    videoComposition.renderSize = videoTrack.naturalSize;

    videoComposition.frameDuration = CMTimeMake(1, 30);


    //  Apply the transform which may have been changed
    AVMutableVideoCompositionLayerInstruction *instruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoTrack];
    [instruction setTransform:rotationTransform atTime:kCMTimeZero];

    //  Set the time range and layer instructions for the video composition
    AVMutableVideoCompositionInstruction *videoTrackInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];

    videoTrackInstruction.layerInstructions = [NSArray arrayWithObject:instruction];
    videoTrackInstruction.timeRange = range;

    videoComposition.instructions = @[videoTrackInstruction];


    // Check so that we can proceed with our desired output preset
    NSArray *compatiblePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:composition];

    if (![compatiblePresets containsObject:AVAssetExportPreset960x540])
    {
        //  Nope.
        if(handler)
            handler(NO, nil);

        return;
    }

    //  Create export session with composition
    AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPreset960x540];

    //  Configure export session
    exportSession.outputURL = [NSURL fileURLWithPath:pathToTemporaryOutput];

    exportSession.outputFileType = AVFileTypeQuickTimeMovie;

    exportSession.videoComposition = videoComposition;



    exportSession.shouldOptimizeForNetworkUse = YES;

    //  Export async
    [exportSession exportAsynchronouslyWithCompletionHandler:^{


        switch ([exportSession status])
        {
            case AVAssetExportSessionStatusCompleted:
            {
                dispatch_async(dispatch_get_main_queue(), ^{

                    //  Everything OK. Execute completion block with URL to rendered video
                    if(handler)
                        handler(exportSession.status == AVAssetExportSessionStatusCompleted, [NSURL fileURLWithPath:pathToTemporaryOutput]);

                });



            }
                break;

            case AVAssetExportSessionStatusFailed:
            {
                NSError *exportError = exportSession.error;

                NSLog(@"AVAssetExportSessionStatusFailed: %@", exportError.description);

                dispatch_async(dispatch_get_main_queue(), ^{

                    //  No go. Execute handler with fail.
                    if(handler)
                        handler(NO, nil);

                });
            }
                break;
        }




    }];
}
4

1 に答える 1