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

使用AVAssetExportSession导出带字幕动画层视频时内存不足问题求助

解决AVAssetExportSession导出大量字幕视频时内存占用过高的问题

问题描述

我开发了一款可录制视频并叠加背景与字幕的应用,播放带字幕的视频时一切正常,但导出含大量字幕的视频时RAM占用剧增,老旧设备更易崩溃。推测所有CALayer在exportAsynchronously(completionHandler:)方法结束前持续占用内存,仅在完成后释放。以下是视频导出示例代码:

mainVideoComposition.animationTool = AVVideoCompositionCoreAnimationTool(
                    postProcessingAsVideoLayer: videoLayer,
                    in: outputLayer)
guard let exporter = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPresetHighestQuality) else {
    errorCallback?(VLError.toError(title: "Could not create exporter"))
    return
}

self.export = exporter
exporter.outputURL = exportURL
exporter.outputFileType = .mp4
exporter.videoComposition = mainVideoComposition
exporter.shouldOptimizeForNetworkUse = true
exporter.exportAsynchronously(completionHandler: { [weak self] in
    guard let self = self else { return }
    if let anError = exporter.error {
        self.errorCallback?(anError)
    } else if exporter.status == AVAssetExportSession.Status.completed {
        self.completionCallback?(AVURLAsset(url: exportURL))
    }
})

请问是否有办法避免内存不足错误?

可行优化方案

1. 动态加载字幕CALayer

不要一次性创建所有字幕对应的CALayer,而是通过自定义视频合成指令,仅在渲染到对应时间段时生成字幕Layer,渲染完成后立即释放:

  • 自定义AVVideoCompositionInstruction子类,设置containsTweening = true确保每帧触发回调。
  • 在AVVideoCompositionLayerInstruction的逻辑中,根据当前时间戳加载对应字幕Layer,使用后立即将其从父层移除并置为nil,让ARC回收内存。

2. 降低导出预设质量

如果业务允许,替换导出预设为更低质量的选项,减少内存占用:

guard let exporter = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPresetMediumQuality) else {
    errorCallback?(VLError.toError(title: "Could not create exporter"))
    return
}

3. 手动管理字幕Layer生命周期

给字幕Layer添加动画时,利用动画完成回调及时移除并释放资源:

// 给字幕Layer添加淡出动画并设置回调
let fadeOut = CABasicAnimation(keyPath: "opacity")
fadeOut.fromValue = 1.0
fadeOut.toValue = 0.0
fadeOut.duration = 0.5
fadeOut.fillMode = .forwards
fadeOut.isRemovedOnCompletion = false
fadeOut.delegate = self

subtitleLayer.add(fadeOut, forKey: "fadeOut")

// 实现CAAnimationDelegate回调移除Layer
func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
    if flag {
        anim.delegate = nil
        subtitleLayer.removeFromSuperlayer()
    }
}

4. 改用AVAssetWriter精细控制导出流程

AVAssetExportSession封装度高,内存优化空间有限。直接使用AVAssetWriter逐帧处理:

  • 逐帧读取视频帧,同步生成对应帧的字幕内容。
  • 将合成后的帧写入文件,写完后立即释放该帧相关资源,从根源避免大量Layer驻留内存。

5. 优化字幕Layer渲染效率

  • 使用CATextLayer替代普通CALayer承载字幕,它对文本渲染的内存优化更友好。
  • 复用相同样式的字幕Layer实例,避免重复创建。
  • 减少字幕的复杂特效(如阴影、多层渐变),降低渲染时的内存开销。

内容的提问来源于stack exchange,提问作者Sergey Zaycev

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 00:47:27