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
相关产品推荐
相关产品推荐

