iOS视频应用开发:如何在指定时段为视频添加文字?
实现视频添加文字水印(基于CATextLayer + AVFoundation)
你要做的本地视频选片加文字水印功能,用CATextLayer结合AVFoundation就能搞定,我把你的代码补全并整理了完整实现,顺便给你拆解关键步骤:
完整代码实现
- (void)createWatermark:(UIImage*)image video:(NSURL*)videoURL { if (videoURL == nil) return; // 加载原视频资源 AVURLAsset* videoAsset = [[AVURLAsset alloc] initWithURL:videoURL options:nil]; CMTime videoDuration = videoAsset.duration; // 创建视频合成容器 AVMutableComposition* mixComposition = [AVMutableComposition composition]; // 添加原视频轨道到合成容器 AVMutableCompositionTrack* compositionVideoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; AVAssetTrack* videoTrack = [[videoAsset tracksWithMediaType:AVMediaTypeVideo] firstObject]; NSError* error = nil; [compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoDuration) ofTrack:videoTrack atTime:kCMTimeZero error:&error]; if (error) { NSLog(@"插入视频轨道失败: %@", error.localizedDescription); return; } // 初始化视频合成配置 AVMutableVideoComposition* videoComposition = [AVMutableVideoComposition videoCompositionWithPropertiesOfAsset:videoAsset]; videoComposition.renderSize = videoTrack.naturalSize; videoComposition.frameDuration = CMTimeMake(1, 30); // 按30帧每秒渲染 // 创建图层容器:用于承载原视频层和水印层 CALayer* parentLayer = [CALayer layer]; CALayer* videoLayer = [CALayer layer]; parentLayer.frame = CGRectMake(0, 0, videoComposition.renderSize.width, videoComposition.renderSize.height); videoLayer.frame = parentLayer.frame; [parentLayer addSublayer:videoLayer]; // 配置文字水印的CATextLayer CATextLayer* textLayer = [CATextLayer layer]; textLayer.string = @"我的专属水印"; // 替换成你需要的水印文字 textLayer.font = (__bridge CFTypeRef)(@"PingFang SC"); // 设置字体 textLayer.fontSize = 32.0; textLayer.foregroundColor = [UIColor whiteColor].CGColor; textLayer.backgroundColor = [UIColor blackColor].CGColor; textLayer.opacity = 0.8; // 调整水印透明度 textLayer.alignmentMode = kCAAlignmentCenter; // 计算文字尺寸,设置水印位置(示例为右下角,可自行调整) CGSize textSize = [textLayer.string sizeWithAttributes:@{NSFontAttributeName: [UIFont fontWithName:@"PingFang SC" size:32.0]}]; CGFloat margin = 20.0; textLayer.frame = CGRectMake( videoComposition.renderSize.width - textSize.width - margin, videoComposition.renderSize.height - textSize.height - margin, textSize.width, textSize.height ); [parentLayer addSublayer:textLayer]; // 将图层容器关联到视频合成配置 videoComposition.animationTool = [AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer]; // 创建导出会话,生成带水印的视频 AVAssetExportSession* exportSession = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetHighestQuality]; exportSession.outputURL = [self outputVideoURL]; exportSession.outputFileType = AVFileTypeMP4; exportSession.videoComposition = videoComposition; exportSession.shouldOptimizeForNetworkUse = YES; // 执行导出,完成后回调 [exportSession exportAsynchronouslyWithCompletionHandler:^{ dispatch_async(dispatch_get_main_queue(), ^{ switch (exportSession.status) { case AVAssetExportSessionStatusCompleted: NSLog(@"水印添加完成!视频路径:%@", exportSession.outputURL.path); // 这里可以添加后续操作,比如保存到相册、预览视频等 break; case AVAssetExportSessionStatusFailed: NSLog(@"导出失败:%@", exportSession.error.localizedDescription); break; case AVAssetExportSessionStatusCancelled: NSLog(@"导出已取消"); break; default: break; } }); }]; } // 生成视频输出路径的辅助方法 - (NSURL*)outputVideoURL { NSString* docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]; NSString* fileName = [NSString stringWithFormat:@"watermarked_%lld.mp4", (long long)[[NSDate date] timeIntervalSince1970]]; return [NSURL fileURLWithPath:[docDir stringByAppendingPathComponent:fileName]]; }
关键细节说明
- 轨道处理:必须把原视频的轨道插入到
AVMutableComposition中,这是后续添加水印的基础,确保原视频内容能被纳入合成流程。 - CATextLayer配置:你可以根据需求自由修改文字内容、字体、颜色、位置——比如想把水印放左上角,就调整
textLayer.frame的x和y值为margin即可;字体要确保设备上存在,避免显示异常。 - 图层关联:通过
AVVideoCompositionCoreAnimationTool把视频层和水印层绑定,这一步是让水印能被渲染到最终视频里的核心操作。 - 导出注意:导出操作是异步的,完成后一定要切回主线程处理UI提示;另外要记得在
Info.plist中添加相册访问权限(NSPhotoLibraryUsageDescription),不然选视频会被系统拦截。
内容的提问来源于stack exchange,提问作者Anand Gautam
相关产品推荐
相关产品推荐

