设置AVVideoComposition后AVPlayer播放多视频AVComposition内存过高求助
AVPlayer+AVVideoComposition内存暴增问题排查
问题场景
使用AVComposition搭配AVPlayer时,不设置playerItem.videoComposition,播放器运行正常且内存占用低:
func configurePlayer(composition: AVMutableComposition, videoComposition: AVVideoComposition) { // Stop the player and reset if needed player.pause() player.replaceCurrentItem(with: nil) // Create a new player item let playerItem = AVPlayerItem(asset: composition) player.play() }
但设置playerItem.videoComposition = videoComposition后,内存占用暴增:
func configurePlayer(composition: AVMutableComposition, videoComposition: AVVideoComposition) { // Stop the player and reset if needed player.pause() player.replaceCurrentItem(with: nil) // Create a new player item let playerItem = AVPlayerItem(asset: composition) playerItem.videoComposition = videoComposition player.play() }
问题细节
- 内存消耗由合成中的视频轨道数量决定,与视频时长无关:比如2个30分钟视频的内存占用低于40个2秒视频
- 高内存占用显示在Xcode调试面板的
Other Processes区域 - 测试数据:42个时长不足30秒的视频,内存占用约1.4GB
- 即使
videoComposition未添加任何图层指令,内存依然会大幅上升
解决思路
1. 降低渲染分辨率
设置AVVideoComposition的renderScale或renderSize,减少单帧渲染的内存占用:
// 初始化时直接设置渲染缩放比例 let videoComposition = AVVideoComposition(propertiesOf: composition) videoComposition.renderScale = 0.5 // 用原分辨率的一半渲染 // 或者在渲染回调中调整尺寸 let videoComposition = AVVideoComposition(asset: composition) { request in guard let renderContext = request.renderContext else { return } request.renderContext.renderSize = CGSize( width: renderContext.renderSize.width / 2, height: renderContext.renderSize.height / 2 ) }
2. 减少视频轨道数量
尽量将短视频合并到同一轨道中(时间线允许的前提下),降低轨道总数。同时检查代码中是否存在未释放的轨道引用,确保AVMutableComposition的轨道在不需要时被正确释放。
3. 强制释放临时对象内存
使用autoreleasepool包裹playerItem的创建逻辑,强制释放临时对象,避免内存堆积:
func configurePlayer(composition: AVMutableComposition, videoComposition: AVVideoComposition) { player.pause() player.replaceCurrentItem(with: nil) autoreleasepool { let playerItem = AVPlayerItem(asset: composition) playerItem.videoComposition = videoComposition player.replaceCurrentItem(with: playerItem) player.play() } }
4. 优化AVVideoComposition初始化方式
避免使用一次性生成所有指令的初始化方式,优先选择基于请求的渲染回调(如闭包形式的初始化方法),让系统按需渲染帧,而非预加载所有轨道的内容。
5. 限制预加载缓冲时长
设置AVPlayerItem的preferredForwardBufferDuration,减少预加载的内容量:
playerItem.preferredForwardBufferDuration = 10 // 仅预加载10秒内容
内容的提问来源于stack exchange,提问作者Tauseef Nasir
相关产品推荐
相关产品推荐

