版本記錄
版本號 | 時間 |
---|---|
V1.0 | 2017.09.14 |
前言
GPUImage
是直接利用顯卡實現(xiàn)視頻或者圖像處理的技術(shù)。感興趣可以看上面幾篇文章。
1. GPUImage解析(一) —— 基本概覽(一)
2. GPUImage解析(二) —— 基本概覽(二)
3. GPUImage解析(三) —— 基本概覽(三)
4. GPUImage解析(四) —— 安裝方法及框架介紹
5. GPUImage解析(五) —— 框架中的幾個基類
6. GPUImage解析(六) —— 一個簡單的實例(一)
7. GPUImage解析(七) —— 一個簡單的實例結(jié)合GPUImageVideoCamera(二)
8. GPUImage解析(八) —— 一個簡單的實例之多濾鏡視頻采集存儲(三)
9. GPUImage解析(九) —— 一個簡單的實例之GPUImageTiltShiftFilter濾鏡處理(四)
10. GPUImage解析(十) —— 一個簡單的實例之實時更改視頻的濾鏡值(五)
11. GPUImage解析(十一) —— 一個簡單的實例之視頻的疊加混合(六)
功能要求
實現(xiàn)視頻添加水印的效果。
功能實現(xiàn)
下面看示例代碼。
#import "JJGPUWatermarkVC.h"
#import "GPUImage.h"
#import <AssetsLibrary/ALAssetsLibrary.h>
#import "Masonry.h"
#define kWidth [UIScreen mainScreen].bounds.size.width
#define kHeight [UIScreen mainScreen].bounds.size.height
@interface JJGPUWatermarkVC ()
@property (nonatomic, strong) GPUImageMovie *imageMovie;
@property (nonatomic, strong) GPUImageOutput <GPUImageInput> *blendFilter;
@property (nonatomic, strong) GPUImageMovieWriter *movieWriter;
@property (nonatomic, strong) UILabel *tipLabel;
@property (nonatomic, strong) GPUImageView *imageView;
@property (nonatomic, copy) NSString *pathStr;
@property (nonatomic, strong) NSURL *movieURL;
@end
@implementation JJGPUWatermarkVC
#pragma mark - Override Base Function
- (void)viewDidLoad
{
[super viewDidLoad];
[self setupUI];
[self setupConfig];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.navigationController.navigationBarHidden = YES;
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
self.navigationController.navigationBarHidden = NO;
}
#pragma mark - Object Private Function
- (void)setupUI
{
//實例化GPUImageView
self.imageView = [[GPUImageView alloc] initWithFrame:self.view.frame];
[self.view addSubview:self.imageView];
//顯示label
self.tipLabel = [[UILabel alloc] init];
self.tipLabel.textColor = [UIColor blueColor];
self.tipLabel.font = [UIFont systemFontOfSize:20.0];
[self.view addSubview:self.tipLabel];
[self.tipLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(self.view);
make.top.equalTo(self.view).offset(20.0);
}];
}
- (void)setupConfig
{
//濾鏡
self.blendFilter = [[GPUImageDissolveBlendFilter alloc] init];
[(GPUImageDissolveBlendFilter *)self.blendFilter setMix:0.5];
//播放
NSURL *resourceURL = [[NSBundle mainBundle] URLForResource:@"lili" withExtension:@"mp4"];
AVAsset *asset = [AVAsset assetWithURL:resourceURL];
//實例化GPUImageMovie
self.imageMovie = [[GPUImageMovie alloc] initWithAsset:asset];
self.imageMovie.runBenchmark = YES;
self.imageMovie.playAtActualSpeed = YES;
//水印提示文字
UILabel *watermarkLabel = [[UILabel alloc] init];
watermarkLabel.text = @"水印";
watermarkLabel.font = [UIFont systemFontOfSize:30.0];
watermarkLabel.textColor = [UIColor redColor];
//水印圖片
UIView *backView = [[UIView alloc] initWithFrame:self.view.frame];
backView.backgroundColor = [UIColor clearColor];
[self.view addSubview:backView];
UIImageView *watermarkImageView = [[UIImageView alloc] init];
watermarkImageView.image = [UIImage imageNamed:@"light_4"];
watermarkImageView.center = CGPointMake(kHeight / 2, kWidth / 2);
[backView addSubview:watermarkLabel];
[backView addSubview:watermarkImageView];
[watermarkImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.equalTo(backView);
make.height.equalTo(@(50.0));
make.width.equalTo(@(50.0));
}];
[watermarkLabel sizeToFit];
[watermarkLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.equalTo(backView);
}];
//實例化GPUImageUIElement
GPUImageUIElement *uiElement = [[GPUImageUIElement alloc] initWithView:backView];
//存儲相關(guān)
NSString *pathStr = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/Movie.m4v"];
unlink([pathStr UTF8String]);
self.pathStr = pathStr;
NSURL *movieURL = [NSURL fileURLWithPath:pathStr];
self.movieURL = movieURL;
//實例化GPUImageMovieWriter
self.movieWriter = [[GPUImageMovieWriter alloc] initWithMovieURL:movieURL size:CGSizeMake(640.0, 480.0)];
GPUImageFilter *imageFilter = [[GPUImageFilter alloc] init];
[self.imageMovie addTarget:imageFilter];
[imageFilter addTarget:self.blendFilter];
[uiElement addTarget:self.blendFilter];
self.movieWriter.shouldPassthroughAudio = YES;
[self.imageMovie enableSynchronizedEncodingUsingMovieWriter:self.movieWriter];
//顯示
[self.blendFilter addTarget:self.imageView];
[self.blendFilter addTarget:self.movieWriter];
[self.movieWriter startRecording];
[self.imageMovie startProcessing];
CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayProgress)];
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
displayLink.paused = NO;
[imageFilter setFrameProcessingCompletionBlock:^(GPUImageOutput *output, CMTime time){
CGRect frame = watermarkImageView.frame;
frame.origin.x += 0.5;
frame.origin.y += 0.5;
watermarkImageView.frame = frame;
[uiElement updateWithTimestamp:time];
}];
//存儲
__weak typeof(self) weakSelf = self;
[self.movieWriter setCompletionBlock:^{
__strong typeof(self) strongSelf = weakSelf;
[strongSelf.blendFilter removeTarget:strongSelf.movieWriter];
[strongSelf.movieWriter finishRecording];
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(strongSelf.pathStr))
{
[library writeVideoAtPathToSavedPhotosAlbum:strongSelf.movieURL completionBlock:^(NSURL *assetURL, NSError *error)
{
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
NSLog(@"保存失敗");
}
else {
NSLog(@"保存成功");
}
});
}];
}
}];
}
#pragma mark - Action && Notification
- (void)displayProgress
{
NSLog(@"self.imageMovie.progress = %f", self.imageMovie.progress);
self.tipLabel.text = [NSString stringWithFormat:@"Progress = %.2f%%",self.imageMovie.progress * 100];
[self.tipLabel sizeToFit];
}
@end
功能效果
下面我們就給出幾個效果圖。分別是錄制時和存儲在相冊回放時候的效果。
后記
未完,待續(xù)~~~