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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 03:03:26