Последовательные вызовы startRecordingToOutputFileURL:

Документы Apple указывают, что во время записи видео в файл приложение может без проблем изменить URL-адрес на лету. Но я вижу проблему. Когда я пытаюсь это сделать, делегат записи вызывается с ошибкой...

Операция не может быть завершена. (Ошибка OSStatus -12780.) Информационный словарь: { AVErrorRecordingSuccessfulFinishedKey = 0; }

(причудливая одинарная кавычка в слове "не удалось" возникла из-за регистрации [описание локализованной ошибки])

Вот код, который в основном настраивает образец WWDC10 AVCam:

1) Начать запись. Запустить таймер для изменения выходного URL каждые несколько секунд

- (void) startRecording
{
    // start the chunk timer
    self.chunkTimer = [NSTimer scheduledTimerWithTimeInterval:5
                                                       target:self
                                                     selector:@selector(chunkTimerFired:)
                                                     userInfo:nil
                                                      repeats:YES];

    AVCaptureConnection *videoConnection = [AVCamCaptureManager connectionWithMediaType:AVMediaTypeVideo fromConnections:[[self movieFileOutput] connections]];
    if ([videoConnection isVideoOrientationSupported]) {
        [videoConnection setVideoOrientation:[self orientation]];
    }

    if ([[UIDevice currentDevice] isMultitaskingSupported]) {
        [self setBackgroundRecordingID:[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{}]];
    }

    NSURL *fileUrl = [[ChunkManager sharedInstance] nextURL];
    NSLog(@"now recording to %@", [fileUrl absoluteString]);
    [[self movieFileOutput] startRecordingToOutputFileURL:fileUrl recordingDelegate:self];
}

2) Когда сработает таймер, измените имя выходного файла, не останавливая запись

- (void)chunkTimerFired:(NSTimer *)aTimer {

    if ([[UIDevice currentDevice] isMultitaskingSupported]) {
        [self setBackgroundRecordingID:[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{}]];
    }

    NSURL *nextUrl = [self nextURL];
    NSLog(@"changing capture output to %@", [[nextUrl absoluteString] lastPathComponent]);

    [[self movieFileOutput] startRecordingToOutputFileURL:nextUrl recordingDelegate:self];
}

Примечание. [self nextURL] генерирует URL-адреса файлов, такие как file-0.mov, file-5.mov, file-10.mov и т. д.

3) Это вызывается каждый раз при изменении файла, и каждый второй вызов является ошибкой...

- (void)              captureOutput:(AVCaptureFileOutput *)captureOutput
didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL
                    fromConnections:(NSArray *)connections
                              error:(NSError *)error
{
    id delegate = [self delegate];
    if (error && [delegate respondsToSelector:@selector(someOtherError:)]) {
        NSLog(@"got an error, tell delegate");
        [delegate someOtherError:error];
    }

    if ([self backgroundRecordingID]) {
        if ([[UIDevice currentDevice] isMultitaskingSupported]) {
            [[UIApplication sharedApplication] endBackgroundTask:[self backgroundRecordingID]];
        }
        [self setBackgroundRecordingID:0];
    }

    if ([delegate respondsToSelector:@selector(recordingFinished)]) {
        [delegate recordingFinished];
    }
}

Когда это запускается, файл-0 записывается, затем мы видим ошибку -12780 сразу после изменения URL-адреса на файл-5, записывается файл-10, затем ошибка, затем все в порядке и так далее.

Похоже, что изменение URL-адреса на лету не работает, но оно останавливает запись, что позволяет работать следующему изменению URL-адреса.


person danh    schedule 02.06.2012    source источник
comment
@danh Вам нужно решение с точностью до кадра, или вам будет нормально, если вы потеряете несколько кадров между видео?   -  person Alladinian    schedule 05.06.2012
comment
@Alladinian - без потерь, но я был бы очень признателен, если бы возникла идея с небольшими потерями, из-за которой я здесь застрял. Я уже пробовал вызывать stopRecording и запускать следующий сегмент в методе делегата. Это работает, но потеря кадров слишком велика... измеряется в секундах.   -  person danh    schedule 05.06.2012
comment
@danh Что ж, подтверждено (инженером Apple), что переключение с точностью до кадра невозможно с AVCaptureFileOutput (хотя они избегают объяснения, почему задокументированное переключение URL-адресов вообще не работает ...). Говорят, что этого можно достичь, используя классы AVCaptureVideoDataOutput и AVAssetWriter, но решение довольно сложное, поскольку вам нужно координировать аудио/видео.   -  person Alladinian    schedule 08.06.2012
comment
@Alladinian - Большое спасибо за предупреждение. До сих пор нет никаких действий по моему двухнедельному запросу DTS, и я начал опасаться того, что вы подтвердили. Я искал обходные пути и опубликую здесь, если придумаю что-то приличное.   -  person danh    schedule 08.06.2012
comment
В документах, на которые вы ссылаетесь на вопрос, всегда прямо упоминается, что образцы мультимедиа не будут отбрасываться в Mac OS X.   -  person Rok Jarc    schedule 09.06.2012
comment
DTS ответил вчера после очень долгой задержки, признав, что это ошибка. Я прикрепил детали в качестве ответа.   -  person danh    schedule 09.06.2012
comment
В более новом документе был удален абзац: developer.apple.com/documentation/avfoundation/   -  person Cœur    schedule 26.03.2019


Ответы (3)


Всем спасибо за отзыв и хорошие мысли по этому поводу. Вот слово от Apple DTS...

Я разговаривал с нашими инженерами AV Foundation, и это определенно ошибка в том, что этот метод не делает то, что указано в документации («Вам не нужно вызывать stopRecording перед вызовом этого метода, пока выполняется другая запись».). Отправьте отчет об ошибке с помощью Apple Bug Reporter (http://developer.apple.com/bugreporter/), чтобы команда могла провести расследование. Убедитесь, что ваш минимальный проект включен в отчет.

Я зарегистрировал это в Apple как ошибку 11632087.

person danh    schedule 09.06.2012
comment
О чувак. Я рад, что кто-то действительно подтвердил ошибку. Я, вероятно, пробовал более 5 различных подходов (хаков), чтобы заставить это работать (даже с двойными сеансами/файловыми выходами, которые жонглируют видеовходом туда и обратно - просто невозможно иметь несколько файлов, не теряя 1-3 секунды видео между ними). Наконец-то я могу отдохнуть :P - person Alladinian; 09.06.2012
comment
Кажется, я не вижу ошибки, отправленные другими людьми. Это было решено с обновлением xcode от 1 ноября 2012 г.? - person noRema; 10.12.2012
comment
Только что проверил отчет об ошибке. Все еще открыт. - person danh; 11.12.2012
comment
Хорошо, спасибо, так вы просто ждете ответа или нашли обходной путь? - person noRema; 12.12.2012
comment
У меня есть плохой обходной путь: дождитесь окончания записи, а затем разделите файл. Это медленно. Это можно сделать асинхронно, чтобы приложение могло оставаться отзывчивым, но для моего приложения пользователю нечего делать, пока файлы не будут готовы. - person danh; 12.12.2012
comment
Есть новости о том, исправлена ​​ли ошибка, @danh? У меня также есть некоторые проблемы с тем, чтобы заставить это работать. - person Jonas Bylov; 10.08.2013
comment
Извини. Отрицательно на том. Я забыл указать нового делегата для каждого выхода. - person Jonas Bylov; 10.08.2013

В документах указано следующее:

If a file at the given URL already exists when capturing starts, recording to the new file will fail.

Вы уверены, что проверили, что nextUrl — несуществующее имя файла?

person Mihai Fratu    schedule 04.06.2012
comment
Спасибо за мысль: я удаляю (и подтверждаю) файлы в каталоге tmp перед началом. - person danh; 04.06.2012

Согласно документации, вызов двух последовательных startRecordingToOutputFileURL не поддерживается.

вы можете прочитать об этом здесь

В iOS такое переключение файлов с точностью до кадра не поддерживается. Вы должны вызвать stopRecording перед повторным вызовом этого метода, чтобы избежать ошибок.

person koby    schedule 24.01.2013