html
<view class="template-1v1" v-show="isVideo">
<view class="view-container player-container" v-for="item in playerList"
:key="item.streamID">
<live-player v-if="item.src && (item.hasVideo || item.hasAudio)" class="player" :id="item.streamID"
:data-userid="item.userID" :data-streamid="item.streamID" :data-streamtype="item.streamType" :src="item.src"
mode="RTC" :autoplay="item.autoplay" :mute-audio="item.muteAudio" :mute-video="item.muteVideo"
:orientation="item.orientation" :object-fit="item.objectFit" :background-mute="item.enableBackgroundMute"
:min-cache="item.minCache" :max-cache="item.maxCache" :sound-mode="item.soundMode"
:enable-recv-message="item.enableRecvMessage" :auto-pause-if-navigate="item.autoPauseIfNavigate"
:auto-pause-if-open-native="item.autoPauseIfOpenNative" :debug="debug" @statechange="_playerStateChange"
@fullscreenchange="_playerFullscreenChange" @netstatus="_playerNetStatus"
@audiovolumenotify="_playerAudioVolumeNotify" />
</view>
<view class="loading" v-if="playerList.length === 0">
<view class="loading-text">等待接听中,若长时间无响应请点击刷新!</view>
</view>
<view class="view-container pusher-container">
<live-pusher class="pusher" :url="pusher.url" :mode="pusher.mode" :autopush="pusher.autopush"
:enable-camera="pusher.enableCamera" :enable-mic="pusher.enableMic" :muted="!pusher.enableMic"
:enable-agc="pusher.enableAgc" :enable-ans="pusher.enableAns" :enable-ear-monitor="pusher.enableEarMonitor"
:auto-focus="pusher.enableAutoFocus" :zoom="pusher.enableZoom" :min-bitrate="pusher.minBitrate"
:max-bitrate="pusher.maxBitrate" :video-width="pusher.videoWidth" :video-height="pusher.videoHeight"
:beauty="pusher.beautyLevel" :whiteness="pusher.whitenessLevel" :orientation="pusher.videoOrientation"
:aspect="pusher.videoAspect" :device-position="pusher.frontCamera" :remote-mirror="pusher.enableRemoteMirror"
:local-mirror="pusher.localMirror" :background-mute="pusher.enableBackgroundMute"
:audio-quality="pusher.audioQuality" :audio-volume-type="pusher.audioVolumeType"
:audio-reverb-type="pusher.audioReverbType" :waiting-image="pusher.waitingImage" :debug="debug"
@statechange="_pusherStateChangeHandler" @netstatus="_pusherNetStatusHandler" @error="_pusherErrorHandler"
@bgmstart="_pusherBGMStartHandler" @bgmprogress="_pusherBGMProgressHandler"
@bgmcomplete="_pusherBGMCompleteHandler" @audiovolumenotify="_pusherAudioVolumeNotify" />
</view>
</view>
javascript
import TRTC from '@/lib/trtc-wx'
videoStart () {
this.TRTC = new TRTC(this)
this.pusher = this.TRTC.createPusher()
this.bindTRTCRoomEvent()
this.enterRoom()
},
enterRoom() {
let that = this;
this.pusher = this.TRTC.enterRoom({
sdkAppID:'',
userID: '',
userSig:'',
roomID:1,
enableCamera: true,
enableMic: true,
beautyLevel: 9,
})
this.TRTC.getPusherInstance().start() // 开始推流(autoPush的模式下不需要)
},
exitRoom() {
const {
pusher,
playerList,
} = this.TRTC.exitRoom()
this.pusher = pusher
this.playerList = playerList
},
// 设置 pusher 属性
setPusherAttributesHandler(options) {
this.pusher = this.TRTC.setPusherAttributes(options)
},
// 设置某个 player 属性
setPlayerAttributesHandler(player, options) {
this.playerList = this.TRTC.setPlayerAttributes(player.streamID, options)
console.log('playerList',this.playerList);
},
// 事件监听
bindTRTCRoomEvent() {
let that = this;
const TRTC_EVENT = this.TRTC.EVENT // 初始化事件订阅
this.TRTC.on(TRTC_EVENT.LOCAL_JOIN, (event) => {
console.log('* room LOCAL_JOIN', event) // // 进房成功,触发该事件后可以对本地视频和音频进行设置
this.setPusherAttributesHandler({
enableCamera: true,
})
this.setPusherAttributesHandler({
enableMic: true,
})
})
//成功离开房间
this.TRTC.on(TRTC_EVENT.LOCAL_LEAVE, (event) => {
console.log('* room LOCAL_LEAVE', event)
})
//本地推流出现错误、渲染错误事件等
this.TRTC.on(TRTC_EVENT.ERROR, (event) => {
console.log('* room ERROR', event)
})
// 远端用户退出
this.TRTC.on(TRTC_EVENT.REMOTE_USER_LEAVE, (event) => {
console.log('* room REMOTE_USER_LEAVE', event)
const {
playerList,
} = event.data
this.playerList = playerList
})
// 远端用户推送视频
this.TRTC.on(TRTC_EVENT.REMOTE_VIDEO_ADD, (event) => {
console.log('* room REMOTE_VIDEO_ADD', event)
const {
player,
} = event.data
// 开始播放远端的视频流,默认是不播放的
this.setPlayerAttributesHandler(player, {
muteVideo: false,
})
})
// 远端用户取消推送视频
this.TRTC.on(TRTC_EVENT.REMOTE_VIDEO_REMOVE, (event) => {
console.log('* room REMOTE_VIDEO_REMOVE', event)
const {
player,
} = event.data
this.setPlayerAttributesHandler(player, {
muteVideo: true,
})
})
// 远端用户推送音频
this.TRTC.on(TRTC_EVENT.REMOTE_AUDIO_ADD, (event) => {
console.log('* room REMOTE_AUDIO_ADD', event)
const {
player,
} = event.data
this.setPlayerAttributesHandler(player, {
muteAudio: false,
})
})
// 远端用户取消推送音频
this.TRTC.on(TRTC_EVENT.REMOTE_AUDIO_REMOVE, (event) => {
console.log('* room REMOTE_AUDIO_REMOVE', event)
const {
player,
} = event.data
this.setPlayerAttributesHandler(player, {
muteAudio: true,
})
})
// 本地网络相关状态变更。
this.TRTC.on(TRTC_EVENT.LOCAL_NET_STATE_UPDATE, (event) => {
//netQualityLevel网络质量:0:未定义 1:最好 2:好 3:一般 4:差 5:很差 6:不可用
const netStatus = event.data.pusher.netStatus
if(netStatus.netQualityLevel > 3){
uni.showToast({
title: '您的网络状态较差',
icon:'none',
duration: 1500
});
}
console.log('本地网络相关状态变更', netStatus.netQualityLevel)
})
// 远端用户网络相关状态变更。
this.TRTC.on(TRTC_EVENT.REMOTE_NET_STATE_UPDATE, (event) => {
// 这里会返回更新后的 playerList,上面有个属性是 netStatus 对应网络状态的对象
// 其中 netQualityLevel 对应网络状态的好坏,1 代表最好,数字越大代表网络越差
const { playerList } = event.data
let qualityLevel = playerList.length > 0 ? playerList[0].netStatus.netQualityLevel : 1;
if(qualityLevel > 3){
uni.showToast({
title: '对方的网络状态较差',
icon:'none',
duration: 1500
});
}
console.log('远端用户网络相关状态变更', qualityLevel)
})
},
// 推流状态变化事件
_pusherStateChangeHandler(event) {
let that = this;
this.TRTC.pusherEventHandler(event)
const code = event.detail.code;
console.log('pusher状态变化事件',code);
switch (code){
case 1022://进入房间失败
uni.showModal({
title: '进入复诊房间失败',
content: '请点击刷新按钮',
showCancel:false,
confirmText:'刷新',
success: function (res) {
if (res.confirm) {
that.updateVideo()
}
}
});
break;
case 3004://推流:RTMP服务器主动断开,请检查推流地址的合法性或防盗链有效期
uni.showToast({
title: '远程服务器主动断开连接',
icon:'none',
duration: 2000
});
break;
case -1301://打开摄像头失败
that.setCameraRecord();
break;
case -1302://打开麦克风失败
that.setCameraRecord();
break;
case -1307://网络断连,且经多次重连抢救无效
uni.showModal({
title: '网络连接异常',
confirmText:'继续复诊',
success: function (res) {
if (res.confirm) {
//先停止再重新播放渲染
that.updateVideo()
//判断是否断网
that.getNetworkType()
} else if (res.cancel) {
//判断是否断网
that.getNetworkType()
}
}
});
break;
}
},
_pusherNetStatusHandler(event) {
this.TRTC.pusherNetStatusHandler(event)
},
_pusherErrorHandler(event) {
this.TRTC.pusherErrorHandler(event)
},
_pusherBGMStartHandler(event) {
this.TRTC.pusherBGMStartHandler(event)
},
_pusherBGMProgressHandler(event) {
this.TRTC.pusherBGMProgressHandler(event)
},
_pusherBGMCompleteHandler(event) {
this.TRTC.pusherBGMCompleteHandler(event)
},
_pusherAudioVolumeNotify(event) {
this.TRTC.pusherAudioVolumeNotify(event)
},
//播放状态变化事件
_playerStateChange(event) {
this.TRTC.playerEventHandler(event);
const code = event.detail.code;
console.log('player状态变化事件',code);
switch (code){
case -2301://网络断连,且经多次重连抢救无效
//判断是否断网
this.getNetworkType()
break;
case 3002://推流:RTMP服务器主动断开,请检查推流地址的合法性或防盗链有效期
uni.showToast({
title: '远程服务器连接失败',
icon:'none',
duration: 2000
});
break;
}
},
_playerFullscreenChange(event) {
this.TRTC.playerFullscreenChange(event)
},
_playerNetStatus(event) {
this.TRTC.playerNetStatus(event)
},
_playerAudioVolumeNotify(event) {
this.TRTC.playerAudioVolumeNotify(event)
},
//获取网络情况
getNetworkType(){
wx.getNetworkType({
success (res) {
const networkType = res.networkType
if (networkType != "none") { //是医生网络异常或医生异常退出
uni.showToast({
title: '医生网络不佳,正在努力恢复',
icon:'none',
duration: 2000
});
} else { //客户自个儿的网络异常
uni.showToast({
title: '请检查你的网络连接是否正常',
icon:'none',
duration: 2000
});
}
}
})
},
//摄像头和麦克风授权
setCameraRecord(){
const that=this;
// 可以通过 wx.getSetting 先查询一下用户是否授权了 "scope.record" 这个 scope
wx.getSetting({
success(res) {
//打印是否已开启摄像头和麦克风
if (!res.authSetting['scope.camera']) {
wx.authorize({
scope: 'scope.camera',
fail(){
wx.showModal({
title: '系统提示',
content: '未授权摄像头,视频功能将无法使用',
showCancel: false,
confirmText: '前往授权',
confirmColor: '#FFAF41',
success: function (res) {
wx.openSetting({
})
}
})
}
})
}
if (!res.authSetting['scope.record']) {
wx.authorize({
scope: 'scope.record',
fail(){
wx.showModal({
title: '系统提示',
content: '未授权麦克风,视频功能将无法使用',
showCancel: false,
confirmText: '前往授权',
confirmColor: '#FFAF41',
success: function (res) {
wx.openSetting({
})
}
})
}
})
}
}
})
},
接入trtc-wx常见问题:
https://cloud.tencent.com/document/product/647/45532
API: