与AVCaptureSession怪异的错误

我使用下面的代码来设置一个AVCaptureSession,录制一个video文件,然后播放:有时候,这个工作很好,有时我会播放黑屏。 据我所知,这是完全随机的。

当错误发生时,如果我试图在quicktime打开文件,我得到一个“文件无法打开,格式不被识别”的消息。 这使我相信它是一个录音问题,而不是一个回放问题。

另外,如果注释掉增加了麦克风input的代码部分,就不会发生错误(但是我的video文件当然没有audio轨道)…所以也许audioinput会随机地破坏文件原因?

- (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]; } 

当按下logging时,我logging到一个“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]; ; [self.mPlayer play]; 

我已经有一段时间了,无法弄清楚,确实是非常随意的。 任何帮助表示赞赏!

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

编辑2:它可以做的行: [movieOutput startRecordingToOutputFileURL:pathUrl recordingDelegate:self]; Xcode给了我一个“发送ViewController * const_strong”参数的不兼容的types“ID”“警告在这一行

EDIT3:问题解决了,马上回答。 谢谢!

我想我已经明白了:

AVCaptureMovieFileOutput类有一个默认为10的movieFragmentIntervalvariables。所以每10秒钟,一个“样本表”被写入到quicktime文件中。 没有示例表文件是不可读的。

当我testing这个时候,所有的录音都很短,所以每当一个样本表没有写出来的时候就会发生这个错误。 这很奇怪,因为我认为当我打电话[movieOutput stopRecording],这将写出示例表,但我想它没有。 当我使用下面的代码将fragmentInterval降低到5秒:

 CMTime fragmentInterval = CMTimeMake(5,1); [movieOutput setMovieFragmentInterval:fragmentInterval]; [movieOutput startRecordingToOutputFileURL:pathUrl recordingDelegate:self]; 

这个bug似乎消失了。 我仍然不确定为什么错误只发生在麦克风添加为input设备时。

在录制之前调用这个,

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

而这个播放之前,

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

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

由于您每次都使用相同的url,因此您应该先将其删除

 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]; 

您应该将AVCaptureMovieFileOutputfragmentInterval属性设置为一个更高的限制。 默认情况下是10秒。

我也有同样的问题,我的video录制使用AVCaptureSession超过10秒,没有得到audiologging。 当我把片段间隔设置为300秒,这是我允许拍摄video的最大秒数,并用audio录制。

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

它是一个重复的答案,但添加这个帮助像我这样的ios开始的人,我尝试了KCMTimeInvalid,但它只是没有为我工作。 一个小时后,我意识到我调用startRecordingToOutputFileURL后设置movieFragmentInterval。

所以对于像我这样盲目打字的新手来说,要记住逻辑和非常明显的顺序

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