2014-11-04 14 views
14

Ich habe den folgenden Code, der für iOS 6 funktioniert & 7.x.iOS 8 iPad AVCaptureMovieFileOutput fällt/verliert/bekommt keine Audiospur nach 13 - 14 Sekunden Aufnahme

In iOS 8.1 habe ich ein seltsames Problem, wo, wenn Sie eine Sitzung für ca. 13 Sekunden oder länger erfassen, der resultierende AVAsset nur 1 Spur (Video) hat, die Audiospur ist einfach nicht da.

Wenn Sie für einen kürzeren Zeitraum aufnehmen, hat der AVAsset 2 Spuren (Video und Audio) wie erwartet. Ich habe viel Speicherplatz, die App hat die Erlaubnis, Kamera und Mikrofon zu benutzen.

Ich habe ein neues Projekt mit minimalem Code erstellt, reproduziert das Problem.

Alle Ideen würden sehr geschätzt werden.

#import "ViewController.h" 

@interface ViewController() 

@end 

@implementation ViewController 
{ 
    enum RecordingState { Recording, Stopped }; 
    enum RecordingState recordingState; 

    AVCaptureSession *session; 
    AVCaptureMovieFileOutput *output; 
    AVPlayer *player; 
    AVPlayerLayer *playerLayer; 
    bool audioGranted; 
} 

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    [self setupAV]; 
    recordingState = Stopped; 
} 

-(void)setupAV 
{ 
    session = [[AVCaptureSession alloc] init]; 
    [session beginConfiguration]; 
    AVCaptureDevice *videoDevice = nil; 

    for (AVCaptureDevice *device in [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]) { 
     if (device.position == AVCaptureDevicePositionBack) { 
      videoDevice = device; 
      break; 
     } 
    } 
    AVCaptureDevice *audioDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio]; 
    if (videoDevice && audioDevice) 
    { 
     AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:nil]; 
     [session addInput:input]; 

     AVCaptureDeviceInput *audioInput = [AVCaptureDeviceInput deviceInputWithDevice:audioDevice error:nil]; 
     [session addInput:audioInput]; 

     NSURL *recordURL = [self tempUrlForRecording]; 
     [[NSFileManager defaultManager] removeItemAtURL:recordURL error:nil]; 

     output= [[AVCaptureMovieFileOutput alloc] init]; 
     output.maxRecordedDuration = CMTimeMake(45, 1); 
     output.maxRecordedFileSize = 1028 * 1028 * 1000; 
     [session addOutput:output]; 
    } 
    [session commitConfiguration]; 
} 

- (IBAction)recordingButtonClicked:(id)sender { 
    if(recordingState == Stopped) 
    { 
     [self startRecording]; 
    } 
    else 
    { 
     [self stopRecording]; 
    } 
} 

-(void)startRecording 
{ 
    recordingState = Recording; 
    [session startRunning]; 
    [output startRecordingToOutputFileURL:[self tempUrlForRecording] recordingDelegate:self]; 

} 

-(void)stopRecording 
{ 
    recordingState = Stopped; 
    [output stopRecording]; 
    [session stopRunning]; 
} 

- (void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error 
{ 
    AVAsset *cameraInput = [AVAsset assetWithURL:[self tempUrlForRecording]]; 
    //DEPENDING ON HOW LONG RECORDED THIS DIFFERS (<14 SECS - 2 Tracks, >14 SECS - 1 Track) 
    NSLog(@"Number of tracks: %i", cameraInput.tracks.count); 
} 

-(id)tempUrlForRecording 
{ 
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDirectoryPath = [paths objectAtIndex:0]; 

    NSString *path = @"camerabuffer.mp4"; 
    NSString *pathCameraInput =[documentsDirectoryPath stringByAppendingPathComponent: path]; 
    NSURL *urlCameraInput = [NSURL fileURLWithPath:pathCameraInput]; 

    return urlCameraInput; 
} 

- (void)didReceiveMemoryWarning { 
    [super didReceiveMemoryWarning]; 
    // Dispose of any resources that can be recreated. 
} 

@end 
+0

Ich sollte auch erwähnen, dass keine Fehler gemeldet werden (nil) in didFinishRecordingToOutputFileAtURL –

+0

Ok Einstellung der FragmentInterval größer als die Aufnahme wird es behoben werden. Aber ich bin mir sicher, dass ich das nicht brauchen sollte 'CMTime fragmentInterval = CMTimeMake (5,1); [movieOutput setMovieFragmentInterval: fragmentInterval]; ' –

+0

Was passiert, wenn Sie die' maxRecordedDuration' nicht verwenden und die Aufzeichnung nach 45 Sekunden manuell beenden? –

Antwort

15

Dies wird Ihnen helfen, es zu beheben.

[movieOutput setMovieFragmentInterval:kCMTimeInvalid];

Ich denke, dies ist ein Bug. Die Dokumentation besagt, dass die Beispieltabelle nicht geschrieben wird, wenn die Aufzeichnung nicht erfolgreich abgeschlossen wird. So wird es automatisch geschrieben, wenn es erfolgreich abgeschlossen wird. Aber jetzt scheint es nicht so.

Irgendwelche Ideen?

+1

Wow. Das hat funktioniert - ich habe mir bei diesem Käfer die Haare ausgerissen. Für andere Referenz hatte ich keine maximale Dauer oder Größe. –

+0

Ich habe eine maximale Größe * und * Dauer. Ich habe zuvor 'movieOutput.movieFragmentInterval = CMTime (Wert: 2, Zeitskala: 1)' 'verwendet und bekam gelegentlich Audio, aber kein Video. Die Einstellung auf kCMTimeInvalid löste 40% meiner Probleme. Meine Videos sind 8 Sekunden lang, so dass Fragmente nicht benötigt werden. – atlex2

+0

Hallo @ atlex2. Könnten Sie mir eine Demo zur Verfügung stellen? Ich bin diesem Problem nicht begegnet. – dusty