Skip to content

Commit

Permalink
feat(IOS): implement video recording
Browse files Browse the repository at this point in the history
  • Loading branch information
WcaleNieWolny committed Sep 3, 2024
1 parent 265e4af commit 519e0b3
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 11 deletions.
46 changes: 36 additions & 10 deletions ios/Plugin/CameraController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ class CameraController: NSObject {

var rearCamera: AVCaptureDevice?
var rearCameraInput: AVCaptureDeviceInput?

var fileVideoOutput: AVCaptureMovieFileOutput?

var previewLayer: AVCaptureVideoPreviewLayer?

Expand Down Expand Up @@ -119,6 +121,12 @@ extension CameraController {
self.photoOutput!.setPreparedPhotoSettingsArray([AVCapturePhotoSettings(format: [AVVideoCodecKey: AVVideoCodecType.jpeg])], completionHandler: nil)
self.photoOutput?.isHighResolutionCaptureEnabled = self.highResolutionOutput
if captureSession.canAddOutput(self.photoOutput!) { captureSession.addOutput(self.photoOutput!) }

let fileVideoOutput = AVCaptureMovieFileOutput()
if captureSession.canAddOutput(fileVideoOutput) {
captureSession.addOutput(fileVideoOutput)
self.fileVideoOutput = fileVideoOutput
}
captureSession.startRunning()
}

Expand Down Expand Up @@ -427,17 +435,24 @@ extension CameraController {
guard let captureSession = self.captureSession, captureSession.isRunning else {
throw CameraControllerError.captureSessionIsMissing
}
let path = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0]
guard let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {
throw CameraControllerError.cannotFindDocumentsDirectory;
}

guard let fileVideoOutput = self.fileVideoOutput else {
throw CameraControllerError.fileVideoOutputNotFound
}

let identifier = UUID()
let randomIdentifier = identifier.uuidString.replacingOccurrences(of: "-", with: "")
let finalIdentifier = String(randomIdentifier.prefix(8))
let fileName="cpcp_video_"+finalIdentifier+".mp4"

let fileUrl = path.appendingPathComponent(fileName)
let fileUrl = documentsDirectory.appendingPathComponent(fileName)
try? FileManager.default.removeItem(at: fileUrl)

// Start recording video
// ...
fileVideoOutput.startRecording(to: fileUrl, recordingDelegate: self)

// Save the file URL for later use
self.videoFileURL = fileUrl
Expand All @@ -448,8 +463,13 @@ extension CameraController {
completion(nil, CameraControllerError.captureSessionIsMissing)
return
}
guard let fileVideoOutput = self.fileVideoOutput else {
completion(nil, CameraControllerError.fileVideoOutputNotFound)
return
}

// Stop recording video
// ...
fileVideoOutput.stopRecording()

// Return the video file URL in the completion handler
completion(self.videoFileURL, nil)
Expand Down Expand Up @@ -579,6 +599,8 @@ enum CameraControllerError: Swift.Error {
case inputsAreInvalid
case invalidOperation
case noCamerasAvailable
case cannotFindDocumentsDirectory
case fileVideoOutputNotFound
case unknown
}

Expand All @@ -602,7 +624,10 @@ extension CameraControllerError: LocalizedError {
return NSLocalizedString("Failed to access device camera(s)", comment: "No Cameras Available")
case .unknown:
return NSLocalizedString("Unknown", comment: "Unknown")

case .cannotFindDocumentsDirectory:
return NSLocalizedString("Cannot find documents directory", comment: "This should never happen")
case .fileVideoOutputNotFound:
return NSLocalizedString("Cannot find fileVideoOutput", comment: "Perhaps you are running IOS < 17 or you are not recording?")
}
}
}
Expand Down Expand Up @@ -678,10 +703,11 @@ extension UIImage {

extension CameraController: AVCaptureFileOutputRecordingDelegate {
func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) {
/*if error == nil {
self.videoRecordCompletionBlock?(outputFileURL, nil)
} else {
self.videoRecordCompletionBlock?(nil, error)
}*/
if let error = error {
print("Error recording movie: \(error.localizedDescription)")
} else {
print("Movie recorded successfully: \(outputFileURL)")
// You can save the file to the library, upload it, etc.
}
}
}
5 changes: 4 additions & 1 deletion ios/Plugin/Plugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,9 @@ public class CameraPreview: CAPPlugin {
}

@objc func startRecordVideo(_ call: CAPPluginCall) {
if #unavailable(iOS 17) {
call.reject("You cannot record video on IOS < 17")
}
DispatchQueue.main.async {
do {
try self.cameraController.captureVideo()
Expand All @@ -317,7 +320,7 @@ public class CameraPreview: CAPPlugin {
return
}

call.resolve(["videoUrl": fileURL.absoluteString])
call.resolve(["videoFilePath": fileURL.absoluteString])
}
}
}
Expand Down

0 comments on commit 519e0b3

Please sign in to comment.