WebRTC - APIs RTCPeerConnection

A API RTCPeerConnection é o núcleo da conexão ponto a ponto entre cada um dos navegadores. Para criar os objetos RTCPeerConnection, basta escrever

var pc = RTCPeerConnection(config);

onde o argumento de configuração contém pelo menos uma chave, iceServers. É uma matriz de objetos de URL que contém informações sobre os servidores STUN e TURN, usados ​​durante a localização dos candidatos ICE. Você pode encontrar uma lista de servidores STUN públicos disponíveis em code.google.com

Dependendo se você é o chamador ou o receptor, o objeto RTCPeerConnection é usado de uma maneira ligeiramente diferente em cada lado da conexão.

Aqui está um exemplo do fluxo do usuário -

  • Registre o manipulador onicecandidate . Ele envia quaisquer candidatos ICE ao outro par, conforme são recebidos.

  • Registre o manipulador onaddstream . Ele lida com a exibição do fluxo de vídeo, uma vez que é recebido do par remoto.

  • Registre o manipulador de mensagens . Seu servidor de sinalização também deve ter um manipulador para mensagens recebidas de outro par. Se a mensagem contiver o objeto RTCSessionDescription , ela deverá ser adicionada ao objeto RTCPeerConnection usando o método setRemoteDescription () . Se a mensagem contiver o objeto RTCIceCandidate , ela deverá ser adicionada ao objeto RTCPeerConnection usando o método addIceCandidate () .

  • Utilize getUserMedia () para configurar seu fluxo de mídia local e adicioná-lo ao objeto RTCPeerConnection usando o método addStream () .

  • Inicie o processo de negociação de oferta / resposta. Esta é a única etapa em que o fluxo do chamador é diferente do fluxo do receptor. O chamador inicia a negociação usando o método createOffer () e registra um retorno de chamada que recebe o objeto RTCSessionDescription . Então este callback deve adicionar este RTCSessionDescription objeto para seu RTCPeerConnection objeto usando setLocalDescription () . E, finalmente, o chamador deve enviar esta RTCSessionDescription para o ponto remoto usando o servidor de sinalização. O receptor, por outro lado, registra o mesmo retorno de chamada, mas no método createAnswer () . Observe que o fluxo do receptor é iniciado somente depois que a oferta é recebida do chamador.

API RTCPeerConnection

Propriedades

  • RTCPeerConnection.iceConnectionState (read only)- Retorna um enum RTCIceConnectionState que descreve o estado da conexão. Um evento iceconnectionstatechange é disparado quando esse valor muda. Os valores possíveis -

    • new - o agente ICE está esperando por candidatos remotos ou reunindo endereços

    • checking - o agente ICE tem candidatos remotos, mas ainda não encontrou uma conexão

    • connected - o agente ICE encontrou uma conexão utilizável, mas ainda está verificando um candidato remoto para uma conexão melhor.

    • completed - o agente ICE encontrou uma conexão utilizável e parou de testar candidatos remotos.

    • failed - o agente ICE verificou todos os candidatos remotos, mas não encontrou uma correspondência para pelo menos um componente.

    • disconnected - pelo menos um componente não está mais ativo.

    • closed - o agente ICE está fechado.

  • RTCPeerConnection.iceGatheringState (read only) - Retorna um RTCIceGatheringState enum que descreve o estado de coleta de ICE para a conexão -

    • new - o objeto acabou de ser criado.

    • gathering - o agente ICE está em processo de reunir candidatos

    • complete o agente ICE concluiu a reunião.

  • RTCPeerConnection.localDescription (read only)- Retorna um RTCSessionDescription que descreve a sessão local. Pode ser nulo se ainda não tiver sido definido.

  • RTCPeerConnection.peerIdentity (read only)- Retorna um RTCIdentityAssertion. Consiste em um idp (nome de domínio) e um nome que representa a identidade do par remoto.

  • RTCPeerConnection.remoteDescription (read only)- Retorne um RTCSessionDescription descrevendo a sessão remota. Pode ser nulo se ainda não tiver sido definido.

  • RTCPeerConnection.signalingState (read only)- Retorna um enum RTCSignalingState que descreve o estado de sinalização da conexão local. Este estado descreve a oferta SDP. Um evento signalingstatechange é disparado quando esse valor muda. Os valores possíveis -

    • stable- O estado inicial. Não há nenhuma troca de oferta / resposta SDP em andamento.

    • have-local-offer - o lado local da conexão aplicou localmente uma oferta SDP.

    • have-remote-offer - o lado remoto da conexão aplicou localmente uma oferta SDP.

    • have-local-pranswer - uma oferta SDP remota foi aplicada e uma pranswer SDP aplicada localmente.

    • have-remote-pranswer - um SDP local foi aplicado e uma pranswer SDP aplicada remotamente.

    • closed - a conexão é fechada.

Manipuladores de eventos

S.No. Manipuladores de eventos e descrição
1

RTCPeerConnection.onaddstream

Este manipulador é chamado quando o evento addstream é disparado. Este evento é enviado quando um MediaStream é adicionado a esta conexão pelo par remoto.

2

RTCPeerConnection.ondatachannel

Este manipulador é chamado quando o evento datachannel é disparado. Este evento é enviado quando um RTCDataChannel é adicionado a esta conexão.

3

RTCPeerConnection.onicecandidate

Este manipulador é chamado quando o evento icecandidate é disparado. Este evento é enviado quando um objeto RTCIceCandidate é adicionado ao script.

4

RTCPeerConnection.oniceconnectionstatechange

Este manipulador é chamado quando o evento iceconnectionstatechange é disparado. Este evento é enviado quando o valor de iceConnectionState muda.

5

RTCPeerConnection.onidentityresult

Este manipulador é chamado quando o evento identityresult é disparado. Este evento é enviado quando uma asserção de identidade é gerada durante a criação de uma oferta ou uma resposta de via getIdentityAssertion ().

6

RTCPeerConnection.onidpassertionerror

Este manipulador é chamado quando o evento idpassertionerror é disparado. Este evento é enviado quando o IdP (Provedor de Identidade) encontra um erro ao gerar uma declaração de identidade.

7

RTCPeerConnection.onidpvalidation

Este manipulador é chamado quando o evento idpvalidationerror é disparado. Este evento é enviado quando o IdP (Identitry Provider) encontra um erro ao validar uma declaração de identidade.

8

RTCPeerConnection.onnegotiationneeded

Este manipulador é chamado quando o evento negotiationneeded é disparado. Este evento é enviado pelo navegador para informar que a negociação será necessária em algum momento no futuro.

9

RTCPeerConnection.onpeeridentity

Este manipulador é chamado quando o evento peeridentity é disparado. Este evento é enviado quando uma identidade de par foi definida e verificada nesta conexão.

10

RTCPeerConnection.onremovestream

Esse manipulador é chamado quando o evento signalingstatechange é disparado. Este evento é enviado quando o valor de signalingState muda.

11

RTCPeerConnection.onsignalingstatechange

Este manipulador é chamado quando o evento removestream é disparado. Este evento é enviado quando um MediaStream é removido desta conexão.

Métodos

S.No. Métodos e Descrição
1

RTCPeerConnection()

Retorna um novo objeto RTCPeerConnection.

2

RTCPeerConnection.createOffer()

Cria uma oferta (solicitação) para encontrar um par remoto. Os dois primeiros parâmetros desse método são callbacks de sucesso e erro. O terceiro parâmetro opcional são opções, como habilitar fluxos de áudio ou vídeo.

3

RTCPeerConnection.createAnswer()

Cria uma resposta à oferta recebida pelo par remoto durante o processo de negociação de oferta / resposta. Os dois primeiros parâmetros desse método são callbacks de sucesso e erro. O terceiro parâmetro opcional são opções para a resposta a ser criada.

4

RTCPeerConnection.setLocalDescription()

Altera a descrição da conexão local. A descrição define as propriedades da conexão. A conexão deve ser capaz de suportar descrições antigas e novas. O método usa três parâmetros, objeto RTCSessionDescription, retorno de chamada se a alteração da descrição for bem-sucedida, retorno de chamada se a alteração da descrição falhar.

5

RTCPeerConnection.setRemoteDescription()

Altera a descrição da conexão remota. A descrição define as propriedades da conexão. A conexão deve ser capaz de suportar descrições antigas e novas. O método usa três parâmetros, objeto RTCSessionDescription, retorno de chamada se a alteração da descrição for bem-sucedida, retorno de chamada se a alteração da descrição falhar.

6

RTCPeerConnection.updateIce()

Atualiza o processo do agente ICE de fazer ping de candidatos remotos e reunir candidatos locais.

7

RTCPeerConnection.addIceCandidate()

Fornece um candidato remoto para o agente ICE.

8

RTCPeerConnection.getConfiguration()

Retorna um objeto RTCConfiguration. Ele representa a configuração do objeto RTCPeerConnection.

9

RTCPeerConnection.getLocalStreams()

Retorna uma matriz de conexão MediaStream local.

10

RTCPeerConnection.getRemoteStreams()

Retorna uma matriz de conexão MediaStream remota.

11

RTCPeerConnection.getStreamById()

Retorna MediaStream local ou remoto pelo ID fornecido.

12

RTCPeerConnection.addStream()

Adiciona um MediaStream como fonte local de vídeo ou áudio.

13

RTCPeerConnection.removeStream()

Remove um MediaStream como fonte local de vídeo ou áudio.

14

RTCPeerConnection.close()

Fecha uma conexão.

15

RTCPeerConnection.createDataChannel()

Cria um novo RTCDataChannel.

16

RTCPeerConnection.createDTMFSender()

Cria um novo RTCDTMFSender, associado a um MediaStreamTrack específico. Permite enviar sinalização de telefone DTMF (Dual-tone multifrequency) pela conexão.

17

RTCPeerConnection.getStats()

Cria um novo RTCStatsReport que contém estatísticas sobre a conexão.

18

RTCPeerConnection.setIdentityProvider()

Define o IdP. Aceita três parâmetros - o nome, o protocolo usado para se comunicar e um nome de usuário opcional.

19

RTCPeerConnection.getIdentityAssertion()

Reúne uma afirmação de identidade. Não se espera lidar com esse método no aplicativo. Portanto, você pode chamá-lo explicitamente apenas para antecipar a necessidade.

Estabelecendo uma conexão

Agora vamos criar um aplicativo de exemplo. Em primeiro lugar, execute o servidor de sinalização que criamos no tutorial “servidor de sinalização” via “servidor de nó”.

Haverá duas entradas de texto na página, uma para um login e outra para um nome de usuário ao qual desejamos nos conectar. Crie um arquivo index.html e adicione o seguinte código -

<html lang = "en"> 
   <head> 
      <meta charset = "utf-8" /> 
   </head>
	
   <body> 
	
      <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>
		
   </body>
	
</html>

Você pode ver que adicionamos a entrada de texto para um login, o botão de login, a entrada de texto para o outro nome de usuário do par e o botão conectar-se a ele. Agora crie um arquivo client.js e adicione o seguinte código -

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)); 
};

Você pode ver que estabelecemos uma conexão de socket com nosso servidor de sinalização. Quando um usuário clica no botão de login, o aplicativo envia seu nome de usuário para o servidor. Se o login for bem-sucedido, o aplicativo cria o objeto RTCPeerConnection e configura o manipulador onicecandidate que envia todos os icecandidates encontrados para o outro par. Agora abra a página e tente fazer o login. Você deve ver a seguinte saída do console -

A próxima etapa é criar uma oferta para o outro par. Adicione o seguinte código ao seu arquivo 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)); 
}

Você pode ver que quando um usuário clica no botão “Estabelecer conexão”, o aplicativo faz uma oferta SDP ao outro par. Nós também definir onAnswer e onCandidate manipuladores. Recarregue a sua página, abra-a em duas abas, faça o login com dois usuários e tente estabelecer uma conexão entre eles. Você deve ver a seguinte saída do console -

Agora a conexão ponto a ponto foi estabelecida. Nos próximos tutoriais, adicionaremos streams de vídeo e áudio, bem como suporte para chat de texto.