我正在尝试使用AVSynchronizedLayer在我的avplayer上添加动画。为此,我已经在CALayer上添加了动画并将该图层添加到AVSynchronizedLayer。但是,仅在运行简单的视频时,动画并不能正常工作。
func exportVideoWithAnimation() {
let composition = AVMutableComposition()
let track = self.asset?.tracks(withMediaType: AVMediaType.video)
let videoTrack:AVAssetTrack = track![0] as AVAssetTrack
let timerange = CMTimeRangeMake(kCMTimeZero, (self.asset?.duration)!)
let compositionVideoTrack:AVMutableCompositionTrack = composition.addMutableTrack(withMediaType: AVMediaType.video, preferredTrackID: CMPersistentTrackID())!
do {
try compositionVideoTrack.insertTimeRange(timerange, of: videoTrack, at: kCMTimeZero)
compositionVideoTrack.preferredTransform = videoTrack.preferredTransform
} catch {
print(error)
}
//if your video has sound, you don’t need to check this
if self.audioIsEnabled {
let compositionAudioTrack:AVMutableCompositionTrack = composition.addMutableTrack(withMediaType: AVMediaType.audio, preferredTrackID: CMPersistentTrackID())!
for audioTrack in (self.asset?.tracks(withMediaType: AVMediaType.audio))! {
do {
try compositionAudioTrack.insertTimeRange(audioTrack.timeRange, of: audioTrack, at: kCMTimeZero)
} catch {
print(error)
}
}
}
let size = videoTrack.naturalSize
let videolayer = CALayer()
videolayer.frame = CGRect(x: 0, y: 0, width: size.width, height: size.height)
parentlayer.frame = CGRect(x: 0, y: 0, width: size.width, height: size.height)
parentlayer.addSublayer(videolayer)
//this is the animation part
var time = [0.00001, 4, 9, 12, 16] //I used this
var imgarray = self.selectedImageArray
parentlayer.removeFromSuperlayer()
for image in 0..<self.selectedImageArray.count {
let nextPhoto = imgarray[image]
let horizontalRatio = CGFloat(self.outputSize.width) / nextPhoto.size.width
let verticalRatio = CGFloat(self.outputSize.height) / nextPhoto.size.height
let aspectRatio = min(horizontalRatio, verticalRatio)
let newSize: CGSize = CGSize(width: nextPhoto.size.width * aspectRatio, height: nextPhoto.size.height * aspectRatio)
let x = newSize.width < self.outputSize.width ? (self.outputSize.width - newSize.width) / 2 : 0
let y = newSize.height < self.outputSize.height ? (self.outputSize.height - newSize.height) / 2 : 0
let blackLayer = CALayer()
blackLayer.removeAllAnimations()
//MARK:- Animations
///#1. left->right///
if(self.globalSelectedTransitionTag == 0){
blackLayer.frame = CGRect(x: 0, y: 0, width: videoTrack.naturalSize.width, height: videoTrack.naturalSize.height)
blackLayer.backgroundColor = UIColor.clear.cgColor
blackLayer.opacity = 0
let imageLayer = CALayer()
imageLayer.frame = CGRect(x: x, y: y, width: newSize.width, height: newSize.height)
imageLayer.contents = imgarray[image].cgImage
blackLayer.addSublayer(imageLayer)
let scaleAnimation = CAKeyframeAnimation(keyPath: "transform.scale")
if(image%2==0){
scaleAnimation.values = [0.9, 1.0, 0.9]
}else{
scaleAnimation.values = [1.0, 0.9, 1.0]
}
scaleAnimation.beginTime = CFTimeInterval(time[image])
scaleAnimation.duration = 10
scaleAnimation.isRemovedOnCompletion = false
blackLayer.add(scaleAnimation, forKey: "transform.scale")
let fadeInOutAnimation = CABasicAnimation(keyPath: "opacity")
fadeInOutAnimation.fromValue = 1
fadeInOutAnimation.toValue = 0.6
fadeInOutAnimation.duration = 10
fadeInOutAnimation.beginTime = CFTimeInterval(time[image])
fadeInOutAnimation.isRemovedOnCompletion = false
blackLayer.add(fadeInOutAnimation, forKey: "opacity")
}
//2.right->left
else if(self.globalSelectedTransitionTag == 1){
if(image == 0 || image == 2 || image == 4){
blackLayer.frame = CGRect(x: 0, y: -videoTrack.naturalSize.height, width: videoTrack.naturalSize.width, height: videoTrack.naturalSize.height)
blackLayer.backgroundColor = UIColor.clear.cgColor
let imageLayer = CALayer()
imageLayer.frame = CGRect(x: x, y: y, width: newSize.width, height: newSize.height)
imageLayer.contents = imgarray[image].cgImage
blackLayer.addSublayer(imageLayer)
let animation = CABasicAnimation()
animation.keyPath = "position.y"
animation.fromValue = videoTrack.naturalSize.height
animation.toValue = -2*videoTrack.naturalSize.height
animation.duration = 10
animation.beginTime = CFTimeInterval(time[image])
animation.fillMode = kCAFillModeForwards
animation.isRemovedOnCompletion = false
// animation.speed = 0.7
blackLayer.add(animation, forKey: "basic")
}else{
blackLayer.frame = CGRect(x: 0, y: -videoTrack.naturalSize.height, width: videoTrack.naturalSize.width, height: videoTrack.naturalSize.height)
blackLayer.backgroundColor = UIColor.clear.cgColor
let imageLayer = CALayer()
imageLayer.frame = CGRect(x: x, y: y, width: newSize.width, height: newSize.height)
imageLayer.contents = imgarray[image].cgImage
blackLayer.addSublayer(imageLayer)
let animation = CABasicAnimation()
animation.keyPath = "position.y"
animation.fromValue = -videoTrack.naturalSize.height
animation.toValue = 2*videoTrack.naturalSize.height
animation.duration = 10
animation.beginTime = CFTimeInterval(time[image])
animation.fillMode = kCAFillModeForwards
animation.isRemovedOnCompletion = false
blackLayer.add(animation, forKey: "basic")
}
}else if(self.globalSelectedTransitionTag == 2){
// #4. bottom->top
blackLayer.frame = CGRect(x: 0, y: -videoTrack.naturalSize.height, width: videoTrack.naturalSize.width, height: videoTrack.naturalSize.height)
blackLayer.backgroundColor = UIColor.clear.cgColor
let imageLayer = CALayer()
imageLayer.frame = CGRect(x: x, y: y, width: newSize.width, height: newSize.height)
imageLayer.contents = imgarray[image].cgImage
blackLayer.addSublayer(imageLayer)
if(image%2 == 0 ){
let animation = CABasicAnimation()
animation.keyPath = "position"
animation.fromValue = [200, 200]
animation.toValue = [2200, 2200]
animation.duration = 5
print("CACurrentMediaTime()",CACurrentMediaTime())
animation.beginTime = CFTimeInterval(time[image]); //CACurrentMediaTime() + 5.0;
animation.fillMode = kCAFillModeForwards
animation.isRemovedOnCompletion = false
blackLayer.add(animation, forKey: "basic")
}else{
let animation = CABasicAnimation()
animation.keyPath = "position.y"
animation.fromValue = 2 * videoTrack.naturalSize.height
animation.toValue = -videoTrack.naturalSize.height
animation.duration = 5
animation.beginTime = CFTimeInterval(time[image])
animation.fillMode = kCAFillModeForwards
animation.isRemovedOnCompletion = false
// animation.speed = 0.7
blackLayer.add(animation, forKey: "basic")
let fadeOutAnimation = CABasicAnimation(keyPath: "opacity")
fadeOutAnimation.fromValue = 1
fadeOutAnimation.toValue = 0
fadeOutAnimation.duration = 10
fadeOutAnimation.beginTime = CACurrentMediaTime() + 0.3;
fadeOutAnimation.isRemovedOnCompletion = false
//fadeOutAnimation.speed = 0.7
blackLayer.add(fadeOutAnimation, forKey: "opacity")
}
}else if(self.globalSelectedTransitionTag == 3){
///#5. opacity(1->0)(left->right)///
blackLayer.frame = CGRect(x: -videoTrack.naturalSize.width, y: 0, width: videoTrack.naturalSize.width, height: videoTrack.naturalSize.height)
blackLayer.backgroundColor = UIColor.clear.cgColor
let imageLayer = CALayer()
imageLayer.frame = CGRect(x: x, y: y, width: newSize.width, height: newSize.height)
imageLayer.contents = imgarray[image].cgImage
blackLayer.addSublayer(imageLayer)
let animation = CABasicAnimation()
animation.keyPath = "position.x"
animation.fromValue = -videoTrack.naturalSize.width
animation.toValue = 2 * (videoTrack.naturalSize.width)
animation.duration = 3
animation.beginTime = CFTimeInterval(time[image])
// animation.speed = 0.7
animation.fillMode = kCAFillModeForwards
animation.isRemovedOnCompletion = false
blackLayer.add(animation, forKey: "basic")
let fadeOutAnimation = CABasicAnimation(keyPath: "opacity")
fadeOutAnimation.fromValue = 1
fadeOutAnimation.toValue = 0
fadeOutAnimation.duration = 5
fadeOutAnimation.beginTime = CFTimeInterval(time[image])
fadeOutAnimation.isRemovedOnCompletion = false
// fadeOutAnimation.speed = 0.7
blackLayer.add(fadeOutAnimation, forKey: "opacity")
}
else if(self.globalSelectedTransitionTag == 4){
blackLayer.frame = CGRect(x: 2 * videoTrack.naturalSize.width, y: 0, width: videoTrack.naturalSize.width, height: videoTrack.naturalSize.height)
blackLayer.backgroundColor = UIColor.clear.cgColor
let imageLayer = CALayer()
imageLayer.frame = CGRect(x: x, y: y, width: newSize.width, height: newSize.height)
imageLayer.contents = imgarray[image].cgImage
blackLayer.addSublayer(imageLayer)
let animation = CABasicAnimation()
animation.keyPath = "position.x"
animation.fromValue = 2 * videoTrack.naturalSize.width
animation.toValue = -videoTrack.naturalSize.width
animation.duration = 5
animation.beginTime = CFTimeInterval(time[image])
animation.fillMode = kCAFillModeForwards
animation.isRemovedOnCompletion = false
blackLayer.add(animation, forKey: "basic")
let fadeOutAnimation = CABasicAnimation(keyPath: "opacity")
fadeOutAnimation.fromValue = 1
fadeOutAnimation.toValue = 0
fadeOutAnimation.duration = 15
fadeOutAnimation.beginTime = CFTimeInterval(time[image])
fadeOutAnimation.isRemovedOnCompletion = false
blackLayer.add(fadeOutAnimation, forKey: "opacity")
}else if(self.globalSelectedTransitionTag == 5){
///#7. opacity(1->0)(top->bottom)///
blackLayer.frame = CGRect(x: 0, y: 2 * videoTrack.naturalSize.height, width: videoTrack.naturalSize.width, height: videoTrack.naturalSize.height)
blackLayer.backgroundColor = UIColor.clear.cgColor
let imageLayer = CALayer()
imageLayer.frame = CGRect(x: x, y: y, width: newSize.width, height: newSize.height)
imageLayer.contents = imgarray[image].cgImage
blackLayer.addSublayer(imageLayer)
let animation = CABasicAnimation()
animation.keyPath = "position.y"
animation.fromValue = 2 * videoTrack.naturalSize.height
animation.toValue = -videoTrack.naturalSize.height
animation.duration = 3
animation.beginTime = CFTimeInterval(time[image])
animation.fillMode = kCAFillModeForwards
animation.isRemovedOnCompletion = false
// animation.speed = 0.7
blackLayer.add(animation, forKey: "basic")
let fadeOutAnimation = CABasicAnimation(keyPath: "opacity")
fadeOutAnimation.fromValue = 1
fadeOutAnimation.toValue = 0
fadeOutAnimation.duration = 3
fadeOutAnimation.beginTime = CFTimeInterval(time[image])
fadeOutAnimation.isRemovedOnCompletion = false
//fadeOutAnimation.speed = 0.7
blackLayer.add(fadeOutAnimation, forKey: "opacity")
}
else if(self.globalSelectedTransitionTag == 6){
//#10. scale(big->small->big)///
if(image == 0){
blackLayer.frame = CGRect(x: 0, y:0, width: videoTrack.naturalSize.width, height: videoTrack.naturalSize.height)
blackLayer.backgroundColor = UIColor.clear.cgColor
let imageLayer = CALayer()
imageLayer.frame = CGRect(x: x, y: y, width: newSize.width, height: newSize.height)
imageLayer.contents = imgarray[image].cgImage
blackLayer.addSublayer(imageLayer)
let rotationAnimation = CAKeyframeAnimation(keyPath: "transform.rotation")
rotationAnimation.keyTimes = [0,1]
rotationAnimation.values = [0, M_PI]
rotationAnimation.duration = 5
rotationAnimation.beginTime = CFTimeInterval(time[image])
rotationAnimation.repeatCount = 1
blackLayer.add(rotationAnimation, forKey: nil)
}
else if(image == 1){
blackLayer.frame = CGRect(x: 0, y: -videoTrack.naturalSize.height, width: videoTrack.naturalSize.width, height: videoTrack.naturalSize.height)
blackLayer.backgroundColor = UIColor.clear.cgColor
let imageLayer = CALayer()
imageLayer.frame = CGRect(x: x, y: y, width: newSize.width, height: newSize.height)
imageLayer.contents = imgarray[image].cgImage
blackLayer.addSublayer(imageLayer)
let animation = CABasicAnimation()
animation.keyPath = "position.y"
animation.fromValue = -videoTrack.naturalSize.height
animation.toValue = 2 * videoTrack.naturalSize.height
animation.duration = 3
animation.beginTime = CFTimeInterval(time[image])
animation.fillMode = kCAFillModeForwards
animation.isRemovedOnCompletion = false
blackLayer.add(animation, forKey: "basic")
let fadeOutAnimation = CABasicAnimation(keyPath: "opacity")
fadeOutAnimation.fromValue = 1
fadeOutAnimation.toValue = 0
fadeOutAnimation.duration = 3
fadeOutAnimation.beginTime = CFTimeInterval(time[image])
fadeOutAnimation.isRemovedOnCompletion = false
blackLayer.add(fadeOutAnimation, forKey: "opacity")
}else if(image == 2){
blackLayer.frame = CGRect(x: 0, y: 0, width: videoTrack.naturalSize.width, height: videoTrack.naturalSize.height)
blackLayer.backgroundColor = UIColor.clear.cgColor
blackLayer.opacity = 0
let imageLayer = CALayer()
imageLayer.frame = CGRect(x: x, y: y, width: newSize.width, height: newSize.height)
imageLayer.contents = imgarray[image].cgImage
blackLayer.addSublayer(imageLayer)
let scaleAnimation = CAKeyframeAnimation(keyPath: "transform.scale")
scaleAnimation.values = [1, 0, 1]
scaleAnimation.beginTime = CFTimeInterval(time[image])
scaleAnimation.duration = 3
scaleAnimation.isRemovedOnCompletion = false
blackLayer.add(scaleAnimation, forKey: "transform.scale")
let fadeOutAnimation = CABasicAnimation(keyPath: "opacity")
fadeOutAnimation.fromValue = 1
fadeOutAnimation.toValue = 1
fadeOutAnimation.duration = 3
fadeOutAnimation.beginTime = CFTimeInterval(time[image])
fadeOutAnimation.isRemovedOnCompletion = false
blackLayer.add(fadeOutAnimation, forKey: "opacity")
}else if(image == 3){
blackLayer.frame = CGRect(x: 0, y: -videoTrack.naturalSize.height, width: videoTrack.naturalSize.width, height: videoTrack.naturalSize.height)
blackLayer.backgroundColor = UIColor.clear.cgColor
let imageLayer = CALayer()
imageLayer.frame = CGRect(x: x, y: y, width: newSize.width, height: newSize.height)
imageLayer.contents = imgarray[image].cgImage
blackLayer.addSublayer(imageLayer)
let animation = CABasicAnimation()
animation.keyPath = "position.y"
animation.fromValue = -videoTrack.naturalSize.height
animation.toValue = 2 * videoTrack.naturalSize.height
animation.duration = 3
animation.beginTime = CFTimeInterval(time[image])
animation.fillMode = kCAFillModeForwards
animation.isRemovedOnCompletion = false
blackLayer.add(animation, forKey: "basic")
let fadeOutAnimation = CABasicAnimation(keyPath: "opacity")
fadeOutAnimation.fromValue = 1
fadeOutAnimation.toValue = 0
fadeOutAnimation.duration = 3
fadeOutAnimation.beginTime = CFTimeInterval(time[image])
fadeOutAnimation.isRemovedOnCompletion = false
blackLayer.add(fadeOutAnimation, forKey: "opacity")
}
} else{
blackLayer.frame = CGRect(x: 0, y: 0, width: videoTrack.naturalSize.width, height: videoTrack.naturalSize.height)
blackLayer.backgroundColor = UIColor.clear.cgColor
let imageLayer = CALayer()
imageLayer.frame = CGRect(x: x, y: y, width: newSize.width, height: newSize.height)
imageLayer.contents = imgarray[image].cgImage
blackLayer.addSublayer(imageLayer)
if(image%2 == 0 ){
let animation = CABasicAnimation(keyPath: "transform.scale.x")
animation.fromValue = 1
animation.toValue = 2
animation.duration = 5
animation.beginTime = CFTimeInterval(time[image])
animation.fillMode = kCAFillModeForwards
animation.repeatCount = 1
blackLayer.add(animation, forKey: nil)
}else{
let animation = CABasicAnimation(keyPath: "opacity")
animation.fromValue = 0
animation.toValue = 1
animation.duration = 5
animation.beginTime = CFTimeInterval(time[image])
animation.fillMode = kCAFillModeForwards
animation.repeatCount = 1
blackLayer.add(animation, forKey: nil)
}
}
parentlayer.addSublayer(blackLayer)
}
self.playVideoInPlayer(animatedVideoURL:self.globalVideoURL as URL, rowIndexPath: 0)
}
func playVideoInPlayer(animatedVideoURL:URL,rowIndexPath:Int){
let newPlayerItem = AVPlayerItem.init(url:animatedVideoURL )
self.player = AVPlayer.init(playerItem:newPlayerItem)
//let fileURL =
player = AVPlayer(url: self.globalVideoURL as URL)
player.actionAtItemEnd = .none
let videoLayer = AVPlayerLayer(player: player)
videoLayer.frame = view.bounds
videoLayer.videoGravity = .resizeAspectFill
videoContainerView.layer.addSublayer(videoLayer)
let synchronizedLayer = AVSynchronizedLayer(playerItem: newPlayerItem)
synchronizedLayer.frame = UIScreen.main.bounds
synchronizedLayer.addSublayer(parentlayer)
playerLayer.addSublayer(synchronizedLayer)
videoContainerView.layer.addSublayer(parentlayer)
player.play()
}
在此代码之后,动画也不会添加到播放器中。如果有人尝试过,请仔细检查代码并帮助我进一步发展。对此方向的任何指导或支持将是不二之选。谢谢!!