AVCaptureMovieFileOutput -- 在写入时修剪文件
Posted
技术标签:
【中文标题】AVCaptureMovieFileOutput -- 在写入时修剪文件【英文标题】:AVCaptureMovieFileOutput -- trimming the file while writing 【发布时间】:2011-08-23 19:02:25 【问题描述】:我正在使用AVCaptureMovieFileOutput
录制视频。但是,我不想在整个录制时间内保留捕获的视频,而只想保留最后 2 分钟的视频。本质上,我想创建一个视频的尾随缓冲区。
我试图通过将movieFragmentInterval
设置为 15 秒来实现这一点。由于这 15 秒的缓冲,MOV 文件的前 15 秒将使用以下代码修剪掉:
//This would be called 7 seconds after the video stream started buffering.
-(void)startTrimTimer
trimTimer = [NSTimer scheduledTimerWithTimeInterval:15 target:self selector:@selector(trimFlashbackBuffer) userInfo:nil repeats:YES];
-(void)trimFlashbackBuffer
//make sure that there is enough video before trimming off 15 seconds
if(trimReadyCount<3)
trimReadyCount++;
return;
AVURLAsset *videoAsset = [AVURLAsset URLAssetWithURL:[NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/flashbackBuffer.MOV",tripDirectory]] options:nil];
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:videoAsset presetName:AVAssetExportPresetHighestQuality];
exportSession.outputURL = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/flashbackBuffer.MOV",tripDirectory]];
exportSession.outputFileType = AVFileTypeQuickTimeMovie;
CMTimeRange timeRange = CMTimeRangeMake(CMTimeMake(15000, 1000), CMTimeMake(120000, 1000));
exportSession.timeRange = timeRange;
[exportSession exportAsynchronouslyWithCompletionHandler:^
switch (exportSession.status)
case AVAssetExportSessionStatusCompleted:
// Custom method to import the Exported Video
[self loadAssetFromFile:exportSession.outputURL];
break;
case AVAssetExportSessionStatusFailed:
//
NSLog(@"Failed:%@",exportSession.error);
break;
case AVAssetExportSessionStatusCancelled:
//
NSLog(@"Canceled:%@",exportSession.error);
break;
default:
break;
];
但是,每次调用 trimFlashbackBuffer
时,我都会收到以下错误:
Failed:Error Domain=AVFoundationErrorDomain Code=-11823 "Cannot Save" UserInfo=0x12e710 NSLocalizedRecoverySuggestion=Try saving again., NSLocalizedDescription=Cannot Save
这是因为文件已经被AVCaptureMovieFileOutput
写入了吗?
如果这种方法行不通,如何实现无缝拖尾视频缓冲的效果?
谢谢!
【问题讨论】:
【参考方案1】:不确定您在此处尝试实现的目标是否可行,这是因为就像您说的那样,您在尝试修剪时正在写入文件,为什么不能录制视频并稍后修剪?如果您真的想随时保留两分钟的视频,您可能想尝试使用 AVCaptureVideoDataOutput,使用它您将获得视频帧,您可以使用 AVAssetWriter 将其写入以压缩并将帧写入文件,请查看此 SO关于如何做到这一点的问题This code to write video+audio through AVAssetWriter and AVAssetWriterInputs is not working. Why?
【讨论】:
用你的方法,我不会遇到和以前一样的问题吗?我仍然会在尝试编辑文件的同时写入文件。 好吧,输出不再写入文件了,现在您有了缓冲区并将它们压缩到文件中,因此您正在控制写入文件的内容,而不是尝试访问AV Foundation 正在使用的文件,因此您不会遇到同样的问题 哦,好吧,太好了!感谢您的澄清! 我仍然无法成功实现此效果。如果您不介意进一步澄清您的答案 - 您建议不要直接写入文件,这会阻止我从修剪文件,因为它已经被修改,我在 RAM 中维护一个尾随视频缓冲区?如果是这样,最好的方法是什么?我想到的唯一解决方案是在内存中保存一个 CVImageBufferRefs 数组,每次我添加一个新引用时都会删除最后一个引用,但我需要一次保持大约 3000 帧。想法?谢谢! 不要将它保存在 ram 中,使用 AVAssetWriter 将其写入文件......但我仍然不确定你到底想要做什么,为什么你只想保留最后 2 分钟视频,为什么在视频停止捕获后你不能进行修剪?【参考方案2】:我怀疑您遇到的错误是因为您试图覆盖与导出 URL 中相同的文件。 文档说“如果您尝试覆盖现有文件或在应用程序的沙箱之外写入文件,则导出将失败。如果您需要覆盖现有文件,则必须先将其删除。”
要获取视频的最后两分钟,您可能希望首先使用另一个异步调用 loadValuesAsynchronouslyForKeys 来获取视频的持续时间。使用此持续时间,您可以创建时间范围并通过将视频导出到不同的 URL 来修剪视频。
CMTime start = CMTimeMakeWithSeconds(durationObtained - 120, 600);
CMTime duration = CMTimeMakeWithSeconds(120, 600);
CMTimeRange range = CMTimeRangeMake(start, duration);
exportSession.timeRange = range;
【讨论】:
以上是关于AVCaptureMovieFileOutput -- 在写入时修剪文件的主要内容,如果未能解决你的问题,请参考以下文章
可以同时使用 AVCaptureVideoDataOutput 和 AVCaptureMovieFileOutput 吗?
使用 AVCaptureMovieFileOutput 记录的时间差异
在使用 AVCaptureMovieFileOutput 保存之前修改 AVCaptureSession
如何将 AVCaptureMovieFileOutput 保存到 iCloud
IOS 将 UIProgressView 添加到 AVFoundation AVCaptureMovieFileOutput