視頻特效製做:如何給視頻添加邊框、水印、動畫以及3D效果

本文內容來自raywenderlich的這篇文章的翻譯:AVFoundation Tutorial: Adding Overlays and Animations to Videosgit

這是我當年作視頻大量參考的文章。寫得很是好,建議看完個人這篇去看原文。github

第一節:給視頻添加邊框less

今天第一節先講解如何爲一個視頻添加邊框和動畫,首先說明的是,這種邊框和動畫並不能直接修改視頻的某一幀給他增長邊框或者產生動畫效果,這種動畫更像是給視頻的上面加一個calayer,而後控制這個layer產生動畫效果。由於具體到某一幀的這種操做不是iphone應該作的他也作不到。iphone

咱們先來看一張圖,瞭解一下給video增長動畫的原理。ide

12.png

動畫層的原理動畫

你能夠看到videoLayer這個東西,其實這個layer就是負責顯示咱們的視頻,和他同級的是一個叫animationLayer的東西,咱們可以掌控而且玩出花樣的實際上是這個叫animationLayer的東西,由於這個animationLayer能夠由咱們本身建立。spa

這裏看一個圖翻譯

VideoEditing.jpg

動畫層的原理code

這是原文中添加邊框的效果。你們能夠思考下原理是什麼?orm

其實很簡單,和咱們videoLayer同級別的layer叫animationLayer(就是上圖的background),他們共同有個父類叫作parentLayer,那麼增長邊框無非是把animationLayer這個layer找個邊框的圖片,而後把他放到videoLayer的下面,而後把videoLayer(crop也就是裁剪)的尺寸控制到恰好能顯示animationLayer的四邊,這樣,不就成了帶邊框的效果麼。

我找了一張帶邊框的圖片。

54.jpg

帶邊框的圖片

咱們這時候建立一個CALayer,而後呢把這個layer的內容設置爲圖片內容。內容以下。

1
2
3
4
CALayer *backgroundLayer = [CALayer layer];
[backgroundLayer setContents:(id)[borderImage CGImage]];
backgroundLayer.frame = CGRectMake(0, 0, size.width, size.height);
[backgroundLayer setMasksToBounds:YES];

咱們建立好了背景layer,那麼須要建立videoLayer了,這時候設置calayer的frame須要注意,這時候你爲了讓videoLayer可以顯示background layer的四邊,因此須要這麼設置。

1
2
3
  CALayer *videoLayer = [CALayer layer];
videoLayer.frame = CGRectMake(_widthBar.value, _widthBar.value,
                             size.width-(_widthBar.value*2), size.height-(_widthBar.value*2));

_widthBar.value就是咱們邊框的寬度,因此這句話的意思就是設置videoLayer的frame使其可以正確顯示background layer的四邊。

這時候,咱們設置好了背景layer和videolayer那麼怎麼讓系統知道,從而在編輯video的時候用到這些設置呢。須要使用這個方法。

1
2
3
4
  [parentLayer addSublayer:backgroundLayer];
    [parentLayer addSublayer:videoLayer];
   composition.animationTool = [AVVideoCompositionCoreAnimationTool
                            videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer];

這裏的composition就是AVMutableVideoComposition,若是不知道是什麼東西,看上一篇blog。 這裏主要是告訴系統咱們的layer層是parentLayer,在parentLayer裏負責video顯示的使咱們的videoLayer。

其實你看到這裏能夠打開demo,找到這個類,而後修改一下parentLayer添加backgroundLayer和videoLayer的順序,看看是什麼狀況。或者本身找幾張圖片,建立幾個layer,把calayer的內容設置爲圖片,而後加到parentLayer裏,看看有什麼變化,總之須要本身多嘗試。

65.png

這種是怎麼作的呢?

這種又是怎麼作的呢?本身思考下。

第二節,如何給視頻添加水印

其實看完第一部分,添加水印的步驟已經呼之欲出,無非就是把咱們本身建的水印放在一個layer上,而後把這個layer添加到videolayer的上面不就好了麼。代碼以下,注意註釋內容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 1 - 這個layer就是用來顯示水印的。
CATextLayer *subtitle1Text = [[CATextLayer alloc] init];
[subtitle1Text setFont:@ "Helvetica-Bold" ];
[subtitle1Text setFontSize:36];
[subtitle1Text setFrame:CGRectMake(0, 0, size.width, 100)];
[subtitle1Text setString:_subTitle1.text];
[subtitle1Text setAlignmentMode:kCAAlignmentCenter];
[subtitle1Text setForegroundColor:[[UIColor whiteColor] CGColor]];
// 2 - The usual overlay
CALayer *overlayLayer = [CALayer layer];
[overlayLayer addSublayer:subtitle1Text];
overlayLayer.frame = CGRectMake(0, 0, size.width, size.height);
[overlayLayer setMasksToBounds:YES];
CALayer *parentLayer = [CALayer layer];
CALayer *videoLayer = [CALayer layer];
parentLayer.frame = CGRectMake(0, 0, size.width, size.height);
videoLayer.frame = CGRectMake(0, 0, size.width, size.height);
// 這裏看出區別了吧,咱們把overlayLayer放在了videolayer的上面,因此水印老是顯示在視頻之上的。
[parentLayer addSublayer:videoLayer];
[parentLayer addSublayer:overlayLayer];
composition.animationTool = [AVVideoCompositionCoreAnimationTool
                              videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer];

SubtitleImage.png

水印內容

第三節:如何給視頻添加動畫

原理不想贅述,一切花樣都在咱們本身建立的layer上,由於咱們用的是layer,因此天然可使用基於CoreAnimation的動畫來使咱們的layer動起來。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
// 1
UIImage *animationImage = [UIImage imageNamed:@ "star.png" ];;
CALayer *overlayLayer1 = [CALayer layer];
[overlayLayer1 setContents:(id)[animationImage CGImage]];
overlayLayer1.frame = CGRectMake(size.width/2-64, size.height/2 + 200, 128, 128);
[overlayLayer1 setMasksToBounds:YES];
CALayer *overlayLayer2 = [CALayer layer];
[overlayLayer2 setContents:(id)[animationImage CGImage]];
overlayLayer2.frame = CGRectMake(size.width/2-64, size.height/2 - 200, 128, 128);
[overlayLayer2 setMasksToBounds:YES];
// 2 - Rotate
if  (_animationSelectSegment.selectedSegmentIndex == 0) {
CABasicAnimation *animation =
[CABasicAnimation animationWithKeyPath:@ "transform.rotation" ];
animation.duration=2.0;
animation.repeatCount=5;
animation.autoreverses=YES;
// rotate from 0 to 360
animation.fromValue=[NSNumber numberWithFloat:0.0];
animation.toValue=[NSNumber numberWithFloat:(2.0 * M_PI)];
animation.beginTime = AVCoreAnimationBeginTimeAtZero;
[overlayLayer1 addAnimation:animation forKey:@ "rotation" ];
animation = [CABasicAnimation animationWithKeyPath:@ "transform.rotation" ];
animation.duration=2.0;
animation.repeatCount=5;
animation.autoreverses=YES;
// rotate from 0 to 360
animation.fromValue=[NSNumber numberWithFloat:0.0];
animation.toValue=[NSNumber numberWithFloat:(2.0 * M_PI)];
animation.beginTime = AVCoreAnimationBeginTimeAtZero;
[overlayLayer2 addAnimation:animation forKey:@ "rotation" ];
// 3 - Fade
else  if (_animationSelectSegment.selectedSegmentIndex == 1) {
CABasicAnimation *animation
=[CABasicAnimation animationWithKeyPath:@ "opacity" ];
animation.duration=3.0;
animation.repeatCount=5;
animation.autoreverses=YES;
// animate from fully visible to invisible
animation.fromValue=[NSNumber numberWithFloat:1.0];
animation.toValue=[NSNumber numberWithFloat:0.0];
animation.beginTime = AVCoreAnimationBeginTimeAtZero;
[overlayLayer1 addAnimation:animation forKey:@ "animateOpacity" ];
animation=[CABasicAnimation animationWithKeyPath:@ "opacity" ];
animation.duration=3.0;
animation.repeatCount=5;
animation.autoreverses=YES;
// animate from invisible to fully visible
animation.fromValue=[NSNumber numberWithFloat:1.0];
animation.toValue=[NSNumber numberWithFloat:0.0];
animation.beginTime = AVCoreAnimationBeginTimeAtZero;
[overlayLayer2 addAnimation:animation forKey:@ "animateOpacity" ];
   // 4 - Twinkle
else  if (_animationSelectSegment.selectedSegmentIndex == 2) {
CABasicAnimation *animation =
[CABasicAnimation animationWithKeyPath:@ "transform.scale" ];
animation.duration=0.5;
animation.repeatCount=10;
animation.autoreverses=YES;
// animate from half size to full size
animation.fromValue=[NSNumber numberWithFloat:0.5];
animation.toValue=[NSNumber numberWithFloat:1.0];
animation.beginTime = AVCoreAnimationBeginTimeAtZero;
[overlayLayer1 addAnimation:animation forKey:@ "scale" ];
animation = [CABasicAnimation animationWithKeyPath:@ "transform.scale" ];
animation.duration=1.0;
animation.repeatCount=5;
animation.autoreverses=YES;
// animate from half size to full size
animation.fromValue=[NSNumber numberWithFloat:0.5];
animation.toValue=[NSNumber numberWithFloat:1.0];
animation.beginTime = AVCoreAnimationBeginTimeAtZero;
[overlayLayer2 addAnimation:animation forKey:@ "scale" ];
}
// 5
CALayer *parentLayer = [CALayer layer];
CALayer *videoLayer = [CALayer layer];
parentLayer.frame = CGRectMake(0, 0, size.width, size.height);
videoLayer.frame = CGRectMake(0, 0, size.width, size.height);
[parentLayer addSublayer:videoLayer];
[parentLayer addSublayer:overlayLayer1];
[parentLayer addSublayer:overlayLayer2];
composition.animationTool = [AVVideoCompositionCoreAnimationTool
                            videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer];
}

Animation.png

動畫效果

第四節:如何給咱們的視頻layer作出3D效果

TiltImage.jpg

3D效果

上面的全部效果都是在咱們的animatinLayer上作文章的,要知道videoLayer他本質上也是個CALayer,那麼其實普通layer能作的事他也同樣能作。代碼以下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 1 - Layer setup
CALayer *parentLayer = [CALayer layer];
CALayer *videoLayer = [CALayer layer];
parentLayer.frame = CGRectMake(0, 0, size.width, size.height);
videoLayer.frame = CGRectMake(0, 0, size.width, size.height);
[parentLayer addSublayer:videoLayer];
// 2 - Set up the transform
CATransform3D identityTransform = CATransform3DIdentity;
// 3 - 具體設置能夠看demo
if  (_tiltSegment.selectedSegmentIndex == 0) {
     identityTransform.m34 = 1.0 / 1000;  // greater the denominator lesser will be the transformation
else  if  (_tiltSegment.selectedSegmentIndex == 1) {
     identityTransform.m34 = 1.0 / -1000;  // lesser the denominator lesser will be the transformation
}
// 4 - 給咱們的video層作rotation
videoLayer.transform = CATransform3DRotate(identityTransform, M_PI/6.0, 1.0f, 0.0f, 0.0f);
// 5 - Composition
composition.animationTool = [AVVideoCompositionCoreAnimationTool
                              videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer];

上面的代碼很容易懂,就是給咱們的video層作rotation,其實你能夠改改demo裏的數據,試試makescale,maketranslate之類的transform。

第五節:如何作出視頻推動效果

具體內容看個人DEMO。

前4節DEMO地址:http://cdn2.raywenderlich.com/wp-content/uploads/2013/05/VideoEditing-Final2.zip

視頻推動DEMO 地址:https://github.com/pingguo-zangqilong/VideoPushDemo

視頻推動demo使用的時候直接點合成,不用選擇視頻。

相關文章
相關標籤/搜索