AVCaptureSession 的奇怪错误

Posted

技术标签:

【中文标题】AVCaptureSession 的奇怪错误【英文标题】:Weird bug with AVCaptureSession 【发布时间】:2012-05-10 22:45:27 【问题描述】:

我使用以下代码设置 AVCaptureSession、录制视频文件并播放: 有时这工作得很好,而其他时候我在播放时会出现黑屏。据我所知,这完全是随机的。

当错误发生时,如果我尝试快速打开文件,我会收到“文件无法打开,格式无法识别”的消息。这让我相信这是录制问题而不是播放问题。

另外,如果注释掉添加麦克风输入的代码部分,则不会发生错误(但我的视频文件当然没有音轨)......所以音频馈送可能会随机损坏出于某种原因归档?

- (void)viewDidLoad 
[super viewDidLoad];

....

captureSession = [[AVCaptureSession alloc] init];
[captureSession setSessionPreset:AVCaptureSessionPresetHigh];

NSArray *devices = [AVCaptureDevice devices];
AVCaptureDevice *frontCamera;
AVCaptureDevice *mic = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];

for (AVCaptureDevice *device in devices) 

    NSLog(@"Device name: %@", [device localizedName]);

    if ([device hasMediaType:AVMediaTypeVideo]) 
    
        if ([device position] == AVCaptureDevicePositionFront) 
            NSLog(@"Device position : front");
            frontCamera = device;
        
    


NSError *error = nil;

AVCaptureDeviceInput * microphone_input = [AVCaptureDeviceInput deviceInputWithDevice:mic error:&error];

AVCaptureDeviceInput *frontFacingCameraDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:frontCamera error:&error];

if (!error) 

    if ([captureSession canAddInput:frontFacingCameraDeviceInput])
    
        [captureSession addInput:frontFacingCameraDeviceInput];
    

    if([captureSession canAddInput:microphone_input])
    
        [captureSession addInput:microphone_input];
    


[captureSession startRunning];

按下录制时,我录制到“movie.mov”文件中:

movieOutput = [[AVCaptureMovieFileOutput alloc]init];
[captureSession addOutput:movieOutput];
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *pathString = [documentsDirectory stringByAppendingPathComponent:@"movie.mov"];
NSURL *pathUrl = [NSURL fileURLWithPath:pathString];

[movieOutput startRecordingToOutputFileURL:pathUrl recordingDelegate:self];

当按下播放时,我播放电影文件:

NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *pathString = [documentsDirectory stringByAppendingPathComponent:@"movie.mov"];
NSURL *pathUrl = [NSURL fileURLWithPath:pathString];

mPlayer = [AVPlayer playerWithURL:pathUrl];

[self.video setPlayer:self.mPlayer];
[video setVideoFillMode:@"AVLayerVideoGravityResizeAspectFill"];
[self.mPlayer play];

我已经有一段时间了,无法弄清楚,这真的很随机​​。任何帮助表示赞赏!

编辑: 如果movie.mov 文件已经存在,我会在开始新录制之前将其删除。

EDIT2:它可能与该行有关: [movieOutput startRecordingToOutputFileURL:pathUrl recordingDelegate:self]; Xcode 在这一行给我一个“发送 ViewController *const_strong 'to parameter of in compatible type 'id'”警告

EDIT3:问题已解决,将很快发布答案。谢谢!

【问题讨论】:

这种行为有什么规律吗?即它是否仅在您每次启动时第一次录制时才成功录制?是否只有在删除后第一次重新安装应用程序时才能成功录制?每次启动时它是否都能成功录制,直到您播放它? 我看不到任何模式。它似乎发生在大约 50% 的尝试中。但它会很容易连续尝试 3 次,尝试 2 次不行,然后奇迹般地再次工作(全部无需重新启动应用程序) 【参考方案1】:

我想我已经明白了:

AVCaptureMovieFileOutput 类有一个movieFragmentInterval 变量,默认值为10。因此,每10 秒,“样本表”就会写入quicktime 文件。如果没有示例表,则该文件是不可读的。

当我对此进行测试时,我的所有记录都很短,因此似乎每当没有将示例表写入文件时就会发生错误。这很奇怪,因为我假设当我调用 [movieOutput stopRecording] 时这会写出示例表,但我想它没有。当我将 fragmentInterval 降低到 5 秒时:

CMTime fragmentInterval = CMTimeMake(5,1);

[movieOutput setMovieFragmentInterval:fragmentInterval];
[movieOutput startRecordingToOutputFileURL:pathUrl recordingDelegate:self];

这个错误似乎已经消失了。我仍然不确定为什么只有在将麦克风添加为输入设备时才会发生错误。

【讨论】:

电影写作应该可以在不设置片段间隔的情况下正常工作 - 我认为你真正的问题出在其他地方。 我同意。 fragmentInterval 修复它是没有意义的。它可能更像是一种创可贴解决方案...... 今天遇到了同样的事情,如果录制时间很短,则在调用委托方法 didStartRecordingToOutputFileAtURL 之前调用 [self.movi​​eFileOutput stopRecording]。所以解决方案是在停止之前等待 startRecordingToOutputFileURL 之后的 didStartRecordingToOutputFileAtURL 调用。 @Valentyn 谢谢!这才是我真正的答案。录制结束时我有空白帧。等待委托调用以停止捕获输入解决了问题! 这让我免于完全发疯,谢谢【参考方案2】:

在录制之前调用它,

[[AVAudiosession sharedInstance] setCategory:AVAudioSessionCategoryRecord error:nil];

在播放之前,

[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];

我认为这应该有助于考虑到除非尝试录制音频,否则您不会遇到任何问题。

由于你每次都使用相同的网址,你应该先删除它

NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *pathString = [documentsDirectory stringByAppendingPathComponent:@"movie.mov"];
NSURL *pathUrl = [NSURL fileURLWithPath:pathString];
[[NSFileManager defaultManager] removeItemAtURL:pathUrl error:nil];
[movieOutput startRecordingToOutputFileURL:pathUrl recordingDelegate:self];

【讨论】:

连续工作了 3 次,但不幸再次失败。 是的,在录制之前,如果 movie.mov 文件已经存在,我会删除它 看起来问题出在 AVCaptureMovieFileOutput fragmentInterval 变量上。将片段从默认的 10 秒降低到 5 秒修复了错误。当 *** 让我回答我自己的问题时,我将在 6 小时内发布更详细的解释。感谢您的帮助!【参考方案3】:

您应该将AVCaptureMovieFileOutputfragmentInterval 属性设置为更高的限制。默认为 10 秒。

我也有同样的问题,我使用AVCaptureSession 录制的视频超过 10 秒时没有录制音频。当我将片段间隔设置为 300 秒时,这是我允许拍摄视频的最大秒数,并记录了音频。

AVCaptureMovieFileOutput *aMovieFileOutput = [[AVCaptureMovieFileOutput alloc] init];
CMTime fragmentInterval = CMTimeMake(300,1);

[aMovieFileOutput setMovieFragmentInterval:fragmentInterval];

【讨论】:

【参考方案4】:

这是一个重复的答案,但添加它以帮助像我一样开始使用 ios 的人,我尝试了 KCMTimeInvalid 但它对我不起作用。 一小时后,我意识到我在调用 startRecordingToOutputFileURL 后设置了movieFragmentInterval。

所以对于像我一样盲目打字的新手 - 请记住合乎逻辑且非常明显的顺序

videoFileOutput.movieFragmentInterval = kCMTimeInvalid
videoFileOutput.startRecordingToOutputFileURL(filePath, recordingDelegate: recordingDelegate)

【讨论】:

以上是关于AVCaptureSession 的奇怪错误的主要内容,如果未能解决你的问题,请参考以下文章

通过deb包安装Jekins时发生错误,导致apt-get安装其他软件时会报错的奇怪问题

对重载函数错误的奇怪模棱两可的调用

CRM 插件奇怪的报错

用Python批量把.xls转换.xlsx出现一个奇怪的错误,帮忙看一下吧。谢谢

C ++中的三元运算符奇怪的行为

Linux升级openssl时遇到的奇怪错误