Kakapos 是一个视频增加过滤器东西,支撑网络和本地网址以及相册视频。
一起能够简单的支撑多种滤镜库,例如Harbeth、GPUImage、MetalPetal、CoreImage等等。
反正核心其实便是对CVPixelBuffer
进行注入滤镜处理,然后再导出视频即可。
支撑全平台体系,macOS、iOS、tvOS、watchOS
演示Demo
- KakaposDemo 地址
这边现已提供关于macOS和iOS两个端的演示Demo,需求的朋友请移步GitHub下载即可。
框架介绍
该架构首要涵盖4个文件:
- Exporter:首要的转化文件,注入滤镜后导出视频。
/// 设置导出文件质量
public var presetName: String = AVAssetExportPresetHighestQuality {
didSet {
if !AVAssetExportSession.allExportPresets().contains(presetName) {
presetName = AVAssetExportPresetMediumQuality
}
}
}
/// 根据视频链接初始化
public init(videoURL: URL, delegate: ExporterDelegate) {
self.init(asset: AVAsset(url: videoURL), delegate: delegate)
}
/// 根据AVAsset初始化
public init(asset: AVAsset, delegate: ExporterDelegate) {
self.asset = asset
self.delegate = delegate
}
/// 增加滤镜然后导出视频,首要在`filtering`当中对`buffer`增加滤镜,最后协议反馈成果。
public func export(outputURL: URL, optimizeForNetworkUse: Bool = true, filtering: @escaping PixelBufferCallback) {
...
}
- ExporterDelegate:导出协议,包括成功和失败两个协议方法。
public protocol ExporterDelegate: NSObjectProtocol {
/// 导出成功的视频网址,相当于outputURL。
func export(_ exporter: Exporter, success videoURL: URL)
/// 视频导出失败。
func export(_ exporter: Exporter, failed error: Exporter.Error)
}
- Compositor:对视频帧进行处理,对缓冲进入注入滤镜处理,最后再复原回去
finish(withComposedVideoFrame:)
即可。
func startRequest(_ request: AVAsynchronousVideoCompositionRequest) {
self.renderQueue.sync {
guard let instruction = request.videoCompositionInstruction as? CompositionInstruction,
let pixels = request.sourceFrame(byTrackID: instruction.trackID) else {
return
}
let buffer = instruction.bufferCallback(pixels) ?? pixels
request.finish(withComposedVideoFrame: buffer)
}
}
- CompositionInstruction:表明一个指令,决议每个
timeRange
内每个轨道的状态,装备视频组合的渲染尺度、缩放、帧时长等,界说时刻规模信息,以及每一帧的层级。
/// 接收回调信息,方便后续转化处理。
init(trackID: CMPersistentTrackID, bufferCallback: @escaping Exporter.PixelBufferCallback) {
self.trackID = trackID
self.bufferCallback = bufferCallback
super.init()
self.enablePostProcessing = true
}
关于AVMutableVideoCompositionInstruction
更多介绍
参阅:www.codersrc.com/archives/11…
该类还能拿来 完成对媒体裁剪 / 缩放 / 转场 / 过渡等操作。
如何运用?
- 设置转化视频存储沙盒链接。
/// 创立临时途径以保存转化的视频
let outputURL: URL = {
let documents = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let outputURL = documents.appendingPathComponent("condy_exporter_video.mp4")
// Check if the file already exists then remove the previous file
if FileManager.default.fileExists(atPath: outputURL.path) {
do {
try FileManager.default.removeItem(at: outputURL)
} catch {
//completionHandler(nil, error)
}
}
return outputURL
}()
- 创立视频导出器
exporter
实例。
let exporter = Exporter.init(videoURL: ``URL Link``, delegate: self)
或许
let exporter = Exporter.init(asset: ``AVAsset``, delegate: self)
- 完成视频导出成果协议
ExporterDelegate
。
/// Video export successed.
/// - Parameters:
/// - exporter: VideoExporter
/// - videoURL: Export the successful video url, Be equivalent to outputURL.
func export(_ exporter: Kakapos.Exporter, success videoURL: URL) {
self.view.hideAllToasts()
let player = AVPlayer(url: videoURL)
let vc = AVPlayerViewController()
vc.player = player
self.present(vc, animated: true) {
vc.player?.play()
}
}
/// Video export failure.
/// - Parameters:
/// - exporter: VideoExporter
/// - error: Failure error message.
func export(_ exporter: Kakapos.Exporter, failed error: Kakapos.Exporter.Error) {
// do someing..
}
- 转化视频缓冲区
CVPixelBuffer
并增加过滤器。
let filters: [C7FilterProtocol] = [
C7Flip(horizontal: true, vertical: false),
C7ColorConvert(with: .gray),
C7SoulOut(soul: 0.3),
MPSGaussianBlur(radius: 5),
]
let exporter = Exporter.init(videoURL: ``URL Link``, delegate: self)
exporter.export(outputURL: outputURL) {
let dest = BoxxIO(element: $0, filters: filters)
return try? dest.output()
}
或许
let martix = C7ColorMatrix4x4(matrix: Matrix4x4.Color.gray)
let screen = C7SplitScreen(type: .two)
let exporter = Exporter.init(videoURL: ``URL Link``, delegate: self)
exporter.export(outputURL: outputURL) { $0 ->> martix ->> screen }
最后
- 再附上一个Metal滤镜库HarbethDemo地址,现在包括
100+
种滤镜,一起也支撑CoreImage混合运用。 - 再附上一个开发加速库KJCategoriesDemo地址
- 再附上一个网络基础库RxNetworksDemo地址
- 喜爱的老板们能够点个星,谢谢各位老板!!!
✌️.