情况:
我正在尝试使用一些参数导出视频,例如视频比特率、音频比特率、帧速率、更改视频分辨率等。请注意,我让用户以分数设置视频帧速率;喜欢用户可以设置视频帧速率,比如 23.98。
我用 AVAssetWriter 和 AVAssetReader 对于这个操作。我用 AVAssetWriterInputPixelBufferAdaptor用于写入样本缓冲区。
除了 之外,其他一切都很好。视频帧率 .
我试过的:
我不确定为什么它不适用于我的代码。这种方法的问题是它总是从 AVAssetReaderVideoCompositionOutput.copyNextSampleBuffer() 返回 nil。
var sampleTimingInfo = CMSampleTimingInfo()
var sampleBufferToWrite: CMSampleBuffer?
CMSampleBufferGetSampleTimingInfo(vBuffer, at: 0, timingInfoOut: &sampleTimingInfo)
sampleTimingInfo.duration = CMTimeMake(value: 100, timescale: Int32(videoConfig.videoFrameRate * 100))
sampleTimingInfo.presentationTimeStamp = CMTimeAdd(previousPresentationTimeStamp, sampleTimingInfo.duration)
previousPresentationTimeStamp = sampleTimingInfo.presentationTimeStamp
let status = CMSampleBufferCreateCopyWithNewTiming(allocator: kCFAllocatorDefault, sampleBuffer: vBuffer,sampleTimingEntryCount: 1, sampleTimingArray: &sampleTimingInfo, sampleBufferOut: &sampleBufferToWrite)
使用这种方法,我确实可以将帧速率设置得恰到好处,但它会增加视频持续时间(如该问题答案的评论中所述)。我认为在某些时候我可能不得不丢弃一些帧(如果目标帧速率较低;在大多数情况下我需要降低帧速率)。如果我知道如果我想要 30fps,并且我当前的帧速率是 60fps,那么很容易丢弃每一秒帧并相应地设置 SampleBuffer 时间。
如果我采用这种方法(即设置 23.98 fps),我如何决定丢弃哪个帧,如果目标帧速率更高,复制哪个帧?提醒:帧速率可以是分数。
最佳答案
这是一个选择框架的想法。假设源视频的fps是F,目标fps是TF。率 = TF/F
启动一个变量 n 等于 -rate 并每次添加 rate,
当 n 的整数部分改变时,选择框架。
e.g. rate = 0.3
n: -0.3 0 0.3 0.6 0.9 1.2 1.5 1.8 2.1
^ ^ ^
frame index: 0 1 2 3 4 5 6 7
select 0 4 7
float rate = 0.39999f; // TF/F
float n = -rate; // to make sure first frame will be selected
for (int i = 0; i < 100; ++i, n += rate) { // i stands for frame index, take a video with 100 frames as an example
int m = floor(n);
int tmp = n+rate;
// if rate > 1.0 repeat i
// if rate < 1.0 some of the frames will be dropped
for (int j = 0; m+j < tmp; ++j) {
// Use this frame
printf("%d ", i);
}
}
关于ios - 使用 AVAssetWriter/AVAssetReader 设置视频帧率的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56613335/