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

iOS 16:9及Mac Catalyst导出Core Animation图层模糊问题咨询

问题分析与修复方案

核心原因

1. 屏幕缩放比例与视频导出尺寸不匹配

你代码里所有图层的rasterizationScale和contentsScale都用了UIScreen.main.scale,但视频导出的renderSize(也就是videoImageSize)的比例/尺寸和设备屏幕原生比例未必一致:

  • iOS端9:16是手机竖屏原生比例,此时图层无需额外缩放,和屏幕scale匹配,所以导出清晰;
  • 16:9是横屏比例,竖屏设备上图层会被拉伸适配视频尺寸,提前用屏幕scale rasterize的图层会因为二次缩放变模糊;
  • Mac Catalyst的屏幕尺寸和比例和视频导出尺寸差异更大,不管哪种比例都会触发缩放,所以全比例模糊。

2. 图层布局的尺寸基准错了

初始化水印层时传了superviewBounds(屏幕的bounds),如果水印层是按屏幕尺寸创建的,放到尺寸为videoImageSize的父图层里,就会被强制缩放,UILabel、UIImage这类元素一缩放就容易模糊。

3. Rasterize的反向作用

开了shouldRasterize后,图层会先以rasterizationScale的分辨率生成位图,再做布局缩放。要是这个scale和视频导出的实际渲染scale不匹配,位图缩放后肯定模糊;就算关了shouldRasterize,图层本身尺寸适配有问题的话,还是会因为缩放糊。

具体修复步骤

1. 把屏幕scale换成视频导出的实际渲染scale

计算视频导出对应的scale,替换掉所有UIScreen.main.scale:

// 计算视频导出的实际缩放比例,确保和视频尺寸匹配
let exportScale = UIScreen.main.scale * (videoImageSize.width / UIScreen.main.bounds.width)
// 也可以直接用视频的目标像素密度,比如导出2K/4K视频时指定2.0或3.0

然后给所有图层设置这个scale:

// 视频层
videolayer.rasterizationScale = exportScale
videolayer.contentsScale = exportScale
// 父图层
parentlayer.rasterizationScale = exportScale
parentlayer.contentsScale = exportScale
// 水印层(如果存在)
watermarkLayer.rasterizationScale = exportScale
watermarkLayer.contentsScale = exportScale
// 循环处理detailViewLayers
for detailViewLayer in detailViewLayers {
    detailViewLayer.rasterizationScale = exportScale
    detailViewLayer.contentsScale = exportScale
}

2. 改水印层的尺寸基准

调整initWatermarkLayer方法,让它基于videoImageSize(视频导出尺寸)来布局,别用屏幕的superviewBounds,确保水印层直接适配视频尺寸,不用后续缩放:

func initWatermarkLayer(videoSize: CGSize, highlightReelType: HighlightReelType) -> CALayer? {
    let watermarkLayer = CALayer()
    // 按视频尺寸比例计算水印大小,比如占视频宽度的15%
    let watermarkWidth = videoSize.width * 0.15
    let watermarkHeight = watermarkWidth / 2 // 保持水印的宽高比
    // 定位到右下角,留10pt边距
    watermarkLayer.frame = CGRect(
        x: videoSize.width - watermarkWidth - 10,
        y: videoSize.height - watermarkHeight - 10,
        width: watermarkWidth,
        height: watermarkHeight
    )
    // 其他初始化逻辑(比如设置图片、文本)...
    return watermarkLayer
}

3. 优化Rasterize的使用

  • 除非图层有复杂特效需要重复渲染,否则建议关掉shouldRasterize;
  • 要是必须开,一定要保证rasterizationScale和视频最终渲染的像素密度完全一致,别让位图二次缩放。

4. 检查XIB组件的适配

打开对应的XIB文件,检查UILabel和UIImageView:

  • UILabel开启「Adjusts Font Size To Fit Width」,避免文字溢出或拉伸;
  • UIImageView的「Content Mode」设为「Aspect Fit」或「Aspect Fill」,防止图片变形;
  • 组件的约束要基于父视图(不是固定尺寸),适配不同的视频尺寸。

额外验证点

  • 确认videoImageSize和最终导出视频的分辨率一致(比如1080x1920是9:16,1920x1080是16:9);
  • 检查layerComposition.renderSize是不是和videoImageSize完全相同,避免视频渲染时额外缩放。

内容的提问来源于stack exchange,提问作者Curiosity

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 12:57:12