expo-nodemediaclient 0.2.2 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +78 -75
- package/README_CN.md +293 -0
- package/android/build.gradle +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
# expo-nodemediaclient
|
|
2
2
|
|
|
3
|
-
##
|
|
4
|
-
-
|
|
5
|
-
-
|
|
6
|
-
-
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
|
|
11
|
-
##
|
|
12
|
-
|
|
13
|
-
|
|
3
|
+
## Features
|
|
4
|
+
- Support for iOS and Android
|
|
5
|
+
- Support for RTMP, HLS, HTTP-FLV, RTSP playback
|
|
6
|
+
- Support for H.264, H.265 video encoding
|
|
7
|
+
- Support for AAC, PCM audio encoding
|
|
8
|
+
- Hardware acceleration support
|
|
9
|
+
- Low-latency playback with cumulative latency elimination
|
|
10
|
+
|
|
11
|
+
## Prerequisites
|
|
12
|
+
Your Expo project should use Continuous Native Generation [(CNG)](https://docs.expo.dev/workflow/continuous-native-generation/)
|
|
13
|
+
If not, please run first:
|
|
14
14
|
```bash
|
|
15
15
|
npx expo prebuild
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
##
|
|
18
|
+
## Installation
|
|
19
19
|
|
|
20
20
|
```bash
|
|
21
21
|
npm install expo-nodemediaclient
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
##
|
|
25
|
-
###
|
|
26
|
-
|
|
24
|
+
## Usage
|
|
25
|
+
### Register SDK
|
|
26
|
+
Android and iOS require different license codes, which need to be registered separately. Please contact [https://www.nodemedia.cn](https://www.nodemedia.cn) to obtain license codes.
|
|
27
27
|
|
|
28
28
|
```js
|
|
29
29
|
import { NodeMediaClient } from 'expo-nodemediaclient';
|
|
@@ -38,7 +38,7 @@ if (Platform.OS === 'ios') {
|
|
|
38
38
|
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
-
###
|
|
41
|
+
### Playback
|
|
42
42
|
|
|
43
43
|
```js
|
|
44
44
|
import { NodePlayer, NodePlayerRef } from 'expo-nodemediaclient';
|
|
@@ -74,44 +74,44 @@ export default function App() {
|
|
|
74
74
|
}
|
|
75
75
|
```
|
|
76
76
|
|
|
77
|
-
###
|
|
77
|
+
### Component Props
|
|
78
78
|
|
|
79
|
-
|
|
|
79
|
+
| Prop | Type | Description |
|
|
80
80
|
|------|------|------|
|
|
81
|
-
| `url` | `string` |
|
|
82
|
-
| `bufferTime` | `number` |
|
|
83
|
-
| `scaleMode` | `number` |
|
|
84
|
-
| `volume` | `number` |
|
|
85
|
-
| `onEventCallback` | `(event) => void` |
|
|
81
|
+
| `url` | `string` | Playback URL (supports RTMP, RTSP, HLS, HTTP-FLV) |
|
|
82
|
+
| `bufferTime` | `number` | Buffer time in milliseconds, default 1000 |
|
|
83
|
+
| `scaleMode` | `number` | Scale mode, `0`=fill, `1`=fit, `2`=stretch |
|
|
84
|
+
| `volume` | `number` | Volume (0.0 - 1.0), default 1.0 |
|
|
85
|
+
| `onEventCallback` | `(event) => void` | Event callback |
|
|
86
86
|
|
|
87
|
-
###
|
|
87
|
+
### Common Methods
|
|
88
88
|
|
|
89
89
|
```js
|
|
90
|
-
//
|
|
90
|
+
// Start playback
|
|
91
91
|
playerRef.current?.start(url);
|
|
92
92
|
|
|
93
|
-
//
|
|
93
|
+
// Stop playback
|
|
94
94
|
playerRef.current?.stop();
|
|
95
95
|
```
|
|
96
96
|
|
|
97
|
-
###
|
|
97
|
+
### Event Callback
|
|
98
98
|
|
|
99
99
|
```js
|
|
100
100
|
const handleEvent = (event: { nativeEvent: NodePlayerEventCallback }) => {
|
|
101
|
-
console.log('
|
|
102
|
-
console.log('
|
|
101
|
+
console.log('Event code:', event.nativeEvent.event);
|
|
102
|
+
console.log('Message:', event.nativeEvent.msg);
|
|
103
103
|
};
|
|
104
104
|
|
|
105
105
|
<NodePlayer
|
|
106
106
|
onEventCallback={handleEvent}
|
|
107
|
-
//
|
|
107
|
+
// ...other props
|
|
108
108
|
/>
|
|
109
109
|
```
|
|
110
110
|
|
|
111
111
|
|
|
112
|
-
##
|
|
112
|
+
## Streaming
|
|
113
113
|
|
|
114
|
-
###
|
|
114
|
+
### Basic Usage
|
|
115
115
|
|
|
116
116
|
```js
|
|
117
117
|
import { NodePublisher, NodePublisherRef } from 'expo-nodemediaclient';
|
|
@@ -155,7 +155,7 @@ export default function PublisherScreen() {
|
|
|
155
155
|
}}
|
|
156
156
|
/>
|
|
157
157
|
<Button
|
|
158
|
-
title={isPublishing ? "
|
|
158
|
+
title={isPublishing ? "Stop" : "Start Streaming"}
|
|
159
159
|
onPress={handleTogglePublish}
|
|
160
160
|
/>
|
|
161
161
|
</SafeAreaView>
|
|
@@ -163,80 +163,83 @@ export default function PublisherScreen() {
|
|
|
163
163
|
}
|
|
164
164
|
```
|
|
165
165
|
|
|
166
|
-
###
|
|
166
|
+
### Component Props
|
|
167
167
|
|
|
168
|
-
|
|
|
168
|
+
| Prop | Type | Description |
|
|
169
169
|
|------|------|------|
|
|
170
|
-
| `url` | `string` |
|
|
171
|
-
| `audioParam` | `AudioParam` |
|
|
172
|
-
| `videoParam` | `VideoParam` |
|
|
173
|
-
| `videoOrientation` | `number` |
|
|
174
|
-
| `keyFrameInterval` | `number` |
|
|
175
|
-
| `frontCamera` | `boolean` |
|
|
176
|
-
| `cameraFrontMirror` | `boolean` |
|
|
177
|
-
| `
|
|
178
|
-
| `
|
|
179
|
-
| `
|
|
180
|
-
| `
|
|
181
|
-
| `
|
|
182
|
-
| `
|
|
170
|
+
| `url` | `string` | Streaming URL (RTMP) |
|
|
171
|
+
| `audioParam` | `AudioParam` | Audio encoding parameters |
|
|
172
|
+
| `videoParam` | `VideoParam` | Video encoding parameters |
|
|
173
|
+
| `videoOrientation` | `number` | Video orientation, e.g., `NodePublisher.VIDEO_ORIENTATION_PORTRAIT` |
|
|
174
|
+
| `keyFrameInterval` | `number` | Key frame interval in seconds, default 2 |
|
|
175
|
+
| `frontCamera` | `boolean` | Whether to use front camera, default false |
|
|
176
|
+
| `cameraFrontMirror` | `boolean` | Whether to mirror front camera, default true |
|
|
177
|
+
| `volume` | `number` | Volume (0.0 - 1.0) |
|
|
178
|
+
| `zoomRatio` | `number` | Camera zoom ratio (0.0 - 1.0)|
|
|
179
|
+
| `torchEnable` | `boolean` | Whether to enable torch/flashlight |
|
|
180
|
+
| `HWAccelEnable` | `boolean` | Whether to enable hardware acceleration, default true |
|
|
181
|
+
| `denoiseEnable` | `boolean` | Whether to enable noise reduction, default true |
|
|
182
|
+
| `colorStyleId` | `number` | Color style ID, e.g., `NodePublisher.EFFECTOR_STYLE_ID_FAIRSKIN` |
|
|
183
|
+
| `colorStyleIntensity` | `number` | Color intensity (0.0 - 1.0) |
|
|
184
|
+
| `smoothskinIntensity` | `number` | Skin smoothing intensity (0.0 - 1.0) |
|
|
185
|
+
| `onEventCallback` | `(event) => void` | Event callback |
|
|
183
186
|
|
|
184
187
|
### AudioParam
|
|
185
188
|
|
|
186
|
-
|
|
|
189
|
+
| Prop | Type | Description |
|
|
187
190
|
|------|------|------|
|
|
188
|
-
| `codecid` | `number` |
|
|
189
|
-
| `profile` | `number` |
|
|
190
|
-
| `channels` | `number` |
|
|
191
|
-
| `samplingRate` | `number` |
|
|
192
|
-
| `bitrate` | `number` |
|
|
191
|
+
| `codecid` | `number` | Codec ID, `NodePublisher.NMC_CODEC_ID_AAC` |
|
|
192
|
+
| `profile` | `number` | Codec profile, `NodePublisher.NMC_PROFILE_AUTO` |
|
|
193
|
+
| `channels` | `number` | Number of channels, 1 or 2 |
|
|
194
|
+
| `samplingRate` | `number` | Sampling rate, e.g., 44100 |
|
|
195
|
+
| `bitrate` | `number` | Bitrate, e.g., 64000 |
|
|
193
196
|
|
|
194
197
|
### VideoParam
|
|
195
198
|
|
|
196
|
-
|
|
|
199
|
+
| Prop | Type | Description |
|
|
197
200
|
|------|------|------|
|
|
198
|
-
| `codecid` | `number` |
|
|
199
|
-
| `profile` | `number` |
|
|
200
|
-
| `width` | `number` |
|
|
201
|
-
| `height` | `number` |
|
|
202
|
-
| `fps` | `number` |
|
|
203
|
-
| `bitrate` | `number` |
|
|
201
|
+
| `codecid` | `number` | Codec ID, `NodePublisher.NMC_CODEC_ID_H264` or `NodePublisher.NMC_CODEC_ID_H265` |
|
|
202
|
+
| `profile` | `number` | Codec profile, `NodePublisher.NMC_PROFILE_AUTO` |
|
|
203
|
+
| `width` | `number` | Video width |
|
|
204
|
+
| `height` | `number` | Video height |
|
|
205
|
+
| `fps` | `number` | Frame rate |
|
|
206
|
+
| `bitrate` | `number` | Bitrate, e.g., 2000000 |
|
|
204
207
|
|
|
205
|
-
###
|
|
208
|
+
### Common Methods
|
|
206
209
|
|
|
207
210
|
```js
|
|
208
|
-
//
|
|
211
|
+
// Start streaming
|
|
209
212
|
publisherRef.current?.start(url);
|
|
210
213
|
|
|
211
|
-
//
|
|
214
|
+
// Stop streaming
|
|
212
215
|
publisherRef.current?.stop();
|
|
213
216
|
```
|
|
214
217
|
|
|
215
|
-
###
|
|
218
|
+
### Event Callback
|
|
216
219
|
|
|
217
220
|
```js
|
|
218
221
|
const handleEvent = (event: { nativeEvent: NodePlayerEventCallback }) => {
|
|
219
|
-
console.log('
|
|
220
|
-
console.log('
|
|
222
|
+
console.log('Event code:', event.nativeEvent.event);
|
|
223
|
+
console.log('Message:', event.nativeEvent.msg);
|
|
221
224
|
};
|
|
222
225
|
|
|
223
226
|
<NodePublisher
|
|
224
227
|
onEventCallback={handleEvent}
|
|
225
|
-
//
|
|
228
|
+
// ...other props
|
|
226
229
|
/>
|
|
227
230
|
```
|
|
228
231
|
|
|
229
|
-
###
|
|
232
|
+
### Permissions
|
|
230
233
|
|
|
231
|
-
|
|
234
|
+
Streaming functionality requires camera and microphone permissions. We recommend using `expo-camera` to request permissions.
|
|
232
235
|
|
|
233
|
-
|
|
236
|
+
First install the dependency:
|
|
234
237
|
|
|
235
238
|
```bash
|
|
236
239
|
npm install expo-camera
|
|
237
240
|
```
|
|
238
241
|
|
|
239
|
-
|
|
242
|
+
Configure the `expo-camera` plugin in `app.json`:
|
|
240
243
|
|
|
241
244
|
```json
|
|
242
245
|
{
|
|
@@ -253,8 +256,8 @@ npm install expo-camera
|
|
|
253
256
|
],
|
|
254
257
|
"ios": {
|
|
255
258
|
"infoPlist": {
|
|
256
|
-
"NSCameraUsageDescription": "
|
|
257
|
-
"NSMicrophoneUsageDescription": "
|
|
259
|
+
"NSCameraUsageDescription": "Camera access is required for live streaming",
|
|
260
|
+
"NSMicrophoneUsageDescription": "Microphone access is required for live streaming"
|
|
258
261
|
}
|
|
259
262
|
},
|
|
260
263
|
"android": {
|
|
@@ -268,7 +271,7 @@ npm install expo-camera
|
|
|
268
271
|
}
|
|
269
272
|
```
|
|
270
273
|
|
|
271
|
-
|
|
274
|
+
Request permissions in code:
|
|
272
275
|
|
|
273
276
|
```js
|
|
274
277
|
import { useCameraPermissions, useMicrophonePermissions } from 'expo-camera';
|
package/README_CN.md
ADDED
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
# expo-nodemediaclient
|
|
2
|
+
|
|
3
|
+
## 特性
|
|
4
|
+
- 支持iOS与Android
|
|
5
|
+
- 支持RTMP、HLS、HTTP-FLV、RTSP播放
|
|
6
|
+
- 支持H.264、H.265视频编码
|
|
7
|
+
- 支持AAC、PCM音频编码
|
|
8
|
+
- 支持硬件加速
|
|
9
|
+
- 支持低延迟播放,累积延迟消除
|
|
10
|
+
|
|
11
|
+
## 前提
|
|
12
|
+
你的Expo项目应该是使用持续的原生生成 [(CNG)](https://docs.expo.dev/workflow/continuous-native-generation/)
|
|
13
|
+
如果不是请先执行
|
|
14
|
+
```bash
|
|
15
|
+
npx expo prebuild
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## 安装
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install expo-nodemediaclient
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## 使用
|
|
25
|
+
### 注册SDK
|
|
26
|
+
android与iOS注册码不同,需要分别注册,注册码请联系[https://www.nodemedia.cn](https://www.nodemedia.cn)获取
|
|
27
|
+
|
|
28
|
+
```js
|
|
29
|
+
import { NodeMediaClient } from 'expo-nodemediaclient';
|
|
30
|
+
import { Platform } from 'react-native';
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
if (Platform.OS === 'ios') {
|
|
34
|
+
NodeMediaClient.setLicense('');
|
|
35
|
+
} else if (Platform.OS === 'android') {
|
|
36
|
+
NodeMediaClient.setLicense('');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### 播放
|
|
42
|
+
|
|
43
|
+
```js
|
|
44
|
+
import { NodePlayer, NodePlayerRef } from 'expo-nodemediaclient';
|
|
45
|
+
import { useRef, useState } from 'react';
|
|
46
|
+
|
|
47
|
+
export default function App() {
|
|
48
|
+
const [url, setUrl] = useState('rtmp://192.168.0.2/live/bbb');
|
|
49
|
+
const playerRef = useRef<NodePlayerRef>(null);
|
|
50
|
+
return (
|
|
51
|
+
<SafeAreaView style={{ flex: 1 }}>
|
|
52
|
+
<NodePlayer
|
|
53
|
+
ref={playerRef}
|
|
54
|
+
url={url}
|
|
55
|
+
bufferTime={1000}
|
|
56
|
+
scaleMode={1}
|
|
57
|
+
style={{ backgroundColor: '#000000', height: 300 }}
|
|
58
|
+
/>
|
|
59
|
+
<TextInput value={url} onChangeText={setUrl} />
|
|
60
|
+
<Button
|
|
61
|
+
title="Play"
|
|
62
|
+
onPress={() => {
|
|
63
|
+
playerRef.current?.start(url);
|
|
64
|
+
}}
|
|
65
|
+
/>
|
|
66
|
+
<Button
|
|
67
|
+
title="Stop"
|
|
68
|
+
onPress={() => {
|
|
69
|
+
playerRef.current?.stop();
|
|
70
|
+
}}
|
|
71
|
+
/>
|
|
72
|
+
</SafeAreaView>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### 组件属性
|
|
78
|
+
|
|
79
|
+
| 属性 | 类型 | 说明 |
|
|
80
|
+
|------|------|------|
|
|
81
|
+
| `url` | `string` | 播放地址 (支持 RTMP、RTSP、HLS、HTTP-FLV) |
|
|
82
|
+
| `bufferTime` | `number` | 缓冲时间 (毫秒),默认 1000 |
|
|
83
|
+
| `scaleMode` | `number` | 缩放模式,`0`=填充,`1`=适应,`2`=拉伸 |
|
|
84
|
+
| `volume` | `number` | 音量 (0.0 - 1.0),默认 1.0 |
|
|
85
|
+
| `onEventCallback` | `(event) => void` | 事件回调 |
|
|
86
|
+
|
|
87
|
+
### 常用方法
|
|
88
|
+
|
|
89
|
+
```js
|
|
90
|
+
// 开始播放
|
|
91
|
+
playerRef.current?.start(url);
|
|
92
|
+
|
|
93
|
+
// 停止播放
|
|
94
|
+
playerRef.current?.stop();
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### 事件回调
|
|
98
|
+
|
|
99
|
+
```js
|
|
100
|
+
const handleEvent = (event: { nativeEvent: NodePlayerEventCallback }) => {
|
|
101
|
+
console.log('事件码:', event.nativeEvent.event);
|
|
102
|
+
console.log('消息:', event.nativeEvent.msg);
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
<NodePlayer
|
|
106
|
+
onEventCallback={handleEvent}
|
|
107
|
+
// ...其他属性
|
|
108
|
+
/>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
## 推流
|
|
113
|
+
|
|
114
|
+
### 基本用法
|
|
115
|
+
|
|
116
|
+
```js
|
|
117
|
+
import { NodePublisher, NodePublisherRef } from 'expo-nodemediaclient';
|
|
118
|
+
import { useRef, useState } from 'react';
|
|
119
|
+
|
|
120
|
+
export default function PublisherScreen() {
|
|
121
|
+
const [url, setUrl] = useState('rtmp://192.168.0.2/live/stream');
|
|
122
|
+
const [isPublishing, setIsPublishing] = useState(false);
|
|
123
|
+
const publisherRef = useRef<NodePublisherRef>(null);
|
|
124
|
+
|
|
125
|
+
const handleTogglePublish = () => {
|
|
126
|
+
if (!isPublishing) {
|
|
127
|
+
setIsPublishing(true);
|
|
128
|
+
publisherRef.current?.start(url);
|
|
129
|
+
} else {
|
|
130
|
+
setIsPublishing(false);
|
|
131
|
+
publisherRef.current?.stop();
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
return (
|
|
136
|
+
<SafeAreaView style={{ flex: 1 }}>
|
|
137
|
+
<NodePublisher
|
|
138
|
+
ref={publisherRef}
|
|
139
|
+
style={{ flex: 1, backgroundColor: '#000' }}
|
|
140
|
+
url={url}
|
|
141
|
+
audioParam={{
|
|
142
|
+
codecid: NodePublisher.NMC_CODEC_ID_AAC,
|
|
143
|
+
profile: NodePublisher.NMC_PROFILE_AUTO,
|
|
144
|
+
channels: 2,
|
|
145
|
+
samplingRate: 44100,
|
|
146
|
+
bitrate: 64_000,
|
|
147
|
+
}}
|
|
148
|
+
videoParam={{
|
|
149
|
+
codecid: NodePublisher.NMC_CODEC_ID_H264,
|
|
150
|
+
profile: NodePublisher.NMC_PROFILE_AUTO,
|
|
151
|
+
width: 720,
|
|
152
|
+
height: 1280,
|
|
153
|
+
fps: 30,
|
|
154
|
+
bitrate: 2000_000,
|
|
155
|
+
}}
|
|
156
|
+
/>
|
|
157
|
+
<Button
|
|
158
|
+
title={isPublishing ? "停止" : "推流"}
|
|
159
|
+
onPress={handleTogglePublish}
|
|
160
|
+
/>
|
|
161
|
+
</SafeAreaView>
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### 组件属性
|
|
167
|
+
|
|
168
|
+
| 属性 | 类型 | 说明 |
|
|
169
|
+
|------|------|------|
|
|
170
|
+
| `url` | `string` | 推流地址 (RTMP) |
|
|
171
|
+
| `audioParam` | `AudioParam` | 音频编码参数 |
|
|
172
|
+
| `videoParam` | `VideoParam` | 视频编码参数 |
|
|
173
|
+
| `videoOrientation` | `number` | 视频方向,如 `NodePublisher.VIDEO_ORIENTATION_PORTRAIT` |
|
|
174
|
+
| `keyFrameInterval` | `number` | 关键帧间隔 (秒),默认 2 |
|
|
175
|
+
| `frontCamera` | `boolean` | 是否使用前置摄像头,默认 false |
|
|
176
|
+
| `cameraFrontMirror` | `boolean` | 前置摄像头是否镜像,默认 true |
|
|
177
|
+
| `volume` | `number` | 音量 (0.0 - 1.0) |
|
|
178
|
+
| `zoomRatio` | `number` | 摄像头缩放比例 (0.0 - 1.0)|
|
|
179
|
+
| `torchEnable` | `boolean` | 是否开启补光灯 |
|
|
180
|
+
| `HWAccelEnable` | `boolean` | 是否启用硬件加速,默认 true |
|
|
181
|
+
| `denoiseEnable` | `boolean` | 是否启用降噪,默认 true |
|
|
182
|
+
| `colorStyleId` | `number` | 色彩风格ID,如 `NodePublisher.EFFECTOR_STYLE_ID_FAIRSKIN` |
|
|
183
|
+
| `colorStyleIntensity` | `number` | 色彩强度 (0.0 - 1.0) |
|
|
184
|
+
| `smoothskinIntensity` | `number` | 磨皮强度 (0.0 - 1.0) |
|
|
185
|
+
| `onEventCallback` | `(event) => void` | 事件回调 |
|
|
186
|
+
|
|
187
|
+
### AudioParam
|
|
188
|
+
|
|
189
|
+
| 属性 | 类型 | 说明 |
|
|
190
|
+
|------|------|------|
|
|
191
|
+
| `codecid` | `number` | 编码ID,`NodePublisher.NMC_CODEC_ID_AAC` |
|
|
192
|
+
| `profile` | `number` | 编码profile,`NodePublisher.NMC_PROFILE_AUTO` |
|
|
193
|
+
| `channels` | `number` | 声道数,1 或 2 |
|
|
194
|
+
| `samplingRate` | `number` | 采样率,如 44100 |
|
|
195
|
+
| `bitrate` | `number` | 比特率,如 64000 |
|
|
196
|
+
|
|
197
|
+
### VideoParam
|
|
198
|
+
|
|
199
|
+
| 属性 | 类型 | 说明 |
|
|
200
|
+
|------|------|------|
|
|
201
|
+
| `codecid` | `number` | 编码ID,`NodePublisher.NMC_CODEC_ID_H264` 或 `NodePublisher.NMC_CODEC_ID_H265` |
|
|
202
|
+
| `profile` | `number` | 编码profile,`NodePublisher.NMC_PROFILE_AUTO` |
|
|
203
|
+
| `width` | `number` | 视频宽度 |
|
|
204
|
+
| `height` | `number` | 视频高度 |
|
|
205
|
+
| `fps` | `number` | 帧率 |
|
|
206
|
+
| `bitrate` | `number` | 比特率,如 2000000 |
|
|
207
|
+
|
|
208
|
+
### 常用方法
|
|
209
|
+
|
|
210
|
+
```js
|
|
211
|
+
// 开始推流
|
|
212
|
+
publisherRef.current?.start(url);
|
|
213
|
+
|
|
214
|
+
// 停止推流
|
|
215
|
+
publisherRef.current?.stop();
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### 事件回调
|
|
219
|
+
|
|
220
|
+
```js
|
|
221
|
+
const handleEvent = (event: { nativeEvent: NodePlayerEventCallback }) => {
|
|
222
|
+
console.log('事件码:', event.nativeEvent.event);
|
|
223
|
+
console.log('消息:', event.nativeEvent.msg);
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
<NodePublisher
|
|
227
|
+
onEventCallback={handleEvent}
|
|
228
|
+
// ...其他属性
|
|
229
|
+
/>
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### 权限说明
|
|
233
|
+
|
|
234
|
+
使用推流功能需要摄像头和麦克风权限,建议使用 `expo-camera` 来申请权限。
|
|
235
|
+
|
|
236
|
+
首先安装依赖:
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
npm install expo-camera
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
在 `app.json` 中配置 `expo-camera` 插件:
|
|
243
|
+
|
|
244
|
+
```json
|
|
245
|
+
{
|
|
246
|
+
"expo": {
|
|
247
|
+
"plugins": [
|
|
248
|
+
[
|
|
249
|
+
"expo-camera",
|
|
250
|
+
{
|
|
251
|
+
"cameraPermission": "Allow $(PRODUCT_NAME) to access your camera",
|
|
252
|
+
"microphonePermission": "Allow $(PRODUCT_NAME) to access your microphone",
|
|
253
|
+
"recordAudioAndroid": true
|
|
254
|
+
}
|
|
255
|
+
]
|
|
256
|
+
],
|
|
257
|
+
"ios": {
|
|
258
|
+
"infoPlist": {
|
|
259
|
+
"NSCameraUsageDescription": "需要访问摄像头以进行直播推流",
|
|
260
|
+
"NSMicrophoneUsageDescription": "需要访问麦克风以进行直播推流"
|
|
261
|
+
}
|
|
262
|
+
},
|
|
263
|
+
"android": {
|
|
264
|
+
"permissions": [
|
|
265
|
+
"android.permission.CAMERA",
|
|
266
|
+
"android.permission.RECORD_AUDIO",
|
|
267
|
+
"android.permission.INTERNET"
|
|
268
|
+
]
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
在代码中申请权限:
|
|
275
|
+
|
|
276
|
+
```js
|
|
277
|
+
import { useCameraPermissions, useMicrophonePermissions } from 'expo-camera';
|
|
278
|
+
import { useEffect } from 'react';
|
|
279
|
+
|
|
280
|
+
export default function App() {
|
|
281
|
+
const [cameraPermission, requestCameraPermission] = useCameraPermissions();
|
|
282
|
+
const [microphonePermission, requestMicrophonePermission] = useMicrophonePermissions();
|
|
283
|
+
|
|
284
|
+
useEffect(() => {
|
|
285
|
+
requestCameraPermission();
|
|
286
|
+
requestMicrophonePermission();
|
|
287
|
+
}, []);
|
|
288
|
+
|
|
289
|
+
const hasPermission = cameraPermission?.granted && microphonePermission?.granted;
|
|
290
|
+
|
|
291
|
+
// ...
|
|
292
|
+
}
|
|
293
|
+
```
|
package/android/build.gradle
CHANGED
|
@@ -33,13 +33,13 @@ if (useManagedAndroidSdkVersions) {
|
|
|
33
33
|
android {
|
|
34
34
|
namespace "expo.modules.nodemediaclient"
|
|
35
35
|
defaultConfig {
|
|
36
|
-
versionCode
|
|
37
|
-
versionName "0.2.
|
|
36
|
+
versionCode 204
|
|
37
|
+
versionName "0.2.4"
|
|
38
38
|
}
|
|
39
39
|
lintOptions {
|
|
40
40
|
abortOnError false
|
|
41
41
|
}
|
|
42
42
|
dependencies {
|
|
43
|
-
implementation 'com.github.NodeMedia:NodeMediaClient-Android:4.1.
|
|
43
|
+
implementation 'com.github.NodeMedia:NodeMediaClient-Android:4.1.2'
|
|
44
44
|
}
|
|
45
45
|
}
|