webRtc 示例

1、使用socket.io进行会话

2、为了方便,参数写死在前端了,前端界面1代码如下(由界面1发起视频):

<!DOCTYPE html>
<html><head><title>Socket.IO chat</title><meta charset="utf-8"><meta name="description" content="WebRTC code samples"><meta name="viewport" content="width=device-width, user-scalable=yes, initial-scale=1, maximum-scale=1"><meta itemprop="description" content="Client-side WebRTC code samples"><meta itemprop="name" content="WebRTC code samples"><meta name="mobile-web-app-capable" content="yes"><meta id="theme-color" name="theme-color" content="#ffffff"><!-- 引入2.0版本的socket.io文件 --><script src="socket.io.js"></script><script src="webrtc.js"></script><script src="jquery-3.6.4.js"></script><link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700" rel="stylesheet" type="text/css"><link rel="stylesheet" href="css/main.css" /><link rel="stylesheet" href="css/c1/main.css" /></head><body><div id="container"><video id="localVideo" title="a" playsinline autoplay muted></video><video id="remoteVideo" title="b" playsinline autoplay></video><div><button id="prepareBtn" type="button" onclick="prepare()">准备</button><button id="callBtn" type="button" onclick="callVideo()">呼叫</button><button id="cancelBtn" type="button" onclick="cancelVideo()">挂断</button></div></div><script>const prepareButton = document.getElementById('prepareBtn');const callBtn = document.getElementById('callBtn');const cancelBtn = document.getElementById('cancelBtn');const localVideo = document.getElementById('localVideo');const remoteVideo = document.getElementById('remoteVideo');let localStream;let pc1;let pc2;let to = '2';var iceServer = {{// urls: 'stun:stun.l.google.com:19302'urls: 'stun:stun.services.mozilla.com'}]};const offerOptions = {offerToReceiveAudio: 1,offerToReceiveVideo: 0};//建立socket连接const socket = io("https://192.168.3.21", {reconnectionDelayMax: 10000,auth: {token: "123"},query: {"userId": "1"}});socket.on("connect", () => {console.log("通道已建立")});//监听服务端发送的 topic1 消息socket.on("exchange", (msg) => {console.log("收到新的数据了");var data = JSON.parse(msg)console.log(data);var type = data.typeif (type === 'invite') {to = data.from} else if (type === 'recive') {to = data.from} else if (type === 'canditate') {if (data.data != undefined) {pc1.addIceCandidate(new RTCIceCandidate(data.data))}} else if (type === 'offer') {//设置远程应答pc1.setRemoteDescription(new RTCSessionDescription(data.data))pc1.createAnswer().then(function (answer) {send({type: 'answer',data: answer})return pc1.setLocalDescription(answer)}).then(sdp => {})} else if (type === 'answer') {if (data.data != undefined) {pc1.setRemoteDescription(new RTCSessionDescription(data.data))}}});function gotStream(stream) {localVideo.srcObject = stream;localStream = stream;}async function init() {navigator.mediaDevices.getUserMedia({audio: true,video: false}).then(gotStream).catch(e => alert(`getUserMedia() error: ${e.name}`));}async function prepare() {init();var data = {type: 'invite',data: 'video',from: '1',toUserId: '2'};// send(data);prepareButton.disabled = true;}function call() {pc1 = new RTCPeerConnection(iceServer);pc1.onicecandidate = e => onIceCandidate(pc1, e);// 有远程视频流时,显示远程视频流 pc1.addEventListener('track', event => {// remoteVideo.srcObject = event.streams[0]// remoteVideo.onloadedmetadata = function (e) {//     remoteVideo.play()// }})pc1.addEventListener('addstream', e => {console.log("AAAAAAAAAAA")console.log(e);remoteVideo.srcObject = e.stream})//初始化本人的视频流navigator.mediaDevices.getUserMedia({audio: false,video: true}).then(stream => {// 将视频流写入到video标签localVideo.srcObject = stream;localStream = stream;stream.getTracks().forEach(track => {pc1.addTrack(track, stream)});//向对方发送应答pc1.createOffer().then(sdp => {pc1.setLocalDescription(sdp)send({type: 'offer',data: sdp})})})localStream.getTracks().forEach(track => pc1.addTrack(track, localStream));callBtn.disabled = true;}function onIceCandidate(pc, event) {if (event.candidate) {send({type: 'canditate',data: event.candidate})}}function send(data) {data.toUserId = data.toUserId || toconsole.log(data)socket.emit("exchange", JSON.stringify(data))}function callVideo() {call();}function cancelVideo() {if (pc1 != null && pc1 != undefined) {pc1.close();}}</script><style>#video {background-color: black;height: 30vh;}</style>
</body></html>

3、前端界面2代码如下(当界面1发起视频呼叫后,该界面被动应答):

<!DOCTYPE html>
<html lang="zh"><head><title>Socket.IO chat</title><meta charset="utf-8"><meta name="description" content="WebRTC code samples"><meta name="viewport" content="width=device-width, user-scalable=yes, initial-scale=1, maximum-scale=1"><meta itemprop="description" content="Client-side WebRTC code samples"><meta itemprop="name" content="WebRTC code samples"><meta name="mobile-web-app-capable" content="yes"><meta id="theme-color" name="theme-color" content="#ffffff"><!-- 引入2.0版本的socket.io文件 --><script src="socket.io.js"></script><script src="webrtc.js"></script><script src="jquery-3.6.4.js"></script><link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700" rel="stylesheet" type="text/css"><link rel="stylesheet" href="css/main.css" /><link rel="stylesheet" href="css/c1/main.css" />
</head><body><div id="container"><video id="localVideo" title="a" playsinline autoplay muted></video><video id="remoteVideo" title="b" playsinline autoplay></video></div><script>const localVideo = document.getElementById('localVideo');const remoteVideo = document.getElementById('remoteVideo');let localStream;let pc1;let pc2;let to = '1';var iceServer = {{// urls: 'stun:stun.l.google.com:19302'urls: 'stun:stun.services.mozilla.com'}]};//建立socket连接const socket = io("https://192.168.3.21", {reconnectionDelayMax: 10000,auth: {token: "123"},query: {"userId": "2"}});socket.on("connect", () => {console.log("通道已建立")});//监听服务端发送的 topic1 消息socket.on("exchange", (msg) => {console.log("收到新的数据了");var data = JSON.parse(msg)var type = data.typeconsole.log({"name": "接收方",data});if (type === 'invite') {to = data.from//打开自己的摄像头init();} else if (type === 'recive') {to = data.from} else if (type === 'canditate') {if (pc1 == null) {init();}if (data.data != undefined) {pc1.addIceCandidate(new RTCIceCandidate(data.data))}} else if (type === 'offer') {if (pc1 == null) {init();}pc1.setRemoteDescription(new RTCSessionDescription(data.data))pc1.createAnswer().then(function (answer) {send({type: 'answer',data: answer})return pc1.setLocalDescription(answer)}).then(sdp => {})} else if (type === 'answer') {if (data.data != undefined) {pc1.setRemoteDescription(new RTCSessionDescription(data.data))}}});function gotStream(stream) {localVideo.srcObject = stream;localStream = stream;}function init() {navigator.mediaDevices.getUserMedia({audio: true,video: false}).then(gotStream).catch(e => alert(`getUserMedia() error: ${e.name}`));call();}function onIceCandidate(pc, event) {if (event.candidate) {send({type: 'canditate',data: event.candidate})}}function call() {pc1 = new RTCPeerConnection(iceServer);//获取本地网络信息,并发送给通信方 pc1.onicecandidate = e => onIceCandidate(pc1, e);// 有远程视频流时,显示远程视频流 // pc1.addEventListener('track', event => {//     console.log("BBBBBBBBBBBBBBBBBBBBBBBBB")//     console.log(event);//     console.log(localVideo.srcObject)//     console.log("BBBBBBBBBBBBBBBBBBBBBBBBB+")//     remoteVideo.srcObject = event.streams[0]//     remoteVideo.onloadedmetadata = function (e) {//         console.log("加载完毕")//         remoteVideo.play()//     }// })pc1.addEventListener('addstream', e => {// 将对方的视频流写入到video标签中remoteVideo.srcObject = e.stream})//本地视频流量,打开视频流navigator.mediaDevices.getUserMedia({audio: false,video: true}).then(stream => {// 将视频流写入到video标签中                localVideo.srcObject = stream;localStream = stream;stream.getTracks().forEach(track => {pc1.addTrack(track, stream)})pc1.createOffer().then(sdp => {pc1.setLocalDescription(sdp)send({type: 'offer',data: sdp})})})}function send(data) {data.toUserId = data.toUserId || toconsole.log({"name": "发送",data})socket.emit("exchange", JSON.stringify(data))}</script><style>#video {background-color: black;height: 30vh;}</style>
</body></html>

WebRTC学习(六)端对端传输_51CTO博客_webrtc学习

webRTC结合webSocket实时通信 - 掘金

4、关于 coturn 信令服务的安装,参考以下文档:coturn安装以及报错“coturn/src/apps/relay/netengine.c:316:对‘SSL_CTX_up_ref’未定义的引用“_coturn 启动报错_Mango酱的博客-CSDN博客

5、coturn 安装后的测试:Trickle ICE (webrtc.github.io)

6、代码中进行如下设置: 

  //该参数为了var iceServer = {// iceServers: [{//     urls: 'stun:stun.l.google.com:19302'// }]iceServers: [{urls: 'stun:stun.services.mozilla.com'},{urls: 'turn:ip:3478',credential: '密码',username: '账号'}]};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/63106.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数字化新零售平台系统提供商,门店商品信息智慧管理-亿发进销存

传统的批发零售业务模式正面临着市场需求变化的冲击。用户日益注重个性化、便捷性和体验感&#xff0c;新兴的新零售模式迅速崛起&#xff0c;改变了传统的零售格局。如何在保持传统业务的基础上&#xff0c;变革发展&#xff0c;成为了业界亟需解决的问题。 在这一背景下&…

JixiPix Artista Impresso Pro for mac(油画滤镜效果软件)

JixiPix Artista Impresso pro Mac是一款专业的图像编辑软件&#xff0c;专为Mac用户设计。它提供了各种高质量的图像编辑工具&#xff0c;可以帮助您创建令人惊叹的图像。该软件具有直观的用户界面&#xff0c;使您可以轻松地浏览和使用各种工具。 它还支持多种文件格式&…

前端是leyui后端sqlserver和maraDB进行分页

项目场景&#xff1a; 前端是leyui后端sqlserver和maraDB进行分页,两种数据库在后端分页的不同写法 解决方案&#xff1a; 前端: 定义table,表格的格式在接口返回时进行创建,根据id进行绑定 <div class"layui-tab-item layui-show" style"padding-top: 10…

@XmlType,@XmlRootElement,@XmlAttribute的作用与区别

XmlType、XmlRootElement 和 XmlAttribute 都是 Java 标准库中 javax.xml.bind.annotation 包提供的注解&#xff0c;用于在使用 JAXB&#xff08;Java Architecture for XML Binding&#xff09;或其他 XML 绑定技术时&#xff0c;控制 Java 类与 XML 数据之间的映射关系。 它…

C++的基类和派生类构造函数

基类的成员函数可以被继承&#xff0c;可以通过派生类的对象访问&#xff0c;但这仅仅指的是普通的成员函数&#xff0c;类的构造函数不能被继承。构造函数不能被继承是有道理的&#xff0c;因为即使继承了&#xff0c;它的名字和派生类的名字也不一样&#xff0c;不能成为派生…

rate-based 拥塞控制吞吐测量

要点&#xff1a;一个方法无法精确刻画链路画像&#xff0c;就用多种方法组合刻画&#xff0c;设计一个 “自定义平均”。 当前 Linux kernel TCP 实现的 TCP delivery rate 测量机制(BBR 有使用到)如下图&#xff1a; 简略后可展示为下图&#xff1a; 详见 net/ipv4/tcp_…

5G NR:RACH流程 -- Msg1发送时RA-RNTI的计算及功率控制

前言 如果阅读了这两篇博文《如何产生PRACH preamble》和《如何选择合适的时频资源发送preamble》&#xff0c;那么对msg1有了基本了解&#xff0c;但是真到了Msg1发送的时候&#xff0c;该怎么处理呢&#xff0c;这里涉及到两个问题&#xff1a; 问题1&#xff1a;发…

数据结构:排序解析

文章目录 前言一、常见排序算法的实现1.插入排序1.直接插入排序2.希尔排序 2.交换排序1.冒泡排序2.快速排序1.hoare版2.挖坑版3.前后指针版4.改进版5.非递归版 3.选择排序1.直接选择排序2.堆排序 4.归并排序1.归并排序递归实现2.归并排序非递归实现 5.计数排序 二、排序算法复杂…

安装cx_Oracle

1&#xff0c;好久不使用的环境安装cx_Oracle 执行 conda install cx_Oracle 报 Invalid version spec: 2. 7 我都python版本是>3.7的 然后根据博客&#xff0c;执行了 conda create -n conda_env_name python3.7 conda4.9.2 下载了一大堆东西。然后重新执行&#xff0c;还…

训练简单的线性模型,预测电影评分和票房收入

文章目录 训练简单的线性模型&#xff0c;预测电影评分和票房收入数据集加载数据可视化数据分割数据集训练模型可视化结果应用模型保存和加载模型 训练简单的线性模型&#xff0c;预测电影评分和票房收入 这是一个简单的线性模型&#xff0c;用于预测电影的评分和票房收入。不…

idea全局搜索失效,Ctrl+shift+F快捷键不起作用

方法1&#xff1a;是否与搜狗等输入法软件存在快捷键冲突&#xff0c;当然也可能是你新下载的什么软件导致的快捷键冲突导致IDEA全局搜索失效。比如下图&#xff1a; 可以改掉输入法的快捷键或者直接关闭输入法的快捷键&#xff0c;这样idea的全局搜索功能就恢复了。 方法2&…

1.9 动态解密ShellCode反弹

动态解密执行技术可以对抗杀软的磁盘特征查杀。其原理是将程序代码段中的代码进行加密&#xff0c;然后将加密后的代码回写到原始位置。当程序运行时&#xff0c;将动态解密加密代码&#xff0c;并将解密后的代码回写到原始位置&#xff0c;从而实现内存加载。这种技术可以有效…

【Cookie和Session的那些事儿】

&#x1f320;作者&#xff1a;TheMythWS. &#x1f386;专栏&#xff1a;《集合与数据结构》 &#x1f387;座右铭&#xff1a;不走心的努力都是在敷衍自己&#xff0c;让自己所做的选择&#xff0c;熠熠发光。 目录 认识Cookie和Session Cookie Cookie对象的特点 Cookie对…

session、cookie、webstorage的区别

Cookie Cookie实际上是一小段的文本信息&#xff0c;是服务器发送到用户浏览器并保存在本地的一小块数据。客户端请求服务器&#xff0c;如果服务器需要记录该用户状态&#xff0c;就使用response向客户端浏览器颁发一个Cookie。客户端会把Cookie保存起来。当浏览器下次向同一…

Unity 之 参数类型之值类型参数的用法

文章目录 基本数据类型结构体结构体的进一步补充 总结&#xff1a; 当谈论值类型参数时&#xff0c;我们可以从基本数据类型和结构体两个方面详细解释。值类型参数指的是以值的形式传递给函数或方法的数据&#xff0c;而不是引用。 基本数据类型 基本数据类型的值类型参数&…

数据库介绍

一.什么是数据库&#xff1f; 通俗的来讲数据库就是用来存放数据的地方&#xff0c;可以理解为和冰箱一样 官方&#xff1a; 数据库&#xff08;Database&#xff09;是按照数据结构来组织、存储和管理数据的仓库。 每个数据库都有一个或多个不同的 API 用于创建&#xff0c;…

说说Flink双流join

分析&回答 Flink双流JOIN主要分为两大类 一类是基于原生State的Connect算子操作另一类是基于窗口的JOIN操作。其中基于窗口的JOIN可细分为window join和interval join两种。 基于原生State的Connect算子操作 实现原理&#xff1a;底层原理依赖Flink的State状态存储&…

第四课:C++实现压缩包破解密码

这里提供一种基于暴力破解的方法: 安装一个压缩工具,比如WinRAR或7-Zip。 使用C++编写程序,读取需要破解密码的压缩包文件。 利用循环和字符串的特性,生成所有可能的密码组合,并逐个尝试打开压缩包。 如果成功打开,则说明找到了正确的密码,程序停止运行并输出密码。 如果…

11.添加侧边栏,并导入数据

修改CommonAside的代码&#xff1a; <template><div><el-menu default-active"1-4-1" class"el-menu-vertical-demo" open"handleOpen" close"handleClose":collapse"isCollapse"><!--<el-menu-it…

Matlab在编码中增加CRC和交织功能

定义CRC生成和检验的类&#xff08;包括函数&#xff09; 我们在MATLAB中定义一个类&#xff08;class&#xff09;&#xff0c;包含了CRC生成函数和检验函数&#xff08;囊括了常用的CRC多项式&#xff09; classdef CRCpropertiesCRCbit_LenpolynomialCRCgenCRCdetendmetho…