The following is a way to record video with sound using the AVFoundation framework. Steps:
1. Prepare the session:
self.captureSession = AVCaptureSession()
2. Prepare available video and audio devices:
let session = AVCaptureDevice.DiscoverySession.init(deviceTypes:[.builtInWideAngleCamera, .builtInMicrophone], mediaType: AVMediaType.video, position: AVCaptureDevice.Position.unspecified) let cameras = (session.devices.compactMap{$0}) for camera in cameras { if camera.position == .front { self.frontCamera = camera } if camera.position == .back { self.rearCamera = camera try camera.lockForConfiguration() camera.focusMode = .continuousAutoFocus camera.unlockForConfiguration() } }
3. Prepare the session input:
guard let captureSession = self.captureSession else { throw CameraControllerError.captureSessionIsMissing } if let rearCamera = self.rearCamera { self.rearCameraInput = try AVCaptureDeviceInput(device: rearCamera) if captureSession.canAddInput(self.rearCameraInput!) { captureSession.addInput(self.rearCameraInput!) self.currentCameraPosition = .rear } else { throw CameraControllerError.inputsAreInvalid } } else if let frontCamera = self.frontCamera { self.frontCameraInput = try AVCaptureDeviceInput(device: frontCamera) if captureSession.canAddInput(self.frontCameraInput!) { captureSession.addInput(self.frontCameraInput!) self.currentCameraPosition = .front } else { throw CameraControllerError.inputsAreInvalid } } else { throw CameraControllerError.noCamerasAvailable }
4. Prepare a conclusion:
self.videoOutput = AVCaptureMovieFileOutput() if captureSession.canAddOutput(self.videoOutput!) { captureSession.addOutput(self.videoOutput!) } captureSession.startRunning()
5. Start recording:
func recordVideo(completion: @escaping (URL?, Error?)-> Void) { guard let captureSession = self.captureSession, captureSession.isRunning else { completion(nil, CameraControllerError.captureSessionIsMissing) return } let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) let fileUrl = paths[0].appendingPathComponent("output.mp4") try? FileManager.default.removeItem(at: fileUrl) videoOutput!.startRecording(to: fileUrl, recordingDelegate: self) self.videoRecordCompletionBlock = completion }
6. Stop recording:
func stopRecording(completion: @escaping (Error?)->Void) { guard let captureSession = self.captureSession, captureSession.isRunning else { completion(CameraControllerError.captureSessionIsMissing) return } self.videoOutput?.stopRecording() }
7. Implement the delegate:
func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) { if error == nil { //do something } else { //do something } }
I took the idea from here: https://www.appcoda.com/avfoundation-swift-guide/
Here is the complete project https://github.com/rubaiyat6370/iOS-Tutorial/