17
votes

I want to record video and play audio simultaneously. when start recording video, preloaded audio start play and when stop video recording, audio also stops playing.

I tried to record Video by using third party library "SwiftyCam" (https://github.com/Awalz/SwiftyCam) and start playing audio in delegate method when start writes video recording file.

main ViewCOntroller code is below :

override func viewDidAppear(_ animated: Bool) {
 super.viewDidAppear(animated)
 var temp = Data()
 let audioPath = Bundle.main.path(forResource: "ab1-FAST", ofType: "mp3")
        temp = FileManager.default.contents(atPath: (audioPath)!)!
     do {
            player = try  AVAudioPlayer(data: temp)
        }
        catch let error {

            print(error)
        }

        self.configureAudioSession()
        player!.delegate = self
        self.player!.prepareToPlay()
}

    // MARK: -
    // MARK: - SwiftyCamViewControllerDelegate method

func swiftyCam(_ swiftyCam: SwiftyCamViewController, didBeginRecordingVideo camera: SwiftyCamViewController.CameraSelection) {
  self.player?.play()
}

func swiftyCam(_ swiftyCam: SwiftyCamViewController, didFinishRecordingVideo camera: SwiftyCamViewController.CameraSelection) 
{
        if self.player != nil{
            if (self.player?.isPlaying)! {
                self.player?.stop()
            }
        }
}


@IBAction func btnStartStopClick(_ sender: UIButton) {

        sender.isSelected = !sender.isSelected
        if sender.isSelected{

            DispatchQueue.main.async {
                self.objVideoRecorderVC.startVideoRecording()
            }
        }else{
             self.objVideoRecorderVC.stopVideoRecording()

        }
  }

swiftycam Library :

/**

    Begin recording video of current session

    SwiftyCamViewControllerDelegate function SwiftyCamDidBeginRecordingVideo() will be called

    */
public func startVideoRecording() {
        guard let movieFileOutput = self.movieFileOutput else {
            return
        }

        if currentCamera == .rear && flashEnabled == true {
            enableFlash()
        }

        if currentCamera == .front && flashEnabled == true {
            flashView = UIView(frame: view.frame)
            flashView?.backgroundColor = UIColor.white
            flashView?.alpha = 0.85
            previewLayer.addSubview(flashView!)
        }

        sessionQueue.async { [unowned self] in
            if !movieFileOutput.isRecording {
                if UIDevice.current.isMultitaskingSupported {
                    self.backgroundRecordingID = UIApplication.shared.beginBackgroundTask(expirationHandler: nil)
                }

                // Update the orientation on the movie file output video connection before starting recording.
                let movieFileOutputConnection = self.movieFileOutput?.connection(withMediaType: AVMediaTypeVideo)


                //flip video output if front facing camera is selected
                if self.currentCamera == .front {
                    movieFileOutputConnection?.isVideoMirrored = true
                }

                movieFileOutputConnection?.videoOrientation = self.getVideoOrientation()

                // Start recording to a temporary file.
                let outputFileName = UUID().uuidString
                let outputFilePath = (NSTemporaryDirectory() as NSString).appendingPathComponent((outputFileName as NSString).appendingPathExtension("mov")!)


                movieFileOutput.startRecording(toOutputFileURL: URL(fileURLWithPath: outputFilePath), recordingDelegate: self)
                self.isVideoRecording = true
    DispatchQueue.main.async {
                    self.cameraDelegate?.swiftyCam(self, didBeginRecordingVideo: self.currentCamera)
                }
            }
            else {
                movieFileOutput.stopRecording()
            }
        }
    }

issue: sometimes getting a delay in start playing audio in a microsecond. when audio start play and sound record in video recording some time sync proper and some time delay in sound.

I check it with merge audio with original audio and there is some delay as shown below image. the issue is not always but random delay and not sync.enter image description here

enter image description here are any solutions? how to do record video and play audio at the same time(on single button click) start and no delay and no sync issue? is any other way?

for play audio used: AVAudioPlayer

for record video used : Swiftycam (AVCaptureSession)

1
May be you can try this SO asnwer: stackoverflow.com/a/36912798/2859764Akshit Zaveri
@AkshitZaveri,,, I can play audio & record video both same times. On single button click start audio play and video recording start. but the issue is playing audio is 0.5 sec delayed (not always).Bhargav B. Bajani
In theory I think it's possible, but have no idea how to synchronize those two tasks. Hope someone will show us elegant solutionsage444
do you want to just listen audio on recording or do you want to add some background music to be added into video ? if you want to add background music than you can try merging Audio track in your video programetically using AVMutableCompositionTrack you can add music to it , i had a similer task ,i merged audio in video and finally exported the video @BhargavB.BajaniDhiru
@dhiru... I'm starting video recording and audio play same time .s o audio sound record in the video . after that when I compare played audio with recorded Video's audio it's not in sync.Bhargav B. Bajani

1 Answers

6
votes

Couple thing you can try:

1) Play audio on the background queue:

dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUN‌​D, 0)) {
    self.player.play()
}

2) Move the code you have in viewDidAppear (including prepareToPlay()) to viewDidLoad. I assume this will be a less helpful suggestions since playing is user-initiated but there is a delay between prepareToPlay() and when your audio is ready.

If you try these and the delay is still too much, you simply might have to use something other than AVAudioPlayer, such as OpenAL.