@capgo/camera-preview 8.5.0 → 8.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +82 -3
- package/android/src/main/java/app/capgo/capacitor/camera/preview/CameraPreview.java +67 -0
- package/android/src/main/java/app/capgo/capacitor/camera/preview/CameraXView.java +94 -1
- package/android/src/main/java/app/capgo/capacitor/camera/preview/model/CameraSessionConfiguration.java +9 -0
- package/dist/docs.json +168 -3
- package/dist/esm/definitions.d.ts +58 -2
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/web.d.ts +11 -1
- package/dist/esm/web.js +12 -0
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +12 -0
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +12 -0
- package/dist/plugin.js.map +1 -1
- package/ios/Sources/CapgoCameraPreviewPlugin/CameraController.swift +161 -48
- package/ios/Sources/CapgoCameraPreviewPlugin/Plugin.swift +40 -3
- package/package.json +1 -1
|
@@ -57,6 +57,15 @@ class CameraController: NSObject {
|
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
private func setVideoOrientation(_ orientation: AVCaptureVideoOrientation, on connection: AVCaptureConnection) {
|
|
61
|
+
guard connection.isVideoOrientationSupported else { return }
|
|
62
|
+
connection.videoOrientation = orientation
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
private func setVideoOrientation(_ orientation: AVCaptureVideoOrientation, on connections: [AVCaptureConnection]) {
|
|
66
|
+
connections.forEach { setVideoOrientation(orientation, on: $0) }
|
|
67
|
+
}
|
|
68
|
+
|
|
60
69
|
// Continuous focus with significant movement if focus was locked from setFocus earlier
|
|
61
70
|
@objc private func subjectAreaDidChange(notification: NSNotification) {
|
|
62
71
|
guard let device = self.currentCameraPosition == .rear ? rearCamera : frontCamera else { return }
|
|
@@ -145,6 +154,7 @@ class CameraController: NSObject {
|
|
|
145
154
|
|
|
146
155
|
var videoQuality: String = "high"
|
|
147
156
|
var videoCodec: String = "avc1"
|
|
157
|
+
var videoStabilizationMode: String = "off"
|
|
148
158
|
|
|
149
159
|
private static let allVideoQualities = ["low", "medium", "high", "2160p", "1080p", "720p", "480p", "4:3"]
|
|
150
160
|
|
|
@@ -203,6 +213,138 @@ class CameraController: NSObject {
|
|
|
203
213
|
return self.videoCodec
|
|
204
214
|
}
|
|
205
215
|
|
|
216
|
+
func isVideoStabilizationSupported() -> Bool {
|
|
217
|
+
guard let connection = self.fileVideoOutput?.connection(with: .video) else {
|
|
218
|
+
return false
|
|
219
|
+
}
|
|
220
|
+
return connection.isVideoStabilizationSupported
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
func getSupportedVideoStabilizationModes() -> [String] {
|
|
224
|
+
guard let connection = self.fileVideoOutput?.connection(with: .video),
|
|
225
|
+
connection.isVideoStabilizationSupported else {
|
|
226
|
+
return ["off"]
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
let savedPreferred = connection.preferredVideoStabilizationMode
|
|
230
|
+
var supported: [String] = []
|
|
231
|
+
|
|
232
|
+
for candidate in Self.allVideoStabilizationModeCandidates() {
|
|
233
|
+
connection.preferredVideoStabilizationMode = candidate.mode
|
|
234
|
+
if connection.preferredVideoStabilizationMode == candidate.mode {
|
|
235
|
+
supported.append(candidate.name)
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
connection.preferredVideoStabilizationMode = savedPreferred
|
|
240
|
+
return supported.isEmpty ? ["off"] : supported
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
func getVideoStabilizationMode() -> String {
|
|
244
|
+
if let connection = self.fileVideoOutput?.connection(with: .video),
|
|
245
|
+
connection.isVideoStabilizationSupported {
|
|
246
|
+
return self.videoStabilizationModeString(from: connection.activeVideoStabilizationMode)
|
|
247
|
+
}
|
|
248
|
+
return self.videoStabilizationMode
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
func setVideoStabilizationMode(_ mode: String) throws {
|
|
252
|
+
if self.fileVideoOutput?.isRecording == true {
|
|
253
|
+
throw CameraControllerError.recordingInProgress
|
|
254
|
+
}
|
|
255
|
+
guard let avMode = self.avVideoStabilizationMode(from: mode) else {
|
|
256
|
+
throw CameraControllerError.invalidOperation
|
|
257
|
+
}
|
|
258
|
+
let supportedModes = self.getSupportedVideoStabilizationModes()
|
|
259
|
+
guard supportedModes.contains(mode) else {
|
|
260
|
+
throw CameraControllerError.invalidOperation
|
|
261
|
+
}
|
|
262
|
+
self.videoStabilizationMode = mode
|
|
263
|
+
self.applyVideoStabilizationMode(avMode)
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
private static func allVideoStabilizationModeCandidates() -> [(name: String, mode: AVCaptureVideoStabilizationMode)] {
|
|
267
|
+
var candidates: [(String, AVCaptureVideoStabilizationMode)] = [
|
|
268
|
+
("off", .off),
|
|
269
|
+
("standard", .standard),
|
|
270
|
+
("cinematic", .cinematic),
|
|
271
|
+
("cinematicExtended", .cinematicExtended),
|
|
272
|
+
("auto", .auto),
|
|
273
|
+
]
|
|
274
|
+
if #available(iOS 17.0, *) {
|
|
275
|
+
candidates.append(("previewOptimized", .previewOptimized))
|
|
276
|
+
}
|
|
277
|
+
if #available(iOS 18.0, *) {
|
|
278
|
+
candidates.append(("cinematicExtendedEnhanced", .cinematicExtendedEnhanced))
|
|
279
|
+
}
|
|
280
|
+
return candidates
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
private func applyVideoStabilizationMode(_ mode: AVCaptureVideoStabilizationMode? = nil) {
|
|
284
|
+
guard let connection = self.fileVideoOutput?.connection(with: .video),
|
|
285
|
+
connection.isVideoStabilizationSupported else {
|
|
286
|
+
return
|
|
287
|
+
}
|
|
288
|
+
let targetMode = mode ?? self.avVideoStabilizationMode(from: self.videoStabilizationMode) ?? .off
|
|
289
|
+
connection.preferredVideoStabilizationMode = targetMode
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
private func avVideoStabilizationMode(from mode: String) -> AVCaptureVideoStabilizationMode? {
|
|
293
|
+
switch mode {
|
|
294
|
+
case "off":
|
|
295
|
+
return .off
|
|
296
|
+
case "standard":
|
|
297
|
+
return .standard
|
|
298
|
+
case "cinematic":
|
|
299
|
+
return .cinematic
|
|
300
|
+
case "cinematicExtended":
|
|
301
|
+
return .cinematicExtended
|
|
302
|
+
case "auto":
|
|
303
|
+
return .auto
|
|
304
|
+
case "previewOptimized":
|
|
305
|
+
if #available(iOS 17.0, *) {
|
|
306
|
+
return .previewOptimized
|
|
307
|
+
}
|
|
308
|
+
return nil
|
|
309
|
+
case "cinematicExtendedEnhanced":
|
|
310
|
+
if #available(iOS 18.0, *) {
|
|
311
|
+
return .cinematicExtendedEnhanced
|
|
312
|
+
}
|
|
313
|
+
return nil
|
|
314
|
+
case "lowLatency":
|
|
315
|
+
return nil
|
|
316
|
+
default:
|
|
317
|
+
return nil
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
private func videoStabilizationModeString(from mode: AVCaptureVideoStabilizationMode) -> String {
|
|
322
|
+
switch mode {
|
|
323
|
+
case .off:
|
|
324
|
+
return "off"
|
|
325
|
+
case .standard:
|
|
326
|
+
return "standard"
|
|
327
|
+
case .cinematic:
|
|
328
|
+
return "cinematic"
|
|
329
|
+
case .cinematicExtended:
|
|
330
|
+
return "cinematicExtended"
|
|
331
|
+
case .auto:
|
|
332
|
+
return "auto"
|
|
333
|
+
default:
|
|
334
|
+
if #available(iOS 17.0, *) {
|
|
335
|
+
if mode == .previewOptimized {
|
|
336
|
+
return "previewOptimized"
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
if #available(iOS 18.0, *) {
|
|
340
|
+
if mode == .cinematicExtendedEnhanced {
|
|
341
|
+
return "cinematicExtendedEnhanced"
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
return self.videoStabilizationMode
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
206
348
|
private func avVideoCodecType(for codec: String) -> AVVideoCodecType? {
|
|
207
349
|
switch codec.lowercased() {
|
|
208
350
|
case "avc1":
|
|
@@ -416,45 +558,7 @@ extension CameraController {
|
|
|
416
558
|
let layer = AVCaptureVideoPreviewLayer()
|
|
417
559
|
// Configure orientation immediately
|
|
418
560
|
if let connection = layer.connection {
|
|
419
|
-
|
|
420
|
-
if Thread.isMainThread {
|
|
421
|
-
if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene {
|
|
422
|
-
switch windowScene.interfaceOrientation {
|
|
423
|
-
case .portrait:
|
|
424
|
-
connection.videoOrientation = .portrait
|
|
425
|
-
case .landscapeLeft:
|
|
426
|
-
connection.videoOrientation = .landscapeLeft
|
|
427
|
-
case .landscapeRight:
|
|
428
|
-
connection.videoOrientation = .landscapeRight
|
|
429
|
-
case .portraitUpsideDown:
|
|
430
|
-
connection.videoOrientation = .portraitUpsideDown
|
|
431
|
-
case .unknown:
|
|
432
|
-
fallthrough
|
|
433
|
-
@unknown default:
|
|
434
|
-
connection.videoOrientation = .portrait
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
} else {
|
|
438
|
-
// If not on main thread, use a sync call to get the orientation
|
|
439
|
-
DispatchQueue.main.sync {
|
|
440
|
-
if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene {
|
|
441
|
-
switch windowScene.interfaceOrientation {
|
|
442
|
-
case .portrait:
|
|
443
|
-
connection.videoOrientation = .portrait
|
|
444
|
-
case .landscapeLeft:
|
|
445
|
-
connection.videoOrientation = .landscapeLeft
|
|
446
|
-
case .landscapeRight:
|
|
447
|
-
connection.videoOrientation = .landscapeRight
|
|
448
|
-
case .portraitUpsideDown:
|
|
449
|
-
connection.videoOrientation = .portraitUpsideDown
|
|
450
|
-
case .unknown:
|
|
451
|
-
fallthrough
|
|
452
|
-
@unknown default:
|
|
453
|
-
connection.videoOrientation = .portrait
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
}
|
|
561
|
+
self.setVideoOrientation(self.getVideoOrientation(), on: connection)
|
|
458
562
|
}
|
|
459
563
|
// Don't set session here - we'll do it during configuration
|
|
460
564
|
self.previewLayer = layer
|
|
@@ -527,7 +631,7 @@ extension CameraController {
|
|
|
527
631
|
let videoQueue = DispatchQueue(label: "com.camera.videoQueue", qos: .userInteractive)
|
|
528
632
|
dataOutput.setSampleBufferDelegate(self, queue: videoQueue)
|
|
529
633
|
// Set orientation immediately
|
|
530
|
-
|
|
634
|
+
self.setVideoOrientation(videoOrientation, on: dataOutput.connections)
|
|
531
635
|
}
|
|
532
636
|
|
|
533
637
|
// Add photo output immediately to avoid later reconfiguration
|
|
@@ -535,21 +639,22 @@ extension CameraController {
|
|
|
535
639
|
photoOutput.isHighResolutionCaptureEnabled = true
|
|
536
640
|
captureSession.addOutput(photoOutput)
|
|
537
641
|
// Set orientation immediately
|
|
538
|
-
|
|
642
|
+
self.setVideoOrientation(videoOrientation, on: photoOutput.connections)
|
|
539
643
|
}
|
|
540
644
|
|
|
541
645
|
// Add video output if in camera mode
|
|
542
646
|
if cameraMode, let fileVideoOutput = self.fileVideoOutput, captureSession.canAddOutput(fileVideoOutput) {
|
|
543
647
|
captureSession.addOutput(fileVideoOutput)
|
|
544
648
|
// Set orientation immediately
|
|
545
|
-
|
|
649
|
+
self.setVideoOrientation(videoOrientation, on: fileVideoOutput.connections)
|
|
650
|
+
self.applyVideoStabilizationMode()
|
|
546
651
|
}
|
|
547
652
|
|
|
548
653
|
// Set up preview layer session in the same configuration block
|
|
549
654
|
if let layer = self.previewLayer {
|
|
550
655
|
layer.session = captureSession
|
|
551
656
|
// Set orientation for preview layer
|
|
552
|
-
layer.connection
|
|
657
|
+
if let connection = layer.connection { self.setVideoOrientation(videoOrientation, on: connection) }
|
|
553
658
|
// Start with a very subtle fade to smooth any remaining visual artifacts
|
|
554
659
|
layer.opacity = 0.95
|
|
555
660
|
}
|
|
@@ -930,9 +1035,10 @@ extension CameraController {
|
|
|
930
1035
|
// Apply orientation asynchronously on main thread
|
|
931
1036
|
let updateBlock = { [weak self] in
|
|
932
1037
|
guard let self = self else { return }
|
|
933
|
-
self.previewLayer?.connection
|
|
934
|
-
self.dataOutput?.connections
|
|
935
|
-
self.photoOutput?.connections
|
|
1038
|
+
if let connection = self.previewLayer?.connection { self.setVideoOrientation(videoOrientation, on: connection) }
|
|
1039
|
+
if let connections = self.dataOutput?.connections { self.setVideoOrientation(videoOrientation, on: connections) }
|
|
1040
|
+
if let connections = self.photoOutput?.connections { self.setVideoOrientation(videoOrientation, on: connections) }
|
|
1041
|
+
if let connections = self.fileVideoOutput?.connections { self.setVideoOrientation(videoOrientation, on: connections) }
|
|
936
1042
|
}
|
|
937
1043
|
|
|
938
1044
|
if Thread.isMainThread {
|
|
@@ -1121,6 +1227,7 @@ extension CameraController {
|
|
|
1121
1227
|
captureSession.removeOutput(fileVideoOutput)
|
|
1122
1228
|
if captureSession.canAddOutput(fileVideoOutput) {
|
|
1123
1229
|
captureSession.addOutput(fileVideoOutput)
|
|
1230
|
+
self.applyVideoStabilizationMode()
|
|
1124
1231
|
}
|
|
1125
1232
|
}
|
|
1126
1233
|
|
|
@@ -1138,7 +1245,7 @@ extension CameraController {
|
|
|
1138
1245
|
if let connection = photoOutput.connection(with: .video) {
|
|
1139
1246
|
let captureOrientation = self.getPhysicalOrientation()
|
|
1140
1247
|
self.lastCaptureOrientation = captureOrientation
|
|
1141
|
-
|
|
1248
|
+
self.setVideoOrientation(captureOrientation, on: connection)
|
|
1142
1249
|
}
|
|
1143
1250
|
let settings = AVCapturePhotoSettings()
|
|
1144
1251
|
// Configure photo capture settings optimized for speed
|
|
@@ -2506,6 +2613,7 @@ extension CameraController {
|
|
|
2506
2613
|
captureSession.beginConfiguration()
|
|
2507
2614
|
if captureSession.canAddOutput(fileVideoOutput) {
|
|
2508
2615
|
captureSession.addOutput(fileVideoOutput)
|
|
2616
|
+
self.applyVideoStabilizationMode()
|
|
2509
2617
|
} else {
|
|
2510
2618
|
captureSession.commitConfiguration()
|
|
2511
2619
|
throw CameraControllerError.invalidOperation
|
|
@@ -2516,7 +2624,7 @@ extension CameraController {
|
|
|
2516
2624
|
if let connection = fileVideoOutput.connection(with: .video) {
|
|
2517
2625
|
if connection.isEnabled == false { connection.isEnabled = true }
|
|
2518
2626
|
// Goes off accelerometer now
|
|
2519
|
-
|
|
2627
|
+
self.setVideoOrientation(self.getPhysicalOrientation(), on: connection)
|
|
2520
2628
|
|
|
2521
2629
|
// Front camera: mirror the recorded video so it looks natural (selfie style).
|
|
2522
2630
|
if self.currentCameraPosition == .front, connection.isVideoMirroringSupported {
|
|
@@ -2547,6 +2655,8 @@ extension CameraController {
|
|
|
2547
2655
|
fileVideoOutput.setOutputSettings([AVVideoCodecKey: codecType], for: connection)
|
|
2548
2656
|
}
|
|
2549
2657
|
|
|
2658
|
+
self.applyVideoStabilizationMode()
|
|
2659
|
+
|
|
2550
2660
|
// Start recording video
|
|
2551
2661
|
fileVideoOutput.startRecording(to: fileUrl, recordingDelegate: self)
|
|
2552
2662
|
|
|
@@ -2851,6 +2961,7 @@ enum CameraControllerError: Swift.Error {
|
|
|
2851
2961
|
case invalidOperation
|
|
2852
2962
|
case noCamerasAvailable
|
|
2853
2963
|
case cannotFindDocumentsDirectory
|
|
2964
|
+
case recordingInProgress
|
|
2854
2965
|
case fileVideoOutputNotFound
|
|
2855
2966
|
case unknown
|
|
2856
2967
|
case invalidZoomLevel(min: CGFloat, max: CGFloat, requested: CGFloat)
|
|
@@ -2878,6 +2989,8 @@ extension CameraControllerError: LocalizedError {
|
|
|
2878
2989
|
return NSLocalizedString("Unknown", comment: "Unknown")
|
|
2879
2990
|
case .cannotFindDocumentsDirectory:
|
|
2880
2991
|
return NSLocalizedString("Cannot find documents directory", comment: "This should never happen")
|
|
2992
|
+
case .recordingInProgress:
|
|
2993
|
+
return NSLocalizedString("Cannot change video stabilization while recording is in progress.", comment: "Recording in progress")
|
|
2881
2994
|
case .fileVideoOutputNotFound:
|
|
2882
2995
|
return NSLocalizedString("Video recording is not available. Make sure the camera is properly initialized.", comment: "Video recording not available")
|
|
2883
2996
|
case .invalidZoomLevel(let min, let max, let requested):
|
|
@@ -35,7 +35,7 @@ extension UIWindow {
|
|
|
35
35
|
*/
|
|
36
36
|
@objc(CameraPreview)
|
|
37
37
|
public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelegate {
|
|
38
|
-
private let pluginVersion: String = "8.
|
|
38
|
+
private let pluginVersion: String = "8.6.0"
|
|
39
39
|
public let identifier = "CameraPreviewPlugin"
|
|
40
40
|
public let jsName = "CameraPreview"
|
|
41
41
|
public let pluginMethods: [CAPPluginMethod] = [
|
|
@@ -54,6 +54,10 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
|
|
|
54
54
|
CAPPluginMethod(name: "getSupportedVideoCodecs", returnType: CAPPluginReturnPromise),
|
|
55
55
|
CAPPluginMethod(name: "getVideoCodec", returnType: CAPPluginReturnPromise),
|
|
56
56
|
CAPPluginMethod(name: "setVideoCodec", returnType: CAPPluginReturnPromise),
|
|
57
|
+
CAPPluginMethod(name: "isVideoStabilizationSupported", returnType: CAPPluginReturnPromise),
|
|
58
|
+
CAPPluginMethod(name: "getSupportedVideoStabilizationModes", returnType: CAPPluginReturnPromise),
|
|
59
|
+
CAPPluginMethod(name: "getVideoStabilizationMode", returnType: CAPPluginReturnPromise),
|
|
60
|
+
CAPPluginMethod(name: "setVideoStabilizationMode", returnType: CAPPluginReturnPromise),
|
|
57
61
|
CAPPluginMethod(name: "getSupportedVideoQualities", returnType: CAPPluginReturnPromise),
|
|
58
62
|
CAPPluginMethod(name: "getVideoQuality", returnType: CAPPluginReturnPromise),
|
|
59
63
|
CAPPluginMethod(name: "setVideoQuality", returnType: CAPPluginReturnPromise),
|
|
@@ -652,7 +656,7 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
|
|
|
652
656
|
print("[CameraPreview] 📋 Settings received:")
|
|
653
657
|
print(" - position: \(call.getString("position") ?? "rear")")
|
|
654
658
|
print(" - deviceId: \(call.getString("deviceId") ?? "nil")")
|
|
655
|
-
print(" -
|
|
659
|
+
print(" - enableVideoMode: \(call.getBool("enableVideoMode") ?? call.getBool("cameraMode") ?? false)")
|
|
656
660
|
print(" - width: \(call.getInt("width") ?? 0)")
|
|
657
661
|
print(" - height: \(call.getInt("height") ?? 0)")
|
|
658
662
|
print(" - x: \(call.getInt("x") ?? -1)")
|
|
@@ -724,7 +728,7 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
|
|
|
724
728
|
|
|
725
729
|
self.cameraPosition = call.getString("position") ?? "rear"
|
|
726
730
|
let deviceId = call.getString("deviceId")
|
|
727
|
-
let cameraMode = call.getBool("cameraMode") ?? false
|
|
731
|
+
let cameraMode = call.getBool("enableVideoMode") ?? call.getBool("cameraMode") ?? false
|
|
728
732
|
|
|
729
733
|
// Set width - use screen width if not provided or if 0
|
|
730
734
|
if let width = call.getInt("width"), width > 0 {
|
|
@@ -1643,12 +1647,45 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
|
|
|
1643
1647
|
call.resolve(["codecs": self.cameraController.getSupportedVideoCodecs()])
|
|
1644
1648
|
}
|
|
1645
1649
|
|
|
1650
|
+
@objc func isVideoStabilizationSupported(_ call: CAPPluginCall) {
|
|
1651
|
+
call.resolve(["supported": self.cameraController.isVideoStabilizationSupported()])
|
|
1652
|
+
}
|
|
1653
|
+
|
|
1654
|
+
@objc func getSupportedVideoStabilizationModes(_ call: CAPPluginCall) {
|
|
1655
|
+
call.resolve(["modes": self.cameraController.getSupportedVideoStabilizationModes()])
|
|
1656
|
+
}
|
|
1657
|
+
|
|
1658
|
+
@objc func getVideoStabilizationMode(_ call: CAPPluginCall) {
|
|
1659
|
+
call.resolve(["mode": self.cameraController.getVideoStabilizationMode()])
|
|
1660
|
+
}
|
|
1661
|
+
|
|
1662
|
+
@objc func setVideoStabilizationMode(_ call: CAPPluginCall) {
|
|
1663
|
+
guard let mode = call.getString("mode") else {
|
|
1664
|
+
call.reject("mode is required")
|
|
1665
|
+
return
|
|
1666
|
+
}
|
|
1667
|
+
do {
|
|
1668
|
+
try self.cameraController.setVideoStabilizationMode(mode)
|
|
1669
|
+
call.resolve()
|
|
1670
|
+
} catch {
|
|
1671
|
+
call.reject("Failed to set video stabilization mode: \(error.localizedDescription)")
|
|
1672
|
+
}
|
|
1673
|
+
}
|
|
1674
|
+
|
|
1646
1675
|
@objc func startRecordVideo(_ call: CAPPluginCall) {
|
|
1647
1676
|
let maxDuration = call.getFloat("maxDuration")
|
|
1648
1677
|
let maxFileSize = call.getInt("maxFileSize")
|
|
1649
1678
|
if let videoCodec = call.getString("videoCodec") {
|
|
1650
1679
|
try? self.cameraController.setVideoCodec(videoCodec)
|
|
1651
1680
|
}
|
|
1681
|
+
if let videoStabilizationMode = call.getString("videoStabilizationMode") {
|
|
1682
|
+
do {
|
|
1683
|
+
try self.cameraController.setVideoStabilizationMode(videoStabilizationMode)
|
|
1684
|
+
} catch {
|
|
1685
|
+
call.reject("Failed to set video stabilization mode: \(error.localizedDescription)")
|
|
1686
|
+
return
|
|
1687
|
+
}
|
|
1688
|
+
}
|
|
1652
1689
|
self.cameraController.recordingFinishedCallback = { [weak self] fileURL, reason in
|
|
1653
1690
|
DispatchQueue.main.async {
|
|
1654
1691
|
self?.notifyListeners("recordingFinished", data: ["videoFilePath": fileURL.absoluteString, "reason": reason])
|