17

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)

  • May be you can try this SO asnwer: http://stackoverflow.com/a/36912798/2859764 – Akshit Zaveri May 18 '17 at 10:32
  • @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 May 18 '17 at 11:52
  • 1
    In theory I think it's possible, but have no idea how to synchronize those two tasks. Hope someone will show us elegant solution – sage444 May 22 '17 at 09:43
  • 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.Bajani – Dhiru May 27 '17 at 06:01
  • @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 May 29 '17 at 05:47

1 Answers1

6

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.

mmd1080
  • 1,658
  • 2
  • 12
  • 26
  • I tried with move code from "viewDidAppear" to "viewDidLoad". also tried with prepareToPlay() -> play() -> pause() – Bhargav B. Bajani May 23 '17 at 05:03
  • @BhargavB.Bajani Did you manage to figure out a solution to this? Did this comment help you? – Rikh Dec 14 '18 at 08:15
  • @Rikh Not got any solutions. and Tried above comment but not solved an issue. I think the issue is related to hardware and thread. because a delay is +/- any. – Bhargav B. Bajani Dec 20 '18 at 11:56