6

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).

Michel
  • 357
  • 1
  • 3
  • 12
  • I'm sure you know this but transcoding without hardware support may not be the best idea, battery wise. – Joachim Isaksson Feb 19 '12 at 12:15
  • Yea, I know. When recording a video with the front facing camera you can have the UIImagePickerController transcoding to 560p, which it does really quickly. Does not work for videos picked from the library. Looking for something similar (i.e. a direct API call to do the same for any video in your library). – Michel Feb 22 '12 at 06:14

1 Answers1

3

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.

Jesse Crossen
  • 6,945
  • 2
  • 31
  • 32
  • Is there a way to set the framerate on the AVAssetExportSession. Seems like I get different frame rates depending on which one I choose. If I choose low I get 15fps and for 720p I get 30p. I want to maintain my 60p footage but does not seem to be any preset which does 60fps. – Michel May 28 '12 at 13:06
  • @user1219167: I was thinking you might be able to do it with the videoComposition property of AVAssetExportSession, but then I ran across this: http://stackoverflow.com/questions/9725193/setting-avmutablecompositions-frameduration – Jesse Crossen May 29 '12 at 13:55
  • Hi, can we reduce the memory space that a video with videoQuality UIImagePickerControllerQualityTypeIFrame960x540 takes (with 16:9 aspect ratio)? – iOS Monster Nov 15 '12 at 09:48
  • Does this work for videos that were not taken on an iPhone and not in the HVEC format? https://developer.apple.com/documentation/avfoundation/media_assets_and_metadata/exporting_video_to_alternative_formats - mentions that the input should be: let anAsset = // Your source AVAsset movie in HEVC format // – voidsstr Mar 30 '21 at 15:26