切换相机后音频/视频不同步

Posted

技术标签:

【中文标题】切换相机后音频/视频不同步【英文标题】:Audio/video out of sync after switch camera 【发布时间】:2012-12-19 11:15:37 【问题描述】:

我正在尝试创建应用程序,在该应用程序中,我可以在录制过程中从设备上的不同摄像头录制视频。 例如。用户从前置摄像头按下“开始录制”按钮,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;

此应用程序更改视频源并继续写入后,但是...音频/视频不同步... 有人能帮我解决这个问题吗?

谢谢。

【问题讨论】:

遇到同样的问题。 【参考方案1】:

我遇到了同样的问题,尝试了很多方法,并想出了一个简单方便的解决方案,而且没有任何故障。

问题是,正如@daij-djan 指出的那样,切换会话输入需要一点时间,并在输出中添加一些黑色帧,然后继续发送帧,就好像它从未停止过一样。据我所知,不可能知道有多少帧受到影响。会话时间码不受此延迟的影响,因此我们不能使用它来忽略某些视频帧。

您可以为每个摄像头输入创建一个会话(如果需要,还可以为音频添加一个会话)和一个视频输出,而不是一个会话具有多个摄像头输入。然后你只需要在会话之间切换这个输出。

因此,您将无需去同步,也无需进行丑陋的黑客攻击。 在我的测试中,内存影响非常有限,我没有注意到任何性能影响。我的理论是会话在附加输出之前是不活动的。

可以这样切换输出:

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

toSession.beginConfiguration()
if toSession.canAddOutput(videoOutput)  toSession.addOutput(videoOutput) 
toSession.commitConfiguration()

【讨论】:

难道你不能简单地捕捉切换相机开始的时间、停止会话、进行更改、再次启动会话并捕捉再次捕捉帧的时间以确定“滞后”并且只是此后调整所有帧的时间戳以解决滞后问题?您可能还需要丢弃在延迟期间带有时间戳的任何帧。 如何在不停止视频录制的情况下切换输出 btw Capture Sessions? @GeorgeHeints 我编辑了我的回复以添加示例代码 非常感谢这个答案!大约一年前,我一直在和某人一起开发一个库(GitHub 上的 HybridCamera),并且该 pod 运行良好。录音超级流畅。我也想实现这个功能。您是否有以这种方式实施的项目?如果是这样,您是否介意向我发送更多有关您如何执行此操作的代码,以便我可以查看它并重写 pod 的一些文件。我对 AVFoundation 比较陌生,可能需要更多背景信息。不过,这个解决方案听起来是我听过的最好的解决方案。希望收到您的来信! 我试着让它工作,但不知何故无法成功。我总是遇到预览视图的预览层的问题。如果您有空余时间,我将非常感谢您的帮助。【参考方案2】:

您需要停止录制,切换并重新开始。 相机开关不是即时AFAIK

你不能录制成 n 个文件,然后将它们拼接在一起吗?

尝试使用单独的 AVMutableComposition 轨道,然后为音频和视频设置一个可变组合。 (见Merging two m4v Movie Files Using AVMutableComposition - Videos Will Not Merge)

【讨论】:

感谢您的回复。如果我停止录制并更换相机,是否有可能以某种方式继续在同一个文件中录制 对不起,我不知道,但是……你不能只记录到 N 文件,然后再将它们拼接在一起吗? 你知道,如果每次停止录制然后开始一个新的,每次停止旧的并开始一个新的录制,应用程序会在短时间内冻结......这不好((( 像 snapChat 这样的应用程序在不影响音轨的情况下执行此操作。也许 2 个独立的录音机? 这在性能上相当缓慢。因此,如果您在录制后立即需要视频,这可能不是正确的选择。【参考方案3】:

切换相机时,需要在委托方法中暂停缓冲区写入:

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

您可以查看开源项目 PBJVision

【讨论】:

你真的有这个工作吗? PBJVision 与此问题所指的 issue 相同。

以上是关于切换相机后音频/视频不同步的主要内容,如果未能解决你的问题,请参考以下文章

FFmpeg concat 视频和音频不同步

MPMoviePlayerController 音频/视频不同步

如何为 HTML5 视频设置音频延迟(不同步)

同步视频和音频(最好不使用 JavaScript)

音视频开发系列(15):视频与音频同步

视频直播技术:使用Ijkplayer播放音视频不同步解决方案