Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best way to transcode a video in objective-c (iOS)?

I would like to, depending on the device and the settings in my application, transcode a video to a specific video format. For an example, if the user has an iPhone 4S and chooses medium settings in my application I would like to convert the video to 540p before I start processing. If he chooses high then I would like to transcode to 720p.

I could read the video frame by frame, resize and save to disc but this does not seem very effective. What would be the easiest and fastest way to transcode a video that I can feed to my video processing libraries?

I have tried using the videoQuality settings on my UIImagePickerController but seems like it is not working as even when I set it to UIImagePickerControllerQualityTypeIFrame960x540 my video comes out as 720p (640x480 is working but I need to be more granular).

like image 914
Michel Avatar asked Feb 19 '12 12:02

Michel


1 Answers

You might want to look at AVAssetExportSession, which makes it reasonably simple to re-encode videos. I think it's also hardware-supported when possible like the rest of AVFoundation:

https://developer.apple.com/library/ios/#DOCUMENTATION/AudioVideo/Conceptual/AVFoundationPG/Articles/01_UsingAssets.html

Note that it will never make the video larger than it already is, so you aren't guaranteed to get the output size you request. The following code might be a start for what you want, assuming you have an instance of ALAsset:

- (void)transcodeLibraryVideo:(ALAsset *)libraryAsset 
        toURL:(NSURL *)fileURL 
        withQuality:(NSString *quality) {
  // get a video asset for the original video file
  AVAsset *asset = [AVAsset assetWithURL:
    [NSURL URLWithString:
      [NSString stringWithFormat:@"%@", 
        [[libraryAsset defaultRepresentation] url]]]];
  // see if it's possible to export at the requested quality
  NSArray *compatiblePresets = [AVAssetExportSession 
    exportPresetsCompatibleWithAsset:asset];
  if ([compatiblePresets containsObject:quality]) {
    // set up the export
    AVAssetExportSession *exportSession = [[AVAssetExportSession alloc]
      initWithAsset:asset presetName:quality];
    exportSession.outputURL = fileURL;
    exportSession.outputFileType = AVFileTypeQuickTimeMovie;
    // run the export
    [exportSession exportAsynchronouslyWithCompletionHandler:^{
      switch ([exportSession status]) {
        case AVAssetExportSessionStatusFailed:
            //TODO: warn of failure
            break;
        case AVAssetExportSessionStatusCancelled:
            //TODO: warn of cancellation
            break;
        default:
            //TODO: do whatever is next
            break;
      }
      [exportSession release];
    }];
  }
  else {
    //TODO: warn that the requested quality is not available
  }
}

You would want to pass a quality of AVAssetExportPreset960x540 for 540p and AVAssetExportPreset1280x720 for 720p, for example.

like image 120
Jesse Crossen Avatar answered Nov 15 '22 04:11

Jesse Crossen