RTRC实时音视频Web端
Vue 接入腾讯云【实时音视频】TRTC
vue接入腾讯实时音视频trtc-js-sdk(web版)
comp-rom.vue
<template>
<div>
<el-row>
<div hidden>
<el-table :data="userLists" v-loading="userLoading" style="width: 100%;" max-height="70%">
<el-table-column prop="userAudioId" label="用户名"></el-table-column>
<el-table-column label="操作" align="center">
<template slot-scope="scope">
<div v-if="userAudioId != scope.row.userAudioId">
<el-button
v-if="scope.row.isAdmin == '0'"
size="small"
type="danger"
icon="el-icon-delete"
@click="goLeave(scope.row)"
>踢出房间</el-button>
</div>
</template>
</el-table-column>
</el-table>
<div class="info-container" style="height: 30%" hidden>
<div style=" height: 13vh;overflow-x: hidden;">
<div v-if="isHostMode" class="log-container" ref="logContainer">
<p class="log-label">Log:</p>
<div v-for="(item, index) in logList" :key="index">
<span class="log-state" v-if="item.type === 'success'">🟩</span>
<span class="log-state" v-if="item.type === 'failed'">🟥</span>
<span>{{ item.log }}</span>
</div>
</div>
</div>
</div>
</div>
<el-col :span="12">
<el-card class="box-card">
<div class="video-card" style="height:500px;">
<div v-if="switchStream">
<div id="switchStream" style="width: 650px; height: 488px" @click="reductionVideo()"></div>
<div>选中用户:{{ switchStream.getUserId() }}</div>
<el-button
size="small"
type="danger"
icon="el-icon-close"
v-if="emergencyAudioDTO.isAdmin == '0'"
@click="goLeave(switchStream)"
></el-button>
<el-button
:type="obj[switchStream.getUserId()+0] ? 'danger' : ''"
icon="el-icon-video-camera"
@click="otherMuteVideos(switchStream.getUserId()+0, switchStream)"
></el-button>
<el-button
:type="obj[switchStream.getUserId()+1] ? 'danger' : ''"
icon="el-icon-turn-off-microphone"
@click="otherMuteAudios(switchStream.getUserId()+1, switchStream)"
></el-button>
</div>
</div>
</el-card>
</el-col>
<el-col :span="12">
<el-card class="box-card">
<div>
<div id="mapDivContainer" style="width: 100%; height:500px"></div>
</div>
<div hidden>
<mapview ref="mapView"></mapview>
</div>
</el-card>
</el-col>
</el-row>
<el-row>
<div style="margin-top: 5px;">
<el-card class="box-card" style="display: flex;">
<div style="margin:15px 4px;">
<div v-if="localStream">
<div id="localStream" style="width: 300px; height: 230px" @click="switchVideo(localStream)"></div>
<div>当前用户:{{ userAudioId }}</div>
<div v-if="isPlayingLocalStream">
<div>
<el-button icon="el-icon-video-camera" v-if="!isMutedVideo" @click="muteVideo"></el-button>
<el-button type="danger" icon="el-icon-video-camera" v-if="isMutedVideo" @click="unmuteVideo"></el-button>
<el-button icon="el-icon-microphone" v-if="!isMutedAudio" @click="muteAudio"></el-button>
<el-button type="danger" icon="el-icon-turn-off-microphone" v-if="isMutedAudio" @click="unmuteAudio"></el-button>
</div>
</div>
</div>
<div v-else style="width: 300px; height: 230px; border: 1px solid #eee; text-align: center;">
<img
class="imgErrors"
src="@/assets/images/video-erro.png"
alt="dark"
title="网络原因,当前可能无法正常视频通话,请检查您的通信协议或摄像头"
/>
<div>当前用户:【{{userAudioId}}】</div>
</div>
</div>
<div v-if="remoteStreamList.length > 0" style="display: flex;">
<div style="margin:15px 4px;" v-for="(item, index) in remoteStreamList" :key="index">
<div
:id="item.getUserId()"
:key="item.getUserId()"
class="userDiv"
style="width: 300px; height: 230px"
@click="switchVideo(item)"
></div>
<b v-for="items in allUserInfo" :key="items.userid">
<span v-if="items.userid == item.getUserId()">{{items.username}}</span>
</b>
<div>用户: {{ item.getUserId() }}</div>
<el-button
size="small"
type="danger"
icon="el-icon-close"
v-if="emergencyAudioDTO.isAdmin == '0'"
@click="goLeave(item)"
></el-button>
<el-button
:type="obj[item.getUserId()+0] ? 'danger' : ''"
icon="el-icon-video-camera"
@click="otherMuteVideos(item.getUserId()+0,item)"
></el-button>
<el-button
:type="obj[item.getUserId()+1] ? 'danger' : ''"
icon="el-icon-turn-off-microphone"
@click="otherMuteAudios(item.getUserId()+1,item)"
></el-button>
</div>
</div>
</el-card>
</div>
</el-row>
</div>
</template>
<script>
import Mapview from '@/components/comp-map'
</script>
<script>
var map, mapTc, mapTc1;
import rtc from './mixins/rtc.js';
import shareRtc from './mixins/share-rtc.js';
import LibGenerateTestUserSig from '@/utils/lib-generate-test-usersig.min.js';
import screenfull from 'screenfull'
import { listAudioRecive, joinRoom, kickOutRoom, deleteAudioRecive, getUserInfo, upOnlineUser } from "@/api/web/bigScreen/emergencyCommandScreen/emergencyCommandScreen";
import Mapview from '../components/comp-map';
import TRTC from 'trtc-js-sdk';
var markList = [];
export default {
name: 'compRoom',
mixins: [rtc, shareRtc],
props: {
type: String,
sdkAppId: Number,
secretKey: String,
userId: String,
userAudioId: String,
roomId: Number,
cameraId: String,
microphoneId: String,
inviteUserSig: String,
},
components: { Mapview },
data() {
return {
fullscreen: false,
list: [
{ key: "第一个盒子" },
{ key: "第一个盒子" },
{ key: "第一个盒子" },
{ key: "第一个盒子" },
{ key: "第一个盒子" },
{ key: "第一个盒子" }
],
otherMutedVideo: false,
streamList: [],
otherMutedAudio: false,
logList: [],
userIds: [],
inviteLink: '',
showCopiedTip: false,
userLists: [],
userLoading: false,
lng: 0,
lat: 0,
map: null,
divWidth: 90,
divHeight: 90,
changeSizeStatus: true,
timers1: null,
timers2: null,
timers3: null,
longitude: 0,
latitude: 0,
allUserInfo: [],
emergencyAudioDTO: {},
switchStream: null,
currentID: '',
isLocalStream: true,
};
},
beforeDestroy() {
clearInterval(this.timers1);
this.timers1 = null;
clearInterval(this.timers2);
this.timers2 = null;
},
computed: {
isHostMode() {
return this.type !== 'invite';
},
isEnLang() {
},
showInviteLink() {
return this.isHostMode && (this.isJoined || this.isShareJoined) && this.inviteLink;
},
},
mounted() {
window.addEventListener('beforeunload', e => this.beforeunloadHandler(e))
this.handleJoinRoom()
},
updated() {
},
watch: {
cameraId(val) {
this.switchDevice('video', val);
},
microphoneId(val) {
this.switchDevice('audio', val);
},
roomId(newVal) {
this.roomId = newVal
},
userAudioId(newVal) {
this.userAudioId = newVal
console.log("new监听" + newVal)
this.handleJoinRoom()
},
latitude(newVal) {
this.joinRooms()
},
remoteStreamList(val) {
this.upOnlineUser(val)
},
leaveUserId(val) {
if (this.currentID = val) {
if (this.switchStream) {
document.getElementById('switchStream').innerHTML = ""
this.switchStream = null;
this.currentID = null;
}
}
}
},
destroyed() {
window.removeEventListener('beforeunload', e => this.beforeunloadHandler(e))
},
methods: {
beforeunloadHandler(e) {
var query = {}
query.userId = this.userId
query.roomId = this.roomId
query.userAudioId = this.userAudioId
deleteAudioRecive(query)
},
clearTimes() {
clearInterval(this.timers1);
this.timers1 = null;
clearInterval(this.timers2);
this.timers2 = null;
clearInterval(this.timers3);
this.timers3 = null;
},
initAMap() {
var marker = {};
var zoom = 12;
var lon = 112.544772;
var lat = 30.678429;
if (this.map == null) {
this.map = new T.Map('mapDivContainer');
this.map.centerAndZoom(new T.LngLat(lon, lat), zoom);
}
var lays = this.map.getOverlays();
for (var i = lays.length - 1; i >= 0; i--) {
if (lays[i].Type = 1000) {
this.map.removeOverLay(lays[i]);
}
}
for (let i = 0; i < this.userLists.length; i++) {
const mapElement = this.userLists[i];
marker = new T.Marker(new T.LngLat(mapElement.longitude, mapElement.latitude));
if (mapElement.userAudioId === this.userAudioId) {
if (mapElement.longitude !== 0 && mapElement.latitude !== 0) {
this.map.centerAndZoom(new T.LngLat(mapElement.longitude, mapElement.latitude));
this.map.addOverLay(marker);
}
} else {
this.map.addOverLay(marker);
}
}
this.timers1 = setTimeout(() => {
console.log("1111111111111")
this.initAMap()
}, 1500);
},
changeSize() {
this.changeSizeStatus = !this.changeSizeStatus
var changeSizeStatus = !this.changeSizeStatus
if (changeSizeStatus) {
this.divWidth = this.divWidth + 20
this.divHeight = this.divHeight + 20
} else {
this.divWidth = this.divWidth - 20
this.divHeight = this.divHeight - 20
}
},
generateInviteLink() {
if (!this.isHostMode) {
return;
}
const { sdkAppId, secretKey, roomId } = this;
const inviteUserId = `user_${parseInt(Math.random() * 100000000, 10)}`;
const userSigGenerator = new LibGenerateTestUserSig(sdkAppId, secretKey, 604800);
const inviteUserSig = userSigGenerator.genTestUserSig(inviteUserId);
this.inviteLink = encodeURI(`${location.origin}${location.pathname}#/invite?sdkAppId=${sdkAppId}&userSig=${inviteUserSig}&roomId=${roomId}&userId=${inviteUserId}`);
},
handleCopyInviteLink() {
navigator.clipboard.writeText(this.inviteLink);
this.showCopiedTip = true;
setTimeout(() => {
this.showCopiedTip = false;
}, 1500);
this.generateInviteLink();
},
async handleJoinRoom() {
console.log("子组件传值1" + this.userId)
console.log("子组件传值2" + this.roomId)
if (this.isHostMode) {
if (!this.sdkAppId || !this.secretKey) {
alert('Please enter sdkAppId and secretKey');
return;
}
if (!this.userId || !this.roomId) {
alert('Please enter userId and roomId');
return;
}
const userSigGenerator = new LibGenerateTestUserSig(this.sdkAppId, this.secretKey, 604800);
this.userSig = userSigGenerator.genTestUserSig(this.userId);
} else {
if (!this.sdkAppId || !this.inviteUserSig || !this.userId || !this.roomId) {
alert('Please reacquire the invitation link');
return;
}
this.userSig = this.inviteUserSig;
}
await this.joinRoom();
await this.initClient();
await this.join();
await this.initLocalStream();
await this.playLocalStream();
await this.publish();
this.generateInviteLink();
this.client.on('client-banned', async (event) => {
alert("很抱歉,您当前被主持人踢出房间了")
this.isPublished = false;
this.localStream = null;
this.$emit('joinRoomVisible', false)
await this.leave();
});
},
getLocation() {
var that = this
this.timers2 = setTimeout(() => {
console.log("2222222222222222222222222222222222222")
that.getLocation()
}, 5000)
AMap.plugin('AMap.Geolocation', function () {
var geolocation = new AMap.Geolocation({
enableHighAccuracy: true,
timeout: 10000,
buttonPosition: 'RB',
buttonOffset: new AMap.Pixel(10, 20),
zoomToAccuracy: true,
});
geolocation.getCurrentPosition(function (status, result) {
if (status === 'complete') {
this.lng = result.position.getLng();
this.lat = result.position.getLat();
var query = {}
query.userId = that.userId
query.roomId = that.roomId
query.longitude = this.lng
that.longitude = this.lng
that.latitude = this.lat
query.latitude = this.lat
query.userAudioId = that.userAudioId
} else {
}
});
});
},
async joinRooms() {
var that = this
var query = {}
query.userId = that.userId
query.roomId = that.roomId
query.latitude = that.latitude
query.longitude = that.longitude
query.userAudioId = that.userAudioId
console.log(query)
joinRoom(query).then(response => {
});
},
async joinRoom() {
var query = {}
query.userId = this.userId
query.roomId = this.roomId
query.latitude = this.lng
query.longitude = this.lat
query.userAudioId = this.userAudioId
var that = this
joinRoom(query).then(response => {
this.initUserInfo();
this.getUserInfo();
this.$nextTick(() => {
this.getLocation()
})
this.initAMap()
});
},
initUserInfo() {
var that = this
var query = {}
query.roomId = this.roomId
that.userLoading = true;
listAudioRecive(query).then(res => {
that.userLists = res.data.emergencyAudioReciveList
that.userLoading = false;
this.timers3 = setTimeout(() => {
this.initUserInfo()
}, 5500);
});
},
otherMuteVideos(index, item) {
this.obj[index] = !this.obj[index]
this.obj = Object.assign({}, { ...this.obj })
if (this.obj[index]) {
item.muteVideo();
} else {
item.unmuteVideo();
}
},
otherMuteAudios(index, item) {
this.obj[index] = !this.obj[index]
this.obj = Object.assign({}, { ...this.obj })
if (this.obj[index]) {
item.muteAudio();
} else {
item.unmuteAudio();
}
},
beforeRefreshClose() {
let self = this;
window.onbeforeunload = function (e) {
if (self.$route.name == "路由名称") {
e = e || window.event;
if (e) e.returnValue = "关闭提示1";
return "关闭提示2";
} else window.onbeforeunload = null;
this.handleLeave()
};
},
async handlePublish() {
await this.publish();
},
async handleUnpublish() {
await this.unPublish();
},
getUserInfo() {
var query = {}
query.roomId = this.roomId
query.userId = this.$store.getters.userId + ""
getUserInfo(query).then(res => {
this.allUserInfo = res.data.userInfo
this.emergencyAudioDTO = res.data.emergencyAudioDTO
});
},
upOnlineUser(remoteStreamList) {
var query = {}
query.roomId = this.roomId
query.userIds = []
remoteStreamList.forEach((item, index) => {
this.userIds.push(item.userId_)
});
debugger
upOnlineUser(query).then(res => {
});
},
goLeave(row) {
var query = {}
query.userId = row.userId_
query.roomId = this.roomId
kickOutRoom(query)
},
async handleLeave() {
var query = {}
query.userId = this.userId
query.roomId = this.roomId
query.userAudioId = this.userAudioId
deleteAudioRecive(query)
await this.leave();
},
async handleStartScreenShare() {
if (!this.sdkAppId || !this.secretKey) {
alert('Please enter sdkAppId and secretKey');
return;
}
await this.initShareClient();
await this.initShareLocalStream();
await this.handleShareJoin();
await this.handleSharePublish();
this.generateInviteLink();
},
async handleStopScreenShare() {
await this.handleShareUnpublish();
await this.handleShareLeave();
},
addSuccessLog(log) {
if (!this.isHostMode) {
return;
}
this.logList.push({
type: 'success',
log,
});
const { scrollHeight } = this.$refs.logContainer;
this.$refs.logContainer.scrollTop = scrollHeight;
},
addFailedLog(log) {
if (!this.isHostMode) {
return;
}
this.logList.push({
type: 'failed',
log,
});
const { scrollHeight } = this.$refs.logContainer;
this.$refs.logContainer.scrollTop = scrollHeight;
},
reportSuccessEvent(name) {
},
reportFailedEvent(name, error, type = 'rtc') {
},
async switchVideo(item) {
console.log(item, '当前点击');
this.currentID = item.getUserId();
const isVideoCapturingSupported = () => 'captureStream' in HTMLVideoElement.prototype;
if (!isVideoCapturingSupported()) {
console.log('your browser does not support capturing stream from video element');
return
}
if (this.switchStream) {
document.getElementById('switchStream').innerHTML = "";
this.switchStream = null;
}
const video = document.getElementById('video_' + item.id_);
console.log(video, 'video');
const stream = video.captureStream();
const audioTrack = stream.getAudioTracks()[0];
const videoTrack = stream.getVideoTracks()[0];
this.switchStream = TRTC.createStream({ userId: item.getUserId(), audioSource: audioTrack, videoSource: videoTrack });
this.switchStream.setVideoProfile('480p');
await this.switchStream.initialize();
this.switchStream.play('switchStream', { objectFit: 'contain' }).catch();
},
reductionVideo() {
if (this.switchStream) {
document.getElementById('switchStream').innerHTML = "";
this.switchStream = null;
this.currentID = null;
}
}
},
};
</script>
<style lang="scss" scoped>
.video-card {
display: flex;
flex-wrap: nowrap;
justify-content: center;
align-content: center;
align-items: center;
}
.rtc-container {
.label {
margin: 14px 0 6px;
text-align: left;
font-weight: bold;
}
.control-container {
text-align: left;
margin-bottom: 10px;
div:not(:nth-last-child(1)) {
margin-bottom: 10px;
}
.button:not(:first-child) {
margin-left: 2px;
}
}
.invite-link-container {
width: 100%;
color: #084298;
background-color: #cfe2ff;
position: relative;
padding: 10px 16px;
margin-bottom: 16px;
border: 1px solid #b6d4fe;
border-radius: 0.25rem;
.invite-input {
margin-top: 10px;
}
.invite-btn {
display: flex;
cursor: pointer;
}
}
.info-container {
width: 100%;
display: flex;
justify-content: space-between;
.log-container {
flex-grow: 1;
border: 1px solid #dddddd;
height: 360px;
padding: 10px;
margin-right: 16px;
overflow-y: scroll;
.log-label {
margin: 0 0 6px;
font-weight: bold;
}
.log-state {
display: inline-block;
margin-right: 6px;
}
> div {
font-size: 12px;
}
}
.local-stream-container {
width: 480px;
height: 360px;
position: relative;
flex-shrink: 0;
.local-stream-content {
width: 100%;
height: 100%;
}
.local-stream-control {
width: 100%;
height: 30px;
position: absolute;
bottom: 0;
background-color: rgba(0, 0, 0, 0.3);
display: flex;
justify-content: flex-end;
align-items: center;
padding: 0 10px;
.control {
margin-left: 10px;
}
.icon-class {
color: #fff;
cursor: pointer;
width: 20px;
height: 20px;
}
}
}
}
.info-container-mobile {
display: block;
.log-container {
margin-right: 0;
}
.local-stream-container {
width: 320px;
height: 240px;
margin-top: 10px;
}
}
.remote-container {
width: 100%;
margin-top: 10px;
display: flex;
flex-wrap: wrap;
.remote-stream-container {
width: 320px;
height: 240px;
margin: 0 10px 10px 0;
}
}
.line {
border-right: 1px solid #ccc;
}
.imgErrors {
max-width: 100%;
max-height: 100%;
position: relative;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
}
::v-deep .el-card__body {
display: flex;
}
</style>
<i18n>
{
"en": {
"Operation": "Operation",
"Join Room": "Join Room",
"Publish": "Publish",
"Unpublish": "Unpublish",
"Leave Room": "Leave Room",
"Start Screen Share": "Start Screen Share",
"Stop Screen Share": "Stop Screen Share",
"Please enter sdkAppId and secretKey": "Please enter sdkAppId and secretKey",
"Please enter userId and roomId": "Please enter userId and roomId",
"Please reacquire the invitation link": "Please reacquire the invitation link!"
},
"zh": {
"Operation": "操作",
"Join Room": "进入房间",
"Publish": "发布流",
"Unpublish": "取消发布流",
"Leave Room": "离开房间",
"Start Screen Share": "开始共享屏幕",
"Stop Screen Share": "停止共享屏幕",
"Please enter sdkAppId and secretKey": "请输入 sdkAppId 和 secretKey",
"Please enter userId and roomId": "请输入 userId 和 roomId",
"Please reacquire the invitation link": "请重新获取邀请链接!"
}
}
</i18n>
rtc.js
import TRTC from 'trtc-js-sdk';
import { isUndefined } from '@/utils/utils.js';
export default {
data() {
return {
client: null,
localStream: null,
remoteStreamList: [],
obj:{},
isJoining: false,
isJoined: false,
isPublishing: false,
isPublished: false,
isMutedVideo: false,
isMutedAudio: false,
isPlayingLocalStream: false,
leaveUserId: null,
};
},
methods: {
async initClient() {
this.client = TRTC.createClient({
mode: 'rtc',
sdkAppId: this.sdkAppId,
userId: this.userId,
userSig: this.userSig,
});
this.addSuccessLog(`Client [${this.userId}] created.`);
this.handleClientEvents();
},
async initLocalStream() {
this.localStream = TRTC.createStream({
audio: true,
video: true,
userId: this.userId,
cameraId: this.cameraId,
microphoneId: this.microphoneId,
});
try {
await this.localStream.initialize();
this.addSuccessLog(`LocalStream [${this.userId}] initialized.`);
} catch (error) {
this.localStream = null;
this.addFailedLog(`LocalStream failed to initialize. Error: ${error.message}.`);
throw error;
}
},
playLocalStream() {
this.localStream.play('localStream')
.then(() => {
this.isPlayingLocalStream = true;
this.addSuccessLog(`LocalStream [${this.userId}] playing.`);
})
.catch((error) => {
this.addFailedLog(`LocalStream [${this.userId}] failed to play. Error: ${error.message}`);
});
},
destroyLocalStream() {
this.localStream && this.localStream.stop();
this.localStream && this.localStream.close();
this.localStream = null;
this.isPlayingLocalStream = false;
},
playRemoteStream(remoteStream, element) {
if (remoteStream.getType() === 'main' && remoteStream.getUserId().indexOf('share') >= 0) {
remoteStream.play(element, { objectFit: 'contain' }).catch();
} else {
remoteStream.play(element).catch();
}
},
resumeStream(stream) {
stream.resume();
},
async join() {
if (this.isJoining || this.isJoined) {
return;
}
this.isJoining = true;
!this.client && await this.initClient();
try {
await this.client.join({ roomId: this.roomId });
this.isJoining = false;
this.isJoined = true;
this.addSuccessLog(`Join room [${this.roomId}] success.`);
this.reportSuccessEvent('joinRoom');
this.startGetAudioLevel();
} catch (error) {
this.isJoining = false;
console.error('join room failed', error);
this.addFailedLog(`Join room ${this.roomId} failed, please check your params. Error: ${error.message}`);
this.reportFailedEvent('joinRoom', error);
throw error;
}
},
async publish() {
if (!this.isJoined || this.isPublishing || this.isPublished) {
return;
}
this.isPublishing = true;
try {
await this.client.publish(this.localStream);
this.isPublishing = false;
this.isPublished = true;
this.addSuccessLog('LocalStream is published successfully.');
this.reportSuccessEvent('publish');
if(this.localStream) {
this.switchVideo(this.localStream);
}
} catch (error) {
this.isPublishing = false;
console.error('publish localStream failed', error);
this.addFailedLog(`LocalStream is failed to publish. Error: ${error.message}`);
this.reportFailedEvent('publish');
throw error;
}
},
async unPublish() {
if (!this.isPublished || this.isUnPublishing) {
return;
}
this.isUnPublishing = true;
try {
await this.client.unpublish(this.localStream);
this.isUnPublishing = false;
this.isPublished = false;
this.addSuccessLog('localStream unpublish successfully.');
this.reportSuccessEvent('unpublish');
} catch (error) {
this.isUnPublishing = false;
console.error('unpublish localStream failed', error);
this.addFailedLog(`LocalStream is failed to unpublish. Error: ${error.message}`);
this.reportFailedEvent('unpublish', error);
throw error;
}
},
async subscribe(remoteStream, config = { audio: true, video: true }) {
try {
await this.client.subscribe(remoteStream, {
audio: isUndefined(config.audio) ? true : config.audio,
video: isUndefined(config.video) ? true : config.video,
});
this.addSuccessLog(`Subscribe [${remoteStream.getUserId()}] success.`);
this.reportSuccessEvent('subscribe');
} catch (error) {
console.error(`subscribe ${remoteStream.getUserId()} with audio: ${config.audio} video: ${config.video} error`, error);
this.addFailedLog(`Subscribe ${remoteStream.getUserId()} failed!`);
this.reportFailedEvent('subscribe', error);
}
},
async unSubscribe(remoteStream) {
try {
await this.client.unsubscribe(remoteStream);
this.addSuccessLog(`unsubscribe [${remoteStream.getUserId()}] success.`);
this.reportSuccessEvent('unsubscribe');
} catch (error) {
console.error(`unsubscribe ${remoteStream.getUserId()} error`, error);
this.addFailedLog(`unsubscribe ${remoteStream.getUserId()} failed!`);
this.reportFailedEvent('unsubscribe', error);
}
},
async leave() {
if (!this.isJoined || this.isLeaving) {
return;
}
this.isLeaving = true;
this.stopGetAudioLevel();
this.isPublished && await this.unPublish();
this.localStream && this.destroyLocalStream();
try {
await this.client.leave();
this.isLeaving = false;
this.isJoined = false;
this.addSuccessLog('Leave room success.');
this.reportSuccessEvent('leaveRoom');
} catch (error) {
this.isLeaving = false;
console.error('leave room error', error);
this.addFailedLog(`Leave room failed. Error: ${error.message}`);
this.reportFailedEvent('leaveRoom', error);
throw error;
}
},
muteVideo() {
if (this.localStream) {
this.localStream.muteVideo();
this.isMutedVideo = true;
this.addSuccessLog('LocalStream muted video.');
}
},
muteAudio() {
if (this.localStream) {
this.localStream.muteAudio();
this.isMutedAudio = true;
this.addSuccessLog('LocalStream muted audio.');
}
},
unmuteVideo() {
if (this.localStream) {
this.localStream.unmuteVideo();
this.isMutedVideo = false;
this.addSuccessLog('LocalStream unmuted video.');
}
},
unmuteAudio() {
if (this.localStream) {
this.localStream.unmuteAudio();
this.isMutedAudio = false;
this.addSuccessLog('LocalStream unmuted audio.');
}
},
switchDevice(type, deviceId) {
try {
if (this.localStream) {
this.localStream.switchDevice(type, deviceId);
this.addSuccessLog(`Switch ${type} device success.`);
}
} catch (error) {
console.error('switchDevice failed', error);
this.addFailedLog(`Switch ${type} device failed.`);
}
},
startGetAudioLevel() {
this.client.on('audio-volume', (event) => {
event.result.forEach(({ userId, audioVolume }) => {
if (audioVolume > 2) {
console.log(`user: ${userId} is speaking, audioVolume: ${audioVolume}`);
}
});
});
this.client.enableAudioVolumeEvaluation(200);
},
stopGetAudioLevel() {
this.client && this.client.enableAudioVolumeEvaluation(-1);
},
handleClientEvents() {
this.client.on('error', (error) => {
console.error(error);
alert(error);
});
this.client.on('client-banned', async (event) => {
console.warn(`client has been banned for ${event.reason}`);
this.isPublished = false;
this.localStream = null;
await this.leave();
});
this.client.on('peer-join', (event) => {
const { userId } = event;
console.log(`peer-join ${userId}`, event);
});
this.client.on('peer-leave', (event) => {
const { userId } = event;
console.log(`peer-leave ${userId}`, event);
this.leaveUserId = userId;
});
this.client.on('stream-added', (event) => {
const { stream: remoteStream } = event;
const remoteUserId = remoteStream.getUserId();
if (remoteUserId === `share_${this.userId}`) {
this.unSubscribe(remoteStream);
} else {
console.log(`remote stream added: [${remoteUserId}] type: ${remoteStream.getType()}`);
this.subscribe(remoteStream);
this.addSuccessLog(`RemoteStream added: [${remoteUserId}].`);
}
});
this.client.on('stream-subscribed', (event) => {
const { stream: remoteStream } = event;
const remoteUserId = remoteStream.getUserId();
console.log('stream-subscribed userId: ', remoteUserId);
this.addSuccessLog(`RemoteStream subscribed: [${remoteUserId}].`);
this.remoteStreamList.push(remoteStream);
this.remoteStreamList.forEach((item) => {
for (let i = 0; i < 2; i++) {
this.$set(this.obj,item.id+i,false);
}
})
this.$nextTick(() => {
this.playRemoteStream(remoteStream, remoteUserId);
});
});
this.client.on('stream-removed', (event) => {
const { stream: remoteStream } = event;
remoteStream.stop();
const index = this.remoteStreamList.indexOf(remoteStream);
if (index >= 0) {
this.remoteStreamList.splice(index, 1);
}
console.log(`stream-removed userId: ${remoteStream.getUserId()} type: ${remoteStream.getType()}`);
});
this.client.on('stream-updated', (event) => {
const { stream: remoteStream } = event;
console.log(`type: ${remoteStream.getType()} stream-updated hasAudio: ${remoteStream.hasAudio()} hasVideo: ${remoteStream.hasVideo()}`);
this.addSuccessLog(`RemoteStream updated: [${remoteStream.getUserId()}] audio:${remoteStream.hasAudio()}, video:${remoteStream.hasVideo()}.`);
});
this.client.on('mute-audio', (event) => {
const { userId } = event;
console.log(`${userId} mute audio`);
this.addSuccessLog(`[${event.userId}] mute audio.`);
});
this.client.on('unmute-audio', (event) => {
const { userId } = event;
console.log(`${userId} unmute audio`);
this.addSuccessLog(`[${event.userId}] unmute audio.`);
});
this.client.on('mute-video', (event) => {
const { userId } = event;
console.log(`${userId} mute video`);
this.addSuccessLog(`[${event.userId}] mute video.`);
});
this.client.on('unmute-video', (event) => {
const { userId } = event;
console.log(`${userId} unmute video`);
this.addSuccessLog(`[${event.userId}] unmute video.`);
});
this.client.on('connection-state-changed', (event) => {
console.log(`RtcClient state changed to ${event.state} from ${event.prevState}`);
});
this.client.on('network-quality', (event) => {
const { uplinkNetworkQuality, downlinkNetworkQuality } = event;
console.log(`network-quality uplinkNetworkQuality: ${uplinkNetworkQuality}, downlinkNetworkQuality: ${downlinkNetworkQuality}`);
});
},
},
};