iOS视频添加水印两种方式(不用到第三方框架) | 您所在的位置:网站首页 › ios视频添加水印怎么设置 › iOS视频添加水印两种方式(不用到第三方框架) |
1、视频加水印,并保存到沙盒当中 //原视频sureasset,有外界传进来 AVURLAsset *asset = (AVURLAsset *)[self addPhotoTitleWithAsset:sureasset][0]; AVMutableVideoComposition *mainCompositionInst = [self addPhotoTitleWithAsset:sureasset][1]; sureasset = asset; AVAssetExportSession *session = [[AVAssetExportSession alloc] initWithAsset: sureasset presetName:AVAssetExportPresetMediumQuality]; NSString *failPath = [self getVideosPath:@"localVideo"];//获取路径 NSURL *filUrl = [NSURL fileURLWithPath:failPath]; session.outputURL = filUrl;//视频输出地址 session.outputFileType = AVFileTypeMPEG4;//AVFileTypeQuickTimeMovie;//AVFileTypeMPEG4; // 这个一般设置为yes(指示输出文件应针对网络使用进行优化,例如QuickTime电影文件应支持“快速启动”) session.shouldOptimizeForNetworkUse = YES; // 文件的最大多大的设置 session.fileLengthLimit = 30 * 1024 * 1024; session.shouldOptimizeForNetworkUse = YES; session.videoComposition = mainCompositionInst; [session exportAsynchronouslyWithCompletionHandler:^(void){ dispatch_async(dispatch_get_main_queue(), ^{ //视频导入成功 //failPath为本地视频地址 completeBlock(failPath,YES); }); }]; //获取路径 - (NSString *)getVideosPath:(NSString *)videoName{ NSString *documents = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0]; documents = [documents stringByAppendingPathComponent:@"CCTV5"]; documents = [self action_addFiles:documents];//判断文件是否存在 NSString *failPath = [documents stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.mp4",videoName]]; return failPath; } #pragma mark- 视频加水印 //添加水印 -(NSArray *)addPhotoTitleWithAsset:(AVAsset *)videoAsset { //1 创建AVAsset实例 //AVURLAsset*videoAsset = [AVURLAsset assetWithURL:[NSURL fileURLWithPath:path]]; AVMutableComposition *mixComposition = [[AVMutableComposition alloc] init]; //3 视频通道 AVMutableCompositionTrack *videoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; [videoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration) ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeVideo] firstObject] atTime:kCMTimeZero error:nil]; //2 音频通道 AVMutableCompositionTrack *audioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid]; [audioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration) ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeAudio] firstObject] atTime:kCMTimeZero error:nil]; //3.1 AVMutableVideoCompositionInstruction 视频轨道中的一个视频,可以缩放、旋转等 AVMutableVideoCompositionInstruction *mainInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction]; mainInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, videoAsset.duration); // 3.2 AVMutableVideoCompositionLayerInstruction 一个视频轨道,包含了这个轨道上的所有视频素材 AVMutableVideoCompositionLayerInstruction *videolayerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoTrack]; [videolayerInstruction setOpacity:0.0 atTime:videoAsset.duration]; // 3.3 - Add instructions mainInstruction.layerInstructions = [NSArray arrayWithObjects:videolayerInstruction,nil]; //AVMutableVideoComposition:管理所有视频轨道,水印添加就在这上面 AVMutableVideoComposition *mainCompositionInst = [AVMutableVideoComposition videoComposition]; AVAssetTrack *videoAssetTrack = [[videoAsset tracksWithMediaType:AVMediaTypeVideo] firstObject]; CGSize naturalSize = videoAssetTrack.naturalSize; //防崩溃处理,这个width可能为空,按比例给他值 if (naturalSize.width == 0) { CGFloat a = (1280.f / 720); naturalSize.width = a * naturalSize.height; } float renderWidth, renderHeight; renderWidth = naturalSize.width; renderHeight = naturalSize.height; mainCompositionInst.renderSize = CGSizeMake(renderWidth, renderHeight); mainCompositionInst.instructions = [NSArray arrayWithObject:mainInstruction]; mainCompositionInst.frameDuration = CMTimeMake(1, 30); [self applyVideoEffectsToComposition:mainCompositionInst size:naturalSize]; NSArray *arrar = [NSArray arrayWithObjects:mixComposition,mainCompositionInst, nil]; return arrar;; } /** 设置水印及其对应视频的位置 @param composition 视频的结构 @param size 视频的尺寸 */ - (void)applyVideoEffectsToComposition:(AVMutableVideoComposition *)composition size:(CGSize)size { // 文字 CATextLayer *subtitle1Text = [[CATextLayer alloc] init]; // [subtitle1Text setFont:@"Helvetica-Bold"]; [subtitle1Text setFontSize:36]; [subtitle1Text setFrame:CGRectMake(10, size.height-10-230, size.width, 100)]; [subtitle1Text setString:@"央视体育5 水印"]; // [subtitle1Text setAlignmentMode:kCAAlignmentCenter]; [subtitle1Text setForegroundColor:[[UIColor whiteColor] CGColor]]; //图片 CALayer*picLayer = [CALayer layer]; //picLayer.contents = (id)[UIImage imageNamed:@"CTVITTRIMSource.bundle/QQ"].CGImage; //本地图片 picLayer.contents = (id)self.videoWaterMarkImage.CGImage; //本地图片2 //NSString *imageUrl = @"http://p1.img.cctvpic.com/photoAlbum/templet/special/PAGEQ1KSin2j2U5FERGWHp1h160415/ELMTnGlKHUJZi7lz19PEnqhM160415_1460715755.png"; //picLayer.contents = (id)[self getImageFromURL:imageUrl].CGImage; //远程图片 CGFloat width = 63; CGFloat leftMargin = 16 * [self scaleSizeWithHeight:size.height]; CGFloat topMargin = 20 * [self scaleSizeWithHeight:size.height]; if (self.videoWaterMarkPlace == WaterMarkTopLeft) { picLayer.frame = CGRectMake(leftMargin, size.height-topMargin-[self scaleSizeWithHeight:size.height]*50, [self scaleSizeWithHeight:size.height]*width, [self scaleSizeWithHeight:size.height]*width); } if (self.videoWaterMarkPlace == WaterMarkBottomLeft) { picLayer.frame = CGRectMake(leftMargin, 20, [self scaleSizeWithHeight:size.height]*50, [self scaleSizeWithHeight:size.height]*50); } if (self.videoWaterMarkPlace == WaterMarkTopRight) { picLayer.frame = CGRectMake(size.width - 20 - [self scaleSizeWithHeight:size.height]*50, size.height-20-[self scaleSizeWithHeight:size.height]*50, [self scaleSizeWithHeight:size.height]*50, [self scaleSizeWithHeight:size.height]*50); } if (self.videoWaterMarkPlace == WaterMarkBottomRight) { picLayer.frame = CGRectMake(size.width - 20 - [self scaleSizeWithHeight:size.height]*50, 20, [self scaleSizeWithHeight:size.height]*50, [self scaleSizeWithHeight:size.height]*50); } // 2 - The usual overlay CALayer *overlayLayer = [CALayer layer]; [overlayLayer addSublayer:picLayer]; // [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); [parentLayer addSublayer:videoLayer]; [parentLayer addSublayer:overlayLayer]; composition.animationTool = [AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer]; } //ios 从网络上获取图片 -(UIImage *) getImageFromURL:(NSString *)fileURL { //https://vod.cctv.cn/cctvsports/cctv5/img/advertisingImage.jpg NSLog(@"执行图片下载函数"); UIImage * result; NSData * data = [NSData dataWithContentsOfURL:[NSURL URLWithString:fileURL]]; result = [UIImage imageWithData:data]; return result; } 2、另一种实现方式 // [self applyVideoEffectsToComposition:mainCompositionInst size:naturalSize]; CIFilter *watermarkFilter = [CIFilter filterWithName:@"CISourceOverCompositing"]; mainCompositionInst = [AVMutableVideoComposition videoCompositionWithAsset:videoAsset applyingCIFiltersWithHandler:^(AVAsynchronousCIImageFilteringRequest * _Nonnull request) { CIImage *watermarkImage = [[CIImage alloc] initWithCGImage:self.videoWaterMarkImage.CGImage]; CIImage *source = request.sourceImage; [watermarkFilter setValue:source forKey:kCIInputBackgroundImageKey]; [watermarkFilter setValue:[watermarkImage imageByApplyingTransform:CGAffineTransformMakeScale(0.5, 0.5)] forKey:kCIInputImageKey]; [watermarkFilter setValue:[watermarkImage imageByApplyingTransform:CGAffineTransformMakeTranslation(14, source.extent.size.height - 14 - watermarkImage.extent.size.height)] forKey:kCIInputImageKey]; [request finishWithImage:watermarkFilter.outputImage context:nil]; }]; // // // 4 - 输出路径 |
CopyRight 2018-2019 实验室设备网 版权所有 |