我必须使用基于帧的方法将视频转换为带音频的慢动作。
以下链接是很多帮助,这是
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将慢速视频写入文件,并且AVMutableCompositionAVAsset的子类(也许令人惊讶),即使您没有导出视频的慢动作版本,也可以使用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!)")
}

10-05 19:47