/*
|
* @Description: 音视频通话集成
|
* @Date: 2022-03-14 17:15:23
|
* @LastEditTime: 2022-03-23 17:47:14
|
*/
|
import TRTC from 'trtc-js-sdk';
|
import { isUndefined } from '@/utils/utils.js';
|
|
export default {
|
data() {
|
return {
|
client: null,
|
localStream: null,
|
remoteStreamList: [],
|
isJoining: false,
|
isJoined: false,
|
isPublishing: false,
|
isPublished: false,
|
isMutedVideo: false,
|
isMutedAudio: false,
|
isPlayingLocalStream: false,
|
};
|
},
|
|
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');
|
} 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() {
|
// 文档:https://web.sdk.qcloud.com/trtc/webrtc/doc/zh-cn/module-ClientEvent.html#.AUDIO_VOLUME
|
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();
|
});
|
// fired when a remote peer is joining the room
|
this.client.on('peer-join', (event) => {
|
const { userId } = event;
|
console.log(`peer-join ${userId}`, event);
|
});
|
// fired when a remote peer is leaving the room
|
this.client.on('peer-leave', (event) => {
|
const { userId } = event;
|
console.log(`peer-leave ${userId}`, event);
|
});
|
|
// fired when a remote stream is added
|
this.client.on('stream-added', (event) => {
|
const { stream: remoteStream } = event;
|
const remoteUserId = remoteStream.getUserId();
|
if (remoteUserId === `share_${this.userId}`) {
|
// don't need screen shared by us
|
this.unSubscribe(remoteStream);
|
} else {
|
console.log(`remote stream added: [${remoteUserId}] type: ${remoteStream.getType()}`);
|
// subscribe to this remote stream
|
this.subscribe(remoteStream);
|
this.addSuccessLog(`RemoteStream added: [${remoteUserId}].`);
|
}
|
});
|
// fired when a remote stream has been subscribed
|
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.$nextTick(() => {
|
this.playRemoteStream(remoteStream, remoteUserId);
|
});
|
});
|
// fired when the remote stream is removed, e.g. the remote user called Client.unpublish()
|
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}`);
|
});
|
},
|
},
|
};
|