webrtc网上封装的很多,demo很多都是一个页面里实现的,今天实现了个完整的 , A 发视频给 B。

1.) A 方

<!DOCTYPE html>
<html id="home" lang="en"> <head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<style> p { padding: 1em; } li {
border-bottom: 1px solid rgb(189, 189, 189);
border-left: 1px solid rgb(189, 189, 189);
padding: .5em;
} </style>
</head> <body> <script>
var mediaConstraints = {
optional: [],
mandatory: {
OfferToReceiveAudio: false,
OfferToReceiveVideo: true
}
};
</script>
<script>
var offerer
,answererWin window.RTCPeerConnection = window.mozRTCPeerConnection || window.webkitRTCPeerConnection;
window.RTCSessionDescription = window.mozRTCSessionDescription || window.RTCSessionDescription;
window.RTCIceCandidate = window.mozRTCIceCandidate || window.RTCIceCandidate; navigator.getUserMedia = navigator.mozGetUserMedia || navigator.webkitGetUserMedia;
window.URL = window.webkitURL || window.URL; window.iceServers = {
iceServers: [{
url: 'stun:23.21.150.121'
}
]
};
</script>
<script>
/* offerer */
function offererPeer(video_stream) {
offerer = new RTCPeerConnection(window.iceServers)
offerer.addStream(video_stream) offerer.onaddstream = function (event) {
// 本地显示video
} offerer.onicecandidate = function (event) {
if (!event || !event.candidate) return sendToP2({
'action' : 'candidate',
'candidate' :event.candidate
}) } offerer.createOffer(function (offer) {
offerer.setLocalDescription(offer)
sendToP2({
'action' : 'create',
'offer':offer
}) }, function() {}, mediaConstraints)
}
</script>
<script>
var video_constraints = {
mandatory: {},
optional: []
} function getUserMedia(callback) {
var n = navigator
n.getMedia = n.webkitGetUserMedia || n.mozGetUserMedia
n.getMedia({
audio: false,
video: video_constraints
}, callback, onerror) function onerror(e) {
alert(JSON.stringify(e, null, '\t'))
}
}
</script>
<script>
function sendToP2(data){
answererWin.postMessage(JSON.stringify(data) ,window.location) }
function receiveMessage(data){
data = JSON.parse(data.data)
switch ( data.action) {
case 'answer' :
offerer.setRemoteDescription(new RTCSessionDescription(data.answer))
break
case "candidate":
offerer.addIceCandidate(new RTCIceCandidate(data.candidate))
break }
console.log('msg' ,data)
} window.addEventListener("message", receiveMessage, false)
answererWin = window.open('answer.html' ,'t')
getUserMedia(function (video_stream) {
offererPeer(video_stream)
});
</script> </body> </html>

2.) B

<!DOCTYPE html>
<html id="home" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> </head> <body>
<article>
<div style="text-align:center;">
<div class="videos-container">
<video id="peer1-to-peer2" autoplay controls></video>
<h2>Offerer-to-Answerer</h2>
<h2>此页面刷新之后,必须重新刷新一下Offer页面</h2>
</div>
</div>
<script>
var mediaConstraints = {
optional: [],
mandatory: {
OfferToReceiveAudio: true,
OfferToReceiveVideo: true
}
};
</script>
<script>
var offerer, answerer;
var offererToAnswerer = document.getElementById('peer1-to-peer2'); window.RTCPeerConnection = window.mozRTCPeerConnection || window.webkitRTCPeerConnection;
window.RTCSessionDescription = window.mozRTCSessionDescription || window.RTCSessionDescription;
window.RTCIceCandidate = window.mozRTCIceCandidate || window.RTCIceCandidate; navigator.getUserMedia = navigator.mozGetUserMedia || navigator.webkitGetUserMedia;
window.URL = window.webkitURL || window.URL; window.iceServers = {
iceServers: [{
url: 'stun:23.21.150.121'
}
]
};
</script>
<script>
/* answerer */ function answererPeer(offer, video_stream) {
answerer = new RTCPeerConnection(window.iceServers);
// answerer.addStream(video_stream); answerer.onaddstream = function (event) {
offererToAnswerer.src = URL.createObjectURL(event.stream);
offererToAnswerer.play();
}; answerer.onicecandidate = function (event) {
if (!event || !event.candidate) return;
sendToP1({
'action' : 'candidate',
'candidate' :event.candidate
})
//offerer.addIceCandidate(event.candidate);
}; answerer.setRemoteDescription(new RTCSessionDescription(offer));
answerer.createAnswer(function (answer) {
answerer.setLocalDescription(answer);
sendToP1({
'action' : 'answer' ,
'answer' : answer
})
//offerer.setRemoteDescription(answer);
}, function() {}, mediaConstraints);
} function receiveMessage(data){
data = JSON.parse(data.data)
console.log(data)
switch(data.action){
case "create":
answererPeer(data.offer , data.stream)
break
case "candidate":
answerer.addIceCandidate(new RTCIceCandidate(data.candidate))
break
}
}
window.addEventListener("message", receiveMessage, false) function sendToP1(data) {
opener.postMessage(JSON.stringify(data) , window.location)
}
</script> </article> </body> </html>

demo用 postMessage传递数据, 业务使用可以用websocket

A 先 createOffer ,生成的offer 供自己setLocalDescription ,并发给B

B 拿A的offer ,setRemoteDescription(offer) , 然后 createAnswer ,生成的answer 供自己setLocalDescription ,并发给A

A 拿B的answer 设置 setRemoteDescription(answer)

A onicecandidate 事件被触发 将得到的通道发给B

B addIceCandidate(new RTCIceCandidate(candidate)) 建立通道

B onicecandidate 事件被触发 将得到的通道发给A

A addIceCandidate(new RTCIceCandidate(candidate)) 建立通道

通道建立后视频就可以共享了

使用时,打开:offer.html 即可。

6. webRTC的更多相关文章

  1. 使用WebRTC搭建前端视频聊天室——数据通道篇

    本文翻译自WebRTC data channels 在两个浏览器中,为聊天.游戏.或是文件传输等需求发送信息是十分复杂的.通常情况下,我们需要建立一台服务器来转发数据,当然规模比较大的情况下,会扩展成 ...

  2. 使用WebRTC搭建前端视频聊天室——点对点通信篇

    WebRTC给我们带来了浏览器中的视频.音频聊天体验.但个人认为,它最实用的特性莫过于DataChannel——在浏览器之间建立一个点对点的数据通道.在DataChannel之前,浏览器到浏览器的数据 ...

  3. 使用WebRTC搭建前端视频聊天室——信令篇

    博客原文地址 建议看这篇之前先看一下使用WebRTC搭建前端视频聊天室——入门篇 如果需要搭建实例的话可以参照SkyRTC-demo:github地址 其中使用了两个库:SkyRTC(github地址 ...

  4. 使用WebRTC搭建前端视频聊天室——入门篇

    http://segmentfault.com/a/1190000000436544 什么是WebRTC? 众所周知,浏览器本身不支持相互之间直接建立信道进行通信,都是通过服务器进行中转.比如现在有两 ...

  5. WebRTC的一个例子

    内容引自:一个WebRTC实现获取内网IP的例子(穿透NAT) 网页代码直接复制到下面(如果以上链接被墙,可以直接将下面代码保存文件,然后在浏览器打开即可,不支持IE浏览器): <!doctyp ...

  6. WebRTC音频预处理单元APM的整体编译及使用

    正文 行的gnu静态库链接路径是针对NDK版本 r8d 的,如读者版本不匹配,请自行找到 libgnustl_static.a 静态库的路径进行替换. 3)本示例并不打算编译 WebRTC 的测试工程 ...

  7. 单独编译使用WebRTC的音频处理模块

    块,每块个点,(12*64=768采样)即AEC-PC仅能处理48ms的单声道16kHz延迟的数据,而 - 加载编译好的NS模块动态库 接下来只需要按照 此文 的描述在 android 的JAVA代码 ...

  8. webrtc中APM(AudioProcessing module)的使用2

    这个其实就是从Audio_processing.h中拿出来的. APM should be placed in the signal chain as close to the audio hardw ...

  9. webrtc中APM(AudioProcessing module)的使用

    一,实例化和配置 AudioProcessing* apm = AudioProcessing::Create(0); //这里的0指的是channelID,只是一个标注那个通道的表示 apm-> ...

  10. WebRTC通信流程

    WebRTC是HTML5支持的重要特性之一,有了它,不再需要借助音视频相关的客户端,直接通过浏览器的Web页面就可以实现音视频对聊功能.而且WebRTC项目是开源的,我们可以借助WebRTC源码快速构 ...

随机推荐

  1. 使用sstream进行int转换string的注意事项

    个人网站 :http://39.106.25.239/ 1.引入sstream文件 2.使用stringstream 声明 3.使用一次sstream转换后要执行成员函数.clear() 来清除str ...

  2. TensorFlow v2.0实现逻辑斯谛回归

    使用TensorFlow v2.0实现逻辑斯谛回归 此示例使用简单方法来更好地理解训练过程背后的所有机制 MNIST数据集概览 此示例使用MNIST手写数字.该数据集包含60,000个用于训练的样本和 ...

  3. 技术大佬:我去,你竟然还在用 try–catch-finally

    二哥,你之前那篇 我去 switch的文章也特么太有趣了,读完后意犹未尽啊,要不要再写一篇啊?虽然用的是 Java 13 的语法,对旧版本不太友好.但谁能保证 Java 不会再来一次重大更新呢,就像 ...

  4. Python python 数据类型--集

    # set 集 '''Python还包括集合的数据类型.集合是无序集合,没有重复元素. 基本用途包括成员资格测试和消除重复条目. 集合对象还支持数学运算,如并集,交集,差异和对称差异. ''' nam ...

  5. Python python 五种数据类型--字典

    # 定义一个字典 var1 = {'a':20,'b':40}; var2 = dict(); print(type(var1)) print(type(var2)) # 长度 length = le ...

  6. Thinking in Java学习杂记(第7章)

    将一个方法调用同一个方法主体连接到一起就称为"绑定"(Binding).若在程序运行以前执行绑定,就叫做"早期绑定".而Java中绑定的所有方法都采用后期绑定技 ...

  7. centos7 编译安装mysql5.7

    mysql源码可以到官网下载 安装依赖包 yum -y install gcc gcc-c++ ncurses ncurses-devel bison libgcrypt perl make cmak ...

  8. WPF使用 Gmap.NET 绘制极坐标运动轨迹

    大家好,已经很久没有更新了,今天写一篇关于WPF 使用 Gmap.NET 相关的,网上很多Winform的很**,所以我给Wpf进行一些补充.虽然它已经很久没有更新了,但是也只能用这个了.没别的好选择 ...

  9. stm32:extern关键字

    参考:http://c.biancheng.net/view/404.html 1.在一个文件中: #include <stdio.h> int max(int x,int y); int ...

  10. PTA | 1005 继续(3n+1)猜想 (25分)

    卡拉兹(Callatz)猜想已经在1001中给出了描述.在这个题目里,情况稍微有些复杂. 当我们验证卡拉兹猜想的时候,为了避免重复计算,可以记录下递推过程中遇到的每一个数.例如对 n=3 进行验证的时 ...