1

I am trying to make an app for musicians involving video recording. In the app the user first chooses the tempo, time signature and number of bars then hits the "Record" button. When the button is hit, I start playing a metronome and show a countdown (4...3...2...1...) before starting the recording. The recording would last for the exact necessary time and not a frame shorter or longer. Given the end use of the video (making music), every slight delay has to be avoided.

My current solution uses AVCaptureMovieFileOutput() and ffmpeg to analyze the audio, find the right start and end then trim the video. I'm wondering if there's a way to capture the right length to begin with using AVCaptureVideoDataOutput() or maybe with a lower level solution like Core Audio.

Mouradif
  • 2,666
  • 1
  • 20
  • 37

1 Answers1

0

You can get the raw pixels with AVCaptureVideoDataOutput and write them to a file with AVAssetWriter.

I give a rather crude example of how to do this: it won't work because I haven't started the session, but you should get the idea.

import AVFoundation

class ViewController: UIViewController {
    
    let captureSession = AVCaptureSession()
    let effectVideoOutput = AVCaptureVideoDataOutput()
    var assetWriter: AVAssetWriter!
    var videoWriterInput: AVAssetWriterInput!

    override func viewDidLoad() {
        super.viewDidLoad()
        
        if captureSession.canAddOutput(effectVideoOutput) {
            captureSession.addOutput(effectVideoOutput)
            effectVideoOutput.setSampleBufferDelegate(self, queue: nil)
        }
        
        let outputUrl = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("output.mp4")
        assetWriter = try! AVAssetWriter(
            outputURL: outputUrl,
            fileType: AVFileType.mp4
        )
        
        videoWriterInput = AVAssetWriterInput(
            mediaType: .video,
            outputSettings: [
                AVVideoCodecKey: AVVideoCodecType.h264,
                AVVideoCompressionPropertiesKey: [
                    AVVideoAverageBitRateKey: 2300000,
                    AVVideoProfileLevelKey: AVVideoProfileLevelH264HighAutoLevel
                ],
                AVVideoWidthKey: UIScreen.main.bounds.size.width,
                AVVideoHeightKey: UIScreen.main.bounds.size.height
            ]
        )

        assetWriter.startWriting()
    }
}

extension ViewController: AVCaptureVideoDataOutputSampleBufferDelegate {
    func captureOutput(_ output: AVCaptureOutput, didDrop sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
        videoWriterInput.append(sampleBuffer)
    }
}

This answer will help you with measuring written duration.

Phil Dukhov
  • 67,741
  • 15
  • 184
  • 220