我正在尝试进行视频编辑,已经成功完成了序列和混合视频/音频,甚至可以做一些基本的慢动作! :) 现在我想要整合视频滤镜,不仅仅是在图层本身上(否则我将使用AVPlayerItemVideoOutput与CIFilter配合使用),而且还要导出到最终的视频文件中。因此,我目前正在研究如何“渲染”我上面提到的CIFilter,并在保持非常精确的时间控制(使用CMTime)的同时将其应用到最终的视频中。 有任何建议吗?
CVPixelBufferRef pixelBuffer = [AVAsynchronousVideoCompositionRequest sourceFrameByTrackID:trackID];
CIImage *theImage = [CIImage imageWithCVPixelBuffer:pixelBuffer];
CIImage *motionBlurredImage = [[CIFilter *filterWithName:@"CIMotionBlur" keysAndValues:@"inputImage", theImage, nil] valueForKey:kCIOutputImageKey];
CIContext *someCIContext = [CIContext contextWithEAGLContext:eaglContext];
[someCIContext render:motionBlurredImage toCVPixelBuffer:outputBuffer];
然后按照 苹果官方文档 所述,使用OpenGL渲染像素缓存。这将允许您实现任意数量的转换或过滤器。
let vidComp = AVVideoComposition(asset: avAsset,
applyingCIFiltersWithHandler: {
request in
filtered = request.sourceImage.imageByClampingToExtent();
filtered = filtered.imageByApplyingFilter("CIGaussianBlur",
withInputParameters: [kCIInputRadiusKey: 100])
filtered = filtered.imageByCroppingToRect(request.sourceImage.extent)
request.finishWithImage(filtered, context: cicontext)
})
let export = AVAssetExportSession(asset: avAsset,
presetName: AVAssetExportPreset1920x1080)
export.outputFileType = AVFileTypeQuickTimeMovie
export.outputURL = outURL
export.videoComposition = vidComp
NSFileManager.defaultManager().removeItemAtURL(outURL)
export.exportAsynchronouslyWithCompletionHandler()
播放:
步骤 01:
let vidComp = AVVideoComposition(asset: avAsset,
applyingCIFiltersWithHandler: {
// same as earlier example
})
let playerItem = AVPlayerItem(asset: avAsset)
playerItem.videoComposition = vidComp
let player = AVPlayer(playerItem: playerItem)
player.play()
乔纳森的回答也是正确的。但是,苹果现在已经停止使用OpenGL。下面是相同的代码,使用Metal编写的Swift代码:
let theImage = CIImage.init(cvImageBuffer: foregroundPixelBuffer)
let blurFilter = CIFilter.init(name: "CIMotionBlur")
blurFilter?.setValue(theImage, forKey: "inputImage")
if let destinationImage = blurFilter?.outputImage {
context?.render(destinationImage, to: outputBuffer)
}
context = CIContext.init(mtlDevice: device)
// Ask for the default Metal device; this represents our GPU.
guard let defaultMetalDevice = MTLCreateSystemDefaultDevice() else {
print("Metal is not supported on this device.")
return nil
}
device = defaultMetalDevice
上下文和设备实例应该只声明一次并重复使用,以从它们的缓存能力中受益。