@tencent-rtc/mcp 1.2.8 → 1.2.9
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/package.json +1 -1
- package/resource/doc/native_live/android/V2TXLiveCode_api_android.md +312 -0
- package/resource/doc/native_live/android/V2TXLiveDef_api_android.md +430 -0
- package/resource/doc/native_live/android/V2TXLivePlayerObserver_api_android.md +679 -0
- package/resource/doc/native_live/android/V2TXLivePlayer_api_android.md +671 -0
- package/resource/doc/native_live/android/V2TXLivePremier_api_android.md +271 -0
- package/resource/doc/native_live/android/V2TXLivePusherObserver_api_android.md +849 -0
- package/resource/doc/native_live/android/V2TXLivePusher_api_android.md +1046 -0
- package/resource/doc/native_live/flutter/V2TXLiveCode_api_flutter.md +460 -0
- package/resource/doc/native_live/flutter/V2TXLiveDef_api_flutter.md +558 -0
- package/resource/doc/native_live/flutter/V2TXLivePlayerObserver_api_flutter.md +865 -0
- package/resource/doc/native_live/flutter/V2TXLivePlayer_api_flutter.md +657 -0
- package/resource/doc/native_live/flutter/V2TXLivePremier_api_flutter.md +437 -0
- package/resource/doc/native_live/flutter/V2TXLivePusherObserver_api_flutter.md +335 -0
- package/resource/doc/native_live/flutter/V2TXLivePusher_api_flutter.md +748 -0
- package/resource/doc/native_live/iOS/V2TXLiveCode_api_iOS.md +327 -0
- package/resource/doc/native_live/iOS/V2TXLiveDef_api_iOS.md +507 -0
- package/resource/doc/native_live/iOS/V2TXLivePlayerObserver_api_iOS.md +507 -0
- package/resource/doc/native_live/iOS/V2TXLivePlayer_api_iOS.md +659 -0
- package/resource/doc/native_live/iOS/V2TXLivePremier_api_iOS.md +284 -0
- package/resource/doc/native_live/iOS/V2TXLivePusherObserver_api_iOS.md +814 -0
- package/resource/doc/native_live/iOS/V2TXLivePusher_api_iOS.md +1000 -0
- package/tools/definitions/get_native_live_api_def.js +23 -0
- package/tools/definitions/get_native_live_api_def.js.map +1 -0
- package/tools/index.js +4 -0
- package/tools/index.js.map +1 -1
- package/tools/native_live/get-native-live-api.js +31 -0
- package/tools/native_live/get-native-live-api.js.map +1 -0
- package/utils/report-cls-client.js +1 -1
- package/utils/report-es-client.js +1 -1
|
@@ -0,0 +1,849 @@
|
|
|
1
|
+
# Tencent Cloud Live Streaming SDK V2TXLivePusherObserver Live Stream Pusher Callback Interface
|
|
2
|
+
|
|
3
|
+
## Feature Overview
|
|
4
|
+
|
|
5
|
+
`V2TXLivePusherObserver` provides callback methods for the stream pusher in the Tencent Cloud Live Streaming SDK. Implement this interface to receive real-time status updates and event notifications from the stream pusher. With these callbacks, you can monitor streaming health, handle events, collect statistics, and manage advanced features.
|
|
6
|
+
|
|
7
|
+
**File Path**: `com/tencent/live2/V2TXLivePusherObserver.java`
|
|
8
|
+
|
|
9
|
+
**Core Features**:
|
|
10
|
+
- Stream pusher status monitoring (errors, warnings, connection updates)
|
|
11
|
+
- Audio and video capture event notifications
|
|
12
|
+
- Streaming statistics and performance metrics
|
|
13
|
+
- Custom audio and video processing
|
|
14
|
+
- Local recording management
|
|
15
|
+
- Screen sharing status monitoring
|
|
16
|
+
- Cloud stream mixing (MixTranscoding) event handling
|
|
17
|
+
|
|
18
|
+
## Callback Method Details
|
|
19
|
+
|
|
20
|
+
### 1. Error and Warning Callbacks
|
|
21
|
+
|
|
22
|
+
#### onError() - Stream Pusher Error Notification
|
|
23
|
+
```java
|
|
24
|
+
public void onError(int code, String msg, Bundle extraInfo)
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**Purpose**: Notifies when the stream pusher encounters an error.
|
|
28
|
+
|
|
29
|
+
**Parameters**:
|
|
30
|
+
- `code`: Error code. See `V2TXLiveCode` enum.
|
|
31
|
+
- `msg`: Error description.
|
|
32
|
+
- `extraInfo`: Additional details about the error.
|
|
33
|
+
|
|
34
|
+
**Typical Scenarios**:
|
|
35
|
+
- Network connection failure
|
|
36
|
+
- Invalid stream URL
|
|
37
|
+
- Encoder errors
|
|
38
|
+
- Streaming permission issues
|
|
39
|
+
|
|
40
|
+
**Example**:
|
|
41
|
+
```java
|
|
42
|
+
pusher.setObserver(new V2TXLivePusherObserver() {
|
|
43
|
+
@Override
|
|
44
|
+
public void onError(int code, String msg, Bundle extraInfo) {
|
|
45
|
+
switch (code) {
|
|
46
|
+
case V2TXLIVE_ERROR_REQUEST_TIMEOUT:
|
|
47
|
+
Log.e(TAG, "Stream connection timed out");
|
|
48
|
+
break;
|
|
49
|
+
case V2TXLIVE_ERROR_SERVER_PROCESS_FAILED:
|
|
50
|
+
Log.e(TAG, "Stream server processing failed");
|
|
51
|
+
break;
|
|
52
|
+
default:
|
|
53
|
+
Log.e(TAG, "Other error: " + msg);
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
#### onWarning() - Stream Pusher Warning Notification
|
|
61
|
+
```java
|
|
62
|
+
public void onWarning(int code, String msg, Bundle extraInfo)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**Purpose**: Notifies when the stream pusher encounters a warning.
|
|
66
|
+
|
|
67
|
+
**Parameters**:
|
|
68
|
+
- `code`: Warning code. See `V2TXLiveCode` enum.
|
|
69
|
+
- `msg`: Warning description.
|
|
70
|
+
- `extraInfo`: Additional details.
|
|
71
|
+
|
|
72
|
+
**Typical Scenarios**:
|
|
73
|
+
- Network quality degradation
|
|
74
|
+
- Encoding delays
|
|
75
|
+
- Buffer underruns
|
|
76
|
+
|
|
77
|
+
**Example**:
|
|
78
|
+
```java
|
|
79
|
+
pusher.setObserver(new V2TXLivePusherObserver() {
|
|
80
|
+
@Override
|
|
81
|
+
public void onWarning(int code, String msg, Bundle extraInfo) {
|
|
82
|
+
switch (code) {
|
|
83
|
+
case V2TXLiveCode.V2TXLIVE_WARNING_CURRENT_ENCODE_TYPE_CHANGED:
|
|
84
|
+
int codec_type = extraInfo.getInt("codec_type");
|
|
85
|
+
if (codec_type == 0) {
|
|
86
|
+
Log.w(TAG, "Encoder switched to h.264, " + msg);
|
|
87
|
+
} else if (codec_type == 1) {
|
|
88
|
+
Log.w(TAG, "Encoder switched to h.265, " + msg);
|
|
89
|
+
}
|
|
90
|
+
break;
|
|
91
|
+
case V2TXLiveCode.V2TXLIVE_WARNING_NETWORK_BUSY:
|
|
92
|
+
Log.w(TAG, "Network busy, " + msg);
|
|
93
|
+
break;
|
|
94
|
+
case V2TXLiveCode.V2TXLIVE_WARNING_CAMERA_START_FAILED:
|
|
95
|
+
Log.w(TAG, "Camera failed to start, " + msg);
|
|
96
|
+
break;
|
|
97
|
+
case V2TXLiveCode.V2TXLIVE_WARNING_CAMERA_NO_PERMISSION:
|
|
98
|
+
Log.w(TAG, "Camera permission denied, " + msg);
|
|
99
|
+
break;
|
|
100
|
+
case V2TXLiveCode.V2TXLIVE_WARNING_CAMERA_OCCUPIED:
|
|
101
|
+
Log.w(TAG, "Camera is occupied, " + msg);
|
|
102
|
+
break;
|
|
103
|
+
case V2TXLIVE_WARNING_SCREEN_CAPTURE_START_FAILED:
|
|
104
|
+
Log.w(TAG, "Screen capture failed to start, " + msg);
|
|
105
|
+
break;
|
|
106
|
+
case V2TXLIVE_WARNING_SCREEN_CAPTURE_NOT_SUPPORTED:
|
|
107
|
+
Log.w(TAG, "Screen capture not supported, " + msg);
|
|
108
|
+
break;
|
|
109
|
+
case V2TXLIVE_WARNING_SCREEN_CAPTURE_INTERRUPTED:
|
|
110
|
+
Log.w(TAG, "Screen capture interrupted, " + msg);
|
|
111
|
+
break;
|
|
112
|
+
case V2TXLIVE_WARNING_MICROPHONE_START_FAILED:
|
|
113
|
+
Log.w(TAG, "Microphone failed to start, " + msg);
|
|
114
|
+
break;
|
|
115
|
+
case V2TXLIVE_WARNING_MICROPHONE_NO_PERMISSION:
|
|
116
|
+
Log.w(TAG, "Microphone permission denied, " + msg);
|
|
117
|
+
break;
|
|
118
|
+
case V2TXLIVE_WARNING_MICROPHONE_OCCUPIED:
|
|
119
|
+
Log.w(TAG, "Microphone is occupied, " + msg);
|
|
120
|
+
break;
|
|
121
|
+
default:
|
|
122
|
+
Log.w(TAG, "Other warning: " + msg);
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### 2. Connection and Status Callbacks
|
|
130
|
+
|
|
131
|
+
#### onPushStatusUpdate() - Stream Pusher Connection Status
|
|
132
|
+
```java
|
|
133
|
+
public void onPushStatusUpdate(V2TXLivePushStatus status, String msg, Bundle extraInfo)
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
**Purpose**: Reports changes in the stream pusher's connection status.
|
|
137
|
+
|
|
138
|
+
**Parameters**:
|
|
139
|
+
- `status`: Connection status (`V2TXLivePushStatus`)
|
|
140
|
+
- `msg`: Status details
|
|
141
|
+
- `extraInfo`: Additional information
|
|
142
|
+
|
|
143
|
+
**Status Values**:
|
|
144
|
+
- `V2TXLivePushStatus.V2TXLivePushStatusDisconnected`: Disconnected
|
|
145
|
+
- `V2TXLivePushStatus.V2TXLivePushStatusConnecting`: Connecting
|
|
146
|
+
- `V2TXLivePushStatus.V2TXLivePushStatusConnectSuccess`: Connected
|
|
147
|
+
- `V2TXLivePushStatus.V2TXLivePushStatusReconnecting`: Reconnecting
|
|
148
|
+
|
|
149
|
+
**Typical Scenarios**:
|
|
150
|
+
- Real-time streaming status monitoring
|
|
151
|
+
- Connection retry logic
|
|
152
|
+
- UI status updates
|
|
153
|
+
|
|
154
|
+
**Example**:
|
|
155
|
+
```java
|
|
156
|
+
pusher.setObserver(new V2TXLivePusherObserver() {
|
|
157
|
+
@Override
|
|
158
|
+
public void onPushStatusUpdate(V2TXLivePushStatus status, String msg, Bundle extraInfo) {
|
|
159
|
+
switch (status) {
|
|
160
|
+
case V2TXLivePushStatusConnectSuccess:
|
|
161
|
+
Log.i(TAG, "Stream connected successfully");
|
|
162
|
+
break;
|
|
163
|
+
case V2TXLivePushStatusConnecting:
|
|
164
|
+
Log.i(TAG, "Connecting to stream...");
|
|
165
|
+
break;
|
|
166
|
+
case V2TXLivePushStatusReconnecting:
|
|
167
|
+
Log.w(TAG, "Reconnecting to stream...");
|
|
168
|
+
break;
|
|
169
|
+
case V2TXLivePushStatusDisconnected:
|
|
170
|
+
Log.e(TAG, "Stream disconnected");
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### 3. Capture Event Callbacks
|
|
178
|
+
|
|
179
|
+
#### onCaptureFirstAudioFrame() - First Audio Frame Notification
|
|
180
|
+
```java
|
|
181
|
+
public void onCaptureFirstAudioFrame()
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
**Purpose**: Notifies when the first audio frame is captured.
|
|
185
|
+
|
|
186
|
+
**Typical Scenarios**:
|
|
187
|
+
- Confirm audio capture started
|
|
188
|
+
- Update audio UI status
|
|
189
|
+
- Initialize audio processing
|
|
190
|
+
|
|
191
|
+
**Example**:
|
|
192
|
+
```java
|
|
193
|
+
pusher.setObserver(new V2TXLivePusherObserver() {
|
|
194
|
+
@Override
|
|
195
|
+
public void onCaptureFirstAudioFrame() {
|
|
196
|
+
Log.i(TAG, "Audio capture started. First audio frame received.");
|
|
197
|
+
// Update UI to indicate audio capture
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
#### onCaptureFirstVideoFrame() - First Video Frame Notification
|
|
203
|
+
```java
|
|
204
|
+
public void onCaptureFirstVideoFrame()
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
**Purpose**: Notifies when the first video frame is captured.
|
|
208
|
+
|
|
209
|
+
**Typical Scenarios**:
|
|
210
|
+
- Confirm video capture started
|
|
211
|
+
- Update video UI status
|
|
212
|
+
- Initialize video processing
|
|
213
|
+
|
|
214
|
+
**Example**:
|
|
215
|
+
```java
|
|
216
|
+
pusher.setObserver(new V2TXLivePusherObserver() {
|
|
217
|
+
@Override
|
|
218
|
+
public void onCaptureFirstVideoFrame() {
|
|
219
|
+
Log.i(TAG, "Video capture started. First video frame received.");
|
|
220
|
+
// Update UI to indicate video capture
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
#### onMicrophoneVolumeUpdate() - Microphone Capture Volume
|
|
226
|
+
```java
|
|
227
|
+
public void onMicrophoneVolumeUpdate(int volume)
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
**Purpose**: Reports real-time microphone capture volume.
|
|
231
|
+
|
|
232
|
+
**Parameters**:
|
|
233
|
+
- `volume`: Volume level (0-100)
|
|
234
|
+
|
|
235
|
+
**Prerequisite**: Call `enableVolumeEvaluation()` to receive volume updates.
|
|
236
|
+
|
|
237
|
+
**Typical Scenarios**:
|
|
238
|
+
- Display live volume levels
|
|
239
|
+
- Animate audio waveform
|
|
240
|
+
- Detect mute state
|
|
241
|
+
|
|
242
|
+
**Example**:
|
|
243
|
+
```java
|
|
244
|
+
pusher.setObserver(new V2TXLivePusherObserver() {
|
|
245
|
+
@Override
|
|
246
|
+
public void onMicrophoneVolumeUpdate(int volume) {
|
|
247
|
+
// Update volume indicator
|
|
248
|
+
|
|
249
|
+
// Detect mute state
|
|
250
|
+
if (volume < 5) {
|
|
251
|
+
Log.d(TAG, "Mute detected");
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
// Enable volume evaluation
|
|
256
|
+
pusher.enableVolumeEvaluation(300);
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### 4. Audio/Video Data Processing Callbacks
|
|
260
|
+
|
|
261
|
+
#### onProcessAudioFrame() - Audio Frame Processing
|
|
262
|
+
```java
|
|
263
|
+
public void onProcessAudioFrame(V2TXLiveDef.V2TXLiveAudioFrame frame)
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
**Purpose**: Provides locally captured audio data after pre-processing, audio effects, and background music mixing.
|
|
267
|
+
|
|
268
|
+
**Parameters**:
|
|
269
|
+
- `frame`: PCM audio data frame
|
|
270
|
+
|
|
271
|
+
**Technical Details**:
|
|
272
|
+
- Frame duration: 0.02s (20ms)
|
|
273
|
+
- Format: PCM
|
|
274
|
+
- Byte length: `Sample rate × frame duration × Audio Channel count × sample bit width`
|
|
275
|
+
- Default: 48000 sample rate, mono, 16-bit = 1920 bytes
|
|
276
|
+
|
|
277
|
+
**Important Notes**:
|
|
278
|
+
1. Avoid time-consuming operations in this callback.
|
|
279
|
+
2. The SDK processes one audio frame every 20ms; exceeding this time may cause audio issues.
|
|
280
|
+
3. Audio data is readable and writable; you can modify it synchronously but must keep processing time under control.
|
|
281
|
+
|
|
282
|
+
**Typical Scenarios**:
|
|
283
|
+
- Custom audio processing
|
|
284
|
+
- Applying audio effects
|
|
285
|
+
- Audio analysis and statistics
|
|
286
|
+
|
|
287
|
+
**Example**:
|
|
288
|
+
```java
|
|
289
|
+
pusher.setObserver(new V2TXLivePusherObserver() {
|
|
290
|
+
@Override
|
|
291
|
+
public void onProcessAudioFrame(V2TXLiveDef.V2TXLiveAudioFrame frame) {
|
|
292
|
+
// Apply custom audio processing (e.g., reverb)
|
|
293
|
+
|
|
294
|
+
// Track processed frames
|
|
295
|
+
audioFrameCount++;
|
|
296
|
+
if (audioFrameCount % 50 == 0) {
|
|
297
|
+
Log.d(TAG, "Processed audio frames: " + audioFrameCount);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
#### onProcessVideoFrame() - Custom Video Frame Processing
|
|
304
|
+
```java
|
|
305
|
+
public int onProcessVideoFrame(V2TXLiveVideoFrame srcFrame, V2TXLiveVideoFrame dstFrame)
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
**Purpose**: Enables custom video frame processing.
|
|
309
|
+
|
|
310
|
+
**Parameters**:
|
|
311
|
+
- `srcFrame`: Original video frame
|
|
312
|
+
- `dstFrame`: Processed video frame
|
|
313
|
+
|
|
314
|
+
**Return Value**: 0 for success
|
|
315
|
+
|
|
316
|
+
**Prerequisite**: Call `enableCustomVideoProcess()` to enable custom video processing.
|
|
317
|
+
|
|
318
|
+
**Usage Examples**:
|
|
319
|
+
|
|
320
|
+
**Case 1: Beauty component generates a new texture**
|
|
321
|
+
```java
|
|
322
|
+
@Override
|
|
323
|
+
public void onGLContextCreated() {
|
|
324
|
+
mFURenderer.onSurfaceCreated();
|
|
325
|
+
mFURenderer.setUseTexAsync(true);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
@Override
|
|
329
|
+
public int onProcessVideoFrame(V2TXLiveVideoFrame srcFrame, V2TXLiveVideoFrame dstFrame) {
|
|
330
|
+
dstFrame.texture.textureId = mFURenderer.onDrawFrameSingleInput(
|
|
331
|
+
srcFrame.texture.textureId, srcFrame.width, srcFrame.height);
|
|
332
|
+
return 0;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
@Override
|
|
336
|
+
public void onGLContextDestroyed() {
|
|
337
|
+
mFURenderer.onSurfaceDestroyed();
|
|
338
|
+
}
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
**Case 2: Beauty component does not generate a new texture**
|
|
342
|
+
```java
|
|
343
|
+
int onProcessVideoFrame(V2TXLiveVideoFrame srcFrame, V2TXLiveVideoFrame dstFrame) {
|
|
344
|
+
thirdparty_process(srcFrame.texture.textureId, srcFrame.width, srcFrame.height, dstFrame.texture.textureId);
|
|
345
|
+
return 0;
|
|
346
|
+
}
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
### 5. OpenGL Environment Callbacks
|
|
350
|
+
|
|
351
|
+
#### onGLContextCreated() - OpenGL Environment Created
|
|
352
|
+
```java
|
|
353
|
+
public void onGLContextCreated()
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
**Purpose**: Notifies when the SDK's internal OpenGL environment is created.
|
|
357
|
+
|
|
358
|
+
**Typical Scenarios**:
|
|
359
|
+
- Initialize beauty components
|
|
360
|
+
- Set up video processing modules
|
|
361
|
+
- Create OpenGL resources
|
|
362
|
+
|
|
363
|
+
**Example**:
|
|
364
|
+
```java
|
|
365
|
+
pusher.setObserver(new V2TXLivePusherObserver() {
|
|
366
|
+
@Override
|
|
367
|
+
public void onGLContextCreated() {
|
|
368
|
+
Log.i(TAG, "OpenGL environment created");
|
|
369
|
+
// Initialize beauty component
|
|
370
|
+
if (mBeautyProcessor != null) {
|
|
371
|
+
mBeautyProcessor.initGL();
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
});
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
#### onGLContextDestroyed() - OpenGL Environment Destroyed
|
|
378
|
+
```java
|
|
379
|
+
public void onGLContextDestroyed()
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
**Purpose**: Notifies when the SDK's internal OpenGL environment is destroyed.
|
|
383
|
+
|
|
384
|
+
**Typical Scenarios**:
|
|
385
|
+
- Clean up beauty components
|
|
386
|
+
- Release video processing modules
|
|
387
|
+
- Free OpenGL resources
|
|
388
|
+
|
|
389
|
+
**Example**:
|
|
390
|
+
```java
|
|
391
|
+
pusher.setObserver(new V2TXLivePusherObserver() {
|
|
392
|
+
@Override
|
|
393
|
+
public void onGLContextDestroyed() {
|
|
394
|
+
Log.i(TAG, "OpenGL environment destroyed");
|
|
395
|
+
// Release beauty component resources
|
|
396
|
+
if (mBeautyProcessor != null) {
|
|
397
|
+
mBeautyProcessor.releaseGL();
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
});
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
### 6. Statistics and Monitoring Callbacks
|
|
404
|
+
|
|
405
|
+
#### onStatisticsUpdate() - Streaming Statistics
|
|
406
|
+
```java
|
|
407
|
+
public void onStatisticsUpdate(V2TXLivePusherStatistics statistics)
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
**Purpose**: Provides real-time streaming statistics every 2 seconds.
|
|
411
|
+
|
|
412
|
+
**Parameters**:
|
|
413
|
+
- `statistics`: Streaming statistics (`V2TXLivePusherStatistics`)
|
|
414
|
+
|
|
415
|
+
**Included Metrics**:
|
|
416
|
+
- Video resolution (width/height)
|
|
417
|
+
- Frame rate and bitrate
|
|
418
|
+
- Network status
|
|
419
|
+
- Buffer size
|
|
420
|
+
- Streaming latency
|
|
421
|
+
|
|
422
|
+
**Typical Scenarios**:
|
|
423
|
+
- Monitor streaming quality
|
|
424
|
+
- Analyze performance
|
|
425
|
+
- Collect user experience metrics
|
|
426
|
+
|
|
427
|
+
**Example**:
|
|
428
|
+
```java
|
|
429
|
+
pusher.setObserver(new V2TXLivePusherObserver() {
|
|
430
|
+
@Override
|
|
431
|
+
public void onStatisticsUpdate(V2TXLivePusherStatistics statistics) {
|
|
432
|
+
Log.d(TAG, "Streaming stats - FPS: " + statistics.fps +
|
|
433
|
+
", Bitrate: " + statistics.videoBitrate +
|
|
434
|
+
", Resolution: " + statistics.width + "x" + statistics.height);
|
|
435
|
+
|
|
436
|
+
// Update streaming quality display
|
|
437
|
+
}
|
|
438
|
+
});
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
### 7. Advanced Feature Callbacks
|
|
442
|
+
|
|
443
|
+
#### onSnapshotComplete() - Snapshot Completion
|
|
444
|
+
```java
|
|
445
|
+
public void onSnapshotComplete(Bitmap image)
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
**Purpose**: Notifies when a video snapshot is captured.
|
|
449
|
+
|
|
450
|
+
**Parameters**:
|
|
451
|
+
- `image`: Bitmap of the captured frame
|
|
452
|
+
|
|
453
|
+
**Typical Scenarios**:
|
|
454
|
+
- Save video snapshots
|
|
455
|
+
- Share frames
|
|
456
|
+
- Preserve evidence
|
|
457
|
+
|
|
458
|
+
**Example**:
|
|
459
|
+
```java
|
|
460
|
+
pusher.setObserver(new V2TXLivePusherObserver() {
|
|
461
|
+
@Override
|
|
462
|
+
public void onSnapshotComplete(Bitmap image) {
|
|
463
|
+
Log.i(TAG, "Snapshot complete, image size: " + image.getWidth() + "x" + image.getHeight());
|
|
464
|
+
|
|
465
|
+
// Save to album
|
|
466
|
+
|
|
467
|
+
// Show snapshot preview
|
|
468
|
+
}
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
// Trigger snapshot
|
|
472
|
+
pusher.snapshot();
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
#### onSetMixTranscodingConfig() - Cloud Stream Mixing (MixTranscoding)
|
|
476
|
+
```java
|
|
477
|
+
public void onSetMixTranscodingConfig(int code, String msg)
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
**Purpose**: Reports the result of setting cloud stream mixing (MixTranscoding) parameters. Supported only by RTC protocol.
|
|
481
|
+
|
|
482
|
+
**Parameters**:
|
|
483
|
+
- `code`: 0 for success, other values indicate failure
|
|
484
|
+
- `msg`: Error details
|
|
485
|
+
|
|
486
|
+
**Related API**: `setMixTranscodingConfig()`
|
|
487
|
+
|
|
488
|
+
**Typical Scenarios**:
|
|
489
|
+
- Monitor MixTranscoding status
|
|
490
|
+
- Handle MixTranscoding failures
|
|
491
|
+
- Track multi-stream composition
|
|
492
|
+
|
|
493
|
+
**Example**:
|
|
494
|
+
```java
|
|
495
|
+
pusher.setObserver(new V2TXLivePusherObserver() {
|
|
496
|
+
@Override
|
|
497
|
+
public void onSetMixTranscodingConfig(int code, String msg) {
|
|
498
|
+
if (code == 0) {
|
|
499
|
+
Log.i(TAG, "Cloud stream mixing (MixTranscoding) configuration succeeded");
|
|
500
|
+
} else {
|
|
501
|
+
Log.e(TAG, "Cloud stream mixing (MixTranscoding) configuration failed: " + msg);
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
});
|
|
505
|
+
|
|
506
|
+
// Configure cloud stream mixing
|
|
507
|
+
V2TXLiveDef.V2TXLiveTranscodingConfig config = new V2TXLiveDef.V2TXLiveTranscodingConfig();
|
|
508
|
+
// ... configure mixing parameters
|
|
509
|
+
pusher.setMixTranscodingConfig(config);
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
#### onVoiceActivityDetectionUpdate() - Voice Activity Detection
|
|
513
|
+
```java
|
|
514
|
+
public void onVoiceActivityDetectionUpdate(boolean active)
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
**Purpose**: Reports voice activity detection status.
|
|
518
|
+
|
|
519
|
+
**Parameters**:
|
|
520
|
+
- `active`: True if voice activity is detected, false otherwise
|
|
521
|
+
|
|
522
|
+
**Prerequisite**: Call `enableVoiceActivityDetection()` to enable this feature.
|
|
523
|
+
|
|
524
|
+
**Typical Scenarios**:
|
|
525
|
+
- Voice activity detection
|
|
526
|
+
- Smart mute handling
|
|
527
|
+
- Voice recognition
|
|
528
|
+
|
|
529
|
+
**Example**:
|
|
530
|
+
```java
|
|
531
|
+
pusher.setObserver(new V2TXLivePusherObserver() {
|
|
532
|
+
@Override
|
|
533
|
+
public void onVoiceActivityDetectionUpdate(boolean active) {
|
|
534
|
+
if (active) {
|
|
535
|
+
Log.i(TAG, "Voice activity detected");
|
|
536
|
+
// Show speaking indicator
|
|
537
|
+
showSpeakingIndicator(true);
|
|
538
|
+
} else {
|
|
539
|
+
Log.i(TAG, "Voice activity stopped");
|
|
540
|
+
// Hide speaking indicator
|
|
541
|
+
showSpeakingIndicator(false);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
});
|
|
545
|
+
|
|
546
|
+
// Enable voice activity detection
|
|
547
|
+
pusher.enableVoiceActivityDetection(true);
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
### 8. Screen Sharing Callbacks
|
|
551
|
+
|
|
552
|
+
#### onScreenCaptureStarted() - Screen Sharing Started
|
|
553
|
+
```java
|
|
554
|
+
public void onScreenCaptureStarted()
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
**Purpose**: Notifies when screen sharing starts.
|
|
558
|
+
|
|
559
|
+
**Typical Scenarios**:
|
|
560
|
+
- Monitor screen sharing status
|
|
561
|
+
- Update UI
|
|
562
|
+
- Confirm permissions
|
|
563
|
+
|
|
564
|
+
**Example**:
|
|
565
|
+
```java
|
|
566
|
+
pusher.setObserver(new V2TXLivePusherObserver() {
|
|
567
|
+
@Override
|
|
568
|
+
public void onScreenCaptureStarted() {
|
|
569
|
+
Log.i(TAG, "Screen sharing started");
|
|
570
|
+
// Update UI to show screen sharing status
|
|
571
|
+
updateScreenShareStatus(true);
|
|
572
|
+
}
|
|
573
|
+
});
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
#### onScreenCaptureStopped() - Screen Sharing Stopped
|
|
577
|
+
```java
|
|
578
|
+
public void onScreenCaptureStopped(int reason)
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
**Purpose**: Notifies when screen sharing stops.
|
|
582
|
+
|
|
583
|
+
**Parameters**:
|
|
584
|
+
- `reason`: Reason code
|
|
585
|
+
- `0`: User stopped manually
|
|
586
|
+
- `1`: Interrupted by system (iOS), window closed (Mac/Windows)
|
|
587
|
+
- `2`: Display status changed (Windows only)
|
|
588
|
+
|
|
589
|
+
**Typical Scenarios**:
|
|
590
|
+
- Handle screen sharing exceptions
|
|
591
|
+
- Restore UI status
|
|
592
|
+
- Handle permission loss
|
|
593
|
+
|
|
594
|
+
**Example**:
|
|
595
|
+
```java
|
|
596
|
+
pusher.setObserver(new V2TXLivePusherObserver() {
|
|
597
|
+
@Override
|
|
598
|
+
public void onScreenCaptureStopped(int reason) {
|
|
599
|
+
Log.i(TAG, "Screen sharing stopped, reason: " + reason);
|
|
600
|
+
|
|
601
|
+
switch (reason) {
|
|
602
|
+
case 0:
|
|
603
|
+
Log.i(TAG, "User manually stopped screen sharing");
|
|
604
|
+
break;
|
|
605
|
+
case 1:
|
|
606
|
+
Log.w(TAG, "Screen sharing interrupted by system");
|
|
607
|
+
break;
|
|
608
|
+
case 2:
|
|
609
|
+
Log.w(TAG, "Display status change caused screen sharing to stop");
|
|
610
|
+
break;
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
// Update UI to show screen sharing status
|
|
614
|
+
updateScreenShareStatus(false);
|
|
615
|
+
}
|
|
616
|
+
});
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
### 9. Local Recording Callbacks
|
|
620
|
+
|
|
621
|
+
#### onLocalRecordBegin() - Local Recording Started
|
|
622
|
+
```java
|
|
623
|
+
public void onLocalRecordBegin(int code, String storagePath)
|
|
624
|
+
```
|
|
625
|
+
|
|
626
|
+
**Purpose**: Notifies when a local recording task starts.
|
|
627
|
+
|
|
628
|
+
**Parameters**:
|
|
629
|
+
- `code`: Status code
|
|
630
|
+
- `0`: Recording started successfully
|
|
631
|
+
- `-1`: Internal error
|
|
632
|
+
- `-2`: Invalid file extension
|
|
633
|
+
- `-6`: Recording already started; stop first
|
|
634
|
+
- `-7`: File already exists; delete first
|
|
635
|
+
- `-8`: No write permission for directory
|
|
636
|
+
- `storagePath`: Recording file path
|
|
637
|
+
|
|
638
|
+
**Related API**: `startLocalRecording()`
|
|
639
|
+
|
|
640
|
+
**Example**:
|
|
641
|
+
```java
|
|
642
|
+
pusher.setObserver(new V2TXLivePusherObserver() {
|
|
643
|
+
@Override
|
|
644
|
+
public void onLocalRecordBegin(int code, String storagePath) {
|
|
645
|
+
if (code == 0) {
|
|
646
|
+
Log.i(TAG, "Local recording started, file path: " + storagePath);
|
|
647
|
+
// Show recording status
|
|
648
|
+
showRecordingStatus(true);
|
|
649
|
+
} else {
|
|
650
|
+
Log.e(TAG, "Failed to start local recording, error code: " + code);
|
|
651
|
+
// Handle recording start failure
|
|
652
|
+
handleRecordingError(code);
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
});
|
|
656
|
+
```
|
|
657
|
+
|
|
658
|
+
#### onLocalRecording() - Local Recording Progress
|
|
659
|
+
```java
|
|
660
|
+
public void onLocalRecording(long durationMs, String storagePath)
|
|
661
|
+
```
|
|
662
|
+
|
|
663
|
+
**Purpose**: Reports recording progress during an active recording task.
|
|
664
|
+
|
|
665
|
+
**Parameters**:
|
|
666
|
+
- `durationMs`: Recording duration (milliseconds)
|
|
667
|
+
- `storagePath`: Recording file path
|
|
668
|
+
|
|
669
|
+
**Default Behavior**: This event only triggers if a callback interval is set when calling `startLocalRecording()`.
|
|
670
|
+
|
|
671
|
+
**Typical Scenarios**:
|
|
672
|
+
- Display recording progress
|
|
673
|
+
- Enforce recording duration limits
|
|
674
|
+
- Monitor recording status
|
|
675
|
+
|
|
676
|
+
**Example**:
|
|
677
|
+
```java
|
|
678
|
+
pusher.setObserver(new V2TXLivePusherObserver() {
|
|
679
|
+
@Override
|
|
680
|
+
public void onLocalRecording(long durationMs, String storagePath) {
|
|
681
|
+
// Update recording progress display
|
|
682
|
+
updateRecordingProgress(durationMs);
|
|
683
|
+
|
|
684
|
+
// Stop recording if duration limit reached (e.g., 1 hour)
|
|
685
|
+
if (durationMs >= 3600000) {
|
|
686
|
+
Log.w(TAG, "Recording duration limit reached, stopping recording automatically");
|
|
687
|
+
pusher.stopLocalRecording();
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
});
|
|
691
|
+
```
|
|
692
|
+
|
|
693
|
+
#### onLocalRecordComplete() - Local Recording Completed
|
|
694
|
+
```java
|
|
695
|
+
public void onLocalRecordComplete(int code, String storagePath)
|
|
696
|
+
```
|
|
697
|
+
|
|
698
|
+
**Purpose**: Notifies when a recording task ends.
|
|
699
|
+
|
|
700
|
+
**Parameters**:
|
|
701
|
+
- `code`: Status code
|
|
702
|
+
- `0`: Recording ended successfully
|
|
703
|
+
- `-1`: Recording failed
|
|
704
|
+
- `-2`: Ended due to resolution/orientation change
|
|
705
|
+
- `-3`: Duration too short or no video/audio captured
|
|
706
|
+
- `storagePath`: Recording file path
|
|
707
|
+
|
|
708
|
+
**Related API**: `stopLocalRecording()`
|
|
709
|
+
|
|
710
|
+
**Example**:
|
|
711
|
+
```java
|
|
712
|
+
pusher.setObserver(new V2TXLivePusherObserver() {
|
|
713
|
+
@Override
|
|
714
|
+
public void onLocalRecordComplete(int code, String storagePath) {
|
|
715
|
+
if (code == 0) {
|
|
716
|
+
Log.i(TAG, "Local recording completed, file path: " + storagePath);
|
|
717
|
+
// Show recording completion status
|
|
718
|
+
showRecordingComplete(storagePath);
|
|
719
|
+
} else {
|
|
720
|
+
Log.w(TAG, "Local recording ended abnormally, status code: " + code);
|
|
721
|
+
// Handle abnormal recording end
|
|
722
|
+
handleRecordingAbnormalEnd(code);
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
});
|
|
726
|
+
```
|
|
727
|
+
|
|
728
|
+
## Code Examples
|
|
729
|
+
|
|
730
|
+
### Basic Stream Pusher Callback Implementation
|
|
731
|
+
```java
|
|
732
|
+
public class MyPusherObserver extends V2TXLivePusherObserver {
|
|
733
|
+
@Override
|
|
734
|
+
public void onError(int code, String msg, Bundle extraInfo) {
|
|
735
|
+
// Handle streaming errors
|
|
736
|
+
Log.e("PusherError", "Error code: " + code + ", Error message: " + msg);
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
@Override
|
|
740
|
+
public void onPushStatusUpdate(V2TXLivePushStatus status, String msg, Bundle extraInfo) {
|
|
741
|
+
// Monitor streaming status
|
|
742
|
+
switch (status) {
|
|
743
|
+
case CONNECT_SUCCESS:
|
|
744
|
+
Log.i("Pusher", "Stream connected successfully");
|
|
745
|
+
break;
|
|
746
|
+
case DISCONNECTED:
|
|
747
|
+
Log.w("Pusher", "Stream disconnected");
|
|
748
|
+
break;
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
@Override
|
|
753
|
+
public void onCaptureFirstVideoFrame() {
|
|
754
|
+
// Video capture started
|
|
755
|
+
Log.i("Pusher", "Video capture started");
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
@Override
|
|
759
|
+
public void onStatisticsUpdate(V2TXLivePusherStatistics statistics) {
|
|
760
|
+
// Update streaming statistics
|
|
761
|
+
Log.d("PusherStats", "FPS: " + statistics.fps + ", Bitrate: " + statistics.bitrate);
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
// Set callback observer
|
|
766
|
+
V2TXLivePusher pusher = new V2TXLivePusherImpl(context);
|
|
767
|
+
pusher.setObserver(new MyPusherObserver());
|
|
768
|
+
```
|
|
769
|
+
|
|
770
|
+
### Custom Video Processing Example
|
|
771
|
+
```java
|
|
772
|
+
public class VideoProcessorObserver extends V2TXLivePusherObserver {
|
|
773
|
+
private BeautyProcessor mBeautyProcessor;
|
|
774
|
+
|
|
775
|
+
@Override
|
|
776
|
+
public void onGLContextCreated() {
|
|
777
|
+
// Initialize beauty component when OpenGL environment is created
|
|
778
|
+
mBeautyProcessor = new BeautyProcessor();
|
|
779
|
+
mBeautyProcessor.init();
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
@Override
|
|
783
|
+
public int onProcessVideoFrame(V2TXLiveVideoFrame srcFrame, V2TXLiveVideoFrame dstFrame) {
|
|
784
|
+
// Custom video frame processing (beauty, filters, etc.)
|
|
785
|
+
if (mBeautyProcessor != null) {
|
|
786
|
+
return mBeautyProcessor.processFrame(srcFrame, dstFrame);
|
|
787
|
+
}
|
|
788
|
+
return 0;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
@Override
|
|
792
|
+
public void onGLContextDestroyed() {
|
|
793
|
+
// Clean up resources when OpenGL environment is destroyed
|
|
794
|
+
if (mBeautyProcessor != null) {
|
|
795
|
+
mBeautyProcessor.release();
|
|
796
|
+
mBeautyProcessor = null;
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
// Enable custom video processing
|
|
802
|
+
pusher.enableCustomVideoProcess(true);
|
|
803
|
+
pusher.setObserver(new VideoProcessorObserver());
|
|
804
|
+
```
|
|
805
|
+
|
|
806
|
+
### Local Recording Monitoring Example
|
|
807
|
+
```java
|
|
808
|
+
public class RecordingObserver extends V2TXLivePusherObserver {
|
|
809
|
+
@Override
|
|
810
|
+
public void onLocalRecordBegin(int code, String storagePath) {
|
|
811
|
+
if (code == 0) {
|
|
812
|
+
Log.i("Recording", "Recording started, file path: " + storagePath);
|
|
813
|
+
} else {
|
|
814
|
+
Log.e("Recording", "Recording failed, error code: " + code);
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
@Override
|
|
819
|
+
public void onLocalRecording(long durationMs, String storagePath) {
|
|
820
|
+
// Update recording progress
|
|
821
|
+
updateRecordingProgress(durationMs);
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
@Override
|
|
825
|
+
public void onLocalRecordComplete(int code, String storagePath) {
|
|
826
|
+
if (code == 0) {
|
|
827
|
+
Log.i("Recording", "Recording completed, file path: " + storagePath);
|
|
828
|
+
} else {
|
|
829
|
+
Log.w("Recording", "Recording ended abnormally, status code: " + code);
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
```
|
|
834
|
+
|
|
835
|
+
## Notes
|
|
836
|
+
|
|
837
|
+
1. **Callback Threading**: Except for custom pre-processing callbacks, all other callback methods run on non-UI threads. Ensure thread safety.
|
|
838
|
+
2. **Performance Considerations**: Custom audio/video processing callbacks may impact streaming performance. Keep processing time minimal.
|
|
839
|
+
3. **Memory Management**: Release observer objects promptly when no longer needed to prevent memory leaks.
|
|
840
|
+
4. **Error Handling**: Handle all error codes appropriately and provide user-friendly feedback.
|
|
841
|
+
5. **Permission Checks**: Ensure proper permissions for screen sharing and local recording.
|
|
842
|
+
6. **OpenGL Resource Management**: Manage OpenGL resource creation and destruction carefully when using custom video processing.
|
|
843
|
+
|
|
844
|
+
## Related APIs
|
|
845
|
+
|
|
846
|
+
- `V2TXLivePusher`: Main stream pusher interface
|
|
847
|
+
- `V2TXLiveCode`: Error and status code definitions
|
|
848
|
+
- `V2TXLiveDef`: Data structures and enums
|
|
849
|
+
- `V2TXLivePremier`: SDK global management interface
|