视频导出卡住问题分析与解决方案

问题描述

现象

在导出某些特定时间范围的视频片段时,导出进度会卡在 23% 左右无法继续,持续数分钟甚至更长时间都没有进展。但是,如果将开始时间向前调整一点点(比如 0.2 秒),或者将结束时间向后调整一点点,导出就能正常完成。

具体案例

  • 失败的时间范围: 65.328s - 73.529s → 卡在 23% 不动
  • 成功的时间范围: 调整开始/结束时间后 → 正常导出完成

系统环境

  • iOS 18+
  • 使用 AVAssetExportSession 进行视频导出
  • 导出状态显示为 “exporting”(正在导出中),没有报错
  • 进度条长时间停留在某个百分比不变

问题分析过程

第一步:添加诊断日志

为了定位问题,我们添加了详细的诊断功能:

  1. 进度卡住检测

    • 监控导出进度是否在同一数值停留超过 10 秒
    • 发现确实卡在 23% 持续很长时间
  2. 关键帧分析

    • 分析视频编码结构
    • 检查时间范围起始点和结束点附近的关键帧(I-frame)分布

第二步:关键帧分析结果

通过分析发现了关键信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
🔍 关键帧分析:
- 目标时间范围: 65.328s - 73.529s
- 分析帧数: 366
- 关键帧数: 15 (约 4% 的帧是关键帧)
- 关键帧间隔: 约 0.93 秒

起始点分析:
🔑 最近的关键帧: 65.11s (距离: 0.218s)
⚠️ 起始时间点未对齐关键帧

结束点分析:
🔑 最近的关键帧: 73.512s (距离: 0.017s)
✅ 结束时间点基本对齐关键帧

第三步:根本原因确定

关键帧对齐问题

视频编码采用 GOP (Group of Pictures) 结构:

  • 关键帧(I-frame): 完整的图像数据,可以独立解码
  • 预测帧(P-frame/B-frame): 依赖其他帧的差异数据

当裁剪时间范围的起始点不在关键帧上时:

  1. AVAssetExportSession 无法直接复制压缩数据

    • 因为预测帧需要依赖前面的关键帧才能解码
  2. 系统尝试重新编码

    • 从最近的关键帧(65.11s)开始解码
    • 重新编码 65.11s → 65.328s 之间的帧
  3. 在某些边界条件下会卡住

    • 视频合成(videoComposition)的时间指令可能与实际视频轨道不匹配
    • 导致导出进程无法继续

验证假设

当我们将开始时间从 65.328s 调整到最近的关键帧 65.11s 时,导出能正常完成,证实了关键帧对齐问题是根本原因。


解决方案

方案设计原则

  1. 在视频处理的入口点进行对齐

    • processVideo 方法中,创建所有视频合成(videoComposition)之前
    • 确保所有后续处理都基于对齐后的时间范围
  2. 对齐策略

    • 起始点: 只向前对齐(提前开始),不向后,确保不丢失用户想要的内容
    • 结束点: 可以向前或向后对齐,误差小即可
    • 安全限制: 调整量不超过 1 秒,避免过度偏离用户意图
  3. 为什么不能在导出阶段对齐?

    • 如果在创建 AVAssetExportSession 时才对齐时间范围
    • videoComposition 中的轨迹绘制、慢动作等时间指令已经基于原时间范围创建
    • 会导致 “The video could not be composed” 错误(-11841)

实现步骤

1. 关键帧查找

实现 findNearestKeyFrame() 函数:

  • 使用 AVAssetReader 读取视频帧
  • 检查每一帧的 attachment 属性判断是否为关键帧
  • 返回目标时间附近最近的关键帧时间

2. 时间范围对齐

实现 alignTimeRangeToKeyFrames() 函数:

  • 查找起始点最近的关键帧(只向前查找)
  • 查找结束点最近的关键帧(可前后查找)
  • 返回对齐后的时间范围

3. 在入口点应用对齐

processVideo 方法中:

1
原始时间范围 → 对齐到关键帧 → 创建 videoComposition → 导出

效果验证

对齐前 (失败)

1
2
3
时间范围: 65.328s - 73.529s
起始点未对齐关键帧 (距离 0.218s)
导出进度: 卡在 23%

对齐后 (成功)

1
2
3
4
5
原始范围: 65.328s - 73.529s
对齐后范围: 65.11s - 73.512s
- 起始点向前调整 0.218s
- 结束点向前调整 0.017s
导出进度: 顺利完成

技术要点总结

1. 视频编码基础

  • GOP 结构:关键帧 + 预测帧
  • 关键帧间隔通常 0.5-2 秒
  • 裁剪操作最好对齐关键帧

2. AVFoundation 导出机制

  • AVAssetExportSession 优先复制压缩数据(快速)
  • 无法对齐时需要重新编码(慢,可能失败)
  • videoComposition 的时间指令必须与视频轨道时间匹配

3. 用户体验考虑

  • 自动对齐是透明的,用户无感知
  • 起始点向前调整不会丢失内容
  • 结束点微调(< 0.1s)用户难以察觉
  • 调整量有上限(1秒),避免过度偏离

4. 诊断方法

  • 添加进度卡住检测
  • 分析关键帧分布
  • 检查导出状态和错误信息
  • 验证时间范围对齐情况

参考资料


文档版本: 1.0
创建日期: 2026-02-09
最后更新: 2026-02-09