上个小节我们通过TRTC官方文档,掌握了创建TrtcClient对象和推送本地流、订阅远端流的方法,这节课咱们把学到的这些内容应用在meeting_video.vue
页面吧。
一、熟悉前端页面
我们动手写JS程序之前,还是要先熟悉前端页面和视频会议的流程。例如当用户进入到meeting_video.vue
页面,并不意味着连接上了在线视频会议室。而是需要我们手动点击右下角的电话图标,才会创建TrtcClient
对象连接视频会议室,订阅远端流、推送本地流。当我再次点击电话图标,则会退出在线视频会议室,然后销毁本地流和远端流。
为什么不设计成进入到meeting_video.vue
页面就自动连接视频会议室,推送本地流和订阅远端流?在技术上是可以实现的,但是不太符合情理。比如说用户希望先整理一下仪容仪表然后再进入视频会议室,如果你写的程序一上来就执行本地推流了,这就不太合适吧。
视频墙中每个格子里面都有用于播放流数据的DIV控件,这些控件的id就是某个参会人的userId。一会儿我们接收到远端流或者本地流的时候,可以从流中取出userId,然后找到对应的DIV控件播放流数据。
<div class="video-list">
<!--当前用户排在视频墙第一位-->
<div class="video">
<div class="user">
<img class="photo" :src="mine.photo" />
<span class="name">{{ mine.name }}{{ shareStatus ? '(共享中)' : '' }}</span>
</div>
<div id="localStream"></div>
</div>
<!--其他参会人-->
<div class="video" v-for="one in memberList">
<div class="user">
<img class="photo" :src="one.photo" />
<span class="name">{{ one.name }}</span>
</div>
<div :id="one.id" class="remote-stream" @dblclick="bigVideoHandle(one.id)"></div>
</div>
</div>
二、连接视频会议室,订阅远程流,推送本地流
在meeting_video.vue
页面右下角有电话图标,这个图标设置了点击事件,我们写代码去实现phoneHandle()
回调函数。当我们第一次点击的时候是进入视频会议室并签到,再点击一次是退出视频会议室。当然了,你可以反复点击,那就是返回进入和退出视频会议室。
<div class="meeting-operate">
<button :class="meetingStatus ? 'phone-btn-off' : 'phone-btn-on'" @click="phoneHandle"/>
<button :class="videoStatus ? 'video-btn-on' : 'video-btn-off'" @click="videoHandle"/>
<button :class="micStatus ? 'mic-btn-on' : 'mic-btn-off'" @click="micHandle"/>
<button :class="shareStatus ? 'share-btn-on' : 'share-btn-off'" @click="shareHandle"/>
</div>
phoneHandle: function() {
let that = this;
//检查浏览器是否支持在线视频会议
TRTC.checkSystemRequirements().then(checkResult => {
if (!checkResult.result) {
that.$alert('当前浏览器不支持在线视频会议', '提示信息', {
confirmButtonText: '确定'
});
} else {
that.meetingStatus = !that.meetingStatus;
if (that.meetingStatus) {
//记录摄像头和话筒的状态
that.videoStatus = true;
that.micStatus = true;
//TRTC日志输出级别为Error
TRTC.Logger.setLogLevel(TRTC.Logger.LogLevel.ERROR);
//生成用户签名(进入视频会才需要用户签名,不需要提前生成)
that.$http('meeting/searchMyUserSig', 'GET', {}, false, function(resp) {
that.appId = resp.appId;
that.userSig = resp.userSig;
that.userId = resp.userId;
});
//创建TrtcClient对象
let client = TRTC.createClient({
mode: 'rtc',
sdkAppId: that.appId,
userId: that.userId + '',
userSig: that.userSig
});
that.client = client;
//监听新增远端流事件(用户进入会议室时候触发)
client.on('stream-added', event => {
let remoteStream = event.stream;
//订阅远端流
client.subscribe(remoteStream);
//从远端流获得远程用户userId(创建TrtcClient对象时候的参数)
let userId = remoteStream.getUserId();
//TODO 把新上线的用户添加到页面右侧的在线人员列表中
//把远端流保存到模型层JSON中,将来大屏显示的时候要找到某个远端流停止小窗口播放,切换到大窗口播放
that.stream[userId] = remoteStream;
});
//远端流订阅成功事件
client.on('stream-subscribed', event => {
let remoteStream = event.stream;
let userId = remoteStream.getUserId();
//找到视频墙中某个远端用户的格子,把其中用于显示视频的DIV,置顶覆盖用户信息
$('#' + userId).css({ 'z-index': 1 });
//在这个置顶的DIV中播放远端音视频讯号
remoteStream.play(userId + '');
});
//订阅远端删除流事件(远端用户退出会议室)
client.on('stream-removed', event => {
let remoteStream = event.stream;
//取消订阅该远端流
client.unsubscribe(remoteStream);
let userId = remoteStream.getUserId();
//TODO 在页面右侧的用户列表中删除该用户
//停止播放远端流视频,并且关闭远端流
remoteStream.stop();
remoteStream.close();
//删除模型层JSON中保存的远端流对象
delete that.stream[userId];
//把视频墙中该用户格子的视频DIV控件置底,显示用户基本信息
$('#' + userId).css({ 'z-index': '-1' });
$('#' + userId).html('');
});
client
.join({ roomId: that.roomId })
.then(() => {
//TODO 执行签到
//成功进入会议室,然后创建本地流
let localStream = TRTC.createStream({
userId: that.userId + '',
audio: true,
video: true
});
that.localStream = localStream;
localStream.setVideoProfile('480p'); //设置分辨率
//TODO 把自己添加到上线用户列表中
//初始化本地音视频流
localStream
.initialize()
.catch(error => {
console.error('初始化本地流失败 ' + error);
})
.then(() => {
console.log('初始化本地流成功');
//视频墙中第一个格子中的视频DIV置顶
$('#localStream').css({ 'z-index': 1 });
//播放本地音视频流
localStream.play('localStream');
//向远端用户推送本地流
client
.publish(localStream)
.catch(error => {
console.error('本地流发布失败 ' + error);
})
.then(() => {
console.log('本地流发布成功');
});
});
})
.catch(error => {
console.error('进入房间失败: ' + error);
});
} else {
//TODO 关闭视频会议
}
}
});
},
写完这些代码,咱们可以找两个都带有摄像头和麦克风的电脑,以不同的员工帐户进入到同一个在线会议,这时候,你看看视频墙上有没有本地流和远端流。
假设我们本地电脑被称作A,另一台电脑称作B,我们在B电脑上模拟其他参会人访问A电脑上的前端项目,必然要写A电脑的IP地址和端口号。但是现在有个问题,浏览器的WebRTC只支持HTTPS访问远端网站,我们在B电脑上用HTTP协议连接A电脑的网站是无法使用TRTC的。所以我们要想个办法,给B电脑上的浏览器添加参数,允许在HTTP协议下远程使用TRTC服务。
如果你用的是MacOS系统,需要用命令行启动Chrome浏览器,并且把其中的IP和端口都改成A电脑的。
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --unsafely-treat-insecure-origin-as-secure="http://ip:port" --user-data-dir=/Users/test/code
如果你用的是Windows系统,需要在Chrome浏览器图标上点击右键,在目标的结尾添加上下面这句话,然后把IP和端口改成A主机的。
--unsafely-treat-insecure-origin-as-secure="http://ip:port" --user-data-dir="C:/temp"
还有一个非常重要的注意事项,那就是前端项目main.js
文件中封装baseUrl
地址,如果你写的是localhost
,一定要改成Windows主机的IP地址。否则B主机的浏览器加载了前端页面之后,所有的Ajax请求都发送给B主机。B主机上面又没运行emos-api
项目,所以就会报错。记住,baseUrl
变量一定要写A主机的IP地址,切记!