@tencentcloud/sdk-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 +334 -0
- package/resource/doc/native_live/android/V2TXLiveDef_api_android.md +434 -0
- package/resource/doc/native_live/android/V2TXLivePlayerObserver_api_android.md +685 -0
- package/resource/doc/native_live/android/V2TXLivePlayer_api_android.md +712 -0
- package/resource/doc/native_live/android/V2TXLivePremier_api_android.md +284 -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 +879 -0
- package/resource/doc/native_live/flutter/V2TXLivePlayer_api_flutter.md +668 -0
- package/resource/doc/native_live/flutter/V2TXLivePremier_api_flutter.md +456 -0
- package/resource/doc/native_live/flutter/V2TXLivePusherObserver_api_flutter.md +332 -0
- package/resource/doc/native_live/flutter/V2TXLivePusher_api_flutter.md +748 -0
- package/resource/doc/native_live/iOS/V2TXLiveCode_api_iOS.md +328 -0
- package/resource/doc/native_live/iOS/V2TXLiveDef_api_iOS.md +505 -0
- package/resource/doc/native_live/iOS/V2TXLivePlayerObserver_api_iOS.md +507 -0
- package/resource/doc/native_live/iOS/V2TXLivePlayer_api_iOS.md +676 -0
- package/resource/doc/native_live/iOS/V2TXLivePremier_api_iOS.md +284 -0
- package/resource/doc/native_live/iOS/V2TXLivePusherObserver_api_iOS.md +820 -0
- package/resource/doc/native_live/iOS/V2TXLivePusher_api_iOS.md +1065 -0
- package/tools/definitions/get_native_live_api_def.js +22 -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
|
+
# 腾讯云直播SDK V2TXLivePusherObserver 直播推流器回调接口
|
|
2
|
+
|
|
3
|
+
## 概述
|
|
4
|
+
|
|
5
|
+
`V2TXLivePusherObserver` 是腾讯云直播SDK的推流器回调接口,用于接收推流器的各种状态通知和事件回调。通过实现该接口的回调方法,开发者可以监控推流器的运行状态、处理推流事件、获取统计数据等。
|
|
6
|
+
|
|
7
|
+
**文件路径**: `com/tencent/live2/V2TXLivePusherObserver.java`
|
|
8
|
+
|
|
9
|
+
**主要功能**:
|
|
10
|
+
- 推流器状态监控(错误、警告、连接状态)
|
|
11
|
+
- 音视频采集事件回调
|
|
12
|
+
- 推流统计数据和性能指标
|
|
13
|
+
- 自定义音视频处理
|
|
14
|
+
- 本地录制任务管理
|
|
15
|
+
- 屏幕分享状态监控
|
|
16
|
+
- 云端混流转码回调
|
|
17
|
+
|
|
18
|
+
## 回调方法详解
|
|
19
|
+
|
|
20
|
+
### 1. 错误和警告回调
|
|
21
|
+
|
|
22
|
+
#### onError() - 推流器错误通知
|
|
23
|
+
```java
|
|
24
|
+
public void onError(int code, String msg, Bundle extraInfo)
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**功能**: 推流器出现错误时回调
|
|
28
|
+
|
|
29
|
+
**参数**:
|
|
30
|
+
- `code`: 错误码,参考 `V2TXLiveCode` 枚举
|
|
31
|
+
- `msg`: 错误描述信息
|
|
32
|
+
- `extraInfo`: 扩展信息,包含详细的错误上下文
|
|
33
|
+
|
|
34
|
+
**使用场景**:
|
|
35
|
+
- 网络连接失败
|
|
36
|
+
- 推流地址无效
|
|
37
|
+
- 编码器错误
|
|
38
|
+
- 推流权限问题
|
|
39
|
+
|
|
40
|
+
**示例**:
|
|
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, "推流连接超时");
|
|
48
|
+
break;
|
|
49
|
+
case V2TXLIVE_ERROR_SERVER_PROCESS_FAILED:
|
|
50
|
+
Log.e(TAG, "推流服务器处理失败");
|
|
51
|
+
break;
|
|
52
|
+
default:
|
|
53
|
+
Log.e(TAG, "其它错误: " + msg);
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
#### onWarning() - 推流器警告通知
|
|
61
|
+
```java
|
|
62
|
+
public void onWarning(int code, String msg, Bundle extraInfo)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**功能**: 推流器出现警告时回调
|
|
66
|
+
|
|
67
|
+
**参数**:
|
|
68
|
+
- `code`: 警告码,参考 `V2TXLiveCode` 枚举
|
|
69
|
+
- `msg`: 警告描述信息
|
|
70
|
+
- `extraInfo`: 扩展信息
|
|
71
|
+
|
|
72
|
+
**使用场景**:
|
|
73
|
+
- 网络质量下降
|
|
74
|
+
- 编码延迟
|
|
75
|
+
- 缓冲区不足
|
|
76
|
+
|
|
77
|
+
**示例**:
|
|
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, "编码器类型变更,h.264, " + msg);
|
|
87
|
+
} else if (codec_type == 1) {
|
|
88
|
+
Log.w(TAG, "编码器类型变更,h.265, " + msg);
|
|
89
|
+
}
|
|
90
|
+
break;
|
|
91
|
+
case V2TXLiveCode.V2TXLIVE_WARNING_NETWORK_BUSY:
|
|
92
|
+
Log.w(TAG, "网络繁忙," + msg);
|
|
93
|
+
break;
|
|
94
|
+
case V2TXLiveCode.V2TXLIVE_WARNING_CAMERA_START_FAILED:
|
|
95
|
+
Log.w(TAG, "摄像头启动失败," + msg);
|
|
96
|
+
break;
|
|
97
|
+
case V2TXLiveCode.V2TXLIVE_WARNING_CAMERA_NO_PERMISSION:
|
|
98
|
+
Log.w(TAG, "摄像头设备未授权," + msg);
|
|
99
|
+
break;
|
|
100
|
+
case V2TXLiveCode.V2TXLIVE_WARNING_CAMERA_OCCUPIED:
|
|
101
|
+
Log.w(TAG, "摄像头设备被占用," + msg);
|
|
102
|
+
break;
|
|
103
|
+
case V2TXLIVE_WARNING_SCREEN_CAPTURE_START_FAILED:
|
|
104
|
+
Log.w(TAG, "屏幕采集启动失败," + msg);
|
|
105
|
+
break;
|
|
106
|
+
case V2TXLIVE_WARNING_SCREEN_CAPTURE_NOT_SUPPORTED:
|
|
107
|
+
Log.w(TAG, "屏幕采集不支持," + msg);
|
|
108
|
+
break;
|
|
109
|
+
case V2TXLIVE_WARNING_SCREEN_CAPTURE_INTERRUPTED:
|
|
110
|
+
Log.w(TAG, "屏幕采集中断," + msg);
|
|
111
|
+
break;
|
|
112
|
+
case V2TXLIVE_WARNING_MICROPHONE_START_FAILED:
|
|
113
|
+
Log.w(TAG, "麦克风启动失败," + msg);
|
|
114
|
+
break;
|
|
115
|
+
case V2TXLIVE_WARNING_MICROPHONE_NO_PERMISSION:
|
|
116
|
+
Log.w(TAG, "麦克风未授权," + msg);
|
|
117
|
+
break;
|
|
118
|
+
case V2TXLIVE_WARNING_MICROPHONE_OCCUPIED:
|
|
119
|
+
Log.w(TAG, "麦克风被占用," + msg);
|
|
120
|
+
break;
|
|
121
|
+
default:
|
|
122
|
+
Log.w(TAG, "其他警告," + msg);
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### 2. 连接和状态回调
|
|
130
|
+
|
|
131
|
+
#### onPushStatusUpdate() - 推流器连接状态回调
|
|
132
|
+
```java
|
|
133
|
+
public void onPushStatusUpdate(V2TXLivePushStatus status, String msg, Bundle extraInfo)
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
**功能**: 推流器连接状态回调通知
|
|
137
|
+
|
|
138
|
+
**参数**:
|
|
139
|
+
- `status`: 推流器连接状态 `V2TXLivePushStatus`
|
|
140
|
+
- `msg`: 连接状态信息
|
|
141
|
+
- `extraInfo`: 扩展信息
|
|
142
|
+
|
|
143
|
+
**状态枚举**:
|
|
144
|
+
- `V2TXLivePushStatus.V2TXLivePushStatusDisconnected`: 断开连接
|
|
145
|
+
- `V2TXLivePushStatus.V2TXLivePushStatusConnecting`: 连接中
|
|
146
|
+
- `V2TXLivePushStatus.V2TXLivePushStatusConnectSuccess`: 连接成功
|
|
147
|
+
- `V2TXLivePushStatus.V2TXLivePushStatusReconnecting`: 重连中
|
|
148
|
+
|
|
149
|
+
**使用场景**:
|
|
150
|
+
- 推流状态实时监控
|
|
151
|
+
- 连接失败重试机制
|
|
152
|
+
- 用户界面状态更新
|
|
153
|
+
|
|
154
|
+
**示例**:
|
|
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, "推流连接成功");
|
|
162
|
+
break;
|
|
163
|
+
case V2TXLivePushStatusConnecting:
|
|
164
|
+
Log.i(TAG, "推流连接中...");
|
|
165
|
+
break;
|
|
166
|
+
case V2TXLivePushStatusReconnecting:
|
|
167
|
+
Log.w(TAG, "推流重连中...");
|
|
168
|
+
break;
|
|
169
|
+
case V2TXLivePushStatusDisconnected:
|
|
170
|
+
Log.e(TAG, "推流连接断开");
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### 3. 采集事件回调
|
|
178
|
+
|
|
179
|
+
#### onCaptureFirstAudioFrame() - 首帧音频采集完成
|
|
180
|
+
```java
|
|
181
|
+
public void onCaptureFirstAudioFrame()
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
**功能**: 首帧音频采集完成的回调通知
|
|
185
|
+
|
|
186
|
+
**使用场景**:
|
|
187
|
+
- 确认音频采集已开始
|
|
188
|
+
- 音频相关UI状态更新
|
|
189
|
+
- 音频处理初始化
|
|
190
|
+
|
|
191
|
+
**示例**:
|
|
192
|
+
```java
|
|
193
|
+
pusher.setObserver(new V2TXLivePusherObserver() {
|
|
194
|
+
@Override
|
|
195
|
+
public void onCaptureFirstAudioFrame() {
|
|
196
|
+
Log.i(TAG, "音频采集开始,首帧音频已采集");
|
|
197
|
+
// 更新UI状态,显示音频采集中
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
#### onCaptureFirstVideoFrame() - 首帧视频采集完成
|
|
203
|
+
```java
|
|
204
|
+
public void onCaptureFirstVideoFrame()
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
**功能**: 首帧视频采集完成的回调通知
|
|
208
|
+
|
|
209
|
+
**使用场景**:
|
|
210
|
+
- 确认视频采集已开始
|
|
211
|
+
- 视频相关UI状态更新
|
|
212
|
+
- 视频处理初始化
|
|
213
|
+
|
|
214
|
+
**示例**:
|
|
215
|
+
```java
|
|
216
|
+
pusher.setObserver(new V2TXLivePusherObserver() {
|
|
217
|
+
@Override
|
|
218
|
+
public void onCaptureFirstVideoFrame() {
|
|
219
|
+
Log.i(TAG, "视频采集开始,首帧视频已采集");
|
|
220
|
+
// 更新UI状态,显示视频采集中
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
#### onMicrophoneVolumeUpdate() - 麦克风采集音量回调
|
|
226
|
+
```java
|
|
227
|
+
public void onMicrophoneVolumeUpdate(int volume)
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
**功能**: 麦克风采集音量值回调
|
|
231
|
+
|
|
232
|
+
**参数**:
|
|
233
|
+
- `volume`: 音量大小(0-100)
|
|
234
|
+
|
|
235
|
+
**前提条件**: 需要调用 `enableVolumeEvaluation()` 开启采集音量大小提示
|
|
236
|
+
|
|
237
|
+
**使用场景**:
|
|
238
|
+
- 实时音量显示
|
|
239
|
+
- 音频波形动画
|
|
240
|
+
- 静音检测
|
|
241
|
+
|
|
242
|
+
**示例**:
|
|
243
|
+
```java
|
|
244
|
+
pusher.setObserver(new V2TXLivePusherObserver() {
|
|
245
|
+
@Override
|
|
246
|
+
public void onMicrophoneVolumeUpdate(int volume) {
|
|
247
|
+
// 实时更新音量显示
|
|
248
|
+
|
|
249
|
+
// 静音检测
|
|
250
|
+
if (volume < 5) {
|
|
251
|
+
Log.d(TAG, "检测到静音状态");
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
// 开启音量评估
|
|
256
|
+
pusher.enableVolumeEvaluation(300);
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### 4. 音视频数据处理回调
|
|
260
|
+
|
|
261
|
+
#### onProcessAudioFrame() - 音频数据处理回调
|
|
262
|
+
```java
|
|
263
|
+
public void onProcessAudioFrame(V2TXLiveDef.V2TXLiveAudioFrame frame)
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
**功能**: 本地采集并经过音频模块前处理、音效处理和混BGM后的音频数据回调
|
|
267
|
+
|
|
268
|
+
**参数**:
|
|
269
|
+
- `frame`: PCM格式的音频数据帧
|
|
270
|
+
|
|
271
|
+
**技术规格**:
|
|
272
|
+
- 音频时间帧长固定为0.02s
|
|
273
|
+
- 格式为PCM格式
|
|
274
|
+
- 字节帧长计算公式:`采样率 × 时间帧长 × 声道数 × 采样点位宽`
|
|
275
|
+
- 默认格式(48000采样率、单声道、16采样点位宽):1920字节
|
|
276
|
+
|
|
277
|
+
**重要注意事项**:
|
|
278
|
+
1. 不要在此回调函数中做任何耗时操作
|
|
279
|
+
2. SDK每隔20ms处理一帧音频数据,处理时间超过20ms会导致声音异常
|
|
280
|
+
3. 音频数据可读写,可同步修改但需保证处理耗时
|
|
281
|
+
|
|
282
|
+
**使用场景**:
|
|
283
|
+
- 自定义音频处理
|
|
284
|
+
- 音频特效应用
|
|
285
|
+
- 音频分析统计
|
|
286
|
+
|
|
287
|
+
**示例**:
|
|
288
|
+
```java
|
|
289
|
+
pusher.setObserver(new V2TXLivePusherObserver() {
|
|
290
|
+
@Override
|
|
291
|
+
public void onProcessAudioFrame(V2TXLiveDef.V2TXLiveAudioFrame frame) {
|
|
292
|
+
// 自定义音频处理,如添加混响效果
|
|
293
|
+
|
|
294
|
+
// 音频数据统计
|
|
295
|
+
audioFrameCount++;
|
|
296
|
+
if (audioFrameCount % 50 == 0) {
|
|
297
|
+
Log.d(TAG, "已处理音频帧数: " + audioFrameCount);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
#### onProcessVideoFrame() - 自定义视频处理回调
|
|
304
|
+
```java
|
|
305
|
+
public int onProcessVideoFrame(V2TXLiveVideoFrame srcFrame, V2TXLiveVideoFrame dstFrame)
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
**功能**: 自定义视频处理回调
|
|
309
|
+
|
|
310
|
+
**参数**:
|
|
311
|
+
- `srcFrame`: 用于承载未处理的视频画面
|
|
312
|
+
- `dstFrame`: 用于承载处理过的视频画面
|
|
313
|
+
|
|
314
|
+
**返回值**: 处理结果(0表示成功)
|
|
315
|
+
|
|
316
|
+
**前提条件**: 需要调用 `enableCustomVideoProcess()` 开启自定义视频处理
|
|
317
|
+
|
|
318
|
+
**使用场景示例**:
|
|
319
|
+
|
|
320
|
+
**情况一:美颜组件产生新纹理**
|
|
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
|
+
**情况二:美颜组件不产生新纹理**
|
|
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环境回调
|
|
350
|
+
|
|
351
|
+
#### onGLContextCreated() - OpenGL环境创建通知
|
|
352
|
+
```java
|
|
353
|
+
public void onGLContextCreated()
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
**功能**: SDK内部的OpenGL环境的创建通知
|
|
357
|
+
|
|
358
|
+
**使用场景**:
|
|
359
|
+
- 美颜组件初始化
|
|
360
|
+
- 视频处理模块初始化
|
|
361
|
+
- OpenGL资源创建
|
|
362
|
+
|
|
363
|
+
**示例**:
|
|
364
|
+
```java
|
|
365
|
+
pusher.setObserver(new V2TXLivePusherObserver() {
|
|
366
|
+
@Override
|
|
367
|
+
public void onGLContextCreated() {
|
|
368
|
+
Log.i(TAG, "OpenGL环境已创建");
|
|
369
|
+
// 初始化美颜组件
|
|
370
|
+
if (mBeautyProcessor != null) {
|
|
371
|
+
mBeautyProcessor.initGL();
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
});
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
#### onGLContextDestroyed() - OpenGL环境销毁通知
|
|
378
|
+
```java
|
|
379
|
+
public void onGLContextDestroyed()
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
**功能**: SDK内部的OpenGL环境的销毁通知
|
|
383
|
+
|
|
384
|
+
**使用场景**:
|
|
385
|
+
- 美颜组件清理
|
|
386
|
+
- 视频处理模块清理
|
|
387
|
+
- OpenGL资源释放
|
|
388
|
+
|
|
389
|
+
**示例**:
|
|
390
|
+
```java
|
|
391
|
+
pusher.setObserver(new V2TXLivePusherObserver() {
|
|
392
|
+
@Override
|
|
393
|
+
public void onGLContextDestroyed() {
|
|
394
|
+
Log.i(TAG, "OpenGL环境已销毁");
|
|
395
|
+
// 清理美颜组件资源
|
|
396
|
+
if (mBeautyProcessor != null) {
|
|
397
|
+
mBeautyProcessor.releaseGL();
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
});
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
### 6. 统计和监控回调
|
|
404
|
+
|
|
405
|
+
#### onStatisticsUpdate() - 统计数据回调
|
|
406
|
+
```java
|
|
407
|
+
public void onStatisticsUpdate(V2TXLivePusherStatistics statistics)
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
**功能**: 推流器统计数据实时回调,2s回调一次
|
|
411
|
+
|
|
412
|
+
**参数**:
|
|
413
|
+
- `statistics`: 推流统计信息 `V2TXLivePusherStatistics`
|
|
414
|
+
|
|
415
|
+
**包含数据**:
|
|
416
|
+
- 视频宽度/高度
|
|
417
|
+
- 帧率/码率
|
|
418
|
+
- 网络状况
|
|
419
|
+
- 缓存大小
|
|
420
|
+
- 推流延迟
|
|
421
|
+
|
|
422
|
+
**使用场景**:
|
|
423
|
+
- 推流质量监控
|
|
424
|
+
- 性能优化分析
|
|
425
|
+
- 用户体验统计
|
|
426
|
+
|
|
427
|
+
**示例**:
|
|
428
|
+
```java
|
|
429
|
+
pusher.setObserver(new V2TXLivePusherObserver() {
|
|
430
|
+
@Override
|
|
431
|
+
public void onStatisticsUpdate(V2TXLivePusherStatistics statistics) {
|
|
432
|
+
Log.d(TAG, "推流统计 - 帧率: " + statistics.fps +
|
|
433
|
+
", 码率: " + statistics.videoBitrate +
|
|
434
|
+
", 分辨率: " + statistics.width + "x" + statistics.height);
|
|
435
|
+
|
|
436
|
+
// 更新推流质量显示
|
|
437
|
+
}
|
|
438
|
+
});
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
### 7. 高级功能回调
|
|
442
|
+
|
|
443
|
+
#### onSnapshotComplete() - 截图完成回调
|
|
444
|
+
```java
|
|
445
|
+
public void onSnapshotComplete(Bitmap image)
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
**功能**: 截图操作完成回调
|
|
449
|
+
|
|
450
|
+
**参数**:
|
|
451
|
+
- `image`: 截取的视频画面Bitmap
|
|
452
|
+
|
|
453
|
+
**使用场景**:
|
|
454
|
+
- 视频截图保存
|
|
455
|
+
- 画面分享功能
|
|
456
|
+
- 证据保存
|
|
457
|
+
|
|
458
|
+
**示例**:
|
|
459
|
+
```java
|
|
460
|
+
pusher.setObserver(new V2TXLivePusherObserver() {
|
|
461
|
+
@Override
|
|
462
|
+
public void onSnapshotComplete(Bitmap image) {
|
|
463
|
+
Log.i(TAG, "截图完成,图片尺寸: " + image.getWidth() + "x" + image.getHeight());
|
|
464
|
+
|
|
465
|
+
// 保存截图到相册
|
|
466
|
+
|
|
467
|
+
// 显示截图预览
|
|
468
|
+
}
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
// 触发截图
|
|
472
|
+
pusher.snapshot();
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
#### onSetMixTranscodingConfig() - 云端混流转码回调
|
|
476
|
+
```java
|
|
477
|
+
public void onSetMixTranscodingConfig(int code, String msg)
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
**功能**: 设置云端的混流转码参数的回调,仅RTC协议支持
|
|
481
|
+
|
|
482
|
+
**参数**:
|
|
483
|
+
- `code`: 0表示成功,其余值表示失败
|
|
484
|
+
- `msg`: 具体错误原因
|
|
485
|
+
|
|
486
|
+
**对应接口**: `setMixTranscodingConfig()`
|
|
487
|
+
|
|
488
|
+
**使用场景**:
|
|
489
|
+
- 混流转码状态监控
|
|
490
|
+
- 转码失败处理
|
|
491
|
+
- 多路流合成状态跟踪
|
|
492
|
+
|
|
493
|
+
**示例**:
|
|
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, "云端混流转码配置成功");
|
|
500
|
+
} else {
|
|
501
|
+
Log.e(TAG, "云端混流转码配置失败: " + msg);
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
});
|
|
505
|
+
|
|
506
|
+
// 配置云端混流
|
|
507
|
+
V2TXLiveDef.V2TXLiveTranscodingConfig config = new V2TXLiveDef.V2TXLiveTranscodingConfig();
|
|
508
|
+
// ... 配置混流参数
|
|
509
|
+
pusher.setMixTranscodingConfig(config);
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
#### onVoiceActivityDetectionUpdate() - 人声检测回调
|
|
513
|
+
```java
|
|
514
|
+
public void onVoiceActivityDetectionUpdate(boolean active)
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
**功能**: 人声检测状态更新回调
|
|
518
|
+
|
|
519
|
+
**参数**:
|
|
520
|
+
- `active`: 人声开始或停止
|
|
521
|
+
|
|
522
|
+
**前提条件**: 调用 `enableVoiceActivityDetection()` 开启人声检测
|
|
523
|
+
|
|
524
|
+
**使用场景**:
|
|
525
|
+
- 语音活动检测
|
|
526
|
+
- 智能静音处理
|
|
527
|
+
- 语音识别应用
|
|
528
|
+
|
|
529
|
+
**示例**:
|
|
530
|
+
```java
|
|
531
|
+
pusher.setObserver(new V2TXLivePusherObserver() {
|
|
532
|
+
@Override
|
|
533
|
+
public void onVoiceActivityDetectionUpdate(boolean active) {
|
|
534
|
+
if (active) {
|
|
535
|
+
Log.i(TAG, "检测到人声活动开始");
|
|
536
|
+
// 显示说话状态指示器
|
|
537
|
+
showSpeakingIndicator(true);
|
|
538
|
+
} else {
|
|
539
|
+
Log.i(TAG, "检测到人声活动停止");
|
|
540
|
+
// 隐藏说话状态指示器
|
|
541
|
+
showSpeakingIndicator(false);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
});
|
|
545
|
+
|
|
546
|
+
// 开启人声检测
|
|
547
|
+
pusher.enableVoiceActivityDetection(true);
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
### 8. 屏幕分享回调
|
|
551
|
+
|
|
552
|
+
#### onScreenCaptureStarted() - 屏幕分享开始回调
|
|
553
|
+
```java
|
|
554
|
+
public void onScreenCaptureStarted()
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
**功能**: 当屏幕分享开始时,SDK会通过此回调通知
|
|
558
|
+
|
|
559
|
+
**使用场景**:
|
|
560
|
+
- 屏幕分享状态监控
|
|
561
|
+
- UI状态更新
|
|
562
|
+
- 权限检查确认
|
|
563
|
+
|
|
564
|
+
**示例**:
|
|
565
|
+
```java
|
|
566
|
+
pusher.setObserver(new V2TXLivePusherObserver() {
|
|
567
|
+
@Override
|
|
568
|
+
public void onScreenCaptureStarted() {
|
|
569
|
+
Log.i(TAG, "屏幕分享已开始");
|
|
570
|
+
// 更新UI显示屏幕分享状态
|
|
571
|
+
updateScreenShareStatus(true);
|
|
572
|
+
}
|
|
573
|
+
});
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
#### onScreenCaptureStopped() - 屏幕分享停止回调
|
|
577
|
+
```java
|
|
578
|
+
public void onScreenCaptureStopped(int reason)
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
**功能**: 当屏幕分享停止时,SDK会通过此回调通知
|
|
582
|
+
|
|
583
|
+
**参数**:
|
|
584
|
+
- `reason`: 停止原因
|
|
585
|
+
- `0`: 用户主动停止
|
|
586
|
+
- `1`: iOS表示录屏被系统中断;Mac、Windows表示屏幕分享窗口被关闭
|
|
587
|
+
- `2`: Windows表示屏幕分享的显示屏状态变更;其他平台不抛出
|
|
588
|
+
|
|
589
|
+
**使用场景**:
|
|
590
|
+
- 屏幕分享异常处理
|
|
591
|
+
- 用户界面状态恢复
|
|
592
|
+
- 权限丢失处理
|
|
593
|
+
|
|
594
|
+
**示例**:
|
|
595
|
+
```java
|
|
596
|
+
pusher.setObserver(new V2TXLivePusherObserver() {
|
|
597
|
+
@Override
|
|
598
|
+
public void onScreenCaptureStopped(int reason) {
|
|
599
|
+
Log.i(TAG, "屏幕分享已停止,原因: " + reason);
|
|
600
|
+
|
|
601
|
+
switch (reason) {
|
|
602
|
+
case 0:
|
|
603
|
+
Log.i(TAG, "用户主动停止屏幕分享");
|
|
604
|
+
break;
|
|
605
|
+
case 1:
|
|
606
|
+
Log.w(TAG, "屏幕分享被系统中断");
|
|
607
|
+
break;
|
|
608
|
+
case 2:
|
|
609
|
+
Log.w(TAG, "显示屏状态变更导致屏幕分享停止");
|
|
610
|
+
break;
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
// 更新UI显示屏幕分享状态
|
|
614
|
+
updateScreenShareStatus(false);
|
|
615
|
+
}
|
|
616
|
+
});
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
### 9. 本地录制回调
|
|
620
|
+
|
|
621
|
+
#### onLocalRecordBegin() - 录制开始回调
|
|
622
|
+
```java
|
|
623
|
+
public void onLocalRecordBegin(int code, String storagePath)
|
|
624
|
+
```
|
|
625
|
+
|
|
626
|
+
**功能**: 录制任务开始的事件回调
|
|
627
|
+
|
|
628
|
+
**参数**:
|
|
629
|
+
- `code`: 状态码
|
|
630
|
+
- `0`: 录制任务启动成功
|
|
631
|
+
- `-1`: 内部错误导致录制任务启动失败
|
|
632
|
+
- `-2`: 文件后缀名有误
|
|
633
|
+
- `-6`: 录制已经启动,需要先停止录制
|
|
634
|
+
- `-7`: 录制文件已存在,需要先删除文件
|
|
635
|
+
- `-8`: 录制目录无写入权限
|
|
636
|
+
- `storagePath`: 录制的文件地址
|
|
637
|
+
|
|
638
|
+
**对应接口**: `startLocalRecording()`
|
|
639
|
+
|
|
640
|
+
**示例**:
|
|
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, "本地录制开始,文件路径: " + storagePath);
|
|
647
|
+
// 显示录制状态
|
|
648
|
+
showRecordingStatus(true);
|
|
649
|
+
} else {
|
|
650
|
+
Log.e(TAG, "本地录制开始失败,错误码: " + code);
|
|
651
|
+
// 处理录制失败情况
|
|
652
|
+
handleRecordingError(code);
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
});
|
|
656
|
+
```
|
|
657
|
+
|
|
658
|
+
#### onLocalRecording() - 录制进度回调
|
|
659
|
+
```java
|
|
660
|
+
public void onLocalRecording(long durationMs, String storagePath)
|
|
661
|
+
```
|
|
662
|
+
|
|
663
|
+
**功能**: 录制任务正在进行中的进展事件回调
|
|
664
|
+
|
|
665
|
+
**参数**:
|
|
666
|
+
- `durationMs`: 录制时长
|
|
667
|
+
- `storagePath`: 录制的文件地址
|
|
668
|
+
|
|
669
|
+
**默认行为**: 不抛出本事件回调,需要在 `startLocalRecording()` 时设定回调间隔参数
|
|
670
|
+
|
|
671
|
+
**使用场景**:
|
|
672
|
+
- 录制进度显示
|
|
673
|
+
- 录制时长限制
|
|
674
|
+
- 录制状态监控
|
|
675
|
+
|
|
676
|
+
**示例**:
|
|
677
|
+
```java
|
|
678
|
+
pusher.setObserver(new V2TXLivePusherObserver() {
|
|
679
|
+
@Override
|
|
680
|
+
public void onLocalRecording(long durationMs, String storagePath) {
|
|
681
|
+
// 更新录制进度显示
|
|
682
|
+
updateRecordingProgress(durationMs);
|
|
683
|
+
|
|
684
|
+
// 录制时长限制检查(例如限制录制1小时)
|
|
685
|
+
if (durationMs >= 3600000) {
|
|
686
|
+
Log.w(TAG, "录制时长已达限制,自动停止录制");
|
|
687
|
+
pusher.stopLocalRecording();
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
});
|
|
691
|
+
```
|
|
692
|
+
|
|
693
|
+
#### onLocalRecordComplete() - 录制完成回调
|
|
694
|
+
```java
|
|
695
|
+
public void onLocalRecordComplete(int code, String storagePath)
|
|
696
|
+
```
|
|
697
|
+
|
|
698
|
+
**功能**: 录制任务已经结束的事件回调
|
|
699
|
+
|
|
700
|
+
**参数**:
|
|
701
|
+
- `code`: 状态码
|
|
702
|
+
- `0`: 结束录制任务成功
|
|
703
|
+
- `-1`: 录制失败
|
|
704
|
+
- `-2`: 切换分辨率或横竖屏导致录制结束
|
|
705
|
+
- `-3`: 录制时间太短,或未采集到任何视频或音频数据
|
|
706
|
+
- `storagePath`: 录制的文件地址
|
|
707
|
+
|
|
708
|
+
**对应接口**: `stopLocalRecording()`
|
|
709
|
+
|
|
710
|
+
**示例**:
|
|
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, "本地录制完成,文件路径: " + storagePath);
|
|
717
|
+
// 显示录制完成状态
|
|
718
|
+
showRecordingComplete(storagePath);
|
|
719
|
+
} else {
|
|
720
|
+
Log.w(TAG, "本地录制异常结束,状态码: " + code);
|
|
721
|
+
// 处理录制异常结束
|
|
722
|
+
handleRecordingAbnormalEnd(code);
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
});
|
|
726
|
+
```
|
|
727
|
+
|
|
728
|
+
## 使用示例
|
|
729
|
+
|
|
730
|
+
### 基础推流器回调实现
|
|
731
|
+
```java
|
|
732
|
+
public class MyPusherObserver extends V2TXLivePusherObserver {
|
|
733
|
+
@Override
|
|
734
|
+
public void onError(int code, String msg, Bundle extraInfo) {
|
|
735
|
+
// 处理推流错误
|
|
736
|
+
Log.e("PusherError", "错误码: " + code + ", 错误信息: " + msg);
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
@Override
|
|
740
|
+
public void onPushStatusUpdate(V2TXLivePushStatus status, String msg, Bundle extraInfo) {
|
|
741
|
+
// 推流状态监控
|
|
742
|
+
switch (status) {
|
|
743
|
+
case CONNECT_SUCCESS:
|
|
744
|
+
Log.i("Pusher", "推流连接成功");
|
|
745
|
+
break;
|
|
746
|
+
case DISCONNECTED:
|
|
747
|
+
Log.w("Pusher", "推流连接断开");
|
|
748
|
+
break;
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
@Override
|
|
753
|
+
public void onCaptureFirstVideoFrame() {
|
|
754
|
+
// 视频采集开始
|
|
755
|
+
Log.i("Pusher", "视频采集开始");
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
@Override
|
|
759
|
+
public void onStatisticsUpdate(V2TXLivePusherStatistics statistics) {
|
|
760
|
+
// 更新推流统计信息
|
|
761
|
+
Log.d("PusherStats", "帧率: " + statistics.fps + ", 码率: " + statistics.bitrate);
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
// 设置回调观察者
|
|
766
|
+
V2TXLivePusher pusher = new V2TXLivePusherImpl(context);
|
|
767
|
+
pusher.setObserver(new MyPusherObserver());
|
|
768
|
+
```
|
|
769
|
+
|
|
770
|
+
### 自定义视频处理示例
|
|
771
|
+
```java
|
|
772
|
+
public class VideoProcessorObserver extends V2TXLivePusherObserver {
|
|
773
|
+
private BeautyProcessor mBeautyProcessor;
|
|
774
|
+
|
|
775
|
+
@Override
|
|
776
|
+
public void onGLContextCreated() {
|
|
777
|
+
// OpenGL环境创建时初始化美颜组件
|
|
778
|
+
mBeautyProcessor = new BeautyProcessor();
|
|
779
|
+
mBeautyProcessor.init();
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
@Override
|
|
783
|
+
public int onProcessVideoFrame(V2TXLiveVideoFrame srcFrame, V2TXLiveVideoFrame dstFrame) {
|
|
784
|
+
// 自定义视频帧处理(美颜、滤镜等)
|
|
785
|
+
if (mBeautyProcessor != null) {
|
|
786
|
+
return mBeautyProcessor.processFrame(srcFrame, dstFrame);
|
|
787
|
+
}
|
|
788
|
+
return 0;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
@Override
|
|
792
|
+
public void onGLContextDestroyed() {
|
|
793
|
+
// OpenGL环境销毁时清理资源
|
|
794
|
+
if (mBeautyProcessor != null) {
|
|
795
|
+
mBeautyProcessor.release();
|
|
796
|
+
mBeautyProcessor = null;
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
// 开启自定义视频处理
|
|
802
|
+
pusher.enableCustomVideoProcess(true);
|
|
803
|
+
pusher.setObserver(new VideoProcessorObserver());
|
|
804
|
+
```
|
|
805
|
+
|
|
806
|
+
### 本地录制监控示例
|
|
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", "录制开始,文件路径: " + storagePath);
|
|
813
|
+
} else {
|
|
814
|
+
Log.e("Recording", "录制失败,错误码: " + code);
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
@Override
|
|
819
|
+
public void onLocalRecording(long durationMs, String storagePath) {
|
|
820
|
+
// 更新录制进度
|
|
821
|
+
updateRecordingProgress(durationMs);
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
@Override
|
|
825
|
+
public void onLocalRecordComplete(int code, String storagePath) {
|
|
826
|
+
if (code == 0) {
|
|
827
|
+
Log.i("Recording", "录制完成,文件路径: " + storagePath);
|
|
828
|
+
} else {
|
|
829
|
+
Log.w("Recording", "录制异常结束,状态码: " + code);
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
```
|
|
834
|
+
|
|
835
|
+
## 注意事项
|
|
836
|
+
|
|
837
|
+
1. **回调线程**: 除自定义预处理回调,其它所有回调方法都在非UI线程执行,需要进行线程安全处理
|
|
838
|
+
2. **性能影响**: 自定义音视频处理回调可能影响推流性能,需控制处理耗时
|
|
839
|
+
3. **内存管理**: 及时释放不再使用的观察者对象,避免内存泄漏
|
|
840
|
+
4. **错误处理**: 合理处理各种错误码,提供友好的用户提示
|
|
841
|
+
5. **权限检查**: 屏幕分享和本地录制需要确保有相应权限
|
|
842
|
+
6. **OpenGL资源**: 自定义视频处理时注意OpenGL资源的创建和销毁时机
|
|
843
|
+
|
|
844
|
+
## 相关接口
|
|
845
|
+
|
|
846
|
+
- `V2TXLivePusher`: 推流器主接口
|
|
847
|
+
- `V2TXLiveCode`: 错误码和状态码定义
|
|
848
|
+
- `V2TXLiveDef`: 数据结构和枚举定义
|
|
849
|
+
- `V2TXLivePremier`: SDK全局管理接口
|