2

我使用下面的代码来设置一个 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:问题已解决,将很快发布答案。谢谢!

4

4 回答 4

6

我想我已经弄清楚了:

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

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

CMTime fragmentInterval = CMTimeMake(5,1);

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

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

于 2012-05-11T07:48:23.537 回答
1

在录音之前调用这个,

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

在播放之前,

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

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

由于您每次都使用相同的 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];
于 2012-05-10T23:13:30.587 回答
1

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

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

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

[aMovieFileOutput setMovieFragmentInterval:fragmentInterval];
于 2014-09-23T14:07:49.857 回答
0

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

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

videoFileOutput.movieFragmentInterval = kCMTimeInvalid
videoFileOutput.startRecordingToOutputFileURL(filePath, recordingDelegate: recordingDelegate)
于 2016-06-26T09:11:05.983 回答