Аудио/видео не синхронизировано после переключения камеры

Я пытаюсь создать приложение, в котором я могу записывать видео с разных камер на устройстве во время записи. Например. Пользователь нажимает кнопку «Начать запись» с передней камеры, через 5 секунд записи пользователь нажимает кнопку «Переключить камеру», и приложение меняет источник видео с передней на заднюю камеру, и запись продолжается. Для переключения камеры я использую следующий код:

NSError *error;
AVCaptureDeviceInput *newVideoInput;
AVCaptureDevicePosition currentCameraPosition = [[videoInput device] position];

if (currentCameraPosition == AVCaptureDevicePositionBack)
{
    currentCameraPosition = AVCaptureDevicePositionFront;
}
else
{
    currentCameraPosition = AVCaptureDevicePositionBack;
}

AVCaptureDevice *backFacingCamera = nil;
NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
for (AVCaptureDevice *device in devices) 
{
    if ([device position] == currentCameraPosition)
    {
        backFacingCamera = device;
    }
}
newVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:backFacingCamera error:&error];

if (newVideoInput != nil)
{
    [_captureSession beginConfiguration];

    [_captureSession removeInput:videoInput];
    if ([_captureSession canAddInput:newVideoInput])
    {
        [_captureSession addInput:newVideoInput];
        videoInput = newVideoInput;
    }
    else
    {
        [_captureSession addInput:videoInput];
    }
    //captureSession.sessionPreset = oriPreset;
    [_captureSession commitConfiguration];
}

_inputCamera = backFacingCamera;

После этого приложения измените источник видео и продолжайте писать, но... аудио/видео не синхронизировано... Кто-нибудь может помочь мне с этой проблемой?

Спасибо.


person kroumvud    schedule 19.12.2012    source источник
comment
Имея ту же проблему.   -  person Liron    schedule 23.04.2015


Ответы (3)


вам нужно остановить запись, переключить и начать снова. переключение камеры не мгновенное AFAIK

Вы не можете записать в n файлов, а затем сшить их вместе?

попробуйте использовать отдельные дорожки AVMutableComposition, а затем установите изменяемую композицию для аудио и одну для видео. (см. Объединение двух файлов фильмов m4v с использованием AVMutableComposition - Видео не будут объединяться)

person Daij-Djan    schedule 19.12.2012
comment
Спасибо за ваш ответ. А если я остановлю запись и поменяю камеру, можно ли как-то продолжить запись в тот же файл - person kroumvud; 19.12.2012
comment
извините, я не знаю, но... вы не можете просто записать в N файл и потом сшить их вместе? - person Daij-Djan; 19.12.2012
comment
знаете, если каждый раз останавливать запись и потом начинать новую, то каждый раз останавливать старую и начинать новую запись, приложение будет зависать на короткое время... а это нехорошо(( - person kroumvud; 19.12.2012
comment
Такие приложения, как SnapChat, делают это, не затрагивая звуковую дорожку. Возможно 2 отдельных регистратора? - person Andres Canella; 04.11.2016
comment
Это довольно медленно по производительности. Так что если вам нужно видео сразу после записи, то это, наверное, не тот вариант. - person slow; 26.06.2020

У меня была та же проблема, я много чего пробовал и нашел простое и удобное решение, которое работает без каких-либо сбоев.

введите здесь описание изображения

Проблема в том, как указал @daij-djan, что переключение входа сеанса занимает немного времени и добавляет несколько черных кадров к выходу, а затем продолжает отправлять кадры, как будто он никогда не останавливался. Насколько я знаю, невозможно узнать, сколько кадров затронуто. Эта задержка не влияет на временной код сеанса, поэтому мы не можем использовать его для игнорирования некоторых видеокадров.

введите здесь описание изображения

Вместо того, чтобы иметь один сеанс с несколькими входами камеры, вы можете иметь один сеанс для каждого входа камеры (+ один для аудио, если вам это нужно) и один видеовыход. Затем вам нужно только переключать этот вывод между сеансами.

введите здесь описание изображения

В результате у вас не будет десинхронизации и уродливого взлома. В моих тестах влияние на память очень ограничено, и я не заметил никакого влияния на производительность. Моя теория состоит в том, что сеанс не активен, пока к нему не подключен выход.

Переключение выходов можно сделать так:

fromSession.beginConfiguration()
fromSession.removeOutput(videoOutput)
fromSession.commitConfiguration()

toSession.beginConfiguration()
if toSession.canAddOutput(videoOutput) { toSession.addOutput(videoOutput) }
toSession.commitConfiguration()
person Macistador    schedule 19.02.2019
comment
Не могли бы вы просто зафиксировать время, когда начинается переключение камеры, остановить сеанс, внести изменения, снова запустить сеанс и зафиксировать время, когда кадры снова захватываются, чтобы определить задержку, и просто настроить метку времени для всех кадров после этого, чтобы учесть отставание? Вам также может понадобиться отбросить любые кадры, которые приходят с отметками времени во время задержки. - person JCutting8; 12.03.2019
comment
Как переключить выход между сеансами захвата, не останавливая видеозапись? - person George Heints; 21.04.2020
comment
@GeorgeHeints Я отредактировал свой ответ, добавив пример кода - person Macistador; 21.04.2020
comment
Очень ценю этот ответ! Около года назад я работал с кем-то над библиотекой (HybridCamera на github), и модуль отлично работает. Запись супер плавная. Я просто хотел бы реализовать эту функцию тоже. У вас есть проект, где вы реализовали это таким образом? Если да, не могли бы вы прислать мне еще немного кода того, как вы это сделали, чтобы я мог изучить его и переписать некоторые файлы модуля. Я относительно новичок в AVFoundation, и мне может понадобиться больше контекста. Однако это решение звучит как лучшее из тех, что я когда-либо слышал. Хотел бы услышать от вас! - person Moritz; 20.06.2020
comment
Я пытался заставить его работать, но у меня почему-то не получается. Я всегда сталкиваюсь с проблемами со слоем предварительного просмотра предварительного просмотра. Я был бы очень признателен за вашу помощь, если бы у вас было немного свободного времени. - person Moritz; 21.06.2020
comment
Когда мы должны вызывать toSession.startRunning()? Одновременно с fromSession.startRunning()? - person Rodion Kuskov; 13.07.2020
comment
@Macistador Как вы справляетесь со слоями предварительного просмотра? Вам придется продолжать переключать сеанс, который вызывает некоторые черные кадры, верно? Также вы сказали, что одна сессия на аудио, но вы можете выводить только одну сессию за раз, верно? - person ; 08.07.2021

при переключении камеры нужно приостановить запись буфера в методе делегата:

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection

вы можете проверить проект с открытым исходным кодом PBJVision

person Ruobin Wang    schedule 05.01.2016
comment
У вас действительно есть это работает на вашем конце? PBJVision имеет ту же проблему, к которой относится этот вопрос. - person Andres Canella; 04.11.2016