AVCaptureSession的奇怪错误

时间:2012-05-10 22:45:28

标签: ios avcapturesession

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

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

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

- (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'到不兼容类型'id'”参数的警告

EDIT3:问题解决了,很快就会发布回复。谢谢!

4 个答案:

答案 0 :(得分:6)

我想我已经明白了:

AVCaptureMovieFileOutput类有一个movieFragmentInterval变量,默认为10.因此,每10秒钟,一个“样本表”被写入quicktime文件。没有样本表,该文件是不可读的。

当我测试这个时,我的所有录音都很短,所以每当样本表没有写入文件时,似乎就会发生错误。这很奇怪,因为我在调用[movieOutput stopRecording]时会假设这会写出示例表,但我猜它没有。当我使用:

将fragmentInterval降低到5秒时
CMTime fragmentInterval = CMTimeMake(5,1);

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

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

答案 1 :(得分:1)

在录制前调用此方法,

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

答案 2 :(得分:1)

您应该将fragmentInterval的{​​{1}}属性设置为更高的限制。默认情况下,它是10秒。

我使用AVCaptureMovieFileOutput我的视频录制也遇到了同样的问题,10秒以上的任何内容都没有录制音频。当我将片段间隔设置为300秒时,这是我允许拍摄视频的最大秒数,并且录制了音频。

AVCaptureSession

答案 3 :(得分:0)

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

对于那些像我一样盲目打字的新手 - 记住逻辑和非常明显的序列

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