2

I'm building this iPad app to record a video with audio. It starts to record when the view appears, and then you can either stop the recording with a button, else it will stopp when a timer hits 0.

This is the entire Controller class.

import UIKit
import AVKit

class RecorderController: UIViewController, AVCaptureFileOutputRecordingDelegate {

  @IBOutlet weak var previewView: UIView!
  @IBOutlet weak var countdownLabel: UILabel!

  var videoUrl: URL?

  var seconds = 11 // Works with 11 seconds, any thing longer audio disappears
  var timer = Timer()

  var captureSession: AVCaptureSession?
  var videoPreviewLayer: AVCaptureVideoPreviewLayer?

  var fileName: String = ""
  var documentsURL: URL?
  var filePath: URL?
  let videoFileOutput = AVCaptureMovieFileOutput()

  override func viewDidLoad() {
    super.viewDidLoad()

    previewView.layer.cornerRadius = 15
    previewView.clipsToBounds = true

  }

  override func viewDidAppear(_ animated: Bool) {
    startVideoRecording()
    let recordingDelegate: AVCaptureFileOutputRecordingDelegate? = self
    videoPreviewLayer!.frame.size = previewView.frame.size
    videoFileOutput.startRecording(to: filePath!, recordingDelegate: recordingDelegate!)
    runTimer()
  }

  func runTimer() {
    countdownLabel.text = "\(seconds)"

    timer = Timer.scheduledTimer(timeInterval: 1, target: self,   selector: #selector(updateTimer), userInfo: nil, repeats: true)
  }

  @objc func updateTimer() {
    seconds -= 1     //This will decrement(count down)the seconds.
    countdownLabel.text = "\(seconds)" //This will update the label.

    if (seconds == 0) {
      timer.invalidate()
      stopRecording()
    }

  }

  func startVideoRecording() {
    let captureDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .front)
    let captureAudio = AVCaptureDevice.default(for: .audio)

    fileName = "mysavefile.mp4"
    documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
    filePath = documentsURL?.appendingPathComponent(fileName)  //.URLByAppendingPathComponent(fileName)

    do {
      let input = try AVCaptureDeviceInput(device: captureDevice!)
      let audio = try AVCaptureDeviceInput(device: captureAudio!)
      captureSession = AVCaptureSession()
      captureSession?.sessionPreset = .high
      captureSession?.addInput(input)
      captureSession?.addInput(audio)

      videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession!)
      videoPreviewLayer?.videoGravity = .resizeAspectFill
      videoPreviewLayer?.frame.size = previewView.frame.size
      previewView.layer.addSublayer(videoPreviewLayer!)

      self.captureSession!.addOutput(videoFileOutput)

      captureSession?.startRunning()

    } catch {
      print(error)
    }
  }

  @IBAction func stopButton(_ sender: Any) {
    stopRecording()
  }

  func stopRecording() {
    videoFileOutput.stopRecording()
  }

  func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) {
    videoUrl = outputFileURL
    captureSession?.stopRunning()
    videoPreviewLayer?.removeFromSuperlayer()
    self.performSegue(withIdentifier: "showViewer", sender: self)
  }

  override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    let transition = CATransition()
    transition.duration = 0.5
    transition.type = kCATransitionPush
    transition.subtype = kCATransitionFromRight
    transition.timingFunction = CAMediaTimingFunction(name:kCAMediaTimingFunctionEaseInEaseOut)
    self.view.window!.layer.add(transition, forKey: kCATransition)

    guard let vc = segue.destination as? ViewerController else { return }
    vc.videoUrl = self.videoUrl
    self.present(vc, animated: false, completion: nil)
  }

}

If I set the timer to 11 seconds or lower, the video is recorded with the audio perfectly fine. But the really weird thing is if I increase the timer to anything longer than 11 seconds, and let the recording stop when the timer hits 0, the recording has absolutely no sound.

Any ideas what might cause this?

eivindml
  • 2,197
  • 7
  • 36
  • 68

1 Answers1

0

I had the same issue and found the solution in this SO post: https://stackoverflow.com/a/31089253/1117968

You should be able to fix your issue by setting:

videoFileOutput.movieFragmentInterval = kCMTimeInvalid

before you start recording.

der_michael
  • 3,151
  • 1
  • 24
  • 43