Skip to content

Latest commit

 

History

History
214 lines (156 loc) · 6.94 KB

README-CN.md

File metadata and controls

214 lines (156 loc) · 6.94 KB

VideoLab

高性能且灵活的视频剪辑与特效框架,基于 AVFoundation 与 Metal。

框架设计与实现介绍

特性

  • 高性能实时剪辑与导出。
  • 高自由度组合视频,图片,音频
  • 支持音频音高设置,音量调节。
  • 支持 CALayer 矢量动画,可以支持复杂的文字动画。
  • 支持关键帧动画。
  • 支持类似于 After Effect 的预合成。
  • 支持转场。
  • 支持自定义各类特效,如 LUT 滤镜,zoom blur 等等(MSL 编写脚本)。

以下是一些特性的 gif(多图层、文字动画、关键帧动画、预合成及转场)

要求

  • iOS 11.0+
  • Swift 5.0+

安装

可以使用 CocoaPods 安装。只需指定如下语句到你的 Podfile 文件中。

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '11.0'
use_frameworks!

target '<Your Target>' do
  pod 'VideoLab'
end

使用

基础概念

RenderLayer

RenderLayerVideoLab 框架中最基本的单元。一个视频、图片、音频都可以是一个 RenderLayer,甚至一个效果也可以是一个 RenderLayerRenderLayer 类似于 After Effect 中图层的概念。

RenderComposition

RenderComposition 可以理解成一个视频作品,可以设置帧率、画布大小,包含多个 RenderLayers,可以设置 CALayer 支持矢量动画。

VideoLab

VideoLab 可以理解成一个实验室,基于 RenderComposition 生成 AVPlayerItem, AVAssetExportSession, AVAssetImageGenerator

基础使用

// 1. Layer 1
var url = Bundle.main.url(forResource: "video1", withExtension: "MOV")
var asset = AVAsset(url: url!)
var source = AVAssetSource(asset: asset)
source.selectedTimeRange = CMTimeRange(start: CMTime.zero, duration: asset.duration)
var timeRange = source.selectedTimeRange
let renderLayer1 = RenderLayer(timeRange: timeRange, source: source)
    
// 1. Layer 2
url = Bundle.main.url(forResource: "video2", withExtension: "MOV")
asset = AVAsset(url: url!)
source = AVAssetSource(asset: asset)
source.selectedTimeRange = CMTimeRange(start: CMTime.zero, duration: asset.duration)
timeRange = source.selectedTimeRange
timeRange.start = CMTimeRangeGetEnd(renderLayer1.timeRange)
let renderLayer2 = RenderLayer(timeRange: timeRange, source: source)
    
// 2. Composition
let composition = RenderComposition()
composition.renderSize = CGSize(width: 1280, height: 720)
composition.layers = [renderLayer1, renderLayer2]

// 3. VideoLab
let videoLab = VideoLab(renderComposition: composition)

// 4. Make playerItem
let playerItem = videoLab.makePlayerItem()
  1. 创建 RenderLayer
  2. 创建 RenderComposition,设置 renderSizelayers
  3. 使用 renderComposition 创建 VideoLab
  4. 生成 AVPlayerItemAVAssetExportSession

更高级的使用

变换

var center = CGPoint(x: 0.25, y: 0.25)
var transform = Transform(center: center, rotation: 0, scale: 0.5)
renderLayer1.transform = transform
  1. 使用 centerrotationscale 创建 Transform
  2. RenderLayer 设置 transform

音频设置

let audioConfiguration = AudioConfiguration()
let volumeRampTimeRange = CMTimeRange(start: CMTime.zero, duration: CMTime(seconds: 5, preferredTimescale: 600))
let volumeRamp1 = VolumeRamp(startVolume: 0.0, endVolume: 0.0, timeRange: volumeRampTimeRange)
audioConfiguration.volumeRamps = [volumeRamp1]
renderLayer2.audioConfiguration = audioConfiguration
  1. 创建 AudioConfiguration
  2. 使用 startVolumeendVolumetimeRange 创建 VolumeRamp
  3. AudioConfiguration设置 volumeRamps
  4. RenderLayer 设置 audioConfiguration

CALayer 动画

导出时,为 RenderComposition 设置自定义的 CALayer

composition.animationLayer = <Your customized CALayer>

播放时,添加 AVSynchronizedLayer 到你显示视图的 layer 上,更多细节参考 Text Animation Demo.

关键帧动画

// 1. Keyframe animation
let keyTimes = [CMTime(seconds: 2, preferredTimescale: 600),
                CMTime(seconds: 4, preferredTimescale: 600),
                CMTime(seconds: 6, preferredTimescale: 600)]
let animation = KeyframeAnimation(keyPath: "blendOpacity",
                                  values: [1.0, 0.2, 1.0],
                                  keyTimes: keyTimes, timingFunctions: [.linear, .linear])
renderLayer1.animations = [animation]
    
var transform = Transform.identity
let animation1 = KeyframeAnimation(keyPath: "scale",
                                   values: [1.0, 1.3, 1.0],
                                   keyTimes: keyTimes, timingFunctions: [.quadraticEaseInOut, .quadraticEaseInOut])
let animation2 = KeyframeAnimation(keyPath: "rotation",
                                   values: [0, Float.pi / 2.0, 0],
                                   keyTimes: keyTimes, timingFunctions: [.quadraticEaseInOut, .quadraticEaseInOut])
transform.animations = [animation1, animation2]
renderLayer1.transform = transform
  1. 使用 keyPathvalueskeyTimestimingFunctions 创建 KeyframeAnimation
  2. 为实现 Animatable 协议的结构体或者类设置 animations

预合成

let layerGroup = RenderLayerGroup(timeRange: timeRange)
layerGroup.layers = [renderLayer1, renderLayer2]
  1. 使用 timeRange 创建 RenderLayerGroup
  2. layerGroup 设置子 layers。更多细节参考 Layer Group Demo

转场

我们没有转场的 layer,但是你可以添加一个给每个 RenderLayer 添加一个 transform 或者 operations,以此来创建一个转场。更多细节参考 Transition Demo

自定义特效

// Filter
var filter = LookupFilter()
filter.addTexture(lutTextures[0], at: 0)
renderLayer.operations = [filter]

// Zoom Blur
var zoomblur = ZoomBlur()
animation = KeyframeAnimation(keyPath: "blurSize",
                              values: [0.0, 3.0],
                              keyTimes: keyTimes, timingFunctions: [.quarticEaseOut])
zoomblur.animations = [animation]
layerGroup1.operations = [zoomblur]
  1. 创建继承自 BasicOperation 的自定义 OperationBasicOperation 同样实现 Animatable 协议。
  2. RenderLayer 设置 operations

待办

  • 支持 Open GL 渲染
  • RenderLayer 增加速度控制
  • 提供更便捷的方式使用转场,可能是提供 TransitionLayer
  • 增加日志系统

作者

许可证

VideoLab 使用 MIT 许可,详情请参考 LICENSE