trtc-cloud-js-sdk 1.0.13 → 2.0.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/.eslintrc.js +88 -0
- package/.prettierrc +5 -0
- package/CHANGELOG.md +58 -0
- package/build/jsdoc/clean-doc.js +12 -0
- package/build/jsdoc/fix-doc.js +141 -0
- package/build/jsdoc/jsdoc.json +42 -0
- package/build/package-bundle.js +29 -0
- package/build/rollup.config.dev.js +88 -0
- package/build/rollup.config.prod.js +93 -0
- package/build/rollup.js +359 -0
- package/build/template/npm-package/package.json +24 -0
- package/coverage/Chrome 103.0.5060 (Mac OS X 10.15.7)/base.css +213 -0
- package/coverage/Chrome 103.0.5060 (Mac OS X 10.15.7)/index.html +80 -0
- package/coverage/Chrome 103.0.5060 (Mac OS X 10.15.7)/prettify.css +1 -0
- package/coverage/Chrome 103.0.5060 (Mac OS X 10.15.7)/prettify.js +1 -0
- package/coverage/Chrome 103.0.5060 (Mac OS X 10.15.7)/sort-arrow-sprite.png +0 -0
- package/coverage/Chrome 103.0.5060 (Mac OS X 10.15.7)/sorter.js +158 -0
- package/examples/apiExample/.env +2 -0
- package/examples/apiExample/README.md +70 -0
- package/examples/apiExample/package-lock.json +30915 -0
- package/examples/apiExample/package.json +51 -0
- package/examples/apiExample/public/audio.js +195 -0
- package/examples/apiExample/public/audio.js.map +7 -0
- package/examples/apiExample/public/av_processing.js +1 -0
- package/examples/apiExample/public/basic/av_processing.wasm +0 -0
- package/examples/apiExample/public/basic/worker.js +10434 -0
- package/examples/apiExample/public/favicon.ico +0 -0
- package/examples/apiExample/public/index.html +47 -0
- package/examples/apiExample/public/logo192.png +0 -0
- package/examples/apiExample/public/logo512.png +0 -0
- package/examples/apiExample/public/manifest.json +25 -0
- package/examples/apiExample/public/robots.txt +3 -0
- package/examples/apiExample/src/App.css +37 -0
- package/examples/apiExample/src/App.js +25 -0
- package/examples/apiExample/src/api/http.js +127 -0
- package/examples/apiExample/src/api/nav.js +44 -0
- package/examples/apiExample/src/components/BasicInfoComponent.css +16 -0
- package/examples/apiExample/src/components/BasicInfoComponent.js +27 -0
- package/examples/apiExample/src/config/gen-test-user-sig.js +64 -0
- package/examples/apiExample/src/config/lib-generate-test-usersig.min.js +7052 -0
- package/examples/apiExample/src/config/nav.js +136 -0
- package/examples/apiExample/src/home.js +16 -0
- package/examples/apiExample/src/index.css +21 -0
- package/examples/apiExample/src/index.js +12 -0
- package/examples/apiExample/src/logo.svg +1 -0
- package/examples/apiExample/src/page/basic/screen-share/index.css +52 -0
- package/examples/apiExample/src/page/basic/screen-share/index.js +223 -0
- package/examples/apiExample/src/page/basic/setDevice/index.js +262 -0
- package/examples/apiExample/src/page/basic/setDevice/index.scss +93 -0
- package/examples/apiExample/src/page/basic/video-call/index.js +521 -0
- package/examples/apiExample/src/page/basic/video-call/index.scss +93 -0
- package/examples/apiExample/src/page/basic/video-call-init/index.js +382 -0
- package/examples/apiExample/src/page/basic/video-call-init/index.scss +93 -0
- package/examples/apiExample/src/page/basic/video-live/index.css +37 -0
- package/examples/apiExample/src/page/basic/video-live/index.js +188 -0
- package/examples/apiExample/src/page/layout.js +22 -0
- package/examples/apiExample/src/page/layout.scss +76 -0
- package/examples/apiExample/src/utils/utils.js +35 -0
- package/examples/jsExample/assets/css/bootstrap-material-design.css +12169 -0
- package/examples/jsExample/assets/css/bootstrap-material-design.min.css +8 -0
- package/examples/jsExample/assets/css/common.css +48 -0
- package/examples/jsExample/assets/icon/iconfont.js +1 -0
- package/examples/jsExample/assets/js/bootstrap-material-design.js +6939 -0
- package/examples/jsExample/assets/js/bootstrap-material-design.js.map +1 -0
- package/examples/jsExample/assets/js/bootstrap-material-design.min.js +1 -0
- package/examples/jsExample/assets/js/graph.js +695 -0
- package/examples/jsExample/assets/js/jquery-3.2.1.min.js +4 -0
- package/examples/jsExample/assets/js/jquery-3.2.1.slim.min.js +4 -0
- package/examples/jsExample/assets/js/lib-generate-test-usersig.min.js +2 -0
- package/examples/jsExample/assets/js/popper.js +2442 -0
- package/examples/jsExample/index.html +57 -0
- package/examples/jsExample/rtc/css/common.css +82 -0
- package/examples/jsExample/rtc/index.html +107 -0
- package/examples/jsExample/rtc/js/index.js +142 -0
- package/examples/vueDemo/LICENSE +21 -0
- package/examples/vueDemo/README.md +144 -0
- package/examples/vueDemo/README_EN.md +136 -0
- package/examples/vueDemo/av_processing.wasm +0 -0
- package/examples/vueDemo/index.html +23 -0
- package/examples/vueDemo/package-lock.json +1375 -0
- package/examples/vueDemo/package.json +36 -0
- package/examples/vueDemo/src/App.vue +12 -0
- package/examples/vueDemo/src/api/index.js +59 -0
- package/examples/vueDemo/src/assets/css/color-dark.css +28 -0
- package/examples/vueDemo/src/assets/css/icon.css +4 -0
- package/examples/vueDemo/src/assets/css/main.css +177 -0
- package/examples/vueDemo/src/assets/img/img.jpg +0 -0
- package/examples/vueDemo/src/assets/img/login-bg.jpg +0 -0
- package/examples/vueDemo/src/components/Header.vue +172 -0
- package/examples/vueDemo/src/components/Sidebar.vue +117 -0
- package/examples/vueDemo/src/components/Tags.vue +174 -0
- package/examples/vueDemo/src/components/tendency.vue +206 -0
- package/examples/vueDemo/src/components/trtc/main-menu.vue +50 -0
- package/examples/vueDemo/src/components/trtc/nav-bar.vue +53 -0
- package/examples/vueDemo/src/components/trtc/show-screen-capture.vue +118 -0
- package/examples/vueDemo/src/components/trtc/trtc-state-check.vue +117 -0
- package/examples/vueDemo/src/config/gen-test-user-sig.js +67 -0
- package/examples/vueDemo/src/config/lib-generate-test-usersig.min.js +7052 -0
- package/examples/vueDemo/src/main.js +11 -0
- package/examples/vueDemo/src/plugins/element.js +17 -0
- package/examples/vueDemo/src/router/index.js +73 -0
- package/examples/vueDemo/src/store/sidebar.js +17 -0
- package/examples/vueDemo/src/store/tags.js +48 -0
- package/examples/vueDemo/src/utils/i18n.js +24 -0
- package/examples/vueDemo/src/utils/request.js +34 -0
- package/examples/vueDemo/src/utils/utils.js +35 -0
- package/examples/vueDemo/src/views/Home.vue +46 -0
- package/examples/vueDemo/src/views/I18n.vue +40 -0
- package/examples/vueDemo/src/views/Icon.vue +229 -0
- package/examples/vueDemo/src/views/basic/trtc.vue +194 -0
- package/examples/vueDemo/src/views/feature/index.vue +259 -0
- package/examples/vueDemo/src/views/github/index.vue +243 -0
- package/examples/vueDemo/src/views/improve/live-index.vue +256 -0
- package/examples/vueDemo/src/views/improve/live-room-anchor.vue +689 -0
- package/examples/vueDemo/src/views/improve/live-room-audience.vue +383 -0
- package/examples/vueDemo/src/views/sdkAppId/index.vue +284 -0
- package/examples/vueDemo/vite.config.js +18 -0
- package/examples/vueDemo/worker.js +22 -0
- package/karma.conf.js +99 -0
- package/package.json +57 -7
- package/scripts/publish.js +86 -0
- package/src/Camera.ts +80 -0
- package/src/Mic.ts +145 -0
- package/src/common/IError.ts +6 -0
- package/src/common/ITRTCCloud.ts +68 -0
- package/src/common/constants.ts +116 -0
- package/src/common/trtc-code.ts +43 -0
- package/src/common/trtc-define.ts +1007 -0
- package/src/common/trtc-event.ts +29 -0
- package/src/index.ts +1672 -0
- package/src/utils/environment.js +297 -0
- package/src/utils/raf.js +131 -0
- package/src/utils/time.js +22 -0
- package/src/utils/utils.ts +71 -0
- package/src/utils/uuid.js +12 -0
- package/test/unit/env.test.js +25 -0
- package/test/unit/get-user-media.test.js +40 -0
- package/test/unit/ice-parser.test.js +23 -0
- package/test/unit/sdp.test.js +45 -0
- package/test/unit/signal.test.js +78 -0
- package/tsconfig.json +32 -0
- package/trtc-cloud-js-sdk.js +0 -1
- /package/{README.md → build/template/npm-package/README.md} +0 -0
|
@@ -0,0 +1,521 @@
|
|
|
1
|
+
/* eslint-disable no-unused-vars */
|
|
2
|
+
import React, { useState, useEffect } from 'react';
|
|
3
|
+
import { Button, Switch, FormControlLabel } from '@material-ui/core';
|
|
4
|
+
import './index.scss';
|
|
5
|
+
import BasicInfoComponent from '../../../components/BasicInfoComponent';
|
|
6
|
+
import TRTC_Cloud, { TRTCAppScene, TRTCParams, TRTCVideoStreamType, TRTCVideoResolution, TRTCRoleType, TRTCVideoMirrorType, TRTCDeviceType, TRTCDeviceState } from 'trtc-cloud-js-sdk';
|
|
7
|
+
import genTestUserSig from '../../../config/gen-test-user-sig';
|
|
8
|
+
import { validParams, getUrlParam } from '../../../utils/utils';
|
|
9
|
+
const trtcCloud = TRTC_Cloud.getTRTCShareInstance();
|
|
10
|
+
let preRemoteUserIdList = [];
|
|
11
|
+
|
|
12
|
+
export default function VideoCall() {
|
|
13
|
+
const [userId, setUserId] = useState(getUrlParam('userId') ? getUrlParam('userId') : 'TRTCCloud_' + parseInt(Math.random() * 100000));
|
|
14
|
+
const [roomId, setRoomId] = useState(getUrlParam('roomId') ? getUrlParam('roomId') : parseInt(Math.random() * 100000) + '');
|
|
15
|
+
const [remoteUserIdList, setRemoteUserIdList] = useState([]);
|
|
16
|
+
const [isMuteAllRemoteAudio, setIsMuteAllRemoteAudio] = useState(false);
|
|
17
|
+
const [isStopRemote, setIsStopRemote] = useState(false);
|
|
18
|
+
const [sceneList] = useState([{
|
|
19
|
+
scene: TRTCAppScene.TRTCAppSceneVideoCall,
|
|
20
|
+
name: '实时通话模式',
|
|
21
|
+
}, {
|
|
22
|
+
scene: TRTCAppScene.TRTCAppSceneLIVE,
|
|
23
|
+
name: '互动直播模式',
|
|
24
|
+
}
|
|
25
|
+
]);
|
|
26
|
+
const [currentScene, setCurrentScene] = useState(TRTCAppScene.TRTCAppSceneVideoCall);
|
|
27
|
+
const [role, setRole] = useState(TRTCRoleType.TRTCRoleAnchor);
|
|
28
|
+
const [cameraList, setCameraList] = useState([]);
|
|
29
|
+
const [micList, setMicList] = useState([]);
|
|
30
|
+
const [speakerList, setSpeakerList] = useState([]);
|
|
31
|
+
// 按钮状态控制
|
|
32
|
+
const [isJoined,setIsJoined] = useState(false);
|
|
33
|
+
const [isLocalVideo, setIsLocalVideo] = useState(false);
|
|
34
|
+
const [isMuteVideo, setIsMuteVideo] = useState(false);
|
|
35
|
+
const [isLocalAudio, setIsLocalAudio] = useState(false);
|
|
36
|
+
const [isScreeShare, setIsScreeShare] = useState(false);
|
|
37
|
+
const [isEnableAudioVolume, setIsEnableAudioVolume] = useState(false);
|
|
38
|
+
//
|
|
39
|
+
let info = {};
|
|
40
|
+
let sdkAppId = 0 || info.sdkAppId;
|
|
41
|
+
let userSignature = '';
|
|
42
|
+
let shareUserId = 'share_' + userId;
|
|
43
|
+
let shareUserSig = '';
|
|
44
|
+
const LOG_PREFIX = '【Video Call Demo】';
|
|
45
|
+
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
console.warn(`${LOG_PREFIX} TRTC version:`, trtcCloud.getSDKVersion());
|
|
48
|
+
async function getDeviceList() {
|
|
49
|
+
const tempCameraList = await trtcCloud.getCameraDevicesList();
|
|
50
|
+
const tempMicList = await trtcCloud.getMicDevicesList();
|
|
51
|
+
const tempSpeakerList = await trtcCloud.getSpeakerDevicesList();
|
|
52
|
+
console.warn('==== camera list = ', tempCameraList);
|
|
53
|
+
console.warn('==== mic list = ', tempMicList);
|
|
54
|
+
console.warn('==== speaker list = ', tempSpeakerList);
|
|
55
|
+
|
|
56
|
+
setCameraList(tempCameraList);
|
|
57
|
+
setMicList(tempMicList);
|
|
58
|
+
setSpeakerList(tempSpeakerList);
|
|
59
|
+
}
|
|
60
|
+
getDeviceList();
|
|
61
|
+
}, []);
|
|
62
|
+
|
|
63
|
+
useEffect(() => {
|
|
64
|
+
try {
|
|
65
|
+
remoteUserIdList.forEach(async (userId) => {
|
|
66
|
+
const domElement = document.getElementById(userId);
|
|
67
|
+
await trtcCloud.startRemoteView(userId, domElement, TRTCVideoStreamType.TRTCVideoStreamTypeBig);
|
|
68
|
+
});
|
|
69
|
+
} catch (error) {
|
|
70
|
+
console.error(`${LOG_PREFIX} remoteUserIdList useEffect error: ${JSON.stringify(error)}`);
|
|
71
|
+
}
|
|
72
|
+
}, [remoteUserIdList]);
|
|
73
|
+
|
|
74
|
+
// 进房
|
|
75
|
+
const enterRoom = async () => {
|
|
76
|
+
subscribeEvents();
|
|
77
|
+
const trtcParams = new TRTCParams();
|
|
78
|
+
trtcParams.userId = userId;
|
|
79
|
+
trtcParams.sdkAppId = sdkAppId;
|
|
80
|
+
trtcParams.userSig = userSignature;
|
|
81
|
+
trtcParams.roomId = +roomId;
|
|
82
|
+
trtcParams.role = role;
|
|
83
|
+
console.warn(`${LOG_PREFIX} enterRoom params: ${JSON.stringify(trtcParams)}, scene: ${currentScene}`);
|
|
84
|
+
trtcCloud.enterRoom(trtcParams, currentScene);
|
|
85
|
+
};
|
|
86
|
+
// 退房
|
|
87
|
+
const exitRoom = async () => {
|
|
88
|
+
try {
|
|
89
|
+
setRemoteUserIdList([]);
|
|
90
|
+
preRemoteUserIdList = [];
|
|
91
|
+
stopLocalPreview();
|
|
92
|
+
stopLocalAudio();
|
|
93
|
+
trtcCloud.exitRoom();
|
|
94
|
+
unsubscribeEvents();
|
|
95
|
+
} catch (error) {
|
|
96
|
+
console.error(`${LOG_PREFIX} exitRoom error: ${JSON.stringify(error)}`);
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
// input 输入框内容改变处理
|
|
100
|
+
const handleInputChange = (event, type) => {
|
|
101
|
+
if (type === 'USERID') {
|
|
102
|
+
setUserId(event.target.value);
|
|
103
|
+
}
|
|
104
|
+
if (type === 'ROOMID') {
|
|
105
|
+
setRoomId(event.target.value);
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
const handleStart = () => {
|
|
109
|
+
info = genTestUserSig(userId);
|
|
110
|
+
sdkAppId = info.sdkAppId;
|
|
111
|
+
userSignature = info.userSig;
|
|
112
|
+
shareUserSig = genTestUserSig(shareUserId).userSig;
|
|
113
|
+
if (!validParams(userId, +roomId, sdkAppId, userSignature)) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
enterRoom();
|
|
117
|
+
setIsJoined(true);
|
|
118
|
+
};
|
|
119
|
+
const handleStop = () => {
|
|
120
|
+
exitRoom();
|
|
121
|
+
setIsJoined(false);
|
|
122
|
+
}
|
|
123
|
+
// 打开本地视频
|
|
124
|
+
const startLocalPreview = async () => {
|
|
125
|
+
await trtcCloud.setLocalRenderParams({
|
|
126
|
+
mirrorType: TRTCVideoMirrorType.TRTCVideoMirrorType_Auto,
|
|
127
|
+
});
|
|
128
|
+
const localVideoWrapper = document.getElementById('localVideoWrapper');
|
|
129
|
+
await trtcCloud.startLocalPreview(true, localVideoWrapper);
|
|
130
|
+
};
|
|
131
|
+
const startLocalPreview2 = async () => {
|
|
132
|
+
const localVideoWrapper = document.getElementById('localVideoWrapper2');
|
|
133
|
+
await trtcCloud.updateLocalView(localVideoWrapper);
|
|
134
|
+
};
|
|
135
|
+
const switchCamera = async () => {
|
|
136
|
+
const isFront = trtcCloud.isFrontCamera();
|
|
137
|
+
await trtcCloud.switchCamera(!isFront);
|
|
138
|
+
};
|
|
139
|
+
// 关闭本地视频
|
|
140
|
+
const stopLocalPreview = () => {
|
|
141
|
+
console.warn(`${LOG_PREFIX} stopLocalPreview`);
|
|
142
|
+
try {
|
|
143
|
+
trtcCloud.stopLocalPreview();
|
|
144
|
+
setIsLocalVideo(false);
|
|
145
|
+
} catch (error) {
|
|
146
|
+
console.error(`${LOG_PREFIX} stopLocalPreview error: ${JSON.stringify(error)}`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
// mute/unmute video 操作
|
|
150
|
+
const muteVideo = (mute) => {
|
|
151
|
+
console.warn(`${LOG_PREFIX} local video mute state = ${mute}`);
|
|
152
|
+
trtcCloud.muteLocalVideo(mute);
|
|
153
|
+
setIsMuteVideo(mute);
|
|
154
|
+
};
|
|
155
|
+
// 开启本地音频
|
|
156
|
+
const startLocalAudio = async () => {
|
|
157
|
+
trtcCloud.startLocalAudio();
|
|
158
|
+
setIsLocalAudio(true);
|
|
159
|
+
}
|
|
160
|
+
// 关闭本地音频
|
|
161
|
+
const stopLocalAudio = async () => {
|
|
162
|
+
trtcCloud.stopLocalAudio();
|
|
163
|
+
setIsLocalAudio(false);
|
|
164
|
+
}
|
|
165
|
+
// 静音掉远端所有用户 audio
|
|
166
|
+
const muteAllRemoteAudio = async () => {
|
|
167
|
+
trtcCloud.muteAllRemoteAudio();
|
|
168
|
+
setIsMuteAllRemoteAudio(!isMuteAllRemoteAudio);
|
|
169
|
+
};
|
|
170
|
+
// 打开音量回调,这用可从 onUserVoiceVolume 事件中获取相应用户的音量
|
|
171
|
+
const handleEnableAudioVolumeEvaluation = async () => {
|
|
172
|
+
await trtcCloud.enableAudioVolumeEvaluation(500);
|
|
173
|
+
setIsEnableAudioVolume(true);
|
|
174
|
+
};
|
|
175
|
+
// 关闭音量回调
|
|
176
|
+
const handleDisableAudioVolumeEvaluation = async () => {
|
|
177
|
+
await trtcCloud.enableAudioVolumeEvaluation(-1);
|
|
178
|
+
setIsEnableAudioVolume(false);
|
|
179
|
+
};
|
|
180
|
+
// 切换设备
|
|
181
|
+
const handleChangeDevice = async (e, type) => {
|
|
182
|
+
const deviceId = e.target.value;
|
|
183
|
+
console.warn(' select device id: ', deviceId);
|
|
184
|
+
switch (type) {
|
|
185
|
+
case 'CAMERA': {
|
|
186
|
+
await trtcCloud.setCurrentCameraDevice(deviceId);
|
|
187
|
+
break;
|
|
188
|
+
}
|
|
189
|
+
case 'MIC': {
|
|
190
|
+
let currentMicDevice = trtcCloud.getCurrentMicDevice();
|
|
191
|
+
console.warn(`${LOG_PREFIX} current Mic deviceId before :`, currentMicDevice);
|
|
192
|
+
const result = await trtcCloud.setCurrentMicDevice(deviceId);
|
|
193
|
+
currentMicDevice = trtcCloud.getCurrentMicDevice();
|
|
194
|
+
console.warn(`${LOG_PREFIX} current Mic deviceId after, deviceId: ${JSON.stringify(currentMicDevice)}, result: ${result}`);
|
|
195
|
+
break;
|
|
196
|
+
}
|
|
197
|
+
case 'SPEAKER': {
|
|
198
|
+
const result = await trtcCloud.setCurrentSpeakerDevice(deviceId);
|
|
199
|
+
console.warn(`${LOG_PREFIX} switch speaker, deviceId: ${deviceId}, result: ${result}`);
|
|
200
|
+
break;
|
|
201
|
+
}
|
|
202
|
+
case 'SCENE': {
|
|
203
|
+
setCurrentScene(+e.target.value);
|
|
204
|
+
break;
|
|
205
|
+
}
|
|
206
|
+
default: {
|
|
207
|
+
break;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
// 角色切换
|
|
212
|
+
const handleSwitchChange = (e, type) => {
|
|
213
|
+
switch (type) {
|
|
214
|
+
case 'ROLE': {
|
|
215
|
+
const role = e.target.checked ? TRTCRoleType.TRTCRoleAudience : TRTCRoleType.TRTCRoleAnchor;
|
|
216
|
+
setRole(role);
|
|
217
|
+
trtcCloud.switchRole(role);
|
|
218
|
+
break;
|
|
219
|
+
}
|
|
220
|
+
default: {}
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
// 开始屏幕分享
|
|
224
|
+
const handleStartScreenShare = async () => {
|
|
225
|
+
try {
|
|
226
|
+
const view = document.getElementById('remote-screen-share-container');
|
|
227
|
+
const type = TRTCVideoStreamType.TRTCVideoStreamTypeSub;
|
|
228
|
+
const params = {
|
|
229
|
+
videoResolution: TRTCVideoResolution.TRTCVideoResolution_1920_1080,
|
|
230
|
+
videoFps: 20,
|
|
231
|
+
videoBitrate: 1600,
|
|
232
|
+
screenAudio: false,
|
|
233
|
+
};
|
|
234
|
+
await trtcCloud.startScreenCapture(view, type, params);
|
|
235
|
+
setIsScreeShare(true);
|
|
236
|
+
} catch (error) {
|
|
237
|
+
setIsScreeShare(false);
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
// 停止屏幕分享
|
|
241
|
+
const handleStopScreenShare = async () => {
|
|
242
|
+
await trtcCloud.stopScreenCapture();
|
|
243
|
+
setIsScreeShare(false);
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
// 操作第一个远端用户
|
|
247
|
+
const operateFirstRemote = async () => {
|
|
248
|
+
if (isStopRemote) {
|
|
249
|
+
const userId = remoteUserIdList[0];
|
|
250
|
+
const domElement = document.getElementById(userId);
|
|
251
|
+
await trtcCloud.startRemoteView(userId, domElement, TRTCVideoStreamType.TRTCVideoStreamTypeBig);
|
|
252
|
+
} else {
|
|
253
|
+
trtcCloud.stopRemoteView(remoteUserIdList[0], TRTCVideoStreamType.TRTCVideoStreamTypeBig);
|
|
254
|
+
}
|
|
255
|
+
setIsStopRemote(!isStopRemote);
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
// ============================【所有需要监听事件的回调】============================
|
|
259
|
+
// 错误回调
|
|
260
|
+
const onError = (errCode, errMsg) => {
|
|
261
|
+
console.warn(`${LOG_PREFIX} onError: errCode: ${errCode}, errMsg: ${errMsg}`);
|
|
262
|
+
};
|
|
263
|
+
// 进房回调
|
|
264
|
+
const onEnterRoom = (elapsed) => {
|
|
265
|
+
if (elapsed > 0) {
|
|
266
|
+
console.warn(`${LOG_PREFIX} onEnterRoom: elapsed: ${elapsed}`);
|
|
267
|
+
} else {
|
|
268
|
+
console.warn(`${LOG_PREFIX} onEnterRoom failed: elapsed: ${elapsed}`);
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
// 退房回调
|
|
272
|
+
const onExitRoom = (reason) => {
|
|
273
|
+
console.warn(`${LOG_PREFIX} onExitRoom: reason: ${reason}`);
|
|
274
|
+
};
|
|
275
|
+
// 远端用户进房事件
|
|
276
|
+
const onRemoteUserEnterRoom = (userId) => {
|
|
277
|
+
console.warn(`${LOG_PREFIX} onRemoteUserEnterRoom: userId: ${userId}`);
|
|
278
|
+
};
|
|
279
|
+
// 远端用户退房事件
|
|
280
|
+
const onRemoteUserLeaveRoom = (userId, reason) => {
|
|
281
|
+
console.warn(`${LOG_PREFIX} onRemoteUserLeaveRoom: userId: ${userId}, ${reason}`);
|
|
282
|
+
};
|
|
283
|
+
// 远端用户 video 可用事件
|
|
284
|
+
const onUserVideoAvailable = (userId, available) => {
|
|
285
|
+
console.warn(`${LOG_PREFIX} onUserVideoAvailable: userId: ${userId}, available: ${available}`);
|
|
286
|
+
if (available) {
|
|
287
|
+
if (preRemoteUserIdList.indexOf(userId) === -1) {
|
|
288
|
+
preRemoteUserIdList = [...preRemoteUserIdList, userId];
|
|
289
|
+
}
|
|
290
|
+
} else {
|
|
291
|
+
preRemoteUserIdList = preRemoteUserIdList.filter((str) => str !== userId);
|
|
292
|
+
}
|
|
293
|
+
setRemoteUserIdList(preRemoteUserIdList);
|
|
294
|
+
};
|
|
295
|
+
// 开启音量大小回调
|
|
296
|
+
const handleUserVoiceVolume = (userVolumes, userVolumesCount) => {
|
|
297
|
+
console.warn(`${LOG_PREFIX} onUserVoiceVolume result = `, userVolumes, userVolumesCount);
|
|
298
|
+
};
|
|
299
|
+
// audio available
|
|
300
|
+
const handleUserAudioAvailable = (userId, available) => {
|
|
301
|
+
console.warn(`${LOG_PREFIX} onUserAudioAvailable: userId: ${userId}, available: ${available}`);
|
|
302
|
+
};
|
|
303
|
+
// 远端屏幕分享流 onUserSubStreamAvailable 事件
|
|
304
|
+
const handleUserSubStreamAvailable = (userId, available) => {
|
|
305
|
+
console.warn('【1】onUserSubStreamAvailable ', userId, available);
|
|
306
|
+
if (available) {
|
|
307
|
+
trtcCloud.startRemoteView(userId, document.getElementById('remote-screen-share-container'), TRTCVideoStreamType.TRTCVideoStreamTypeSub);
|
|
308
|
+
}
|
|
309
|
+
};
|
|
310
|
+
// 网络质量统计数据事件
|
|
311
|
+
const handleOnNetworkQuality = (localQuality, remoteQuality) => {
|
|
312
|
+
console.warn(`${LOG_PREFIX} onNetworkQuality: `, localQuality, remoteQuality);
|
|
313
|
+
};
|
|
314
|
+
// 设备变化:设备切换、设备插拔 事件
|
|
315
|
+
const handleOnDeviceChange = async (deviceId, type, state) => {
|
|
316
|
+
console.warn(`${LOG_PREFIX} onDeviceChange: `, deviceId, type, state);
|
|
317
|
+
const stateList = ['add', 'remove', 'active'];
|
|
318
|
+
if (type === TRTCDeviceType.TRTCDeviceTypeMic) {
|
|
319
|
+
console.log(`onDeviceChange: deviceId: ${deviceId}, type: microphone, state: ${stateList[state]}`);
|
|
320
|
+
const deviceList = await trtcCloud.getMicDevicesList();
|
|
321
|
+
console.error('lixin-debug getMicDevicesList', deviceList);
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
if (type === TRTCDeviceType.TRTCDeviceTypeSpeaker) {
|
|
325
|
+
console.log(`onDeviceChange: deviceId: ${deviceId}, type: speaker, state: ${stateList[state]}`);
|
|
326
|
+
const deviceList =await trtcCloud.getSpeakerDevicesList();
|
|
327
|
+
console.error('lixin-debug getSpeakerDevicesList', deviceList);
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
if (type === TRTCDeviceType.TRTCDeviceTypeCamera) {
|
|
331
|
+
console.log(`onDeviceChange: deviceId: ${deviceId}, type: camera, state: ${stateList[state]}`);
|
|
332
|
+
const deviceList = await trtcCloud?.getCameraDevicesList();
|
|
333
|
+
console.error('lixin-debug getCameraDevicesList', deviceList);
|
|
334
|
+
}
|
|
335
|
+
};
|
|
336
|
+
const handleOnSwitchRole = (code, message) => {
|
|
337
|
+
console.warn(`${LOG_PREFIX} onSwitchRole: `, code, message);
|
|
338
|
+
};
|
|
339
|
+
// 注册所有的事件监听
|
|
340
|
+
const subscribeEvents = () => {
|
|
341
|
+
trtcCloud.on('onError', onError);
|
|
342
|
+
trtcCloud.on('onEnterRoom', onEnterRoom);
|
|
343
|
+
trtcCloud.on('onExitRoom', onExitRoom);
|
|
344
|
+
trtcCloud.on('onRemoteUserEnterRoom', onRemoteUserEnterRoom);
|
|
345
|
+
trtcCloud.on('onRemoteUserLeaveRoom', onRemoteUserLeaveRoom);
|
|
346
|
+
trtcCloud.on('onUserVideoAvailable', onUserVideoAvailable);
|
|
347
|
+
trtcCloud.on('onUserAudioAvailable', handleUserAudioAvailable);
|
|
348
|
+
trtcCloud.on('onUserVoiceVolume', handleUserVoiceVolume);
|
|
349
|
+
trtcCloud.on('onUserSubStreamAvailable', handleUserSubStreamAvailable);
|
|
350
|
+
trtcCloud.on('onNetworkQuality', handleOnNetworkQuality);
|
|
351
|
+
trtcCloud.on('onDeviceChange', handleOnDeviceChange);
|
|
352
|
+
trtcCloud.on('onSwitchRole', handleOnSwitchRole);
|
|
353
|
+
};
|
|
354
|
+
// 注销所有的事件监听
|
|
355
|
+
const unsubscribeEvents = () => {
|
|
356
|
+
// trtcCloud.off('*');
|
|
357
|
+
trtcCloud.off('onError', onError);
|
|
358
|
+
trtcCloud.off('onEnterRoom', onEnterRoom);
|
|
359
|
+
trtcCloud.off('onExitRoom', onExitRoom);
|
|
360
|
+
trtcCloud.off('onRemoteUserEnterRoom', onRemoteUserEnterRoom);
|
|
361
|
+
trtcCloud.off('onRemoteUserLeaveRoom', onRemoteUserLeaveRoom);
|
|
362
|
+
trtcCloud.off('onUserVideoAvailable', onUserVideoAvailable);
|
|
363
|
+
trtcCloud.off('onUserAudioAvailable', handleUserAudioAvailable);
|
|
364
|
+
trtcCloud.off('onUserVoiceVolume', handleUserVoiceVolume);
|
|
365
|
+
trtcCloud.off('onUserSubStreamAvailable', handleUserSubStreamAvailable);
|
|
366
|
+
trtcCloud.off('onNetworkQuality', handleOnNetworkQuality);
|
|
367
|
+
trtcCloud.off('onDeviceChange', handleOnDeviceChange);
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
return (
|
|
371
|
+
<div className="content-container">
|
|
372
|
+
<div className="operate-container">
|
|
373
|
+
<BasicInfoComponent userId={userId} roomId={roomId} isJoined={isJoined} handleInputChange={handleInputChange} handleStart={handleStart} handleStop={handleStop}></BasicInfoComponent>
|
|
374
|
+
{/* 主播、观众 角色 */}
|
|
375
|
+
{!isJoined &&
|
|
376
|
+
<div className="select-container">
|
|
377
|
+
<label htmlFor="camera-select" className="select-item-label">
|
|
378
|
+
角色:
|
|
379
|
+
</label>
|
|
380
|
+
<select id="camera-select" className="select-item" onChange={(e) => handleChangeDevice(e, 'SCENE')}>
|
|
381
|
+
{sceneList.map((obj, idx) => (
|
|
382
|
+
<option key={obj.scene} value={obj.scene}>
|
|
383
|
+
{obj.name}
|
|
384
|
+
</option>
|
|
385
|
+
))}
|
|
386
|
+
</select>
|
|
387
|
+
</div>
|
|
388
|
+
}
|
|
389
|
+
{(currentScene === TRTCAppScene.TRTCAppSceneLIVE && isJoined) &&
|
|
390
|
+
<div>
|
|
391
|
+
<FormControlLabel
|
|
392
|
+
control={<Switch checked={role === TRTCRoleType.TRTCRoleAnchor ? false : true} onChange={(e) => handleSwitchChange(e, 'ROLE')} name="gilad" />}
|
|
393
|
+
label="观众"
|
|
394
|
+
/>
|
|
395
|
+
</div>
|
|
396
|
+
}
|
|
397
|
+
{/* 摄像头选择 */}
|
|
398
|
+
<div className="select-container">
|
|
399
|
+
<label htmlFor="camera-select" className="select-item-label">
|
|
400
|
+
摄像头:
|
|
401
|
+
</label>
|
|
402
|
+
<select id="camera-select" className="select-item" onChange={(e) => handleChangeDevice(e, 'CAMERA')}>
|
|
403
|
+
{cameraList.map((obj, idx) => (
|
|
404
|
+
<option key={obj.deviceId} value={obj.deviceId}>
|
|
405
|
+
{obj.deviceName}
|
|
406
|
+
</option>
|
|
407
|
+
))}
|
|
408
|
+
</select>
|
|
409
|
+
</div>
|
|
410
|
+
{/* 麦克风选择 */}
|
|
411
|
+
<div className="select-container">
|
|
412
|
+
<label htmlFor="mic-select" className="select-item-label">
|
|
413
|
+
麦克风:
|
|
414
|
+
</label>
|
|
415
|
+
<select id="mic-select" className="select-item" onChange={(e) => handleChangeDevice(e, 'MIC')}>
|
|
416
|
+
{micList.map((obj, idx) => (
|
|
417
|
+
<option key={obj.deviceId} value={obj.deviceId}>
|
|
418
|
+
{obj.deviceName}
|
|
419
|
+
</option>
|
|
420
|
+
))}
|
|
421
|
+
</select>
|
|
422
|
+
</div>
|
|
423
|
+
{/* Speaker */}
|
|
424
|
+
<div className="select-container">
|
|
425
|
+
<label htmlFor="speaker-select" className="select-item-label">
|
|
426
|
+
外放:
|
|
427
|
+
</label>
|
|
428
|
+
<select id="speaker-select" className="select-item" onChange={(e) => handleChangeDevice(e, 'SPEAKER')}>
|
|
429
|
+
{speakerList.map((obj, idx) => (
|
|
430
|
+
<option key={obj.deviceId} value={obj.deviceId}>
|
|
431
|
+
{obj.deviceName}
|
|
432
|
+
</option>
|
|
433
|
+
))}
|
|
434
|
+
</select>
|
|
435
|
+
</div>
|
|
436
|
+
{/* 额外操作 */}
|
|
437
|
+
<div className="external-operate-container">
|
|
438
|
+
<div className="btn-operate-group">
|
|
439
|
+
<Button variant="contained" color="primary" onClick={() => startLocalPreview()} disabled={isLocalVideo}>
|
|
440
|
+
打开视频
|
|
441
|
+
</Button>
|
|
442
|
+
<Button variant="contained" color="primary" onClick={() => startLocalPreview2()}>
|
|
443
|
+
打开视频2
|
|
444
|
+
</Button>
|
|
445
|
+
<Button variant="contained" color="primary" onClick={() => switchCamera()}>
|
|
446
|
+
切换摄像头
|
|
447
|
+
</Button>
|
|
448
|
+
<Button variant="contained" color="primary" onClick={() => stopLocalPreview()} disabled={!isLocalVideo}>
|
|
449
|
+
关闭视频
|
|
450
|
+
</Button>
|
|
451
|
+
</div>
|
|
452
|
+
{isLocalVideo && <div className="btn-operate-group">
|
|
453
|
+
<Button variant="contained" color="primary" onClick={() => muteVideo(true)} disabled={isMuteVideo}>
|
|
454
|
+
Mute 视频
|
|
455
|
+
</Button>
|
|
456
|
+
<Button variant="contained" color="primary" onClick={() => muteVideo(false)} disabled={!isMuteVideo}>
|
|
457
|
+
UnMute 视频
|
|
458
|
+
</Button>
|
|
459
|
+
</div>
|
|
460
|
+
}
|
|
461
|
+
<div className="btn-operate-group">
|
|
462
|
+
<Button variant="contained" color="primary" onClick={() => startLocalAudio()} disabled={isLocalAudio}>
|
|
463
|
+
打开音频
|
|
464
|
+
</Button>
|
|
465
|
+
<Button variant="contained" color="primary" onClick={() => stopLocalAudio()} disabled={!isLocalAudio}>
|
|
466
|
+
关闭音频
|
|
467
|
+
</Button>
|
|
468
|
+
</div>
|
|
469
|
+
<div className="btn-operate-group">
|
|
470
|
+
<Button variant="contained" color="primary" onClick={() => handleEnableAudioVolumeEvaluation()} disabled={isEnableAudioVolume}>
|
|
471
|
+
开启音量回调
|
|
472
|
+
</Button>
|
|
473
|
+
<Button variant="contained" color="primary" onClick={() => handleDisableAudioVolumeEvaluation()} disabled={!isEnableAudioVolume}>
|
|
474
|
+
关闭音量回调
|
|
475
|
+
</Button>
|
|
476
|
+
</div>
|
|
477
|
+
{isJoined && <div className="btn-operate-group">
|
|
478
|
+
<Button variant="contained" color="primary" onClick={() => handleStartScreenShare()} disabled={isScreeShare}>
|
|
479
|
+
开启屏幕分享
|
|
480
|
+
</Button>
|
|
481
|
+
<Button variant="contained" color="primary" onClick={() => handleStopScreenShare()} disabled={!isScreeShare}>
|
|
482
|
+
关闭屏幕分享
|
|
483
|
+
</Button>
|
|
484
|
+
</div>
|
|
485
|
+
}
|
|
486
|
+
{/* <Button variant="contained" color="primary" onClick={() => operateFirstRemote()} style={{ marginTop: '8px' }}>
|
|
487
|
+
{isStopRemote ? 'start' : 'stop'}第一个远端用户
|
|
488
|
+
</Button> */}
|
|
489
|
+
{/*
|
|
490
|
+
<Button variant="contained" color="primary" onClick={() => disableAudioVolumeEvaluation()} style={{ marginTop: '8px' }}>关闭音量采集</Button>
|
|
491
|
+
<Button variant="contained" color="primary" onClick={() => muteAllRemoteAudio()} style={{ marginTop: '8px' }}>{isMuteAllRemoteAudio ? '开启' : '关闭'}远端所有音频</Button> */}
|
|
492
|
+
</div>
|
|
493
|
+
</div>
|
|
494
|
+
|
|
495
|
+
<div className="video-view-preview">
|
|
496
|
+
<div className="video-wrapper local-user">
|
|
497
|
+
<div className="user-desc">
|
|
498
|
+
<span className="user-type">本地用户</span>
|
|
499
|
+
<span className="user-role" id="localUserRole"></span>
|
|
500
|
+
</div>
|
|
501
|
+
<div id="localVideoWrapper"></div>
|
|
502
|
+
</div>
|
|
503
|
+
<div id="localVideoWrapper2" style={{ width: '400px', height: '300px', backgroundColor: '#eeeeee' }}></div>
|
|
504
|
+
<div className="video-wrapper remote-user">
|
|
505
|
+
<div className="user-desc">
|
|
506
|
+
<span className="user-type">远程用户</span>
|
|
507
|
+
<span className="user-role" id="remoteUserRole"></span>
|
|
508
|
+
</div>
|
|
509
|
+
<div className="video-wrapper-container">
|
|
510
|
+
<div className="remoteVideoWrapper" id="remote-screen-share-container">
|
|
511
|
+
<div className="remote-share-text">远端屏幕分享</div>
|
|
512
|
+
</div>
|
|
513
|
+
{remoteUserIdList.map((userId, index) => (
|
|
514
|
+
<div id={userId} key={userId + '_' + index} className="remoteVideoWrapper"></div>
|
|
515
|
+
))}
|
|
516
|
+
</div>
|
|
517
|
+
</div>
|
|
518
|
+
</div>
|
|
519
|
+
</div>
|
|
520
|
+
);
|
|
521
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
.content-container {
|
|
2
|
+
display: flex;
|
|
3
|
+
.operate-container {
|
|
4
|
+
display: flex;
|
|
5
|
+
flex-direction: column;
|
|
6
|
+
width: 320px;
|
|
7
|
+
.external-operate-container {
|
|
8
|
+
display: flex;
|
|
9
|
+
justify-content: center;
|
|
10
|
+
flex-direction: column;
|
|
11
|
+
.btn-operate-group {
|
|
12
|
+
display: flex;
|
|
13
|
+
justify-content: space-between;
|
|
14
|
+
margin-top: 6px;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
.select-container {
|
|
18
|
+
display: flex;
|
|
19
|
+
margin-top: 8px;
|
|
20
|
+
.select-item-label {
|
|
21
|
+
flex: 1;
|
|
22
|
+
width: 80px;
|
|
23
|
+
}
|
|
24
|
+
.select-item {
|
|
25
|
+
height: 28px;
|
|
26
|
+
width: 240px;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
.video-view-preview {
|
|
31
|
+
margin-left: 12px;
|
|
32
|
+
/* padding: 1rem 2rem; */
|
|
33
|
+
display: flex;
|
|
34
|
+
flex: 1;
|
|
35
|
+
flex-direction: column;
|
|
36
|
+
justify-content: center;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.video-wrapper {
|
|
41
|
+
flex: 0 0 auto;
|
|
42
|
+
padding: 0 0.5rem;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.user-desc {
|
|
46
|
+
margin: 0.5rem 0rem;
|
|
47
|
+
}
|
|
48
|
+
.user-type {
|
|
49
|
+
font-weight: bold;
|
|
50
|
+
}
|
|
51
|
+
.video-wrapper-container {
|
|
52
|
+
display: flex;
|
|
53
|
+
flex-wrap: wrap;
|
|
54
|
+
margin-bottom: 1rem;
|
|
55
|
+
}
|
|
56
|
+
#localVideoWrapper,
|
|
57
|
+
.remoteVideoWrapper {
|
|
58
|
+
position: relative;
|
|
59
|
+
width: 320px;
|
|
60
|
+
height: 184px;
|
|
61
|
+
box-shadow: 2px 2px 18px 4px #c0c0c0;
|
|
62
|
+
background-color: lightblue;
|
|
63
|
+
margin-right: 20px;
|
|
64
|
+
border-radius: 8px;
|
|
65
|
+
}
|
|
66
|
+
.remote-share-text {
|
|
67
|
+
position: absolute;
|
|
68
|
+
background-color: white;
|
|
69
|
+
color: black;
|
|
70
|
+
opacity: 0.7;
|
|
71
|
+
border-radius: 6px;
|
|
72
|
+
bottom: 0rem;
|
|
73
|
+
display: flex;
|
|
74
|
+
justify-content: center;
|
|
75
|
+
align-items: center;
|
|
76
|
+
padding: 0rem 0.5rem;
|
|
77
|
+
z-index: 100;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.local-statistic,
|
|
81
|
+
.remote-statistic {
|
|
82
|
+
margin-top: 1rem;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.config-form {
|
|
86
|
+
margin: 1rem 0;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.form-line {
|
|
90
|
+
padding: 0.5rem 0.25rem;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
|