AVFoundation框架解析(二十三) —— 向视频层添加叠加层和动画(一)

版本记录

版本号 时间
V1.0 2019.12.14 星期六

前言

AVFoundation框架是ios中很重要的框架,所有与视频音频相关的软硬件控制都在这个框架里面,接下来这几篇就主要对这个框架进行介绍和讲解。感兴趣的可以看我上几篇。
1. AVFoundation框架解析(一)—— 基本概览
2. AVFoundation框架解析(二)—— 实现视频预览录制保存到相册
3. AVFoundation框架解析(三)—— 几个关键问题之关于框架的深度概括
4. AVFoundation框架解析(四)—— 几个关键问题之AVFoundation探索(一)
5. AVFoundation框架解析(五)—— 几个关键问题之AVFoundation探索(二)
6. AVFoundation框架解析(六)—— 视频音频的合成(一)
7. AVFoundation框架解析(七)—— 视频组合和音频混合调试
8. AVFoundation框架解析(八)—— 优化用户的播放体验
9. AVFoundation框架解析(九)—— AVFoundation的变化(一)
10. AVFoundation框架解析(十)—— AVFoundation的变化(二)
11. AVFoundation框架解析(十一)—— AVFoundation的变化(三)
12. AVFoundation框架解析(十二)—— AVFoundation的变化(四)
13. AVFoundation框架解析(十三)—— 构建基本播放应用程序
14. AVFoundation框架解析(十四)—— VAssetWriter和AVAssetReader的Timecode支持(一)
15. AVFoundation框架解析(十五)—— VAssetWriter和AVAssetReader的Timecode支持(二)
16. AVFoundation框架解析(十六)—— 一个简单示例之播放、录制以及混合视频(一)
17. AVFoundation框架解析(十七)—— 一个简单示例之播放、录制以及混合视频之源码及效果展示(二)
18. AVFoundation框架解析(十八)—— AVAudioEngine之基本概览(一)
19. AVFoundation框架解析(十九)—— AVAudioEngine之详细说明和一个简单示例(二)
20. AVFoundation框架解析(二十)—— AVAudioEngine之详细说明和一个简单示例源码(三)
21. AVFoundation框架解析(二十一)—— 一个简单的视频流预览和播放示例之解析(一)
22. AVFoundation框架解析(二十二)—— 一个简单的视频流预览和播放示例之源码(二)

开始

首先看下主要内容:

在本AVFoundation教程中,您将学习如何使用AVVideoCompositionCoreAnimationTool向视频添加叠加层(overlays)和动画,该工具可将CALayers与视频结合在一起以添加背景和叠加层。

接着,看下写作环境

Swift 5, iOS 13, Xcode 11

如果您要制作相机应用,则可以在视频中添加叠加层和动画,从而从中受益。 无论您添加当前日期,位置名称,天气还是有趣的GIF,您的用户都将能够自定义视频。

您可以使用AVFoundation(苹果公司用于处理音频和视频内容的框架)来完成所有这些工作。 您可以将AVFoundation视为一个程序化的视频和音频编辑器,它使您可以组成视频和音频轨道(tracks),然后向其添加漂亮的叠加层。

在此AVFoundation教程中,您将学习如何:

  • 为您的视频添加自定义边框。
  • 在视频中添加文字和图像。
  • 对视频叠加层进行动画处理。
  • 将叠加的视频导出到文件中。

要充分利用本教程,您需要熟悉iOS开发。 熟悉Core Animation也会很有用。 不过请放心,本教程将逐步解释所有内容。

打开入门项目,该项目的名称为Cubica,代表“自定义生日贺卡”。 您将制作一个应用程序,使您可以录制视频并添加叠加层和边框,以将其转变为为朋友定制的生日贺卡。

在Xcode中打开begin项目。 您可以使用模拟器或设备,但是请记住,本教程需要视频。 确保将视频文件从Mac拖放到模拟器中。

开始项目已经有一个屏幕,您可以在其中输入朋友的名字并选择一个视频来添加叠加层。 这一切都发生在PickerViewController.swift中。

AVFoundation框架解析(二十三) —— 向视频层添加叠加层和动画(一)_第1张图片

用户选择视频后,应用程序会将其发送到VideoEditor.swift。 当前,该文件只有几个帮助程序方法和一个名为makeBirthdayCard(fromVideoAt:forName:onComplete :)的方法。 您将编辑此方法,以将叠加层添加到视频中。

一旦应用将叠加层添加到视频中,该方法就会调用完成处理程序(completion handler),并将视频URL发送到PlayerViewController.swift。 该视图控制器播放视频文件,并允许您将文件导出到照片库。


Composing a Video

在向视频添加任何叠加之前,您需要进行一些设置。您要做的就是根据现有视频创建一个新的视频文件,并添加背景和叠加层。

首先,您将创建一个新的AVFoundation composition。您可以将composition视为程序化视频编辑器。该composition包含不同类型的音轨,例如音频和视频音轨,并管理它们在视频时间线上的开始或结束时间。

创建空composition后,您将在composition中添加两条轨道,一条轨道用于视频,一条轨道用于音频。对于音轨,您只需复制现有视频的音频。要创建视频,您将使用AVVideoCompositionCoreAnimationTool,该类可让您将现有视频与Core Animation图层结合在一起。

composition的视频和音频都包含在合成中之后,您将使用AVAssetExportSessioncomposition导出到视频文件中。

别担心,它并不像听起来那样令人生畏!第一步是创建composition

1. Creating a Composition

打开VideoEditor.swift。 示例项目的内容位于makeBirthdayCard(fromVideoAt:forName:onComplete :)中。 当前,此方法仅使用现有视频调用完成处理程序(completion handler)。 用以下内容替换onComplete(videoURL)行:

let asset = AVURLAsset(url: videoURL)
let composition = AVMutableComposition()

创建一个AVAset,其中包含有关所提供视频的所有必需信息和数据。 此外,创建一个空的构图。 您将用叠加的视频填充此composition

接下来,将轨道添加到composition中,并通过向该方法添加以下代码,从资源中获取视频轨道:

guard
  let compositionTrack = composition.addMutableTrack(
    withMediaType: .video, preferredTrackID: kCMPersistentTrackID_Invalid),
  let assetTrack = asset.tracks(withMediaType: .video).first
  else {
    print("Something is wrong with the asset.")
    onComplete(nil)
    return
}

您可以通过使用.video媒体类型调用addMutableTrack来添加新的视频轨道。 如果您将不使用ID,则为轨道ID传递无效的ID常数。 您还可以通过捕获资产中的第一个也是唯一一个视频轨道来从资产中捕获视频。 如果您无法执行这两个操作中的任何一个,请打印出错误并使用nil调用完成处理程序。

现在,在makeBirthdayCard(fromVideoAt:forName:onComplete :)的末尾添加以下代码,以将资产中的视频轨道插入到合成的视频轨道内:

do {
  // 1
  let timeRange = CMTimeRange(start: .zero, duration: asset.duration)
  // 2
  try compositionTrack.insertTimeRange(timeRange, of: assetTrack, at: .zero)
  
  // 3
  if let audioAssetTrack = asset.tracks(withMediaType: .audio).first,
    let compositionAudioTrack = composition.addMutableTrack(
      withMediaType: .audio, 
      preferredTrackID: kCMPersistentTrackID_Invalid) {
    try compositionAudioTrack.insertTimeRange(
      timeRange, 
      of: audioAssetTrack, 
      at: .zero)
  }
} catch {
  // 4
  print(error)
  onComplete(nil)
  return
}

上面的代码是这样的:

  • 1) CMTimeRange指定视频内的时间范围。 在这种情况下,您要从头到尾添加视频,因此您可以设置从零到视频持续时间的范围。
  • 2) 一旦有了时间范围,就可以将资产中的整个视频插入到合成的视频轨道中。
  • 3) 如果资源还包含音频轨道,请执行与音频轨道相同的操作。 首先,将新的音轨添加到您的composition中,然后将资产的音频插入音轨中。
  • 4) 如果出现错误,请打印该错误并使用nil调用完成处理程序。

2. Setting Up the Composition

接下来,通过在方法末尾添加以下代码来考虑composition的大小和方向:

compositionTrack.preferredTransform = assetTrack.preferredTransform
let videoInfo = orientation(from: assetTrack.preferredTransform)

let videoSize: CGSize
if videoInfo.isPortrait {
  videoSize = CGSize(
    width: assetTrack.naturalSize.height,
    height: assetTrack.naturalSize.width)
} else {
  videoSize = assetTrack.naturalSize
}

首先,请确保composition和资源的首选变换相同。 入门项目包括orientation(from:),它返回视频的方向(纵向还是横向)。 如果方向是纵向,则在检查视频尺寸时需要反转宽度和高度。 否则,您可以使用原始尺寸。

现在,您已经创建了一个新的composition,其中包括原始文件中的视频和音频。 接下来,您将设置图层,以确保可以向composition中的视频添加背景和叠加层。

3. Core Animation – The Star of the Show

AVFoundation框架解析(二十三) —— 向视频层添加叠加层和动画(一)_第2张图片

您的背景和叠加层均为CALayersCALayer是称为Core Animation的框架的主要类。

Core Animation位于应用程序中每个视图的后面,负责绘制内容并为其设置动画。 由于CALayer支持所有视图,因此手机屏幕上绘制的所有内容都是一个图层。

顾名思义,您可以在其他图层的下方或上方绘制图层,使其非常适合在视频中添加背景或叠加层。 您可以通过AVFoundation合适的类AVVideoCompositionCoreAnimationTool在视频中利用此功能。 这是compositionCore Animation之间的桥梁,可让您创建将CALayers应用于视频composition的新视频。

首先,您需要三个不同的层。 一层是背景,绘制在视频后面。 第二层绘制视频的帧。 第三层是在视频层顶部绘制的覆盖层。

AVFoundation框架解析(二十三) —— 向视频层添加叠加层和动画(一)_第3张图片

4. Layering the Cake

通过将以下代码添加到makeBirthdayCard(fromVideoAt:forName:onComplete :)的末尾来创建三层:

let backgroundLayer = CALayer()
backgroundLayer.frame = CGRect(origin: .zero, size: videoSize)
let videoLayer = CALayer()
videoLayer.frame = CGRect(origin: .zero, size: videoSize)
let overlayLayer = CALayer()
overlayLayer.frame = CGRect(origin: .zero, size: videoSize)

每层将具有相同的frame,跨越整个视频。

接下来,通过将所有这些层添加到方法中,将所有这些层组装为单个父层:

let outputLayer = CALayer()
outputLayer.frame = CGRect(origin: .zero, size: videoSize)
outputLayer.addSublayer(backgroundLayer)
outputLayer.addSublayer(videoLayer)
outputLayer.addSublayer(overlayLayer)

在这里,您将创建一个新图层,它将成为最终composition的图层。 首先添加背景层,然后添加视频层,最后添加叠加层。 添加这些层的顺序很重要。 在这里,您将视频布置在叠加层后面,将背景布置在视频后面。

现在,您可能会急于构建项目并查看结果。 不幸的是,您还没有视频要播放!

AVFoundation框架解析(二十三) —— 向视频层添加叠加层和动画(一)_第4张图片

您已经设置好图层,但是仍然必须使用AVFoundation从这些图层导出视频。


Exporting the Video

现在,您已经拥有了所有的图层,是时候使用AVVideoCompositionCoreAnimationTool将它们组合成美味的视频合成蛋糕了!

1. Creating a Video Composition

将以下内容添加到方法中:

let videoComposition = AVMutableVideoComposition()
videoComposition.renderSize = videoSize
videoComposition.frameDuration = CMTime(value: 1, timescale: 30)
videoComposition.animationTool = AVVideoCompositionCoreAnimationTool(
  postProcessingAsVideoLayer: videoLayer, 
  in: outputLayer)

首先,创建一个新的AVMutableVideoComposition。 您之前创建的compositionAVComposition,它可以保存视频,音频和其他类型的音轨。 另一方面,您仅使用AVVideoComposition来合成视频轨道。 在这种情况下,您只需要一个视频轨道。

接下来,将渲染视频的尺寸设置为等于原始视频的尺寸。 frameDuration确定帧持续多长时间。 通过传递值为1且时间标度(timescale)30CMTime,可以将帧持续时间设置为1/30秒,从而产生具有每秒30帧速率的视频。

视频合成(composition)的最后一点是添加动画工具。 此工具将组装的输出层和视频层带入视频层,并将视频轨道渲染到视频层中。

接下来,添加以下代码以将视频轨道添加到视频composition中:

let instruction = AVMutableVideoCompositionInstruction()
instruction.timeRange = CMTimeRange(
  start: .zero, 
  duration: composition.duration)
videoComposition.instructions = [instruction]
let layerInstruction = compositionLayerInstruction(
  for: compositionTrack, 
  assetTrack: assetTrack)
instruction.layerInstructions = [layerInstruction]

视频composition使用指令集来确定随时显示在视频中的内容。 在这种情况下,您只需要一条指令就可以在整个composition过程中显示组合的视频。

每个指令可以具有自己的分层指令,这些分层指令确定如何分层不同的视频轨道。 入门项目包括一个有用的方法,称为compositionLayerInstruction,它为您的视频返回正确的指令。 这些说明告诉视频进行缩放和旋转以匹配原始视频的尺寸和方向。 如果没有此指示,竖屏视频将显示为横屏,并导致怪异的视频拉伸。

现在,您拥有了所有必需的片段:一个包含原始视频和音频的新合成,以及一个将视频渲染到您的多层蛋糕中的视频合成。 您将在导出会话(export session)中合并这些片段。

2. Using an Export Session

创建导出会话(export session)以将视频渲染到文件:

guard let export = AVAssetExportSession(
  asset: composition, 
  presetName: AVAssetExportPresetHighestQuality) 
  else {
    print("Cannot create export session.")
    onComplete(nil)
    return
}

您可以通过传递其组成composition并使用最高质量视频的预设来创建新的AVAssetExportSession。 最优质的生日贺卡,最优质的朋友。

现在,创建一个文件路径并设置导出会话:

let videoName = UUID().uuidString
let exportURL = URL(fileURLWithPath: NSTemporaryDirectory())
  .appendingPathComponent(videoName)
  .appendingPathExtension("mov")

export.videoComposition = videoComposition
export.outputFileType = .mov
export.outputURL = exportURL

在这里,您可以使用UUID获得唯一的随机字符串,并将其用作文件名。 您现在将文件保存到临时目录中; 用户可以稍后决定将其存储在照片库中。

然后,确保导出会话知道文件的URL和扩展名,并为其提供您之前创建的视频组成以呈现视频。

仍在makeBirthdayCard(fromVideoAt:forName:onComplete :)中,通过添加以下内容来启动导出:

export.exportAsynchronously {
  DispatchQueue.main.async {
    switch export.status {
    case .completed:
      onComplete(exportURL)
    default:
      print("Something went wrong during export.")
      print(export.error ?? "unknown error")
      onComplete(nil)
      break
    }
  }
}

开始导出时,最终将通过在后台线程上调用完成处理程序来完成导出。 确保调度到主线程,然后检查导出结果。 如果成功完成,请使用导出文件的URL调用完成处理程序(completion handler)。 如果出了点问题,您就会知道:打印出错误和带有nilcompletion

现在,终于到了构建和运行项目的时候了。 选择一个视频并输入一个名称,然后在您的设备稍等之后…您会看到与以前相同的结果。

AVFoundation框架解析(二十三) —— 向视频层添加叠加层和动画(一)_第5张图片

是的,您完成所有这些工作都是为了获得完全相同的结果。 只是不一样。 背景和叠加层正在渲染,只是它们目前完全透明,因为您还没有添加任何内容。 所以开始添加东西!


Adding a Background

现在,您已经设置了用于制作视频的应用程序,就可以开始为视频添加色彩,使其看起来像一张生日贺卡。

在视频下方绘制背景层。 当前,视频与背景一样大,因此您首先需要裁剪视频以使背景从下方显示。 背景层将充当视频的边框。 然后,您将图像添加到背景图层,以使边框充满纸屑。

makeBirthdayCard(fromVideoAt:forName:onComplete :)中,在创建三层的下面,在设置overlayLayerframe的行的下面,添加以下代码:

backgroundLayer.backgroundColor = UIColor(named: "rw-green")?.cgColor
videoLayer.frame = CGRect(
  x: 20,
  y: 20, 
  width: videoSize.width - 40, 
  height: videoSize.height - 40)

在这里,您可以为图层添加背景色,以便在运行应用程序时可以清楚地看到发生了什么。 接下来,将图层的frame设置为在每条边上缩小20点,为视频提供20点宽的绿色边框。

构建并运行该项目,选择一个视频,然后将其导出,您将在视频周围看到一个边框。

AVFoundation框架解析(二十三) —— 向视频层添加叠加层和动画(一)_第6张图片

现在您可以看到视频周围的背景了,通过在您刚刚写的内容下面添加以下代码,将图像添加到背景层:

backgroundLayer.contents = UIImage(named: "background")?.cgImage
backgroundLayer.contentsGravity = .resizeAspectFill

要使用Core Animation显示图片,请设置CALayercontents为图片。 还要将contentsGravity设置为.resizeAspectFill,以确保图像始终填充图层的大小,同时保持其纵横比。

再次构建并运行,您将看到边界,现在到处都是可爱的小五彩纸屑!

AVFoundation框架解析(二十三) —— 向视频层添加叠加层和动画(一)_第7张图片

设置好背景后,您就可以处理视频顶部的内容了。

注意:iOS版本的Simulator中存在一个错误,包括13.2.2,其中您要添加的背景和图像将显示为黑色。 如果遇到此错误,则需要在设备上运行才能看到您的手工作品。


Adding Images

您将通过在视频中添加图片来开始视频叠加之旅。 入门项目已经包含SwiftAndroid和恐龙(出于某种原因)的图像,它们在生日聚会上玩得很开心。

AVFoundation框架解析(二十三) —— 向视频层添加叠加层和动画(一)_第8张图片

VideoEditor.swift中添加一个新方法,该方法会将图像添加到图层:

private func addImage(to layer: CALayer, videoSize: CGSize) {
  let image = UIImage(named: "overlay")!
  let imageLayer = CALayer()
}

就像您对背景所做的一样,请使用普通的CALayer来保存图像。 接下来,将以下内容添加到方法中以设置图像的frame,使其位于视频底部的中心:

let aspect: CGFloat = image.size.width / image.size.height
let width = videoSize.width
let height = width / aspect
imageLayer.frame = CGRect(
  x: 0, 
  y: -height * 0.15, 
  width: width, 
  height: height)

在这里,您首先要计算图像的长宽比。 图片将与视频一样宽,因此您必须使用宽高比来确定图片的高度。 无论图像的大小如何,都可以使它适合纵横比。

您不希望显示图片的底部,因此将图片的y坐标设置为负值,这样可以确保图片在视频下方开始播放。

接下来,将图像添加到图像层,并将图像层添加到方法内部传递的层。

imageLayer.contents = image.cgImage
layer.addSublayer(imageLayer)

返回makeBirthdayCard(fromVideoAt:forName:onComplete :),在设置contentsGravity后立即在后台代码之后调用您的方法:

addImage(to: overlayLayer, videoSize: videoSize)

您不再需要在后台工作; 相反,您想在视频顶部显示图像。 这就是为什么您将overlayLayer传递给该方法的原因。

构建并运行项目,选择一个视频,您应该看到该图像显示在视频上。

AVFoundation框架解析(二十三) —— 向视频层添加叠加层和动画(一)_第9张图片

现在,您知道了如何向视频添加叠加层。 看起来像是一场真正的派对! 在下一部分中,您将通过添加一些文字来改进生日贺卡。


Adding Text

如果没有说“Happy Birthday”,那将不会是一张生日贺卡,因此您需要在视频中添加文字。 在VideoEditor.swift中,添加一个新方法:

private func add(text: String, to layer: CALayer, videoSize: CGSize) {
}

要显示文本,您将使用称为CATextLayerCALayer子类。 由于子类具有一些繁琐的API,因此您将使用NSAttributedString创建和自定义文本。 将以下代码添加到刚创建的方法中:

let attributedText = NSAttributedString(
  string: text,
  attributes: [
    .font: UIFont(name: "ArialRoundedMTBold", size: 60) as Any,
    .foregroundColor: UIColor(named: "rw-green")!,
    .strokeColor: UIColor.white,
    .strokeWidth: -3])

使用此代码,您可以创建属性字符串,并确保其使用大而圆的字体。 您将文字设为绿色,因此很容易看到并添加白色描边,这样文字就可以在所有背景上使用。 如果希望文本既有描边又有填充,则需要使描边宽度为负; 否则,只会显示描边。 不要怀疑为什么会这样,就是这样。

接下来,使用属性字符串创建一个文本层:

let textLayer = CATextLayer()
textLayer.string = attributedText
textLayer.shouldRasterize = true
textLayer.rasterizationScale = UIScreen.main.scale
textLayer.backgroundColor = UIColor.clear.cgColor
textLayer.alignmentMode = .center

这将创建一个文本层并设置文本。 您确保使用与当前屏幕的比例相匹配的比例对文本进行光栅化,以使其看起来不会模糊。 最后,为图层提供透明的背景并将文本居中。

现在,设置文本的frame并将其添加到图层中:

textLayer.frame = CGRect(
  x: 0, 
  y: videoSize.height * 0.66, 
  width: videoSize.width, 
  height: 150)
textLayer.displayIfNeeded()
layer.addSublayer(textLayer)

在将其添加到图层之前,请在文本图层上调用displayIfNeeded()CALayersUIViews一样,都是异步更新的,有时Core Animation不会在视频的前一秒或后两秒显示文本。 通过调用此方法,可以确保Core Animation尽快渲染文本。

最后,返回makeBirthdayCard(fromVideoAt:forName:onComplete :),在对addImage(to:videoSize :)的调用下直接调用新方法:

add(
  text: "Happy Birthday,\n\(name)", 
  to: overlayLayer, 
  videoSize: videoSize)

就像处理图像一样,将文本添加到覆盖层。

构建并运行该项目,选择一个视频,然后输入朋友的名字。 本教程将把卡片发给Ray。 导出后,您会看到一行文字,祝您的朋友生日快乐!

AVFoundation框架解析(二十三) —— 向视频层添加叠加层和动画(一)_第10张图片

今天是否实际上是您朋友的生日,都不应阻止您庆祝,因为您的生日贺卡现在看起来不错! 但是仍然缺少的一件事是运动。 继续阅读以了解如何向叠加层添加动画。


Adding Animations

关于CALayers的一件好事是,正如Core Animation所暗示的那样,它们是可动画的! 为了使您的生日贺卡更具动态感,您将在文本中添加缩放动画以使其放大和缩小。

add(text:to:videoSize :)中,在最后一行之前添加以下行,在该行中您将文本图层添加为图层的子图层:

let scaleAnimation = CABasicAnimation(keyPath: "transform.scale")

CABasicAnimation使您可以在两个特定值之间向CALayers添加简单的动画。 CABasicAnimation使用键值观察来设置和读取动画值。 在这种情况下,您将设置变换的比例。

接下来,通过在刚添加的行下方添加以下代码来设置动画:

scaleAnimation.fromValue = 0.8
scaleAnimation.toValue = 1.2
scaleAnimation.duration = 0.5
scaleAnimation.repeatCount = .greatestFiniteMagnitude
scaleAnimation.autoreverses = true
scaleAnimation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)

此代码在0.5秒内将文本从0.8缩放为1.2。 您希望此动画无限期重复,因此请将重复计数设置为.greatestFiniteMagnitude。 您还可以将autoreverses设置为true,以便scale0.81.2之间来回反弹。

最后,设置一些其他设置并将动画添加到图层:

scaleAnimation.beginTime = AVCoreAnimationBeginTimeAtZero
scaleAnimation.isRemovedOnCompletion = false
textLayer.add(scaleAnimation, forKey: "scale")

在向视频添加动画时,请务必将beginTime设置为AVCoreAnimationBeginTimeAtZero;否则,动画将永远不会开始。 您还需要确保动画不会在完成时被删除。

构建并运行该项目,然后选择一个视频。

不用了无聊的静态生日贺卡,现在您的文本可以上下缩放!您使卡片更具动态性,但是为什么要停在那里?在下一部分中,您也将五彩纸屑添加到您的生日贺卡中!


Adding the Final Touches

除了CATextLayer,还有许多其他强大的CALayer子类。例如,CAGradientLayer显示颜色渐变。 CAReplicatorLayer允许您通过根据一组规则重复一层来创建样式。使用CAShapeLayer,您可以绘制圆形,椭圆形,弧形,多边形甚至任意形状。通过将其与CAAnimation结合使用,您可以动态更改形状并为其设置动画效果,从而产生一些很酷的效果。

没有五彩纸屑的生日是不完整的,这就是为什么要最后添加五彩纸屑效果的原因。五彩纸屑将从视频的顶部落下。幸运的是,这是数字纸屑,因此您以后无需清理混乱。

要创建五彩纸屑,您将使用另一个称为CAEmitterLayerCALayer子类,该子类可用于创建粒子效果。您可以确定图层的形状,并设置所需的粒子出生率,​​速度和其他设置。然后,该层将根据其形状发出粒子。

入门项目已经包括一个名为addConfetti(to :)的方法,该方法通过将随机的五彩纸屑图像和随机的颜色组合在一起来创建16个不同的粒子。然后,将CAEmitterLayer设置为具有这16个粒子的视频层正上方的线。结果是五彩纸屑从视频顶部掉落!

要添加五彩纸屑,请在最后一次滚动到makeBirthdayCard(fromVideoAt:forName:onComplete :),然后在调用addImage(to:videoSize :)的上方调用该方法:

addConfetti(to: overlayLayer)

构建并运行该项目,并享受CALayers的荣耀!

通过添加五彩纸屑,您可以使生日贺卡获得至少10倍的胜利。 相信我,我自己算了算。

到目前为止,您应该得到一张卡片,祝贺您在此AVFoundation教程中学到的一切! 您学习了如何使用AVVideoCompositionCoreAnimationToolCALayers与视频结合起来以添加背景和叠加层,如何制作视频合成以及如何将视频导出到文件。

后记

本篇主要讲述了向视频层添加叠加层和动画,感兴趣的给个赞或者关注~~~

AVFoundation框架解析(二十三) —— 向视频层添加叠加层和动画(一)_第11张图片

你可能感兴趣的:(AVFoundation框架解析(二十三) —— 向视频层添加叠加层和动画(一))