WebRTC-RTCPeerConnection API



RTCPeerConnection API是每个浏览器之间对等连接的核心。要创建RTCPeerConnection对象,只需编写

var pc = RTCPeerConnection(config);

其中config参数至少包含密钥iceServers。它是URL对象的数组,其中包含有关ICE候选服务器的信息,用于查找ICE候选对象。您可以在code.google.com上找到可用的公共STUN服务器列表。

根据您是调用方还是被调用方,RTCPeerConnection对象在连接的两边使用的方式略有不同。

这是用户流程的示例-

  • 注册onicecandidate处理程序。接收到任何ICE候选者后,它将ICE候选者发送给其他对等体。

  • 注册onaddstream处理程序。一旦从远程对等方接收到视频流,它将处理视频流的显示。

  • 注册消息处理程序。您的信令服务器还应该具有一个处理程序,用于处理从其他对等方接收到的消息。如果消息包含RTCSessionDescription对象,则应使用setRemoteDescription()方法将其添加到RTCPeerConnection对象。如果消息包含RTCIceCandidate对象,则应使用addIceCandidate()方法将其添加到RTCPeerConnection对象。

  • 利用getUserMedia()设置本地媒体流,并使用addStream()方法将其添加到RTCPeerConnection对象。

  • 开始报价/答案协商过程。这是呼叫者的流程与被呼叫者的流程不同的唯一步骤。调用方使用createOffer()方法开始协商,并注册一个接收RTCSessionDescription对象的回调。然后,此回调应使用setLocalDescription()将此RTCSessionDescription对象添加到您的RTCPeerConnection对象。最后,调用者应使用信令服务器将此RTCSessionDescription发送到远程对等方。另一方面,被调用方在createAnswer()方法中注册了相同的回调。请注意,仅在收到来自主叫方的报价后,才启动被叫方流程。

RTCPeerConnection API

物产

  • RTCPeerConnection.iceConnectionState(只读) -返回描述连接状态的RTCIceConnectionState枚举。当该值更改时,将触发iceconnectionstatechange事件。可能的值-

    • -ICE代理正在等待远程候选者或收集地址

    • 检查-ICE代理具有远程候选者,但尚未找到连接

    • 已连接-ICE代理已找到可用的连接,但仍在检查更多的远程候选者以获得更好的连接。

    • 已完成-ICE代理已找到可用的连接,并停止测试远程候选对象。

    • 失败-ICE代理检查了所有远程候选者,但没有找到至少一个组件的匹配项。

    • 断开连接-至少一个组件不再活动。

    • 已关闭-ICE代理已关闭。

  • RTCPeerConnection.iceGatheringState(只读) -返回描述连接的ICE收集状态的RTCIceGatheringState枚举-

    • new-该对象刚刚创建。

    • 收集-ICE代理正在收集候选人

    • 完成ICE代理已完成收集。

  • RTCPeerConnection.localDescription(只读) -返回描述本地会话的RTCSessionDescription。如果尚未设置,则可以为null。

  • RTCPeerConnection.peerIdentity(只读) -返回RTCIdentityAssertion。它由一个idp(域名)和一个代表远程对等方身份的名称组成。

  • RTCPeerConnection.remoteDescription(只读) -返回描述远程会话的RTCSessionDescription。如果尚未设置,则可以为null。

  • RTCPeerConnection.signalingState(只读) -返回描述本地连接的信令状态的RTCSignalingState枚举。此状态描述了SDP报价。当此值更改时,将触发signalingstatechange事件。可能的值-

    • 稳定-初始状态。没有正在进行的SDP报价/答案交换。

    • have-local-offer-连接的本地已在本地应用了SDP报价。

    • 有远程报价-连接的远程端已在本地应用了SDP报价。

    • have-local-pranswer-已应用远程SDP报价,并在本地应用SDP pranswer。

    • have-remote-pranswer-已应用本地SDP,并且已远程应用SDP pranswer。

    • 已关闭-连接已关闭。

事件处理程序

S.No. Event Handlers & Description
1

RTCPeerConnection.onaddstream

This handler is called when the addstream event is fired. This event is sent when a MediaStream is added to this connection by the remote peer.

2

RTCPeerConnection.ondatachannel

This handler is called when the datachannel event is fired. This event is sent when a RTCDataChannel is added to this connection.

3

RTCPeerConnection.onicecandidate

This handler is called when the icecandidate event is fired. This event is sent when a RTCIceCandidate object is added to the script.

4

RTCPeerConnection.oniceconnectionstatechange

This handler is called when the iceconnectionstatechange event is fired. This event is sent when the value of iceConnectionState changes.

5

RTCPeerConnection.onidentityresult

This handler is called when the identityresult event is fired. This event is sent when an identity assertion is generated during the creating of an offer or an answer of via getIdentityAssertion().

6

RTCPeerConnection.onidpassertionerror

This handler is called when the idpassertionerror event is fired. This event is sent when the IdP (Identitry Provider) finds an error while generating an identity assertion.

7

RTCPeerConnection.onidpvalidation

This handler is called when the idpvalidationerror event is fired. This event is sent when the IdP (Identitry Provider) finds an error while validating an identity assertion.

8

RTCPeerConnection.onnegotiationneeded

This handler is called when the negotiationneeded event is fired. This event is sent by the browser to inform the negotiation will be required at some point in the future.

9

RTCPeerConnection.onpeeridentity

This handler is called when the peeridentity event is fired. This event is sent when a peer identity has been set and verified on this connection.

10

RTCPeerConnection.onremovestream

This handler is called when the signalingstatechange event is fired. This event is sent when the value of signalingState changes.

11

RTCPeerConnection.onsignalingstatechange

This handler is called when the removestream event is fired. This event is sent when a MediaStream is removed from this connection.

方法

S.No. Methods & Description
1

RTCPeerConnection()

Returns a new RTCPeerConnection object.

2

RTCPeerConnection.createOffer()

Creates an offer(request) to find a remote peer. The two first parameters of this method are success and error callbacks. The optional third parameter are options, like enabling audio or video streams.

3

RTCPeerConnection.createAnswer()

Creates an answer to the offer received by the remote peer during the offer/answer negotiation process. The two first parameters of this method are success and error callbacks. The optional third parameter are options for the answer to be created.

4

RTCPeerConnection.setLocalDescription()

Changes the local connection description. The description defines the properties of the connection. The connection must be able to support both old and new descriptions. The method takes three parameters, RTCSessionDescription object, callback if the change of description succeeds, callback if the change of description fails.

5

RTCPeerConnection.setRemoteDescription()

Changes the remote connection description. The description defines the properties of the connection. The connection must be able to support both old and new descriptions. The method takes three parameters, RTCSessionDescription object, callback if the change of description succeeds, callback if the change of description fails.

6

RTCPeerConnection.updateIce()

Updates the ICE agent process of pinging remote candidates and gathering local candidates.

7

RTCPeerConnection.addIceCandidate()

Provides a remote candidate to the ICE agent.

8

RTCPeerConnection.getConfiguration()

Returns a RTCConfiguration object. It represents the configuration of the RTCPeerConnection object.

9

RTCPeerConnection.getLocalStreams()

Returns an array of local MediaStream connection.

10

RTCPeerConnection.getRemoteStreams()

Returns an array of remote MediaStream connection.

11

RTCPeerConnection.getStreamById()

Returns local or remote MediaStream by the given ID.

12

RTCPeerConnection.addStream()

Adds a MediaStream as a local source of video or audio.

13

RTCPeerConnection.removeStream()

Removes a MediaStream as a local source of video or audio.

14

RTCPeerConnection.close()

Closes a connection.

15

RTCPeerConnection.createDataChannel()

Creates a new RTCDataChannel.

16

RTCPeerConnection.createDTMFSender()

Creates a new RTCDTMFSender, associated to a specific MediaStreamTrack. Allows to send DTMF (Dual-tone multifrequency) phone signaling over the connection.

17

RTCPeerConnection.getStats()

Creates a new RTCStatsReport that contains statistics concerning the connection.

18

RTCPeerConnection.setIdentityProvider()

Sets the IdP. Takes three parameters − the name, the protocol used to communicate and an optional username.

19

RTCPeerConnection.getIdentityAssertion()

Gathers an identity assertion. It is not expected to deal with this method in the application. So you may call it explicitly only to anticipate the need.

建立连接

现在让我们创建一个示例应用程序。首先,通过“节点服务器”运行在“信令服务器”教程中创建的信令服务器。

页面上将有两个文本输入,一个用于登录,另一个用于我们要连接的用户名。创建一个index.html文件并添加以下代码-

<meta charset="utf-8"> 
   
    
    
    
      <div> 
         <input type="text" id="loginInput"> 
         <button id="loginBtn">Login</button> 
      </div> 
    
      <div> 
         <input type="text" id="otherUsernameInput">
         <button id="connectToOtherUsernameBtn">Establish connection</button> 
      </div> 
        
      <script src="client2.js"></script>
        
   
    

可以看到,我们已经添加了用于登录的文本输入,登录按钮,用于其他对等用户名的文本输入以及“连接至他”按钮。现在创建一个client.js文件并添加以下代码-

var connection = new WebSocket('ws://localhost:9090'); 
var name = ""; 
 
var loginInput = document.querySelector('#loginInput'); 
var loginBtn = document.querySelector('#loginBtn'); 
var otherUsernameInput = document.querySelector('#otherUsernameInput'); 
var connectToOtherUsernameBtn = document.querySelector('#connectToOtherUsernameBtn'); 
var connectedUser, myConnection;
  
//when a user clicks the login button 
loginBtn.addEventListener("click", function(event){ 
   name = loginInput.value; 
    
   if(name.length > 0){ 
      send({ 
         type: "login", 
         name: name 
      }); 
   } 
    
});
  
//handle messages from the server 
connection.onmessage = function (message) { 
   console.log("Got message", message.data);
   var data = JSON.parse(message.data); 
    
   switch(data.type) { 
      case "login": 
         onLogin(data.success); 
         break; 
      case "offer": 
         onOffer(data.offer, data.name); 
         break; 
      case "answer": 
         onAnswer(data.answer); 
         break; 
      case "candidate": 
         onCandidate(data.candidate); 
         break; 
      default: 
         break; 
   } 
};
  
//when a user logs in 
function onLogin(success) { 

   if (success === false) { 
      alert("oops...try a different username"); 
   } else { 
      //creating our RTCPeerConnection object 
        
      var configuration = { 
         "iceServers": [{ "url": "stun:stun.1.google.com:19302" }] 
      }; 
        
      myConnection = new webkitRTCPeerConnection(configuration); 
      console.log("RTCPeerConnection object was created"); 
      console.log(myConnection); 
  
      //setup ice handling
      //when the browser finds an ice candidate we send it to another peer 
      myConnection.onicecandidate = function (event) { 
        
         if (event.candidate) { 
            send({ 
               type: "candidate", 
               candidate: event.candidate 
            }); 
         } 
      }; 
   } 
};
  
connection.onopen = function () { 
   console.log("Connected"); 
};
  
connection.onerror = function (err) { 
   console.log("Got error", err); 
};
  
// Alias for sending messages in JSON format 
function send(message) { 

   if (connectedUser) { 
      message.name = connectedUser; 
   } 
    
   connection.send(JSON.stringify(message)); 
};

您可以看到我们建立了到信令服务器的套接字连接。当用户单击登录按钮时,应用程序会将其用户名发送到服务器。如果登录成功,则应用程序将创建RTCPeerConnection对象并设置onicecandidate处理程序,该处理程序将所有找到的icecandidates发送到另一个对等方。现在打开页面并尝试登录。您应该看到以下控制台输出-

建立连接

下一步是向其他同伴创建要约。将以下代码添加到client.js文件中-

//setup a peer connection with another user 
connectToOtherUsernameBtn.addEventListener("click", function () { 
 
   var otherUsername = otherUsernameInput.value; 
   connectedUser = otherUsername;
    
   if (otherUsername.length > 0) { 
      //make an offer 
      myConnection.createOffer(function (offer) { 
         console.log(); 
         send({ 
            type: "offer", 
            offer: offer 
         });
            
         myConnection.setLocalDescription(offer); 
      }, function (error) { 
         alert("An error has occurred."); 
      }); 
   } 
}); 
 
//when somebody wants to call us 
function onOffer(offer, name) { 
   connectedUser = name; 
   myConnection.setRemoteDescription(new RTCSessionDescription(offer)); 
    
   myConnection.createAnswer(function (answer) { 
      myConnection.setLocalDescription(answer); 
        
      send({ 
         type: "answer", 
         answer: answer 
      }); 
        
   }, function (error) { 
      alert("oops...error"); 
   }); 
}
  
//when another user answers to our offer 
function onAnswer(answer) { 
   myConnection.setRemoteDescription(new RTCSessionDescription(answer)); 
} 
 
//when we got ice candidate from another user 
function onCandidate(candidate) { 
   myConnection.addIceCandidate(new RTCIceCandidate(candidate)); 
}    

您可以看到,当用户单击“建立连接”按钮时,应用程序向另一对等方发出SDP报价。我们还设置了onAnsweronCandidate处理程序。重新加载页面,在两个选项卡中打开它,使用两个用户登录并尝试在他们之间建立连接。您应该看到以下控制台输出-

控制台输出

现在,对等连接已建立。在接下来的教程中,我们将添加视频和音频流以及文本聊天支持。

Made with ❤️ in Chengdu. Copyright reserved 2019-2022.

蜀ICP备20006366号-1