AVFoundation和视频特效

3
我正在尝试进行视频编辑,已经成功完成了序列和混合视频/音频,甚至可以做一些基本的慢动作! :) 现在我想要整合视频滤镜,不仅仅是在图层本身上(否则我将使用AVPlayerItemVideoOutput与CIFilter配合使用),而且还要导出到最终的视频文件中。因此,我目前正在研究如何“渲染”我上面提到的CIFilter,并在保持非常精确的时间控制(使用CMTime)的同时将其应用到最终的视频中。 有任何建议吗?

你能找到一个简单明了的解决方案吗?一种方法是使用AVAssetReader和AVAssetWriter编写AVAssetExportSession的自定义实现,但这将涉及大量工作。 - P.K.
1
看看GPUImageFilter,它真的很棒。 - Tim Specht
2个回答

3
您可以使用AVVideoCompositing和AVAsynchronousVideoCompositionRequest协议来实现自定义合成器,具体请参考AVVideoCompositingAVAsynchronousVideoCompositionRequest文档。
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渲染像素缓存。这将允许您实现任意数量的转换或过滤器。


有没有关于如何做这个的示例项目? - izzy
好的,我在iOS开发者库中找到了一个示例项目,对于下一个找到它的人来说,AVCustomEdit位于https://developer.apple.com/library/ios/samplecode/AVCustomEdit/Listings/ReadMe_txt.html。干杯! - izzy

2
2015年的WWDC演讲详细讲解了如何实现此功能。
从20:32开始收看https://developer.apple.com/videos/play/wwdc2015/510/
导出:
步骤01:
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)
 })

步骤 02:
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
 })

步骤 02:
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

上下文和设备实例应该只声明一次并重复使用,以从它们的缓存能力中受益。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接