iOS 錄製視頻時,添加水印

想要實現這個功能,能夠先了解一下有關錄製視頻的相關知識:素材庫、素材的軌道、合成視頻的工程文件等等,具體能夠參考視頻編輯素材
html

相關術語:ios

AVAsset:素材庫裏的素材; 
AVAssetTrack:素材的軌道; 
AVMutableComposition:一個用來合成視頻的工程文件; 
AVMutableCompositionTrack:工程文件中的軌道,有音頻軌、視頻軌等,裏面能夠插入各類對應的素材; 
AVMutableVideoCompositionLayerInstruction:視頻軌道中的一個視頻,能夠縮放、旋轉等; 
AVMutableVideoCompositionInstruction:一個視頻軌道,包含了這個軌道上的全部視頻素材; 
AVMutableVideoComposition:管理全部視頻軌道,能夠決定最終視頻的尺寸,裁剪須要在這裏進行; 
AVAssetExportSession:配置渲染參數並渲染。複製代碼


問題記錄:git

下面帶橫線的是錯誤思路,一開始走進了誤區,這種方式並不能解決點擊view觸發toucherBegan的問題github

長按拍攝,利用的是touchesbegan開始錄製,touchesEnded結束錄製;存在一個小問題就是點擊這個view的時候,會觸發touchesBegan,然而不會觸發touchesEnded。這裏使用了一個延時機制去觸發touchesBegan事件的觸發,代碼以下
bash

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    NSLog(@"開始觸摸");
    if ([[touches anyObject] view] == self.progressView) {
        if (!self.capture) {    // 表示是否正在錄製
            double delayInSeconds = 0.5; // 長按0.5s觸發錄製事件
            dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
            dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
                [self startCapture]; // 開始錄製
            });
        }else {
            [self startCapture];
        }
        
    }
}複製代碼

解決方案就是用長按手勢來觸發ide

UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(LongPressProgressView:)];
        longPress.minimumPressDuration = 0.5;
        [progressView addGestureRecognizer:longPress];複製代碼

- (void)LongPressProgressView:(UILongPressGestureRecognizer *)gestureRecognizer {
    if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
        [self startCapture];
    }else if (gestureRecognizer.state == UIGestureRecognizerStateEnded) {
        if ([self.mediaCaptureDelegate respondsToSelector:@selector(stopCapture)]) {
            self.capture = NO;
            self.bgView.hidden = YES;
            [self.mediaCaptureDelegate stopCapture];
            [self.progressView clearProgress];
        }
    }
    
}複製代碼

其次有個能夠拖動、縮放、旋轉的文本框,點擊能夠從新編輯,我是封裝了一個類FWTextView,具體代碼能夠從下面的demo裏找到,如圖fetch



最關鍵的一點就是水印的添加,主要功能就是這個麼。先說下思路:ui

首先咱們要知道咱們能看到的視頻其實是由一個叫作videoLayer負責顯示的,和他同級的有個layer叫作animationLayer,咱們可以控制的其實就是這個東西,他能夠由咱們本身建立,他們有一個共同的父類叫作parentLayer。spa

添加圖片水印的代碼:.net

CALayer *imgLayer = [CALayer layer];
    imgLayer.contents = (id)img.CGImage;
    imgLayer.frame = CGRectMake(0, 0, size.width, size.height);複製代碼

建立好了圖片layer後,就須要建立videoLayer

//把文字和圖標都添加到layer
    CALayer *overlayLayer = [CALayer layer];
    [overlayLayer addSublayer:imgLayer];
    overlayLayer.frame = CGRectMake(0, 0, size.width, size.height);
    [overlayLayer setMasksToBounds:YES];
    [overlayLayer addSublayer:imgLayer];
    CALayer *parentLayer = [CALayer layer];
    CALayer *videoLayer = [CALayer layer];
    parentLayer.frame = CGRectMake(0, 0, size.width, size.height);
    parentLayer.backgroundColor = [UIColor redColor].CGColor;
    videoLayer.frame = CGRectMake(0, 0, size.width, size.height);
    [parentLayer addSublayer:videoLayer];
    [parentLayer addSublayer:overlayLayer];
    
    composition.animationTool = [AVVideoCompositionCoreAnimationTool
                                 videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer];複製代碼

這裏主要是告訴系統咱們的layer層時parentLayer,在parentLayer裏負責video顯示的是咱們的videoLayer。想詳細瞭解的可參考視頻特效製做

最後就是錄製完的視頻保存本地,這裏使用的不是系統的,ios10開始ALAssetsLibrary被標誌爲棄用(DEPRECATED),並建議使用Photos framework的PHPhotoLibrary,使用需先引用#import <Photos/Photos.h>

方法1:同步存到系統相冊(iOS10系統執行該方法,沒法保存成功)

__block NSString *createdAssetID =nil;//惟一標識,能夠用於圖片資源獲取
    NSError *error =nil;
    [[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
        createdAssetID = [PHAssetChangeRequest creationRequestForAssetFromImage:image].placeholderForCreatedAsset.localIdentifier;
    } error:&error];複製代碼

補充:

上面的方法1在系統是10的真機上出現保存視頻失敗,更新一下新的方法:

NSString *path = [SNSImageEngine getRealHouseVideoPathWithVideoPath:videoPath];
            if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(path)) {
                UISaveVideoAtPathToSavedPhotosAlbum(path , self, @selector(video:didFinishSavingWithError:contextInfo:), nil);
            }else {
                [MBProgressHUD showMessage:@"保存失敗"];
            }


// 視頻保存回調
- (void)video:(NSString *)videoPath didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
    if (error == nil) {
        [MBProgressHUD showMessage:@"已保存至手機"];
    }else {
        [MBProgressHUD showMessage:@"保存失敗"];
    }
}
複製代碼

上面代碼裏的path是視頻在本地的路徑,還有一個回調方法提供。

方法2:存到某個自定義相冊

[[PHPhotoLibrary sharedPhotoLibrary]performChanges:^{
        PHAssetChangeRequest *changeAssetRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:image];
        PHAssetCollection *targetCollection = [[PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeSmartAlbumUserLibrary options:nil]lastObject];
        PHAssetCollectionChangeRequest *changeCollectionRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:targetCollection];
        PHObjectPlaceholder *assetPlaceholder = [changeAssetRequest placeholderForCreatedAsset];
        [changeCollectionRequest addAssets:@[assetPlaceholder]];
    } completionHandler:^(BOOL success,NSError * _Nullable error) {
        NSLog(@"finished adding");
    }];複製代碼

詳細瞭解參考保存照片到相冊


demo連接:github.com/SXDgit/ZB_A…

到此基本結束了,後期有更新的話,會繼續更新。


需求更改,要求錄製時間加長,大於10s,會出現新的bug。視頻超過10s後,聲音會丟失。

  • 問題所在:AVCaptureMovieFileOutput他有默認的時間限制,默認值是 10 秒
  • 更改辦法:設置 AVCaptureMovieFileOutput 的 movieFragmentInterval 屬性爲 kCMTimeInvalid,視頻錄製就不會受到限制

-(AVCaptureMovieFileOutput *)movieFileOutput{
    
    if (!_movieFileOutput) {
        _movieFileOutput = [[AVCaptureMovieFileOutput alloc] init];
        /*  默認的錄製視頻時間是10秒,若是視頻大於10秒必須禁用他,不然錄製的視頻將會沒有聲音*/
        _movieFileOutput.movieFragmentInterval = kCMTimeInvalid;
    }
    return _movieFileOutput;
}

複製代碼
相關文章
相關標籤/搜索