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

UIGraphicsGetImageFromCurrentImageContext后续帧返回nil无法生成图片如何解决

问题根因及解决方案

核心原因

92帧后生成图片失败的本质是内存/显存溢出触发系统资源限制,代码存在多处资源积压的逻辑漏洞:

  • 现有autoreleasepool包裹了整个绘图流程,循环内生成的临时渲染缓存、临时对象无法及时释放,内存持续上涨
  • 绘图上下文没有每帧清空,多帧渲染内容持续累积在上下文的显存缓冲区里,占用资源随帧数线性上升
  • 所有生成的UIImage全部存储在images数组中,高清场景下单张图就有数MB甚至数十MB,100帧左右就会触发系统内存上限,直接导致绘图上下文失效
  • 循环边界写为0...count多了一次越界迭代,额外产生无效操作

修正方案

1. 调整autoreleasepool作用范围到循环内部,每帧处理完就释放临时资源

2. 每帧渲染前清空绘图上下文,避免内容累积

3. 不要缓存所有帧到数组,生成一帧就直接传给AssetWriter写入,写完立即释放当前帧

4. 修正循环边界为左闭右开区间

修正后参考代码

// 不需要提前缓存所有image到数组,生成一帧就写一帧
UIGraphicsBeginImageContextWithOptions(settings.size, false, UIScreen.main.scale)
guard let context = UIGraphicsGetCurrentContext() else {
    fatalError("无法获取绘图上下文")
}
let frameCount = drawAnimationObjectsByIndex.count
for index in 0..<frameCount  {
    autoreleasepool {
        guard let object = drawAnimationObjectsByIndex[index] else { return }
        // 清空上一帧的上下文内容
        CGContextClearRect(context, CGRect(origin: .zero, size: settings.size))
        object.parent.render(in: context)
        guard let image = UIGraphicsGetImageFromCurrentImageContext() else {
            os_log("第%d帧生成失败,使用上一帧写入", log: self.tag, type: .debug, index)
            // 这里直接拿上一帧写入AssetWriter,不要缓存到数组
            writeLastFrameToAssetWriter()
            drawAnimationObjectsByIndex[index] = nil
            return
        }
        // 直接写入当前帧到AssetWriter,不要append到images数组
        writeFrameToAssetWriter(image: image)
        drawAnimationObjectsByIndex[index] = nil
    }
}
UIGraphicsEndImageContext()

额外优化建议

如果你的视频尺寸大于1080P,可以把UIGraphicsBeginImageContextWithOptions的scale参数改为1,不需要和屏幕scale一致,能大幅降低每帧的内存占用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.21 06:54:05