Getting Started with WebRTC [note]
Getting Started with WebRTC
RTCPeerConnection
1.caller和callee互相发现彼此
2.并且交换capabilities信息
3.初始化session
4.开始实时交换数据
名词解释:
信令:在客户端之间传递控制信息,通过控制信息处理客户端之间的发现、连接建立、连接维护和连接关闭等任务的机制。
function initialize() {
console.log("Initializing; room=99688636.");
card = document.getElementById("card");
localVideo = document.getElementById("localVideo");
miniVideo = document.getElementById("miniVideo");
remoteVideo = document.getElementById("remoteVideo");
resetStatus();
openChannel('AHRlWrqvgCpvbd9B-Gl5vZ2F1BlpwFv0xBUwRgLF/* ...*/');/*room token 由Google App Engine app 提供*/
doGetUserMedia();//确认浏览器是否支持getUserMedia API 如果支持则调用onUserMediaSuccess
}
/* 建立通道过程
1.客户端A生成一个唯一的ID
2.客户端A把ID传给App Engine app,请求获得Channel token
3.App Engine app 把ID传给 Channel API,请求获得一个channel和token
4.App把token传给客户端A
5.客户端A打开socket,监听channel
*/
function openChannel(channelToken) {
console.log("Opening channel.");
var channel = new goog.appengine.Channel(channelToken);
var handler = {
'onopen': onChannelOpened,
'onmessage': onChannelMessage,
'onerror': onChannelError,
'onclose': onChannelClosed
};
socket = channel.open(handler);
}
/*Sending a message works like this: 1.Client B makes a POST request to the App Engine app with an update.
2.The App Engine app passes a request to the channel.
3.The channel carries a message to Client A.
4.Client A's onmessage callback is called.
*/
//如果浏览器支持getUserMedia,则函数被调用
function onUserMediaSuccess(stream) {
console.log("User has granted access to local media.");
// Call the polyfill wrapper to attach the media stream to this element.
attachMediaStream(localVideo, stream);//localVideo.src = ... localViedo代表一个标签
localVideo.style.opacity = 1;
localStream = stream;
// Caller creates PeerConnection.
if (initiator) maybeStart();//initiator 已经被设置为1,直到caller的session终止 所以这里会调用maybeStart
}
//connection只会被建立一次
//建立前提1.第一次建立 2.localStream已经准备好了,即本地视频 3.信令通道准备好了
function maybeStart() {
if (!started && localStream && channelReady) {
// ...调用func,使用STUN创建RTCPeerConnection(pc),设置各种事件监听函数
createPeerConnection();
// ...
pc.addStream(localStream);
started = true;
// Caller initiates offer to peer.
if (initiator)
doCall();
}
}
//被maybeStart调用
//主要目的是使用STUN服务器和回调函数onIceCandidata来建立connection
//为每一个RTCPeerConnection事件建立handlers
function createPeerConnection() {
var pc_config = {"iceServers": [{"url": "stun:stun.l.google.com:19302"}]};
try {
// Create an RTCPeerConnection via the polyfill (adapter.js).
pc = new RTCPeerConnection(pc_config);//在adapter.js中被包装过了
pc.onicecandidate = onIceCandidate;
console.log("Created RTCPeerConnnection with config:\n" + " \"" +
JSON.stringify(pc_config) + "\".");
} catch (e) {
console.log("Failed to create PeerConnection, exception: " + e.message);
alert("Cannot create RTCPeerConnection object; WebRTC is not supported by this browser.");
return;
} pc.onconnecting = onSessionConnecting;//log status messages作用
pc.onopen = onSessionOpened; //log status messages作用
pc.onaddstream = onRemoteStreamAdded; //log status messages作用
pc.onremovestream = onRemoteStreamRemoved;//为remoteVideo标签设置内容
}
//handler
function onRemoteStreamAdded(event) {
// ...
miniVideo.src = localVideo.src;
attachMediaStream(remoteVideo, event.stream);
remoteStream = event.stream;
waitForRemoteVideo();
}
//在maybeStart()调用createPeerConnection()之后, a call is intitiated by creating and offer and sending it to the callee
function doCall() {
console.log("Sending offer to peer.");
pc.createOffer(setLocalAndSendMessage, null, mediaConstraints);
}
//创建offer的过程和非信令的例子(caller callee都在一个浏览器内)类似。
//不同点:message被发送到远端(remote peer),giving a serialized SessionDescription
//不同点的功能有setLocalAndMessage()完成
//客户端配置信息叫做Session Description
function setLocalAndSendMessage(sessionDescription) {
// Set Opus as the preferred codec in SDP if Opus is present.
sessionDescription.sdp = preferOpus(sessionDescription.sdp);
pc.setLocalDescription(sessionDescription);
sendMessage(sessionDescription);
}
/*signaling with the Channel API*/
/*当createPeerConnection()成功创建RTCPeerConnetion后 回调函数onIceCandidate被调用:
发送收集来的candidates的信息
*/
function onIceCandidate(event) {
if (event.candidate) {
//使用XHR请求,客户端向服务器发送出站信息
sendMessage({type: 'candidate',
label: event.candidate.sdpMLineIndex,
id: event.candidate.sdpMid,
candidate: event.candidate.candidate});
} else {
console.log("End of candidates.");
}
}
//使用XHR请求,从客户端向服务器发送出站消息(Outbound messaging)
function sendMessage(message) {
var msgString = JSON.stringify(message);
console.log('C->S: ' + msgString);
path = '/message?r=99688636' + '&u=92246248';
var xhr = new XMLHttpRequest();
xhr.open('POST', path, true);
xhr.send(msgString);
}
/*
客户端->服务器发送信令消息:使用XHR
服务器->客户端发送信令消息:使用Google App Engine Channel API
*/
//处理由App Engine server发送来的消息
function processSignalingMessage(message) {
var msg = JSON.parse(message); if (msg.type === 'offer') {
// Callee creates PeerConnection
if (!initiator && !started)//initiator代表session是否创建 RTCPeerConnection是否被创建
maybeStart(); pc.setRemoteDescription(new RTCSessionDescription(msg));
doAnswer();
} else if (msg.type === 'answer' && started) {
pc.setRemoteDescription(new RTCSessionDescription(msg));
} else if (msg.type === 'candidate' && started) {
var candidate = new RTCIceCandidate({sdpMLineIndex:msg.label,
candidate:msg.candidate});
pc.addIceCandidate(candidate);//??
} else if (msg.type === 'bye' && started) {
onRemoteHangup();
}
}
function doAnswer() {
console.log("Sending answer to peer.");
pc.createAnswer(setLocalAndSendMessage, null, mediaConstraints);
}
//在哪里设置msg.type?
Getting Started with WebRTC [note]的更多相关文章
- Build Android Webrtc Libjingle Library On Ubuntu
Our team is developing an app to help people solve problem face to face. We choose webrtc protocol a ...
- A Study of WebRTC Security
转自:http://webrtc-security.github.io/ A Study of WebRTC Security Abstract Web Real-Time Communication ...
- WebRTC音视频引擎研究(1)--整体架构分析
WebRTC技术交流群:234795279 原文地址:http://blog.csdn.net/temotemo/article/details/7530504 1.WebRTC目的 ...
- WebRTC is for Losers:WebRTC是输家
该文章是引述,仅代表作者Dave Michels观点 WebRTC is for Losers WebRTC technology has fallen short on many of its pr ...
- Android IOS WebRTC 音视频开发总结(七)-- 基于浏览器的开发
前面写的一系列总结都是讲webrtc如何下载,编译,开发的,有些人可能有点云里雾里了,WEBRTC不是用来搞跨浏览器开发的吗,怎么我讲的这些跟浏览器扯不上任何关系,其实看看下面这个架构图,你就明白了, ...
- webrtc学习——RTCPeerConnection
The RTCPeerConnection interface represents a WebRTC connection and handles efficient streaming of da ...
- WebRTC 音视频开发之路
早在2014年就通过WebRTC实现了PC客户端的实时视频语音,那时P2P连接的建立使用的WebRTC自带的libjingle库,使用peerconnection的API实现的.后来在做远程桌面,文件 ...
- webrtc之视频显示模块--video_render
在上一篇博文中,简单介绍了webrtc为我们提供了跨平台的视频采集模块,这篇博文也简单介绍下webrtc为我们提供的跨平台的视频显示模块:video_render. 该模块的源码结构如下: 如上图,我 ...
- webrtc之视频捕获模块--video_capture
webrtc的video_capture模块,为我们在不同端设备上采集视频提供了一个跨平台封装的视频采集功能,如下图中的webrtc的video_capture源码,现webrtc的video_cap ...
随机推荐
- NSDate和NSString相互转换
一.NSDate转NSString //获取系统当前时间 NSDate *currentDate = [NSDate date]; //用于格式化NSDate对象 NSDateFormatter *d ...
- jQuery的input 失去焦点之后,不能再获取到焦点
今天写了一个字段唯一性校验功能,验证设备仪器编号唯一,当输入编号之后 ,点击其他,失去焦点后,后台验证唯一,有过此编号,就给出提示,重新填写. 当使用ie时候,获取焦点正常 ,但是使用火狐就获取不到焦 ...
- Only the sqlmigrate and sqlflush commands can be used when an app has migrations.
samcao@samcao-Lenovo-IdeaPad-Y470:~/caodjango/caossh$ python manage.py sqlall getssh System check id ...
- MySQL中优化常用的查询sql语
1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索 ...
- VBA学习之关于数据透视表的应用
工作中很多地方需要同时处理多个数据表,而且用数据透视表进行排版,排序,计算字段,一个一个的做非常累,这里给出批量处理的方法. 学习VBA之前最好懂一点点VB的基础知识,因为里面的很多语法问题都是由VB ...
- python学习之路-day12-mysql && orm
一.数据库 1.数据库介绍 数据库(Database)是按照数据结构来组织.存储和管理数据的仓库,每个数据库都有一个或多个不同的API用于创建,访问,管理,搜索和复制所保存的数据.我们也可以将数据存储 ...
- ue4 模块的构建和加载
ue4的代码是模块的形式来组织 在源码层面,一个包含*.build.cs的目录就是一个模块 这个目录里的文件在编译后都会被链接在一起,比如一个静态库lib,或者一个动态库dll. 不管是哪种形式,都需 ...
- SQL关于limit的用法
SELECT * FROM table LIMIT [offset,] rows | rows OFFSET offset 在我们使用查询语句的时候,经常要返回前几条或者中间某几行数据,这个时 ...
- Linux下使用Eclipse开发Hadoop应用程序
在前面一篇文章中介绍了如果在完全分布式的环境下搭建Hadoop0.20.2,现在就再利用这个环境完成开发. 首先用hadoop这个用户登录linux系统(hadoop用户在前面一篇文章中创建的),然后 ...
- discuz MVC结构分析
Discuz软件经解压后产生的三个文件夹中的一个叫upload的成为网站的根目录.里面的内容可以在某些网站上在线阅读,如用好库编程网.也可以离线在本地阅读,如用VS.Php for Visual St ...