现在,我们已经找到创建所有RTCPeerConnection之外步骤的通用方法了,接下来就需要适当的组件提供和处理PeerConnection对象和过程中所需信息(远程描述、候选人、请求、回复等等)了。
详见使用 mixins 时所有的合并策略
视频通话和相关控制
考虑到视频相关的情况,我们创建了一个通用的Video.vue组件让视频变得更简单。
<template>
<div class="video">
<div class="video__spinner">
<md-progress-spinner
v-if="!videoStream"
class="md-accent"
md-mode="indeterminate">
</md-progress-spinner>
</div>
<AudioVideoControls
v-if="displayControls"
:pauseVideo="pauseVideo"
:pauseAudio="pauseAudio">
</AudioVideoControls>
<video :id="videoId" autoplay="true"> </video>
</div>
</template>
<script>
export default {
name: "Video",
components: { AudioVideoControls },
props: {
videoId: String,
displayControls: Boolean,
videoStream: MediaStream,
pauseVideo: Function,
pauseAudio: Function,
}
}
</script>
(视频组件)
不管是哪种情况,组件都会获取合适的媒体流以及输入值的剩余部分。
pauseVideo和pauseAudio是通用的mixin媒体方法。
此外,我们还添加了视频音频控制(AudioVideControls.vue),这样,每一端都可以分别暂停/恢复或关闭/开启自己的视频和音频,具体操作如下。
// Pause video
this.ls.getVideoTracks().forEach(t => t.enabled = !t.enabled)
// Pause audio
this.ls.getAudioTracks().forEach(t => t.enabled = !t.enabled)
这并不意味着你每次都要重启webRTC连接,你只需启用/禁用音频/视频本地流轨道就可以了。
音频
在我们之前发布的版本中,音频问题较突出。所以这次我们在请求用户媒体时的普通配置中设置约束,从而解决了反馈的问题。
constraints: {
audio: {
echoCancellation: true,
noiseSuppression: true,
autoGainControl: false
}
}
MediaTrack API中可查看所有可用的约束条件。
但这还不够。为了消除回声和噪音,我们还需要将本地视频元素的音量静音并设置为0,如下所示:
// Local video
<video id="localVideo" autoplay="true" muted> </video>
// Fix volume to 0
this.myVideo.volume = 0
注:这个操作只静音了本地播放,并不意味着你把正在运行的音频流也静音了。
WebRTC 适配器
为了处理可能会出现的浏览器问题,我们引入了WebRTC适配器,把代码和不同的WebRTC浏览器实现连接起来。
import adapter from ‘webrtc-adapter’
console.log(`Browser ${adapter.browserDetails.browser} — version ${adapter.browserDetails.version}`)
用户信息
如上所述,用户无法一边私聊一边参加会议。所以我们在用户进入房间时,就在Redis中存储的对象中添加了一个会议标志(joinRoom web socket服务器监听器),来监测用户状态。
try {
// add user to the suitable ROOM
await ChatRedis.addUser(room, userName, { username, status,
privateChat: false,
conference: false
})
const users = await ChatRedis.getUsers(room)
// Notify all the users in the same room
namespace.in(room).emit(‘newUser’, { users, username })
} catch (error) {
console.log(error)
}
注:我们更改了redis hash模式中的密钥(从socketId 变成了userName),这使得从web socket连接中获取用户信息更方便了。
会议
某一用户发起会议,会议开始,该用户成为该房间管理员。当开启app时,管理员会自动加入由自己用户名定义的会议室。
注:每个用户名在系统中都是唯一不重复的,所以每个web socket会议室都是独一无二的。
为做到这一点,我们开发了一个新的 joinConference 服务器监听器。