Как я могу записать видео и синхронизировать его с AVPlayer? - PullRequest
0 голосов
/ 24 апреля 2020

Мне нужно записать видео и показать видео одновременно с AVPlayer. Результат должен быть синхронизирован: если видео, которое я показываю, является метрономом или кто-то хлопает, записанное видео и проигрыватель должны щелкнуть или хлопнуть одновременно.

Я играю AVPlayer, используя предварительную прокрутку и setRate, с делегатом в контроллере камеры.

Используя AVCaptureMovieFileOutput, я попытался вызвать setRate на проигрывателе после вызова fileOutput (output: didStartRecordingTo), но видео заканчивается десинхронизированным, с записанным видео, идущим позади проигрывателя.

Используя AssetWriter, я попытался вызвать setRate на проигрывателе после вызова captureOutput (captureOutput: sampleBuffer) и добавления первого буфера, но результат тот же.

Есть ли другой способ сделать это?

РЕДАКТИРОВАТЬ: добавить код, чтобы показать, что я делаю:

Камера с AVCaptureMovieFileOutput:

func startRecordingVideo() {
        guard let movieFileOutput = self.movieFileOutput else {
            return
        }

        sessionQueue.async {
            if !movieFileOutput.isRecording {

                let movieFileOutputConnection = movieFileOutput.connection(with: .video)

                movieFileOutput.setOutputSettings([AVVideoCodecKey: AVVideoCodecH264], for: movieFileOutputConnection!)

                let outputFileName = NSUUID().uuidString
                let outputFilePath = (NSTemporaryDirectory() as NSString).appendingPathComponent((outputFileName as NSString).appendingPathExtension("mov")!)
                movieFileOutput.startRecording(to: URL(fileURLWithPath: outputFilePath), recordingDelegate: self)
            } else {
                movieFileOutput.stopRecording()
            }
        }
    }

    func fileOutput(_ output: AVCaptureFileOutput, didStartRecordingTo fileURL: URL, from connections: [AVCaptureConnection]) {
        cameraDelegate?.startedRecording()
    }

Реализация startRecording делегата в viewController:

private func setRateForAll() {
        let hostTime = CMClockGetTime(CMClockGetHostTimeClock())
        activePlayers.forEach {
            $0.setRate(atHostTime: hostTime)
        }
    }

Как только активный игрок или игроки заканчивают, я вызываю opRecording на камеру, и показать полученное записанное видео в другом плеере вместе с плеером или проигрывателями, которые я показывал.

1 Ответ

0 голосов
/ 06 мая 2020

В итоге я использовал главные часы сеанса записи в качестве hostTime для метода setRate. Десинхронизация теперь почти незаметна!

В fileOutput (output: didStartRecordingTo):

cameraDelegate?.startedRecording(clock: CMClockGetTime(self.session.masterClock!))

В представлении с игроками:

private func setRateForAll(clock: CMTime) {
        activePlayers.forEach {
            $0.setRate(atHostTime: clock)
        }
}
...