使用AVAssetWriter / AVAssetReader

时间:2019-06-15 19:00:54

标签: ios swift macos video video-encoding

情况:

我正在尝试导出具有某些参数的视频,例如视频比特率,音频比特率,帧频,更改视频分辨率等。请注意,我让用户以分数设置视频帧频;例如用户可以将视频帧频设置为23.98。

我使用 AVAssetWriter AVAssetReader 进行此操作。我使用AVAssetWriterInputPixelBufferAdaptor编写示例缓冲区。

视频帧速率外,其他所有功能都可以正常工作。

我尝试过的事情:

  1. 按照建议的here设置 AVAssetWriter.movi​​eTimeScale 。这确实会改变视频帧速率,但也会使视频速度变慢。 (gist here

  1. 设置 AVVideoExpectedSourceFrameRateKey 。这没有帮助。 (gist here

  1. 设置 AVAssetWriterInput.mediaTimeScale 。同样,它会更改视频帧速率,但会使视频变慢,就像 AVAssetWriter.movi​​eTimeScale 一样。视频在某些时候显示了不同的帧,有时会粘住并再次恢复。 (gist here

  1. 使用 AVAssetReaderVideoCompositionOutput 并设置 AVMutableVideoComposition.frameDuration ;就像SDAVAssetExportSession一样。具有讽刺意味的是,使用SDAVAssetExportSession代码,将以我想要的正确帧速率导出视频,但是在我的代码中它不起作用。 gist here

我不确定为什么它不能与我的代码一起使用。这种方法的问题在于,它总是从 AVAssetReaderVideoCompositionOutput.copyNextSampleBuffer()返回nil。


  1. 根据建议here使用 CMSampleTimingInfo 手动更改帧时间戳。
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),如何确定要丢弃的帧以及目标帧速率是否较高,要复制的帧?提醒:帧速率可以是分数。


0 个答案:

没有答案