|
@@ -0,0 +1,484 @@
|
|
|
+<template>
|
|
|
+ <view class="wraper">
|
|
|
+ <view class="infoConnecting">
|
|
|
+ 11多人会议
|
|
|
+ </view>
|
|
|
+ <live-pusher class="live-pusher" :url="pubUrl" @netstatus="netstatusChange" :muted="false" :enable-camera="true" id="livePusher"
|
|
|
+ ref="livePusher" @statechange="statechange" mode="HD" @error="error"></live-pusher>
|
|
|
+ </live-pusher>
|
|
|
+
|
|
|
+ <view
|
|
|
+ v-if="subUrls.length > 0"
|
|
|
+ v-for="item in subUrls">
|
|
|
+
|
|
|
+ <video
|
|
|
+ :id="item.streamId"
|
|
|
+ :src="item.subUrl"
|
|
|
+ object-fit="contain"
|
|
|
+ autoplay
|
|
|
+ >
|
|
|
+ <view class="userName">{{item.memName}}</view>
|
|
|
+ </video>
|
|
|
+
|
|
|
+ </view>
|
|
|
+ <!-- </scroll-view> -->
|
|
|
+
|
|
|
+
|
|
|
+ <!-- <view class="controlContent">
|
|
|
+ <view class="emediaContrContent">
|
|
|
+ <view class="controlItem" @tap="toggleCamera" style="{color: devicePositionColor}">
|
|
|
+ <image
|
|
|
+ class="icon-record"
|
|
|
+ :src="'../../../static/images/'+devicePositionIcon+'2x.png'" style="{width:'22px'; height: '24px'}"/>
|
|
|
+ 切换摄像头
|
|
|
+ </view>
|
|
|
+ <view class="controlItem" @tap="toggleMuted" style="{color: micphoneColor}">
|
|
|
+ <image
|
|
|
+ class="icon-record"
|
|
|
+ :src="'../../../static/images/'+micphoneIcon+'2x.png'" style="{width:'22px'; height: '24px'}"/>
|
|
|
+ 麦克风</view>
|
|
|
+ <view class="controlItem" @tap="togglePlay" style="{color: videoColor}">
|
|
|
+ <image
|
|
|
+ class="icon-record"
|
|
|
+ :src="'../../../static/images/'+videoIcon+'2x.png'" style="{width:'22px'; height: '24px'}"/>
|
|
|
+ 视频</view>
|
|
|
+ <view class="controlItem" @tap="toggleBeauty" style="{color: beautyColor}">
|
|
|
+ <image
|
|
|
+ class="icon-record"
|
|
|
+ :src="'../../../static/images/'+beautyIcon+'.png'" style="{width:'16px'; height: '24px'}"/>
|
|
|
+ 美颜</view>
|
|
|
+ <view class="controlItem" @tap="inviteMember">
|
|
|
+ <image
|
|
|
+ class="icon-record"
|
|
|
+ src='../../../static/images/invite_white2x.png' style="{width:'22px'; height: '24px'"/>
|
|
|
+ 邀请</view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view class="hangup" @tap="hangup">
|
|
|
+ <image
|
|
|
+ class="icon-record"
|
|
|
+ src='../../../static/images/hangup2x.png'/>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ -->
|
|
|
+ </view>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+ export default {
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ pubUrl: "",
|
|
|
+ subUrls: [],
|
|
|
+ showInvite: true,
|
|
|
+ devicePosition: "front",
|
|
|
+ muted: false,
|
|
|
+ playVideoMuted: false,
|
|
|
+
|
|
|
+ devicePositionIcon: 'switchCamera_white',
|
|
|
+ devicePositionColor: '#fff',
|
|
|
+ micphoneIcon: 'micphone_white',
|
|
|
+ beautyIcon: 'beauty',
|
|
|
+ micphoneColor: '#fff',
|
|
|
+ videoIcon: 'video_white',
|
|
|
+ videoColor: '#fff',
|
|
|
+ beauty: 9,
|
|
|
+ beautyColor: '#fff',
|
|
|
+ myName: '',
|
|
|
+ confrId: '',
|
|
|
+ enableCamera: true,
|
|
|
+ time: '',
|
|
|
+ context: {}
|
|
|
+ }
|
|
|
+ },
|
|
|
+ props: {
|
|
|
+ username: {
|
|
|
+ type: Object,
|
|
|
+ default: () => ({}),
|
|
|
+ },
|
|
|
+ action: {
|
|
|
+ type: Object,
|
|
|
+ default: {},
|
|
|
+ },
|
|
|
+ groupId:{
|
|
|
+ type: String,
|
|
|
+ default: '',
|
|
|
+ },
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ joinRoom(data){
|
|
|
+ let me = this;
|
|
|
+ console.log('joinRoom', data)
|
|
|
+ me.context = uni.createLivePusherContext("livePusher", me);
|
|
|
+ console.log('我的播放组件', me.context)
|
|
|
+ var context = this.context
|
|
|
+ if (context && context.ctx && context.ctx.attr && context.ctx.attr.url) {
|
|
|
+ context.stop()
|
|
|
+ }
|
|
|
+ let id = wx.WebIM.conn.getUniqueId();
|
|
|
+ let roomName = 'wxConfr' + id //随机的房间名,防止和别人的房间名冲突
|
|
|
+ let rec = wx.getStorageSync("rec") || false;
|
|
|
+ let recMerge = wx.getStorageSync("recMerge") || false;
|
|
|
+ let params = {
|
|
|
+ roomName,
|
|
|
+ password: '',
|
|
|
+ role: 7,
|
|
|
+ config: {
|
|
|
+ rec,
|
|
|
+ recMerge
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (data) {
|
|
|
+ params.roomName = data.roomName
|
|
|
+ params.password = data.password
|
|
|
+ }
|
|
|
+
|
|
|
+ wx.emedia.mgr.joinRoom(params).then((res) => {
|
|
|
+ console.log('res', res)
|
|
|
+ let confrId = res.confrId
|
|
|
+ me.confrId= confrId
|
|
|
+ me.$emit('createConfrSuccess', {confrId: confrId, groupId: me.username.groupId, roomName: params.roomName, password: params.password})
|
|
|
+
|
|
|
+ console.log('--------+--+----+---+--------')
|
|
|
+ let rtcId = wx.emedia.util.getRtcId()
|
|
|
+ console.log(11111111111111, confrId)
|
|
|
+ wx.emedia.mgr.pubStream(rtcId).then(function(res){
|
|
|
+ console.log('pubUrl-------------', res.data.rtmp)
|
|
|
+ console.log(2222222222222)
|
|
|
+ me.pubUrl= res.data.rtmp
|
|
|
+ setTimeout(() => {
|
|
|
+ console.log('55555555555', me)
|
|
|
+ console.log(me.context)
|
|
|
+ me.context.start()
|
|
|
+ }, 500)
|
|
|
+ }).catch(e => {
|
|
|
+ console.log(4444444, e) //404
|
|
|
+ return f(false); //即便返回了一个成功的promise,下面的finally也会执行,如果返回的是失败的promise,控制台最后一行会报错uncaught (in promise) 404
|
|
|
+ })
|
|
|
+ .finally( (e) => {
|
|
|
+ console.log(100,e) //100
|
|
|
+ })
|
|
|
+ console.log(33333333333333, me.pubUrl)
|
|
|
+ })
|
|
|
+
|
|
|
+
|
|
|
+ },
|
|
|
+ createConf(){
|
|
|
+ console.log('>>> createConf');
|
|
|
+
|
|
|
+ var me = this
|
|
|
+ let rec = wx.getStorageSync("rec") || false;
|
|
|
+ let recMerge = wx.getStorageSync("recMerge") || false;
|
|
|
+ //参数:会议类型 密码 是否录制 是否合并
|
|
|
+ wx.emedia.mgr.createConference(10, '', rec, recMerge).then(function(data){
|
|
|
+ console.log('成功', data)
|
|
|
+ let ticket = data.data.ticket
|
|
|
+ let ticketJosn = JSON.parse(ticket)
|
|
|
+ let confrId = ticketJosn.confrId
|
|
|
+
|
|
|
+ wx.emedia.mgr.joinConferenceWithTicket(confrId, ticket).then(function(res){
|
|
|
+ console.log('加入会议成功', res)
|
|
|
+ })
|
|
|
+ // wx.emedia.mgr.joinConference(confrId, '').then(function(res){
|
|
|
+ // console.log('加入会议成功', res)
|
|
|
+ // })
|
|
|
+
|
|
|
+ me.confrId = confrId
|
|
|
+ me.$emit('createConfrSuccess', {confrId: confrId, groupId: me.username.groupId})
|
|
|
+ })
|
|
|
+ },
|
|
|
+
|
|
|
+ joinConf(data){
|
|
|
+ console.log('加入会议 ————-------————')
|
|
|
+ console.log(data)
|
|
|
+ let me = this
|
|
|
+ wx.emedia.mgr.getConferenceTkt(data.confrId, data.password).then(function(res){
|
|
|
+ console.log('申请reqTkt成功', res.data)
|
|
|
+ let ticket = res.data.ticket || ''
|
|
|
+ let tktObj = JSON.parse(ticket)
|
|
|
+ wx.emedia.mgr.joinConferenceWithTicket(data.confrId, ticket).then(function(res){
|
|
|
+ console.log('加入会议成功', res)
|
|
|
+ })
|
|
|
+ me.confrId= tktObj.confrId
|
|
|
+ me.$emit('createConfrSuccess', {confrId: tktObj.confrId, groupId: me.username.groupId})
|
|
|
+ })
|
|
|
+ },
|
|
|
+
|
|
|
+ togglePlay(){
|
|
|
+ let me = this
|
|
|
+ console.log("%c togglePlay", "color:green")
|
|
|
+
|
|
|
+ // this.LivePusherContext.stop()
|
|
|
+ this.enableCamera= !me.enableCamera
|
|
|
+ this.pubUrl= me.pubUrl
|
|
|
+ this.videoIcon= this.videoIcon == 'video_white'?'video_gray': 'video_white'
|
|
|
+ this.videoColor= this.videoColor == '#fff'? '#aaa': '#fff'
|
|
|
+ this.LivePusherContext.start()
|
|
|
+ /* this.setData({
|
|
|
+
|
|
|
+ }, () => {
|
|
|
+
|
|
|
+ }) */
|
|
|
+ },
|
|
|
+
|
|
|
+ toggleCamera(){
|
|
|
+ console.log("%c toggleCamera", "color:green")
|
|
|
+ let me = this
|
|
|
+ // me.LivePusherContext.stop()
|
|
|
+ me.LivePusherContext.switchCamera({
|
|
|
+ success: function(){
|
|
|
+ me.devicePosition= me.devicePosition == 'fron' ? 'back' : 'front',
|
|
|
+ me.devicePositionIcon= me.devicePositionIcon =='switchCamera_white'?'switchCamera_gray': 'switchCamera_white',
|
|
|
+ me.devicePositionColor= me.devicePositionColor == '#fff'? '#aaa':'#fff'
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ toggleMuted(){
|
|
|
+ console.log("%c toggleMuted", "color:green")
|
|
|
+ this.muted= !this.muted
|
|
|
+ this.micphoneIcon= this.micphoneIcon == 'micphone_white'? 'micphone_gray': 'micphone_white'
|
|
|
+ this.micphoneColor= this.micphoneColor == '#fff'? '#aaa': '#fff'
|
|
|
+ },
|
|
|
+
|
|
|
+ toggleBeauty(){
|
|
|
+ this.beauty= this.beauty == 0 ? 9 : 0
|
|
|
+ this.beautyColor= this.beautyColor == '#fff'? '#aaa': '#fff'
|
|
|
+ this.beautyIcon= this.beautyIcon == 'beauty' ? 'beauty_gray': 'beauty'
|
|
|
+ },
|
|
|
+
|
|
|
+ hangup(){
|
|
|
+ console.log('挂断', this.confrId)
|
|
|
+ wx.emedia.mgr.exitConference(this.confrId)
|
|
|
+ this.$emit('hangup')
|
|
|
+ this.stopTimer()
|
|
|
+ },
|
|
|
+ inviteMember(){
|
|
|
+ this.$emit('inviteMember', this.groupId)
|
|
|
+ },
|
|
|
+ // statechange(e){
|
|
|
+ // console.log('>>>>>>>>>live-pusher code:', e.detail)
|
|
|
+ // if (e.detail.code === 5001) {
|
|
|
+ // // 部分安卓手机在接电话时会停止推拉流报错,状态码5001,此时退出会议。 https://developers.weixin.qq.com/community/develop/doc/0006ac6d7a4968fa675a49fef53c00
|
|
|
+ // this.hangup()
|
|
|
+ // console.error('由于有电话接入,已退出会议')
|
|
|
+ // }
|
|
|
+ // },
|
|
|
+ netstatusChange(e){
|
|
|
+ console.log('>>>>>>>>>>net status:', e.detail)
|
|
|
+ },
|
|
|
+
|
|
|
+ getTimer(){
|
|
|
+ let count = 0;
|
|
|
+ let time = '00:00:00'
|
|
|
+ this.timer = setInterval(() => {
|
|
|
+ count++;
|
|
|
+ let s = showNum(count % 60);
|
|
|
+ let m = showNum(parseInt((count / 60)) % 60)
|
|
|
+ let h = showNum(parseInt(count / 60 / 60))
|
|
|
+ time = `${h}:${m}:${s}`
|
|
|
+ this.time = time
|
|
|
+ }, 1000)
|
|
|
+
|
|
|
+ function showNum(num) {
|
|
|
+ if (num < 10) {
|
|
|
+ return '0' + num
|
|
|
+ }
|
|
|
+ return num
|
|
|
+ }
|
|
|
+
|
|
|
+ },
|
|
|
+ stopTimer(){
|
|
|
+ clearInterval(this.timer)
|
|
|
+ },
|
|
|
+ error(err){
|
|
|
+ console.log('EEEEEEEEEEEEE', err)
|
|
|
+ },
|
|
|
+ statechange(state){
|
|
|
+ console.log("SSSSSSSSSSS", state)
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ mounted() {
|
|
|
+ console.log('进入')
|
|
|
+ wx.setKeepScreenOn({
|
|
|
+ keepScreenOn: true
|
|
|
+ })
|
|
|
+ console.log('进入111')
|
|
|
+ this.myName= wx.WebIM.conn.context.userId
|
|
|
+ console.log('进入222')
|
|
|
+ this.getTimer()
|
|
|
+ var me = this
|
|
|
+ let subUrls = []
|
|
|
+ let obj = {};
|
|
|
+ console.log('进入333')
|
|
|
+ this.LivePusherContext = uni.createLivePusherContext('livePusher',this)
|
|
|
+ console.log('this.LivePusherContext ..', this.LivePusherContext)
|
|
|
+ if(this.action&&this.action.action == 'join'){
|
|
|
+ console.log('join')
|
|
|
+ // 音视频sdk提供两种创建、加入会议的api 使用任意一种都可以:(1) 一种是通过会议id ticket 或者 会议id 密码加入会议 如使用下面 joinConf
|
|
|
+ // (2)另一种是通过房间名 密码加入 如使用下面joinRoom
|
|
|
+
|
|
|
+ //this.joinConf(this.action) // (1)
|
|
|
+ //this.joinRoom(this.action) // (2)
|
|
|
+ if (this.action.roomName) {
|
|
|
+ console.log('使用joinroom')
|
|
|
+ this.joinRoom(this.action)
|
|
|
+ }else{
|
|
|
+ console.log('使用joinConf')
|
|
|
+ this.joinConf(this.action)
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ // 创建会议同样是两种api (1)一种是使用createConf 单纯创建一个会议,需要再申请ticket 或者用密码加入会议 如使用下面的createConf
|
|
|
+ // (2)也可以使用joinRoom,通过房间名、密码创建房间并直接加入 不需再进行加入会议的操作
|
|
|
+ this.joinRoom() // (1)
|
|
|
+ //this.createConf() // (2)
|
|
|
+ }
|
|
|
+ wx.emedia.mgr.onMediaChanaged = function(e){
|
|
|
+ console.log('onMediaChanaged', e)
|
|
|
+ }
|
|
|
+ wx.emedia.mgr.onConferenceExit = function(e){
|
|
|
+ console.log('onConferenceExit', e)
|
|
|
+ }
|
|
|
+ wx.emedia.mgr.onMemberExited = function(reason){
|
|
|
+ console.log('onMemberExited', reason)
|
|
|
+ };
|
|
|
+
|
|
|
+ wx.emedia.mgr.onStreamControl = function(mem){
|
|
|
+ console.log('onStreamControl', mem)
|
|
|
+ }
|
|
|
+
|
|
|
+ wx.emedia.mgr.onStreamControl.onSoundChanage = function(a, b, c, d){
|
|
|
+ console.log('onSoundChanage')
|
|
|
+ }
|
|
|
+
|
|
|
+ wx.emedia.mgr.onReconnect = function (res, ent){
|
|
|
+ // 发生断网重连,相当于重新加入会议
|
|
|
+
|
|
|
+ // 清空live-player 否则在原来的后面追加,导致原来的黑屏显示
|
|
|
+ subUrls = []
|
|
|
+
|
|
|
+ // 重新加入恢复到初始状态,防止和控制按钮状态不符
|
|
|
+
|
|
|
+ // 重连后摄像头方向不会改变
|
|
|
+ me.subUrls= []
|
|
|
+ me.showInvite= true
|
|
|
+ me.devicePosition= "front"
|
|
|
+ me.muted= false
|
|
|
+ me.playVideoMuted= false
|
|
|
+
|
|
|
+
|
|
|
+ me.micphoneIcon= 'micphone_white'
|
|
|
+ me.micphoneColor= '#fff'
|
|
|
+ me.videoIcon= 'video_white'
|
|
|
+ me.beautyIcon= 'beauty'
|
|
|
+ me.videoColor= '#fff'
|
|
|
+ me.beauty= 9
|
|
|
+ me.beautyColor= '#fff'
|
|
|
+ me.enableCamera= true
|
|
|
+ }
|
|
|
+
|
|
|
+ wx.emedia.mgr.onMemberJoined = function(mem){
|
|
|
+ console.log("++++++++++ member", mem)
|
|
|
+ var jid = wx.WebIM.conn.context.jid
|
|
|
+ let identityName = jid.appKey + '_' + jid.name+ '@' + jid.domain
|
|
|
+ // let identityName = wx.WebIM.conn.context.jid.split("/")[0]
|
|
|
+ // 如果是自己进入会议了,开始发布流
|
|
|
+ if(mem.name == identityName){
|
|
|
+ let rtcId = wx.emedia.util.getRtcId()
|
|
|
+ wx.emedia.mgr.pubStream(rtcId).then(function(res){
|
|
|
+ me.pubUrl= res.data.rtmp
|
|
|
+ })
|
|
|
+
|
|
|
+ var enableCamera = me.enableCamera;
|
|
|
+ console.warn("begin enable camera", me.enableCamera);
|
|
|
+
|
|
|
+ //默认enableCamera为false 关闭摄像头时声音不会有延迟,否则有延迟
|
|
|
+ //所以最好别用autopush
|
|
|
+ me.enableCamera= false
|
|
|
+ me.pubUrl= me.url + 'record_type=audio' || 'https://domain/push_stream'
|
|
|
+ // enableCamera && me.enableCamera= enableCamera
|
|
|
+ /* me.setData({
|
|
|
+ enableCamera: false,
|
|
|
+ pubUrl: me.url + 'record_type=audio' || 'https://domain/push_stream',
|
|
|
+ }, () => {
|
|
|
+ // var enableCameraDefault = true
|
|
|
+ //if(!enableCameraDefault){ //治疗不推流的毛病
|
|
|
+ // console.log('关闭摄像头推流')
|
|
|
+ // setTimeout(() => {
|
|
|
+ // me.LivePusherContext.start({
|
|
|
+ // success: function () {
|
|
|
+ // console.log('关闭摄像头推流', enableCamera)
|
|
|
+ // }
|
|
|
+ // })
|
|
|
+ // }, 1500)
|
|
|
+ // }else{
|
|
|
+ // me.LivePusherContext.start({
|
|
|
+ // success: function () {
|
|
|
+ // console.log('开始推流了', enableCamera)
|
|
|
+ // enableCamera && me.setData({enableCamera: enableCamera})
|
|
|
+ // }
|
|
|
+ // })
|
|
|
+ // }
|
|
|
+ }) */
|
|
|
+ }
|
|
|
+ }
|
|
|
+ wx.emedia.mgr.onStreamAdded = function(stream){
|
|
|
+ console.log('%c onAddStream', 'color: green', stream)
|
|
|
+ let streamId = stream.id
|
|
|
+ // setTimeout(() => {
|
|
|
+ if(subUrls.length > 8){
|
|
|
+ return
|
|
|
+ }
|
|
|
+ wx.emedia.mgr.subStream(streamId).then(function(data){
|
|
|
+ console.log('%c 订阅流成功', 'color:green', data)
|
|
|
+ // let playContext = wx.createLivePlayerContext(streamId, me)
|
|
|
+ let subUrl = {
|
|
|
+ streamId: streamId,
|
|
|
+ subUrl: data.data.rtmp,
|
|
|
+ memName: stream.memName.split("_")[1].split("@")[0],
|
|
|
+ // playContext: playContext
|
|
|
+ }
|
|
|
+ subUrls.push(subUrl)
|
|
|
+ console.log('%c subUrls 11 ....', "background:yellow")
|
|
|
+ console.log(subUrls)
|
|
|
+
|
|
|
+ me.subUrls= subUrls
|
|
|
+ me.showInvite= false
|
|
|
+ })
|
|
|
+ // }, 2000)
|
|
|
+
|
|
|
+ }
|
|
|
+ wx.emedia.mgr.onStreamRemoved = function(stream){
|
|
|
+ console.log('%c onRemoveStream', 'color: red', stream)
|
|
|
+ subUrls = subUrls.filter((item) => {
|
|
|
+ if(item.streamId != stream.id){
|
|
|
+ return item
|
|
|
+ }else{
|
|
|
+ console.log('%c ------', 'backgroukd:yellow')
|
|
|
+ console.log(item)
|
|
|
+ // item.playContext.stop({
|
|
|
+ // success: function(){
|
|
|
+ // console.log('关闭成功')
|
|
|
+ // },
|
|
|
+ // complete: function(){
|
|
|
+ // console.log('关闭成功')
|
|
|
+ // }
|
|
|
+ // })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ obj[stream.id] = false
|
|
|
+ me.subUrls= subUrls
|
|
|
+ console.log('subUrls', subUrls)
|
|
|
+ },
|
|
|
+ wx.emedia.mgr.onConfrAttrsUpdated = function(e){
|
|
|
+ console.log('onConfrAttrsUpdated: ', e)
|
|
|
+ }
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ }
|
|
|
+</script>
|
|
|
+
|
|
|
+
|