SwiftUI视频编辑中CATextLayer字体大小匹配问题求助
解决SwiftUI预览与导出视频中日期字体大小不一致的问题
问题核心
SwiftUI预览里设置14pt的日期字体,导出视频后显示的字体偏小,核心原因是SwiftUI的逻辑点坐标系和AVFoundation视频渲染的像素坐标系不匹配,加上字体设置方式的错误导致尺寸计算偏差。
问题分析
- 坐标系差异:SwiftUI的字体大小基于逻辑点(pt),而
CATextLayer在视频合成中基于视频的像素分辨率(px)计算,直接乘以屏幕缩放因子无法适配不同分辨率的视频。 - 字体设置冲突:同时设置
textLayer.fontSize和带尺寸的UIFont实例给textLayer.font,会导致CATextLayer的尺寸计算混乱。 - 相对比例缺失:预览时的字体大小是相对于SwiftUI预览视图的,视频中的字体需要保持相同的视觉比例,而非固定像素值。
解决方案
1. 修正字体设置逻辑
移除UIFont初始化的方式,改用字体名称字符串设置font,避免尺寸冲突:
// 替换原有的font设置代码 textLayer.font = "Helvetica" as CFTypeRef textLayer.fontSize = calculatedFontSize
2. 基于相对比例计算字体大小
要让视频中的字体和预览保持一致视觉大小,需要计算预览视图像素尺寸与视频渲染像素尺寸的比例:
- 先获取你在SwiftUI中显示视频预览的视图尺寸(比如
VideoPlayer的父视图尺寸,记为previewViewSize) - 计算比例并得到最终字体大小:
let previewPixelWidth = previewViewSize.width * UIScreen.main.scale let scaleRatio = Composition.renderSize.width / previewPixelWidth let calculatedFontSize = 14 * scaleRatio
如果无法直接获取预览视图尺寸,也可以基于视频自然分辨率和渲染分辨率的比例计算:
let renderScale = Composition.renderSize.width / NaturalSize.width let calculatedFontSize = 14 * UIScreen.main.scale * renderScale
3. 调整文本层的bounds与位置
确保文本层的尺寸基于视频渲染尺寸,而非原始视频的自然尺寸:
textLayer.bounds = CGRect(x: 0, y: 0, width: Composition.renderSize.width, height: 100) textLayer.position = CGPoint(x: Composition.renderSize.width / 2, y: Composition.renderSize.height / 2)
4. 修正contentsScale
将contentsScale设为1.0,因为视频渲染尺寸是像素级,不需要额外缩放:
textLayer.contentsScale = 1.0
修改后的完整函数代码
func DateTextLayer(Composition: AVMutableVideoComposition, videoModel: VideoModel, NaturalSize: CGSize, previewViewSize: CGSize) -> CATextLayer { let textLayer = CATextLayer() textLayer.string = videoModel.VideoDate textLayer.foregroundColor = videoModel.DateColor?.cgColor textLayer.alignmentMode = .center textLayer.contentsScale = 1.0 // 计算适配后的字体大小 let previewPixelWidth = previewViewSize.width * UIScreen.main.scale let scaleRatio = Composition.renderSize.width / previewPixelWidth let calculatedFontSize = 14 * scaleRatio textLayer.font = "Helvetica" as CFTypeRef textLayer.fontSize = calculatedFontSize // 基于渲染尺寸设置文本层位置和大小 textLayer.bounds = CGRect(x: 0, y: 0, width: Composition.renderSize.width, height: 100) textLayer.position = CGPoint(x: Composition.renderSize.width / 2, y: Composition.renderSize.height / 2) return textLayer }
额外注意事项
- 确认字体名称:iOS中
Helvetica实际对应Helvetica Neue,可以通过UIFont.fontNames(forFamilyName: "Helvetica")查看系统可用的字体名称,避免因找不到字体使用默认小字体。 - 多分辨率测试:分别测试1080p、4K等不同分辨率的视频,验证字体大小是否一致。
内容的提问来源于stack exchange,提问作者user1591668
相关产品推荐
相关产品推荐

