2014-11-04 36 views
14

Mam następujący kod, który działa na iOS 6 & 7.x.iOS 8 iPad AVCaptureMovieFileOutput upuszcza/przegrywa/nigdy nie pobiera ścieżki dźwiękowej po 13 - 14 sekundach nagrywania

W iOS 8.1 Mam dziwny problem, w przypadku przechwytywania sesji przez około 13 sekund lub dłużej, wynikowy zestaw AVA ma tylko 1 ścieżkę (wideo), ścieżka audio po prostu nie istnieje.

Jeśli nagrywasz przez krótszy okres, zestaw AVA ma 2 ścieżki (wideo i audio) zgodnie z oczekiwaniami. Mam dużo miejsca na dysku, aplikacja ma pozwolenie na używanie kamery i mikrofonu.

Utworzyłem nowy projekt z minimalnym kodem, który powtarza problem.

Wszelkie pomysły będą mile widziane.

#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

Należy również wspomnieć, że nie zgłoszono żadnych błędów (zero) w didFinishRecordingToOutputFileAtURL –

+0

Ok ustawienie fragmentInterval większe niż nagrywanie spowoduje jego naprawienie. Ale jestem pewny, że nie powinienem tego potrzebować. 'CMTime fragmentInterval = CMTimeMake (5,1); [movieOutput setMovieFragmentInterval: fragmentInterval]; ' –

+0

Co się stanie, jeśli nie użyjesz' maxRecordedDuration' i ręcznie zatrzymasz nagrywanie po 45 sekundach? –

Odpowiedz

15

Pomoże to to naprawić.

[movieOutput setMovieFragmentInterval:kCMTimeInvalid];

myślę, że to jest błąd. Dokumentacja mówi, że przykładowa tabela nie zostanie zapisana, jeśli nagranie nie zakończy się pomyślnie. Zostanie więc automatycznie napisane, jeśli zakończy się pomyślnie. Ale teraz wygląda na to, że tak nie jest.

Wszelkie pomysły?

+1

Wow. To działało - wyciągałem włosy z tego błędu. Dla innych osób nie miałem maksymalnego czasu trwania ani rozmiaru. –

+0

Mam maksymalny rozmiar * i * czas trwania. Poprzednio używałem 'movieOutput.movieFragmentInterval = CMTime (value: 2, timescale: 1)' i od czasu do czasu uzyskiwałem dźwięk, ale nie wideo. Ustawienie na kCMTimeInvalid rozwiązało 40% moich problemów. Moje filmy mają 8 sekund, więc fragmenty nie są potrzebne. – atlex2

+0

Witam @ atlex2. Czy możesz podać mi wersję demo? Nie napotkałem tego problemu. – dusty