企业级音视频会议实战之webrtc服务器janus品尝实战

2023-10-27

1、前言

之前写过单纯用webrtc和springboot实现单人,多人,屏幕分享等功能的一系列文章了,心疼各位giegie,已将例子放在下面,不麻烦你们去找了

2、单纯使用webrtc的缺点

  • 维护连接关系上,无法统计也无法集中统一管理客户端(尤其系统中出现多对的p2p);

  • 在通信过程中获取媒体传输的实时码率,也无法对正在传输中的媒体流做出中间过滤,涉及到录制等操作时就没法玩了;

  • 每次建立通信,代码虽然很容易写出来,但是需要很繁琐;

  • 统一的日志记录;

janus演示图

3、使用webrtc服务器之后(这里以janus为例)

  • 回声测试、会议桥、媒体记录器、SIP 网关等基本功能

  • 可插拔的,按需引入所需的功能,比如会议功能,p2p通信功能,录制功能,播放第三方媒体流rtmp,屏幕共享等每个小功能可单独引入,只需要引入对应的插件即可

  • 自带用户统计,只需要按照特定的格式去请求即可,相当于给你提供了websockte服务器,你只需要按照规范来就完事了

  • 使用json作为向服务器请求服务的参数,简洁

  • 接入成本及其低

【学习地址】:FFmpeg/WebRTC/RTMP/NDK/Android音视频流媒体高级开发

【文章福利】:免费领取更多音视频学习资料包、大厂面试题、技术视频和学习路线图,资料包括(C/C++,Linux,FFmpeg webRTC rtmp hls rtsp ffplay srs 等等)有需要的可以点击1079654574加群领取哦~

4、janus服务器搭建教程

  • 在已经安装了docker的服务器上,创建docker-compose.yml,内容如下

注意:下面有几个文件需要手动去添加janus.jcfgjanus.eventhandler.sampleevh.jcfg相当于俩插件配置,这里面需要更改一些东西,所以直接挂载到宿主机即可,文件内容在https://github.com/meetecho/janus-gateway/tree/master/conf,找到同名字的(不用考虑文件后缀.sample,仅看前半部分即可)复制内容到本地创建的那俩文件里即可同时要注意看下面挂载的路径,换成自己想换的目录即可

version: '2.1'
services:
  #
  # janus-gateway
  #
  janus-gateway:
    image: 'canyan/janus-gateway:latest'
    command: ["/usr/local/bin/janus", "-F", "/usr/local/etc/janus"]
    network_mode: "host"
    volumes:
#- "./etc/janus/janus.transport.http.jcfg:/usr/local/etc/janus/janus.transport.http.jcfg"  # 打开adminapi的时候设
      - "./etc/janus/janus.jcfg:/usr/local/etc/janus/janus.jcfg"
      - "./etc/janus/janus.eventhandler.sampleevh.jcfg:/usr/local/etc/janus/janus.eventhandler.sampleevh.jcfg"
    restart: always
  • 更改重要配置参数

修改janus.jcfg文件,找到下面几个参数

api_secret = "sukejanxxusrocks"  ## 客户端使用restApi用的token
token_auth_secret = "sukexjanus" ## 使用ws使用的token
token_auth = true  ## 使用开启校验ws
admin_secret = "suaanusoverlord"  #管理员
  • 启动和日志查看

docker-compose up -d
docker-compse logs ## 查看日志

5、web端vue项目中初始化和使用

  • 官网git下载最新的js复制到本地文件,最后一行加入 export default Janus

下载地址:https://github.com/meetecho/janus-gateway/blob/master/html/janus.js

  • APP.vue引入

import adapter from 'webrtc-adapter'; //本地安装
import Janus from "./assets/janus/janus.js";
​
Janus.init({
 debug: true,
 dependencies: Janus.useDefaultDependencies({
   adapter: adapter
 }),
 callback: ()=> {
   if(!Janus.isWebrtcSupported()) {
  console.log('not Supported Webrtc!');
  return;
   }
 }
});
var janus = new Janus(
        {
   server: 'http://192.168.1.12/janus',
   apisecret:'apisecret',//这个密钥就是前面服务器搭建时配置的api_secret
   success: function() {
     // Done! attach to plugin XYZ
     console.log("done")
   },
   error: function(cause) {
     // Error, can't go on...
     console.log(cause)
   },
   destroyed: function() {
     // I should get rid of this
     console.log("destroyed")
   }
        });

初始化成功则会打印如下

Initializing library
janus.js?6559:450 Library initialized: true
janus.js?6559:473 Using REST API to contact Janus: http://192.168.1.12:8088/janus

6、使用janus实现人员注册视频通话

前面基础的环境已经准备就绪,接下来就是加载janus.plugin.videocall插件,实现视频通话,插件相关文档https://janus.conf.meetecho.com/docs/pages.html

  • 用初始化好的janus全局变量加载上面的插件

janus.attach(
{
  plugin: "janus.plugin.videocall",
  opaqueId: opaqueId,//随机变量即可
  success: function(pluginHandle) {
   // 这个变量一定要记住了pluginHandle,后续的操作都需要这个变量来操作
    Janus.log("Plugin attached! (" + pluginHandle.getPlugin() + ", id=" + pluginHandle.getId() + ")");
    // that.$store.commit("setVideoCallPluginHandle",pluginHandle)
  },
  error: function(cause) {
    console.log("videocall error cause",cause)
  },
  onmessage: function(msg, jsep) {
   // 所有相关操作的响应都会在这里出来(比如下面的用户注册成功失败响应)
    console.log("videocall onmessage",msg,jsep);
    
  },
  iceState: function(state) {
   Janus.log("ICE state changed to " + state);
  },
  mediaState: function(medium, on) {
   Janus.log("Janus " + (on ? "started" : "stopped") + " receiving our " + medium);
  },
  webrtcState: function(on) {
   Janus.log("Janus says our WebRTC PeerConnection is " + (on ? "up" : "down") + " now");
  },
  onlocalstream: function(stream){
   // 本地媒体流监听获取
   // that.setTargetMedia(stream,'local')
   console.log("localstream",stream)
  },
  onremotestream: function(stream) {
   //远程通话时远端媒体流监听
   //在这里可以通过前面全局变量pluginHandle.getBitrate获取实时通话的比特率
   console.log("remotestream",stream)
  },
  ondataopen: function(data) {
   Janus.log("The DataChannel is available!",data);
   
  },
  ondata: function(data) {
   Janus.debug("We got data from the DataChannel!", data);
  },
  oncleanup: function() {
   // PeerConnection with the plugin closed, clean the UI
   // The plugin handle is still valid so we can create a new one
 }
   
});

加载成功后,控制台会打印如下类似的内容

Created session: 8531598282085770
janus.js?6559:1280 Created handle: 7328474459571692
App.vue?234e:67 Plugin attached! (janus.plugin.videocall, id=7328474459571692)

注:前面加载插件成功之后会有一个很重要的变量pluginHandle,后续对视频通话的所有操作都是基于这个handle的

  • 向janus注册通话用户(callhandler 就是上述初始化后的handle)

下面注册的参数都是janus规范好的,username传自己的参数即可

var register = { request: "register", username: this.loginInfo.username };
callhandler.send({ message: register });

注册成功,则会在前面onmessage监听到下面打印的内容,重复注册的为第二条都会有对应提示Already registered (zhangsan)"

在两个页面分别注册,也就是注册两个用户

  • 发起视频通话

const that = this;
//创建offer 这个基本流程和普通建立rtc连接的流程一样的,不懂的直接回到前面看看我之前不用janus服务器的纯webrtc实现
callhandler.createOffer(
{
 media: { 
  audio:true,
  video: { width: 1920, height: 1080 }
  // video:"lowres"/"lowres-16:9"/"stdres"/"stdres-16:9"/"hires"/"hires-16:9",
  },
 iceRestart: true,
 success: function(jsep) {
  Janus.debug("Got SDP!", jsep);
  var body = { request: "call", username: 'lisi' };
  callhandler.send({ message: body, jsep: jsep });
 },
 error: function(error) {
  Janus.error("WebRTC error...", error);
 }
});

这边创建offer后呼叫另一个注册用户lisi,在lisi的那边onmessage监听方法下面,就会监听到呼叫,之后创建应答

//监听到呼入事件(janus自带的规范好的事件名称)
if(event === 'incomingcall') {
 Janus.log("Incoming call from " + result["username"] + "!");
 that.$store.state.videoCall.createAnswer(
  {
   jsep: jsep,
   media: {
    audio:true,
    video: { width: 1920, height: 1080 }
    }, 
   success: function(jsep) {
    Janus.debug("Got SDP!", jsep);
    var body = { request: "accept" };
                                //向呼叫者发送accept事件
    that.$store.state.videoCall.send({ message: body, jsep: jsep });
   },
   error: function(error) {
    Janus.error("WebRTC error:", error);
   }
  });
}
----------------呼叫者监听到accepted事件-------------------------
if(event === 'accepted') {
 var peer = result["username"];
 if(!peer) {
  Janus.log("Call started!");
 } else {
  Janus.log(peer + " accepted the call!");
 }
 // Video call can start
 if(jsep)
  that.$store.state.videoCall.handleRemoteJsep({ jsep: jsep });
​
}

以上基本整个流程完毕,就可以进行视频通话了

7、最后

有什么问题请留言哦

原文链接:企业级音视频会议实战之webrtc服务器janus品尝实战

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

企业级音视频会议实战之webrtc服务器janus品尝实战 的相关文章

随机推荐

  • 克隆get项目报错 OpenSSL SSL_read: Connection was reset, errno 10054解决办法

    克隆get项目报错 OpenSSL SSL read Connection was reset errno 10054解决办法 通过报错我们看到这个问题是链接被重置 问题 解决方法 在命令号修改设置解除ssl验证 git config gl
  • 强化学习中的马尔可夫决策过程,常见公式回顾

    0 基础知识 0 1 贝尔曼方程 这个公式是强化学习的核心 其中 s 可以看成未来的某个状态 p s s 是指从当前状态转移到未来状态的概率 V s 代表的是未来某一个状态的价值 我们从当前状态开始 有一定的概率去到未来的所有状态 所以我们
  • Vite2 + Vue3 + TypeScript + Pinia 搭建一套企业级的开发脚手架

    Vue2 与 Vue3 的区别 Vue3由于完全由TS进行重写 在应用中对类型判断的定义和使用有很强的表现 同一对象的多个键返回值必须通过定义对应的接口 interface 来进行类型定义 要不然在 ESLint 时都会报错 Vue2 与
  • Java从入门到实战总结-3.7、XML和JSON

    Java从入门到实战总结 3 7 XML和JSON 文章目录 Java从入门到实战总结 3 7 XML和JSON 1 前言 2 XML介绍 1 XML概述 2 用途 3 处理器与应用 4 标记 Markup 与内容 content 5 标签
  • java 利用方法实现数组之间的传递

    import java util public class HelloWorld public static void main String args int arr 1 2 3 int output transform arr 运用tr
  • springboot打印启动信息

    打印启动信息 param application 应用 SneakyThrows private static void printMsg ApplicationContext application String ip InetAddre
  • vuex(4.x)

    1 简介 vuex状态管理插件 在vue最重要就是数据驱动和组件化 每个组件都有自己的data template和methods data是数据 我们也叫做状态 通过methods中方法改变状态来更新视图 在单个组件中修改状态更新视图是很方
  • vue - mvvm模式的理解?

    1 MVVM 是Model View ViewModel 的缩写 它是一种基于前端开发的架构模式 其核心是提供对View 和 ViewModel 的双向数据绑定 2 MVVM 中的核心 VM vm负责连接 View 和 Model 保证视图
  • Python如何永久修改sys.path

    Python如何永久修改sys path 起因 这两天运行需要用命令行来运行python文件 但是总是报错ModuleNotFoundError No module named xxx tf liushanlin liushanlindeM
  • 解决Fastjson的下划线与大小写映射问题

    一 问题场景 目前我有一个类如下所示 Data ToString class BTEST Long infoId Long info id 需要执行的方法如下 Test public void jsonToBean Map
  • python3使用pykeyboard和Pyhook的问题及解决

    python3 7无法import pykeyboard的原因 问题1 ModuleNotFoundError No module named windows 问题2 cant import name PyKeyboard from pkk
  • python(列表、元组、字典)详解

    文章目录 什么是列表 列表的定义 in max min sum在列表中的使用 操作列表 初识元组 元组定义 列表与元组的区别 初识字典 字典的结构与创建方法 字典的遍历 字典支持的数据类型 循环 什么是列表 列表就是队列 是各种数据类型的集
  • 关于数论中的互质数的最大不能组合数

    题意 给定A和B A和B互质 求最大不能组合数 和不能组合数的个数 基础知识 Gcd A B 1 Lcm A B AB剩余类 把所有整数划分成m个等价类 每个等价类由相互同余的整数组成任何数分成m个剩余类 分别为 mk mk 1 mk 2
  • 新论文石锤Transformer:别只看注意力,没有残差和MLP,它啥都不是

    作者 青暮 基于注意力的架构在机器学习社区中已经变得无处不在 Transformer最初在机器翻译打出名堂 随着BERT的问世几乎统治了整个NLP领域 RNN LSTM等老前辈瑟瑟发抖 GPT 3的零样本学习能力又令人不禁怀疑其智能本质 还
  • 简单几步,让Mac外接显示器更好用

    光懂得给MacBook连接外置显示器还不行 了解这几点 才能让Mac外接显示器更好用 可以在两个显示器桌面之间任意拖拽移动软件窗口 这也是双 多 显示器一个高效的地方 将外接显示器设置为最佳分辨率 MacBook连接上外接显示器后 打开 系
  • Qt之工程文件

    文章目录 1 注释 2 QT 3 模板变量 TEMPLATE 4 TARGET 5 CONFIG 6 控制输出目录 6 1 UIC DIR 6 2 RCC DIR 6 3 MOC DIR 6 4 OBJECTS DIR 6 5 DESTDI
  • linux下制作动态库

    1 动态库的介绍 动态库 也叫共享库 动态库与用户编写的程序相互独立 不被包含在用户生成的可执行文件当中 2 动态库的创建 第一步 将写好的程序编译 我们事先写好两个程序 bye c hello c 一个输出hello一个输出bye 在终端
  • Spring AOP(一)五种增强(Advice)

    AOP术语都非常抽象 结合某些小例子就会形象 具体一些 连接点 Joinpoint Spring仅支持方法的连接点 即仅能在方法调用前 方法调用后 方法抛出异常时及方法调用前后 这些程序执行点织入增强 黑客攻击系统需要找到突破口 从某种程度
  • 【安卓网络编程】Android Studio导入Volley

    在Android Studio中使用Volley框架 首先要导入Volley到项目中去 点击主界面左上角File 点击Project Structure 在Modules下 点击app 然后点击Dependencies 然后点击右边的那个
  • 企业级音视频会议实战之webrtc服务器janus品尝实战

    1 前言 之前写过单纯用webrtc和springboot实现单人 多人 屏幕分享等功能的一系列文章了 心疼各位giegie 已将例子放在下面 不麻烦你们去找了 webrtc实现视频群聊系列文章 一 之基础入门 webrtc实现视频群聊系列