webrtc实现点对点视频通讯
html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>webrtc</title>
<style>
#yours{
width:300px;
position:absolute;
top:200px;
left:100px;
}
#theirs{
width:300px;
position:absolute;
top:200px;
left:400px;
}
</style>
</head>
<body>
<button onclick="createOffer()">建立连接</button>
<video id="yours" autoplay></video>
<video id="theirs" autoplay></video> </body> <script src="./lib/jquery.min.js"></script>
<script src="./lib/webrtc.js"></script> </html>
webrtc.js
var websocket; function randomNum(minNum,maxNum){
switch(arguments.length){
case :
return parseInt(Math.random()*minNum+,);
break;
case :
return parseInt(Math.random()*(maxNum-minNum+)+minNum,);
break;
default:
return ;
break;
}
}
const userid = 'user' + randomNum(,); function hasUserMedia() {
navigator.getUserMedia = navigator.getUserMedia || navigator.msGetUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
return !!navigator.getUserMedia;
}
function hasRTCPeerConnection() {
window.RTCPeerConnection = window.RTCPeerConnection || window.webkitRTCPeerConnection || window.mozRTCPeerConnection || window.msRTCPeerConnection;
return !!window.RTCPeerConnection;
} var yourVideo = document.getElementById("yours");
var theirVideo = document.getElementById("theirs");
var Connection; function startPeerConnection() {
//return;
var config = {
'iceServers': [
//{ 'urls': 'stun:stun.xten.com:3478' },
//{ 'urls': 'stun:stun.voxgratia.org:3478' },
{ 'url': 'stun:stun.l.google.com:19302' }
]
};
config = {
iceServers: [
{ urls: 'stun:stun.l.google.com:19302' },
{ urls: 'stun:global.stun.twilio.com:3478?transport=udp' }
],
//sdpSemantics: 'unified-plan'
};
// {
// "iceServers": [{
// "url": "stun:stun.1.google.com:19302"
// }]
// };
Connection = new RTCPeerConnection(config);
Connection.onicecandidate = function(e) {
console.log('onicecandidate');
if (e.candidate) {
websocket.send(JSON.stringify({
"userid":userid,
"event": "_ice_candidate",
"data": {
"candidate": e.candidate
}
}));
}
}
Connection.onaddstream = function(e) {
console.log('onaddstream'); //theirVideo.src = window.URL.createObjectURL(e.stream);
theirVideo.srcObject = e.stream;
}
} createSocket();
startPeerConnection(); if (hasUserMedia()) {
navigator.getUserMedia({ video: true, audio: false },
stream => {
yourVideo.srcObject = stream;
window.stream = stream;
Connection.addStream(stream)
},
err => {
console.log(err);
})
} function createOffer(){
//发送offer和answer的函数,发送本地session描述
Connection.createOffer().then(offer => {
Connection.setLocalDescription(offer);
websocket.send(JSON.stringify({
"userid":userid,
"event": "offer",
"data": {
"sdp": offer
}
}));
});
} function createSocket(){
//websocket = null;
websocket = new WebSocket('wss://www.ecoblog.online/wss');
eventBind();
};
function eventBind() {
//连接成功
websocket.onopen = function(e) {
console.log('连接成功')
};
//server端请求关闭
websocket.onclose = function(e) {
console.log('close')
};
//error
websocket.onerror = function(e) { };
//收到消息
websocket.onmessage = (event)=> {
if(event.data == "new user") {
location.reload();
} else {
var json = JSON.parse(event.data);
console.log('onmessage: ', json);
if(json.userid !=userid){
//如果是一个ICE的候选,则将其加入到PeerConnection中,否则设定对方的session描述为传递过来的描述
if(json.event === "_ice_candidate"&&json.data.candidate) {
Connection.addIceCandidate(new RTCIceCandidate(json.data.candidate));
}else if(json.event ==='offer'){
Connection.setRemoteDescription(json.data.sdp);
Connection.createAnswer().then(answer => {
Connection.setLocalDescription(answer);
console.log(window.stream)
websocket.send(JSON.stringify({
"userid":userid,
"event": "answer",
"data": {
"sdp": answer
}
}));
})
}else if(json.event ==='answer'){
Connection.setRemoteDescription(json.data.sdp);
console.log(window.stream) }
}
}
};
}
建立连接的过程:
1⃣️两个浏览器都打开该页面,连接到同一个socket('wss://www.ecoblog.online/wss');
注意:webrtc只能在localhost或者https下使用,所以线上环境的话,我们的socket服务以及html页面都必须是要有https证书的;
对于wss,利用反向代理,在nginx的站点配置下如下配置/wss:
正如你所看到的那样,socket服务开在12345端口,所以还要去阿里云网站开一个这个端口的出入站规则;
另外centos的防火墙对该端口开放,或者直接关闭防火墙(自行百度)
socket服务写得比较简陋,但已够用,功能就是把收到的信息发给当前连接的所有c端
2⃣️两个c端已经和socket建立连接,然后任意其中一端点击“建立连接”
此时点击建立连接的端就是offer(携带信号源信息),发给另外一个端,另外一个端收到offer之后,发出响应answer(携带信号源信息),offer端收到answer端信息进行存储;
这样每个端都有了自己的信息和对方的信息,
3⃣️candidata信息的发送
其实这块,网上有的说法是offer发出answer发出后设置了localDescription和remoteDescription后就会触发onicecandidate,但是我测试的时候貌似没有,所以
我这里是在获取摄像头信息后通过
Connection.addStream(stream)
来触发Connection.onicecandidate,在这个事件监听的回调里,发出自身端的candidata给对方,如此一来,双方都有了对方的localDescription、remoteDescription和candidata;
三者齐全之后,就会触发Connection.onaddstream,这样,直接通过:
theirVideo.srcObject = e.stream;
把流写到video里面去,这样就能展示对方的视频信息了:
但是这样,只能在局域网内使用,如果要在公网使用的话,还要一个穿透服务器,网上找的一些免费的好像都不能用了?还是说我写得有问题?
具体的可百度,webrtc搭建stun服务器
webrtc实现点对点视频通讯的更多相关文章
- webrtc笔记(3): 多人视频通讯常用架构Mesh/MCU/SFU
问题:为什么要搞这么多架构? webrtc虽然是一项主要使用p2p的实时通讯技术,本应该是无中心化节点的,但是在一些大型多人通讯场景,如果都使用端对端直连,端上会遇到很带宽和性能的问题,所以就有了下图 ...
- 使用WebRTC搭建前端视频聊天室——点对点通信篇
WebRTC给我们带来了浏览器中的视频.音频聊天体验.但个人认为,它最实用的特性莫过于DataChannel——在浏览器之间建立一个点对点的数据通道.在DataChannel之前,浏览器到浏览器的数据 ...
- 使用WebRTC搭建前端视频聊天室——信令篇
博客原文地址 建议看这篇之前先看一下使用WebRTC搭建前端视频聊天室——入门篇 如果需要搭建实例的话可以参照SkyRTC-demo:github地址 其中使用了两个库:SkyRTC(github地址 ...
- JMeter扩展Java请求实现WebRTC本地音视频推流压测脚本
WebRTC是Web Real-Time Communication缩写,指网页即时通讯,是一个支持Web浏览器进行实时语音或视频对话的API,实现了基于网页的视频会议,比如声网的Agora Web ...
- 使用WebRTC搭建前端视频聊天室——数据通道篇
本文翻译自WebRTC data channels 在两个浏览器中,为聊天.游戏.或是文件传输等需求发送信息是十分复杂的.通常情况下,我们需要建立一台服务器来转发数据,当然规模比较大的情况下,会扩展成 ...
- 使用WebRTC搭建前端视频聊天室
在两个浏览器中,为聊天.游戏.或是文件传输等需求发送信息是十分复杂的.通常情况下,我们需要建立一台服务器来转发数据,当然规模比较大的情况下,会扩展成多个数据中心.这种情况下很容易出现很高的延迟,同时难 ...
- WebRTC:一个视频聊天的简单例子
相关API简介 在前面的章节中,已经对WebRTC相关的重要知识点进行了介绍,包括涉及的网络协议.会话描述协议.如何进行网络穿透等,剩下的就是WebRTC的API了. WebRTC通信相关的API非常 ...
- WebRTC搭建前端视频聊天室——数据通道篇
本文翻译自WebRTC data channels 在两个浏览器中,为聊天.游戏.或是文件传输等需求发送信息是十分复杂的.通常情况下,我们需要建立一台服务器来转发数据,当然规模比较大的情况下,会扩展成 ...
- springboot+kurento+coturn+contos的视频通讯服务搭建
springboot+kurento+coturn+contos的视频通讯服务搭建 服务器CentOS Linux release 7.9.2009 (Core) 本案例成功于20210628 1.默 ...
随机推荐
- kotlin字符串和数字之间的转换和人机交互
继续基础学习~ 字符串和数字之间的转换 那如何转换呢,其实很简单: 编译木有报错,但是运行: 所以这里了解下. 人机交互 看这标题貌似高端的,其实也就是程序可以接受键盘的输入啦,下面开始: 首先提示用 ...
- hbase单机搭建
一.下载 https://hbase.apache.org/downloads.html 2.1.3版本 解压,拷贝到文件夹 /hbase/hbase-2.1.3 设置HBASE_HOME环境变量,把 ...
- 为什么重写equals()方法就必须重写hashCode()方法
hashCode()和equals()保持一致,如果equals方法返回true,那么两个对象的hasCode()返回值必须一样.如果equals方法返回false,hashcode可以不一样,但是这 ...
- 使用idea 搭建一个 SpringBoot + Mybatis + logback 的maven 项目
(注意项目名不能有大写......),把项目类型 改成 War 类型.(web项目) 使用 mybatis-generator 插件 生成 实体类 和 接口 在 resources 目录 中 新建一个 ...
- axios时遇到的Request Method: OPTIONS
前言 在请求axios 请求数据的时候,会出现options的,是因为请求是分为简单请求和复杂请求. 简单请求 满足下面两个条件的请求是简单请求: 请求方式是以下三种之一: HEAD GET POST ...
- ESP8266—“ICACHE_FLASH_ATTR”宏
问:ESP8266_NONOS_SDK中ICACHE_FLASH_ATTR宏的用途是什么?我看到它取决于ICACHE_FLASH,但我不知道何时应该定义该符号.什么时候需要包括它?答:对于ESP826 ...
- 第十一章 前端开发-bootstrap
11.5.0 bootstrap 11.5.1 bootstrap的介绍和响应式 http://book.luffycity.com/python-book/95-bootstrap/951-boot ...
- Netty入门 零基础
因为接下来的项目要用到netty,所以就了解一下这个程序,奈何网上的教程都是稍微有点基础的,所以,就写一篇对于netty零基础的,顺便也记录一下. 先扔几个参考学习的网页: netty 官方API: ...
- jenkins 中MultiJob Phase的使用,简单的pipeline可以用这个写
- 配置Multipath多路径环境
iscsi服务器 eth0:192.168.4.5/24 eth1:192.168.2.5/24 iscsi客户端 eth0:192.168.4.100/24 eth3:201 ...