10

I would make reduced size video, maybe 50 pixel across and 75 pixels for length. Those are the physical dimension.

How do you set that? in the videosettings? I think AVVideoWidthKey and AVVideoHeightKey are more for resolution not for physically dimension which what I needed.

NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                               AVVideoCodecH264, AVVideoCodecKey,
                               [NSNumber numberWithInt: 320], AVVideoWidthKey,    
                               [NSNumber numberWithInt:480], AVVideoHeightKey,   
                               nil];
AVAssetWriterInput* writerInput = [[AVAssetWriterInput
                                    assetWriterInputWithMediaType:AVMediaTypeVideo
                                    outputSettings:videoSettings] retain
Mohamed Jaleel Nazir
  • 5,776
  • 3
  • 34
  • 48
lilzz
  • 5,243
  • 14
  • 59
  • 87

2 Answers2

20

You need to set video codec parameters:

NSDictionary *videoCleanApertureSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                                           [NSNumber numberWithInt:320], AVVideoCleanApertureWidthKey,
                                           [NSNumber numberWithInt:480], AVVideoCleanApertureHeightKey,
                                           [NSNumber numberWithInt:10], AVVideoCleanApertureHorizontalOffsetKey,
                                           [NSNumber numberWithInt:10], AVVideoCleanApertureVerticalOffsetKey,
                                            nil];


NSDictionary *videoAspectRatioSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                                             [NSNumber numberWithInt:3], AVVideoPixelAspectRatioHorizontalSpacingKey,
                                             [NSNumber numberWithInt:3],AVVideoPixelAspectRatioVerticalSpacingKey,
                                                    nil];



NSDictionary *codecSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                               [NSNumber numberWithInt:960000], AVVideoAverageBitRateKey,
                               [NSNumber numberWithInt:1],AVVideoMaxKeyFrameIntervalKey,
                               videoCleanApertureSettings, AVVideoCleanApertureKey,
                               //videoAspectRatioSettings, AVVideoPixelAspectRatioKey,
                               //AVVideoProfileLevelH264Main30, AVVideoProfileLevelKey,
                               nil];





NSString *targetDevice = [[UIDevice currentDevice] model];

NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                               AVVideoCodecH264, AVVideoCodecKey,
                               codecSettings,AVVideoCompressionPropertiesKey,
                               [NSNumber numberWithInt:320], AVVideoWidthKey,
                               [NSNumber numberWithInt:480], AVVideoHeightKey,
                               nil];
sth
  • 222,467
  • 53
  • 283
  • 367
Victor
  • 217
  • 2
  • 3
  • Why do [NSNumber numberWithInt:1],AVVideoMaxKeyFrameIntervalKey ? – Meekohi Jun 26 '12 at 21:15
  • 1
    @Meekohi: [`AVVideoMaxKeyFrameIntervalKey`](https://developer.apple.com/library/mac/documentation/AVFoundation/Reference/AVFoundation_Constants/Reference/reference.html#//apple_ref/doc/c_ref/AVVideoMaxKeyFrameIntervalKey) specifies a key to access the maximum interval between key frames. The corresponding value is an instance of `NSNumber`. `1` means key **frames only**. – Regexident Sep 28 '12 at 14:25
  • 3
    Hey sorry I understand technically what it does, my question is why you would intensionally do that in this situation? Doesn't that reduce the ability to compress the final video? – Meekohi Sep 28 '12 at 18:11
  • I tried this with 320x320 but my video is squeezed together now. – MichaelScaria Jul 14 '13 at 15:43
9

You need a PhD to work with AVAssetWriter - it's non-trivial: https://developer.apple.com/library/mac/documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/05_Export.html#//apple_ref/doc/uid/TP40010188-CH9-SW1

There's an amazing library for doing exactly what you want which is just an AVAssetExportSession drop-in replacement with more crucial features like changing the bit rate: https://github.com/rs/SDAVAssetExportSession

Here's how to use it:

-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{

  SDAVAssetExportSession *encoder = [SDAVAssetExportSession.alloc initWithAsset:[AVAsset assetWithURL:[info objectForKey:UIImagePickerControllerMediaURL]]];
  NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
  NSString *documentsDirectory = [paths objectAtIndex:0];
  self.myPathDocs =  [documentsDirectory stringByAppendingPathComponent:
                      [NSString stringWithFormat:@"lowerBitRate-%d.mov",arc4random() % 1000]];
  NSURL *url = [NSURL fileURLWithPath:self.myPathDocs];
  encoder.outputURL=url;
  encoder.outputFileType = AVFileTypeMPEG4;
  encoder.shouldOptimizeForNetworkUse = YES;

  encoder.videoSettings = @
  {
  AVVideoCodecKey: AVVideoCodecH264,
  AVVideoCompressionPropertiesKey: @
    {
    AVVideoAverageBitRateKey: @2300000,
    AVVideoProfileLevelKey: AVVideoProfileLevelH264High40,
    },
  };
  encoder.audioSettings = @
  {
  AVFormatIDKey: @(kAudioFormatMPEG4AAC),
  AVNumberOfChannelsKey: @2,
  AVSampleRateKey: @44100,
  AVEncoderBitRateKey: @128000,
  };

  [encoder exportAsynchronouslyWithCompletionHandler:^
  {
    int status = encoder.status;

    if (status == AVAssetExportSessionStatusCompleted)
    {
      AVAssetTrack *videoTrack = nil;
      AVURLAsset *asset = [AVAsset assetWithURL:encoder.outputURL];
      NSArray *videoTracks = [asset tracksWithMediaType:AVMediaTypeVideo];
      videoTrack = [videoTracks objectAtIndex:0];
      float frameRate = [videoTrack nominalFrameRate];
      float bps = [videoTrack estimatedDataRate];
      NSLog(@"Frame rate == %f",frameRate);
      NSLog(@"bps rate == %f",bps/(1024.0 * 1024.0));
      NSLog(@"Video export succeeded");
      // encoder.outputURL <- this is what you want!!
    }
    else if (status == AVAssetExportSessionStatusCancelled)
    {
      NSLog(@"Video export cancelled");
    }
    else
    {
      NSLog(@"Video export failed with error: %@ (%d)", encoder.error.localizedDescription, encoder.error.code);
    }
  }];
}
etayluz
  • 15,920
  • 23
  • 106
  • 151
  • Could you please tell me what settings I have to put to use AVVideoProfileLevelH264Baseline30 with this library? I tried yours by replacing AVVideoProfileLevelH264High40 but it reports an error, so I'm guessing the settings are not fit to baseline 3.0. Thanks in advance @etayluz – Gannicus Sep 02 '15 at 17:56
  • @etayluz, what would be the range of values I could use for AVVideoAverageBitRateKey? Also, how should other properties change according the value given for the AVVideoAverageBitRateKey – ThE uSeFuL Aug 06 '19 at 18:24
  • I wish I could tell you but I haven't touched this in almost 4 years. – etayluz Aug 07 '19 at 19:02