制作一个真正的慢动作视频,都是慢动作
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: {
我正在创建我的这个应用程序并以 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: {