Swift5中如何在竖屏录制视频顶部中间添加水印
代码中的错误及修复方案
1. 未正确使用AVMutableComposition,导致水印图层无法生效
你创建了AVMutableComposition但未将原视频轨道内容添加进去,且导出时直接使用原始asset而非composition。AVAssetExportSession结合videoComposition.animationTool时,必须基于AVMutableComposition才能让CoreAnimation图层(水印)被正确渲染。
修复代码:
// 替换原composition相关代码 let composition = AVMutableComposition() guard let compositionVideoTrack = composition.addMutableTrack(withMediaType: .video, preferredTrackID: kCMPersistentTrackID_Invalid) else { print("Failed to create composition track") return } do { try compositionVideoTrack.insertTimeRange(CMTimeRangeMake(start: .zero, duration: asset.duration), of: clipVideoTrack, at: .zero) } catch { print("Failed to insert track into composition: \(error)") return } // 导出时使用composition而非asset let exporter = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetMediumQuality)
2. 视频旋转Transform计算错误,导致尺寸异常、空白区域
硬编码的旋转变换没有考虑原视频的preferredTransform(竖屏视频的原始方向信息),直接平移+旋转会导致视频尺寸错位,出现右侧空白。
修复代码:
// 替换原旋转transform代码 let transformer = AVMutableVideoCompositionLayerInstruction(assetTrack: compositionVideoTrack) // 注意这里用composition的轨道 let assetTrackTransform = clipVideoTrack.preferredTransform let videoSize = clipVideoTrack.naturalSize.applying(assetTrackTransform) let renderSize = CGSize(width: abs(videoSize.width), height: abs(videoSize.height)) // 正确设置旋转后的transform transformer.setTransform(assetTrackTransform, at: .zero)
3. 水印图层未适配旋转后的视频尺寸
你设置的水印frame是固定值(417x103),且parentLayer、videoLayer的frame未匹配旋转后的实际渲染尺寸,导致水印可能被移出可视区域或未显示。
修复代码:
// 替换原图层设置代码 let imglogo = UIImage(named: "WatermarkImage") let watermarkLayer = CALayer() watermarkLayer.contents = imglogo?.cgImage // 按比例设置水印尺寸,避免固定值适配问题 let watermarkWidth = renderSize.width * 0.3 // 占宽度30% let watermarkHeight = watermarkWidth * (imglogo?.size.height ?? 1)/(imglogo?.size.width ?? 1) watermarkLayer.frame = CGRect(x: 25, y: 25, width: watermarkWidth, height: watermarkHeight) watermarkLayer.opacity = 0.86 let parentlayer = CALayer() let videoLayer = CALayer() parentlayer.frame = CGRect(x: 0, y: 0, width: renderSize.width, height: renderSize.height) videoLayer.frame = parentlayer.bounds // 直接使用parentlayer的bounds parentlayer.addSublayer(videoLayer) parentlayer.addSublayer(watermarkLayer) // 更新videoComposition的renderSize videoComposition.renderSize = renderSize
4. 导出时长硬编码为60秒,适配性差
instruction.timeRange的duration固定为60秒,如果原视频时长不足60秒,会导致导出异常;若长于60秒,会截断视频。
修复代码:
instruction.timeRange = CMTimeRangeMake(start: .zero, duration: asset.duration)
5. 输出文件类型与路径后缀不匹配
输出路径后缀是.mp4,但exporter?.outputFileType设为.mov,会导致导出文件无法正常播放或格式错误。
修复代码:
exporter?.outputFileType = .mp4 // 或者将输出路径后缀改为.mov
6. 打印语句语法错误
print("videoUrl:::\", outputURL)存在语法错误,引号未正确闭合,会导致编译失败。
修复代码:
print("videoUrl:::\(outputURL)")
内容的提问来源于stack exchange,提问作者Kumar Lav
相关产品推荐
相关产品推荐

