expo-nodemediaclient 0.2.0 → 0.2.1

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/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## [0.2.1] 2026-01-05
2
+ - SDK更新到4.1
3
+ - 添加推流静音,镜头缩放,补光灯开关api
4
+
1
5
  ## [0.2.0] 2025-12-31
2
6
  - SDK更新到4.0
3
7
  - 添加推流实现
package/CLAUDE.md ADDED
@@ -0,0 +1,55 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Project Overview
6
+
7
+ This is **expo-nodemediaclient**, an Expo native module providing live streaming capabilities using the NodeMedia SDK 4.0. It enables RTMP/RTSP/HLS/HTTP-FLV video playback and RTMP live streaming (publishing) for React Native applications using Expo's Continuous Native Generation (CNG) workflow.
8
+
9
+ ## Architecture
10
+
11
+ The module follows Expo's custom native module pattern with three main components:
12
+
13
+ - **NodeMediaClient** (`ExpoNodeMediaClientModule.tsx`) - SDK license management, requires separate license keys for iOS and Android
14
+ - **NodePlayer** (`ExpoNodePlayerView.tsx`) - Video playback component using `requireNativeViewManager`
15
+ - **NodePublisher** (`ExpoNodePublisherView.tsx`) - Camera capture and streaming component using `requireNativeViewManager`
16
+
17
+ The native implementations are in:
18
+ - `ios/ExpoNodemediaclient/` - iOS native code (Objective-C/Swift)
19
+ - `android/src/main/java/` - Android native code (Java)
20
+
21
+ Module configuration is in `expo-module.config.json` which maps platform-specific module names.
22
+
23
+ ## Development Commands
24
+
25
+ ```bash
26
+ npm run build # Build the module (TypeScript -> build/)
27
+ npm run clean # Clean build artifacts
28
+ npm run lint # Run linting
29
+ npm run test # Run tests
30
+ npm run prepare # Prepare module for development
31
+ npm run prepublishOnly # Prepare for publishing
32
+ npm run open:ios # Open example iOS project in Xcode
33
+ npm run open:android # Open example Android project in Android Studio
34
+ ```
35
+
36
+ The example app in `example/` demonstrates both Player and Publisher functionality with navigation between screens.
37
+
38
+ ## Key Constants
39
+
40
+ NodePublisher exposes these important constants:
41
+ - `NMC_CODEC_ID_AAC`, `NMC_CODEC_ID_H264`, `NMC_CODEC_ID_H265` - Codec identifiers
42
+ - `NMC_PROFILE_AUTO` - Auto profile selection
43
+ - `VIDEO_ORIENTATION_PORTRAIT`, `VIDEO_ORIENTATION_LANDSCAPE` - Video orientation
44
+ - `EFFECTOR_STYLE_ID_FAIRSKIN` - Beauty filter style
45
+
46
+ ## Event Callbacks
47
+
48
+ Both NodePlayer and NodePublisher support `onEventCallback` that receives `{ nativeEvent: { event: number, msg: string } }`. The `event` code indicates status changes (connection, buffering, error, etc.).
49
+
50
+ ## Important Notes
51
+
52
+ - **License Required**: NodeMedia SDK requires separate license keys for iOS and Android from https://www.nodemedia.cn
53
+ - **CNG Required**: Projects must use Expo's Continuous Native Generation - run `npx expo prebuild` if using managed workflow
54
+ - **Permissions**: Publisher requires camera and microphone permissions; use `expo-camera` plugin for permission handling
55
+ - **SDK Version**: Currently on NodeMedia SDK 4.0 (updated in v0.2.0)
@@ -33,13 +33,13 @@ if (useManagedAndroidSdkVersions) {
33
33
  android {
34
34
  namespace "expo.modules.nodemediaclient"
35
35
  defaultConfig {
36
- versionCode 1
37
- versionName "0.1.1"
36
+ versionCode 201
37
+ versionName "0.2.1"
38
38
  }
39
39
  lintOptions {
40
40
  abortOnError false
41
41
  }
42
42
  dependencies {
43
- implementation 'com.github.NodeMedia:NodeMediaClient-Android:4.0.11'
43
+ implementation 'com.github.NodeMedia:NodeMediaClient-Android:4.1.0'
44
44
  }
45
45
  }
@@ -19,6 +19,24 @@ class ExpoNodePublisherView(context: Context, appContext: AppContext) :
19
19
  var HWAccelEnable = true
20
20
  var denoiseEnable = true
21
21
 
22
+ var zoomRatio: Float? = null
23
+ set(value) {
24
+ field = value
25
+ value?.let { np?.setZoomRatio(it) }
26
+ }
27
+
28
+ var volume: Float? = null
29
+ set(value) {
30
+ field = value
31
+ value?.let { np?.setVolume(it) }
32
+ }
33
+
34
+ var torchEnable: Boolean? = null
35
+ set(value) {
36
+ field = value
37
+ value?.let { np?.setTorchEnable(it) }
38
+ }
39
+
22
40
  // Color and effect parameters
23
41
  var colorStyleId: Int? = null
24
42
  set(value) {
@@ -58,7 +76,7 @@ class ExpoNodePublisherView(context: Context, appContext: AppContext) :
58
76
  field = value
59
77
  value?.let {
60
78
  np?.closeCamera()
61
- np?.openCamera(if (it) 0 else 1)
79
+ np?.openCamera(if (it) NodePublisher.NMC_CAMERA_FRONT else NodePublisher.NMC_CAMERA_BACK)
62
80
  }
63
81
  }
64
82
 
@@ -86,17 +104,28 @@ class ExpoNodePublisherView(context: Context, appContext: AppContext) :
86
104
  np?.setOnNodePublisherEventListener { obj, event, msg ->
87
105
  onEventCallback(mapOf("event" to event, "msg" to msg))
88
106
  }
107
+ // Apply audio and video params
89
108
  applyAudioParams()
90
109
  applyVideoParams()
110
+
111
+ // Apply crypto key and HWAccelEnable
91
112
  np?.setCryptoKey(this.cryptoKey)
92
113
  np?.setHWAccelEnable(this.HWAccelEnable)
93
- np?.openCamera(if (frontCamera == true) 0 else 1)
94
- np?.attachView(videoView)
95
-
114
+ np?.setDenoiseEnable(this.denoiseEnable)
115
+
96
116
  // Apply color and effect params if set
97
117
  colorStyleId?.let { np?.setEffectStyle(it) }
98
118
  colorStyleIntensity?.let { np?.setEffectParameter("style", it) }
99
119
  smoothskinIntensity?.let { np?.setEffectParameter("smoothskin", it) }
120
+
121
+ // Apply volume if set
122
+ volume?.let { np?.setVolume(it) }
123
+
124
+ // opencamera and attachview
125
+ np?.openCamera(if (frontCamera == true) 0 else 1)
126
+ np?.attachView(videoView)
127
+
128
+ np?.setZoomRatio(zoomRatio ?: 1f)
100
129
  }
101
130
 
102
131
  override fun onDetachedFromWindow() {
@@ -139,4 +168,8 @@ class ExpoNodePublisherView(context: Context, appContext: AppContext) :
139
168
  fun setEffectStyle(style: Int) {
140
169
  np?.setEffectStyle(style)
141
170
  }
171
+
172
+ fun startFocusAndMeteringCenter() {
173
+ np?.startFocusAndMeteringCenter()
174
+ }
142
175
  }
@@ -61,17 +61,29 @@ class ExpoNodePublisherViewModule : Module() {
61
61
  view.denoiseEnable = denoiseEnable
62
62
  }
63
63
 
64
+ Prop("zoomRatio") { view: ExpoNodePublisherView, zoomRatio: Float ->
65
+ view.zoomRatio = zoomRatio
66
+ }
67
+
68
+ Prop("volume") { view: ExpoNodePublisherView, volume: Float ->
69
+ view.volume = volume
70
+ }
71
+
72
+ Prop("torchEnable") { view: ExpoNodePublisherView, torchEnable: Boolean ->
73
+ view.torchEnable = torchEnable
74
+ }
75
+
64
76
  // Color and effect parameters
65
77
  Prop("colorStyleId") { view: ExpoNodePublisherView, colorStyleId: Int ->
66
78
  view.colorStyleId = colorStyleId
67
79
  }
68
80
 
69
- Prop("colorStyleIntensity") { view: ExpoNodePublisherView, colorStyleIntensity: Double ->
70
- view.colorStyleIntensity = colorStyleIntensity.toFloat()
81
+ Prop("colorStyleIntensity") { view: ExpoNodePublisherView, colorStyleIntensity: Float ->
82
+ view.colorStyleIntensity = colorStyleIntensity
71
83
  }
72
84
 
73
- Prop("smoothskinIntensity") { view: ExpoNodePublisherView, smoothskinIntensity: Double ->
74
- view.smoothskinIntensity = smoothskinIntensity.toFloat()
85
+ Prop("smoothskinIntensity") { view: ExpoNodePublisherView, smoothskinIntensity: Float ->
86
+ view.smoothskinIntensity = smoothskinIntensity
75
87
  }
76
88
 
77
89
  // Methods
@@ -90,6 +102,10 @@ class ExpoNodePublisherViewModule : Module() {
90
102
  AsyncFunction("setEffectStyle") { view: ExpoNodePublisherView, style: Int ->
91
103
  view.setEffectStyle(style)
92
104
  }
105
+
106
+ AsyncFunction("startFocusAndMeteringCenter") { view: ExpoNodePublisherView ->
107
+ view.startFocusAndMeteringCenter()
108
+ }
93
109
  }
94
110
  }
95
111
  }
@@ -2,8 +2,9 @@ import { ViewProps } from 'react-native';
2
2
  export type NodePublisherRef = {
3
3
  start: (url?: string) => Promise<void>;
4
4
  stop: () => Promise<void>;
5
- setEffectParameter: (key: string, value: number) => void;
6
- setEffectStyle: (style: number) => void;
5
+ setEffectParameter: (key: string, value: number) => Promise<void>;
6
+ setEffectStyle: (style: number) => Promise<void>;
7
+ startFocusAndMeteringCenter: () => Promise<void>;
7
8
  };
8
9
  export type NodePublisherEventCallback = {
9
10
  event: number;
@@ -34,6 +35,9 @@ export type NodePublisherProps = {
34
35
  videoOrientation?: number;
35
36
  frontCamera?: boolean;
36
37
  cameraFrontMirror?: boolean;
38
+ zoomRatio?: number;
39
+ volume?: number;
40
+ torchEnable?: boolean;
37
41
  HWAccelEnable?: boolean;
38
42
  denoiseEnable?: boolean;
39
43
  colorStyleId?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"ExpoNodePublisherView.d.ts","sourceRoot":"","sources":["../src/ExpoNodePublisherView.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAGzC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC,CAAA;AAED,MAAM,MAAM,0BAA0B,GAAG;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb,CAAA;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAA;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAA;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,GAAG,CAAC,EAAE,gBAAgB,CAAC;IACvB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,WAAW,EAAE,0BAA0B,CAAA;KAAE,KAAK,IAAI,CAAC;CAChF,GAAG,SAAS,CAAC;AAGd,iBAAS,qBAAqB,CAAC,KAAK,EAAE,kBAAkB,+BAEvD;kBAFQ,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0C9B,eAAe,qBAAqB,CAAC"}
1
+ {"version":3,"file":"ExpoNodePublisherView.d.ts","sourceRoot":"","sources":["../src/ExpoNodePublisherView.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAGzC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAClE,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjD,2BAA2B,EAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACjD,CAAA;AAED,MAAM,MAAM,0BAA0B,GAAG;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb,CAAA;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAA;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAA;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,GAAG,CAAC,EAAE,gBAAgB,CAAC;IACvB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,WAAW,EAAE,0BAA0B,CAAA;KAAE,KAAK,IAAI,CAAC;CAChF,GAAG,SAAS,CAAC;AAGd,iBAAS,qBAAqB,CAAC,KAAK,EAAE,kBAAkB,+BAEvD;kBAFQ,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0C9B,eAAe,qBAAqB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ExpoNodePublisherView.js","sourceRoot":"","sources":["../src/ExpoNodePublisherView.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAiD7D,MAAM,UAAU,GAA4C,wBAAwB,CAAC,uBAAuB,CAAC,CAAC;AAC9G,SAAS,qBAAqB,CAAC,KAAyB;IACtD,OAAO,CAAC,UAAU,CAAC,IAAI,KAAK,CAAC,EAAG,CAAC;AACnC,CAAC;AAED,qBAAqB,CAAC,iBAAiB,GAAG,EAAE,CAAC;AAC7C,qBAAqB,CAAC,iBAAiB,GAAG,GAAG,CAAC;AAC9C,qBAAqB,CAAC,gBAAgB,GAAG,KAAK,CAAC;AAC/C,qBAAqB,CAAC,iBAAiB,GAAG,KAAK,CAAC;AAChD,qBAAqB,CAAC,iBAAiB,GAAG,KAAK,CAAC;AAChD,qBAAqB,CAAC,iBAAiB,GAAG,KAAK,CAAC;AAChD,qBAAqB,CAAC,gBAAgB,GAAG,CAAC,CAAC;AAC3C,qBAAqB,CAAC,yBAAyB,GAAG,EAAE,CAAC;AACrD,qBAAqB,CAAC,qBAAqB,GAAG,EAAE,CAAC;AACjD,qBAAqB,CAAC,qBAAqB,GAAG,GAAG,CAAC;AAClD,qBAAqB,CAAC,qBAAqB,GAAG,CAAC,CAAC;AAChD,qBAAqB,CAAC,kBAAkB,GAAG,CAAC,CAAC;AAC7C,qBAAqB,CAAC,kBAAkB,GAAG,CAAC,CAAC;AAC7C,qBAAqB,CAAC,qBAAqB,GAAG,EAAE,CAAC;AACjD,qBAAqB,CAAC,0BAA0B,GAAG,CAAC,CAAC;AACrD,qBAAqB,CAAC,iCAAiC,GAAG,CAAC,CAAC;AAC5D,qBAAqB,CAAC,gCAAgC,GAAG,CAAC,CAAC;AAC3D,qBAAqB,CAAC,OAAO,GAAG,CAAC,CAAC;AAClC,qBAAqB,CAAC,OAAO,GAAG,CAAC,CAAC;AAClC,qBAAqB,CAAC,QAAQ,GAAG,CAAC,CAAC;AACnC,qBAAqB,CAAC,+BAA+B,GAAG,CAAC,CAAC;AAC1D,qBAAqB,CAAC,+BAA+B,GAAG,CAAC,CAAC;AAC1D,qBAAqB,CAAC,+BAA+B,GAAG,CAAC,CAAC;AAC1D,qBAAqB,CAAC,0BAA0B,GAAG,CAAC,CAAC;AACrD,qBAAqB,CAAC,4BAA4B,GAAG,CAAC,CAAC;AACvD,qBAAqB,CAAC,mBAAmB,GAAG,YAAY,CAAC;AACzD,qBAAqB,CAAC,iBAAiB,GAAG,UAAU,CAAC;AACrD,qBAAqB,CAAC,mBAAmB,GAAG,YAAY,CAAC;AACzD,qBAAqB,CAAC,gBAAgB,GAAG,SAAS,CAAC;AACnD,qBAAqB,CAAC,mBAAmB,GAAG,YAAY,CAAC;AACzD,qBAAqB,CAAC,cAAc,GAAG,OAAO,CAAC;AAC/C,qBAAqB,CAAC,0BAA0B,GAAG,CAAC,CAAC;AACrD,qBAAqB,CAAC,0BAA0B,GAAG,CAAC,CAAC;AACrD,qBAAqB,CAAC,0BAA0B,GAAG,CAAC,CAAC;AACrD,qBAAqB,CAAC,sBAAsB,GAAG,CAAC,CAAC;AACjD,qBAAqB,CAAC,sBAAsB,GAAG,CAAC,CAAC;AACjD,qBAAqB,CAAC,uBAAuB,GAAG,CAAC,CAAC;AAElD,eAAe,qBAAqB,CAAC","sourcesContent":["\nimport { ViewProps } from 'react-native';\nimport { requireNativeViewManager } from 'expo-modules-core';\n\nexport type NodePublisherRef = {\n start: (url?: string) => Promise<void>;\n stop: () => Promise<void>;\n setEffectParameter: (key: string, value: number) => void;\n setEffectStyle: (style: number) => void;\n}\n\nexport type NodePublisherEventCallback = {\n event: number;\n msg: string;\n}\n\nexport type AudioParam = {\n codecid?: number;\n profile?: number;\n samplingRate?: number;\n channels?: number;\n bitrate?: number;\n}\n\nexport type VideoParam = {\n codecid?: number;\n profile?: number;\n width?: number;\n height?: number;\n fps?: number;\n bitrate?: number;\n}\n\nexport type NodePublisherProps = {\n ref?: NodePublisherRef;\n url?: string;\n cryptoKey?: string;\n audioParam?: AudioParam\n videoParam?: VideoParam;\n keyFrameInterval?: number;\n videoOrientation?: number;\n frontCamera?: boolean;\n cameraFrontMirror?: boolean;\n HWAccelEnable?: boolean;\n denoiseEnable?: boolean;\n colorStyleId?: number;\n colorStyleIntensity?: number;\n smoothskinIntensity?: number;\n onEventCallback?: (event: { nativeEvent: NodePublisherEventCallback }) => void;\n} & ViewProps;\n\nconst NativeView: React.ComponentType<NodePublisherProps> = requireNativeViewManager('ExpoNodePublisherView');\nfunction ExpoNodePublisherView(props: NodePublisherProps) {\n return <NativeView {...props} />;\n}\n\nExpoNodePublisherView.NMC_CODEC_ID_H264 = 27;\nExpoNodePublisherView.NMC_CODEC_ID_H265 = 173;\nExpoNodePublisherView.NMC_CODEC_ID_AAC = 86018;\nExpoNodePublisherView.NMC_CODEC_ID_OPUS = 86076;\nExpoNodePublisherView.NMC_CODEC_ID_PCMA = 65543;\nExpoNodePublisherView.NMC_CODEC_ID_PCMU = 65542;\nExpoNodePublisherView.NMC_PROFILE_AUTO = 0;\nExpoNodePublisherView.NMC_PROFILE_H264_BASELINE = 66;\nExpoNodePublisherView.NMC_PROFILE_H264_MAIN = 77;\nExpoNodePublisherView.NMC_PROFILE_H264_HIGH = 100;\nExpoNodePublisherView.NMC_PROFILE_H265_MAIN = 1;\nExpoNodePublisherView.NMC_PROFILE_AAC_LC = 1;\nExpoNodePublisherView.NMC_PROFILE_AAC_HE = 4;\nExpoNodePublisherView.NMC_PROFILE_AAC_HE_V2 = 28;\nExpoNodePublisherView.VIDEO_ORIENTATION_PORTRAIT = 1;\nExpoNodePublisherView.VIDEO_ORIENTATION_LANDSCAPE_RIGHT = 3;\nExpoNodePublisherView.VIDEO_ORIENTATION_LANDSCAPE_LEFT = 4;\nExpoNodePublisherView.FLAG_AF = 1;\nExpoNodePublisherView.FLAG_AE = 2;\nExpoNodePublisherView.FLAG_AWB = 4;\nExpoNodePublisherView.NMC_DEVICE_TYPE_WideAngleCamera = 0;\nExpoNodePublisherView.NMC_DEVICE_TYPE_TelephotoCamera = 1;\nExpoNodePublisherView.NMC_DEVICE_TYPE_UltraWideCamera = 2;\nExpoNodePublisherView.NMC_DEVICE_TYPE_DualCamera = 3;\nExpoNodePublisherView.NMC_DEVICE_TYPE_TripleCamera = 4;\nExpoNodePublisherView.EFFECTOR_BRIGHTNESS = \"brightness\";\nExpoNodePublisherView.EFFECTOR_CONTRAST = \"contrast\";\nExpoNodePublisherView.EFFECTOR_SATURATION = \"saturation\";\nExpoNodePublisherView.EFFECTOR_SHARPEN = \"sharpen\";\nExpoNodePublisherView.EFFECTOR_SMOOTHSKIN = \"smoothskin\";\nExpoNodePublisherView.EFFECTOR_STYLE = \"style\";\nExpoNodePublisherView.EFFECTOR_STYLE_ID_ORIGINAL = 0;\nExpoNodePublisherView.EFFECTOR_STYLE_ID_ENHANCED = 1;\nExpoNodePublisherView.EFFECTOR_STYLE_ID_FAIRSKIN = 2;\nExpoNodePublisherView.EFFECTOR_STYLE_ID_COOL = 3;\nExpoNodePublisherView.EFFECTOR_STYLE_ID_FILM = 4;\nExpoNodePublisherView.EFFECTOR_STYLE_ID_BOOST = 5;\n\nexport default ExpoNodePublisherView;"]}
1
+ {"version":3,"file":"ExpoNodePublisherView.js","sourceRoot":"","sources":["../src/ExpoNodePublisherView.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAqD7D,MAAM,UAAU,GAA4C,wBAAwB,CAAC,uBAAuB,CAAC,CAAC;AAC9G,SAAS,qBAAqB,CAAC,KAAyB;IACtD,OAAO,CAAC,UAAU,CAAC,IAAI,KAAK,CAAC,EAAG,CAAC;AACnC,CAAC;AAED,qBAAqB,CAAC,iBAAiB,GAAG,EAAE,CAAC;AAC7C,qBAAqB,CAAC,iBAAiB,GAAG,GAAG,CAAC;AAC9C,qBAAqB,CAAC,gBAAgB,GAAG,KAAK,CAAC;AAC/C,qBAAqB,CAAC,iBAAiB,GAAG,KAAK,CAAC;AAChD,qBAAqB,CAAC,iBAAiB,GAAG,KAAK,CAAC;AAChD,qBAAqB,CAAC,iBAAiB,GAAG,KAAK,CAAC;AAChD,qBAAqB,CAAC,gBAAgB,GAAG,CAAC,CAAC;AAC3C,qBAAqB,CAAC,yBAAyB,GAAG,EAAE,CAAC;AACrD,qBAAqB,CAAC,qBAAqB,GAAG,EAAE,CAAC;AACjD,qBAAqB,CAAC,qBAAqB,GAAG,GAAG,CAAC;AAClD,qBAAqB,CAAC,qBAAqB,GAAG,CAAC,CAAC;AAChD,qBAAqB,CAAC,kBAAkB,GAAG,CAAC,CAAC;AAC7C,qBAAqB,CAAC,kBAAkB,GAAG,CAAC,CAAC;AAC7C,qBAAqB,CAAC,qBAAqB,GAAG,EAAE,CAAC;AACjD,qBAAqB,CAAC,0BAA0B,GAAG,CAAC,CAAC;AACrD,qBAAqB,CAAC,iCAAiC,GAAG,CAAC,CAAC;AAC5D,qBAAqB,CAAC,gCAAgC,GAAG,CAAC,CAAC;AAC3D,qBAAqB,CAAC,OAAO,GAAG,CAAC,CAAC;AAClC,qBAAqB,CAAC,OAAO,GAAG,CAAC,CAAC;AAClC,qBAAqB,CAAC,QAAQ,GAAG,CAAC,CAAC;AACnC,qBAAqB,CAAC,+BAA+B,GAAG,CAAC,CAAC;AAC1D,qBAAqB,CAAC,+BAA+B,GAAG,CAAC,CAAC;AAC1D,qBAAqB,CAAC,+BAA+B,GAAG,CAAC,CAAC;AAC1D,qBAAqB,CAAC,0BAA0B,GAAG,CAAC,CAAC;AACrD,qBAAqB,CAAC,4BAA4B,GAAG,CAAC,CAAC;AACvD,qBAAqB,CAAC,mBAAmB,GAAG,YAAY,CAAC;AACzD,qBAAqB,CAAC,iBAAiB,GAAG,UAAU,CAAC;AACrD,qBAAqB,CAAC,mBAAmB,GAAG,YAAY,CAAC;AACzD,qBAAqB,CAAC,gBAAgB,GAAG,SAAS,CAAC;AACnD,qBAAqB,CAAC,mBAAmB,GAAG,YAAY,CAAC;AACzD,qBAAqB,CAAC,cAAc,GAAG,OAAO,CAAC;AAC/C,qBAAqB,CAAC,0BAA0B,GAAG,CAAC,CAAC;AACrD,qBAAqB,CAAC,0BAA0B,GAAG,CAAC,CAAC;AACrD,qBAAqB,CAAC,0BAA0B,GAAG,CAAC,CAAC;AACrD,qBAAqB,CAAC,sBAAsB,GAAG,CAAC,CAAC;AACjD,qBAAqB,CAAC,sBAAsB,GAAG,CAAC,CAAC;AACjD,qBAAqB,CAAC,uBAAuB,GAAG,CAAC,CAAC;AAElD,eAAe,qBAAqB,CAAC","sourcesContent":["\nimport { ViewProps } from 'react-native';\nimport { requireNativeViewManager } from 'expo-modules-core';\n\nexport type NodePublisherRef = {\n start: (url?: string) => Promise<void>;\n stop: () => Promise<void>;\n setEffectParameter: (key: string, value: number) => Promise<void>;\n setEffectStyle: (style: number) => Promise<void>;\n startFocusAndMeteringCenter:() => Promise<void>;\n}\n\nexport type NodePublisherEventCallback = {\n event: number;\n msg: string;\n}\n\nexport type AudioParam = {\n codecid?: number;\n profile?: number;\n samplingRate?: number;\n channels?: number;\n bitrate?: number;\n}\n\nexport type VideoParam = {\n codecid?: number;\n profile?: number;\n width?: number;\n height?: number;\n fps?: number;\n bitrate?: number;\n}\n\nexport type NodePublisherProps = {\n ref?: NodePublisherRef;\n url?: string;\n cryptoKey?: string;\n audioParam?: AudioParam\n videoParam?: VideoParam;\n keyFrameInterval?: number;\n videoOrientation?: number;\n frontCamera?: boolean;\n cameraFrontMirror?: boolean;\n zoomRatio?: number;\n volume?: number;\n torchEnable?: boolean;\n HWAccelEnable?: boolean;\n denoiseEnable?: boolean;\n colorStyleId?: number;\n colorStyleIntensity?: number;\n smoothskinIntensity?: number;\n onEventCallback?: (event: { nativeEvent: NodePublisherEventCallback }) => void;\n} & ViewProps;\n\nconst NativeView: React.ComponentType<NodePublisherProps> = requireNativeViewManager('ExpoNodePublisherView');\nfunction ExpoNodePublisherView(props: NodePublisherProps) {\n return <NativeView {...props} />;\n}\n\nExpoNodePublisherView.NMC_CODEC_ID_H264 = 27;\nExpoNodePublisherView.NMC_CODEC_ID_H265 = 173;\nExpoNodePublisherView.NMC_CODEC_ID_AAC = 86018;\nExpoNodePublisherView.NMC_CODEC_ID_OPUS = 86076;\nExpoNodePublisherView.NMC_CODEC_ID_PCMA = 65543;\nExpoNodePublisherView.NMC_CODEC_ID_PCMU = 65542;\nExpoNodePublisherView.NMC_PROFILE_AUTO = 0;\nExpoNodePublisherView.NMC_PROFILE_H264_BASELINE = 66;\nExpoNodePublisherView.NMC_PROFILE_H264_MAIN = 77;\nExpoNodePublisherView.NMC_PROFILE_H264_HIGH = 100;\nExpoNodePublisherView.NMC_PROFILE_H265_MAIN = 1;\nExpoNodePublisherView.NMC_PROFILE_AAC_LC = 1;\nExpoNodePublisherView.NMC_PROFILE_AAC_HE = 4;\nExpoNodePublisherView.NMC_PROFILE_AAC_HE_V2 = 28;\nExpoNodePublisherView.VIDEO_ORIENTATION_PORTRAIT = 1;\nExpoNodePublisherView.VIDEO_ORIENTATION_LANDSCAPE_RIGHT = 3;\nExpoNodePublisherView.VIDEO_ORIENTATION_LANDSCAPE_LEFT = 4;\nExpoNodePublisherView.FLAG_AF = 1;\nExpoNodePublisherView.FLAG_AE = 2;\nExpoNodePublisherView.FLAG_AWB = 4;\nExpoNodePublisherView.NMC_DEVICE_TYPE_WideAngleCamera = 0;\nExpoNodePublisherView.NMC_DEVICE_TYPE_TelephotoCamera = 1;\nExpoNodePublisherView.NMC_DEVICE_TYPE_UltraWideCamera = 2;\nExpoNodePublisherView.NMC_DEVICE_TYPE_DualCamera = 3;\nExpoNodePublisherView.NMC_DEVICE_TYPE_TripleCamera = 4;\nExpoNodePublisherView.EFFECTOR_BRIGHTNESS = \"brightness\";\nExpoNodePublisherView.EFFECTOR_CONTRAST = \"contrast\";\nExpoNodePublisherView.EFFECTOR_SATURATION = \"saturation\";\nExpoNodePublisherView.EFFECTOR_SHARPEN = \"sharpen\";\nExpoNodePublisherView.EFFECTOR_SMOOTHSKIN = \"smoothskin\";\nExpoNodePublisherView.EFFECTOR_STYLE = \"style\";\nExpoNodePublisherView.EFFECTOR_STYLE_ID_ORIGINAL = 0;\nExpoNodePublisherView.EFFECTOR_STYLE_ID_ENHANCED = 1;\nExpoNodePublisherView.EFFECTOR_STYLE_ID_FAIRSKIN = 2;\nExpoNodePublisherView.EFFECTOR_STYLE_ID_COOL = 3;\nExpoNodePublisherView.EFFECTOR_STYLE_ID_FILM = 4;\nExpoNodePublisherView.EFFECTOR_STYLE_ID_BOOST = 5;\n\nexport default ExpoNodePublisherView;"]}
@@ -63,33 +63,35 @@ class ExpoNodePublisherView: ExpoView, NodePublisherDelegate {
63
63
 
64
64
  var frontCamera: Bool? {
65
65
  didSet {
66
- if let fc = frontCamera {
66
+ if let fc = frontCamera, oldValue != frontCamera {
67
67
  _np?.closeCamera()
68
68
  _np?.openCamera(fc)
69
69
  }
70
70
  }
71
71
  }
72
72
 
73
- var roomRatio: Float? {
73
+ var zoomRatio: Float = 0.0{
74
74
  didSet {
75
- if let ratio = roomRatio {
76
- _np?.setRoomRatio(ratio)
77
- }
75
+ _np?.zoomRatio = zoomRatio
78
76
  }
79
77
  }
80
78
 
81
- var torchEnable: Bool? {
79
+ var torchEnable: Bool = false {
82
80
  didSet {
83
- if let torch = torchEnable {
84
- _np?.enableTorch(torch)
85
- }
81
+ _np?.torchEnable = torchEnable
86
82
  }
87
83
  }
88
-
84
+
85
+ var volume: Float = 1.0 {
86
+ didSet {
87
+ _np?.volume = volume
88
+ }
89
+ }
90
+
89
91
  required init(appContext: AppContext? = nil) {
90
92
  super.init(appContext: appContext)
91
93
  }
92
-
94
+
93
95
  override func didMoveToWindow() {
94
96
  super.didMoveToWindow()
95
97
  if window != nil {
@@ -104,6 +106,8 @@ class ExpoNodePublisherView: ExpoView, NodePublisherDelegate {
104
106
  _np?.cryptoKey = cryptoKey
105
107
  _np?.hwAccelEnable = HWAccelEnable
106
108
  _np?.denoiseEnable = denoiseEnable
109
+ _np?.torchEnable = torchEnable
110
+ _np?.volume = volume
107
111
  _np?.openCamera(frontCamera == true)
108
112
  _np?.attach(self)
109
113
 
@@ -153,6 +157,10 @@ class ExpoNodePublisherView: ExpoView, NodePublisherDelegate {
153
157
  func setEffectStyle(style: Int) {
154
158
  _np?.setEffectStyleWithId(style)
155
159
  }
160
+
161
+ func startFocusAndMeteringCenter() {
162
+ _np?.startFocusAndMeteringCenter()
163
+ }
156
164
 
157
165
  // MARK: - NodePublisherDelegate
158
166
 
@@ -7,101 +7,108 @@
7
7
  import ExpoModulesCore
8
8
 
9
9
  public class ExpoNodePublisherViewModule: Module {
10
- public func definition() -> ModuleDefinition {
11
- Name("ExpoNodePublisherView")
12
-
13
- View(ExpoNodePublisherView.self) {
14
- Events("onEventCallback")
15
-
16
- Prop("url") { (view, url: String) in
17
- view.url = url
18
- }
19
-
20
- Prop("cryptoKey") { (view, key: String) in
21
- view.cryptoKey = key
22
- }
23
-
24
- Prop("HWAccelEnable") { (view, enable: Bool) in
25
- view.HWAccelEnable = enable
26
- }
27
-
28
- // Audio parameters
29
- Prop("audioParam") { (view, audioParam: [String: Int]) in
30
- view.audioCodecid = audioParam["codecid"]!
31
- view.audioProfile = audioParam["profile"]!
32
- view.audioChannels = audioParam["channels"]!
33
- view.audioSamplingRate = audioParam["samplingRate"]!
34
- view.audioBitrate = audioParam["bitrate"]!
35
- }
36
-
37
- // Video parameters
38
- Prop("videoParam") { (view, videoParam: [String: Int]) in
39
- view.videoCodecid = videoParam["codecid"]!
40
- view.videoProfile = videoParam["profile"]!
41
- view.videoWidth = videoParam["width"]!
42
- view.videoHeight = videoParam["height"]!
43
- view.videoFps = videoParam["fps"]!
44
- view.videoBitrate = videoParam["bitrate"]!
45
- }
46
-
47
- Prop("keyFrameInterval") { (view, interval: Int) in
48
- view.keyFrameInterval = interval
49
- }
50
-
51
- Prop("videoOrientation") { (view, orientation: Int) in
52
- view.videoOrientation = orientation
53
- }
54
-
55
- Prop("frontCamera") { (view, front: Bool) in
56
- view.frontCamera = front
57
- }
58
-
59
- Prop("cameraFrontMirror") { (view, mirror: Bool) in
60
- view.cameraFrontMirror = mirror
61
- }
62
-
63
- Prop("roomRatio") { (view, ratio: Double) in
64
- view.roomRatio = Float(ratio)
65
- }
66
-
67
- Prop("torchEnable") { (view, enable: Bool) in
68
- view.torchEnable = enable
69
- }
70
-
71
- Prop("denoiseEnable") { (view, enable: Bool) in
72
- view.denoiseEnable = enable
73
- }
74
-
75
- // Color and effect parameters
76
- Prop("colorStyleId") { (view, styleId: Int) in
77
- view.colorStyleId = styleId
78
- }
79
-
80
- Prop("colorStyleIntensity") { (view, intensity: Double) in
81
- view.colorStyleIntensity = Float(intensity)
82
- }
83
-
84
- Prop("smoothskinIntensity") { (view, intensity: Double) in
85
- view.smoothskinIntensity = Float(intensity)
86
- }
87
-
88
- // Methods
89
- AsyncFunction("start") { (view: ExpoNodePublisherView, url: String?) in
90
- view.start(u: url)
91
- }
92
-
93
- AsyncFunction("stop") { (view: ExpoNodePublisherView) in
94
- view.stop()
95
- }
96
-
97
- AsyncFunction("setEffectParameter") { (view: ExpoNodePublisherView, key: String, value: Float) in
98
- view.setEffectParameter(key: key, value: value)
99
- }
100
-
101
- AsyncFunction("setEffectStyle") { (view: ExpoNodePublisherView, style: Int) in
102
- view.setEffectStyle(style: style)
103
- }
10
+ public func definition() -> ModuleDefinition {
11
+ Name("ExpoNodePublisherView")
104
12
 
13
+ View(ExpoNodePublisherView.self) {
14
+ Events("onEventCallback")
15
+
16
+ Prop("url") { (view, url: String) in
17
+ view.url = url
18
+ }
19
+
20
+ Prop("cryptoKey") { (view, key: String) in
21
+ view.cryptoKey = key
22
+ }
23
+
24
+ Prop("HWAccelEnable") { (view, enable: Bool) in
25
+ view.HWAccelEnable = enable
26
+ }
27
+
28
+ // Audio parameters
29
+ Prop("audioParam") { (view, audioParam: [String: Int]) in
30
+ view.audioCodecid = audioParam["codecid"]!
31
+ view.audioProfile = audioParam["profile"]!
32
+ view.audioChannels = audioParam["channels"]!
33
+ view.audioSamplingRate = audioParam["samplingRate"]!
34
+ view.audioBitrate = audioParam["bitrate"]!
35
+ }
36
+
37
+ // Video parameters
38
+ Prop("videoParam") { (view, videoParam: [String: Int]) in
39
+ view.videoCodecid = videoParam["codecid"]!
40
+ view.videoProfile = videoParam["profile"]!
41
+ view.videoWidth = videoParam["width"]!
42
+ view.videoHeight = videoParam["height"]!
43
+ view.videoFps = videoParam["fps"]!
44
+ view.videoBitrate = videoParam["bitrate"]!
45
+ }
46
+
47
+ Prop("keyFrameInterval") { (view, interval: Int) in
48
+ view.keyFrameInterval = interval
49
+ }
50
+
51
+ Prop("videoOrientation") { (view, orientation: Int) in
52
+ view.videoOrientation = orientation
53
+ }
54
+
55
+ Prop("frontCamera") { (view, front: Bool) in
56
+ view.frontCamera = front
57
+ }
58
+
59
+ Prop("cameraFrontMirror") { (view, mirror: Bool) in
60
+ view.cameraFrontMirror = mirror
61
+ }
62
+
63
+ Prop("zoomRatio") { (view, ratio: Float) in
64
+ view.zoomRatio = ratio
65
+ }
66
+
67
+ Prop("torchEnable") { (view, enable: Bool) in
68
+ view.torchEnable = enable
69
+ }
70
+
71
+ Prop("denoiseEnable") { (view, enable: Bool) in
72
+ view.denoiseEnable = enable
73
+ }
74
+
75
+ Prop("volume") { (view, volume: Float) in
76
+ view.volume = volume
77
+ }
78
+
79
+ // Color and effect parameters
80
+ Prop("colorStyleId") { (view, styleId: Int) in
81
+ view.colorStyleId = styleId
82
+ }
83
+
84
+ Prop("colorStyleIntensity") { (view, intensity: Float) in
85
+ view.colorStyleIntensity = intensity
86
+ }
87
+
88
+ Prop("smoothskinIntensity") { (view, intensity: Float) in
89
+ view.smoothskinIntensity = intensity
90
+ }
91
+
92
+ // Methods
93
+ AsyncFunction("start") { (view: ExpoNodePublisherView, url: String?) in
94
+ view.start(u: url)
95
+ }
96
+
97
+ AsyncFunction("stop") { (view: ExpoNodePublisherView) in
98
+ view.stop()
99
+ }
100
+
101
+ AsyncFunction("setEffectParameter") { (view: ExpoNodePublisherView, key: String, value: Float) in
102
+ view.setEffectParameter(key: key, value: value)
103
+ }
104
+
105
+ AsyncFunction("setEffectStyle") { (view: ExpoNodePublisherView, style: Int) in
106
+ view.setEffectStyle(style: style)
107
+ }
108
+
109
+ AsyncFunction("startFocusAndMeteringCenter") { (view: ExpoNodePublisherView) in
110
+ view.startFocusAndMeteringCenter()
111
+ }
112
+ }
105
113
  }
106
- }
107
114
  }
@@ -19,7 +19,7 @@ Pod::Spec.new do |s|
19
19
  s.static_framework = true
20
20
 
21
21
  s.dependency 'ExpoModulesCore'
22
- s.dependency 'NodeMediaClient', '~> 4.0.12'
22
+ s.dependency 'NodeMediaClient', '~> 4.1.0'
23
23
  # Swift/Objective-C compatibility
24
24
  s.pod_target_xcconfig = {
25
25
  'DEFINES_MODULE' => 'YES',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-nodemediaclient",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Expo NodeMediaClient module",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -5,8 +5,9 @@ import { requireNativeViewManager } from 'expo-modules-core';
5
5
  export type NodePublisherRef = {
6
6
  start: (url?: string) => Promise<void>;
7
7
  stop: () => Promise<void>;
8
- setEffectParameter: (key: string, value: number) => void;
9
- setEffectStyle: (style: number) => void;
8
+ setEffectParameter: (key: string, value: number) => Promise<void>;
9
+ setEffectStyle: (style: number) => Promise<void>;
10
+ startFocusAndMeteringCenter:() => Promise<void>;
10
11
  }
11
12
 
12
13
  export type NodePublisherEventCallback = {
@@ -41,6 +42,9 @@ export type NodePublisherProps = {
41
42
  videoOrientation?: number;
42
43
  frontCamera?: boolean;
43
44
  cameraFrontMirror?: boolean;
45
+ zoomRatio?: number;
46
+ volume?: number;
47
+ torchEnable?: boolean;
44
48
  HWAccelEnable?: boolean;
45
49
  denoiseEnable?: boolean;
46
50
  colorStyleId?: number;