Using AVAssetWriter to re-encode H264 mov file - how to set frame rate?

I am trying to transcode an input MOV file with variable frame rate and reduced duration in iOS. At the moment I have AVAssetWriter settings like:

NSMutableDictionary* compressionPropertiesDict = [NSMutableDictionary new];
compressionPropertiesDict[AVVideoProfileLevelKey] = AVVideoProfileLevelH264High40;

if(self.fps > 0) {
    compressionPropertiesDict[AVVideoAverageNonDroppableFrameRateKey] = [NSNumber numberWithInt:self.fps];


_sessionMgr.videoSettings = @
{
AVVideoCodecKey: AVVideoCodecH264,
AVVideoWidthKey: [NSNumber numberWithFloat:self.outputSize.width],
AVVideoHeightKey: [NSNumber numberWithFloat:self.outputSize.height],
AVVideoCompressionPropertiesKey: compressionPropertiesDict,
};

      

This happens at runtime that looks like this:

videoSettings = 
{
AVVideoCodecKey = avc1;
AVVideoCompressionPropertiesKey =     {
    AverageNonDroppableFrameRate = 15;
    ProfileLevel = "H264_High_4_0";
};
AVVideoHeightKey = 960;
AVVideoWidthKey = 640;
}

      

At the end of this I get a crash with NSInvalidArgumentException: "Compression property AverageNonDroppableFrameRate is not supported for video codec type avc1"

. (In unit tests using a simulator.)

There's only one type of codec that can be used on iOS, AVVideoCodecH264 / "avc1", and I notice that other projects have used AVVideoAverageNonDroppableFrameRateKey

. In fact, I am using SDAVAssetExportSession and in this codebase I can see the explicit use of this key. So I would think that one should use this key to set the frame rate.?

I've also experimented a bit with the usage AVVideoMaxKeyFrameIntervalKey

, but that doesn't change the frame rate ...

So to summarize, can anyone help me with setting a different (always lower) output frame rate for iOS AVFoundation based video conversion? Thank!

+3


source to share


1 answer


As mentioned in the question, I used SDAVAssetExportSession for the convenience of exporting videos. I made some small changes that allowed me to easily use this rate to change the frame rate.

The main point is that you can change the frame rate with by AVMutableVideoComposition

setting the property frameDuration

to the desired frame rate and passing this composition object to the object AVAssetReaderVideoCompositionOutput

used in transcoding.

In the SDAVAssetExportSession method, buildDefaultVideoComposition

I changed it to look something like this:



- (AVMutableVideoComposition *)buildDefaultVideoComposition
{
  AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition];
  AVAssetTrack *videoTrack = [[self.asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];

  // ...

  videoComposition.frameDuration = CMTimeMake(1, myDesiredFramerate);

  // ...

      

This did the trick.

+1


source







All Articles