首先这次接触到IM,是因为项目里需要用到一个群聊视频,通讯录,消息发送等功能,但是Im提供的dom是 react框架写的,并没有vue框架的dom,于是自己根据IM的官方文档实现了在vue框架下的IM通讯。

这是最终效果图,因个人项目而异,弹窗或者不弹窗灵活改动,还有很多功能没写,待此功能重构后再继续更新,因信息数据保密所以打码

IM官方文档:https://doc.rentsoft.cn/#/integrate/web/integrate_login_web
–》web就看每一个功能下面web端文档说明
视频通讯文档 官方没有写,但是在IM项目的源码里面发现视频通讯功能使用的是LiveKit
LiveKit官方文档 :https://docs.livekit.io/guides/room/connect/
LiveKit GitHub: https://github.com/livekit/client-sdk-js
LiveKit JS Client SDK文档: https://docs.livekit.io/client-sdk-js/index.html
LiveKit其实只需要看 官方文档就OK,当然,除非你想深入了解它
下面贴实现过程代码
首先第一步 登录IM 我将它部分封装在一个JS里面

PS:音频功能需要在HTTPS 和 本地环境下浏览器才允许通过安全策略,否则调取本地摄像头你会报错,目前没找到浏览器关闭使用摄像头,目前找到的资料是挂断电话或者关闭通话弹窗时刷新此页面

import { OpenIMSDK } from 'open-im-sdk'
import axios from "axios";
import store from "@/store";
import { Message } from 'element-ui';//       音视频邀请相关信息
// {//      "inviterUserID": "18666662412",  //邀请者UserID
//      "inviteeUserIDList": ["18349115126"], //被邀请者UserID列表,如果是单聊只有一个元素
//      "groupID": "f2e77b9ec33e92298675ad511fdfa6ab", //如果是单聊,为""
//      "roomID": "room_id_111", //房间ID,必须唯一,可以不设置。
//      "timeout": 1000, //邀请超时时间(秒)
//      "mediaType": "video", //video 或者audio
//      "sessionType": 2 //1为单聊,2为群聊
//      "platformID":1 // 创建时写什么就是什么 1 2 皆可
//  }
let user = '';
const openIM = new OpenIMSDK();
const onGetImData = (datas) => {user = JSON.parse(datas.serviceTag1)let urls = window.location.host;let obj = {platform: "5",userID: JSON.parse(datas.serviceTag1).openImUserId,};let urltype = 'https://****:端口/portaluserIm/im/user/obtainToken';let urlstype =document.location.protocol.indexOf("https") > -1 ? true : false;axios.post(urltype, obj).then((data) => {console.log("openIMopenIM", data);sessionStorage.setItem("SET_IMTOKEN", JSON.stringify(data.data.data));var commonIp = ''commonIp = eval("(" + sessionStorage.getItem('commonIp') + ")")console.log('commonIp',commonIp);const config = {userID: data.data.data.userID,token: data.data.data.token,url: commonIp? commonIp.newImWss : '你的wss地址',platformID: 5,};openIM.login(config).then((res) => {console.log("login 结果...", res);sessionStorage.setItem("SET_IMUSER", JSON.stringify(res));openIM.on("OnRecvNewMessage", (dataMessage) => {console.log("会话消息监听测试", JSON.parse(dataMessage.data));});openIM.on("OnReceiveNewInvitation", (dataInvitation) => {let row = dataInvitation;row.objData = JSON.parse(row.data);row.objDataName = row.objData.participant.groupInfo.groupNameconsole.log('urlstype', urlstype);if (row.objData.invitation.inviterUserID != user.openImUserId) {// 被邀请者需要点击接受后 方可进入视频房间sessionStorage.removeItem("ImRow")sessionStorage.setItem("ImRow", JSON.stringify(row))store.commit("SET_IMTYPE", true);console.log('this.$store.state.user.ImType', store.state.ImType);} else {}console.log("被邀请者收到:音视频通话邀请", row,user);});openIM.on("OnInviteeAccepted", (dataAccepted) => {console.log("邀请者收到:被邀请者同意音视频通话", dataAccepted);});openIM.on("OnInviteeRejected", (inviteeRejectedCallback) => {console.log("邀请者收到:被邀请者拒绝音视频通话",inviteeRejectedCallback);});openIM.on("OnInvitationCancelled", (dataCancelled) => {console.log("被邀请者收到:邀请者取消音视频通话", dataCancelled);});openIM.on("OnInvitationTimeout", (dataTimeout) => {console.log("邀请者收到:被邀请者超时未接通", dataTimeout);});openIM.on("OnInviteeAcceptedByOtherDevice", (dataOtherDevice) => {console.log("被邀请者(其他端)收到:比如被邀请者在手机接听,在pc上会收到此回调",dataOtherDevice);});openIM.on("OnInviteeRejectedByOtherDevice", (dataDevice) => {console.log("被邀请者(其他端)收到:比如被邀请者在手机拒接,在pc上会收到此回调",dataDevice);});}).catch((err) => {console.log("login 报错结果...", err);});});
}
export default {onGetImData: onGetImData,openIM: openIM
};

上面是封装好的JS文件,既然封装了就得引用对吧,是的,你知道的

import openIMData from "@/components/ImToken";
const openIM = openIMData.openIM;

好了 接下来我们将一步一步来
1,创建群
https://doc.rentsoft.cn/#/integrate/web/integrate_group_web 官方文档有写
2,创建群组成功后 ,如果需要二次确认就获取下当前群组信息你能拿到当前群成员所有ID,如果不用那么就直接发起呼叫

//       音视频邀请相关信息// {//         "inviterUserID": "18666662412",  //邀请者UserID//      "inviteeUserIDList": ["18349115126"], //被邀请者UserID列表,如果是单聊只有一个元素//       "groupID": "f2e77b9ec33e92298675ad511fdfa6ab", //如果是单聊,为""//       "roomID": "room_id_111", //房间ID,必须唯一,可以不设置。//         "timeout": 1000, //邀请超时时间(秒)//      "mediaType": "video", //video 或者audio//         "sessionType": 2 //1为单聊,2为群聊//         "platformID":1//  }let invitation = {inviterUserID: user.userID,inviteeUserIDList: this.qunUid.arrData,groupID: this.qunData.groupID,// groupID: "eaaf2f787bd59b5c8ac2c1039d8388ff", // 方便测试创建好一个群后你需要记录这个群的 IDroomID: this.oncode(),// 唯一ID 你可以随机生成15位数字+字母timeout: 10000,mediaType: "video",sessionType: 2,};openIM.signalingInviteInGroup(invitation).then((res) => {console.log("res11", res);Message({showClose: true,message: "音频发起成功,如长时间未反应,请刷新页面后重新发起!",type: "success",duration: 5000,});this.qunUidView = res;this.qunUidView.obj = JSON.parse(res.data);let row = {objData: {invitation: invitation,},};sessionStorage.setItem("ImRow", JSON.stringify(row));store.commit("SET_CreateVideoUserType", true);}).catch((err) => {console.log("err", err);});

好的,上面这一块代码 你已经成功发起了 呼叫,现在回到封装好的JS文件,不管是创建群还是消息接受 OnRecvNewMessage 函数都会接收到反馈数据,比如别人创建了一个群 把你添加进去 此函数会返回数据,好了让我们继续往下走,或许你觉得我讲的废话很多,你可以关闭当前浏览器。

上面讲到发起了群聊视频,被邀请者 OnReceiveNewInvitation 方法会触发,此函数会返回 当前群聊视频房间所有信息,比如房间ID 房间成员,记住 这是视频群聊房间 不是上面创建的群。群不等于音频群聊房间。

你可以和我一样设置一个监听vuex -》 store.commit(“SET_IMTYPE”, true);当有人邀请我 需要弹出接受邀请按钮,下面我们来看看点击接受按钮后的事件

import { Room, RoomEvent, ParticipantEvent, Track } from "livekit-client";//记得引用
class VideoPreset {constructor(width, height, maxBitrate, maxFramerate) {this.width = width;this.height = height;this.encoding = {maxBitrate,maxFramerate,};}get resolution() {return {width: this.width,height: this.height,frameRate: this.encoding.maxFramerate,aspectRatio: this.width / this.height,};}
}const VideoPresets = {h90: new VideoPreset(160, 90, "60_000", 15),h180: new VideoPreset(320, 180, "120_000", 15),h216: new VideoPreset(384, 216, "180_000", 15),h360: new VideoPreset(640, 360, "300_000", 20),h540: new VideoPreset(960, 540, "600_000", 25),h720: new VideoPreset(1280, 720, "2_000_000", 30),h1080: new VideoPreset(1920, 1080, "3_000_000", 30),h1440: new VideoPreset(2560, 1440, "5_000_000", 30),h2160: new VideoPreset(3840, 2160, "8_000_000", 30),/** @deprecated */qvga: new VideoPreset(320, 180, "120_000", 10),/** @deprecated */vga: new VideoPreset(640, 360, "300_000", 20),/** @deprecated */qhd: new VideoPreset(960, 540, "600_000", 25),/** @deprecated */hd: new VideoPreset(1280, 720, "2_000_000", 30),
};
// created 里面 需要 this.room = new Room(); 初始化
let obj = {opUserID: SET_IMTOKEN.userID,invitation: {inviterUserID: this.sessData.objData.invitation.inviterUserID, // 邀请者inviteeUserIDList: [SET_IMTOKEN.userID], // 参与者IDgroupID: this.sessData.objData.invitation.groupID, // 群IDroomID: this.sessData.objData.invitation.roomID, //房间ID,必须唯一,可以不设置。timeout: 60, //邀请超时时间(秒)mediaType: "video",sessionType: 2,},};console.log("接受视频邀请参数", obj);openIM.signalingAccept(obj).then(async ({ data }) => {this.signalAcceptReqData = JSON.parse(data);console.log("接受某人邀请返回房间进入token,和 ws 地址",this.signalAcceptReqData);await this.room.connect(this.signalAcceptReqData.liveURL, // rtc 地址this.signalAcceptReqData.token, // rtc 链接当前登录用户token{// to publish camera and microphone immediately after joining 加入后立即发布相机和麦克风audio: true,video: true,// don't subscribe to other participants automatically 不要自动订阅其他参与者autoSubscribe: true,// automatically manage video quality 自动管理视频质量autoManageVideo: true,// default publish settings 默认发布publishDefaults: {simulcast: true,},// default capture settings 默认捕获设置captureDefaults: {videoResolution: VideoPresets.hd.resolution,},}).then(async (room) => {// 此时你已经连接进入到了群聊视频房间console.log("livekit-client->connect 回调", room);this.roomData = room;room.on(RoomEvent.TrackSubscribed,(track, publication, participant) => {let ele = document.getElementById("videodata");var videoDomDiv = document.createElement("div"); // 创建文字标签if (track.kind == "video") {console.log("接受媒体", track, publication, participant);videoDomDiv.setAttribute("style","height:150px;width:200px;display: flex;flex-direction: column-reverse;align-items: center;margin: 0px 5px;");videoDomDiv.setAttribute("id", participant.identity);let nameData = JSON.parse(participant.metadata);videoDomDiv.innerHTML = nameData.userInfo.nickname? nameData.userInfo.nickname: nameData.userInfo.userID;console.log(nameData.userInfo.nickname? nameData.userInfo.nickname: nameData.userInfo.userID);ele.appendChild(videoDomDiv);}const element = track.attach();element.className = participant.identity;videoDomDiv.appendChild(element);});room.on(RoomEvent.TrackPublished,(track, publication, participant) => {console.log("查看房间活动", track, publication, participant);});room.on(RoomEvent.LocalTrackPublished, (track, publication) => {console.log("本地音轨已发布", new Track(), track, publication);});room.on(RoomEvent.RoomMetadataChanged, (track) => {console.log("房间元数据已更改", track);});room.on(RoomEvent.TrackStreamStateChanged,(track, publication, participant) => {console.log("跟踪流状态已更改",track,publication,participant);if (document.getElementById(participant.identity)) {console.log("当前ID,DOM存在", participant.identity);document.getElementById(participant.identity).remove();setTimeout(() => {let ele = document.getElementById("videodata");var videoDomDiv = document.createElement("div"); // 创建文字标签if (track.kind == "video") {console.log("跟踪流状态已更改后的媒体流数据",track,publication,participant);videoDomDiv.setAttribute("style","height:150px;width:200px;display: flex;flex-direction: column-reverse;align-items: center;margin: 0px 5px;");videoDomDiv.setAttribute("id", participant.identity);let nameData = JSON.parse(participant.metadata);videoDomDiv.innerHTML = nameData.userInfo.nickname? nameData.userInfo.nickname: nameData.userInfo.userID;console.log(nameData.userInfo.nickname? nameData.userInfo.nickname: nameData.userInfo.userID);ele.appendChild(videoDomDiv);}const element = track.track.attach();element.className = participant.identity;videoDomDiv.appendChild(element);}, 200);}});room.on(RoomEvent.TrackUnsubscribed,(track, publication, participant) => {console.log("从所有附加元素中删除轨道",track,publication,participant);if (track.detach) {track.detach();}if (document.getElementById(participant.identity)) {document.getElementById(participant.identity).remove();}});room.on(RoomEvent.ConnectionQualityChanged, (participant) => {// 目前这里输出 good  excellentconsole.log("模仿源码未知函数", participant);});room.on(RoomEvent.TrackSubscriptionFailed,(track, publication, participant) => {console.log("跟踪订阅失败", track, publication, participant);});room.on(RoomEvent.ActiveSpeakersChanged, (speakers) => {// show UI indicators when participant is speaking// 当参与者发言时显示用户界面指示器});room.on(RoomEvent.Disconnected, () => {console.log("参与者离开时");});room.on(RoomEvent.LocalTrackUnpublished, (track, participant) => {console.log("当本地轨迹结束时,更新UI以将其从渲染中删除",track,participant);if (track.detach) {track.detach();document.getElementById(participant.identity).remove();}});room.on(RoomEvent.ParticipantConnected, (participant) => {// set up any per-participant callbacks 设置每个参与者的回调participant.on(ParticipantEvent.TrackMuted, (publication) => {console.log("设置每个参与者的回调", publication);});});room.on(RoomEvent.ParticipantDisconnected, (track) => {console.log("参与者 分离", track);let elements = document.getElementsByClassName(track.identity);for (var i = elements.length - 1; i >= 0; i--) {elements[i].parentNode.removeChild(elements[i]);}});room.on(RoomEvent.DataReceived, (payload, participant, kind) => {// receive data from other participants// 接收其他参与者的数据 RemoteTrackPublication});// publish local camera and mic tracks  发布本地摄像头和麦克风轨道await room.localParticipant.enableCameraAndMicrophone();const p = room.localParticipant;await p.setCameraEnabled(true).then((data) => {console.log("有摄像头", data);navigator.mediaDevices.getUserMedia({ audio: false, video: true }).then((stream) => {console.log("stream", stream, stream.getTracks());this.loading = false;this.videoStream =typeof stream.stop === "function"? stream: stream.getTracks();let ele = document.getElementById("videodata"); // 获取父级标签var videoDomDiv = document.createElement("div"); // 创建多媒体承载盒子标签videoDomDiv.setAttribute("style","height:150px;width:200px;display: flex;flex-direction: column-reverse;align-items: center;");videoDomDiv.innerHTML = store.state.userInfo.nickName;var videoDom = document.createElement("video"); // 创建多媒体标签videoDom.setAttribute("id", "newRTC");videoDom.autoplay = true;videoDom.setAttribute("style","height:125px;width:200px;");videoDom.srcObject = stream;videoDomDiv.appendChild(videoDom);ele.appendChild(videoDomDiv);}).catch((err) => {this.loading = false;console.log(err);});}).catch((err) => {console.log("没有摄像头");}); // 调取摄像头 没有会报错await p.setMicrophoneEnabled(true).then((data) => {console.log("有麦克风", data);}).catch((err) => {console.log("没有麦克风");}); // 调取声音 没有会报错// 屏幕 true 会分享屏幕await p.setScreenShareEnabled(false).then((data) => {console.log("屏幕", data);}).catch((err) => {console.log("屏幕", err);});room.on(RoomEvent.AudioPlaybackStatusChanged, () => {if (!room.canPlayAudio) {// UI is necessary.console.log("333333");button.onclick = () => {room.startAudio().then(() => {button.remove();});};}});}).catch((err) => {console.log("livekit-client->connect 回调 报错", err);});}).catch((err) => {this.loading = false;console.log("接受视频邀请 报错信息", err);});

3,关闭房间记得退群,因项目而异。这里说的群 是上面创建的群

喜欢就关注吧,后续将持续输出一些接触到的新东西

前端IM使用以及视频通讯记录分项相关推荐

  1. 前端如何实现整套视频直播技术流程(以打扑克直播软件为例)

    前端如何实现整套视频直播技术流程目录大纲: 直播技术的简单介绍 前端搭建使用的技术 实践效果 后续需要深入的地方 打扑克直播软件视频直播技术简介: 首先说明,本篇文章是概念+实践,对于希望了解和实践一 ...

  2. 直播平台软件开发的前端如何实现整套视频直播技术流程

    直播平台软件开发的前端如何实现整套视频直播技术流程 正文 下面按照目录大纲来一个一个讲解. 1. 直播技术的介绍 直播技术涵盖很广,现如今大家广泛了解的就有视频网站的个人直播.手机直播.安防方面的摄像 ...

  3. FreeSWITCH学习笔记 第二场 第二个镜头 JsSIP视频通讯

    上一章JsSIP初识已经介绍了JsSIP的基本使用方法,这一章将使用FreeSWITCH+JsSIP实现视频通讯,截止本文FreeSWITCH使用1.6.18版本,JsSIP使用的3.0.15版本(经 ...

  4. WebRTC / Jitsi / 多人视频通讯常用架构 Mesh / MCU / SFU

    问题:为什么要搞这么多架构? WebRTC 虽然是一项主要使用 P2P 的实时通讯技术,本应该是无中心化节点的,但是在一些大型多人通讯场景,如果都使用端对端直连,端上会遇到很带宽和性能的问题,所以就有 ...

  5. 前端初学者开发学习视频_初学者学习前端开发的实用指南

    前端初学者开发学习视频 by Nikita Rudenko 通过尼基塔·鲁登科(Nikita Rudenko) 初学者学习前端开发的实用指南 (A practical guide to learnin ...

  6. 基于SIP协议的视频通讯

    1.sip协议及其发展 sip(session initiation protocal)称为会话发起协议,是由ietf(internet engineering task force)组织于1999年 ...

  7. 多人视频通讯常用架构Mesh/MCU/SFU

    问题:为什么要搞这么多架构? webrtc虽然是一项主要使用p2p的实时通讯技术,本应该是无中心化节点的,但是在一些大型多人通讯场景,如果都使用端对端直连,端上会遇到很带宽和性能的问题,所以就有了下图 ...

  8. uniapp实现音视频通讯

    uniapp实现音视频通讯 还在为uniapp的音视频通讯发愁吗?anyRTC为解决广大开发者需求,特别研发了uniapp版的音视频通讯. anyRTC 实时通信包括两个模块: 实时音视频模块- 音视 ...

  9. 音视频通讯QoS技术及其演进

    利用多种算法和策略进行网络传输控制,最大限度满足弱网场景下的音视频用户体验. 良逸|技术作者 01 什么是QoS?音视频通讯QoS是哪一类? QoS(Quality of Service)是服务质量的 ...

最新文章

  1. Unity进阶技巧 - RectTransform详解
  2. 清华、北邮等高校研究人员实现具有 160 个目标的基于 SSVEP 的免校准 BCI 系统...
  3. java 根据预览图片上传_JavaSctit 利用FileReader和滤镜上传图片预览功能
  4. php读取txt插入数据库,PHP读取TXT文件插入数据库
  5. 十大最常见的Java性能问题
  6. golang time包梳理
  7. unsigned char s1 : 2的用法
  8. 获取本地ip地址适用于windows和Linux环境
  9. BZOJ-1922 大陆争霸 多限制、分层图最短路 (堆+dijkstra)
  10. spark.sql读取Hive数据报错
  11. php中计算时间差的几种方法,php计算时间差的方法
  12. Linux FrameBuffer分析
  13. ASP.NET MVC 学习第三天
  14. Android代码中实现关机
  15. matlab 逻辑矩阵方格图,均匀设计表的MATLAB实现.pdf
  16. 聊聊北京大部分前端从业者所面临的困境
  17. 执行linux操作时提示:权限不够
  18. for循环如果先--_JavaSE第04篇:Java基础语法之循环结构
  19. 北大新任校长王恩哥的10句话
  20. unity3d 鼠标点击事件处理 处理鼠标点击

热门文章

  1. excel html 查询,html 连接 excel表格数据库数据-利用EXCEL表格为数据库制作查询网页...
  2. Dos命令简单操作入门操作
  3. FireMonkey 手机 APP 的手势
  4. ZYNQ-IO模拟HDMI输出图像
  5. C语言编程优化运行速度
  6. python实现滑块移动操作
  7. Gradle下载超时
  8. 深圳自建房能申请学位吗 自建房申请学位需要哪些材料
  9. 语义分割丨PSPNet源码解析「训练阶段」
  10. C++(数据结构复习篇)(数组【压缩】|广义表)的概念和相关算法)