简体   繁体   English

AVAssetWriter AVVideoExpectedSourceFrameRateKey(帧频)已忽略

[英]AVAssetWriter AVVideoExpectedSourceFrameRateKey (frame rate) ignored

Me and my team are trying to re-encode a video file to a more "gify" feeling by changing the video frame rate. 我和我的团队正在尝试通过更改视频帧速率来对视频文件进行重新编码,以使其更具“动感”。 We are using the following properties for the AVAssetWriterInput : 我们将以下属性用于AVAssetWriterInput

let videoSettings:[String:Any] = [
            AVVideoCodecKey: AVVideoCodecH264,
            AVVideoHeightKey: videoTrack.naturalSize.height,
            AVVideoWidthKey: videoTrack.naturalSize.width,
            AVVideoCompressionPropertiesKey: [AVVideoExpectedSourceFrameRateKey: NSNumber(value: 12)]                                         
        ]

But the output video keep playing in the normal frame rate (played using AVPlayer ). 但是输出视频将继续以正常帧速率播放(使用AVPlayer播放)。

What is the right way to reduce video frame rate? 降低视频帧速率的正确方法是什么? (12 for example). (例如12)。

Any help in the right direction would be HIGHLY approcated. 朝着正确方向的任何帮助都将受到高度重视。 We stuck. 我们卡住了。 Best regards, Roi 此致Roi

You can control the timing of each sample you append to your AVAssetWriterInput directly with CMSampleBufferCreateCopyWithNewTiming . 您可以使用CMSampleBufferCreateCopyWithNewTiming直接控制附加到AVAssetWriterInput的每个样本的时序。

You need to adjust the timing in the CMSampleTimingInfo you provide. 您需要在提供的CMSampleTimingInfo调整时间。 Retrieve current timing info with CMSampleBufferGetOutputSampleTimingInfoArray and just go over the duration of each sample and calculate the correct duration to get 12 frames per second and adjust presentation and decode timestamps to match this new duration. 使用CMSampleBufferGetOutputSampleTimingInfoArray检索当前的时序信息,然后遍历每个样本的持续时间,计算正确的持续时间以每秒获取12帧,并调整演示和解码时间戳以匹配此新的持续时间。 You then make your copy and feed it to your writer's input. 然后,您制作副本并将其提供给作者的输入。

Let's say you have existingSampleBuffer : 假设您有existingSampleBuffer

CMSampleBufferRef sampleBufferToWrite = NULL;
CMSampleTimingInfo sampleTimingInfo = {0};

CMSampleBufferGetSampleTimingInfo(existingSampleBuffer, 0, &sampleTimingInfo);

// modify duration & presentationTimeStamp
sampleTimingInfo.duration = CMTimeMake(1, 12) // or whatever frame rate you desire
sampleTimingInfo.presentationTimeStamp = CMTimeAdd(previousPresentationTimeStamp, sampleTimingInfo.duration);
previousPresentationTimeStamp = sampleTimingInfo.presentationTimeStamp; // should be initialised before passing here the first time

OSStatus status = CMSampleBufferCreateCopyWithNewTiming(kCFAllocatorDefault, existingSampleBuffer, 1, &sampleTimingInfo, &sampleBufferToWrite);

if (status == noErr) {
    // you can write sampleBufferToWrite
}

I'm making some assumptions in this code: 我在这段代码中做一些假设:

  • SampleBuffer contains only one sample SampleBuffer仅包含一个样本
  • SampleBuffer contains uncompressed video (otherwise, you need to handle decodeTimeStamp as well) SampleBuffer包含未压缩的视频(否则,您还需要处理decodeTimeStamp)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM