AVAssetWriter AVVideoExpectedSourceFrameRateKey(帧率)被忽略。

3

我和我的团队正在尝试通过更改视频帧率将视频文件重新编码为更具“gif感觉”的格式。我们正在使用以下属性来设置AVAssetWriterInput

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

但是输出的视频保持正常帧率播放(使用AVPlayer播放)。

降低视频帧率的正确方法是什么?(例如12)。

任何指向正确方向的帮助都将不胜感激。我们卡住了。 此致, Roi

1个回答

4
您可以使用CMSampleBufferCreateCopyWithNewTiming直接控制每个附加到AVAssetWriterInput的样本的时间。
您需要在提供的CMSampleTimingInfo中调整时间。使用CMSampleBufferGetOutputSampleTimingInfoArray检索当前的计时信息,然后只需遍历每个样本的持续时间并计算正确的持续时间以获取每秒12帧,并调整演示和解码时间戳以匹配这个新的持续时间。然后,您可以创建副本并将其馈送到编写器的输入中。
假设您有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
}

我在这段代码中做了一些假设:

  • SampleBuffer只包含一个样本
  • SampleBuffer包含未压缩的视频(否则,您需要处理decodeTimeStamp)

1
嘿,瓦莱里安。我们尝试在谷歌上搜索并理解你的意思。但是我们无法让它工作。如果您可以分享更多信息或代码,那就太完美了。 - Roi Mulia
1
快速向我的帖子添加了一些代码...不过是ObjC,但我希望您能理解 :-) - Valérian
1
它运行了,瓦莱丽安!AVFoundation 真的需要博士学位。非常感谢!我们发现尽管这会将视频减速到 15 fps,但也会让视频变长(显然)。所以一个简单的解决方法就是删除一些视频帧。让视频保持相同的时长,但帧数和 FPS 更少,给它那种 GIFY 的感觉。您是否知道在 copyNextSampleBuffer() 函数内跳过帧是否可能? - Roi Mulia
1
底线是,我们正在尝试在保持相同的持续时间的情况下降低帧速率(这意味着我们需要找到一些方法来删除或去除帧)。这在理论上可行吗? - Roi Mulia
1
它会崩溃,就像缓冲区没有样本一样 :/ 如果我将时长加倍,它不会在某个时候超过总时长吗? - Roi Mulia
显示剩余8条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接