You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 17:05:18