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

SwiftUI视频编辑中CATextLayer字体大小匹配问题求助

解决SwiftUI预览与导出视频中日期字体大小不一致的问题

问题核心

SwiftUI预览里设置14pt的日期字体,导出视频后显示的字体偏小,核心原因是SwiftUI的逻辑点坐标系和AVFoundation视频渲染的像素坐标系不匹配,加上字体设置方式的错误导致尺寸计算偏差。

问题分析

  1. 坐标系差异:SwiftUI的字体大小基于逻辑点(pt),而CATextLayer在视频合成中基于视频的像素分辨率(px)计算,直接乘以屏幕缩放因子无法适配不同分辨率的视频。
  2. 字体设置冲突:同时设置textLayer.fontSize和带尺寸的UIFont实例给textLayer.font,会导致CATextLayer的尺寸计算混乱。
  3. 相对比例缺失:预览时的字体大小是相对于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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 04:37:12