Ios 使用AVAssetWriter将大量图像写入视频文件时的高峰值内存使用率

Ios 使用AVAssetWriter将大量图像写入视频文件时的高峰值内存使用率,ios,memory,video,Ios,Memory,Video,我使用AvAssetWriter创建了一个将图像组装成视频文件的函数。论坛上有一些关于这个实现的帖子。我已经成功地使用AVAssetWriter编写了视频。我的问题不是这个实现,而是内存消耗。在我的例子中,当我写4秒30FPS的视频1024*768时,峰值内存使用量大约为300MB。更长的时间,10秒等。它将崩溃与内存警告。问题是,在将每个图像写入视频文件的循环过程中,内存使用量会累积。循环结束后,内存使用量会下降到正常水平,而不会出现泄漏 下面的代码是循环的一次迭代。它会将一个新图像附加到av

我使用AvAssetWriter创建了一个将图像组装成视频文件的函数。论坛上有一些关于这个实现的帖子。我已经成功地使用AVAssetWriter编写了视频。我的问题不是这个实现,而是内存消耗。在我的例子中,当我写4秒30FPS的视频1024*768时,峰值内存使用量大约为300MB。更长的时间,10秒等。它将崩溃与内存警告。问题是,在将每个图像写入视频文件的循环过程中,内存使用量会累积。循环结束后,内存使用量会下降到正常水平,而不会出现泄漏

下面的代码是循环的一次迭代。它会将一个新图像附加到avassetwriter

        CVPixelBufferRef buffer = [self pixelBufferFromCGImage:[newimg CGImage] 
            size:CGSizeMake(self.frameOrigWidth, self.frameOrigHeight) poolRef:adaptor.pixelBufferPool];
        BOOL append_ok = NO;
        int j = 0;
        CMTime frameTime = CMTimeMake(frameCount,(int32_t)FPS);
        while (!append_ok && j < 30) //attemp maximum 30 times
        {
            if (adaptor.assetWriterInput.readyForMoreMediaData)
            {
                if(frameCount==0) append_ok = [adaptor appendPixelBuffer:buffer 
                            withPresentationTime:kCMTimeZero];
                else append_ok = [adaptor appendPixelBuffer:buffer withPresentationTime:frameTime];
                [NSThread sleepForTimeInterval:0.05];//use sleep instead of runloop because it is not in main thread
            }else{
                [NSThread sleepForTimeInterval:0.1];
            }
            j++;
        }
        if(buffer) CVBufferRelease(buffer);
CVPixelBufferRef buffer=[self pixelBufferFromCGImage:[newimg CGImage]
大小:CGSizeMake(self.frameOrigWidth,self.frameOrigHeight)poolRef:adapter.pixelBufferPool];
BOOL append_ok=否;
int j=0;
CMTime frameTime=CMTimeMake(帧数,(int32_t)FPS);
而(!append_ok&&j<30)//最多尝试30次
{
if(适配器.assetWriterInput.readyForMoreMediaData)
{
if(frameCount==0)append_ok=[适配器appendPixelBuffer:buffer
with presentationtime:kCMTimeZero];
else append_ok=[适配器appendPixelBuffer:BufferwithPresentationTime:frameTime];
[NSThread sleepForTimeInterval:0.05];//使用睡眠而不是运行循环,因为它不在主线程中
}否则{
[NSThread sleepForTimeInterval:0.1];
}
j++;
}
if(缓冲器)CVBufferRelease(缓冲器);
即使在最后一行有缓冲区释放,内存也不会在整个循环过程中释放,我猜这是因为写入程序将此缓冲区保留到循环之后,并且写入程序执行finishwriting

我尝试使用@autoreleasepool{}来包装这个部分。它有效地停止了峰值内存使用累积,但即使没有运行错误,它也无法再成功写入视频文件

以上解释来自真实的设备调试


我认为可能的解决方案是分段写入,或者在写入周期中暂停几次,以允许写入程序真正释放缓冲区。但我没有找到一种方法来做到这一点。我感谢任何知道解决峰值内存问题方法的人。

我也有同样的问题

我试着在里面使用sleepForTimeInterval

  • (无效)未收到记忆警告
我希望当这一事件触发时,它将暂停主要进程,而不会给我们太多时间 系统将刷新未使用的内存


但我不知道这是否有效

目前我使用的解决方案是将写入任务分为不同的段,每个段写入一个文件。在循环结束时,我使用AVMutableComposition组合所有小文件。通过这种方法,峰值内存出现在每个段中。因为每个段没有很多IMG要写入,所以内存不会消耗太多。我很感激其他的想法,只是想让你知道我用前面提到的方法来解决这个问题。您可以将导出视频任务拆分为多个片段生成短视频。最后把它们合并在一起。这对我来说很好。我的应用程序已经放在app store上了,你可以看看它,看看这个方法如何生成长时间视频。我的应用程序是“动画DIY”