Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for setting video settings, moved to pnpm, fixed 2nd stream reconnection #39

Open
wants to merge 33 commits into
base: master
Choose a base branch
from

Conversation

Andriiklymiuk
Copy link

@Andriiklymiuk Andriiklymiuk commented Apr 14, 2023

In the MR I added:

  • setVideoSettings method, with which you can setup your needed video quality
  • videoSettings prop - does the same as setVideoSettings, but useful, when you need just default video setting
  • added fix for 2nd stream reconnection based on this one Stream publish fix on iOS #35
  • added listener for CLOSED status (useful, when the stream closed and you need to listen to that and act accordingly)
  • added fix for green dot, when screen is unmounted, based on this one Detach devices on remove #36
  • changed yarn to pnpm, because it is faster and has autocomplete in it
  • added some useful scripts in the package.json to easy local testing of the library
  • fix styling for tsconfig

p.s. will publish separate library till these fixes are implemented (don't know if this library still supported)

@Andriiklymiuk
Copy link
Author

Andriiklymiuk commented Apr 14, 2023

created react-native-publisher, till we are waiting for approval.

You can also use patch-package react-native-rtmp-publisher+0.4.7.patch with this library, if you don't want to use just another fork.
Here it is

diff --git a/node_modules/react-native-rtmp-publisher/ios/RTMPCreator.swift b/node_modules/react-native-rtmp-publisher/ios/RTMPCreator.swift
index 7538bf3..a897ef9 100644
--- a/node_modules/react-native-rtmp-publisher/ios/RTMPCreator.swift
+++ b/node_modules/react-native-rtmp-publisher/ios/RTMPCreator.swift
@@ -6,6 +6,14 @@
 //
 import HaishinKit
 import AVFoundation
+import VideoToolbox
+
+struct VideoSettingsType {
+    var width: Int
+    var height: Int
+    var bitrate: Int
+    var audioBitrate: Int
+}
 
 class RTMPCreator {
     public static let connection: RTMPConnection = RTMPConnection()
@@ -14,6 +22,12 @@ class RTMPCreator {
     private static var _streamUrl: String = ""
     private static var _streamName: String = ""
     public static var isStreaming: Bool = false
+    public static var videoSettings: VideoSettingsType = VideoSettingsType(
+        width: 720,
+        height: 1280,
+        bitrate: 3000 * 1024,
+        audioBitrate: 128 * 1000
+    )
 
     public static func setStreamUrl(url: String){
         _streamUrl = url
@@ -38,10 +52,24 @@ class RTMPCreator {
     public static func startPublish(){
         connection.requireNetworkFramework = true
         connection.connect(_streamUrl)
-        stream.publish(_streamName)
         isStreaming = true
     }
     
+    public static func setVideoSettings(_ newVideoSettings: VideoSettingsType) {
+        videoSettings = newVideoSettings
+        stream.videoSettings = [
+            .width: videoSettings.width,
+            .height: videoSettings.height,
+            .bitrate: videoSettings.bitrate,
+            .scalingMode: ScalingMode.cropSourceToCleanAperture,
+            .profileLevel: kVTProfileLevel_H264_High_AutoLevel
+        ]
+
+        RTMPCreator.stream.audioSettings = [
+            .bitrate: videoSettings.audioBitrate
+        ]
+    }
+  
     public static func stopPublish(){
         stream.close()
         connection.close()
diff --git a/node_modules/react-native-rtmp-publisher/ios/RTMPManager/RTMPView.swift b/node_modules/react-native-rtmp-publisher/ios/RTMPManager/RTMPView.swift
index 06276dd..f5c4592 100644
--- a/node_modules/react-native-rtmp-publisher/ios/RTMPManager/RTMPView.swift
+++ b/node_modules/react-native-rtmp-publisher/ios/RTMPManager/RTMPView.swift
@@ -8,6 +8,7 @@
 import UIKit
 import HaishinKit
 import AVFoundation
+import VideoToolbox
 
 class RTMPView: UIView {
   private var hkView: MTHKView!
@@ -30,6 +31,28 @@ class RTMPView: UIView {
     }
   }
   
+  @objc var videoSettings: NSDictionary = NSDictionary(
+      dictionary: [
+        "width": 720,
+        "height": 1280,
+        "bitrate": 3000 * 1000,
+        "audioBitrate": 192 * 1000
+      ]
+  ){
+    didSet {
+        let width = videoSettings["width"] as? Int ?? 720
+        let height = videoSettings["height"] as? Int ?? 1280
+        let bitrate = videoSettings["bitrate"] as? Int ?? (3000 * 1000)
+        let audioBitrate = videoSettings["audioBitrate"] as? Int ?? (192 * 1000)
+        
+        RTMPCreator.setVideoSettings(VideoSettingsType(width: width, height: height, bitrate: bitrate, audioBitrate: audioBitrate)
+        )
+    }
+  }
+    
+    private var retryCount: Int = 0
+    private static let maxRetryCount: Int = 10
+  
   override init(frame: CGRect) {
     super.init(frame: frame)
     UIApplication.shared.isIdleTimerDisabled = true
@@ -37,25 +60,30 @@ class RTMPView: UIView {
     hkView = MTHKView(frame: UIScreen.main.bounds)
     hkView.videoGravity = .resizeAspectFill
     
+    RTMPCreator.stream.audioSettings = [
+        .bitrate: RTMPCreator.videoSettings.audioBitrate
+    ]
+      
     RTMPCreator.stream.captureSettings = [
-        .fps: 30,
-        .sessionPreset: AVCaptureSession.Preset.hd1920x1080,
-        .continuousAutofocus: true,
-        .continuousExposure: true
+      .fps: 30,
+      .sessionPreset: AVCaptureSession.Preset.hd1920x1080,
+      .continuousAutofocus: true,
+      .continuousExposure: true,
     ]
 
     RTMPCreator.stream.videoSettings = [
-        .width: 720,
-        .height: 1280,
-        .bitrate: 3000 * 1024,
-        .scalingMode: ScalingMode.cropSourceToCleanAperture
-        
+      .width: RTMPCreator.videoSettings.width,
+      .height: RTMPCreator.videoSettings.height,
+      .bitrate: RTMPCreator.videoSettings.bitrate,
+      .scalingMode: ScalingMode.cropSourceToCleanAperture,
+      .profileLevel: kVTProfileLevel_H264_High_AutoLevel
     ]
 
     RTMPCreator.stream.attachAudio(AVCaptureDevice.default(for: .audio))
-    RTMPCreator.stream.attachCamera(DeviceUtil.device(withPosition: AVCaptureDevice.Position.back))
+    RTMPCreator.stream.attachCamera(AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back))
 
     RTMPCreator.connection.addEventListener(.rtmpStatus, selector: #selector(statusHandler), observer: self)
+    RTMPCreator.connection.addEventListener(.ioError, selector: #selector(rtmpErrorHandler), observer: self)
 
     hkView.attachStream(RTMPCreator.stream)
 
@@ -63,13 +91,22 @@ class RTMPView: UIView {
       
 }
     
+    @objc
+    private func rtmpErrorHandler(_ notification: Notification) {
+        print("rtmpErrorHandler", notification)
+
+        changeStreamState(status: "I/O ERROR")
+        RTMPCreator.connection.connect(streamURL as String)
+    }
+    
     required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
      }
     
     override func removeFromSuperview() {
-        print("ON REMOVE")
-    }
+        RTMPCreator.stream.attachAudio(nil)
+        RTMPCreator.stream.attachCamera(nil)
+     }
   
     @objc
     private func statusHandler(_ notification: Notification){
@@ -83,7 +120,9 @@ class RTMPView: UIView {
          if onConnectionSuccess != nil {
               onConnectionSuccess!(nil)
             }
+           retryCount = 0
            changeStreamState(status: "CONNECTING")
+           RTMPCreator.stream.publish(streamName as String)
            break
        
        case RTMPConnection.Code.connectFailed.rawValue:
@@ -91,12 +130,15 @@ class RTMPView: UIView {
               onConnectionFailed!(nil)
             }
            changeStreamState(status: "FAILED")
+           reconnect()
            break
          
        case RTMPConnection.Code.connectClosed.rawValue:
          if onDisconnect != nil {
               onDisconnect!(nil)
             }
+           changeStreamState(status: "CLOSED")
+           reconnect()
            break
          
        case RTMPStream.Code.publishStart.rawValue:
@@ -107,10 +149,20 @@ class RTMPView: UIView {
            break
          
        default:
+           changeStreamState(status: code)
            break
        }
     }
     
+    public func reconnect(){
+        guard retryCount <= RTMPView.maxRetryCount else {
+         return
+        }
+        Thread.sleep(forTimeInterval: pow(2.0, Double(retryCount)))
+        RTMPCreator.connection.connect(streamURL as String)
+        retryCount += 1
+    }
+
     public func changeStreamState(status: String){
       if onStreamStateChanged != nil {
         onStreamStateChanged!(["data": status])
diff --git a/node_modules/react-native-rtmp-publisher/ios/RTMPManager/RTMPViewManager.m b/node_modules/react-native-rtmp-publisher/ios/RTMPManager/RTMPViewManager.m
index de3f5bc..1351444 100644
--- a/node_modules/react-native-rtmp-publisher/ios/RTMPManager/RTMPViewManager.m
+++ b/node_modules/react-native-rtmp-publisher/ios/RTMPManager/RTMPViewManager.m
@@ -18,6 +18,8 @@ RCT_EXPORT_VIEW_PROPERTY(streamURL, NSString)
 
 RCT_EXPORT_VIEW_PROPERTY(streamName, NSString)
 
+RCT_EXPORT_VIEW_PROPERTY(videoSettings, NSDictionary)
+
 RCT_EXPORT_VIEW_PROPERTY(onDisconnect, RCTDirectEventBlock)
 
 RCT_EXPORT_VIEW_PROPERTY(onConnectionFailed, RCTDirectEventBlock)
diff --git a/node_modules/react-native-rtmp-publisher/ios/RTMPModule/RTMPModule.m b/node_modules/react-native-rtmp-publisher/ios/RTMPModule/RTMPModule.m
index b29a6f7..da37b37 100644
--- a/node_modules/react-native-rtmp-publisher/ios/RTMPModule/RTMPModule.m
+++ b/node_modules/react-native-rtmp-publisher/ios/RTMPModule/RTMPModule.m
@@ -81,4 +81,10 @@ RCT_EXTERN_METHOD(
                     reject: (RCTPromiseRejectBlock)reject
                   )
 
+RCT_EXTERN_METHOD(
+                    setVideoSettings: (NSDictionary *)videoSettings
+                    resolve: (RCTPromiseResolveBlock)resolve
+                    reject: (RCTPromiseRejectBlock)reject
+                  )
+
 @end
diff --git a/node_modules/react-native-rtmp-publisher/ios/RTMPModule/RTMPModule.swift b/node_modules/react-native-rtmp-publisher/ios/RTMPModule/RTMPModule.swift
index d346b74..04e0da0 100644
--- a/node_modules/react-native-rtmp-publisher/ios/RTMPModule/RTMPModule.swift
+++ b/node_modules/react-native-rtmp-publisher/ios/RTMPModule/RTMPModule.swift
@@ -20,6 +20,21 @@ class RTMPModule: NSObject {
         RTMPCreator.startPublish()
     }
 
+    @objc
+    func setVideoSettings(_ videoSettingsDict: NSDictionary, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
+        guard let width = videoSettingsDict["width"] as? Int,
+              let height = videoSettingsDict["height"] as? Int,
+              let bitrate = videoSettingsDict["bitrate"] as? Int else {
+            reject("INVALID_ARGUMENTS", "Invalid video settings", nil)
+            return
+        }
+        let audioBitrate = videoSettingsDict["audioBitrate"] as? Int ?? 128000
+        let videoSettings = VideoSettingsType(width: width, height: height, bitrate: bitrate, audioBitrate: audioBitrate)
+        
+        resolve(RTMPCreator.setVideoSettings(videoSettings))
+    }
+
+
     @objc
     func stopStream(_ resolve: (RCTPromiseResolveBlock), reject: (RCTPromiseRejectBlock)){
         RTMPCreator.stopPublish()
@@ -38,7 +53,13 @@ class RTMPModule: NSObject {
     @objc
     func switchCamera(_ resolve: (RCTPromiseResolveBlock), reject: (RCTPromiseRejectBlock)){
         cameraPosition = cameraPosition == .back ? .front : .back
-        RTMPCreator.stream.attachCamera(DeviceUtil.device(withPosition: cameraPosition))
+        
+        RTMPCreator.stream.captureSettings = [
+            .isVideoMirrored: cameraPosition == .back ? false : true
+        ]
+        RTMPCreator.stream.attachCamera(
+            AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: cameraPosition)
+        )
     }
 
     @objc
diff --git a/node_modules/react-native-rtmp-publisher/lib/commonjs/Component.js.map b/node_modules/react-native-rtmp-publisher/lib/commonjs/Component.js.map
index 550b862..a2c27af 100644
--- a/node_modules/react-native-rtmp-publisher/lib/commonjs/Component.js.map
+++ b/node_modules/react-native-rtmp-publisher/lib/commonjs/Component.js.map
@@ -1 +1 @@
-{"version":3,"sources":["Component.tsx"],"names":[],"mappings":";;;;;;;AAAA;;eAkCe,yCACb,eADa,C","sourcesContent":["import {\n  NativeSyntheticEvent,\n  requireNativeComponent,\n  ViewStyle,\n} from 'react-native';\nimport type { StreamState, BluetoothDeviceStatuses } from './types';\n\ntype RTMPData<T> = { data: T };\n\nexport type ConnectionFailedType = NativeSyntheticEvent<RTMPData<string>>;\nexport type ConnectionStartedType = NativeSyntheticEvent<RTMPData<string>>;\nexport type ConnectionSuccessType = NativeSyntheticEvent<RTMPData<null>>;\nexport type DisconnectType = NativeSyntheticEvent<RTMPData<null>>;\nexport type NewBitrateReceivedType = NativeSyntheticEvent<RTMPData<number>>;\nexport type StreamStateChangedType = NativeSyntheticEvent<\n  RTMPData<StreamState>\n>;\nexport type BluetoothDeviceStatusChangedType = NativeSyntheticEvent<\n  RTMPData<BluetoothDeviceStatuses>\n>;\nexport interface NativeRTMPPublisherProps {\n  style?: ViewStyle;\n  streamURL: string;\n  streamName: string;\n  onConnectionFailed?: (e: ConnectionFailedType) => void;\n  onConnectionStarted?: (e: ConnectionStartedType) => void;\n  onConnectionSuccess?: (e: ConnectionSuccessType) => void;\n  onDisconnect?: (e: DisconnectType) => void;\n  onNewBitrateReceived?: (e: NewBitrateReceivedType) => void;\n  onStreamStateChanged?: (e: StreamStateChangedType) => void;\n  onBluetoothDeviceStatusChanged?: (\n    e: BluetoothDeviceStatusChangedType\n  ) => void;\n}\nexport default requireNativeComponent<NativeRTMPPublisherProps>(\n  'RTMPPublisher'\n);\n"]}
\ No newline at end of file
+{"version":3,"sources":["Component.tsx"],"names":[],"mappings":";;;;;;;AAAA;;eAuCe,yCACb,eADa,C","sourcesContent":["import {\n  NativeSyntheticEvent,\n  requireNativeComponent,\n  ViewStyle,\n} from 'react-native';\nimport type {\n  StreamState,\n  BluetoothDeviceStatuses,\n  VideoSettingsType,\n} from './types';\n\ntype RTMPData<T> = { data: T };\n\nexport type ConnectionFailedType = NativeSyntheticEvent<RTMPData<string>>;\nexport type ConnectionStartedType = NativeSyntheticEvent<RTMPData<string>>;\nexport type ConnectionSuccessType = NativeSyntheticEvent<RTMPData<null>>;\nexport type DisconnectType = NativeSyntheticEvent<RTMPData<null>>;\nexport type NewBitrateReceivedType = NativeSyntheticEvent<RTMPData<number>>;\nexport type StreamStateChangedType = NativeSyntheticEvent<\n  RTMPData<StreamState>\n>;\nexport type BluetoothDeviceStatusChangedType = NativeSyntheticEvent<\n  RTMPData<BluetoothDeviceStatuses>\n>;\nexport interface NativeRTMPPublisherProps {\n  style?: ViewStyle;\n  streamURL: string;\n  streamName: string;\n  videoSettings?: VideoSettingsType;\n  onConnectionFailed?: (e: ConnectionFailedType) => void;\n  onConnectionStarted?: (e: ConnectionStartedType) => void;\n  onConnectionSuccess?: (e: ConnectionSuccessType) => void;\n  onDisconnect?: (e: DisconnectType) => void;\n  onNewBitrateReceived?: (e: NewBitrateReceivedType) => void;\n  onStreamStateChanged?: (e: StreamStateChangedType) => void;\n  onBluetoothDeviceStatusChanged?: (\n    e: BluetoothDeviceStatusChangedType\n  ) => void;\n}\nexport default requireNativeComponent<NativeRTMPPublisherProps>(\n  'RTMPPublisher'\n);\n"]}
\ No newline at end of file
diff --git a/node_modules/react-native-rtmp-publisher/lib/commonjs/RTMPPublisher.js b/node_modules/react-native-rtmp-publisher/lib/commonjs/RTMPPublisher.js
index e456074..c016d55 100644
--- a/node_modules/react-native-rtmp-publisher/lib/commonjs/RTMPPublisher.js
+++ b/node_modules/react-native-rtmp-publisher/lib/commonjs/RTMPPublisher.js
@@ -60,6 +60,8 @@ const RTMPPublisher = /*#__PURE__*/(0, _react.forwardRef)((_ref, ref) => {
 
   const setAudioInput = audioInput => RTMPModule.setAudioInput(audioInput);
 
+  const setVideoSettings = async videoSettings => RTMPModule.setVideoSettings(videoSettings);
+
   const handleOnConnectionFailed = e => {
     onConnectionFailed && onConnectionFailed(e.nativeEvent.data);
   };
@@ -102,7 +104,8 @@ const RTMPPublisher = /*#__PURE__*/(0, _react.forwardRef)((_ref, ref) => {
     unmute,
     switchCamera,
     toggleFlash,
-    setAudioInput
+    setAudioInput,
+    setVideoSettings
   }));
   return /*#__PURE__*/_react.default.createElement(_Component.default, _extends({}, props, {
     onDisconnect: handleOnDisconnect,
diff --git a/node_modules/react-native-rtmp-publisher/lib/commonjs/RTMPPublisher.js.map b/node_modules/react-native-rtmp-publisher/lib/commonjs/RTMPPublisher.js.map
index b9e167c..482eee9 100644
--- a/node_modules/react-native-rtmp-publisher/lib/commonjs/RTMPPublisher.js.map
+++ b/node_modules/react-native-rtmp-publisher/lib/commonjs/RTMPPublisher.js.map
@@ -1 +1 @@
-{"version":3,"sources":["RTMPPublisher.tsx"],"names":["RTMPModule","NativeModules","RTMPPublisher","ref","onConnectionFailed","onConnectionStarted","onConnectionSuccess","onDisconnect","onNewBitrateReceived","onStreamStateChanged","onBluetoothDeviceStatusChanged","props","startStream","stopStream","isStreaming","isCameraOnPreview","getPublishURL","hasCongestion","isAudioPrepared","isVideoPrepared","isMuted","mute","unmute","switchCamera","toggleFlash","setAudioInput","audioInput","handleOnConnectionFailed","e","nativeEvent","data","handleOnConnectionStarted","handleOnConnectionSuccess","handleOnDisconnect","handleOnNewBitrateReceived","handleOnStreamStateChanged","handleBluetoothDeviceStatusChanged"],"mappings":"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","sourcesContent":["import React, { forwardRef, useImperativeHandle } from 'react';\nimport { NativeModules, ViewStyle } from 'react-native';\nimport PublisherComponent, {\n  DisconnectType,\n  ConnectionFailedType,\n  ConnectionStartedType,\n  ConnectionSuccessType,\n  NewBitrateReceivedType,\n  StreamStateChangedType,\n  BluetoothDeviceStatusChangedType,\n} from './Component';\nimport type {\n  RTMPPublisherRefProps,\n  StreamState,\n  BluetoothDeviceStatuses,\n  AudioInputType,\n} from './types';\n\nconst RTMPModule = NativeModules.RTMPPublisher;\nexport interface RTMPPublisherProps {\n  style?: ViewStyle;\n  streamURL: string;\n  streamName: string;\n  /**\n   * Callback for connection fails on RTMP server\n   */\n  onConnectionFailed?: (data: string) => void;\n  /**\n   * Callback for starting connection to RTMP server\n   */\n  onConnectionStarted?: (data: string) => void;\n  /**\n   * Callback for connection successfully to RTMP server\n   */\n  onConnectionSuccess?: (data: null) => void;\n  /**\n   * Callback for disconnect successfully to RTMP server\n   */\n  onDisconnect?: (data: null) => void;\n  /**\n   * Callback for receiving new bitrate value about stream\n   */\n  onNewBitrateReceived?: (data: number) => void;\n  /**\n   * Alternatively callback for changing stream state\n   * Returns parameter StreamState type\n   */\n  onStreamStateChanged?: (data: StreamState) => void;\n  /**\n   * Callback for bluetooth device connection changes\n   */\n  onBluetoothDeviceStatusChanged?: (data: BluetoothDeviceStatuses) => void;\n}\n\nconst RTMPPublisher = forwardRef<RTMPPublisherRefProps, RTMPPublisherProps>(\n  (\n    {\n      onConnectionFailed,\n      onConnectionStarted,\n      onConnectionSuccess,\n      onDisconnect,\n      onNewBitrateReceived,\n      onStreamStateChanged,\n      onBluetoothDeviceStatusChanged,\n      ...props\n    },\n    ref\n  ) => {\n    const startStream = async () => await RTMPModule.startStream();\n\n    const stopStream = async () => await RTMPModule.stopStream();\n\n    const isStreaming = async () => RTMPModule.isStreaming();\n\n    const isCameraOnPreview = async () => RTMPModule.isCameraOnPreview();\n\n    const getPublishURL = async () => RTMPModule.getPublishURL();\n\n    const hasCongestion = async () => RTMPModule.hasCongestion();\n\n    const isAudioPrepared = async () => RTMPModule.isAudioPrepared();\n\n    const isVideoPrepared = async () => RTMPModule.isVideoPrepared();\n\n    const isMuted = async () => RTMPModule.isMuted();\n\n    const mute = () => RTMPModule.mute();\n\n    const unmute = () => RTMPModule.unmute();\n\n    const switchCamera = () => RTMPModule.switchCamera();\n\n    const toggleFlash = () => RTMPModule.toggleFlash();\n\n    const setAudioInput = (audioInput: AudioInputType) =>\n      RTMPModule.setAudioInput(audioInput);\n\n    const handleOnConnectionFailed = (e: ConnectionFailedType) => {\n      onConnectionFailed && onConnectionFailed(e.nativeEvent.data);\n    };\n\n    const handleOnConnectionStarted = (e: ConnectionStartedType) => {\n      onConnectionStarted && onConnectionStarted(e.nativeEvent.data);\n    };\n\n    const handleOnConnectionSuccess = (e: ConnectionSuccessType) => {\n      onConnectionSuccess && onConnectionSuccess(e.nativeEvent.data);\n    };\n\n    const handleOnDisconnect = (e: DisconnectType) => {\n      onDisconnect && onDisconnect(e.nativeEvent.data);\n    };\n\n    const handleOnNewBitrateReceived = (e: NewBitrateReceivedType) => {\n      onNewBitrateReceived && onNewBitrateReceived(e.nativeEvent.data);\n    };\n\n    const handleOnStreamStateChanged = (e: StreamStateChangedType) => {\n      onStreamStateChanged && onStreamStateChanged(e.nativeEvent.data);\n    };\n\n    const handleBluetoothDeviceStatusChanged = (\n      e: BluetoothDeviceStatusChangedType\n    ) => {\n      onBluetoothDeviceStatusChanged &&\n        onBluetoothDeviceStatusChanged(e.nativeEvent.data);\n    };\n\n    useImperativeHandle(ref, () => ({\n      startStream,\n      stopStream,\n      isStreaming,\n      isCameraOnPreview,\n      getPublishURL,\n      hasCongestion,\n      isAudioPrepared,\n      isVideoPrepared,\n      isMuted,\n      mute,\n      unmute,\n      switchCamera,\n      toggleFlash,\n      setAudioInput,\n    }));\n\n    return (\n      <PublisherComponent\n        {...props}\n        onDisconnect={handleOnDisconnect}\n        onConnectionFailed={handleOnConnectionFailed}\n        onConnectionStarted={handleOnConnectionStarted}\n        onConnectionSuccess={handleOnConnectionSuccess}\n        onNewBitrateReceived={handleOnNewBitrateReceived}\n        onStreamStateChanged={handleOnStreamStateChanged}\n        onBluetoothDeviceStatusChanged={handleBluetoothDeviceStatusChanged}\n      />\n    );\n  }\n);\n\nexport default RTMPPublisher;\n"]}
\ No newline at end of file
+{"version":3,"sources":["RTMPPublisher.tsx"],"names":["RTMPModule","NativeModules","RTMPPublisher","ref","onConnectionFailed","onConnectionStarted","onConnectionSuccess","onDisconnect","onNewBitrateReceived","onStreamStateChanged","onBluetoothDeviceStatusChanged","props","startStream","stopStream","isStreaming","isCameraOnPreview","getPublishURL","hasCongestion","isAudioPrepared","isVideoPrepared","isMuted","mute","unmute","switchCamera","toggleFlash","setAudioInput","audioInput","setVideoSettings","videoSettings","handleOnConnectionFailed","e","nativeEvent","data","handleOnConnectionStarted","handleOnConnectionSuccess","handleOnDisconnect","handleOnNewBitrateReceived","handleOnStreamStateChanged","handleBluetoothDeviceStatusChanged"],"mappings":"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","sourcesContent":["import React, { forwardRef, useImperativeHandle } from 'react';\nimport { NativeModules, type ViewStyle } from 'react-native';\nimport PublisherComponent, {\n  type DisconnectType,\n  type ConnectionFailedType,\n  type ConnectionStartedType,\n  type ConnectionSuccessType,\n  type NewBitrateReceivedType,\n  type StreamStateChangedType,\n  type BluetoothDeviceStatusChangedType,\n} from './Component';\nimport type {\n  RTMPPublisherRefProps,\n  StreamState,\n  BluetoothDeviceStatuses,\n  AudioInputType,\n  VideoSettingsType,\n} from './types';\n\nconst RTMPModule = NativeModules.RTMPPublisher;\nexport interface RTMPPublisherProps {\n  testID?: string;\n  style?: ViewStyle;\n  streamURL: string;\n  streamName: string;\n  /**\n   * Video settings for video\n   */\n  videoSettings?: VideoSettingsType;\n  /**\n   * Callback for connection fails on RTMP server\n   */\n  onConnectionFailed?: (data: string) => void;\n  /**\n   * Callback for starting connection to RTMP server\n   */\n  onConnectionStarted?: (data: string) => void;\n  /**\n   * Callback for connection successfully to RTMP server\n   */\n  onConnectionSuccess?: (data: null) => void;\n  /**\n   * Callback for disconnect successfully to RTMP server\n   */\n  onDisconnect?: (data: null) => void;\n  /**\n   * Callback for receiving new bitrate value about stream\n   */\n  onNewBitrateReceived?: (data: number) => void;\n  /**\n   * Alternatively callback for changing stream state\n   * Returns parameter StreamState type\n   */\n  onStreamStateChanged?: (data: StreamState) => void;\n  /**\n   * Callback for bluetooth device connection changes\n   */\n  onBluetoothDeviceStatusChanged?: (data: BluetoothDeviceStatuses) => void;\n}\n\nconst RTMPPublisher = forwardRef<RTMPPublisherRefProps, RTMPPublisherProps>(\n  (\n    {\n      onConnectionFailed,\n      onConnectionStarted,\n      onConnectionSuccess,\n      onDisconnect,\n      onNewBitrateReceived,\n      onStreamStateChanged,\n      onBluetoothDeviceStatusChanged,\n      ...props\n    },\n    ref\n  ) => {\n    const startStream = async () => await RTMPModule.startStream();\n\n    const stopStream = async () => await RTMPModule.stopStream();\n\n    const isStreaming = async () => RTMPModule.isStreaming();\n\n    const isCameraOnPreview = async () => RTMPModule.isCameraOnPreview();\n\n    const getPublishURL = async () => RTMPModule.getPublishURL();\n\n    const hasCongestion = async () => RTMPModule.hasCongestion();\n\n    const isAudioPrepared = async () => RTMPModule.isAudioPrepared();\n\n    const isVideoPrepared = async () => RTMPModule.isVideoPrepared();\n\n    const isMuted = async () => RTMPModule.isMuted();\n\n    const mute = () => RTMPModule.mute();\n\n    const unmute = () => RTMPModule.unmute();\n\n    const switchCamera = () => RTMPModule.switchCamera();\n\n    const toggleFlash = () => RTMPModule.toggleFlash();\n\n    const setAudioInput = (audioInput: AudioInputType) =>\n      RTMPModule.setAudioInput(audioInput);\n\n    const setVideoSettings = async (videoSettings: VideoSettingsType) =>\n      RTMPModule.setVideoSettings(videoSettings);\n\n    const handleOnConnectionFailed = (e: ConnectionFailedType) => {\n      onConnectionFailed && onConnectionFailed(e.nativeEvent.data);\n    };\n\n    const handleOnConnectionStarted = (e: ConnectionStartedType) => {\n      onConnectionStarted && onConnectionStarted(e.nativeEvent.data);\n    };\n\n    const handleOnConnectionSuccess = (e: ConnectionSuccessType) => {\n      onConnectionSuccess && onConnectionSuccess(e.nativeEvent.data);\n    };\n\n    const handleOnDisconnect = (e: DisconnectType) => {\n      onDisconnect && onDisconnect(e.nativeEvent.data);\n    };\n\n    const handleOnNewBitrateReceived = (e: NewBitrateReceivedType) => {\n      onNewBitrateReceived && onNewBitrateReceived(e.nativeEvent.data);\n    };\n\n    const handleOnStreamStateChanged = (e: StreamStateChangedType) => {\n      onStreamStateChanged && onStreamStateChanged(e.nativeEvent.data);\n    };\n\n    const handleBluetoothDeviceStatusChanged = (\n      e: BluetoothDeviceStatusChangedType\n    ) => {\n      onBluetoothDeviceStatusChanged &&\n        onBluetoothDeviceStatusChanged(e.nativeEvent.data);\n    };\n\n    useImperativeHandle(ref, () => ({\n      startStream,\n      stopStream,\n      isStreaming,\n      isCameraOnPreview,\n      getPublishURL,\n      hasCongestion,\n      isAudioPrepared,\n      isVideoPrepared,\n      isMuted,\n      mute,\n      unmute,\n      switchCamera,\n      toggleFlash,\n      setAudioInput,\n      setVideoSettings,\n    }));\n\n    return (\n      <PublisherComponent\n        {...props}\n        onDisconnect={handleOnDisconnect}\n        onConnectionFailed={handleOnConnectionFailed}\n        onConnectionStarted={handleOnConnectionStarted}\n        onConnectionSuccess={handleOnConnectionSuccess}\n        onNewBitrateReceived={handleOnNewBitrateReceived}\n        onStreamStateChanged={handleOnStreamStateChanged}\n        onBluetoothDeviceStatusChanged={handleBluetoothDeviceStatusChanged}\n      />\n    );\n  }\n);\n\nexport default RTMPPublisher;\n"]}
\ No newline at end of file
diff --git a/node_modules/react-native-rtmp-publisher/lib/commonjs/types.js b/node_modules/react-native-rtmp-publisher/lib/commonjs/types.js
index 3e4c3ba..cac7253 100644
--- a/node_modules/react-native-rtmp-publisher/lib/commonjs/types.js
+++ b/node_modules/react-native-rtmp-publisher/lib/commonjs/types.js
@@ -11,6 +11,7 @@ exports.StreamState = StreamState;
   StreamState["CONNECTING"] = "CONNECTING";
   StreamState["CONNECTED"] = "CONNECTED";
   StreamState["DISCONNECTED"] = "DISCONNECTED";
+  StreamState["CLOSED"] = "CLOSED";
   StreamState["FAILED"] = "FAILED";
 })(StreamState || (exports.StreamState = StreamState = {}));
 
diff --git a/node_modules/react-native-rtmp-publisher/lib/commonjs/types.js.map b/node_modules/react-native-rtmp-publisher/lib/commonjs/types.js.map
index 5c5fd9e..d70feba 100644
--- a/node_modules/react-native-rtmp-publisher/lib/commonjs/types.js.map
+++ b/node_modules/react-native-rtmp-publisher/lib/commonjs/types.js.map
@@ -1 +1 @@
-{"version":3,"sources":["types.ts"],"names":["StreamState","BluetoothDeviceStatuses","AudioInputType"],"mappings":";;;;;;IA8EYA,W;;;WAAAA,W;AAAAA,EAAAA,W;AAAAA,EAAAA,W;AAAAA,EAAAA,W;AAAAA,EAAAA,W;GAAAA,W,2BAAAA,W;;IAMAC,uB;;;WAAAA,uB;AAAAA,EAAAA,uB;AAAAA,EAAAA,uB;AAAAA,EAAAA,uB;GAAAA,uB,uCAAAA,uB;;IAMAC,c;;;WAAAA,c;AAAAA,EAAAA,c,CAAAA,c;AAAAA,EAAAA,c,CAAAA,c;AAAAA,EAAAA,c,CAAAA,c;GAAAA,c,8BAAAA,c","sourcesContent":["import type { ViewStyle } from 'react-native';\n\nexport interface RTMPPublisherRefProps {\n  /**\n   * Starts stream operation\n   */\n  startStream: () => Promise<void>;\n  /**\n   * Stops stream operation\n   */\n  stopStream: () => Promise<void>;\n  /**\n   * Checks stream status\n   */\n  isStreaming: () => Promise<boolean>;\n  /**\n   * Checks if camera on mount\n   */\n  isCameraOnPreview: () => Promise<boolean>;\n  /**\n   * Gets settled publish url\n   */\n  getPublishURL: () => Promise<string>;\n  /**\n   * Checks congestion status\n   */\n  hasCongestion: () => Promise<boolean>;\n  /**\n   * Checks audio status\n   */\n  isAudioPrepared: () => Promise<boolean>;\n  /**\n   * Checks video status\n   */\n  isVideoPrepared: () => Promise<boolean>;\n  /**\n   * Checks if mic closed\n   */\n  isMuted: () => Promise<boolean>;\n  /**\n   * Mutes the mic\n   */\n  mute: () => Promise<void>;\n  /**\n   * Unmutes the mic\n   */\n  unmute: () => Promise<void>;\n  /**\n   * Switches the camera\n   */\n  switchCamera: () => Promise<void>;\n  /**\n   * Toggles the flash\n   */\n  toggleFlash: () => Promise<void>;\n  /**\n   * Sets the audio input (microphone type)\n   */\n  setAudioInput: (audioInput: AudioInputType) => Promise<void>;\n}\n\nexport interface RTMPPublisherProps {\n  style?: ViewStyle;\n  streamURL: string;\n  streamName: string;\n  onConnectionFailed?: (e: null) => void;\n  onConnectionStarted?: (e: null) => void;\n  onConnectionSuccess?: (e: null) => void;\n  onDisconnect?: (e: null) => void;\n  onNewBitrateReceived?: (e: number) => void;\n  onStreamStateChanged?: (e: StreamState) => void;\n}\nexport type StreamStatus =\n  | 'CONNECTING'\n  | 'CONNECTED'\n  | 'DISCONNECTED'\n  | 'FAILED';\n\nexport enum StreamState {\n  CONNECTING = 'CONNECTING',\n  CONNECTED = 'CONNECTED',\n  DISCONNECTED = 'DISCONNECTED',\n  FAILED = 'FAILED',\n}\nexport enum BluetoothDeviceStatuses {\n  CONNECTING = 'CONNECTING',\n  CONNECTED = 'CONNECTED',\n  DISCONNECTED = 'DISCONNECTED',\n}\n\nexport enum AudioInputType {\n  BLUETOOTH_HEADSET = 0,\n  SPEAKER = 1,\n  WIRED_HEADSET = 2,\n}\n"]}
\ No newline at end of file
+{"version":3,"sources":["types.ts"],"names":["StreamState","BluetoothDeviceStatuses","AudioInputType"],"mappings":";;;;;;IAoFYA,W;;;WAAAA,W;AAAAA,EAAAA,W;AAAAA,EAAAA,W;AAAAA,EAAAA,W;AAAAA,EAAAA,W;AAAAA,EAAAA,W;GAAAA,W,2BAAAA,W;;IAOAC,uB;;;WAAAA,uB;AAAAA,EAAAA,uB;AAAAA,EAAAA,uB;AAAAA,EAAAA,uB;GAAAA,uB,uCAAAA,uB;;IAMAC,c;;;WAAAA,c;AAAAA,EAAAA,c,CAAAA,c;AAAAA,EAAAA,c,CAAAA,c;AAAAA,EAAAA,c,CAAAA,c;GAAAA,c,8BAAAA,c","sourcesContent":["import type { ViewStyle } from 'react-native';\n\nexport interface RTMPPublisherRefProps {\n  /**\n   * Starts stream operation\n   */\n  startStream: () => Promise<void>;\n  /**\n   * Stops stream operation\n   */\n  stopStream: () => Promise<void>;\n  /**\n   * Checks stream status\n   */\n  isStreaming: () => Promise<boolean>;\n  /**\n   * Checks if camera on mount\n   */\n  isCameraOnPreview: () => Promise<boolean>;\n  /**\n   * Gets settled publish url\n   */\n  getPublishURL: () => Promise<string>;\n  /**\n   * Checks congestion status\n   */\n  hasCongestion: () => Promise<boolean>;\n  /**\n   * Checks audio status\n   */\n  isAudioPrepared: () => Promise<boolean>;\n  /**\n   * Checks video status\n   */\n  isVideoPrepared: () => Promise<boolean>;\n  /**\n   * Checks if mic closed\n   */\n  isMuted: () => Promise<boolean>;\n  /**\n   * Mutes the mic\n   */\n  mute: () => Promise<void>;\n  /**\n   * Unmutes the mic\n   */\n  unmute: () => Promise<void>;\n  /**\n   * Switches the camera\n   */\n  switchCamera: () => Promise<void>;\n  /**\n   * Toggles the flash\n   */\n  toggleFlash: () => Promise<void>;\n  /**\n   * Sets the audio input (microphone type)\n   */\n  setAudioInput: (audioInput: AudioInputType) => Promise<void>;\n  /**\n   * Sets video settings quality\n   */\n  setVideoSettings: (audioInput: VideoSettingsType) => Promise<void>;\n}\n\nexport interface RTMPPublisherProps {\n  style?: ViewStyle;\n  streamURL: string;\n  streamName: string;\n  videoSettings?: VideoSettingsType;\n  onConnectionFailed?: (e: null) => void;\n  onConnectionStarted?: (e: null) => void;\n  onConnectionSuccess?: (e: null) => void;\n  onDisconnect?: (e: null) => void;\n  onNewBitrateReceived?: (e: number) => void;\n  onStreamStateChanged?: (e: StreamState) => void;\n}\nexport type StreamStatus =\n  | 'CONNECTING'\n  | 'CONNECTED'\n  | 'DISCONNECTED'\n  | 'CLOSED'\n  | 'FAILED';\n\nexport enum StreamState {\n  CONNECTING = 'CONNECTING',\n  CONNECTED = 'CONNECTED',\n  DISCONNECTED = 'DISCONNECTED',\n  CLOSED = 'CLOSED',\n  FAILED = 'FAILED',\n}\nexport enum BluetoothDeviceStatuses {\n  CONNECTING = 'CONNECTING',\n  CONNECTED = 'CONNECTED',\n  DISCONNECTED = 'DISCONNECTED',\n}\n\nexport enum AudioInputType {\n  BLUETOOTH_HEADSET = 0,\n  SPEAKER = 1,\n  WIRED_HEADSET = 2,\n}\n\nexport interface VideoSettingsType {\n  width: number;\n  height: number;\n  bitrate: number;\n}\n"]}
\ No newline at end of file
diff --git a/node_modules/react-native-rtmp-publisher/lib/module/Component.js.map b/node_modules/react-native-rtmp-publisher/lib/module/Component.js.map
index 2a24090..a6dcac6 100644
--- a/node_modules/react-native-rtmp-publisher/lib/module/Component.js.map
+++ b/node_modules/react-native-rtmp-publisher/lib/module/Component.js.map
@@ -1 +1 @@
-{"version":3,"sources":["Component.tsx"],"names":["requireNativeComponent"],"mappings":"AAAA,SAEEA,sBAFF,QAIO,cAJP;AAkCA,eAAeA,sBAAsB,CACnC,eADmC,CAArC","sourcesContent":["import {\n  NativeSyntheticEvent,\n  requireNativeComponent,\n  ViewStyle,\n} from 'react-native';\nimport type { StreamState, BluetoothDeviceStatuses } from './types';\n\ntype RTMPData<T> = { data: T };\n\nexport type ConnectionFailedType = NativeSyntheticEvent<RTMPData<string>>;\nexport type ConnectionStartedType = NativeSyntheticEvent<RTMPData<string>>;\nexport type ConnectionSuccessType = NativeSyntheticEvent<RTMPData<null>>;\nexport type DisconnectType = NativeSyntheticEvent<RTMPData<null>>;\nexport type NewBitrateReceivedType = NativeSyntheticEvent<RTMPData<number>>;\nexport type StreamStateChangedType = NativeSyntheticEvent<\n  RTMPData<StreamState>\n>;\nexport type BluetoothDeviceStatusChangedType = NativeSyntheticEvent<\n  RTMPData<BluetoothDeviceStatuses>\n>;\nexport interface NativeRTMPPublisherProps {\n  style?: ViewStyle;\n  streamURL: string;\n  streamName: string;\n  onConnectionFailed?: (e: ConnectionFailedType) => void;\n  onConnectionStarted?: (e: ConnectionStartedType) => void;\n  onConnectionSuccess?: (e: ConnectionSuccessType) => void;\n  onDisconnect?: (e: DisconnectType) => void;\n  onNewBitrateReceived?: (e: NewBitrateReceivedType) => void;\n  onStreamStateChanged?: (e: StreamStateChangedType) => void;\n  onBluetoothDeviceStatusChanged?: (\n    e: BluetoothDeviceStatusChangedType\n  ) => void;\n}\nexport default requireNativeComponent<NativeRTMPPublisherProps>(\n  'RTMPPublisher'\n);\n"]}
\ No newline at end of file
+{"version":3,"sources":["Component.tsx"],"names":["requireNativeComponent"],"mappings":"AAAA,SAEEA,sBAFF,QAIO,cAJP;AAuCA,eAAeA,sBAAsB,CACnC,eADmC,CAArC","sourcesContent":["import {\n  NativeSyntheticEvent,\n  requireNativeComponent,\n  ViewStyle,\n} from 'react-native';\nimport type {\n  StreamState,\n  BluetoothDeviceStatuses,\n  VideoSettingsType,\n} from './types';\n\ntype RTMPData<T> = { data: T };\n\nexport type ConnectionFailedType = NativeSyntheticEvent<RTMPData<string>>;\nexport type ConnectionStartedType = NativeSyntheticEvent<RTMPData<string>>;\nexport type ConnectionSuccessType = NativeSyntheticEvent<RTMPData<null>>;\nexport type DisconnectType = NativeSyntheticEvent<RTMPData<null>>;\nexport type NewBitrateReceivedType = NativeSyntheticEvent<RTMPData<number>>;\nexport type StreamStateChangedType = NativeSyntheticEvent<\n  RTMPData<StreamState>\n>;\nexport type BluetoothDeviceStatusChangedType = NativeSyntheticEvent<\n  RTMPData<BluetoothDeviceStatuses>\n>;\nexport interface NativeRTMPPublisherProps {\n  style?: ViewStyle;\n  streamURL: string;\n  streamName: string;\n  videoSettings?: VideoSettingsType;\n  onConnectionFailed?: (e: ConnectionFailedType) => void;\n  onConnectionStarted?: (e: ConnectionStartedType) => void;\n  onConnectionSuccess?: (e: ConnectionSuccessType) => void;\n  onDisconnect?: (e: DisconnectType) => void;\n  onNewBitrateReceived?: (e: NewBitrateReceivedType) => void;\n  onStreamStateChanged?: (e: StreamStateChangedType) => void;\n  onBluetoothDeviceStatusChanged?: (\n    e: BluetoothDeviceStatusChangedType\n  ) => void;\n}\nexport default requireNativeComponent<NativeRTMPPublisherProps>(\n  'RTMPPublisher'\n);\n"]}
\ No newline at end of file
diff --git a/node_modules/react-native-rtmp-publisher/lib/module/RTMPPublisher.js b/node_modules/react-native-rtmp-publisher/lib/module/RTMPPublisher.js
index d834c39..30a9c00 100644
--- a/node_modules/react-native-rtmp-publisher/lib/module/RTMPPublisher.js
+++ b/node_modules/react-native-rtmp-publisher/lib/module/RTMPPublisher.js
@@ -44,6 +44,8 @@ const RTMPPublisher = /*#__PURE__*/forwardRef((_ref, ref) => {
 
   const setAudioInput = audioInput => RTMPModule.setAudioInput(audioInput);
 
+  const setVideoSettings = async videoSettings => RTMPModule.setVideoSettings(videoSettings);
+
   const handleOnConnectionFailed = e => {
     onConnectionFailed && onConnectionFailed(e.nativeEvent.data);
   };
@@ -86,7 +88,8 @@ const RTMPPublisher = /*#__PURE__*/forwardRef((_ref, ref) => {
     unmute,
     switchCamera,
     toggleFlash,
-    setAudioInput
+    setAudioInput,
+    setVideoSettings
   }));
   return /*#__PURE__*/React.createElement(PublisherComponent, _extends({}, props, {
     onDisconnect: handleOnDisconnect,
diff --git a/node_modules/react-native-rtmp-publisher/lib/module/RTMPPublisher.js.map b/node_modules/react-native-rtmp-publisher/lib/module/RTMPPublisher.js.map
index 2233e3b..78c5685 100644
--- a/node_modules/react-native-rtmp-publisher/lib/module/RTMPPublisher.js.map
+++ b/node_modules/react-native-rtmp-publisher/lib/module/RTMPPublisher.js.map
@@ -1 +1 @@
-{"version":3,"sources":["RTMPPublisher.tsx"],"names":["React","forwardRef","useImperativeHandle","NativeModules","PublisherComponent","RTMPModule","RTMPPublisher","ref","onConnectionFailed","onConnectionStarted","onConnectionSuccess","onDisconnect","onNewBitrateReceived","onStreamStateChanged","onBluetoothDeviceStatusChanged","props","startStream","stopStream","isStreaming","isCameraOnPreview","getPublishURL","hasCongestion","isAudioPrepared","isVideoPrepared","isMuted","mute","unmute","switchCamera","toggleFlash","setAudioInput","audioInput","handleOnConnectionFailed","e","nativeEvent","data","handleOnConnectionStarted","handleOnConnectionSuccess","handleOnDisconnect","handleOnNewBitrateReceived","handleOnStreamStateChanged","handleBluetoothDeviceStatusChanged"],"mappings":"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","sourcesContent":["import React, { forwardRef, useImperativeHandle } from 'react';\nimport { NativeModules, ViewStyle } from 'react-native';\nimport PublisherComponent, {\n  DisconnectType,\n  ConnectionFailedType,\n  ConnectionStartedType,\n  ConnectionSuccessType,\n  NewBitrateReceivedType,\n  StreamStateChangedType,\n  BluetoothDeviceStatusChangedType,\n} from './Component';\nimport type {\n  RTMPPublisherRefProps,\n  StreamState,\n  BluetoothDeviceStatuses,\n  AudioInputType,\n} from './types';\n\nconst RTMPModule = NativeModules.RTMPPublisher;\nexport interface RTMPPublisherProps {\n  style?: ViewStyle;\n  streamURL: string;\n  streamName: string;\n  /**\n   * Callback for connection fails on RTMP server\n   */\n  onConnectionFailed?: (data: string) => void;\n  /**\n   * Callback for starting connection to RTMP server\n   */\n  onConnectionStarted?: (data: string) => void;\n  /**\n   * Callback for connection successfully to RTMP server\n   */\n  onConnectionSuccess?: (data: null) => void;\n  /**\n   * Callback for disconnect successfully to RTMP server\n   */\n  onDisconnect?: (data: null) => void;\n  /**\n   * Callback for receiving new bitrate value about stream\n   */\n  onNewBitrateReceived?: (data: number) => void;\n  /**\n   * Alternatively callback for changing stream state\n   * Returns parameter StreamState type\n   */\n  onStreamStateChanged?: (data: StreamState) => void;\n  /**\n   * Callback for bluetooth device connection changes\n   */\n  onBluetoothDeviceStatusChanged?: (data: BluetoothDeviceStatuses) => void;\n}\n\nconst RTMPPublisher = forwardRef<RTMPPublisherRefProps, RTMPPublisherProps>(\n  (\n    {\n      onConnectionFailed,\n      onConnectionStarted,\n      onConnectionSuccess,\n      onDisconnect,\n      onNewBitrateReceived,\n      onStreamStateChanged,\n      onBluetoothDeviceStatusChanged,\n      ...props\n    },\n    ref\n  ) => {\n    const startStream = async () => await RTMPModule.startStream();\n\n    const stopStream = async () => await RTMPModule.stopStream();\n\n    const isStreaming = async () => RTMPModule.isStreaming();\n\n    const isCameraOnPreview = async () => RTMPModule.isCameraOnPreview();\n\n    const getPublishURL = async () => RTMPModule.getPublishURL();\n\n    const hasCongestion = async () => RTMPModule.hasCongestion();\n\n    const isAudioPrepared = async () => RTMPModule.isAudioPrepared();\n\n    const isVideoPrepared = async () => RTMPModule.isVideoPrepared();\n\n    const isMuted = async () => RTMPModule.isMuted();\n\n    const mute = () => RTMPModule.mute();\n\n    const unmute = () => RTMPModule.unmute();\n\n    const switchCamera = () => RTMPModule.switchCamera();\n\n    const toggleFlash = () => RTMPModule.toggleFlash();\n\n    const setAudioInput = (audioInput: AudioInputType) =>\n      RTMPModule.setAudioInput(audioInput);\n\n    const handleOnConnectionFailed = (e: ConnectionFailedType) => {\n      onConnectionFailed && onConnectionFailed(e.nativeEvent.data);\n    };\n\n    const handleOnConnectionStarted = (e: ConnectionStartedType) => {\n      onConnectionStarted && onConnectionStarted(e.nativeEvent.data);\n    };\n\n    const handleOnConnectionSuccess = (e: ConnectionSuccessType) => {\n      onConnectionSuccess && onConnectionSuccess(e.nativeEvent.data);\n    };\n\n    const handleOnDisconnect = (e: DisconnectType) => {\n      onDisconnect && onDisconnect(e.nativeEvent.data);\n    };\n\n    const handleOnNewBitrateReceived = (e: NewBitrateReceivedType) => {\n      onNewBitrateReceived && onNewBitrateReceived(e.nativeEvent.data);\n    };\n\n    const handleOnStreamStateChanged = (e: StreamStateChangedType) => {\n      onStreamStateChanged && onStreamStateChanged(e.nativeEvent.data);\n    };\n\n    const handleBluetoothDeviceStatusChanged = (\n      e: BluetoothDeviceStatusChangedType\n    ) => {\n      onBluetoothDeviceStatusChanged &&\n        onBluetoothDeviceStatusChanged(e.nativeEvent.data);\n    };\n\n    useImperativeHandle(ref, () => ({\n      startStream,\n      stopStream,\n      isStreaming,\n      isCameraOnPreview,\n      getPublishURL,\n      hasCongestion,\n      isAudioPrepared,\n      isVideoPrepared,\n      isMuted,\n      mute,\n      unmute,\n      switchCamera,\n      toggleFlash,\n      setAudioInput,\n    }));\n\n    return (\n      <PublisherComponent\n        {...props}\n        onDisconnect={handleOnDisconnect}\n        onConnectionFailed={handleOnConnectionFailed}\n        onConnectionStarted={handleOnConnectionStarted}\n        onConnectionSuccess={handleOnConnectionSuccess}\n        onNewBitrateReceived={handleOnNewBitrateReceived}\n        onStreamStateChanged={handleOnStreamStateChanged}\n        onBluetoothDeviceStatusChanged={handleBluetoothDeviceStatusChanged}\n      />\n    );\n  }\n);\n\nexport default RTMPPublisher;\n"]}
\ No newline at end of file
+{"version":3,"sources":["RTMPPublisher.tsx"],"names":["React","forwardRef","useImperativeHandle","NativeModules","PublisherComponent","RTMPModule","RTMPPublisher","ref","onConnectionFailed","onConnectionStarted","onConnectionSuccess","onDisconnect","onNewBitrateReceived","onStreamStateChanged","onBluetoothDeviceStatusChanged","props","startStream","stopStream","isStreaming","isCameraOnPreview","getPublishURL","hasCongestion","isAudioPrepared","isVideoPrepared","isMuted","mute","unmute","switchCamera","toggleFlash","setAudioInput","audioInput","setVideoSettings","videoSettings","handleOnConnectionFailed","e","nativeEvent","data","handleOnConnectionStarted","handleOnConnectionSuccess","handleOnDisconnect","handleOnNewBitrateReceived","handleOnStreamStateChanged","handleBluetoothDeviceStatusChanged"],"mappings":"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","sourcesContent":["import React, { forwardRef, useImperativeHandle } from 'react';\nimport { NativeModules, type ViewStyle } from 'react-native';\nimport PublisherComponent, {\n  type DisconnectType,\n  type ConnectionFailedType,\n  type ConnectionStartedType,\n  type ConnectionSuccessType,\n  type NewBitrateReceivedType,\n  type StreamStateChangedType,\n  type BluetoothDeviceStatusChangedType,\n} from './Component';\nimport type {\n  RTMPPublisherRefProps,\n  StreamState,\n  BluetoothDeviceStatuses,\n  AudioInputType,\n  VideoSettingsType,\n} from './types';\n\nconst RTMPModule = NativeModules.RTMPPublisher;\nexport interface RTMPPublisherProps {\n  testID?: string;\n  style?: ViewStyle;\n  streamURL: string;\n  streamName: string;\n  /**\n   * Video settings for video\n   */\n  videoSettings?: VideoSettingsType;\n  /**\n   * Callback for connection fails on RTMP server\n   */\n  onConnectionFailed?: (data: string) => void;\n  /**\n   * Callback for starting connection to RTMP server\n   */\n  onConnectionStarted?: (data: string) => void;\n  /**\n   * Callback for connection successfully to RTMP server\n   */\n  onConnectionSuccess?: (data: null) => void;\n  /**\n   * Callback for disconnect successfully to RTMP server\n   */\n  onDisconnect?: (data: null) => void;\n  /**\n   * Callback for receiving new bitrate value about stream\n   */\n  onNewBitrateReceived?: (data: number) => void;\n  /**\n   * Alternatively callback for changing stream state\n   * Returns parameter StreamState type\n   */\n  onStreamStateChanged?: (data: StreamState) => void;\n  /**\n   * Callback for bluetooth device connection changes\n   */\n  onBluetoothDeviceStatusChanged?: (data: BluetoothDeviceStatuses) => void;\n}\n\nconst RTMPPublisher = forwardRef<RTMPPublisherRefProps, RTMPPublisherProps>(\n  (\n    {\n      onConnectionFailed,\n      onConnectionStarted,\n      onConnectionSuccess,\n      onDisconnect,\n      onNewBitrateReceived,\n      onStreamStateChanged,\n      onBluetoothDeviceStatusChanged,\n      ...props\n    },\n    ref\n  ) => {\n    const startStream = async () => await RTMPModule.startStream();\n\n    const stopStream = async () => await RTMPModule.stopStream();\n\n    const isStreaming = async () => RTMPModule.isStreaming();\n\n    const isCameraOnPreview = async () => RTMPModule.isCameraOnPreview();\n\n    const getPublishURL = async () => RTMPModule.getPublishURL();\n\n    const hasCongestion = async () => RTMPModule.hasCongestion();\n\n    const isAudioPrepared = async () => RTMPModule.isAudioPrepared();\n\n    const isVideoPrepared = async () => RTMPModule.isVideoPrepared();\n\n    const isMuted = async () => RTMPModule.isMuted();\n\n    const mute = () => RTMPModule.mute();\n\n    const unmute = () => RTMPModule.unmute();\n\n    const switchCamera = () => RTMPModule.switchCamera();\n\n    const toggleFlash = () => RTMPModule.toggleFlash();\n\n    const setAudioInput = (audioInput: AudioInputType) =>\n      RTMPModule.setAudioInput(audioInput);\n\n    const setVideoSettings = async (videoSettings: VideoSettingsType) =>\n      RTMPModule.setVideoSettings(videoSettings);\n\n    const handleOnConnectionFailed = (e: ConnectionFailedType) => {\n      onConnectionFailed && onConnectionFailed(e.nativeEvent.data);\n    };\n\n    const handleOnConnectionStarted = (e: ConnectionStartedType) => {\n      onConnectionStarted && onConnectionStarted(e.nativeEvent.data);\n    };\n\n    const handleOnConnectionSuccess = (e: ConnectionSuccessType) => {\n      onConnectionSuccess && onConnectionSuccess(e.nativeEvent.data);\n    };\n\n    const handleOnDisconnect = (e: DisconnectType) => {\n      onDisconnect && onDisconnect(e.nativeEvent.data);\n    };\n\n    const handleOnNewBitrateReceived = (e: NewBitrateReceivedType) => {\n      onNewBitrateReceived && onNewBitrateReceived(e.nativeEvent.data);\n    };\n\n    const handleOnStreamStateChanged = (e: StreamStateChangedType) => {\n      onStreamStateChanged && onStreamStateChanged(e.nativeEvent.data);\n    };\n\n    const handleBluetoothDeviceStatusChanged = (\n      e: BluetoothDeviceStatusChangedType\n    ) => {\n      onBluetoothDeviceStatusChanged &&\n        onBluetoothDeviceStatusChanged(e.nativeEvent.data);\n    };\n\n    useImperativeHandle(ref, () => ({\n      startStream,\n      stopStream,\n      isStreaming,\n      isCameraOnPreview,\n      getPublishURL,\n      hasCongestion,\n      isAudioPrepared,\n      isVideoPrepared,\n      isMuted,\n      mute,\n      unmute,\n      switchCamera,\n      toggleFlash,\n      setAudioInput,\n      setVideoSettings,\n    }));\n\n    return (\n      <PublisherComponent\n        {...props}\n        onDisconnect={handleOnDisconnect}\n        onConnectionFailed={handleOnConnectionFailed}\n        onConnectionStarted={handleOnConnectionStarted}\n        onConnectionSuccess={handleOnConnectionSuccess}\n        onNewBitrateReceived={handleOnNewBitrateReceived}\n        onStreamStateChanged={handleOnStreamStateChanged}\n        onBluetoothDeviceStatusChanged={handleBluetoothDeviceStatusChanged}\n      />\n    );\n  }\n);\n\nexport default RTMPPublisher;\n"]}
\ No newline at end of file
diff --git a/node_modules/react-native-rtmp-publisher/lib/module/types.js b/node_modules/react-native-rtmp-publisher/lib/module/types.js
index 33ab0d6..f4f39f2 100644
--- a/node_modules/react-native-rtmp-publisher/lib/module/types.js
+++ b/node_modules/react-native-rtmp-publisher/lib/module/types.js
@@ -4,6 +4,7 @@ export let StreamState;
   StreamState["CONNECTING"] = "CONNECTING";
   StreamState["CONNECTED"] = "CONNECTED";
   StreamState["DISCONNECTED"] = "DISCONNECTED";
+  StreamState["CLOSED"] = "CLOSED";
   StreamState["FAILED"] = "FAILED";
 })(StreamState || (StreamState = {}));
 
diff --git a/node_modules/react-native-rtmp-publisher/lib/module/types.js.map b/node_modules/react-native-rtmp-publisher/lib/module/types.js.map
index a00b7f2..6dfb0b0 100644
--- a/node_modules/react-native-rtmp-publisher/lib/module/types.js.map
+++ b/node_modules/react-native-rtmp-publisher/lib/module/types.js.map
@@ -1 +1 @@
-{"version":3,"sources":["types.ts"],"names":["StreamState","BluetoothDeviceStatuses","AudioInputType"],"mappings":"AA8EA,WAAYA,WAAZ;;WAAYA,W;AAAAA,EAAAA,W;AAAAA,EAAAA,W;AAAAA,EAAAA,W;AAAAA,EAAAA,W;GAAAA,W,KAAAA,W;;AAMZ,WAAYC,uBAAZ;;WAAYA,uB;AAAAA,EAAAA,uB;AAAAA,EAAAA,uB;AAAAA,EAAAA,uB;GAAAA,uB,KAAAA,uB;;AAMZ,WAAYC,cAAZ;;WAAYA,c;AAAAA,EAAAA,c,CAAAA,c;AAAAA,EAAAA,c,CAAAA,c;AAAAA,EAAAA,c,CAAAA,c;GAAAA,c,KAAAA,c","sourcesContent":["import type { ViewStyle } from 'react-native';\n\nexport interface RTMPPublisherRefProps {\n  /**\n   * Starts stream operation\n   */\n  startStream: () => Promise<void>;\n  /**\n   * Stops stream operation\n   */\n  stopStream: () => Promise<void>;\n  /**\n   * Checks stream status\n   */\n  isStreaming: () => Promise<boolean>;\n  /**\n   * Checks if camera on mount\n   */\n  isCameraOnPreview: () => Promise<boolean>;\n  /**\n   * Gets settled publish url\n   */\n  getPublishURL: () => Promise<string>;\n  /**\n   * Checks congestion status\n   */\n  hasCongestion: () => Promise<boolean>;\n  /**\n   * Checks audio status\n   */\n  isAudioPrepared: () => Promise<boolean>;\n  /**\n   * Checks video status\n   */\n  isVideoPrepared: () => Promise<boolean>;\n  /**\n   * Checks if mic closed\n   */\n  isMuted: () => Promise<boolean>;\n  /**\n   * Mutes the mic\n   */\n  mute: () => Promise<void>;\n  /**\n   * Unmutes the mic\n   */\n  unmute: () => Promise<void>;\n  /**\n   * Switches the camera\n   */\n  switchCamera: () => Promise<void>;\n  /**\n   * Toggles the flash\n   */\n  toggleFlash: () => Promise<void>;\n  /**\n   * Sets the audio input (microphone type)\n   */\n  setAudioInput: (audioInput: AudioInputType) => Promise<void>;\n}\n\nexport interface RTMPPublisherProps {\n  style?: ViewStyle;\n  streamURL: string;\n  streamName: string;\n  onConnectionFailed?: (e: null) => void;\n  onConnectionStarted?: (e: null) => void;\n  onConnectionSuccess?: (e: null) => void;\n  onDisconnect?: (e: null) => void;\n  onNewBitrateReceived?: (e: number) => void;\n  onStreamStateChanged?: (e: StreamState) => void;\n}\nexport type StreamStatus =\n  | 'CONNECTING'\n  | 'CONNECTED'\n  | 'DISCONNECTED'\n  | 'FAILED';\n\nexport enum StreamState {\n  CONNECTING = 'CONNECTING',\n  CONNECTED = 'CONNECTED',\n  DISCONNECTED = 'DISCONNECTED',\n  FAILED = 'FAILED',\n}\nexport enum BluetoothDeviceStatuses {\n  CONNECTING = 'CONNECTING',\n  CONNECTED = 'CONNECTED',\n  DISCONNECTED = 'DISCONNECTED',\n}\n\nexport enum AudioInputType {\n  BLUETOOTH_HEADSET = 0,\n  SPEAKER = 1,\n  WIRED_HEADSET = 2,\n}\n"]}
\ No newline at end of file
+{"version":3,"sources":["types.ts"],"names":["StreamState","BluetoothDeviceStatuses","AudioInputType"],"mappings":"AAoFA,WAAYA,WAAZ;;WAAYA,W;AAAAA,EAAAA,W;AAAAA,EAAAA,W;AAAAA,EAAAA,W;AAAAA,EAAAA,W;AAAAA,EAAAA,W;GAAAA,W,KAAAA,W;;AAOZ,WAAYC,uBAAZ;;WAAYA,uB;AAAAA,EAAAA,uB;AAAAA,EAAAA,uB;AAAAA,EAAAA,uB;GAAAA,uB,KAAAA,uB;;AAMZ,WAAYC,cAAZ;;WAAYA,c;AAAAA,EAAAA,c,CAAAA,c;AAAAA,EAAAA,c,CAAAA,c;AAAAA,EAAAA,c,CAAAA,c;GAAAA,c,KAAAA,c","sourcesContent":["import type { ViewStyle } from 'react-native';\n\nexport interface RTMPPublisherRefProps {\n  /**\n   * Starts stream operation\n   */\n  startStream: () => Promise<void>;\n  /**\n   * Stops stream operation\n   */\n  stopStream: () => Promise<void>;\n  /**\n   * Checks stream status\n   */\n  isStreaming: () => Promise<boolean>;\n  /**\n   * Checks if camera on mount\n   */\n  isCameraOnPreview: () => Promise<boolean>;\n  /**\n   * Gets settled publish url\n   */\n  getPublishURL: () => Promise<string>;\n  /**\n   * Checks congestion status\n   */\n  hasCongestion: () => Promise<boolean>;\n  /**\n   * Checks audio status\n   */\n  isAudioPrepared: () => Promise<boolean>;\n  /**\n   * Checks video status\n   */\n  isVideoPrepared: () => Promise<boolean>;\n  /**\n   * Checks if mic closed\n   */\n  isMuted: () => Promise<boolean>;\n  /**\n   * Mutes the mic\n   */\n  mute: () => Promise<void>;\n  /**\n   * Unmutes the mic\n   */\n  unmute: () => Promise<void>;\n  /**\n   * Switches the camera\n   */\n  switchCamera: () => Promise<void>;\n  /**\n   * Toggles the flash\n   */\n  toggleFlash: () => Promise<void>;\n  /**\n   * Sets the audio input (microphone type)\n   */\n  setAudioInput: (audioInput: AudioInputType) => Promise<void>;\n  /**\n   * Sets video settings quality\n   */\n  setVideoSettings: (audioInput: VideoSettingsType) => Promise<void>;\n}\n\nexport interface RTMPPublisherProps {\n  style?: ViewStyle;\n  streamURL: string;\n  streamName: string;\n  videoSettings?: VideoSettingsType;\n  onConnectionFailed?: (e: null) => void;\n  onConnectionStarted?: (e: null) => void;\n  onConnectionSuccess?: (e: null) => void;\n  onDisconnect?: (e: null) => void;\n  onNewBitrateReceived?: (e: number) => void;\n  onStreamStateChanged?: (e: StreamState) => void;\n}\nexport type StreamStatus =\n  | 'CONNECTING'\n  | 'CONNECTED'\n  | 'DISCONNECTED'\n  | 'CLOSED'\n  | 'FAILED';\n\nexport enum StreamState {\n  CONNECTING = 'CONNECTING',\n  CONNECTED = 'CONNECTED',\n  DISCONNECTED = 'DISCONNECTED',\n  CLOSED = 'CLOSED',\n  FAILED = 'FAILED',\n}\nexport enum BluetoothDeviceStatuses {\n  CONNECTING = 'CONNECTING',\n  CONNECTED = 'CONNECTED',\n  DISCONNECTED = 'DISCONNECTED',\n}\n\nexport enum AudioInputType {\n  BLUETOOTH_HEADSET = 0,\n  SPEAKER = 1,\n  WIRED_HEADSET = 2,\n}\n\nexport interface VideoSettingsType {\n  width: number;\n  height: number;\n  bitrate: number;\n}\n"]}
\ No newline at end of file
diff --git a/node_modules/react-native-rtmp-publisher/lib/typescript/Component.d.ts b/node_modules/react-native-rtmp-publisher/lib/typescript/Component.d.ts
index d192f60..284149f 100644
--- a/node_modules/react-native-rtmp-publisher/lib/typescript/Component.d.ts
+++ b/node_modules/react-native-rtmp-publisher/lib/typescript/Component.d.ts
@@ -1,5 +1,5 @@
 import { NativeSyntheticEvent, ViewStyle } from 'react-native';
-import type { StreamState, BluetoothDeviceStatuses } from './types';
+import type { StreamState, BluetoothDeviceStatuses, VideoSettingsType } from './types';
 declare type RTMPData<T> = {
     data: T;
 };
@@ -14,6 +14,7 @@ export interface NativeRTMPPublisherProps {
     style?: ViewStyle;
     streamURL: string;
     streamName: string;
+    videoSettings?: VideoSettingsType;
     onConnectionFailed?: (e: ConnectionFailedType) => void;
     onConnectionStarted?: (e: ConnectionStartedType) => void;
     onConnectionSuccess?: (e: ConnectionSuccessType) => void;
diff --git a/node_modules/react-native-rtmp-publisher/lib/typescript/RTMPPublisher.d.ts b/node_modules/react-native-rtmp-publisher/lib/typescript/RTMPPublisher.d.ts
index dc79cdd..6189ec4 100644
--- a/node_modules/react-native-rtmp-publisher/lib/typescript/RTMPPublisher.d.ts
+++ b/node_modules/react-native-rtmp-publisher/lib/typescript/RTMPPublisher.d.ts
@@ -1,10 +1,15 @@
 import React from 'react';
-import { ViewStyle } from 'react-native';
-import type { RTMPPublisherRefProps, StreamState, BluetoothDeviceStatuses } from './types';
+import { type ViewStyle } from 'react-native';
+import type { RTMPPublisherRefProps, StreamState, BluetoothDeviceStatuses, VideoSettingsType } from './types';
 export interface RTMPPublisherProps {
+    testID?: string;
     style?: ViewStyle;
     streamURL: string;
     streamName: string;
+    /**
+     * Video settings for video
+     */
+    videoSettings?: VideoSettingsType;
     /**
      * Callback for connection fails on RTMP server
      */
diff --git a/node_modules/react-native-rtmp-publisher/lib/typescript/types.d.ts b/node_modules/react-native-rtmp-publisher/lib/typescript/types.d.ts
index f2ce585..226319c 100644
--- a/node_modules/react-native-rtmp-publisher/lib/typescript/types.d.ts
+++ b/node_modules/react-native-rtmp-publisher/lib/typescript/types.d.ts
@@ -56,11 +56,16 @@ export interface RTMPPublisherRefProps {
      * Sets the audio input (microphone type)
      */
     setAudioInput: (audioInput: AudioInputType) => Promise<void>;
+    /**
+     * Sets video settings quality
+     */
+    setVideoSettings: (audioInput: VideoSettingsType) => Promise<void>;
 }
 export interface RTMPPublisherProps {
     style?: ViewStyle;
     streamURL: string;
     streamName: string;
+    videoSettings?: VideoSettingsType;
     onConnectionFailed?: (e: null) => void;
     onConnectionStarted?: (e: null) => void;
     onConnectionSuccess?: (e: null) => void;
@@ -68,11 +73,12 @@ export interface RTMPPublisherProps {
     onNewBitrateReceived?: (e: number) => void;
     onStreamStateChanged?: (e: StreamState) => void;
 }
-export declare type StreamStatus = 'CONNECTING' | 'CONNECTED' | 'DISCONNECTED' | 'FAILED';
+export declare type StreamStatus = 'CONNECTING' | 'CONNECTED' | 'DISCONNECTED' | 'CLOSED' | 'FAILED';
 export declare enum StreamState {
     CONNECTING = "CONNECTING",
     CONNECTED = "CONNECTED",
     DISCONNECTED = "DISCONNECTED",
+    CLOSED = "CLOSED",
     FAILED = "FAILED"
 }
 export declare enum BluetoothDeviceStatuses {
@@ -85,3 +91,8 @@ export declare enum AudioInputType {
     SPEAKER = 1,
     WIRED_HEADSET = 2
 }
+export interface VideoSettingsType {
+    width: number;
+    height: number;
+    bitrate: number;
+}
diff --git a/node_modules/react-native-rtmp-publisher/src/Component.tsx b/node_modules/react-native-rtmp-publisher/src/Component.tsx
index 7d273ee..04dd800 100644
--- a/node_modules/react-native-rtmp-publisher/src/Component.tsx
+++ b/node_modules/react-native-rtmp-publisher/src/Component.tsx
@@ -3,7 +3,11 @@ import {
   requireNativeComponent,
   ViewStyle,
 } from 'react-native';
-import type { StreamState, BluetoothDeviceStatuses } from './types';
+import type {
+  StreamState,
+  BluetoothDeviceStatuses,
+  VideoSettingsType,
+} from './types';
 
 type RTMPData<T> = { data: T };
 
@@ -22,6 +26,7 @@ export interface NativeRTMPPublisherProps {
   style?: ViewStyle;
   streamURL: string;
   streamName: string;
+  videoSettings?: VideoSettingsType;
   onConnectionFailed?: (e: ConnectionFailedType) => void;
   onConnectionStarted?: (e: ConnectionStartedType) => void;
   onConnectionSuccess?: (e: ConnectionSuccessType) => void;
diff --git a/node_modules/react-native-rtmp-publisher/src/RTMPPublisher.tsx b/node_modules/react-native-rtmp-publisher/src/RTMPPublisher.tsx
index 7f11946..f0e64ee 100644
--- a/node_modules/react-native-rtmp-publisher/src/RTMPPublisher.tsx
+++ b/node_modules/react-native-rtmp-publisher/src/RTMPPublisher.tsx
@@ -14,13 +14,19 @@ import type {
   StreamState,
   BluetoothDeviceStatuses,
   AudioInputType,
+  VideoSettingsType,
 } from './types';
 
 const RTMPModule = NativeModules.RTMPPublisher;
 export interface RTMPPublisherProps {
+  testID?: string;
   style?: ViewStyle;
   streamURL: string;
   streamName: string;
+  /**
+   * Video settings for video
+   */
+  videoSettings?: VideoSettingsType;
   /**
    * Callback for connection fails on RTMP server
    */
@@ -95,6 +101,9 @@ const RTMPPublisher = forwardRef<RTMPPublisherRefProps, RTMPPublisherProps>(
     const setAudioInput = (audioInput: AudioInputType) =>
       RTMPModule.setAudioInput(audioInput);
 
+    const setVideoSettings = async (videoSettings: VideoSettingsType) =>
+      RTMPModule.setVideoSettings(videoSettings);
+
     const handleOnConnectionFailed = (e: ConnectionFailedType) => {
       onConnectionFailed && onConnectionFailed(e.nativeEvent.data);
     };
@@ -141,6 +150,7 @@ const RTMPPublisher = forwardRef<RTMPPublisherRefProps, RTMPPublisherProps>(
       switchCamera,
       toggleFlash,
       setAudioInput,
+      setVideoSettings,
     }));
 
     return (
diff --git a/node_modules/react-native-rtmp-publisher/src/types.ts b/node_modules/react-native-rtmp-publisher/src/types.ts
index 3fc9fda..4b93be4 100644
--- a/node_modules/react-native-rtmp-publisher/src/types.ts
+++ b/node_modules/react-native-rtmp-publisher/src/types.ts
@@ -57,12 +57,17 @@ export interface RTMPPublisherRefProps {
    * Sets the audio input (microphone type)
    */
   setAudioInput: (audioInput: AudioInputType) => Promise<void>;
+  /**
+   * Sets video settings quality
+   */
+  setVideoSettings: (audioInput: VideoSettingsType) => Promise<void>;
 }
 
 export interface RTMPPublisherProps {
   style?: ViewStyle;
   streamURL: string;
   streamName: string;
+  videoSettings?: VideoSettingsType;
   onConnectionFailed?: (e: null) => void;
   onConnectionStarted?: (e: null) => void;
   onConnectionSuccess?: (e: null) => void;
@@ -74,12 +79,14 @@ export type StreamStatus =
   | 'CONNECTING'
   | 'CONNECTED'
   | 'DISCONNECTED'
+  | 'CLOSED'
   | 'FAILED';
 
 export enum StreamState {
   CONNECTING = 'CONNECTING',
   CONNECTED = 'CONNECTED',
   DISCONNECTED = 'DISCONNECTED',
+  CLOSED = 'CLOSED',
   FAILED = 'FAILED',
 }
 export enum BluetoothDeviceStatuses {
@@ -93,3 +100,9 @@ export enum AudioInputType {
   SPEAKER = 1,
   WIRED_HEADSET = 2,
 }
+
+export interface VideoSettingsType {
+  width: number;
+  height: number;
+  bitrate: number;
+}

@ezranbayantemur
Copy link
Owner

Hello @Andriiklymiuk thanks for the PR and contribution.
Looks like Makefile file is crashing the pipeline process. Can you remove it and change the PR to the develop branch?

Comment on lines +2 to +10
import { NativeModules, ViewStyle } from 'react-native';
import PublisherComponent, {
type DisconnectType,
type ConnectionFailedType,
type ConnectionStartedType,
type ConnectionSuccessType,
type NewBitrateReceivedType,
type StreamStateChangedType,
type BluetoothDeviceStatusChangedType,
DisconnectType,
ConnectionFailedType,
ConnectionStartedType,
ConnectionSuccessType,
NewBitrateReceivedType,
StreamStateChangedType,
BluetoothDeviceStatusChangedType,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you remove the type aliases?

@@ -24,4 +27,4 @@
"strict": true,
"target": "esnext"
}
}
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like you've delete the newline on the bottom

@@ -96,6 +101,9 @@ const RTMPPublisher = forwardRef<RTMPPublisherRefProps, RTMPPublisherProps>(
const setAudioInput = (audioInput: AudioInputType) =>
RTMPModule.setAudioInput(audioInput);

const setVideoSettings = async (videoSettings: VideoSettingsType) =>
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

async keyword is unnecessary on here.

@@ -27,9 +31,11 @@
"lint": "eslint \"**/*.{js,ts,tsx}\"",
"prepare": "bob build",
"release": "dotenv release-it --",
"example": "yarn --cwd example",
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you delete example script?

Comment on lines +36 to +38
"build": "pnpm install && pnpm pack",
"unpack": "for file in react-native-rtmp-publisher*.tgz; do tar -xzf \"$file\"; done",
"deletePackage": "rm -r package && rm -r react-native-rtmp-publisher*.tgz"
Copy link
Owner

@ezranbayantemur ezranbayantemur Apr 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think sticking on yarn is much more good idea for right now. We can consider pnpm on the future. Thanks for the suggestion 👍🏼
Can you revert this for now?

@@ -209,6 +216,7 @@ For live stream, Youtube gives you stream url and stream key, you can place the
| `isVideoPrepared` | `Promise<boolean>` | Returns video prepare state | ✅ | ✅ |
| `isCameraOnPreview` | `Promise<boolean>` | Returns camera is on | ✅ | ❌ |
| `setAudioInput` | `Promise<AudioInputType>`| Sets microphone input | ✅ | ✅ |
|`setVideoSettings` | `Promise<VideoSettingsType>`| Sets camera quality settings| ❌ | ✅ |
Copy link
Owner

@ezranbayantemur ezranbayantemur Apr 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not setting the camera quality, it's setting the video scale values. Can you update it for avoiding misunderstanding?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants