webrtc 视频 demo

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

A webrtc.html作为offer

<!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-scal
able=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.webkit
RTCPeerConnection;
window.RTCSessionDescription = window.mozRTCSessionDescription || windo
w.RTCSessionDescription;
window.RTCIceCandidate = window.mozRTCIceCandidate || window.RTCIceCand
idate; navigator.getUserMedia = navigator.mozGetUserMedia || navigator.webkitG
etUserMedia;
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(ne
w RTCSessionDescription(data.answer))
break
case "candidate":
offerer.addIceCandidate(new RTC
IceCandidate(data.candidate))
break }
console.log('msg' ,data)
} window.addEventListener("message", receiveMessage, fals
e)
answererWin = window.open('webrtc2.html' ,'t')
getUserMedia(function (video_stream) {
offererPeer(video_stream)
});
</script> </body> </html>

B webrtc2.html 作为answer

<!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">
<link rel="stylesheet" href="https://www.webrtc-experiment.com/style.css"> <style>
audio, video {
-moz-transition: all 1s ease;
-ms-transition: all 1s ease; -o-transition: all 1s ease;
-webkit-transition: all 1s ease;
transition: all 1s ease;
vertical-align: top;
} p { padding: 1em; } li {
border-bottom: 1px solid rgb(189, 189, 189);
border-left: 1px solid rgb(189, 189, 189);
padding: .5em;
} .videos-container {
display: inline-block;
border: 2px solid black;
padding: .1em;
border-radius: 0.2em;
margin: 2em .2em;
background: white;
vertical-align: top;
}
.videos-container h2 {
border: 0;
border-top: 1px solid black;
margin: 0;
text-align: center;
display:block;
}
video {
width:20em;
height: 15em;
background: black;
}
</style>
<!-- for HTML5 el styling -->
<script>
document.createElement('article');
</script>
</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> </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)) 建立通道

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

参考网址

http://www.html5rocks.com/en/tutorials/webrtc/basics/?redirect_from_locale=fr
https://github.com/muaz-khan/WebRTC-Experiment/blob/master/demos/client-side.html

webrtc 视频 demo的更多相关文章

  1. WebRTC 视频对话

    今天聊一下WebRTC.很多开发者,可能会觉得有些陌生,或者直接感觉繁杂.因为WebRTC在iOS上的应用,只是编译都让人很是头痛.这些话,到此为止,以防让了解者失去信心.我们只传播正能量,再多的困难 ...

  2. Android IOS WebRTC 音视频开发总结(七五)-- WebRTC视频通信中的错误恢复机制

    本文主要介绍WebRTC视频通信中的错误恢复机制(我们翻译和整理的,译者:jiangpeng),最早发表在[这里] 支持原创,转载必须注明出处,欢迎关注我的微信公众号blacker(微信ID:blac ...

  3. 5分钟快速打造WebRTC视频聊天<转>

    原文地址: 5分钟快速打造WebRTC视频聊天 百度一下WebRTC,我想也是一堆.本以为用这位朋友( 搭建WebRtc环境 )的SkyRTC-demo 就可以一马平川的实现聊天,结果折腾了半天,文本 ...

  4. WebRTC视频分辨率设置

    前面我们能够打开摄像头.getUserMedia()时会传入参数,在参数里我们可以指定宽高信息.通过宽高参数控制输出的视频分辨率. html 在页面上摆放一些元素,下面是主要部分 <div id ...

  5. Android WebRTC视频旋转问题

    最近在对接WebRTC到安卓手机上,有个需求就是手机横屏时将对方图像进行旋转,研究了WebRTC video_render的代码后发现远端的视频渲染使用opengles20或surfaceview实现 ...

  6. 动手搭建第一个小程序音视频Demo

    欢迎大家前往云+社区,获取更多腾讯海量技术实践干货哦~ 作者:小程序音视频产品经理 腾讯云提供了全套技术文档和源码来帮助您快速构建一个音视频小程序,但是再好的源码和文档也有学习成本,为了尽快的能调试起 ...

  7. 5分钟快速打造WebRTC视频聊天

    百度一下WebRTC,我想也是一堆.本以为用这位朋友( 搭建WebRtc环境 )的SkyRTC-demo 就可以一马平川的实现聊天,结果折腾了半天,文本信息都发不出去,更别说视频了.于是自己动手. 想 ...

  8. Android使用VideoView播放本地视频及网络视频Demo

    1.xm文件 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:and ...

  9. webRTC peerconnection_client demo创建VS工程

    编译了webRTC Windows源码之后,想使用编译出来的库写一个demo出来,但是又不知到怎么下手.就想通过源码中带的示例peerconnection_client和peerconnection_ ...

随机推荐

  1. Android PopupWindow使用时注意

    项目中使用PopupWindown出现的坑 1.部分设备,PopWindow在Android4.0后版本,出现NullPointerException调用以下方法可解决, fixPopupWindow ...

  2. 远程监视jboss应用java内存的配置(实测) .

    前言 因为最近一个项目部署在客户那边运行一个月左右就会出现java内存溢出的问题,为了时时监控java内存的情况需要,需要远程查看服务器上java内存的一些情况.在公司模拟部署了远程监视linux下项 ...

  3. JavaScript 单例,Hash,抛异常

    1. 单例 ECMA 5 版 记得以前写过几种单例实现,找不到了... function Singleton() { if (this.constructor.instance) { return t ...

  4. [oracle]表空间情况查看、占用、扩容、使用情况、空间维护等操作

    --查询表空间使用情况SELECT Upper(F.TABLESPACE_NAME)         "表空间名",       D.TOT_GROOTTE_MB          ...

  5. java虚拟机(八)--java性能监控与故障处理工具

    问题定位: 除了个人经验,知识,工具也是很重要的,通过数据进行问题分析,包括:运行日志.异常堆栈.GC日志.线程快照(threaddump/javacore文件 ).堆转储快照(heapdump/hp ...

  6. JavaScipt30(第十八个案例)(主要知识点:Array.prototype.map)

    承接上文,这是第十八个案例,中间的十到十八我直接看了答案,因为有些例子从他打开的页面看不出他要做什么. 附上项目链接: https://github.com/wesbos/JavaScript30 这 ...

  7. python队列的实现

    队列是一种抽象数据结构,具有以下特点: (1)具有先进先出的特性(FIFO) (2)拥有两种基本操作,即加入和删除,而且使用front和rear两个指针来分别指向队列的前端和末尾. 队列的基本操作 c ...

  8. Java图形界面GUI

    Java图形界面GUI 设置窗体JFrame对象 package com.Aha.Best; import javax.swing.ImageIcon; import javax.swing.JFra ...

  9. Python爬虫:抓取手机APP的数据

    摘要 大多数APP里面返回的是json格式数据,或者一堆加密过的数据 .这里以超级课程表APP为例,抓取超级课程表里用户发的话题. 1.抓取APP数据包 表单: 表单中包括了用户名和密码,当然都是加密 ...

  10. 第二节:SQLServer导出-重置sa密码-常用sql语句

    1.SQLServer导出: 点击要导出数据库----->右键(任务)----->生成脚本----->下一步----->下一步(高级)要编写脚本的数据类型---选择架构和数据 ...