制作一个真正的慢动作视频,都是慢动作

Making a real slow motion video that are all slow motion

我正在创建我的这个应用程序并以 120 和 240 fps 的速度拍摄视频。

当我在 mac 上观看这些视频时,我会在时间轴下方看到这些标记。

这些标记是可编辑的,代表慢动作区域。因此,视频以正常帧率开始,以慢动作进入,最后 returns 到正常帧率。我没有把那些标记放在那里,iOS 放在那里。在那种情况下,我想知道是否有办法删除它们并使视频完全慢动作。

我只是正常初始化 AVAssetWriter,就像我对非慢动作视频一样。

此外,我注意到这些 "slow motion" 视频并不是真正的慢动作,而是 "recipes" 慢动作,可以在 iOS 设备和使用 QuickTime X 的 Mac 上正确播放. 甚至 QuickTime 7 也无法正确播放它们。

有没有办法让这个东西成为真正的慢动作,可以在任何播放器、任何计算机上播放?

您的 "slow motion" 视频文件实际上只是具有高帧率的视频文件。 iOS 正在降低播放速率以以慢动作的形式展示额外的帧。问题是其他播放器以 1 的播放速率播放,因此要使效果可移植,您需要改为修改帧呈现时间戳。

您或许可以使用 AVMutableComposition 来做到这一点,但我更喜欢使用所见即所得的 AVAssetReader/AVAssetWriter 对。输入文件中的每一帧都是这样的:

if let inSampleBuffer = readerOutput.copyNextSampleBuffer() {
    let inTimeStamp = CMSampleBufferGetPresentationTimeStamp(inSampleBuffer)
    let outTimeStamp = CMTimeMultiplyByFloat64(inTimeStamp, 240.0/30)  // slow 240 fps down to 30fps (8x slowmo)
    var outSampleBuffer: CMSampleBuffer?
    var outTimingInfo = CMSampleTimingInfo(duration: kCMTimeInvalid, presentationTimeStamp: outTimeStamp, decodeTimeStamp: kCMTimeInvalid)

    if CMSampleBufferCreateCopyWithNewTiming(kCFAllocatorDefault, inSampleBuffer, 1, &outTimingInfo, &outSampleBuffer) == noErr {
        writerInput.appendSampleBuffer(outSampleBuffer!)
    }
} else {
    // finished
}

出现这种情况是因为您的视频帧率太高。所以 iOS 会自动将 slowMo 添加到您的视频中。 对于那些正在为这个问题寻找 AVComposition 解决方案的人, 我发现了两个(不好的)解决方案:

  • 将 AVAssetExportSession 设置为 AVAssetExportPresetMediumQuality 或更小会导致帧率下降但质量也会变差。不好。
  • 将 AVAssetExportSession.videoComposition 设置为 frameDuration 为 CMTimeMake(1, 30) 的视频合成,但用它导出视频需要很长时间,这也不好。我不知道是什么原因导致它花了这么长时间。

第二个是目前最好的解决方案。我为此发布了一些示例代码:

   let videoComposition = AVMutableVideoComposition(propertiesOf: mixComposition)
            videoComposition.sourceTrackIDForFrameTiming = kCMPersistentTrackID_Invalid
            videoComposition.frameDuration = CMTimeMake(value: 1, timescale: 30)
            // Changes FPS to 30

            //export the video to as per your requirement conversion
            if let exportSession = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPresetHighestQuality) {
                exportSession.videoComposition =  videoComposition
                exportSession.outputURL = outputURL
                exportSession.outputFileType = AVFileType.mp4
               
                
                /// try to export the file and handle the status cases
                exportSession.exportAsynchronously(completionHandler: {