Skip to content

Commit

Permalink
Merge pull request #104 from Cap-go/implement_video_recording_ios
Browse files Browse the repository at this point in the history
feat(IOS): implement video recording
  • Loading branch information
riderx authored Sep 3, 2024
2 parents ca1fc09 + 1f64c46 commit c950519
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 11 deletions.
63 changes: 53 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,41 @@ 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
}

// cpcp_video_A6C01203 - portrait
//
if let connection = fileVideoOutput.connection(with: .video) {
switch UIDevice.current.orientation {
case .landscapeRight:
connection.videoOrientation = .landscapeLeft
case .landscapeLeft:
connection.videoOrientation = .landscapeRight
case .portrait:
connection.videoOrientation = .portrait
case .portraitUpsideDown:
connection.videoOrientation = .portraitUpsideDown
default:
connection.videoOrientation = .portrait
}
}

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 +480,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 +616,8 @@ enum CameraControllerError: Swift.Error {
case inputsAreInvalid
case invalidOperation
case noCamerasAvailable
case cannotFindDocumentsDirectory
case fileVideoOutputNotFound
case unknown
}

Expand All @@ -602,7 +641,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 +720,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.
}
}
}
20 changes: 19 additions & 1 deletion ios/Plugin/Plugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,21 @@ public class CameraPreview: CAPPlugin {
}
self.cameraController.previewLayer?.frame = self.previewView.frame
}

if let connection = self.cameraController.fileVideoOutput?.connection(with: .video) {
switch UIDevice.current.orientation {
case .landscapeRight:
connection.videoOrientation = .landscapeLeft
case .landscapeLeft:
connection.videoOrientation = .landscapeRight
case .portrait:
connection.videoOrientation = .portrait
case .portraitUpsideDown:
connection.videoOrientation = .portraitUpsideDown
default:
connection.videoOrientation = .portrait
}
}

cameraController.updateVideoOrientation()
}
Expand Down Expand Up @@ -294,6 +309,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 +335,7 @@ public class CameraPreview: CAPPlugin {
return
}

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

0 comments on commit c950519

Please sign in to comment.