1. 程式人生 > 其它 >uniapp使用環信外掛實現視訊通話

uniapp使用環信外掛實現視訊通話

技術標籤:uni-app學習javascriptuni-app

前言:因為我所做的專案需求是,接到後端推送視訊訊息,APP端點選訊息跳轉到通話頁面進行1對1通話,而後端已經進行賬號好友等的處理,環信提供的demo很多功能前端暫時用不到了,以下就把我用到的羅列出來。

PS:本人並不是前端大神,第一次分享文章,有寫不對的歡迎提出來哦,請大佬們多多包涵!

效果:
在這裡插入圖片描述 在這裡插入圖片描述

![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210201172544716.png

一、引入外掛

  1. 首先,在外掛市場https://ext.dcloud.net.cn/plugin?id=3507,按照官方文件整合參考說明,把所用到外掛匯入到你的專案中

    在這裡插入圖片描述

  2. 下載環信demo,以下是需要直接複製貼上到你的專案中的sdk和元件以及你所用到的圖片,圖片暫不展示
    在這裡插入圖片描述
    在這裡插入圖片描述

  3. 音視訊SDK在emediaSDK/emedia_for_miniProgram.js裡,引入SDK方法:在App.vue頁面引入

let emedia = uni.emedia = require("./emediaSDK/emedia_for_miniProgram");
    emedia.config({useUniappPlugin: true}) // 設定使用uniapp外掛

二、改造demo實現我的專案需求

  1. 專案只是單純實現接聽視訊通話,所以思路大概如下:
    (1)專案需求直接用專案的賬號進行登入,後端已處理環信的賬號登入、好友繫結、建立群聊等,所以我這邊登入專案的賬號的時候已經跟後端的賬號好友綁定了。現在展示一下環信登入的程式碼:
    (appKey是每個專案使用環信的唯一標識,就相當於微信小程式的appid)
// //接收環信多人視訊
var options = {
	apiUrl: 'https://a1.easemob.com',
	user: XX,
	pwd: XX,
	appKey: XX
};
//環信登入
WebIM.conn.open(options);

(2)在App.vue入口頁,通過onTextMessage()函式監聽到後端傳來的視訊引數,接收到我的賬號、發出視訊邀請的賬號、會議Id,接收到的引數直接傳入groupChatRoom頁面:

(這裡只展示關鍵程式碼,後面附上groupChatRoom頁面完整程式碼)

WebIM.conn.listen({
	onTextMessage(message) {
		console.log("onTextMessage", message);
		if (message) {
		   if (onMessageError(message)) {
		      msgStorage.saveReceiveMsg(message, msgType.TEXT);
		   }
		var my = uni.getStorageSync("myUsername");
		var nameList = {
			myName: my,
			your: message.from,
			groupId: message.ext.conferenceId
		};
		uni.navigateTo({
			url: "/pages/groupChatRoom/groupChatRoom?username=" + JSON.stringify(nameList)
		});
		calcUnReadSpot(message);
		ack(message);
	}
},
		

(3)groupChatRoom頁面裡展示的是接收群聊訊息,因為後端已做好好友繫結、建立群聊,所以這裡我只需列出後端傳來的最新訊息即可,以下是demo提供的處理資料的程式碼,有一些資料我的專案需求用不到,不過懶得整理了,處理最後得到的array資料,存入瀏覽器本地,之後需要呼叫到:

getChatList() {
    var array = [];
    var member = uni.getStorageSync("member");
    var myName = uni.getStorageSync("myUsername");
    var listGroups = uni.getStorageSync('listGroup') || [];

    for (let i = 0; i < member.length; i++) {
        let newChatMsgs = uni.getStorageSync(member[i].name + myName) || [];
        let historyChatMsgs = uni.getStorageSync("rendered_" + member[i].name + myName) || [];
        let curChatMsgs = historyChatMsgs.concat(newChatMsgs);

        if (curChatMsgs.length) {
            let lastChatMsg = curChatMsgs[curChatMsgs.length - 1];
            lastChatMsg.unReadCount = newChatMsgs.length;

            if (lastChatMsg.unReadCount > 99) {
                lastChatMsg.unReadCount = "99+";
            }

            let dateArr = lastChatMsg.time.split(' ')[0].split('-');
            let timeArr = lastChatMsg.time.split(' ')[1].split(':');
            let month = dateArr[2] < 10 ? '0' + dateArr[2] : dateArr[2];
            lastChatMsg.dateTimeNum = `${dateArr[1]}${month}${timeArr[0]}${timeArr[1]}${timeArr[2]}`;
            lastChatMsg.time = `${dateArr[1]}${dateArr[2]}${timeArr[0]}${timeArr[1]}分`;
            array.push(lastChatMsg);
        }
    }

    for (let i = 0; i < listGroups.length; i++) {
        let newChatMsgs = uni.getStorageSync(listGroups[i].groupid + myName) || [];
        let historyChatMsgs = uni.getStorageSync("rendered_" + listGroups[i].groupid + myName) || [];
        let curChatMsgs = historyChatMsgs.concat(newChatMsgs);
        if (curChatMsgs.length) {
            let lastChatMsg = curChatMsgs[curChatMsgs.length - 1];
            lastChatMsg.unReadCount = newChatMsgs.length;
            if (lastChatMsg.unReadCount > 99) {
                lastChatMsg.unReadCount = "99+";
            }
            let dateArr = lastChatMsg.time.split(' ')[0].split('-') let timeArr = lastChatMsg.time.split(' ')[1].split(':') let month = dateArr[2] < 10 ? '0' + dateArr[2] : dateArr[2] lastChatMsg.time = `${dateArr[1]}${dateArr[2]}${timeArr[0]}${timeArr[1]}分`
            lastChatMsg.dateTimeNum = `${dateArr[1]}${month}${timeArr[0]}${timeArr[1]}${timeArr[2]}`lastChatMsg.groupName = listGroups[i].groupname array.push(lastChatMsg);
        }
    }

    array.sort((a, b) = >{
        return b.dateTimeNum - a.dateTimeNum;
    });
    console.log('array:', array)
    //2021/02/01新加
    uni.setStorageSync("newChatMsg", array);
    return array;

},

array得到的資料格式:

[{
	"info": {
		"from": "nzXXXXXXfk", //對方的賬號
		"to": "lXXXXXX5" //你的賬號
	},
	"username": "nzXXXXXXfk",
	"yourname": "nzXXXXXXfk",
	"msg": {
		"type": "txt",
		"url": "",
		"data": [{
			"data": "快來加入會議 - LBJ13H055XXXXXXXXXXXXXC65666",
			"type": "txt"
		}],
		"ext": {
			"conferenceId": "LBJ13H05522QATI4O4DEXH00C65666", //會議id,後端每發一個視訊流對應一個id
			"msg_extension": "{\"inviter\":\"nzXXXXXXfk\"}", //處理過的對方的賬號
			"password": ""//會議密碼
		}
	},
	"style": "",
	"time": "2月1日 15時41分",
	"mid": "txt835802715723401212",
	"chatType": "chat",
	"unReadCount": 10,
	"dateTimeNum": "201154124"
}]

上面的array將會傳到comps/chat/chat.vue–comps/chat/msglist/msglist.vue元件裡處理,這個元件放的就是群聊視窗,而msglist就是處理訊息列表的。
chatMsg獲取之前的array值,遍歷出msgList訊息列表值

let timer = setTimeout(function() {
    me.username = uni.username;
    let username = me.username;
    let myUsername = uni.getStorageSync("myUsername");
    let sessionKey = username.groupId ? username.groupId + myUsername: username.your + myUsername;
    // let chatMsg = uni.getStorageSync(sessionKey) || [];
    // 2021/02/01 新增  !!!!!
    let chatMsg = uni.getStorageSync("newChatMsg");  //更改了這裡!!!
    console.log('chatMsg:', chatMsg) me.renderMsg(null, null, chatMsg, sessionKey);
    uni.setStorageSync(sessionKey, null);
    disp.on('em.error.sendMsgErr',
    function(err) {
        curMsgMid = err.data.mid;
        isFail = true;
        console.log('傳送失敗了');
        return;
        let msgList = me.chatMsg;
        msgList.map(item = >{
            if (item.mid.substring(item.mid.length - 10) == curMsgMid.substring(curMsgMid.length - 10)) {
                item.msg.data[0].isFail = true;
                item.isFail = true;
                me.setData({
                    chatMsg: msgList
                });
            }
        });
        console.log('msgList:', msgList)

        if (me.curChatMsg[0].mid == curMsgMid) {
            me.curChatMsg[0].msg.data[0].isShow = false;
            me.curChatMsg[0].isShow = false;
        }

        uni.setStorageSync("rendered_" + sessionKey, msgList);
    });
    msgStorage.on("newChatMsg", this.dispMsg);
},
1000);

(4)comps/chat/chat.vue頁面裡點選訊息列表,引用父級頁面groupChatRoom的onClickInviteMsg方法,並跳轉到視訊通話頁面:emedia頁面

comps/chat/chat.vue頁面

clickMsg(msg) {
    this.$emit('onClickInviteMsg', msg) console.log('點選訊息上一級', msg)
},

groupChatRoom頁面

<chat 
	id="groupchat" 
	ref="chat" 
	:username="username" 
	:groupId="groupId" 
	chatType="chatRoom" 
	@onMakeVideoCall="makeVideoCall" 
	@onClickInviteMsg="onClickMsg">
</chat>
export default {
	methods: {
		onClickMsg(msg){
			msg.action = 'join'
			uni.navigateTo({
				url: "../emedia/index?srcData="+JSON.stringify(msg)
			});
		}
   }
}

(5)emedia頁面
外掛市場裡所展示的程式碼就寫在這個頁面裡邊,此時效果已經出來了。

< emlive - player id = "livePlayer"ref = "livePlayer"objectFit = "fit"@bindstatechange = "playerStateChange"@bindnetstatus = "playerNetChange": data - streamId = "item.id": muted = "false": enableCamera = "true": openSpeaker = "openSpeaker"@callbackData = "onPlayerData"style = "width:170px;height:170px; margin: 5px" > </emlive-player>

三、附上groupChatRoom頁面完整程式碼:

<template>
<chat 
	id="groupchat" 
	ref="chat" 
	:username="username" 
	:groupId="groupId" 
	chatType="chatRoom" 
	@onMakeVideoCall="makeVideoCall" 
	@onClickInviteMsg="onClickMsg">
</chat>
</template>

<script>
let disp = require("../../utils/broadcast");
import chat from "../../comps/chat/chat.vue";
var WebIM = require("../../utils/WebIM")["default"];
export default {
  data() {
    return {
      username: {
        your: ""
      },
			search_btn: true,
			search_chats: false,
			show_mask: false,
			yourname: "",
			unReadSpotNum: 0,
			unReadNoticeNum: 0,
			messageNum: 0,
			unReadTotalNotNum: 0,
			arr: [],
			show_clear: false,
			member: "",
			isIPX: false,
			gotop: false,
			input_code: ""
    };
  },

  components: {
    chat
  },

   props: {
    groupId:{
      type:String,
      default:''
    }
  },

  // options = 系統傳入的 url 引數
  onLoad(options) {
		let me = this; 
    let username = JSON.parse(options.username);
    this.setData({
      username: username
    });
		uni.username = username;
    uni.setNavigationBarTitle({
      title: username.your
    });
		this.getRoster();
  },
	onShow: function () {
	  this.setData({
	    arr: this.getChatList()
	  });
		if (getApp().globalData.isIPX) {
		  this.setData({
		    isIPX: true
		  });
		}
	},
  onUnload() {
    disp.fire("em.chatroom.leave");
  },
  methods: {
		getRoster() {
		  let me = this;
		  let rosters = {
		    success(roster) {
		      var member = [];
		
		      for (let i = 0; i < roster.length; i++) {
		        if (roster[i].subscription == "both") {
		          member.push(roster[i]);
		        }
		      }
		
		      uni.setStorage({
		        key: "member",
		        data: member
		      });
		      me.setData({
		        member: member
		      });
		      me.listGroups(); //if(!systemReady){
		
		      disp.fire("em.main.ready"); //systemReady = true;
		      //}
		      // me.getChatList()
		      me.setData({
		        arr: me.getChatList(),
		        unReadSpotNum: getApp().globalData.unReadMessageNum > 99 ? '99+' : getApp().globalData.unReadMessageNum
		      });
		    },
		
		    error(err) {
		      console.log(err);
		    }
		
		  };
		  WebIM.conn.getRoster(rosters);
		},
		listGroups() {
		  var me = this;
		  return WebIM.conn.getGroup({
		    limit: 50,
		    success: function (res) {
		      uni.setStorage({
		        key: "listGroup",
		        data: res.data
		      });
		      me.getChatList();
		    },
		    error: function (err) {
		      console.log(err);
		    }
		  });
		},
		makeVideoCall(data){
			console.log('data:', data)
			 if(false){
				uni.showToast({
					title: '請輸入會議Id',
					duration: 2000
				});
				return
			}
			uni.navigateTo({
				url: "../emedia/index?srcData="+JSON.stringify(data)
			});
		
		},
		// 不包含陌生人版本
		getChatList() {
		  var array = [];
		  var member = uni.getStorageSync("member");
		  var myName = uni.getStorageSync("myUsername");
		  var listGroups = uni.getStorageSync('listGroup') || [];
		
		  for (let i = 0; i < member.length; i++) {
		    let newChatMsgs = uni.getStorageSync(member[i].name + myName) || [];
		    let historyChatMsgs = uni.getStorageSync("rendered_" + member[i].name + myName) || [];
		    let curChatMsgs = historyChatMsgs.concat(newChatMsgs);
		
		    if (curChatMsgs.length) {
		      let lastChatMsg = curChatMsgs[curChatMsgs.length - 1];
		      lastChatMsg.unReadCount = newChatMsgs.length;
		
		      if (lastChatMsg.unReadCount > 99) {
		        lastChatMsg.unReadCount = "99+";
		      }
		
		      let dateArr = lastChatMsg.time.split(' ')[0].split('-');
		      let timeArr = lastChatMsg.time.split(' ')[1].split(':');
		      let month = dateArr[2] < 10 ? '0' + dateArr[2] : dateArr[2];
		      lastChatMsg.dateTimeNum = `${dateArr[1]}${month}${timeArr[0]}${timeArr[1]}${timeArr[2]}`;
		      lastChatMsg.time = `${dateArr[1]}${dateArr[2]}${timeArr[0]}${timeArr[1]}分`;
		      array.push(lastChatMsg);
					console.log('array1:', array)
		    }
		  }
		
		  for(let i = 0; i < listGroups.length; i++){
			let newChatMsgs = uni.getStorageSync(listGroups[i].groupid + myName) || [];
			let historyChatMsgs = uni.getStorageSync("rendered_" + listGroups[i].groupid + myName) || [];
			let curChatMsgs = historyChatMsgs.concat(newChatMsgs);
			if(curChatMsgs.length){
				let lastChatMsg = curChatMsgs[curChatMsgs.length - 1];
				lastChatMsg.unReadCount = newChatMsgs.length;
				if(lastChatMsg.unReadCount > 99) {
					lastChatMsg.unReadCount = "99+";
				}
				let dateArr = lastChatMsg.time.split(' ')[0].split('-')
				let timeArr = lastChatMsg.time.split(' ')[1].split(':')
				let month = dateArr[2] < 10 ? '0' + dateArr[2] : dateArr[2]
				lastChatMsg.time = `${dateArr[1]}${dateArr[2]}${timeArr[0]}${timeArr[1]}分`
				lastChatMsg.dateTimeNum = `${dateArr[1]}${month}${timeArr[0]}${timeArr[1]}${timeArr[2]}`
				lastChatMsg.groupName = listGroups[i].groupname
				array.push(lastChatMsg);
				console.log('array2:', array)
			}
		} 
		
		  array.sort((a, b) => {
		    return b.dateTimeNum - a.dateTimeNum;
		  });
			console.log('array3:', array)
			//2021/02/01新加
			uni.setStorageSync("newChatMsg" , array);
		  return array;
			
		},
		onClickMsg(msg){
			msg.action = 'join'
			uni.navigateTo({
				url: "../emedia/index?srcData="+JSON.stringify(msg)
			});
		}
  }
};
</script>
<style>
@import "./groupChatRoom.css";
</style>

四、總結與遇到的問題

  1. 整理demo時因為很多引數被封裝了,單獨引入很容易出錯,建議直接複製,然後再把不需要的程式碼刪掉。
  2. 注意:groupChatRoom模組、emedia模組等建議不要放在自己新建的子目錄裡,而直接放在pages目錄下,要不然會出現路徑錯誤而無法正常執行。