We'll start with a basic example: Let's assume we have a video with duration of 6 seconds and 30 FPS (180 frames in total). I'd like to reduce the FPS to 15 while keeping the video 6 seconds. Meaning I'll need to remove/drop frames from the video ( 6 seconds * 15 FPS = 90 frames).
Me & my team are able to change video frame rate using AVAssetWriter
, but it just makes the video longer. We tried to skip frames inside the:
while(videoInput.isReadyForMoreMediaData){
let sample = assetReaderVideoOutput.copyNextSampleBuffer()
if (sample != nil){
if counter % 2 == 0 {
continue // skip frame
}
videoInput.append(sampleBufferToWrite!)
}
But it does not work. The writer forces the initial samples count, even if we skip it.
Bottom line, How can we reduce the video Frame Rate while maintain the same duration (We are trying to create a GIFY video feeling)?
Any help would be highly appreciated!
Best Regards, Roi
For each dropped frame, you need to compensate by doubling the duration of the sample you're going to write.
while(videoInput.isReadyForMoreMediaData){
if let sample = assetReaderVideoOutput.copyNextSampleBuffer() {
if counter % 2 == 0 {
let timingInfo = UnsafeMutablePointer<CMSampleTimingInfo>.allocate(capacity: 1)
let newSample = UnsafeMutablePointer<CMSampleBuffer?>.allocate(capacity: 1)
// Should check call succeeded
CMSampleBufferGetSampleTimingInfo(sample, 0, timingInfo)
timingInfo.pointee.duration = CMTimeMultiply(timingInfo.pointee.duration, 2)
// Again, should check call succeeded
CMSampleBufferCreateCopyWithNewTiming(nil, sample, 1, timingInfo, newSample)
videoInput.append(newSample.pointee!)
}
counter = counter + 1
}
}