diff --git a/docs/RNCamera.md b/docs/RNCamera.md index 9c8a3c821..6727b5943 100644 --- a/docs/RNCamera.md +++ b/docs/RNCamera.md @@ -250,6 +250,17 @@ By default a `Camera not authorized` message will be displayed when access to th By default a will be displayed while the component is waiting for the user to grant/deny access to the camera, if set displays the passed react element instead of the default one. +### `iOS` `videoStabilizationMode` + +The video stabilization mode used for a video recording. The possible values are: + + - `RNCamera.Constants.VideoStabilization['off']` + - `RNCamera.Constants.VideoStabilization['standard']` + - `RNCamera.Constants.VideoStabilization['cinematic']` + - `RNCamera.Constants.VideoStabilization['auto']` + +You can read more about each stabilization type here: https://developer.apple.com/documentation/avfoundation/avcapturevideostabilizationmode + ### Native Event callbacks props #### `onCameraReady` diff --git a/ios/RN/RNCamera.h b/ios/RN/RNCamera.h index e7d1cefc3..b70003994 100644 --- a/ios/RN/RNCamera.h +++ b/ios/RN/RNCamera.h @@ -33,6 +33,7 @@ @property (nonatomic, assign) BOOL isReadingBarCodes; @property (nonatomic, assign) BOOL isDetectingFaces; @property(assign, nonatomic) AVVideoCodecType videoCodecType; +@property (assign, nonatomic) AVCaptureVideoStabilizationMode videoStabilizationMode; - (id)initWithBridge:(RCTBridge *)bridge; - (void)updateType; diff --git a/ios/RN/RNCamera.m b/ios/RN/RNCamera.m index 36ff71471..f08f197e4 100644 --- a/ios/RN/RNCamera.m +++ b/ios/RN/RNCamera.m @@ -441,6 +441,13 @@ - (void)record:(NSDictionary *)options resolve:(RCTPromiseResolveBlock)resolve r [self updateSessionAudioIsMuted:!!options[@"mute"]]; AVCaptureConnection *connection = [self.movieFileOutput connectionWithMediaType:AVMediaTypeVideo]; + if (self.videoStabilizationMode != nil) { + if (connection.isVideoStabilizationSupported == NO) { + RCTLogWarn(@"%s: Video Stabilization is not supported on this device.", __func__); + } else { + [connection setPreferredVideoStabilizationMode:self.videoStabilizationMode]; + } + } [connection setVideoOrientation:[RNCameraUtils videoOrientationForDeviceOrientation:[[UIDevice currentDevice] orientation]]]; if (options[@"codec"]) { diff --git a/ios/RN/RNCameraManager.h b/ios/RN/RNCameraManager.h index c07b2ab03..36412875d 100644 --- a/ios/RN/RNCameraManager.h +++ b/ios/RN/RNCameraManager.h @@ -59,6 +59,7 @@ typedef NS_ENUM(NSInteger, RNCameraVideoResolution) { + (NSDictionary *)validBarCodeTypes; + (NSDictionary *)validCodecTypes; ++ (NSDictionary *)validVideoStabilizationModes; @end diff --git a/ios/RN/RNCameraManager.m b/ios/RN/RNCameraManager.m index 8b0b2a581..64038fbda 100644 --- a/ios/RN/RNCameraManager.m +++ b/ios/RN/RNCameraManager.m @@ -66,7 +66,8 @@ - (NSDictionary *)constantsToExport }, @"VideoCodec": [[self class] validCodecTypes], @"BarCodeType" : [[self class] validBarCodeTypes], - @"FaceDetection" : [[self class] faceDetectorConstants] + @"FaceDetection" : [[self class] faceDetectorConstants], + @"VideoStabilization": [[self class] validVideoStabilizationModes] }; } @@ -93,6 +94,16 @@ + (NSDictionary *)validCodecTypes } } ++ (NSDictionary *)validVideoStabilizationModes +{ + return @{ + @"off": AVCaptureVideoStabilizationModeOff, + @"standard": AVCaptureVideoStabilizationModeStandard, + @"cinematic": AVCaptureVideoStabilizationModeCinematic, + @"auto": AVCaptureVideoStabilizationModeAuto + }; +} + + (NSDictionary *)validBarCodeTypes { return @{ diff --git a/src/RNCamera.js b/src/RNCamera.js index ed4ec1433..8e91114c1 100644 --- a/src/RNCamera.js +++ b/src/RNCamera.js @@ -97,6 +97,7 @@ type PropsType = typeof View.props & { captureAudio?: boolean, useCamera2Api?: boolean, playSoundOnCapture?: boolean, + videoStabilizationMode?: string, pictureSize?: string, }; @@ -156,6 +157,7 @@ export default class Camera extends React.Component { GoogleVisionBarcodeDetection: CameraManager.GoogleVisionBarcodeDetection, FaceDetection: CameraManager.FaceDetection, CameraStatus, + VideoStabilization: CameraManager.VideoStabilization || {}, }; // Values under keys from this object will be transformed to native options @@ -198,6 +200,7 @@ export default class Camera extends React.Component { captureAudio: PropTypes.bool, useCamera2Api: PropTypes.bool, playSoundOnCapture: PropTypes.bool, + videoStabilizationMode: PropTypes.string, pictureSize: PropTypes.string, };