@tencentcloud/trtc-cloud-wx 1.0.7 → 1.0.9-beta.0
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/.babelrc +6 -0
- package/.eslintrc.json +129 -0
- package/build/chokidar.js +19 -0
- package/build/clear.js +24 -0
- package/build/copy.js +24 -0
- package/build/copy_to_roomkit.js +19 -0
- package/dist/package.json +14 -0
- package/{trtc-cloud-wx.js → dist/trtc-cloud-wx.js} +25 -40
- package/docs/API/TRTCCloud.html +4353 -0
- package/docs/API/index.html +98 -0
- package/docs/API/scripts/add-toc.js +57 -0
- package/docs/API/scripts/collapse.js +20 -0
- package/docs/API/scripts/highlight/highlight.min.js +1282 -0
- package/docs/API/scripts/highlight/highlightjs-line-numbers.min.js +1 -0
- package/docs/API/scripts/linenumber.js +25 -0
- package/docs/API/scripts/nav.js +12 -0
- package/docs/API/scripts/polyfill.js +4 -0
- package/docs/API/scripts/prettify/Apache-License-2.0.txt +202 -0
- package/docs/API/scripts/prettify/lang-css.js +2 -0
- package/docs/API/scripts/prettify/prettify.js +28 -0
- package/docs/API/scripts/search.js +83 -0
- package/docs/API/styles/font.css +81 -0
- package/docs/API/styles/fonts/JTURjIg1_i6t8kCHKm45_dJE3g3D_vx3rCubqg.woff2 +0 -0
- package/docs/API/styles/fonts/JTURjIg1_i6t8kCHKm45_dJE3gTD_vx3rCubqg.woff2 +0 -0
- package/docs/API/styles/fonts/JTURjIg1_i6t8kCHKm45_dJE3gbD_vx3rCubqg.woff2 +0 -0
- package/docs/API/styles/fonts/JTURjIg1_i6t8kCHKm45_dJE3gfD_vx3rCubqg.woff2 +0 -0
- package/docs/API/styles/fonts/JTURjIg1_i6t8kCHKm45_dJE3gnD_vx3rCs.woff2 +0 -0
- package/docs/API/styles/fonts/JTUSjIg1_i6t8kCHKm459W1hyyTh89ZNpQ.woff2 +0 -0
- package/docs/API/styles/fonts/JTUSjIg1_i6t8kCHKm459WRhyyTh89ZNpQ.woff2 +0 -0
- package/docs/API/styles/fonts/JTUSjIg1_i6t8kCHKm459WZhyyTh89ZNpQ.woff2 +0 -0
- package/docs/API/styles/fonts/JTUSjIg1_i6t8kCHKm459WdhyyTh89ZNpQ.woff2 +0 -0
- package/docs/API/styles/fonts/JTUSjIg1_i6t8kCHKm459WlhyyTh89Y.woff2 +0 -0
- package/docs/API/styles/highlight/highlight.min.css +26 -0
- package/docs/API/styles/highlight/rainbow.min.css +1 -0
- package/docs/API/styles/jsdoc.css +684 -0
- package/docs/API/styles/prettify.css +79 -0
- package/docs/API/styles/toc.css +44 -0
- package/docs/API/tutorial-00-guideline.html +81 -0
- package/docs/doc-src/home.md +7 -0
- package/docs/doc-src/tutorials/00-guideline.md +1 -0
- package/docs/doc-src/tutorials/tutorials.json +5 -0
- package/jsdoc.json +43 -0
- package/package.json +40 -3
- package/rollup.config.js +19 -0
- package/sdk_publish.bash +5 -0
- package/src/TaskMachine.ts +371 -0
- package/src/index.ts +1184 -0
- package/src/interface/index.ts +45 -0
- package/src/interface/types.ts +95 -0
- package/src/log/logger.ts +80 -0
- package/src/types.d.ts +1 -0
- package/src/utils/common.ts +50 -0
- package/src/utils/index.ts +2 -0
- package/src/utils/translate.ts +139 -0
- package/tsconfig.json +15 -0
- package/typedoc.json +21 -0
package/src/index.ts
ADDED
|
@@ -0,0 +1,1184 @@
|
|
|
1
|
+
import EventEmitter from 'eventemitter3'
|
|
2
|
+
import TRTC from 'trtc-wx-sdk'
|
|
3
|
+
import {
|
|
4
|
+
TRTCParams,
|
|
5
|
+
TRTCAppScene,
|
|
6
|
+
TRTCRoleType,
|
|
7
|
+
TRTCVideoStreamType,
|
|
8
|
+
TRTCVideoEncParam,
|
|
9
|
+
TRTCRenderParams,
|
|
10
|
+
TRTCAudioQuality,
|
|
11
|
+
TRTCVolumeInfo,
|
|
12
|
+
TRTCBeautyStyle,
|
|
13
|
+
AudioMusicParam,
|
|
14
|
+
TRTCAudioRoute,
|
|
15
|
+
} from './interface'
|
|
16
|
+
import {
|
|
17
|
+
setHandle, Handletype, TaskQueueEvent, taskMachine
|
|
18
|
+
} from './TaskMachine'
|
|
19
|
+
import {
|
|
20
|
+
translateTRTCAppScene,
|
|
21
|
+
translateTRTCStreamId,
|
|
22
|
+
translateTRTCVideoMirrorType,
|
|
23
|
+
translateTRTCVideoResolution,
|
|
24
|
+
translateTRTCVideoRotation,
|
|
25
|
+
translateVideoFillMod,
|
|
26
|
+
translateTRTCAudioRoute,
|
|
27
|
+
uniqueFunc,
|
|
28
|
+
isNumber,
|
|
29
|
+
safelyParse,
|
|
30
|
+
translateBeautyStyle
|
|
31
|
+
} from './utils'
|
|
32
|
+
|
|
33
|
+
import {logger} from './log/logger'
|
|
34
|
+
|
|
35
|
+
import packageJson from '../package.json' // 假设 package.json 文件在项目根目录下
|
|
36
|
+
|
|
37
|
+
export * from './interface'
|
|
38
|
+
export * from './utils/translate'
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* TRTCCloud
|
|
42
|
+
* @interface
|
|
43
|
+
*/
|
|
44
|
+
export class TRTCCloud {
|
|
45
|
+
static instance;
|
|
46
|
+
|
|
47
|
+
public version = packageJson.version;
|
|
48
|
+
|
|
49
|
+
// 内部使用,用于调用接口时UI测监听,完成剩余逻辑
|
|
50
|
+
public InterfaceEventEmitter = new EventEmitter();
|
|
51
|
+
|
|
52
|
+
// 外部使用,用户监听回调事件
|
|
53
|
+
private EventEmitter = new EventEmitter();
|
|
54
|
+
|
|
55
|
+
public trtc;
|
|
56
|
+
|
|
57
|
+
public TRTC_EVENT;
|
|
58
|
+
|
|
59
|
+
private role = TRTCRoleType.TRTCRoleAnchor;
|
|
60
|
+
|
|
61
|
+
private scene: TRTCAppScene;
|
|
62
|
+
|
|
63
|
+
public userId = '';
|
|
64
|
+
|
|
65
|
+
private isEnterRoom = false;
|
|
66
|
+
|
|
67
|
+
private isVideoMuted = false;
|
|
68
|
+
|
|
69
|
+
private isOpenCamera = false;
|
|
70
|
+
|
|
71
|
+
private currentSoundMode = TRTCAudioRoute.TRTC_AUDIO_ROUTE_SPEAKER;
|
|
72
|
+
|
|
73
|
+
private audioVolumeEvaluation = 0;
|
|
74
|
+
|
|
75
|
+
private encsmall = 0;
|
|
76
|
+
|
|
77
|
+
private enableinfiniteanchor = 0;
|
|
78
|
+
|
|
79
|
+
private allTimer: Record<string, NodeJS.Timer> = {};
|
|
80
|
+
|
|
81
|
+
private renderMap = new Map();
|
|
82
|
+
|
|
83
|
+
private pusherIsReady = false;
|
|
84
|
+
|
|
85
|
+
public logger = logger;
|
|
86
|
+
|
|
87
|
+
// private handleAudioVolumeUpdate: (userVolumes: Array<TRTCVolumeInfo>) => void;
|
|
88
|
+
|
|
89
|
+
constructor() {
|
|
90
|
+
this.init()
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* 获取 TRTCCloud 实例(单例模式)
|
|
95
|
+
* @category Base
|
|
96
|
+
*/
|
|
97
|
+
static getTRTCShareInstance(): TRTCCloud {
|
|
98
|
+
if (!TRTCCloud.instance) {
|
|
99
|
+
TRTCCloud.instance = new TRTCCloud()
|
|
100
|
+
}
|
|
101
|
+
return TRTCCloud.instance
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* 销毁 TRTCCloud 实例(单例模式)
|
|
106
|
+
* @category Base
|
|
107
|
+
*/
|
|
108
|
+
static destroyTRTCShareInstance(): void {
|
|
109
|
+
if (!TRTCCloud.instance) return
|
|
110
|
+
TRTCCloud.instance.destroy()
|
|
111
|
+
TRTCCloud.instance = null
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
public createSubCloud(): TRTCCloud {
|
|
115
|
+
return TRTCCloud.getTRTCShareInstance()
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
getSDKVersion(): string {
|
|
119
|
+
return this.version
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
private destroy(): void {
|
|
123
|
+
this.offTRTCEvent()
|
|
124
|
+
this.EventEmitter.removeAllListeners()
|
|
125
|
+
this.InterfaceEventEmitter.removeAllListeners()
|
|
126
|
+
this.trtc.exitRoom()
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
private init(): void {
|
|
130
|
+
this.trtc = new TRTC(this)
|
|
131
|
+
this.trtc.setLogLevel(3)
|
|
132
|
+
this.TRTC_EVENT = this.trtc.EVENT
|
|
133
|
+
this.bindTRTCEvent()
|
|
134
|
+
this.bindComponentEvent()
|
|
135
|
+
this.handleNetworkQuality = this.getHandleNetworkQuality(2000)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
private reset(): void {
|
|
139
|
+
this.role = TRTCRoleType.TRTCRoleAnchor
|
|
140
|
+
this.userId = ''
|
|
141
|
+
this.isEnterRoom = false
|
|
142
|
+
this.isVideoMuted = false
|
|
143
|
+
this.isOpenCamera = false
|
|
144
|
+
this.currentSoundMode = TRTCAudioRoute.TRTC_AUDIO_ROUTE_SPEAKER
|
|
145
|
+
this.encsmall = 0
|
|
146
|
+
this.enableinfiniteanchor = 0
|
|
147
|
+
taskMachine.reset()
|
|
148
|
+
Object.keys(this.allTimer).forEach((key) => {
|
|
149
|
+
clearInterval(this.allTimer[key])
|
|
150
|
+
this.allTimer[key] = null
|
|
151
|
+
})
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
private bindComponentEvent(): void {
|
|
155
|
+
this.InterfaceEventEmitter.on('pusherDomReady', (isReady: boolean) => {
|
|
156
|
+
this.pusherIsReady = isReady
|
|
157
|
+
taskMachine.setPusherDomReady(isReady)
|
|
158
|
+
if (isReady) {
|
|
159
|
+
this.trtc.createPusher({})
|
|
160
|
+
taskMachine.send(TaskQueueEvent.SETPROCESS)
|
|
161
|
+
} else {
|
|
162
|
+
if (this.isEnterRoom) {
|
|
163
|
+
this.exitRoom()
|
|
164
|
+
}
|
|
165
|
+
taskMachine.send(TaskQueueEvent.SETDONE)
|
|
166
|
+
}
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
this.InterfaceEventEmitter.on('playerDomReady', ({isReady, view}) => {
|
|
170
|
+
taskMachine.setPlayerDomReady(view, isReady)
|
|
171
|
+
if (isReady) {
|
|
172
|
+
taskMachine.send(TaskQueueEvent.SETPROCESS, view)
|
|
173
|
+
} else {
|
|
174
|
+
taskMachine.send(TaskQueueEvent.SETDONE, view)
|
|
175
|
+
}
|
|
176
|
+
})
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
private bindTRTCEvent(): void {
|
|
180
|
+
this.trtc.on(this.TRTC_EVENT.LOCAL_LEAVE, (event) => {
|
|
181
|
+
// todo 第二个参数为进房耗时 此处调用start的时候处理
|
|
182
|
+
// this.emit('onEnterRoom', 0)
|
|
183
|
+
})
|
|
184
|
+
this.trtc.on(this.TRTC_EVENT.PLAYER_WARNING, (event) => {
|
|
185
|
+
const {code, message} = event.data
|
|
186
|
+
this.emit('onWarnning', code, message)
|
|
187
|
+
})
|
|
188
|
+
this.trtc.on(this.TRTC_EVENT.ERROR, (event) => {
|
|
189
|
+
const {code, message} = event.data
|
|
190
|
+
this.emit('onError', code, message)
|
|
191
|
+
})
|
|
192
|
+
this.trtc.on(this.TRTC_EVENT.REMOTE_USER_JOIN, (event) => {
|
|
193
|
+
const {userID} = event.data
|
|
194
|
+
this.emit('onRemoteUserEnterRoom', userID)
|
|
195
|
+
})
|
|
196
|
+
// 远端用户退出
|
|
197
|
+
this.trtc.on(this.TRTC_EVENT.REMOTE_USER_LEAVE, (event) => {
|
|
198
|
+
const {userID, playerList} = event.data
|
|
199
|
+
this.InterfaceEventEmitter.emit('onRemoteUserLeaveRoom', userID, 0)
|
|
200
|
+
this.emit('onUserVideoAvailable', userID, 0)
|
|
201
|
+
this.emit('onUserSubStreamAvailable', userID, 0)
|
|
202
|
+
this.emit('onRemoteUserLeaveRoom', userID, 0)
|
|
203
|
+
})
|
|
204
|
+
// 远端用户推送视频
|
|
205
|
+
this.trtc.on(this.TRTC_EVENT.REMOTE_VIDEO_ADD, (event) => {
|
|
206
|
+
const {player} = event.data
|
|
207
|
+
this.emit(player.streamType === 'aux' ? 'onUserSubStreamAvailable' : 'onUserVideoAvailable', player.userID, 1)
|
|
208
|
+
})
|
|
209
|
+
// 远端用户取消推送视频
|
|
210
|
+
this.trtc.on(this.TRTC_EVENT.REMOTE_VIDEO_REMOVE, (event) => {
|
|
211
|
+
const {player} = event.data
|
|
212
|
+
this.emit(player.streamType === 'aux' ? 'onUserSubStreamAvailable' : 'onUserVideoAvailable', player.userID, 0)
|
|
213
|
+
})
|
|
214
|
+
// 远端用户推送音频
|
|
215
|
+
this.trtc.on(this.TRTC_EVENT.REMOTE_AUDIO_ADD, (event) => {
|
|
216
|
+
const {player} = event.data
|
|
217
|
+
this.emit('onUserAudioAvailable', player.userID, 1)
|
|
218
|
+
})
|
|
219
|
+
// 远端用户取消推送音频
|
|
220
|
+
this.trtc.on(this.TRTC_EVENT.REMOTE_AUDIO_REMOVE, (event) => {
|
|
221
|
+
const {player} = event.data
|
|
222
|
+
this.emit('onUserAudioAvailable', player.userID, 0)
|
|
223
|
+
})
|
|
224
|
+
this.trtc.on(this.TRTC_EVENT.REMOTE_AUDIO_VOLUME_UPDATE, (event) => {
|
|
225
|
+
const {playerList} = event.data
|
|
226
|
+
const userVolumes = playerList.map((player) => ({
|
|
227
|
+
userId: player.userID,
|
|
228
|
+
volume: player.volume,
|
|
229
|
+
}))
|
|
230
|
+
this.handleAudioVolumeUpdate(userVolumes)
|
|
231
|
+
})
|
|
232
|
+
this.trtc.on(this.TRTC_EVENT.LOCAL_AUDIO_VOLUME_UPDATE, (event) => {
|
|
233
|
+
const {pusher} = event.data
|
|
234
|
+
const userVolumes = [
|
|
235
|
+
{
|
|
236
|
+
userId: pusher.userID,
|
|
237
|
+
volume: pusher.volume,
|
|
238
|
+
},
|
|
239
|
+
]
|
|
240
|
+
this.handleAudioVolumeUpdate(userVolumes)
|
|
241
|
+
})
|
|
242
|
+
this.trtc.on(this.TRTC_EVENT.LOCAL_NET_STATE_UPDATE, (event) => {
|
|
243
|
+
const {pusher} = event.data
|
|
244
|
+
this.handleNetworkQuality({pusher})
|
|
245
|
+
})
|
|
246
|
+
this.trtc.on(this.TRTC_EVENT.REMOTE_NET_STATE_UPDATE, (event) => {
|
|
247
|
+
const {playerList} = event.data
|
|
248
|
+
this.handleNetworkQuality({playerList})
|
|
249
|
+
})
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
private offTRTCEvent(): void {
|
|
253
|
+
this.trtc.off(this.TRTC_EVENT.LOCAL_LEAVE)
|
|
254
|
+
this.trtc.off(this.TRTC_EVENT.ERROR)
|
|
255
|
+
this.trtc.off(this.TRTC_EVENT.REMOTE_USER_JOIN)
|
|
256
|
+
this.trtc.off(this.TRTC_EVENT.REMOTE_USER_LEAVE)
|
|
257
|
+
this.trtc.off(this.TRTC_EVENT.REMOTE_VIDEO_ADD)
|
|
258
|
+
this.trtc.off(this.TRTC_EVENT.REMOTE_VIDEO_REMOVE)
|
|
259
|
+
this.trtc.off(this.TRTC_EVENT.REMOTE_AUDIO_ADD)
|
|
260
|
+
this.trtc.off(this.TRTC_EVENT.REMOTE_AUDIO_REMOVE)
|
|
261
|
+
this.trtc.off(this.TRTC_EVENT.REMOTE_AUDIO_VOLUME_UPDATE)
|
|
262
|
+
this.trtc.off(this.TRTC_EVENT.REMOTE_NET_STATE_UPDATE)
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
private getHandleAudioVolumeUpdate(
|
|
266
|
+
interval: number
|
|
267
|
+
): (userVolumes: Array<TRTCVolumeInfo>) => void {
|
|
268
|
+
if (this.allTimer?.AudioVolume) {
|
|
269
|
+
clearInterval(this.allTimer.AudioVolume)
|
|
270
|
+
this.allTimer.AudioVolume = null
|
|
271
|
+
}
|
|
272
|
+
if (interval === 0) return (): void => { }
|
|
273
|
+
let tempUserVolumes = []
|
|
274
|
+
const filterUselessItem = function (userId: string): void {
|
|
275
|
+
tempUserVolumes = tempUserVolumes.filter(userVolume => userVolume.userId !== userId)
|
|
276
|
+
}
|
|
277
|
+
this.InterfaceEventEmitter.off('onRemoteUserLeaveRoom') // 防止重复监听
|
|
278
|
+
this.InterfaceEventEmitter.on('onRemoteUserLeaveRoom', filterUselessItem, this.getHandleAudioVolumeUpdate)
|
|
279
|
+
return (userVolumes: Array<TRTCVolumeInfo>): void => {
|
|
280
|
+
tempUserVolumes = uniqueFunc(
|
|
281
|
+
[...userVolumes, ...tempUserVolumes],
|
|
282
|
+
'userId'
|
|
283
|
+
)
|
|
284
|
+
if (this.allTimer.AudioVolume) return
|
|
285
|
+
const timer = setInterval(() => {
|
|
286
|
+
this.emit(
|
|
287
|
+
'onUserVoiceVolume',
|
|
288
|
+
tempUserVolumes,
|
|
289
|
+
tempUserVolumes.length,
|
|
290
|
+
0 // todo 此参数无用,暂时废弃
|
|
291
|
+
)
|
|
292
|
+
}, interval)
|
|
293
|
+
this.allTimer.AudioVolume = timer
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
private handleAudioVolumeUpdate(userVolumes: Array<TRTCVolumeInfo>): void { }
|
|
298
|
+
|
|
299
|
+
private getHandleNetworkQuality(
|
|
300
|
+
interval: number
|
|
301
|
+
): (data: {
|
|
302
|
+
pusher?: Record<string, unknown>;
|
|
303
|
+
playerList?: Array<Record<string, unknown>>;
|
|
304
|
+
}) => void {
|
|
305
|
+
if (this.allTimer?.networkQuality) {
|
|
306
|
+
clearInterval(this.allTimer.networkQuality)
|
|
307
|
+
this.allTimer.networkQuality = null
|
|
308
|
+
}
|
|
309
|
+
if (interval === 0) return (): void => { }
|
|
310
|
+
const resultQuality = {localQuality: null, remoteQuality: []}
|
|
311
|
+
this.on('onRemoteUserLeaveRoom', (userId) => {
|
|
312
|
+
resultQuality.remoteQuality = resultQuality.remoteQuality.filter(quality => quality.userId !== userId)
|
|
313
|
+
}, this)
|
|
314
|
+
|
|
315
|
+
return (data): void => {
|
|
316
|
+
const {pusher, playerList} = data
|
|
317
|
+
if (pusher) resultQuality.localQuality = {userId: pusher.userID, quality: pusher.netStatus}
|
|
318
|
+
if (playerList) {
|
|
319
|
+
resultQuality.remoteQuality = playerList.map(player => ({
|
|
320
|
+
userId: player.userID,
|
|
321
|
+
quality: player.netStatus
|
|
322
|
+
}))
|
|
323
|
+
}
|
|
324
|
+
if (this.allTimer.networkQuality) return
|
|
325
|
+
const timer = setInterval(() => {
|
|
326
|
+
this.emit('onNetworkQuality', resultQuality.localQuality, resultQuality.remoteQuality)
|
|
327
|
+
}, interval)
|
|
328
|
+
this.allTimer.networkQuality = timer
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
private handleNetworkQuality(quality: {
|
|
333
|
+
pusher?: Record<string, unknown>;
|
|
334
|
+
playerList?: Array<Record<string, unknown>>;
|
|
335
|
+
}): void { }
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* @category Base
|
|
339
|
+
*/
|
|
340
|
+
on(eventName, handler, context): void {
|
|
341
|
+
this.EventEmitter.on(eventName, handler, context)
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* @category Base
|
|
346
|
+
*/
|
|
347
|
+
off(eventName, handler, context): void {
|
|
348
|
+
this.EventEmitter.off(eventName, handler, context)
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* @category Base
|
|
353
|
+
*/
|
|
354
|
+
emit(eventName, ...args): void {
|
|
355
|
+
this.EventEmitter.emit(eventName, ...args)
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* @category 房间
|
|
360
|
+
*/
|
|
361
|
+
async enterRoom(params: TRTCParams, scene: TRTCAppScene): Promise<void> {
|
|
362
|
+
if (this.isEnterRoom) {
|
|
363
|
+
logger.warn('You are already in the room, please exit the current room first.')
|
|
364
|
+
return
|
|
365
|
+
}
|
|
366
|
+
this.trtc.createPusher({})
|
|
367
|
+
const startTime = new Date().getTime()
|
|
368
|
+
const {
|
|
369
|
+
sdkAppId,
|
|
370
|
+
userId,
|
|
371
|
+
userSig,
|
|
372
|
+
roomId,
|
|
373
|
+
strRoomId,
|
|
374
|
+
role,
|
|
375
|
+
privateMapKey,
|
|
376
|
+
} = params
|
|
377
|
+
logger.setInfo({sdkAppId, userId, roomId: strRoomId})
|
|
378
|
+
logger.info('enterRoom with options: ', JSON.stringify(params), scene)
|
|
379
|
+
this.userId = userId
|
|
380
|
+
this.isEnterRoom = true
|
|
381
|
+
try {
|
|
382
|
+
await this.setAttributes({
|
|
383
|
+
params: {
|
|
384
|
+
sdkAppID: sdkAppId, // 您的腾讯云账号
|
|
385
|
+
userID: userId, // 当前进房用户的userID
|
|
386
|
+
userSig, // 您服务端生成的userSig
|
|
387
|
+
roomID: roomId, // 您进房的房间号,
|
|
388
|
+
strRoomID: strRoomId,
|
|
389
|
+
role,
|
|
390
|
+
privateMapKey,
|
|
391
|
+
scene: translateTRTCAppScene(scene),
|
|
392
|
+
enableMic: false, // 进房默认开启音频上行
|
|
393
|
+
enableCamera: false, // 进房默认开启视频上行
|
|
394
|
+
videoPreview: false,
|
|
395
|
+
encsmall: this.encsmall,
|
|
396
|
+
enableinfiniteanchor: this.enableinfiniteanchor, // 是否开启无限主播
|
|
397
|
+
recvMode: this.enableinfiniteanchor ? 2 : 1, // 1 自动接收音视频 2 仅自动接收音频
|
|
398
|
+
}
|
|
399
|
+
}, 'enterRoom')
|
|
400
|
+
} catch (error) {
|
|
401
|
+
this.isEnterRoom = false
|
|
402
|
+
logger.info('enterRoom fail')
|
|
403
|
+
this.emit('onEnterRoom', -1)
|
|
404
|
+
}
|
|
405
|
+
this.trtc.getPusherInstance().start({
|
|
406
|
+
success: async () => {
|
|
407
|
+
logger.info('enterRoom success')
|
|
408
|
+
this.scene = scene
|
|
409
|
+
const endTime = new Date().getTime()
|
|
410
|
+
this.emit('onEnterRoom', endTime - startTime)
|
|
411
|
+
if (this.trtc.getPusherAttributes().videoPreview === true) {
|
|
412
|
+
// 如果进房前有打开摄像头,需要开启视频上行,并抛出 onSendFirstLocalVideoFrame 事件
|
|
413
|
+
await this.setAttributes(
|
|
414
|
+
{
|
|
415
|
+
params: {
|
|
416
|
+
videoPreview: false,
|
|
417
|
+
enableCamera: true,
|
|
418
|
+
}
|
|
419
|
+
},
|
|
420
|
+
'other'
|
|
421
|
+
)
|
|
422
|
+
this.emit(
|
|
423
|
+
'onSendFirstLocalVideoFrame',
|
|
424
|
+
TRTCVideoStreamType.TRTCVideoStreamTypeBig,
|
|
425
|
+
)
|
|
426
|
+
}
|
|
427
|
+
},
|
|
428
|
+
fail: () => {
|
|
429
|
+
this.isEnterRoom = false
|
|
430
|
+
logger.info('enterRoom fail')
|
|
431
|
+
this.emit('onEnterRoom', -1)
|
|
432
|
+
},
|
|
433
|
+
})
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* @category 房间
|
|
438
|
+
*/
|
|
439
|
+
exitRoom(): void {
|
|
440
|
+
logger.info('exitRoom')
|
|
441
|
+
const {pusher} = this.trtc.exitRoom()
|
|
442
|
+
this.reset()
|
|
443
|
+
if (!this.pusherIsReady) {
|
|
444
|
+
logger.info('exitRoom success')
|
|
445
|
+
this.emit('onExitRoom', 0)
|
|
446
|
+
} else {
|
|
447
|
+
this.InterfaceEventEmitter.emit('pusherAttributesChange', {
|
|
448
|
+
pusher,
|
|
449
|
+
callback: () => {
|
|
450
|
+
logger.info('exitRoom success')
|
|
451
|
+
this.emit('onExitRoom', 0)
|
|
452
|
+
},
|
|
453
|
+
})
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
/**
|
|
458
|
+
* @category 房间
|
|
459
|
+
*/
|
|
460
|
+
switchRoom(): void { }
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* 切换角色,仅适用于直播场景(TRTCAppSceneLIVE 和 TRTCAppSceneVoiceChatRoom)
|
|
464
|
+
* @category 房间
|
|
465
|
+
*/
|
|
466
|
+
async switchRole(role: TRTCRoleType): Promise<void> {
|
|
467
|
+
logger.info('switchRole with options: ', role)
|
|
468
|
+
const tempRole = this.role
|
|
469
|
+
this.role = role
|
|
470
|
+
if (tempRole === role || role === TRTCRoleType.TRTCRoleAnchor) {
|
|
471
|
+
logger.info('switchRole success')
|
|
472
|
+
this.emit('onSwitchRole', 0, '')
|
|
473
|
+
return
|
|
474
|
+
}
|
|
475
|
+
await this.setAttributes({params: {enableCamera: false, enableMic: false}}, 'switchRole')
|
|
476
|
+
logger.info('switchRole success')
|
|
477
|
+
this.emit('onSwitchRole', 0, '')
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
connectOtherRoom(): void { }
|
|
481
|
+
|
|
482
|
+
disconnectOtherRoom(): void { }
|
|
483
|
+
|
|
484
|
+
setDefaultStreamRecvMode(): void { }
|
|
485
|
+
|
|
486
|
+
useVirtualBackground(): void { }
|
|
487
|
+
|
|
488
|
+
/**
|
|
489
|
+
* 启动本地摄像头采集和预览
|
|
490
|
+
* @category 视频
|
|
491
|
+
*/
|
|
492
|
+
async startLocalPreview(frontCamera = true): Promise<void> {
|
|
493
|
+
logger.info('startLocalPreview with options: ', frontCamera)
|
|
494
|
+
if (this.role !== TRTCRoleType.TRTCRoleAnchor) {
|
|
495
|
+
return
|
|
496
|
+
}
|
|
497
|
+
const pusher = await this.setAttributes({
|
|
498
|
+
params: () => ({
|
|
499
|
+
videoPreview: this.isEnterRoom ? this.isVideoMuted : true,
|
|
500
|
+
enableCamera: this.isEnterRoom ? !this.isVideoMuted : false,
|
|
501
|
+
frontCamera: frontCamera ? 'front' : 'back',
|
|
502
|
+
})
|
|
503
|
+
}, 'startLocalPreview')
|
|
504
|
+
logger.info('startLocalPreview success')
|
|
505
|
+
this.emit('onCameraDidReady')
|
|
506
|
+
this.emit(
|
|
507
|
+
'onFirstVideoFrame',
|
|
508
|
+
'',
|
|
509
|
+
TRTCVideoStreamType.TRTCVideoStreamTypeBig,
|
|
510
|
+
pusher.videoWidth,
|
|
511
|
+
pusher.videoHeight
|
|
512
|
+
)
|
|
513
|
+
if (this.isEnterRoom) {
|
|
514
|
+
this.emit(
|
|
515
|
+
'onSendFirstLocalVideoFrame',
|
|
516
|
+
TRTCVideoStreamType.TRTCVideoStreamTypeBig,
|
|
517
|
+
)
|
|
518
|
+
}
|
|
519
|
+
this.isOpenCamera = true
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
/**
|
|
523
|
+
* 停止本地摄像头采集和预览
|
|
524
|
+
* @category 视频
|
|
525
|
+
*/
|
|
526
|
+
async stopLocalPreview(): Promise<void> {
|
|
527
|
+
logger.info('stopLocalPreview')
|
|
528
|
+
await this.setAttributes({
|
|
529
|
+
params: {
|
|
530
|
+
videoPreview: false,
|
|
531
|
+
enableCamera: false,
|
|
532
|
+
}
|
|
533
|
+
}, 'stopLocalPreview')
|
|
534
|
+
logger.info('stopLocalPreview success')
|
|
535
|
+
this.isOpenCamera = false
|
|
536
|
+
this.emit('onUserVideoAvailable', this.userId, 0)
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
/**
|
|
540
|
+
* 修改本地摄像头预览的 HTML 元素,小程序不支持
|
|
541
|
+
* @category 视频
|
|
542
|
+
*/
|
|
543
|
+
updateLocalView(view: string | null): void {
|
|
544
|
+
logger.info('updateLocalView with options: ', view)
|
|
545
|
+
if (view !== null) {
|
|
546
|
+
this.startLocalPreview()
|
|
547
|
+
return
|
|
548
|
+
}
|
|
549
|
+
this.stopLocalPreview()
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* 暂停/恢复发布本地的视频流
|
|
554
|
+
* @category 视频
|
|
555
|
+
* @param {boolean} mute true:屏蔽;false:开启,默认值:false
|
|
556
|
+
* @param {TRTCVideoStreamType} streamType 要暂停/恢复的视频流类型, 仅支持 TRTCVideoStreamTypeBig 和 TRTCVideoStreamTypeSub
|
|
557
|
+
*/
|
|
558
|
+
async muteLocalVideo(
|
|
559
|
+
mute: boolean,
|
|
560
|
+
streamType: TRTCVideoStreamType
|
|
561
|
+
): Promise<void> {
|
|
562
|
+
logger.info('muteLocalVideo called with options: ', mute, streamType)
|
|
563
|
+
if (!this.isOpenCamera) {
|
|
564
|
+
logger.info('muteLocalVideo early exit: isOpenCamera is false')
|
|
565
|
+
return
|
|
566
|
+
}
|
|
567
|
+
switch (streamType) {
|
|
568
|
+
case TRTCVideoStreamType.TRTCVideoStreamTypeBig:
|
|
569
|
+
case TRTCVideoStreamType.TRTCVideoStreamTypeSub:
|
|
570
|
+
this.isVideoMuted = mute
|
|
571
|
+
logger.info('muteLocalVideo: isVideoMuted set to ', mute)
|
|
572
|
+
try {
|
|
573
|
+
await this.setAttributes({
|
|
574
|
+
params: {
|
|
575
|
+
videoPreview: mute,
|
|
576
|
+
enableCamera: !mute,
|
|
577
|
+
}
|
|
578
|
+
}, 'muteLocalVideo')
|
|
579
|
+
logger.info('muteLocalVideo: setAttributes success')
|
|
580
|
+
} catch (error) {
|
|
581
|
+
logger.error('muteLocalVideo: setAttributes failed with error ', error)
|
|
582
|
+
}
|
|
583
|
+
logger.info('muteLocalVideo success')
|
|
584
|
+
break
|
|
585
|
+
default:
|
|
586
|
+
logger.info('muteLocalVideo: streamType not supported ', streamType)
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
/**
|
|
591
|
+
* 开始显示远端视频画面
|
|
592
|
+
* @category 视频
|
|
593
|
+
* @param userId 对方的用户标识
|
|
594
|
+
* @param view 此参数无效,小程序不支持
|
|
595
|
+
* @param streamType 视频流类型
|
|
596
|
+
*/
|
|
597
|
+
async startRemoteView(
|
|
598
|
+
userId: string,
|
|
599
|
+
view: string,
|
|
600
|
+
streamType: TRTCVideoStreamType
|
|
601
|
+
): Promise<void> {
|
|
602
|
+
logger.info('startRemoteView with options: ', userId, view, streamType)
|
|
603
|
+
const streamId = translateTRTCStreamId(userId, streamType) // trtc
|
|
604
|
+
this.renderMap.set(streamId, view)
|
|
605
|
+
await this.setAttributes({
|
|
606
|
+
params: {
|
|
607
|
+
muteVideo: false,
|
|
608
|
+
stopVideo: false,
|
|
609
|
+
},
|
|
610
|
+
streamId,
|
|
611
|
+
view
|
|
612
|
+
}, 'startRemoteView')
|
|
613
|
+
this.updateAudioRoute()
|
|
614
|
+
logger.info('startRemoteView success')
|
|
615
|
+
this.emit('onFirstVideoFrame', userId, streamType, 0, 0)
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
/**
|
|
619
|
+
* 停止显示远端视频画面,同时不再拉取该远端用户的视频数据流
|
|
620
|
+
* @param userId 对方的用户标识
|
|
621
|
+
* @param streamType 视频流类型
|
|
622
|
+
*/
|
|
623
|
+
async stopRemoteView(userId: string, streamType: TRTCVideoStreamType): Promise<void> {
|
|
624
|
+
logger.info('stopRemoteView with options: ', userId, streamType)
|
|
625
|
+
const streamId = translateTRTCStreamId(userId, streamType)
|
|
626
|
+
await this.setAttributes({
|
|
627
|
+
params: {
|
|
628
|
+
muteVideo: true,
|
|
629
|
+
stopVideo: true,
|
|
630
|
+
},
|
|
631
|
+
streamId,
|
|
632
|
+
view: this.renderMap.get(streamId),
|
|
633
|
+
}, 'stopRemoteView')
|
|
634
|
+
logger.info('stopRemoteView success')
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
/**
|
|
638
|
+
* 修改远端视频渲染的 HTML 元素,小程序不支持
|
|
639
|
+
* @param userId 远端视频流的用户 ID
|
|
640
|
+
* @param view
|
|
641
|
+
* 接受远端视频流渲染的 HTML 元素,传入 null 结束远端视频的渲染
|
|
642
|
+
* - 传入的 HTML 元素必须时块元素,例如:div
|
|
643
|
+
* @param streamType
|
|
644
|
+
* @returns
|
|
645
|
+
*/
|
|
646
|
+
async updateRemoteView(
|
|
647
|
+
userId: string,
|
|
648
|
+
view: string,
|
|
649
|
+
streamType: TRTCVideoStreamType
|
|
650
|
+
): Promise<void> {
|
|
651
|
+
logger.info('updateRemoteView with options: ', userId, view, streamType)
|
|
652
|
+
if (view !== null) {
|
|
653
|
+
await this.startRemoteView(userId, view, streamType)
|
|
654
|
+
return
|
|
655
|
+
}
|
|
656
|
+
await this.stopRemoteView(userId, streamType)
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
|
|
660
|
+
// 停止显示所有远端视频画面,同时不再拉取该远端用户的视频数据流
|
|
661
|
+
async stopAllRemoteView(): Promise<void> {
|
|
662
|
+
logger.info('stopAllRemoteView')
|
|
663
|
+
const playerList = this.trtc.getPlayerList()
|
|
664
|
+
playerList.forEach(async (player) => {
|
|
665
|
+
const streamId = player.streamID
|
|
666
|
+
await this.setAttributes({
|
|
667
|
+
params: {
|
|
668
|
+
muteVideo: true,
|
|
669
|
+
stopVideo: true,
|
|
670
|
+
},
|
|
671
|
+
streamId,
|
|
672
|
+
view: this.renderMap.get(streamId),
|
|
673
|
+
}, 'stopAllRemoteView')
|
|
674
|
+
})
|
|
675
|
+
logger.info('stopAllRemoteView success')
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
// 暂停接收指定的远端视频流
|
|
679
|
+
// 该接口仅停止接收远程用户的视频流,但并不释放显示资源,所以视频画面会冻屏在 mute 前的最后一帧。
|
|
680
|
+
async muteRemoteVideoStream(
|
|
681
|
+
userId: string,
|
|
682
|
+
mute: boolean,
|
|
683
|
+
streamType: TRTCVideoStreamType
|
|
684
|
+
): Promise<void> {
|
|
685
|
+
logger.info('muteRemoteVideoStream')
|
|
686
|
+
const streamId = translateTRTCStreamId(userId, streamType)
|
|
687
|
+
await this.setAttributes({
|
|
688
|
+
params: {muteVideo: mute},
|
|
689
|
+
streamId,
|
|
690
|
+
view: this.renderMap.get(streamId),
|
|
691
|
+
}, 'muteRemoteVideoStream')
|
|
692
|
+
logger.info('muteRemoteVideoStream success')
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
async muteAllRemoteVideoStreams(mute: boolean): Promise<void> {
|
|
696
|
+
logger.info('muteAllRemoteVideoStreams with options: ', mute)
|
|
697
|
+
const playerList = this.trtc.getPlayerList()
|
|
698
|
+
playerList.forEach(async (player) => {
|
|
699
|
+
const streamId = player.streamID
|
|
700
|
+
await this.setAttributes({
|
|
701
|
+
params: {muteVideo: mute},
|
|
702
|
+
streamId,
|
|
703
|
+
view: this.renderMap.get(streamId),
|
|
704
|
+
}, 'muteAllRemoteVideoStreams')
|
|
705
|
+
})
|
|
706
|
+
logger.info('muteAllRemoteVideoStreams success')
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
private setTRTCPlayerAttributes(streamId, options): object {
|
|
710
|
+
logger.info('setTRTCPlayerAttributes with options: ', streamId, options)
|
|
711
|
+
this.trtc.setPlayerAttributes(streamId, options)
|
|
712
|
+
return this.trtc.getPlayerInstance(streamId)?.playerAttributes || {}
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
async setVideoEncoderParam(params: TRTCVideoEncParam): Promise<void> {
|
|
716
|
+
logger.info('setVideoEncoderParam with options: ', JSON.stringify(params))
|
|
717
|
+
const {
|
|
718
|
+
videoResolution,
|
|
719
|
+
resMode,
|
|
720
|
+
videoFps,
|
|
721
|
+
videoBitrate,
|
|
722
|
+
minVideoBitrate,
|
|
723
|
+
} = params
|
|
724
|
+
const {videoWidth, videoHeight} =
|
|
725
|
+
translateTRTCVideoResolution(videoResolution)
|
|
726
|
+
await this.setAttributes({
|
|
727
|
+
params: {
|
|
728
|
+
videoWidth,
|
|
729
|
+
videoHeight,
|
|
730
|
+
// videoOrientation,
|
|
731
|
+
fps: videoFps,
|
|
732
|
+
minBitrate: minVideoBitrate,
|
|
733
|
+
}
|
|
734
|
+
}, 'setVideoEncoderParam')
|
|
735
|
+
logger.info('setVideoEncoderParam success')
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
async setLocalRenderParams(params: TRTCRenderParams): Promise<void> {
|
|
739
|
+
logger.info('setLocalRenderParams with options: ', JSON.stringify(params))
|
|
740
|
+
const {rotation, fillMode, mirrorType} = params
|
|
741
|
+
const videoOrientation = translateTRTCVideoRotation(rotation)
|
|
742
|
+
const localMirror = translateTRTCVideoMirrorType(mirrorType)
|
|
743
|
+
await this.setAttributes({
|
|
744
|
+
params: {
|
|
745
|
+
videoOrientation,
|
|
746
|
+
localMirror,
|
|
747
|
+
}
|
|
748
|
+
}, 'setLocalRenderParams')
|
|
749
|
+
logger.info('setLocalRenderParams success')
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
/**
|
|
753
|
+
* 设置远端图像的渲染模式
|
|
754
|
+
* @param {string} userId
|
|
755
|
+
* @param {TRTCVideoStreamType} streamType
|
|
756
|
+
* @param {TRTCRenderParams} params
|
|
757
|
+
*/
|
|
758
|
+
async setRemoteRenderParams(
|
|
759
|
+
userId: string, streamType: TRTCVideoStreamType, params: TRTCRenderParams
|
|
760
|
+
): Promise<void> {
|
|
761
|
+
logger.info('setRemoteRenderParams with options: ', userId, streamType, JSON.stringify(params))
|
|
762
|
+
const {fillMode, rotation, mirrorType} = params
|
|
763
|
+
const streamId = translateTRTCStreamId(userId, streamType) // 音频默认都是主流
|
|
764
|
+
await this.setAttributes({
|
|
765
|
+
params: {
|
|
766
|
+
objectFit: translateVideoFillMod(fillMode),
|
|
767
|
+
orientation: translateTRTCVideoRotation(rotation)
|
|
768
|
+
},
|
|
769
|
+
streamId,
|
|
770
|
+
view: this.renderMap.get(streamId),
|
|
771
|
+
}, 'setRemoteRenderParams')
|
|
772
|
+
logger.info('setRemoteRenderParams success')
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
async startLocalAudio(quality: TRTCAudioQuality): Promise<void> {
|
|
776
|
+
logger.info('startLocalAudio with options: ', quality)
|
|
777
|
+
if (this.role !== TRTCRoleType.TRTCRoleAnchor) {
|
|
778
|
+
throw new Error('Current role is audience, unable to access mic. Call switchRole to become a host.')
|
|
779
|
+
}
|
|
780
|
+
const getAudioQuality = (quality: TRTCAudioQuality) => {
|
|
781
|
+
if (quality === TRTCAudioQuality.TRTCAudioQualitySpeech) {
|
|
782
|
+
return 'low'
|
|
783
|
+
}
|
|
784
|
+
return 'high'
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
await this.setAttributes({params: {enableMic: true, audioQuality: getAudioQuality(quality)}}, 'startLocalAudio')
|
|
788
|
+
logger.info('startLocalAudio success')
|
|
789
|
+
this.emit('onMicDidReady')
|
|
790
|
+
if (this.enterRoom) {
|
|
791
|
+
this.emit('onSendFirstLocalAudioFrame')
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
async stopLocalAudio(): Promise<void> {
|
|
796
|
+
logger.info('stopLocalAudio')
|
|
797
|
+
await this.setAttributes({params: {enableMic: false}}, 'stopLocalAudio')
|
|
798
|
+
logger.info('stopLocalAudio success')
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
async muteLocalAudio(mute: boolean): Promise<void> {
|
|
802
|
+
logger.info('muteLocalAudio called with options: ', mute)
|
|
803
|
+
|
|
804
|
+
try {
|
|
805
|
+
await this.setAttributes({params: {muted: mute}}, 'muteLocalAudio')
|
|
806
|
+
logger.info('setAttributes executed successfully')
|
|
807
|
+
} catch (error) {
|
|
808
|
+
logger.error('Error in setAttributes: ', error)
|
|
809
|
+
throw error
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
try {
|
|
813
|
+
this.emit('onUserAudioAvailable', this.userId, mute === true ? 0 : 1)
|
|
814
|
+
logger.info('onUserAudioAvailable event emitted successfully')
|
|
815
|
+
} catch (error) {
|
|
816
|
+
logger.error('Error in emitting onUserAudioAvailable event: ', error)
|
|
817
|
+
throw error
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
logger.info('muteLocalAudio execution finished')
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
async setAudioRoute(route: TRTCAudioRoute): Promise<void> {
|
|
824
|
+
logger.info('setAudioRoute with options: ', route)
|
|
825
|
+
this.currentSoundMode = route
|
|
826
|
+
const soundMode = translateTRTCAudioRoute(route)
|
|
827
|
+
try {
|
|
828
|
+
await this.playerAudioRouteChange({
|
|
829
|
+
soundMode,
|
|
830
|
+
})
|
|
831
|
+
logger.info('setAudioRoute success')
|
|
832
|
+
} catch (error) {
|
|
833
|
+
logger.error('Error in setAttributes: ', error)
|
|
834
|
+
throw error
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
private async updateAudioRoute(): Promise<void> {
|
|
839
|
+
logger.info('updateAudioRoute with options: ', this.currentSoundMode)
|
|
840
|
+
const soundMode = translateTRTCAudioRoute(this.currentSoundMode)
|
|
841
|
+
try {
|
|
842
|
+
await this.playerAudioRouteChange({
|
|
843
|
+
soundMode,
|
|
844
|
+
})
|
|
845
|
+
} catch (error) {
|
|
846
|
+
logger.error('Error in setAttributes: ', error)
|
|
847
|
+
throw error
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
async muteRemoteAudio(userId: string, mute: boolean): Promise<void> {
|
|
852
|
+
logger.info('muteRemoteAudio with options: ', userId, mute)
|
|
853
|
+
const streamId = translateTRTCStreamId(
|
|
854
|
+
userId,
|
|
855
|
+
TRTCVideoStreamType.TRTCVideoStreamTypeBig
|
|
856
|
+
) // 音频默认都是主流
|
|
857
|
+
await this.setAttributes({
|
|
858
|
+
params: {
|
|
859
|
+
muteAudio: mute,
|
|
860
|
+
},
|
|
861
|
+
streamId,
|
|
862
|
+
view: this.renderMap.get(streamId),
|
|
863
|
+
}, 'muteRemoteAudio')
|
|
864
|
+
logger.info('muteRemoteAudio success')
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
async muteAllRemoteAudio(mute: boolean): Promise<void> {
|
|
868
|
+
logger.info('muteAllRemoteAudio with options: ', mute)
|
|
869
|
+
const playerList = this.trtc.getPlayerList()
|
|
870
|
+
playerList.forEach(async (player) => {
|
|
871
|
+
const streamId = player.streamID
|
|
872
|
+
await this.setAttributes({
|
|
873
|
+
params: {
|
|
874
|
+
muteAudio: mute,
|
|
875
|
+
},
|
|
876
|
+
streamId,
|
|
877
|
+
view: this.renderMap.get(streamId),
|
|
878
|
+
}, 'muteRemoteAudio')
|
|
879
|
+
})
|
|
880
|
+
logger.info('muteAllRemoteAudio success')
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
enableAudioVolumeEvaluation(interval: number): void {
|
|
884
|
+
logger.info('enableAudioVolumeEvaluation with options: ', interval)
|
|
885
|
+
this.handleAudioVolumeUpdate = this.getHandleAudioVolumeUpdate(interval)
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
/**
|
|
889
|
+
* 切换前后摄像头
|
|
890
|
+
*/
|
|
891
|
+
switchCamera(frontCamera: boolean): Promise<any> {
|
|
892
|
+
logger.info('switchCamera with options: ', frontCamera)
|
|
893
|
+
const pusher = this.trtc.getPusherInstance()
|
|
894
|
+
if (frontCamera === (pusher.pusherAttributes.frontCamera === 'front')) return Promise.resolve()
|
|
895
|
+
return new Promise((resolve, reject) => {
|
|
896
|
+
wx.createLivePusherContext().switchCamera({
|
|
897
|
+
success: async (event) => {
|
|
898
|
+
await this.setAttributes(
|
|
899
|
+
{params: {frontCamera: frontCamera ? 'front' : 'back'}},
|
|
900
|
+
'switchCamera'
|
|
901
|
+
)
|
|
902
|
+
logger.info('switchCamera success')
|
|
903
|
+
resolve(event)
|
|
904
|
+
},
|
|
905
|
+
fail: (error) => {
|
|
906
|
+
logger.info('switchCamera fail')
|
|
907
|
+
reject(error)
|
|
908
|
+
},
|
|
909
|
+
})
|
|
910
|
+
})
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
async setBeautyStyle(
|
|
914
|
+
style: TRTCBeautyStyle,
|
|
915
|
+
beauty: number,
|
|
916
|
+
white: number,
|
|
917
|
+
ruddiness: number
|
|
918
|
+
): Promise<void> {
|
|
919
|
+
logger.info('setBeautyStyle with options: ', style, beauty, white, ruddiness)
|
|
920
|
+
await this.setAttributes({
|
|
921
|
+
params: {
|
|
922
|
+
beautyStyle: translateBeautyStyle(style),
|
|
923
|
+
beautyLevel: beauty,
|
|
924
|
+
whitenessLevel: white,
|
|
925
|
+
}
|
|
926
|
+
}, 'setBeautyStyle')
|
|
927
|
+
logger.info('setBeautyStyle success')
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
sendSEIMsg(msg: string, repeatCount = 1): Promise<any> {
|
|
931
|
+
logger.info('sendSEIMsg with options: ', msg, repeatCount)
|
|
932
|
+
return new Promise((resolve, reject) => {
|
|
933
|
+
wx.createLivePusherContext().sendMessage({
|
|
934
|
+
msg,
|
|
935
|
+
success: (event) => {
|
|
936
|
+
logger.info('sendSEIMsg success')
|
|
937
|
+
resolve(event)
|
|
938
|
+
},
|
|
939
|
+
fail: (error) => {
|
|
940
|
+
logger.info('sendSEIMsg fail')
|
|
941
|
+
reject(error)
|
|
942
|
+
},
|
|
943
|
+
})
|
|
944
|
+
})
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
startPlayMusic(
|
|
948
|
+
musicParam: AudioMusicParam,
|
|
949
|
+
callbackMap: Record<'onStart' | 'onPlayProgress' | 'onComplete', () => void>
|
|
950
|
+
): Promise<any> {
|
|
951
|
+
logger.info('startPlayMusic with options: ', JSON.stringify(musicParam))
|
|
952
|
+
return new Promise((resolve, reject) => {
|
|
953
|
+
const {path, startTimeMS = 0, endTimeMS = 0} = musicParam
|
|
954
|
+
wx.createLivePusherContext().playBGM({
|
|
955
|
+
url: path,
|
|
956
|
+
startTimeMs: startTimeMS,
|
|
957
|
+
endTimeMs: endTimeMS,
|
|
958
|
+
success: (event) => {
|
|
959
|
+
logger.info('startPlayMusic success')
|
|
960
|
+
resolve(event)
|
|
961
|
+
},
|
|
962
|
+
fail: (error) => {
|
|
963
|
+
logger.info('startPlayMusic fail')
|
|
964
|
+
reject(error)
|
|
965
|
+
},
|
|
966
|
+
})
|
|
967
|
+
})
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
stopPlayMusic(): Promise<any> {
|
|
971
|
+
logger.info('stopPlayMusic')
|
|
972
|
+
return new Promise((resolve, reject) => {
|
|
973
|
+
wx.createLivePusherContext().stopBGM({
|
|
974
|
+
success: (event) => {
|
|
975
|
+
logger.info('stopPlayMusic success')
|
|
976
|
+
resolve(event)
|
|
977
|
+
},
|
|
978
|
+
fail: (error) => {
|
|
979
|
+
logger.info('stopPlayMusic fail')
|
|
980
|
+
reject(error)
|
|
981
|
+
},
|
|
982
|
+
})
|
|
983
|
+
})
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
pausePlayMusic(): Promise<any> {
|
|
987
|
+
logger.info('pausePlayMusic')
|
|
988
|
+
return new Promise((resolve, reject) => {
|
|
989
|
+
wx.createLivePusherContext().pauseBGM({
|
|
990
|
+
success: (event) => {
|
|
991
|
+
logger.info('pausePlayMusic success')
|
|
992
|
+
resolve(event)
|
|
993
|
+
},
|
|
994
|
+
fail: (error) => {
|
|
995
|
+
logger.info('pausePlayMusic fail')
|
|
996
|
+
reject(error)
|
|
997
|
+
},
|
|
998
|
+
})
|
|
999
|
+
})
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
resumePlayMusic(): Promise<any> {
|
|
1003
|
+
logger.info('resumePlayMusic')
|
|
1004
|
+
return new Promise((resolve, reject) => {
|
|
1005
|
+
wx.createLivePusherContext().resumeBGM({
|
|
1006
|
+
success: (event) => {
|
|
1007
|
+
logger.info('resumePlayMusic success')
|
|
1008
|
+
resolve(event)
|
|
1009
|
+
},
|
|
1010
|
+
fail: (error) => {
|
|
1011
|
+
logger.info('resumePlayMusic fail')
|
|
1012
|
+
reject(error)
|
|
1013
|
+
},
|
|
1014
|
+
})
|
|
1015
|
+
})
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
// 设置背景音乐的音量大小,播放背景音乐混音时使用,用来控制背景音音量大小
|
|
1019
|
+
setAllMusicVolume(volume: number): Promise<any> {
|
|
1020
|
+
logger.info('setAllMusicVolume with options: ', volume)
|
|
1021
|
+
return new Promise((resolve, reject) => {
|
|
1022
|
+
const volumeStr = (volume / 200).toString()
|
|
1023
|
+
wx.createLivePusherContext().setBGMVolume({
|
|
1024
|
+
volume: volumeStr,
|
|
1025
|
+
success: (event) => {
|
|
1026
|
+
logger.info('setAllMusicVolume success')
|
|
1027
|
+
resolve(event)
|
|
1028
|
+
},
|
|
1029
|
+
fail: (error) => {
|
|
1030
|
+
logger.info('setAllMusicVolume fail')
|
|
1031
|
+
reject(error)
|
|
1032
|
+
},
|
|
1033
|
+
})
|
|
1034
|
+
})
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
// 开启大小画面双路编码模式
|
|
1038
|
+
enableSmallVideoStream(enable: boolean, params: TRTCVideoEncParam) {
|
|
1039
|
+
logger.info('enableSmallVideoStream with options: ', enable, JSON.stringify(params))
|
|
1040
|
+
this.encsmall = enable ? 1 : 0
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
/**
|
|
1044
|
+
* 调用实验性 API 接口
|
|
1045
|
+
*
|
|
1046
|
+
* 注意:该接口用于调用一些实验性功能, 目前 web 端空实现
|
|
1047
|
+
*
|
|
1048
|
+
* @param {String} jsonStr - 接口及参数描述的 JSON 字符串
|
|
1049
|
+
*/
|
|
1050
|
+
callExperimentalAPI(jsonStr: string): void {
|
|
1051
|
+
logger.info('callExperimentalAPI with options: ', jsonStr)
|
|
1052
|
+
const jsonObj = safelyParse(jsonStr)
|
|
1053
|
+
if (jsonObj === jsonStr) {
|
|
1054
|
+
return
|
|
1055
|
+
}
|
|
1056
|
+
const {api, params} = jsonObj
|
|
1057
|
+
if (!api || !params) {
|
|
1058
|
+
return
|
|
1059
|
+
}
|
|
1060
|
+
switch (api) {
|
|
1061
|
+
case 'setFramework':
|
|
1062
|
+
this.handleSetFrameWork(params)
|
|
1063
|
+
break
|
|
1064
|
+
case 'enableInfiniteAnchor':
|
|
1065
|
+
this.enableinfiniteanchor = params?.enable ? 1 : 0
|
|
1066
|
+
break
|
|
1067
|
+
default:
|
|
1068
|
+
break
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
private handleSetFrameWork(params: any): void {
|
|
1073
|
+
const {component} = params
|
|
1074
|
+
if (isNumber(component)) {
|
|
1075
|
+
try {
|
|
1076
|
+
if (wx) {
|
|
1077
|
+
wx.TUIScene = component
|
|
1078
|
+
wx.setStorageSync('TUIScene', String(component))
|
|
1079
|
+
}
|
|
1080
|
+
} catch (err) {
|
|
1081
|
+
throw err
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
private pusherAttributesChange(pusher: any): Promise<any> {
|
|
1087
|
+
return new Promise((resolve) => {
|
|
1088
|
+
this.InterfaceEventEmitter.emit(
|
|
1089
|
+
'pusherAttributesChange',
|
|
1090
|
+
{
|
|
1091
|
+
pusher,
|
|
1092
|
+
callback: () => {
|
|
1093
|
+
resolve(pusher)
|
|
1094
|
+
},
|
|
1095
|
+
}
|
|
1096
|
+
)
|
|
1097
|
+
})
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
private playerAttributesChange(params: any): Promise<any> {
|
|
1101
|
+
const {streamId, playerAttributes} = params
|
|
1102
|
+
return new Promise((resolve) => {
|
|
1103
|
+
this.InterfaceEventEmitter.emit(
|
|
1104
|
+
'playerAttributesChange',
|
|
1105
|
+
{
|
|
1106
|
+
streamId,
|
|
1107
|
+
view: this.renderMap.get(streamId),
|
|
1108
|
+
playerAttributes,
|
|
1109
|
+
callback: () => {
|
|
1110
|
+
resolve(playerAttributes)
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
)
|
|
1114
|
+
})
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1117
|
+
private playerAudioRouteChange(params: any): Promise<any> {
|
|
1118
|
+
const {soundMode} = params
|
|
1119
|
+
return new Promise((resolve) => {
|
|
1120
|
+
this.InterfaceEventEmitter.emit(
|
|
1121
|
+
'playerAudioRouteChange',
|
|
1122
|
+
{
|
|
1123
|
+
soundMode,
|
|
1124
|
+
callback: () => {
|
|
1125
|
+
resolve(soundMode)
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
)
|
|
1129
|
+
})
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
@setHandle
|
|
1133
|
+
private async setAttributes(options: any, funName: string, handleType?: Handletype): Promise<any> {
|
|
1134
|
+
const {params, streamId} = options
|
|
1135
|
+
const handleMap = {
|
|
1136
|
+
[Handletype.setPlayer]: async () => {
|
|
1137
|
+
const playerAttributes = await this.playerAttributesChange({
|
|
1138
|
+
playerAttributes: this.setTRTCPlayerAttributes(streamId, params),
|
|
1139
|
+
streamId
|
|
1140
|
+
})
|
|
1141
|
+
return playerAttributes
|
|
1142
|
+
},
|
|
1143
|
+
[Handletype.setPusher]: async () => {
|
|
1144
|
+
if (funName === 'enterRoom') {
|
|
1145
|
+
const pusher = await this.pusherAttributesChange(this.trtc.enterRoom(params))
|
|
1146
|
+
return pusher
|
|
1147
|
+
}
|
|
1148
|
+
const pusher = await this.pusherAttributesChange(this.trtc.setPusherAttributes(params))
|
|
1149
|
+
return pusher
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
// 定义一个超时时间(以毫秒为单位)
|
|
1153
|
+
const timeoutDuration = 2000
|
|
1154
|
+
// 定义超时重试次数
|
|
1155
|
+
const retriesNumber = 3
|
|
1156
|
+
return this.retryWithTimeout(
|
|
1157
|
+
() => (handleMap[handleType]
|
|
1158
|
+
? handleMap[handleType]()
|
|
1159
|
+
: Promise.reject(Object.assign(new Error('setAttributes fail'), {errorCode: -1}))),
|
|
1160
|
+
timeoutDuration,
|
|
1161
|
+
retriesNumber
|
|
1162
|
+
)
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
private async retryWithTimeout<T>(fn: () => Promise<T>, timeout: number, retries: number): Promise<T> {
|
|
1166
|
+
let lastError = null
|
|
1167
|
+
for (let i = 0; i < retries; i++) {
|
|
1168
|
+
try {
|
|
1169
|
+
logger.info(`setAttributes ${i + 1}st retry`)
|
|
1170
|
+
const result = await Promise.race([
|
|
1171
|
+
fn(),
|
|
1172
|
+
new Promise<T>((resolve, reject) => setTimeout(() => reject(new Error('setAttributes timed out')), timeout)),
|
|
1173
|
+
])
|
|
1174
|
+
return result
|
|
1175
|
+
} catch (error) {
|
|
1176
|
+
if (error?.errorCode === -1) return error
|
|
1177
|
+
lastError = error
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
throw lastError
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1184
|
+
export default TRTCCloud
|