这篇翻译不完整。请帮忙从英语翻译这篇文章。
当你理解 WebRTC架构之后,你就可以阅读本篇文章了。本篇文章将带领你贯穿整个跨浏览器RTC应用的创建过程。到本章结束的时候,你就拥有了一个可以运行的点对点的数据通道和媒体通道。
本页的案例过期了!不要再尝试他们了。
注意
由于近期API做了一些修改,一些比较老的案例需要修复,暂时不可用。
当前可以正常工作的的案例是:
正确的实现方式或许可以从标准中推断出来。
本页包含的其余的过期的信息,在bugzilla。
Shims
就像你想的那样,这样前卫的API肯定需要浏览器前缀才可以,然后再将它转换成通用的变量。
var RTCPeerConnection = window.mozRTCPeerConnection || window.webkitRTCPeerConnection; var IceCandidate = window.mozRTCIceCandidate || window.RTCIceCandidate; var SessionDescription = window.mozRTCSessionDescription || window.RTCSessionDescription; navigator.getUserMedia = navigator.getUserMedia || navigator.mozGetUserMedia || navigator.webkitGetUserMedia;
RTCPeerConnection
这是使用peer创建连接的起始点。它接收一个配置选项,其中配置了用来创建连接的ICE服务器信息。
var pc = new RTCPeerConnection(configuration);
RTCConfiguration
RTCConfiguration
对象包含了一些信息,这些信息是关于用来做ICE的TURN和/或STUN服务器的。这是用来确保大多数用户可以避免因NAT和防火墙导致的无法建立连接。
var configuration = { iceServers: [ {urls: "stun:23.21.150.121"}, {urls: "stun:stun.l.google.com:19302"}, {urls: "turn:numb.viagenie.ca", credential: "webrtcdemo", username: "louis%40mozilla.com"} ] }
Google运行了一个我们可以使用的公共STUN服务器。我也在https://numb.viagenie.ca/ 创建了一个免费的可以访问TURN服务器的账户。可能你也想这么做,你只要替换到你自己的许可证书就可以了。
ICECandidate
创建好PeerConnection并传入可用的STUN和TURN之后,当ICE框架找到可以使用Peer创建连接的“候选者”,会立即触发一个事件(onicecandidate)。这些“候选者”就是ICECandidate,而且他们会在PeerConnection#onicecandidate事件中执行一个回调函数。
pc.onicecandidate = function (e) {
// candidate exists in e.candidate
if (!e.candidate) return;
send("icecandidate", JSON.stringify(e.candidate));
};
回调函数执行之后,我们必须使用信令通道(signal channel)将候选发送到其他的点。在Chrome中,ICE框架一般会找到重复的候选者,所以,我一般只发送第一个,然后将处理函数删除。Firfox中将候选者包含在了Offer SDP中。
Signal Channel
现在我们有了ICE候选,然后需要将它发送到我们的另一端,以让它知道如何跟我们建立连接。然而,现在有一个先有鸡还是先有蛋的问题。我们想要PeerConnection发送数据到另一端,但是在那之前我们需要先把元数据发送过去……
现在就是用到信令通道(Signal Channel)的时候了。它的任何一个数据传输方法都允许两个端点之间交换信息。在本文中,我们将使用FireBase。因为它设置起来灰常简单,并且不需要任何主机或者服务器端的代码编写。
现在我们想象只有两个两个方法:send(), 它将使用一个键,然后将数据赋值给它;recv() ,当一个键有值的时候会调用一个处理函数。
数据库的结构就像下面这样:
{
"": {
"candidate:": …
"offer": …
"answer": …
}
}
连接会被roomId分割,然后会保存四条信息:发起者(oferer)的ICE候选、应答者(answerer)的ICE候选、offer SDP 和 answer SDP.
Offer
Offer SDP是用来向另一端描述期望格式(视频, 格式, 解编码, 加密, 解析度, 尺寸 等等)的元数据。
一次信息的交换需要从一端拿到offer,然后另外一端接受这个offer然后返回一个answer。
pc.createOffer(function (offer) {
pc.setLocalDescription(offer, function() {
send("offer", JSON.stringify(pc.localDescription);
}, errorHandler);
}, errorHandler, options);
errorHandler
创建offer的过程如果出现问题,就会执行这个函数,并且将错误的详细信息作为第一个参数。
var errorHandler = function (err) {
console.error(err);
};
options
Offer SDP 的选项.
var options = {
offerToReceiveAudio: true,
offerToReceiveVideo: true
};
offerToReceiveAudio/Video
告诉另一端,你想接收视频还是音频。对于DataChannel来说,这些是不需要的。
offer创建好之后,我们必须将本地SDP设置进去,然后通过信令通道将它发送到另一端,之久就静静地等待另一端的Answer SDP吧.
Answer
Answer SDP跟offer是差不多的,只不过它是作为相应的。有点像接电话一样。我们只能在接收到offer的时候创建一次Answer.
recv("offer", function (offer) {
offer = new SessionDescription(JSON.parse(offer))
pc.setRemoteDescription(offer);
pc.createAnswer(function (answer) {
pc.setLocalDescription(answer, function() {
send("answer", JSON.stringify(pc.localDescription));
}, errorHandler);
}, errorHandler);
});
DataChannel
I will first explain how to use PeerConnection for the DataChannels API and transferring arbitrary data between peers.
Note: At the time of this article, interoperability between Chrome and Firefox is not possible with DataChannels. Chrome supports a similar but private protocol and will be supporting the standard protocol soon.
var channel = pc.createDataChannel(channelName, channelOptions);
The offerer should be the peer who creates the channel. The answerer will receive the channel in the callback ondatachannel
on PeerConnection. You must call createDataChannel()
once before creating the offer.
channelName
This is a string that acts as a label for your channel name. Warning: Make sure your channel name has no spaces or Chrome will fail on createAnswer()
.
channelOptions
var channelOptions = {};
Currently these options are not well supported on Chrome so you can leave this empty for now. Check the RFC for more information about the options.
Channel Events and Methods
onopen
Executed when the connection is established.
onerror
Executed if there is an error creating the connection. First argument is an error object.
channel.onerror = function (err) {
console.error("Channel Error:", err);
};
onmessage
channel.onmessage = function (e) {
console.log("Got message:", e.data);
}
The heart of the connection. When you receive a message, this method will execute. The first argument is an event object which contains the data, time received and other information.
onclose
Executed if the other peer closes the connection.
Binding the Events
If you were the creator of the channel (meaning the offerer), you can bind events directly to the DataChannel you created with createChannel
. If you are the answerer, you must use the ondatachannel
callback on PeerConnection to access the same channel.
pc.ondatachannel = function (e) {
e.channel.onmessage = function () { … };
};
The channel is available in the event object passed into the handler as e.channel
.
send()
channel.send("Hi Peer!");
This method allows you to send data directly to the peer! Amazing. You must send either String, Blob, ArrayBuffer or ArrayBufferView, so be sure to stringify objects.
close()
Close the channel once the connection should end. It is recommended to do this on page unload.
Media
Now we will cover transmitting media such as audio and video. To display the video and audio you must include a <video>
tag on the document with the attribute autoplay
.
Get User Media
<video id="preview" autoplay></video> var video = document.getElementById("preview"); navigator.getUserMedia(constraints, function (stream) { video.src = URL.createObjectURL(stream); }, errorHandler);
constraints
Constraints on what media types you want to return from the user.
var constraints = {
video: true,
audio: true
};
If you just want an audio chat, remove the video
member.
errorHandler
Executed if there is an error returning the requested media.
Media Events and Methods
addStream
Add the stream from getUserMedia
to the PeerConnection.
pc.addStream(stream);
onaddstream
<video id="otherPeer" autoplay></video> var otherPeer = document.getElementById("otherPeer"); pc.onaddstream = function (e) { otherPeer.src = URL.createObjectURL(e.stream); };
Executed when the connection has been setup and the other peer has added the stream to the peer connection with addStream
. You need another <video>
tag to display the other peer's media.
The first argument is an event object with the other peer's media stream.