我必须使用基于帧的方法将视频转换为带音频的慢动作。
以下链接是很多帮助,这是
Reverse-AVAsset-Efficient
在解决方案中,我可以更改缓冲区的时间戳并获得慢动作视频。
for sample in videoSamples {
var presentationTime = CMSampleBufferGetPresentationTimeStamp(sample)
//Changing Timestamp to achieve slow-motion
presentationTime.timescale = presentationTime.timescale * 2
let imageBufferRef = CMSampleBufferGetImageBuffer(sample)
while !videoWriterInput.isReadyForMoreMediaData {
Thread.sleep(forTimeInterval: 0.1)
}
pixelBufferAdaptor.append(imageBufferRef!, withPresentationTime: presentationTime)
}
对于音频慢动作,我尝试更改音频样本的时间戳,但没有任何效果。
有音频慢动作的任何解决方案。
如果您有Objective-C解决方案,请随时发布。
谢谢。
最佳答案
您可以使用AVMutableComposition
轻松慢动作。正如@ hotpaw2所提到的,有多种方法可以降低音频速度-例如,您可以降低音调或使其保持恒定。这种解决方案似乎使其保持不变,我看不出有任何方法可以改变它。也许这就是您想要的。也许不会。
您可以使用AVAssetExportSession
将慢速视频写入文件,并且AVMutableComposition
是AVAsset
的子类(也许令人惊讶),即使您没有导出视频的慢动作版本,也可以使用AVPlayer
预览结果。
let asset = AVURLAsset(url: Bundle.main.url(forResource: "video", withExtension: "mp4")! , options : nil)
let srcVideoTrack = asset.tracks(withMediaType: .video).first!
let srcAudioTrack = asset.tracks(withMediaType: .audio).first!
let sloMoComposition = AVMutableComposition()
let sloMoVideoTrack = sloMoComposition.addMutableTrack(withMediaType: .video, preferredTrackID: kCMPersistentTrackID_Invalid)!
let sloMoAudioTrack = sloMoComposition.addMutableTrack(withMediaType: .audio, preferredTrackID: kCMPersistentTrackID_Invalid)!
let assetTimeRange = CMTimeRange(start: .zero, duration: asset.duration)
try! sloMoVideoTrack.insertTimeRange(assetTimeRange, of: srcVideoTrack, at: .zero)
try! sloMoAudioTrack.insertTimeRange(assetTimeRange, of: srcAudioTrack, at: .zero)
let newDuration = CMTimeMultiplyByFloat64(assetTimeRange.duration, multiplier: 2)
sloMoVideoTrack.scaleTimeRange(assetTimeRange, toDuration: newDuration)
sloMoAudioTrack.scaleTimeRange(assetTimeRange, toDuration: newDuration)
// you can play sloMoComposition in an AVPlayer at this point
// Export to a file using AVAssetExportSession
let exportSession = AVAssetExportSession(asset: sloMoComposition, presetName: AVAssetExportPresetPassthrough)!
exportSession.outputFileType = .mp4
exportSession.outputURL = getDocumentsDirectory().appendingPathComponent("slow-mo-\(Date.timeIntervalSinceReferenceDate).mp4")
exportSession.exportAsynchronously {
assert(exportSession.status == .completed)
print("File in \(exportSession.outputURL!)")
}