3

我正在尝试自己进行一些视频编辑,我得到了排序和混合视频/音频,所有这些都正常工作,甚至是一些基本的慢动作!:) 现在我想将视频过滤器集成到图层本身(否则我将使用 AVPlayerItemVideoOutput 与 CIFilter 一起使用),还要集成到最终导出的视频文件中。因此,我目前正在研究将上面提到的 CIFilter“渲染”到最终视频中,同时仍然使用 CMTime 保持非常精确的时序控制。

有什么建议么?

4

2 回答 2

3

您可以使用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];

然后按照Apple 文档中的描述使用 OpenGL 渲染像素缓冲区。这将允许您实现任意数量的转换或您想要的过滤器。

于 2014-08-27T17:04:36.577 回答
1

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()

乔纳森的回答也是正确的。但是,Apple 现在已经停止使用 OpenGL。下面是在 Swift 中使用 Metal 的相同代码,

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

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

于 2019-04-04T21:01:34.440 回答