如何在SwiftUI中使用AVCaptionRenderer并预览AVCaption?
如何在SwiftUI的CGContext中预览AVCaption或AVMutableCaption?
我已经能通过SwiftUI的Canvas和context.withCGContext获取CGContext,也知道AVCaptionRenderer有render(in: CGContext)方法,但不清楚它的正确用法。相关资料只有WWDC2021的视频提到:
AVCaptionRenderer类可将单个或一组字幕渲染到CGContext中,以预览其播放时的显示效果。
我写了下面的代码,能编译运行但只显示空白矩形:
import SwiftUI import AVFoundation struct ContentView: View { var body: some View { VStack { Canvas() { context, size in let caption = AVMutableCaption("Subtitle String", timeRange: CMTimeRange(start: CMTime(value: 0, timescale: 1000), duration: CMTime(value: 3, timescale: 1000))) let renderer = AVCaptionRenderer() renderer.captions = [caption] let rect = CGRect(origin: .zero, size: CGSize(width: size.width, height: size.height)) context.withCGContext { ctx in ctx.setFillColor(NSColor.white.cgColor) ctx.setStrokeColor(NSColor.black.cgColor) ctx.setLineWidth(5) renderer.render(in: ctx, for: .positiveInfinity) ctx.addRect(rect) ctx.drawPath(using: .eoFillStroke) } } } .padding() } }
问题原因与修正方案
代码空白的核心原因是没有为AVCaptionRenderer指定渲染边界,同时缺少必要配置让字幕正确显示。以下是修正后的完整代码:
import SwiftUI import AVFoundation struct ContentView: View { var body: some View { VStack { Canvas() { context, size in // 1. 创建字幕并设置基础样式(确保文字可见) let caption = AVMutableCaption("Subtitle String", timeRange: CMTimeRange(start: .zero, duration: CMTime(seconds: 3, preferredTimescale: 1000))) let style = AVMutableCaptionStyle() style.fontSize = 32 style.foregroundColor = .white style.backgroundColor = .black.withAlphaComponent(0.7) caption.style = style // 2. 初始化渲染器并配置关键属性 let renderer = AVCaptionRenderer() renderer.captions = [caption] // 设置字幕渲染的边界区域,与Canvas尺寸一致 renderer.renderingBounds = CGRect(origin: .zero, size: size) // 设置布局策略,让字幕自适应边界 renderer.layoutStrategy = .fitToBounds let rect = CGRect(origin: .zero, size: size) context.withCGContext { ctx in // 绘制灰色背景,方便看清字幕 ctx.setFillColor(NSColor.gray.cgColor) ctx.fill(rect) // 3. 传入处于字幕时间范围内的当前时间,触发渲染 let currentTime = CMTime(seconds: 1, preferredTimescale: 1000) renderer.render(in: ctx, for: currentTime) // 绘制边框作为参考 ctx.setStrokeColor(NSColor.black.cgColor) ctx.setLineWidth(2) ctx.stroke(rect) } } } .padding() } }
关键修改点说明
- 设置渲染边界:必须通过
renderingBounds指定字幕的渲染区域,否则渲染器无法确定布局位置。 - 配置字幕样式:默认样式可能和背景颜色重合导致不可见,显式设置字体大小、前景色和背景色能确保文字清晰。
- 传入有效时间:
render(in:for:)的时间参数需要落在字幕的timeRange范围内(示例中为0-3秒),渲染器才会绘制该字幕。 - 布局策略:
layoutStrategy控制字幕布局方式,.fitToBounds会让字幕自适应边界大小,避免超出显示区域。
内容的提问来源于stack exchange,提问作者A. Saunders
相关产品推荐
相关产品推荐

