Trim video without displaying UIVideoEditorController?

Midhun MP picture Midhun MP · Oct 3, 2012 · Viewed 9.3k times · Source

Currently I'm working on a application which deals with the videos. In my application user can trim the video, I have a custom control for selecting the start time and end time. I need to trim the video by these two values. I tried with UIVideoEditorController like follows.

    UIVideoEditorController* videoEditor = [[[UIVideoEditorController alloc] init] autorelease];
    videoEditor.delegate = self;
    NSString* videoPath = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"MOV"];
    if ( [UIVideoEditorController canEditVideoAtPath:videoPath] )
    {
      videoEditor.videoPath = videoPath;
      [self presentModalViewController:videoEditor animated:YES];
    }
    else
    {
      NSLog( @"can't edit video at %@", videoPath );
    }

But the issue is the above code will display apple's video editor control and user can do some operations on that view. I don't want to display this view, because I have already displayed the video on MPMoviePlayer and received the user input (start time and end time) for trimming the video on a custom control. How can I trim a video without displaying UIVideoEditorController ?

Answer

Midhun MP picture Midhun MP · Oct 4, 2012

Finally I found the solution.

We can use AVAssetExportSession for trimming video without displaying UIVideoEditorController.

My code is like:

- (void)splitVideo:(NSString *)outputURL
{

    @try
    {
        NSString *videoBundleURL = [[NSBundle mainBundle] pathForResource:@"Video_Album" ofType:@"mp4"];

        AVAsset *asset = [[AVURLAsset alloc] initWithURL:[NSURL fileURLWithPath:videoBundleURL] options:nil];

        NSArray *compatiblePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:asset];

        if ([compatiblePresets containsObject:AVAssetExportPresetLowQuality])
        {

            [self trimVideo:outputURL assetObject:asset];

        }
        videoBundleURL = nil;

        [asset release];
        asset = nil;

        compatiblePresets = nil;
    }
    @catch (NSException * e)
    {
        NSLog(@"Exception Name:%@ Reason:%@",[e name],[e reason]);
    }
}

This method trims the video

- (void)trimVideo:(NSString *)outputURL assetObject:(AVAsset *)asset
  {

    @try
    {

        AVAssetExportSession *exportSession = [[AVAssetExportSession alloc]initWithAsset:asset presetName:AVAssetExportPresetLowQuality];

        exportSession.outputURL = [NSURL fileURLWithPath:outputURL];

        exportSession.outputFileType = AVFileTypeQuickTimeMovie;

        CMTime start = CMTimeMakeWithSeconds(splitedDetails.startTime, 1);

        CMTime duration = CMTimeMakeWithSeconds((splitedDetails.stopTime - splitedDetails.startTime), 1);

        CMTimeRange range = CMTimeRangeMake(start, duration);

        exportSession.timeRange = range;

        exportSession.outputFileType = AVFileTypeQuickTimeMovie;

        [self checkExportSessionStatus:exportSession];

        [exportSession release];
        exportSession = nil;

    }
    @catch (NSException * e)
    {
        NSLog(@"Exception Name:%@ Reason:%@",[e name],[e reason]);
    }
}

This method checks the status of trimming:

- (void)checkExportSessionStatus:(AVAssetExportSession *)exportSession
  {

    [exportSession exportAsynchronouslyWithCompletionHandler:^(void)
    {

        switch ([exportSession status])
            {

            case AVAssetExportSessionStatusCompleted:

                NSLog(@"Export Completed");
                break;

            case AVAssetExportSessionStatusFailed:

                NSLog(@"Error in exporting");
                break;

            default:
                break;

        }
    }];
}

I'm calling the splitVideo method from the export button action method and passes the output URL as argument.