Tecnologia WebRTC: chat de áudio e vídeo no navegador. Bate-papo por vídeo P2P baseado em WebRTC WebRTC por um desenvolvedor web

A maior parte do material sobre WebRTC concentra-se no nível de aplicação de escrever código e não contribui para a compreensão da tecnologia. Vamos tentar ir mais a fundo e descobrir como ocorre a conexão, qual é o descritor de sessão e os candidatos, quais são ATORDOAR e VIRAR servidor.

WebRTC

Introdução

WebRTC é uma tecnologia baseada em navegador que permite conectar dois clientes para transmissão de dados de vídeo. Os principais recursos são o suporte interno ao navegador (sem necessidade de tecnologias incorporadas de terceiros, como adobe flash) e a capacidade de conectar clientes sem usar servidores adicionais - conexão pessoa para pessoa(Mais longe, p2p).

Estabeleça uma conexão p2p- uma tarefa bastante difícil, uma vez que os computadores nem sempre têm IP endereços, ou seja, endereços na Internet. Devido à pequena quantidade IPv4 endereços (e para fins de segurança) foi desenvolvido um mecanismo NAT, que permite criar redes privadas, por exemplo, para uso doméstico. Muitos roteadores domésticos agora suportam NAT e graças a isso, todos os dispositivos domésticos têm acesso à Internet, embora os provedores de Internet geralmente forneçam um IP Morada. público IP Os endereços são únicos na Internet, mas os endereços privados não. Então conecte p2p- difícil.

Para entender melhor, considere três situações: ambos os nós estão na mesma rede (Imagem 1), ambos os nós estão em redes diferentes (um em privado, o outro em público) (Imagem 2) e ambos os nós estão em redes privadas diferentes com o mesmo IP endereços (Figura 3).

Figura 1: Ambos os nós na mesma rede

Figura 2: Nós em redes diferentes (um em privado, um em público)

Figura 3: Nós em redes privadas diferentes, mas com endereços numericamente iguais

Nas figuras acima, a primeira letra na notação de dois caracteres indica o tipo de nó (p = par, r = roteador). Na primeira figura, a situação é favorável: os nós em sua rede são completamente identificados por rede IP endereços e, portanto, podem se conectar diretamente. Na segunda figura, temos duas redes diferentes que possuem números de nós semelhantes. Aqui aparecem roteadores (roteadores), que possuem duas interfaces de rede - dentro de sua rede e fora de sua rede. Portanto, eles têm dois IP endereços. Os nós regulares têm apenas uma interface através da qual eles só podem se comunicar em sua própria rede. Se eles transmitirem dados para alguém fora de sua rede, somente com a ajuda de NAT dentro do roteador (roteador) e, portanto, visível para outras pessoas sob IP endereço do roteador é o seu externo IP Morada. Assim, o nó p1interior IP = 192.168.0.200 e externo IP = 10.50.200.5 , com o último endereço sendo externo a todos os outros hosts em sua rede também. A situação é semelhante para o nó p2. Portanto, sua conexão é impossível se apenas o seu interno (próprio) IP endereços. Você pode usar endereços externos, ou seja, endereços de roteadores, mas como todos os nós da mesma rede privada têm o mesmo endereço externo, isso é bastante difícil. Este problema é resolvido pelo mecanismo NAT

O que acontecerá se ainda decidirmos conectar os nós por meio de seus endereços internos? Os dados não sairão da rede. Para aumentar o efeito, você pode imaginar a situação mostrada na última figura - ambos os nós possuem os mesmos endereços internos. Se eles os usarem para se comunicar, cada nó se comunicará consigo mesmo.

WebRTC lida com sucesso com esses problemas usando o protocolo GELO, que, no entanto, requer o uso de servidores adicionais ( ATORDOAR, VIRAR). Tudo isso abaixo.

Duas fases do WebRTC

Para conectar dois nós por meio de um protocolo WebRTC(ou simplesmente RTC se dois estão conectados Iphone'a) algumas etapas preliminares devem ser tomadas para estabelecer uma conexão. Esta é a primeira fase - estabelecer uma conexão. A segunda fase é a transmissão de dados de vídeo.

Deve-se dizer desde já que, embora a tecnologia WebRTC usa muitos métodos de comunicação diferentes em seu trabalho ( TCP e UDP) e possui alternância flexível entre eles, essa tecnologia não tem um protocolo para passar dados de conexão. Não é surpreendente, porque conecta dois nós p2p não tão fácil. Portanto, é necessário ter alguns adicional método de transferência de dados, não relacionado a WebRTC. Pode ser uma transferência de socket, protocolo http, pode até ser um protocolo SMTP ou correio russo. Este mecanismo de transmissão primário dados são chamados sinal. Não é necessário transferir muita informação. Todos os dados são transmitidos como texto e são divididos em dois tipos - SDP e Candidato a Gelo. O primeiro tipo é usado para estabelecer uma conexão lógica e o segundo para uma conexão física. Mais sobre isso mais tarde, mas por enquanto, é importante lembrar que WebRTC nos dará algumas informações que precisarão ser transmitidas para outro nó. Assim que tivermos transmitido todas as informações necessárias, os nós poderão se conectar e nossa ajuda não será mais necessária. Então, o mecanismo de sinalização que precisamos implementar separadamente, será usado somente quando conectado, e não será usado ao transmitir dados de vídeo.

Então vamos olhar para a primeira fase, a fase de configuração da conexão. É composto por vários itens. Considere esta fase primeiro para o nó que inicia a conexão e depois para o de espera.

  • Iniciador (chamador - chamador):
    1. Oferta para iniciar a transmissão de dados de vídeo (createOffer)
    2. Obtendo seu SDP SDP)
    3. Obtendo seu Candidato a gelo Candidato a gelo)
  • Chamada em espera ( chamado):
    1. Obtendo um fluxo de mídia local (próprio) e configurando-o para transmissão (getUserMediaStream)
    2. Receba uma oferta para iniciar uma transferência de dados de vídeo e crie uma resposta (createAnswer)
    3. Obtendo seu SDP objeto e passando-o através do mecanismo de sinalização ( SDP)
    4. Obtendo seu Candidato a gelo objetos e sua transmissão através do mecanismo de sinalização ( Candidato a gelo)
    5. Recebendo um fluxo de mídia remoto (estrangeiro) e exibindo-o na tela (onAddStream)

A única diferença está no segundo parágrafo.

Apesar da aparente complexidade das etapas, na verdade existem três delas: enviar seu próprio fluxo de mídia (p. 1), definir parâmetros de conexão (p. 2-4), receber o fluxo de mídia de outra pessoa (p. 5). O mais difícil é o segundo passo, pois consiste em duas partes: estabelecer fisica e lógico conexões. A primeira indica caminho, ao longo do qual os pacotes devem ir para ir de um nó de rede para outro. A segunda indica parâmetros de vídeo/áudio- que qualidade usar, que codecs usar.

Palco mental criarOferta ou criarResposta deve ser conectado aos estágios de transferência SDP e Candidato a gelo objetos.

Entidades básicas

Fluxos de mídia (MediaStream)

A entidade principal é o fluxo de mídia, ou seja, o fluxo de dados de vídeo e áudio, imagem e som. Existem dois tipos de fluxos de mídia - local e remoto. O local recebe dados dos dispositivos de entrada (câmera, microfone) e o remoto pela rede. Assim, cada nó tem uma thread local e uma remota. NO WebRTC existe uma interface para streams fluxo de mídia e há também uma subinterface LocalMediaStream especificamente para thread local. NO JavaScript você só pode encontrar o primeiro, e se você usar lib jingle, então o segundo também pode ser encontrado.

NO WebRTC há uma hierarquia bastante confusa dentro do segmento. Cada fluxo pode consistir em várias faixas de mídia ( faixa de mídia), que por sua vez pode consistir em vários canais de mídia ( Canal de mídia). E também pode haver vários fluxos de mídia.

Vamos considerar tudo em ordem. Para fazer isso, vamos ter em mente alguns exemplos. Digamos que queremos transmitir não apenas um vídeo nosso, mas também um vídeo da nossa mesa, na qual está um pedaço de papel no qual vamos escrever algo. Vamos precisar de dois vídeos (nós + mesa) e um áudio (nós). É claro que nós e a tabela devemos ser divididos em threads diferentes, porque esses dados provavelmente são fracamente dependentes um do outro. Portanto teremos dois fluxo de mídia‘a – um para nós e outro para a mesa. O primeiro conterá dados de vídeo e áudio e o segundo conterá apenas vídeo (Figura 4).

Figura 4: Dois fluxos de mídia diferentes. Um para nós, um para a nossa mesa

Fica imediatamente claro que o fluxo de mídia deve incluir pelo menos a capacidade de conter dados de diferentes tipos - vídeo e áudio. Isso é levado em consideração na tecnologia e, portanto, cada tipo de dado é implementado por meio de uma trilha de mídia. faixa de mídia. A faixa de mídia tem uma propriedade especial Gentil, que determina o que está à nossa frente - vídeo ou áudio (Figura 5)

Figura 5: Os fluxos de mídia são compostos de faixas de mídia

Como será tudo no programa? Vamos criar dois fluxos de mídia. Em seguida, criaremos duas faixas de vídeo e uma faixa de áudio. Vamos ter acesso a câmeras e um microfone. Vamos dizer a cada faixa qual dispositivo usar. Vamos adicionar uma faixa de vídeo e áudio ao primeiro fluxo de mídia e uma faixa de vídeo de outra câmera ao segundo fluxo de mídia.

Mas como distinguimos os fluxos de mídia na outra extremidade da conexão? Para fazer isso, cada fluxo de mídia tem uma propriedade etiqueta– rótulo do stream, seu nome (Figura 6). As faixas de mídia têm a mesma propriedade. Embora à primeira vista pareça que o vídeo pode ser distinguido do som de outras maneiras.

Figura 6: fluxos de mídia e faixas são identificados por rótulos

Então, e se as faixas de mídia podem ser identificadas por meio de um rótulo, por que precisamos usar dois fluxos de mídia para nosso exemplo, em vez de um? Afinal, você pode transferir um fluxo de mídia e usar faixas diferentes nele. Chegamos a uma propriedade importante dos fluxos de mídia - eles sincronizar faixas de mídia. Diferentes fluxos de mídia não são sincronizados entre si, mas dentro de cada fluxo de mídia todas as faixas jogado ao mesmo tempo.

Assim, se queremos que nossas palavras, nossas emoções no rosto e nosso pedaço de papel sejam reproduzidos ao mesmo tempo, vale a pena usar um fluxo de mídia. Se isso não for tão importante, é mais lucrativo usar fluxos diferentes - a imagem será mais suave.

Se uma faixa precisar ser desativada durante a transmissão, você poderá usar a propriedade ativado faixas de mídia.

No final, você deve pensar em som estéreo. Como você sabe, o som estéreo é dois sons diferentes. E eles também precisam ser enviados separadamente. Os canais são usados ​​para isso. Canal de mídia. Uma faixa de mídia de áudio pode ter muitos canais (por exemplo, 6 se você precisar de áudio 5+1). Dentro da faixa de mídia, canais, é claro, também sincronizado. Para vídeo, geralmente apenas um canal é usado, mas vários podem ser usados, por exemplo, para sobreposições de publicidade.

Para resumir: usamos um fluxo de mídia para transmitir dados de vídeo e áudio. Dentro de cada fluxo de mídia, os dados são sincronizados. Podemos usar vários fluxos de mídia se não precisarmos de sincronização. Dentro de cada fluxo de mídia existem dois tipos de faixas de mídia - para vídeo e para áudio. Geralmente não há mais de duas faixas, mas pode haver mais se você precisar transferir vários vídeos diferentes (do interlocutor e sua mesa). Cada faixa pode consistir em vários canais, que geralmente são usados ​​apenas para som estéreo.

Na situação mais simples de bate-papo por vídeo, teremos um fluxo de mídia local, que consistirá em duas faixas - uma faixa de vídeo e uma faixa de áudio, cada uma consistindo em um canal principal. A trilha de vídeo é responsável pela câmera, a trilha de áudio pelo microfone e o fluxo de mídia é o contêiner de ambos.

Descritor de Sessão (SDP)

Computadores diferentes sempre terão câmeras, microfones, placas de vídeo e outros equipamentos diferentes. Há muitas opções que eles têm. Tudo isso deve ser coordenado para transferência de dados de mídia entre dois nós de rede. WebRTC faz isso automaticamente e cria um objeto especial - o identificador de sessão SDP. Passe este objeto para outro nó e você poderá enviar dados de mídia. Só que ainda não há conexão com outro nó.

Para isso, qualquer mecanismo de sinalização é usado. SDP pode ser transmitido mesmo através de soquetes, até mesmo por uma pessoa (informe-o a outro nó por telefone), até mesmo por correio russo. Tudo é muito simples - você receberá uma SDP e precisa ser enviado. E após o recebimento do outro lado - transferência para o departamento WebRTC. O identificador de sessão é armazenado como texto e você pode alterá-lo em seus aplicativos, mas geralmente não é necessário. Por exemplo, ao conectar o desktop↔phone, às vezes você precisa forçar a seleção do codec de áudio desejado.

Normalmente, ao estabelecer uma conexão, você deve especificar algum endereço, por exemplo URL. Não há necessidade disso aqui, pois você mesmo enviará os dados para o destino por meio do mecanismo de sinalização. Indicar WebRTC o que queremos instalar p2p conexão, você precisa chamar a função createOffer. Depois de chamar esta função e dar-lhe um especial ligue de volta‘um será criado SDP objeto e passado para o mesmo ligue de volta. Tudo o que é exigido de você é transferir esse objeto pela rede para outro nó (interlocutor). Depois disso, na outra ponta, os dados virão através do mecanismo de sinalização, ou seja, este SDP um objeto. Este descritor de sessão é estranho a este nó e, portanto, carrega informações úteis. O recebimento deste objeto é um sinal para iniciar a conexão. Portanto, você deve concordar com isso e chamar a função createAnswer. É um análogo completo de createOffer . De volta ao seu ligue de volta passará um descritor de sessão local e precisará ser passado de volta pelo mecanismo de sinalização.

Vale a pena notar que você pode chamar a função createAnswer somente depois de receber o SDP objeto. Por quê? Porque local SDP o objeto que será gerado quando createAnswer for chamado deve contar com o controle remoto SDP um objeto. Somente neste caso é possível coordenar suas configurações de vídeo com as configurações do interlocutor. Além disso, não chame createAnswer e createOffer até que o fluxo de mídia local seja recebido - eles não terão nada para gravar SDP um objeto .

Desde em WebRTCé possível editar SDP objeto, então depois de obter um identificador local, ele deve ser definido. Pode parecer um pouco estranho passar WebRTC o que ela mesma nos deu, mas esse é o protocolo. Ao receber um identificador remoto, você também deve defini-lo. Portanto, você deve instalar dois descritores em um nó - o seu próprio e o de outra pessoa (ou seja, local e remoto).

Depois de tal apertos de mão nós sabem sobre os desejos uns dos outros. Por exemplo, se o nó 1 suporta codecs UMA e B, e o nó 2 suporta codecs B e C, então, como cada nó conhece seus próprios descritores e os de outro, ambos os nós escolherão um codec B(Figura 7). A lógica de conexão agora está estabelecida e os fluxos de mídia podem ser transmitidos, mas há outro problema - os nós ainda estão conectados apenas por um mecanismo de sinalização.


Figura 7: Negociação de codecs

Candidatos (candidato de gelo)

Tecnologia WebRTC tentando nos confundir com sua nova metodologia. Ao estabelecer uma conexão, o endereço do nó com o qual você deseja se conectar não é especificado. Instalado primeiro lógico conexão, não fisica, embora o contrário sempre tenha sido feito. Mas isso não parecerá estranho, se não esquecermos que usamos um mecanismo de sinalização de terceiros.

Portanto, a conexão já foi estabelecida (conexão lógica), mas ainda não há como os nós da rede transmitirem dados. Não é tão simples assim, mas vamos começar simples. Deixe os nós estarem na mesma rede privada. Como já sabemos, eles podem se conectar facilmente uns aos outros através de seus IP endereços (ou talvez algum outro, se não for usado TCP/IP).

Através de alguns ligue de volta'e WebRTC diga-nos Candidato a gelo objetos. Eles também vêm em formato textual e, assim como com os descritores de sessão, eles só precisam ser enviados através do mecanismo de sinalização. Se o descritor de sessão contiver informações sobre nossas configurações no nível da câmera e do microfone, os candidatos conterão informações sobre nossa localização na rede. Passe-os para outro nó, e ele poderá se conectar fisicamente a nós e, como já possui um descritor de sessão, ele poderá se conectar logicamente e os dados “fluirão”. Se ele não se esquecer de nos enviar seu objeto candidato, ou seja, informações sobre onde ele está na rede, poderemos nos conectar com ele. Notamos aqui mais uma diferença da interação cliente-servidor clássica. A comunicação com o servidor HTTP ocorre de acordo com o esquema de solicitação-resposta, o cliente envia os dados para o servidor, que os processa e os envia via endereço especificado no pacote de solicitação. NO WebRTC precisa saber dois endereços e conecte-os em ambos os lados.

A diferença dos identificadores de sessão é que apenas os candidatos remotos precisam ser definidos. A edição é proibida aqui e não pode trazer nenhum benefício. Em algumas implementações WebRTC os candidatos só precisam ser definidos depois que os identificadores de sessão forem definidos.

E por que havia apenas um descritor de sessão, mas pode haver muitos candidatos? Como a localização na rede pode ser determinada não apenas por sua IP endereço, mas também o endereço externo do roteador, e não necessariamente um, bem como os endereços VIRAR servidores. O restante do parágrafo será dedicado a uma discussão detalhada de candidatos e como conectar nós de diferentes redes privadas.

Assim, dois nós estão na mesma rede (Figura 8). Como identificá-los? Usando IP endereços. Não há outro jeito. É verdade que você ainda pode usar transportes diferentes ( TCP e UDP) e portas diferentes. Esta é a informação contida no objeto candidato - IP, PORTA, TRANSPORTE e alguns outros. Vamos, por exemplo, usar UDP transporte e 531 porta.

Figura 8: Dois nós estão na mesma rede

Então, se estamos em um nó p1, então WebRTC nos dará um objeto candidato - . Este não é um formato exato, mas apenas um diagrama. Se estamos em um nó p2, então o candidato é . Através do mecanismo de sinalização p1 vai receber um candidato p2(ou seja, localização do nó p2, ou seja, seu IP e PORTA). Então p1 pode se conectar com p2 diretamente. Mais correto, p1 enviará dados para o endereço 10.50.150.3:531 na esperança de que alcancem p2. Não importa se este endereço pertence a um nó p2 ou algum intermediário. A única coisa importante é que os dados serão enviados através deste endereço e podem chegar p2.

Desde que os nós estejam na mesma rede - tudo é simples e fácil - cada nó tem apenas um objeto candidato (sempre significando o seu próprio, ou seja, sua localização na rede). Mas haverá muito mais candidatos quando os nós estiverem em diferente redes.

Vamos para um caso mais complicado. Um nó estará atrás do roteador (mais precisamente, atrás do NAT), e o segundo nó estará na mesma rede com este roteador (por exemplo, na Internet) (Figura 9).

Figura 9: Um host atrás do NAT, outro não

Este caso tem uma solução particular para o problema, que agora consideramos. Um roteador doméstico geralmente contém uma tabela NAT. Este é um mecanismo especial projetado para permitir que nós dentro da rede privada do roteador acessem, por exemplo, sites.

Vamos supor que o servidor web esteja conectado diretamente à Internet, ou seja, possui um IP* Morada. Que seja um nó p2. Nó p1(cliente web) envia uma solicitação para o endereço 10.50.200.10 . Primeiro, os dados vão para o roteador r1, ou melhor, em seu interior interface 192.168.0.1 . Depois disso, o roteador lembra o endereço de origem (endereço p1) e o insere em uma tabela especial NAT, em seguida, altera o endereço de origem para seu próprio ( p1 r1). Além disso, de acordo com externo interface, o roteador envia dados diretamente para o servidor web p2. O servidor web processa os dados, gera uma resposta e a envia de volta. Envia para o roteador r1, já que é ele quem está no endereço de retorno (o roteador mudou o endereço para o seu próprio). O roteador recebe dados, olha para a tabela NAT e envia os dados para o nó p1. O roteador atua como um intermediário aqui.

Mas e se vários nós da rede interna acessarem a rede externa ao mesmo tempo? Como o roteador entenderá para quem enviar a resposta? Este problema é resolvido com portas. Quando o roteador substitui o endereço do host pelo seu próprio, ele também substitui a porta. Se dois nós acessarem a Internet, o roteador substituirá suas portas de origem por vários. Então, quando o pacote do servidor web voltar ao roteador, o roteador entenderá pela porta à qual esse pacote está atribuído. Um exemplo está abaixo.

Voltar para Tecnologia WebRTC, ou melhor, à sua parte que utiliza GELO protocolo (daí Gelo candidatos). Nó p2 tem um candidato (sua localização na rede - 10.50.200.10 ) e o nó p1, que está localizado atrás de um roteador com NAT, terá dois candidatos - local ( 192.168.0.200 ) e candidato a roteador ( 10.50.200.5 ). O primeiro não é útil, mas é gerado, pois WebRTC ainda não sabe nada sobre o host remoto - ele pode ou não estar na mesma rede. O segundo candidato será útil e, como já sabemos, o porto desempenhará um papel importante (para passar NAT).

Entrada de tabela NAT gerado apenas quando os dados saem da rede interna. Portanto, o nó p1 deve primeiro transmitir os dados e só depois os dados do nó p2 pode chegar ao nó p1.

Na prática ambos os nós estará para trás NAT. Para criar uma entrada em uma tabela NAT cada roteador, os nós devem enviar algo para o nó remoto, mas desta vez nem o primeiro pode alcançar o segundo, nem vice-versa. Isso se deve ao fato de os nós não conhecerem seus IP endereços e enviar dados para endereços internos não tem sentido.

No entanto, se os endereços externos forem conhecidos, a conexão será facilmente estabelecida. Se o primeiro nó enviar dados para o roteador do segundo nó, o roteador os ignorará, pois sua tabela NAT enquanto vazio. No entanto, no roteador do primeiro nó da tabela NAT havia necessidade de um registro. Se agora o segundo nó enviar dados para o roteador do primeiro nó, o roteador os transmitirá com sucesso ao primeiro nó. Agora a mesa NAT o segundo roteador tem os dados que você precisa.

O problema é que para conhecer o seu IP endereço, você precisa de um nó localizado em uma rede comum. Para resolver esse problema, são usados ​​servidores adicionais que estão diretamente conectados à Internet. Com a ajuda deles, os registros preciosos na tabela também são criados. NAT.

Servidores STUN e TURN

Na inicialização WebRTC acessível ATORDOAR e VIRAR servidores, aos quais nos referimos como GELO servidores. Se os servidores não forem especificados, apenas nós na mesma rede (conectados a ela sem NAT). Deve-se notar imediatamente que para 3g-redes devem ser usadas VIRAR servidores.

ATORDOAR servidoré simplesmente um servidor na Internet que retorna um endereço de retorno, ou seja, o endereço do host do remetente. O nó atrás do roteador acessa ATORDOAR servidor para passar NAT. O pacote que veio ATORDOAR server, contém o endereço de origem - o endereço do roteador, ou seja, o endereço externo do nosso nó. Este endereço ATORDOAR servidor e envia de volta. Assim, o nó obtém sua IP endereço e porta através da qual é acessível a partir da rede. Mais longe, WebRTC o uso desse endereço cria um candidato adicional (endereço e porta do roteador externo). Agora na mesa NAT o roteador tem uma entrada que passa os pacotes enviados ao roteador na porta necessária para o nosso nó.

Vejamos este processo com um exemplo.

Exemplo (operação do servidor STUN)

ATORDOAR o servidor será indicado por s1. Roteador, como antes, através r1, e o nó por p1. Você também precisará seguir a tabela NAT- vamos denotar como r1_nat. Além disso, essa tabela geralmente contém muitas entradas de diferentes nós de sub-rede - elas não serão fornecidas.

Então, no início temos uma tabela vazia r1_nat.

Tabela 2: Cabeçalho do pacote

p1 envia este pacote para o roteador r1(não importa como, diferentes tecnologias podem ser usadas em diferentes sub-redes). O roteador precisa fazer uma substituição do endereço de origem src IP, uma vez que o endereço especificado no pacote obviamente não é adequado para a sub-rede externa, além disso, os endereços desse intervalo são reservados e nenhum endereço na Internet possui esse endereço. O roteador faz uma substituição no pacote e cria uma nova entrada em sua tabela r1_nat. Para fazer isso, ele precisa encontrar um número de porta. Lembre-se de que, como vários nós em uma sub-rede podem acessar uma rede externa, na tabela NAT informações adicionais devem ser armazenadas para que o roteador possa determinar a qual desses vários hosts o pacote de retorno do servidor é destinado. Deixe o roteador criar uma porta 888 .

Cabeçalho do pacote alterado:

Tabela 4: Tabela NAT atualizada com uma nova entrada

Aqui IP o endereço e a porta da sub-rede são exatamente os mesmos do pacote original. De fato, no postback, devemos ter uma maneira de restaurá-los completamente. IP o endereço da rede externa é o endereço do roteador, e a porta foi alterada para aquela inventada pelo roteador.

A porta real para a qual o nó p1 aceita uma conexão - isso, é claro, 35777 , mas o servidor envia dados para fictício porta 888 , que será alterado pelo roteador para o real 35777 .

Assim, o roteador alterou o endereço de origem e a porta no cabeçalho do pacote e adicionou uma entrada à tabela NAT. Agora o pacote é enviado pela rede para o servidor, ou seja, o nó s1. na entrada, s1 tem este pacote:

src IP Src PORTA IP de destino PORTO DE DESTINO
10.50.200.5 888 12.62.100.200 6000

Tabela 5: O servidor STUN recebeu um pacote

Total ATORDOAR o servidor sabe que recebeu um pacote do endereço 10.50.200.5:888 . Agora o servidor envia esse endereço de volta. Vale a pena parar por aqui e revisitar o que acabamos de considerar. As tabelas acima fazem parte cabeçalho pacote, não a partir dele contente. Não falamos sobre o conteúdo, pois não é tão importante - está de alguma forma descrito no protocolo ATORDOAR. Agora vamos considerar além do título também o conteúdo. Será simples e conterá o endereço do roteador - 10.50.200.5:888 embora tivéssemos tirado de cabeçalho pacote. Isso não é feito com frequência, geralmente os protocolos não se preocupam com as informações sobre os endereços dos nós, é importante apenas que os pacotes sejam entregues ao seu destino. Aqui consideramos um protocolo que estabelece um caminho entre dois nós.

Então agora temos um segundo lote indo na direção oposta:

Tabela 7: O servidor STUN envia um pacote com este conteúdo

Em seguida, o pacote percorre a rede até atingir a interface externa do roteador r1. O roteador entende que o pacote não é destinado a ele. Como ele entende isso? Isso só pode ser encontrado pela porta. Porta 888 ele não usa para seus propósitos pessoais, mas usa para o mecanismo NAT. Portanto, o roteador examina essa tabela. olha a coluna PORTA Externa e procura uma string que corresponda PORTO DE DESTINO do pacote recebido, ou seja, 888 .

IP interno Porta Interna IP externo PORTA Externa
192.168.0.200 35777 10.50.200.5 888

Tabela 8: Tabela NAT

Temos sorte que tal linha existe. Se não tivesse sorte, o pacote seria simplesmente descartado. Agora você precisa entender qual dos nós da sub-rede deve enviar este pacote. Não tenhamos pressa, vamos recapitular a importância das portas nesse mecanismo. Ao mesmo tempo, dois nós na sub-rede podem enviar solicitações para a rede externa. Então, se para o primeiro nó o roteador veio com uma porta 888 , então para o segundo ele viria com uma porta 889 . Suponha que isso aconteceu, ou seja, a tabela r1_nat parece com isso:

Tabela 10: Endereço do receptor de falsificação do roteador

src IP Src PORTA IP de destino PORTO DE DESTINO
12.62.100.200 6000 192.168.0.200 35777

Tabela 11: O roteador alterou o endereço do receptor

O pacote chega com sucesso ao nó p1 e olhando para o conteúdo do pacote, o nó aprende sobre sua IP endereço, ou seja, o endereço do roteador na rede externa. Ele também conhece a porta pela qual o roteador passa NAT.

Qual é o próximo? De que adianta tudo isso? Benefício é uma entrada na tabela r1_nat. Se agora alguém vai enviar para o roteador r1 pacote de porta 888 , então o roteador encaminhará este pacote para o host p1. Assim, uma pequena passagem estreita foi criada para o nó oculto p1.

A partir do exemplo acima, você pode ter uma ideia de como funciona. NAT e essência ATORDOAR servidor. Em geral, o mecanismo GELO e ATORDOAR/TURNAR servidores visam apenas superar restrições NAT.

Pode haver mais de um roteador entre o nó e o servidor, mas vários. Nesse caso, o nó receberá o endereço do roteador que for o primeiro a entrar na mesma rede do servidor. Em outras palavras, obtemos o endereço do roteador conectado ao ATORDOAR servidor. Por p2p a comunicação é exatamente o que precisamos, se não esquecermos o fato de que em cada roteador a linha que precisamos será adicionada à tabela NAT. Assim, o caminho de volta será tão suave novamente.

VIRAR servidor é melhorado ATORDOAR servidor. Disto segue-se imediatamente que qualquer VIRAR o servidor pode funcionar e como ATORDOAR servidor. No entanto, também há benefícios. Se um p2p comunicação não é possível (como em 3g redes), então o servidor muda para o modo repetidor ( retransmissão), ou seja, funciona como intermediário. Claro, sobre qualquer p2p então não é uma questão, mas fora da estrutura do mecanismo GELO os nós pensam que estão se comunicando diretamente.

Em que casos é necessário VIRAR servidor? Por que não é suficiente ATORDOAR servidores? O fato é que existem vários tipos NAT. Eles substituem o mesmo IP endereço e porta, mas alguns deles têm proteção adicional integrada contra “falsificação”. Por exemplo, em simétrico tabela NAT Mais 2 parâmetros são salvos - IP e porta do host remoto. Um pacote da rede externa passa por NATà rede interna apenas se o endereço de origem e a porta corresponderem aos registrados na tabela. Portanto, o foco ATORDOAR servidor falha - tabela NAT armazena endereço e porta ATORDOAR servidor e quando o roteador recebe um pacote de WebRTC interlocutor, ele o descarta, pois é “falsificado”. Ele não veio de ATORDOAR servidor.

Nesse caminho VIRAR um servidor é necessário quando ambos os interlocutores estão atrás simétrico NAT(cada um por si).

Sumário breve

Aqui estão algumas declarações sobre entidades WebRTC que deve ser sempre lembrado. Eles são descritos em detalhes acima. Se alguma das afirmações não lhe parecer completamente clara, releia os parágrafos relevantes.

  • fluxo de mídia
    • Os dados de vídeo e áudio são compactados em fluxos de mídia
    • Os fluxos de mídia sincronizam as faixas de mídia que compõem
    • Diferentes fluxos de mídia estão fora de sincronia
    • Os fluxos de mídia podem ser locais e remotos, uma câmera e um microfone geralmente são conectados ao local, os remotos recebem dados da rede de forma criptografada
    • Existem dois tipos de faixas de mídia - para vídeo e para áudio.
    • As faixas de mídia têm a capacidade de ligar/desligar
    • As faixas de mídia são compostas de canais de mídia
    • As faixas de mídia sincronizam os canais de mídia que compõem
    • Os fluxos de mídia e as faixas de mídia têm rótulos pelos quais podem ser distinguidos
  • Identificador de sessão
    • O descritor de sessão é usado para conectar logicamente dois nós de rede
    • O descritor de sessão armazena informações sobre os métodos de codificação disponíveis para dados de vídeo e áudio.
    • WebRTC usa um mecanismo de sinalização externo - a tarefa de encaminhar descritores de sessão ( sdp) recai sobre a aplicação
    • O mecanismo de conexão lógica consiste em duas etapas - uma proposta ( oferta) e resposta ( responda)
    • A geração do descritor de sessão não é possível sem o uso de um fluxo de mídia local no caso de uma oferta ( oferta) e não é possível sem usar um descritor de sessão remota em caso de resposta ( responda)
    • O descritor resultante deve ser dado à implementação WebRTC, e não importa se esse identificador é obtido remotamente ou localmente da mesma implementação WebRTC
    • É possível editar ligeiramente o descritor de sessão
  • Candidatos
    • Candidato ( Candidato a gelo) é o endereço do nó na rede
    • O endereço do nó pode ser seu ou pode ser o endereço de um roteador ou VIRAR servidores
    • Há sempre muitos candidatos
    • O candidato é composto por IP endereço, porto e tipo de transporte ( TCP ou UDP)
    • Os candidatos são usados ​​para estabelecer uma conexão física entre dois nós em uma rede
    • Os candidatos também precisam ser enviados através do mecanismo de sinalização
    • Os candidatos também precisam passar por implementações WebRTC, mas apenas remoto
    • Em algumas implementações WebRTC Os candidatos só podem ser aprovados após o descritor de sessão ter sido definido
  • STUN/TURN/ICE/NAT
    • NAT– um mecanismo para fornecer acesso a uma rede externa
    • Os roteadores domésticos suportam uma tabela especial NAT
    • O roteador substitui os endereços nos pacotes - o endereço de origem pelo seu próprio, caso o pacote vá para a rede externa, e o endereço do receptor pelo endereço do host na rede interna, se o pacote veio da rede externa
    • Para fornecer acesso multicanal a uma rede externa NAT usa portas
    • GELO- mecanismo de desvio NAT
    • ATORDOAR e VIRAR servidores - servidores auxiliares para contornar NAT
    • ATORDOAR o servidor permite que você crie as entradas necessárias na tabela NAT, e também retorna o endereço externo do nó
    • VIRAR servidor generaliza ATORDOAR mecanismo e faz com que sempre funcione
    • Nos piores casos VIRAR o servidor é usado como intermediário ( retransmissão), isso é p2p se transforma em uma conexão cliente-servidor-cliente.

Os usuários europeus da Internet estão divididos em duas partes: de acordo com uma pesquisa do Instituto de Análise de Opinião Pública de Allenbach (Alemanha), o Skype, o chat e os sistemas de mensagens instantâneas tornaram-se parte integrante da vida cotidiana de 16,5 milhões de adultos e crianças, 9 milhões usam esses serviços caso a caso, e 28 milhões não os tocam.

A situação pode mudar, já que agora o Firefox está integrado tecnologia de comunicação em tempo real (WebRTC), bem como o próprio cliente. Iniciar um bate-papo por áudio e vídeo agora não é mais difícil do que abrir um site. Serviços como Facebook e Skype, por outro lado, contam com soluções usando um cliente separado e criando uma conta.

O WebRTC não é apenas fácil de usar. Este método ainda permite que você defina conexão direta entre dois navegadores. Assim, os dados de áudio e vídeo não passam por um servidor onde possa ocorrer congestionamento ou onde o administrador não seja particularmente sensível sobre privacidade ou proteção de dados. Com uma conexão direta, o WebRTC não requer registro ou conta em nenhum serviço.

Para iniciar uma conversa, você só precisa seguir o link. A comunicação permanece privada porque o fluxo de dados é criptografado. Comunicação em tempo real através do navegador, o Google começou a se envolver ativamente em 2011, quando publicou o código-fonte de sua implementação WebRTC.

Pouco tempo depois, o Chrome e o Firefox receberam seus próprios mecanismos WebRTC. Atualmente, suas versões mobile são equipadas tanto com essa tecnologia quanto com o motor WebView 3.6 instalado com Android 5.0, que é utilizado por aplicativos.

Para comunicação em tempo real, as interfaces JavaScript apropriadas devem ser implementadas no visualizador da web. Com GetUserMedia, o software permite a captura de fontes de áudio e vídeo, ou seja, webcam e microfone. O RTCPeerConnection é responsável por estabelecer a conexão, bem como pela própria comunicação.

Em paralelo com a integração do navegador, o grupo de trabalho do World Wide Web Consortium (W3C) vem impulsionando o processo de padronização do WebRTC. Deve ser concluído em 2015.

WebRTC se contenta com pouco

A utilização do serviço WebRTC não requer muitos recursos, pois o servidor apenas conecta os buddies. Estabelecer uma conexão também não é particularmente difícil. Primeiro, o navegador sinaliza ao servidor WebRTC que planeja iniciar uma chamada. Ele recebe um link HTTPS do servidor - a conexão é criptografada. O usuário envia este link para seu interlocutor. O navegador então pede permissão ao usuário para acessar a webcam e o microfone.

Para estabelecer uma conexão de streaming direta com a outra parte, o navegador recebe seu endereço IP e dados de configuração do serviço WebRTC. O navegador da web do amigo faz o mesmo.

Para que a conexão de streaming funcione sem problemas e com boa qualidade, três mecanismos funcionam no navegador. Dois deles otimizam e compactam dados de áudio e vídeo, o terceiro é responsável pelo seu transporte. Ele envia dados por protocolo SRTP(Secure Real-time Transport Protocol), que permite streaming criptografado em tempo real.

Se uma conexão direta falhar, o WebRTC procura outro caminho. Por exemplo, isso acontece quando as configurações de rede impedem que o servidor STUN possa relatar o endereço IP. O padrão WebRTC estipula que neste caso a conversa ocorrerá, mas com a inclusão intermediária do servidor TURN (Traversal Using Relays around NAT). Assim, no site netscan.co, você pode verificar se o WebRTC está implementado em seu computador e com seu acesso à Web.

Como é feita a ligação

Primeiro você precisa registrar uma conversa (1). O serviço WebRTC disponibiliza um link que precisa ser enviado ao interlocutor. O navegador, usando o STUNserver, descobre seu próprio endereço IP (2), envia para o serviço e recebe o IP do parceiro para estabelecer uma conexão direta (3). Se o STUN falhar, a conversação é redirecionada usando o TURNserver (4).

A comunicação usando a tecnologia WebRTC no navegador é iniciada usando o código JavaScript. Depois disso, três mecanismos são responsáveis ​​pela comunicação: os mecanismos de voz e vídeo coletam dados multimídia da webcam e do microfone, e o mecanismo de transporte combina as informações e envia o fluxo de forma criptografada usando o Secure Real-time Protocol (SRTP).

Quais navegadores funcionam com WebRTC

O Chrome e o Firefox estão equipados com um mecanismo WebRTC que usa serviços como talky.io. O navegador Mozilla pode trabalhar diretamente com seu próprio cliente.

Google e Mozilla continuam a desenvolver a ideia de comunicação em tempo real: o Chrome pode hospedar uma conferência WebRTC com vários participantes, e o novo cliente Hello no Firefox é desenvolvido com a ajuda de uma subsidiária da gigante das telecomunicações Telefonica. A Apple permanece à margem por enquanto, você não deve esperar o WebRTC no Safari ainda. No entanto, existem muitos aplicativos e plugins iOS alternativos para o Safari.

A Microsoft está tomando um rumo um pouco diferente. Como proprietária do competitivo serviço Skype, esta empresa não vai capitular ao WebRTC tão facilmente. Em vez disso, a Microsoft está desenvolvendo uma tecnologia chamada ORTC (Object Real-Time Communications) para o Internet Explorer.

As diferenças do WebRTC, como codecs e protocolos diferentes para estabelecer contato com o servidor, são pequenas e, com o tempo, provavelmente se tornarão adicionais ao padrão WebRTC, que incluirá essas diferenças. Assim, apenas a Apple fica para trás - como de costume.

Uma foto: companhias de manutafuramento; goodluz/Photolia.com

As tecnologias para chamar a partir do navegador têm muitos anos: Java, ActiveX, Adobe Flash... Nos últimos anos ficou claro que os plug-ins e as máquinas virtuais esquerdas não brilham com conveniência (por que devo instalar algo ?) e, o mais importante, segurança . O que fazer? Existe uma saída!

Até recentemente, vários protocolos eram usados ​​em redes IP para telefonia IP ou vídeo: SIP, o protocolo mais comum saindo de cena, H.323 e MGCP, Jabber/Jingle (usado no Gtalk), Adobe RTMP* semi-aberto e, é claro, fechou o Skype. O projeto WebRTC, iniciado pelo Google, está tentando transformar o mundo da telefonia IP e web tornando todos os softphones, incluindo o Skype, obsoletos. O WebRTC não apenas implementa todos os recursos de comunicação diretamente dentro do navegador, que agora está instalado em quase todos os dispositivos, mas simultaneamente tenta resolver uma tarefa mais geral de comunicação entre usuários do navegador (troca de vários dados, tradução de tela, colaboração com documentos e muito mais).

WebRTC por um desenvolvedor web

Do ponto de vista de um desenvolvedor web, o WebRTC consiste em duas partes principais:

  • o gerenciamento de fluxos de mídia de recursos locais (câmera, microfone ou tela do computador local) é implementado pelo método navigator.getUserMedia, que retorna um objeto MediaStream;
  • comunicações ponto a ponto entre dispositivos que geram fluxos de mídia, incluindo a definição de métodos de comunicação e sua transmissão direta - objetos RTCPeerConnection (para envio e recebimento de fluxos de áudio e vídeo) e RTCDataChannel (para envio e recebimento de dados do navegador).

O que nós fazemos?

Vamos descobrir como organizar o chat de vídeo multijogador mais simples entre navegadores baseados em WebRTC usando soquetes da web. Vamos começar a experimentar no Chrome/Chromium, como os navegadores mais avançados em termos de WebRTC, embora o Firefox 22, lançado em 24 de junho, quase os alcançou. Deve-se dizer que o padrão ainda não foi adotado, e a API pode mudar de versão para versão. Todos os exemplos foram testados no Chromium 28. Para simplificar, não monitoraremos a limpeza do código e a compatibilidade entre navegadores.

fluxo de mídia

O primeiro e mais simples componente WebRTC é o MediaStream. Ele fornece ao navegador acesso a fluxos de mídia da câmera e do microfone do computador local. No Chrome, isso requer chamar a função navigator.webkitGetUserMedia() (porque o padrão ainda não está finalizado, todas as funções vêm com um prefixo, e no Firefox a mesma função é chamada navigator.mozGetUserMedia()). Quando for chamado, o usuário será solicitado a permitir o acesso à câmera e ao microfone. Será possível continuar a chamada somente após o consentimento do usuário. Os parâmetros do fluxo de mídia necessário e duas funções de retorno de chamada são passados ​​como parâmetros para esta função: a primeira será chamada em caso de acesso bem-sucedido à câmera/microfone, a segunda - em caso de erro. Primeiro, vamos criar um arquivo HTML rtctest1.html com um botão e um elemento

WebRTC - primeiro conhecimento

Microsoft CU-RTC-Web

A Microsoft não seria a Microsoft se não lançasse imediatamente sua própria variante personalizada incompatível chamada CU-RTC-Web (html5labs.interoperabilitybridges.com/cu-rtc-web/cu-rtc-web.htm) em resposta à iniciativa do Google . Embora a participação do IE, já pequena, continue diminuindo, o número de usuários do Skype dá à Microsoft esperança de empurrar o Google, e pode-se supor que esse padrão será usado na versão do navegador do Skype. O padrão do Google se concentra principalmente na comunicação entre navegadores; ao mesmo tempo, a maior parte do tráfego de voz ainda permanece na rede telefônica convencional, e os gateways entre ela e as redes IP são necessários não apenas para facilidade de uso ou distribuição mais rápida, mas também como meio de monetização que permitirá que mais players desenvolvê-los. O aparecimento de outro padrão pode não apenas levar a uma necessidade desagradável para os desenvolvedores de suportar duas tecnologias incompatíveis ao mesmo tempo, mas também, no futuro, dar ao usuário uma escolha mais ampla de funcionalidades possíveis e soluções técnicas disponíveis. Espere e veja.

Ativar encadeamento local

Etiquetas internas Em nosso arquivo HTML, vamos declarar uma variável global para o fluxo de mídia:

VarlocalStream = null;

O primeiro parâmetro para o método getUserMedia é especificar os parâmetros do fluxo de mídia solicitado - por exemplo, basta habilitar áudio ou vídeo:

Var streamConstraints = ( "audio": true, "video": true ); // Solicita acesso a áudio e vídeo

Ou especifique opções adicionais:

Var streamConstraints = ( "audio": true, "video": ( "mandatory": ( "maxWidth": "320", "maxHeight": "240", "maxFrameRate": "5" ), "opcional": ) );

O segundo parâmetro para o método getUserMedia é passar uma função de retorno de chamada que será chamada se for bem-sucedida:

Function getUserMedia_success(stream) ( console.log("getUserMedia_success():", stream); localVideo1.src = URL.createObjectURL(stream); // Anexar stream de mídia ao elemento HTML

O terceiro parâmetro é uma função de retorno de chamada, um manipulador de erros que será chamado em caso de erro.

Função getUserMedia_error(error) ( console.log("getUserMedia_error():", error); )

A chamada real para o método getUserMedia - solicitando acesso ao microfone e à câmera quando o primeiro botão é pressionado

Função getUserMedia_click() ( console.log("getUserMedia_click()"); navigator.webkitGetUserMedia(streamConstraints, getUserMedia_success, getUserMedia_error); )

Não é possível acessar o fluxo de mídia de um arquivo aberto localmente. Se tentarmos fazer isso, recebemos um erro:

NavigatorUserMediaError (código: 1, PERMISSION_DENIED: 1)"

Vamos fazer o upload do arquivo resultante para o servidor, abri-lo no navegador e, em resposta à solicitação que aparece, permitir o acesso à câmera e ao microfone.

Você pode selecionar quais dispositivos o Chrome acessará acessando Configurações, Mostrar link de configurações avançadas, seção Privacidade, botão Conteúdo. Nos navegadores Firefox e Opera, os dispositivos são selecionados na lista suspensa diretamente quando o acesso é concedido.

Ao usar o protocolo HTTP, a permissão será solicitada sempre que um fluxo de mídia for acessado após o carregamento da página. Mudar para HTTPS permitirá que você exiba a solicitação uma vez, apenas no primeiro acesso ao fluxo de mídia.

Preste atenção no círculo pulsante no ícone da guia e no ícone da câmera no lado direito da barra de endereços:

RTCMediaConnection

RTCMediaConnection - um objeto projetado para estabelecer e transferir fluxos de mídia pela rede entre os participantes. Além disso, este objeto é responsável por gerar uma descrição de sessão de mídia (SDP), obter informações sobre os candidatos ICE para passar por NAT ou firewalls (locais e usando STUN) e interagir com o servidor TURN. Cada participante deve ter um RTCMediaConnection por conexão. Os fluxos de mídia são transmitidos pelo protocolo SRTP criptografado.

GIRAR servidores

Existem três tipos de candidatos a ICE: host, srflx e relay. Host contém informações obtidas localmente, srflx é a aparência do host para um servidor externo (STUN) e relay são informações para tráfego de proxy através do servidor TURN. Se nosso nó estiver atrás de um NAT, os candidatos de host conterão endereços locais e serão inúteis, os candidatos srflx só ajudarão com certos tipos de NAT e a retransmissão será a última esperança de passar o tráfego por um servidor intermediário.

Um exemplo de um candidato ICE do tipo host, com endereço 192.168.1.37 e porta udp/34022:

A=candidato:337499441 2 udp 2113937151 192.168.1.37 34022 tipo host geração 0

Formato geral para especificar servidores STUN/TURN:

Var servers = ( "iceServers": [ ( "url": "stun:stun.stunprotocol.org:3478" ), ( "url": "turn: [e-mail protegido]:port", "credential": "password" ) ]);

Existem muitos servidores STUN públicos na Internet. Uma lista grande, por exemplo, é . Infelizmente, eles resolvem muito poucos dos problemas. Praticamente não existem servidores TURN públicos, ao contrário do STUN. Isso se deve ao fato de que o servidor TURN passa fluxos de mídia por si mesmo, o que pode carregar significativamente tanto o canal de rede quanto o próprio servidor. Portanto, a maneira mais fácil de se conectar aos servidores TURN é instalá-lo você mesmo (obviamente, você precisará de um IP público). De todos os servidores, na minha opinião, o melhor é o rfc5766-turn-server . Abaixo dele, há até uma imagem pronta para o Amazon EC2.

Com o TURN, nem tudo é tão bom quanto gostaríamos, mas o desenvolvimento ativo está em andamento, e eu gostaria de esperar que depois de algum tempo o WebRTC, se não for igual ao Skype em termos de qualidade de passagem pela tradução de endereços (NAT) e firewalls, então pelo menos visivelmente se aproxime.

O RTCMediaConnection precisa de um mecanismo adicional de troca de informações de controle para estabelecer uma conexão - embora gere esses dados, ele não os transmite, e a transmissão por outros participantes deve ser implementada separadamente.


A escolha do método de transmissão é de responsabilidade do desenvolvedor - pelo menos manualmente. Assim que os dados necessários forem trocados, o RTCMediaConnection configurará os fluxos de mídia automaticamente (se possível, é claro).

modelo de oferta-resposta

Para estabelecer e modificar os fluxos de mídia, são utilizados o modelo de oferta/resposta (oferta/resposta; descrito na RFC3264) e o protocolo SDP (Session Description Protocol). Eles também são usados ​​pelo protocolo SIP. Neste modelo, distinguem-se dois agentes: Ofertante - aquele que gera a descrição da sessão SDP para criar uma nova ou modificar uma existente (Oferta SDP), e Respondente - aquele que recebe a descrição da sessão SDP de outro agente e responde a ele com sua própria descrição de sessão (Responder SDP). Ao mesmo tempo, a especificação requer um protocolo de nível superior (por exemplo, SIP ou seu próprio over web sockets, como no nosso caso), que é responsável pela transferência do SDP entre os agentes.

Quais dados precisam ser passados ​​entre dois RTCMediaConnections para que eles possam estabelecer fluxos de mídia com sucesso:

  • A primeira parte que inicia a conexão forma uma Oferta na qual transmite uma estrutura de dados SDP (o mesmo protocolo é usado para a mesma finalidade no SIP) descrevendo as possíveis características do fluxo de mídia que está prestes a começar a transmitir. Este bloco de dados deve ser transferido para o segundo participante. O segundo participante gera uma Resposta com seu SDP e envia para o primeiro.
  • Tanto o primeiro quanto o segundo participantes realizam o procedimento para determinar possíveis candidatos ICE, com a ajuda de que o segundo participante pode transferir o fluxo de mídia para eles. À medida que os candidatos são identificados, as informações sobre eles devem ser transferidas para outro participante.

Formação da Oferta

Para formar uma Oferta, precisamos de duas funções. O primeiro será chamado em caso de sua formação bem sucedida. O segundo parâmetro do método createOffer() é uma função callback chamada em caso de erro durante sua execução (desde que o stream local já esteja disponível).

Além disso, dois manipuladores de eventos são necessários: onicecandidate ao definir um novo candidato a ICE e onaddstream ao conectar um fluxo de mídia do outro lado. Vamos voltar ao nosso arquivo. Adicionar ao HTML após linhas com elementos

E depois da linha com o elemento


Além disso, no início do código JavaScript, declararemos uma variável global para RTCPeerConnection:

varpc1;

Ao chamar o construtor RTCPeerConnection, você deve especificar os servidores STUN/TURN. Veja a barra lateral para mais detalhes; desde que todos os participantes estejam na mesma rede, eles não são necessários.

var servidores = null;

Opções para Oferta de Provisionamento SDP

var ofertaRestrições = ();

O primeiro parâmetro do método createOffer() é uma função de retorno de chamada chamada após a formação bem-sucedida de uma Oferta

Function pc1_createOffer_success(desc) ( console.log("pc1_createOffer_success(): \ndesc.sdp:\n"+desc.sdp+"desc:", desc); pc1.setLocalDescription(desc); // Configura o RTCPeerConnection gerado pelo Offer SDP setLocalDescription method. // Quando o lado distante enviar seu SDP de resposta, ele precisará ser definido usando o método setRemoteDescription // Até que o segundo lado seja implementado, não faça nada // pc2_receivedOffer(desc); )

O segundo parâmetro é uma função de retorno de chamada que será chamada em caso de erro

Função pc1_createOffer_error(erro)( console.log("pc1_createOffer_success_error(): erro:", erro); )

E vamos declarar uma função de retorno de chamada que receberá candidatos ICE conforme eles são definidos:

Function pc1_onicecandidate(event)( if (event.candidate) ( console.log("pc1_onicecandidate():\n"+ event.candidate.candidate.replace("\r\n", ""), event.candidate); // Não faça nada até que o segundo lado seja implementado // pc2.addIceCandidate(new RTCIceCandidate(event.candidate)); ) )

Assim como uma função de retorno de chamada para adicionar um fluxo de mídia do lado distante (para o futuro, pois temos apenas um RTCPeerConnection até agora):

Função pc1_onaddstream(evento) ( console.log("pc_onaddstream()"); remoteVideo1.src = URL.createObjectURL(event.stream); )

Ao clicar no botão “createOffer”, crie um RTCPeerConnection, defina os métodos onicecandidate e onaddstream e solicite a formação de um SDP de Oferta chamando o método createOffer():

Function createOffer_click() ( console.log("createOffer_click()"); pc1 = new webkitRTCPeerConnection(servers); // Cria um RTCPeerConnection pc1.onicecandidate = pc1_onicecandidate; // Função de retorno de chamada para processar candidatos ICE pc1.onaddstream = pc1_onaddstream; / / Função de retorno de chamada chamada quando há um fluxo de mídia do lado distante, ele ainda não existe pc1.addStream(localStream); // Passa o fluxo de mídia local (supondo que já tenha sido recebido) pc1.createOffer(// E na verdade solicitar a formação da Oferta pc1_createOffer_success , pc1_createOffer_error, offerConstraints); )

Vamos salvar o arquivo como rtctest2.html, colocá-lo no servidor, abri-lo em um navegador e ver no console quais dados são gerados durante sua operação. O segundo vídeo ainda não aparecerá, pois há apenas um participante. Lembre-se de que SDP é uma descrição dos parâmetros da sessão de mídia, codecs disponíveis, fluxos de mídia e candidatos ICE são opções possíveis para se conectar a este participante.

Formação do Answer SDP e intercâmbio de candidatos ICE

Tanto o Offer SDP quanto cada um dos candidatos ICE devem ser passados ​​para o outro lado, e lá, após recebê-los do RTCPeerConnection, chame os métodos setRemoteDescription para o Offer SDP e addIceCandidate para cada candidato ICE recebido do lado distante; da mesma forma em sentido inverso para SDP de resposta e candidatos ICE remotos. A própria Resposta SDP é formada de forma semelhante à Oferta; a diferença é que não o método createOffer é chamado, mas o método createAnswer, e antes deste RTCPeerConnection, o método setRemoteDescription passa o SDP de Oferta recebido do chamador.

Vamos adicionar outro elemento de vídeo ao HTML:

E uma variável global para o segundo RTCPeerConnection sob a declaração do primeiro:

Varpc2;

Processando Oferta e Resposta SDP

Formar um SDP de Resposta é muito semelhante a uma Oferta. Na função callback chamada após a formação bem-sucedida da Resposta, semelhante à Oferta, daremos uma descrição local e passaremos a Resposta SDP recebida para o primeiro participante:

Função pc2_createAnswer_success(desc) ( pc2.setLocalDescription(desc); console.log("pc2_createAnswer_success()", desc.sdp); pc1.setRemoteDescription(desc); )

A função callback chamada em caso de erro ao gerar a Resposta é completamente semelhante à Oferta:

Função pc2_createAnswer_error(erro) ( console.log("pc2_createAnswer_error():", erro); )

Parâmetros para gerar Resposta SDP:

Var answerConstraints = ( "mandatory": ( "OfferToReceiveAudio":true, "OfferToReceiveVideo":true ) );

Quando o segundo participante receber uma Oferta, crie um RTCPeerConnection e forme uma Resposta da mesma forma que a Oferta:

Function pc2_receivedOffer(desc) ( console.log("pc2_receiveOffer()", desc); // Cria um objeto RTCPeerConnection para o segundo participante semelhante ao primeiro pc2 = new webkitRTCPeerConnection(servers); pc2.onicecandidate = pc2_onicecandidate; // Configura the event handler when ICE candidate pc2.onaddstream = pc_onaddstream; // Quando um stream aparece, conecta-o ao HTML

Para transferir o SDP da Oferta do primeiro participante para o segundo, como parte do nosso exemplo, descomente na função pc1 criarOferta success() string de chamada:

Pc2_receivedOffer(desc);

Para implementar o processamento de candidatos de ICE, descomente no manipulador de eventos de prontidão de candidato de ICE do primeiro participante pc1_onicecandidate() sua transmissão para o segundo:

Pc2.addIceCandidate(novo RTCIceCandidate(evento.candidato));

O manipulador de eventos de prontidão do candidato ICE do segundo participante é semelhante ao primeiro:

Function pc2_onicecandidate(event) ( if (event.candidate) ( console.log("pc2_onicecandidate():", event.candidate.candidate); pc1.addIceCandidate(new RTCIceCandidate(event.candidate)); ) )

Função de retorno de chamada para adicionar um fluxo de mídia do primeiro participante:

Função pc2_onaddstream(evento) ( console.log("pc_onaddstream()"); remoteVideo2.src = URL.createObjectURL(event.stream); )

Terminando uma conexão

Vamos adicionar outro botão em HTML

E uma função para encerrar a conexão

Function btnHangupClick() ( // Desativa o vídeo local dos elementos HTML

Vamos salvá-lo como rtctest3.html, colocá-lo no servidor e abri-lo no navegador. Este exemplo implementa o streaming de mídia bidirecional entre dois RTCPeerConnections na mesma guia do navegador. Para organizar a troca de ofertas e respostas SDP, candidatos ICE entre participantes e outras informações através da rede, será necessário implementar a troca entre participantes utilizando algum tipo de transporte, no nosso caso, web sockets, ao invés de uma chamada direta para procedimentos.

Transmissão de tela

Com a função getUserMedia, você também pode capturar a tela e transmitir como um MediaStream especificando os seguintes parâmetros:

Var mediaStreamConstraints = ( audio: false, video: ( obrigatório: ( chromeMediaSource: "screen" ), opcional: ) );

Para um acesso bem-sucedido à tela, várias condições devem ser atendidas:

  • habilite o sinalizador de captura de tela em getUserMedia() em chrome://flags/,chrome://flags/;
  • o arquivo fonte deve ser baixado via HTTPS (origem SSL);
  • o fluxo de áudio não deve ser solicitado;
  • várias solicitações não devem ser feitas na mesma guia do navegador.

Bibliotecas para WebRTC

Embora o WebRTC ainda não esteja completo, várias bibliotecas baseadas nele já apareceram. O JsSIP foi projetado para criar softphones baseados em navegador que funcionam com switches SIP, como Asterisk e Camalio. O PeerJS simplificará a criação de redes P2P para troca de dados e a Holla reduzirá a quantidade de desenvolvimento necessária para comunicação P2P de navegadores.

Node.js e socket.io

Para organizar a troca de candidatos SDP e ICE entre dois RTCPeerConnections pela rede, usamos Node.js com o módulo socket.io.

A instalação da última versão estável do Node.js (para Debian/Ubuntu) é descrita

$ sudo apt-get install python-software-properties python g++ make $ sudo add-apt-repository ppa:chris-lea/node.js $ sudo apt-get update $ sudo apt-get install nodejs

A instalação para outros sistemas operacionais é descrita

Vamos checar:

$ echo "sys=require("util"); sys.puts("Mensagem de teste");" > nodetest1.js $ nodejs nodetest1.js

Usando npm (Node Package Manager) instale o socket.io e o módulo express adicional:

$ npm instalar socket.io express

Vamos verificar criando um arquivo nodetest2.js para o lado do servidor:

$ nano nodetest2.js var app = require("express")() , server = require("http").createServer(app) , io = require("socket.io").listen(server); servidor.ouvir(80); // Se a porta 80 for livre app.get("/", function (req, res) ( // Ao acessar a página raiz res.sendfile(__dirname + "/nodetest2.html"); // fornecer o arquivo HTML ) ); io.sockets.on("connection", function (socket) ( // Na conexão socket.emit("server event", ( hello: "world" )); // envia mensagem socket.on("client event", function (data) ( // e declara um manipulador de eventos quando uma mensagem chega do cliente console.log(data); )); ));

E nodetest2.html para o lado do cliente:

$nano nodetest2.html

Vamos iniciar o servidor:

$ sudo nodejs nodetest2.js

e abra a página http://localhost:80 (se estiver executando localmente na porta 80) em um navegador. Se tudo der certo, no console JavaScript do navegador veremos a troca de eventos entre o navegador e o servidor na conexão.

Troca de informações entre RTCPeerConnection via web sockets

Lado do cliente

Vamos salvar nosso exemplo principal (rtcdemo3.html) sob o novo nome rtcdemo4.html. Inclua a biblioteca socket.io no elemento:

E no início do script JavaScript - conexão de soquete da web:

var socket = io.connect("http://localhost");

Vamos substituir uma chamada direta para as funções de outro participante enviando-lhe uma mensagem via web sockets:

Function createOffer_success(desc) ( ... // pc2_receivedOffer(desc); socket.emit("offer", desc); ... ) function pc2_createAnswer_success(desc) ( ... // pc1.setRemoteDescription(desc); socket .emit("answer", desc); ) function pc1_onicecandidate(event) ( ... // pc2.addIceCandidate(new RTCIceCandidate(event.candidate)); socket.emit("ice1", event.candidate); .. . ) function pc2_onicecandidate(event) ( ... // pc1.addIceCandidate(new RTCIceCandidate(event.candidate)); socket.emit("ice2", event.candidate); ... )

Na função hangup(), ao invés de chamar diretamente as funções do segundo participante, enviaremos uma mensagem via web sockets:

Função btnHangupClick() ( ... // remoteVideo2.src = ""; pc2.close(); pc2 = null; socket.emit("hangup", ()); )

E adicione manipuladores de recebimento de mensagens:

Socket.on("oferta", função (dados) ( console.log("socket.on("oferta"):", dados); pc2_receivedOffer(dados); )); socket.on("answer", function (data) (e console.log("socket.on("answer"):", data); pc1.setRemoteDescription(new RTCSessionDescription(data)); )); socket.on("ice1", function (dados) ( console.log("socket.on("ice1"):", data); pc2.addIceCandidate(new RTCIceCandidate(data)); )); socket.on("ice2", function (dados) ( console.log("socket.on("ice2"):", data); pc1.addIceCandidate(new RTCIceCandidate(data)); )); socket.on("desligar", function (dados) ( console.log("socket.on("desligar")):", data); remoteVideo2.src = ""; pc2.close(); pc2 = null; ));

Parte do servidor

No lado do servidor, salve o arquivo nodetest2 com o novo nome rtctest4.js e dentro da função io.sockets.on("connection", function (socket) ( ... ) adicione o recebimento e envio de mensagens do cliente:

Socket.on("offer", function (data) ( // Ao receber a mensagem "offer", // já que há apenas uma conexão de cliente neste exemplo, // envia a mensagem de volta pelo mesmo socket socket.emit( "offer" , data); // Se for necessário encaminhar a mensagem em todas as conexões // exceto no remetente: // socket.broadcast.emit("offer", data); )); socket.on("resposta", função (dados) ( socket.emit("resposta", dados); )); socket.on("gelo1", função (dados) ( socket.emit("gelo1", dados); )); socket.on("gelo2", função (dados) ( socket.emit("gelo2", dados); )); socket.on("desligar", função (dados) ( socket.emit("desligar", dados); ));

Além disso, altere o nome do arquivo HTML:

// res.sendfile(__dirname + "/nodetest2.html"); // Envia o arquivo HTML res.sendfile(__dirname + "/rtctest4.html");

Início do servidor:

$ sudo nodejs nodetest2.js

Apesar do código de ambos os clientes ser executado dentro da mesma aba do navegador, toda a interação entre os participantes do nosso exemplo é feita completamente pela rede e não é mais difícil “espalhar” os participantes. No entanto, o que fizemos também foi muito simples - essas tecnologias são boas por sua facilidade de uso. Embora às vezes enganador. Em particular, não esqueçamos que sem servidores STUN/TURN, nosso exemplo não poderá funcionar na presença de tradução de endereços e firewalls.

Conclusão

O exemplo resultante é muito condicional, mas se universalizarmos um pouco os manipuladores de eventos para que eles não difiram entre as partes chamadora e chamada, em vez de dois objetos pc1 e pc2, faça um array RTCPeerConnection e implemente a criação e exclusão dinâmica de elementos

Pode-se supor que muito em breve, graças ao WebRTC, haverá uma revolução não apenas na nossa compreensão das comunicações de voz e vídeo, mas também na forma como percebemos a Internet como um todo. O WebRTC está posicionado não apenas como uma tecnologia de chamada de navegador para navegador, mas também como uma tecnologia de comunicação em tempo real. A comunicação por vídeo, que analisamos, é apenas uma pequena parte das opções possíveis para seu uso. Já existem exemplos de compartilhamento de tela (compartilhamento de tela) e colaboração, e até mesmo uma rede de entrega de conteúdo P2P baseada em navegador usando o RTCDataChannel.

WebRTC (Web Real Time Communications) é um padrão que descreve a transferência de streaming de dados de áudio, dados de vídeo e conteúdo do navegador e para o navegador em tempo real sem instalar plugins ou outras extensões. O padrão permite transformar o navegador em um terminal de videoconferência, basta abrir uma página web para iniciar a comunicação.

O que é WebRTC?

Neste artigo, abordaremos tudo o que há para saber sobre a tecnologia WebRTC para o usuário médio. Vamos considerar as vantagens e desvantagens do projeto, revelar alguns segredos, contar como funciona, onde e para que serve o WebRTC.

O que você precisa saber sobre WebRTC?

A evolução dos padrões e tecnologias de vídeo

Sergey Yutsaitis, Cisco, Video+Conference 2016

Como o WebRTC funciona

Do lado do cliente

  • O usuário abre uma página contendo uma tag HTML5
  • O navegador solicita acesso à webcam e ao microfone do usuário.
  • O código JavaScript na página do usuário controla os parâmetros de conexão (endereços IP e portas do servidor WebRTC ou outros clientes WebRTC) para ignorar o NAT e o Firewall.
  • Ao receber informações sobre o interlocutor ou sobre o stream com a conferência mixada no servidor, o navegador passa a negociar os codecs de áudio e vídeo utilizados.
  • Inicia-se o processo de codificação e streaming de dados entre clientes WebRTC (no nosso caso, entre o navegador e o servidor).

No lado do servidor WebRTC

Um servidor de vídeo não é necessário para a troca de dados entre dois participantes, mas se você deseja combinar vários participantes em uma conferência, é necessário um servidor.



O servidor de vídeo receberá o tráfego de mídia de várias fontes, o converterá e o enviará aos usuários que usam o WebRTC como terminal.

O servidor WebRTC também receberá tráfego de mídia de pares WebRTC e o transmitirá aos participantes da conferência usando aplicativos de desktop ou móveis, se houver.

Benefícios do padrão

  • Nenhuma instalação de software necessária.
  • Qualidade de comunicação muito alta graças a:
    • Uso de codecs modernos de vídeo (VP8, H.264) e áudio (Opus).
    • Ajuste automático da qualidade do fluxo às condições de conexão.
    • Cancelamento de eco e ruído integrado.
    • Controle automático de nível dos microfones dos participantes (AGC).
  • Alto nível de segurança: todas as conexões são seguras e criptografadas de acordo com os protocolos TLS e SRTP.
  • Há um mecanismo interno para capturar conteúdo, como a área de trabalho.
  • Capacidade de implementar qualquer interface de controle baseada em HTML5 e JavaScript.
  • A capacidade de integrar a interface com qualquer sistema back-end usando WebSockets.
  • Um projeto de código aberto - você pode incorporá-lo em seu produto ou serviço.
  • Verdadeira plataforma cruzada: o mesmo aplicativo WebRTC funcionará igualmente bem em qualquer sistema operacional, desktop ou móvel, desde que o navegador suporte WebRTC. Isso economiza muitos recursos para o desenvolvimento de software.

Desvantagens do padrão

  • Para organizar conferências de áudio e vídeo em grupo, é necessário um servidor de videoconferência que misture vídeo e áudio dos participantes, porque o navegador não sabe como sincronizar vários fluxos de entrada entre si.
  • Todas as soluções WebRTC são incompatíveis entre si, pois o padrão descreve apenas métodos para transmissão de vídeo e som, deixando a implementação de métodos para endereçamento de assinantes, rastreamento de sua disponibilidade, troca de mensagens e arquivos, agendamento e outras coisas para o fornecedor.
  • Em outras palavras, você não poderá chamar de um aplicativo WebRTC de um desenvolvedor para um aplicativo WebRTC de outro desenvolvedor.
  • A mixagem de conferência em grupo exige muitos recursos computacionais, portanto, esse tipo de comunicação de vídeo exige a compra de uma assinatura paga ou investimento em sua infraestrutura, onde cada conferência requer 1 núcleo físico de um processador moderno.

Segredos do WebRTC: como os fornecedores se beneficiam da tecnologia disruptiva da Web


Tzachi Levent-Levi, Bloggeek.me, Video+Conference 2015

WebRTC para o mercado de videoconferência

Aumento do número de terminais de videoconferência

A tecnologia WebRTC teve uma forte influência no desenvolvimento do mercado de videoconferência. Após o lançamento dos primeiros navegadores com suporte WebRTC em 2013, o número potencial de terminais de videoconferência em todo o mundo aumentou imediatamente em 1 bilhão de dispositivos. Na verdade, cada navegador tornou-se um terminal de videoconferência que não é inferior aos seus homólogos de hardware em termos de qualidade de comunicação.

Uso em soluções especializadas

O uso de várias bibliotecas JavaScript e APIs de serviço em nuvem com suporte WebRTC facilita a adição de suporte de vídeo a qualquer projeto da web. No passado, a transmissão de dados em tempo real exigia que os desenvolvedores aprendessem como os protocolos funcionam e usassem o trabalho de outras empresas, que na maioria das vezes exigiam licenciamento adicional, o que aumentava os custos. O WebRTC já é usado ativamente em serviços como “Chamada do site”, “Chat de suporte online”, etc.

Ex-usuários do Skype para Linux

Em 2014, a Microsoft anunciou o fim do suporte ao projeto Skype for Linux, o que causou grande incômodo entre os profissionais de TI. A tecnologia WebRTC não está vinculada ao sistema operacional, mas é implementada no nível do navegador, ou seja, Os usuários do Linux poderão ver os produtos e serviços baseados em WebRTC como um substituto completo para o Skype.

Competição com Flash

WebRTC e HTML5 foram um golpe mortal para a tecnologia Flash, que já estava passando por seus melhores anos. Desde 2017, os principais navegadores pararam oficialmente de oferecer suporte ao Flash e a tecnologia finalmente desapareceu do mercado. Mas você tem que dar crédito ao Flash, porque foi ele quem criou o mercado de webconferência e ofereceu os recursos técnicos para comunicação ao vivo em navegadores.

Apresentações de vídeo WebRTC

Dmitry Odintsov, TrueConf, Video+Conference outubro de 2017

Codecs em WebRTC

Codecs de áudio

Para compactar o tráfego de áudio no WebRTC, são usados ​​os codecs Opus e G.711.

G.711- o codec de voz mais antigo com alta taxa de bits (64 kbps), que é mais usado em sistemas de telefonia tradicionais. A principal vantagem é a carga computacional mínima devido ao uso de algoritmos de compressão leves. O codec tem um baixo nível de compressão de sinais de voz e não introduz atraso de áudio adicional durante a comunicação entre usuários.

G.711 é suportado por um grande número de dispositivos. Os sistemas que usam este codec são mais fáceis de usar do que aqueles baseados em outros codecs de áudio (G.723, G.726, G.728, etc.). Em termos de qualidade, o G.711 recebeu uma pontuação de 4,2 no teste MOS (uma pontuação de 4-5 é a mais alta e significa boa qualidade, semelhante à qualidade do tráfego de voz em ISDN e até superior).

Opusé um codec com baixa latência de codificação (de 2,5 ms a 60 ms), suporte a taxa de bits variável e alta compactação, ideal para streaming de áudio em redes de largura de banda variável. Opus é uma solução híbrida que combina os melhores recursos dos codecs SILK (Voice Compression, Human Speech Distortion Elimination) e CELT (Audio Data Encoding). O codec está disponível gratuitamente, os desenvolvedores que o utilizam não precisam pagar royalties aos detentores dos direitos autorais. Comparado a outros codecs de áudio, o Opus certamente vence de várias maneiras. Ele eclipsou codecs de baixa taxa de bits bastante populares, como MP3, Vorbis, AAC LC. Opus restaura a "imagem" do som mais próximo do original do que AMR-WB e Speex. Este codec é o futuro, razão pela qual os criadores da tecnologia WebRTC o incluíram na faixa obrigatória de padrões de áudio suportados.

Codecs de vídeo

A questão de escolher um codec de vídeo para WebRTC levou vários anos para os desenvolvedores, no final eles decidiram usar H.264 e VP8. Quase todos os navegadores modernos suportam ambos os codecs. Os servidores de videoconferência precisam de apenas um suporte para funcionar com o WebRTC.

VP8é um codec de vídeo gratuito com licença aberta, com alta velocidade de decodificação de fluxo de vídeo e maior resistência à perda de quadros. O codec é universal, é fácil implementá-lo em plataformas de hardware, por isso os desenvolvedores de sistemas de videoconferência costumam usá-lo em seus produtos.

Codec de vídeo pago H.264 tornou-se conhecido muito antes de seu irmão. Este é um codec com alto grau de compactação do fluxo de vídeo, mantendo alta qualidade de vídeo. A alta prevalência desse codec entre os sistemas de videoconferência por hardware sugere seu uso no padrão WebRTC.

Google e Mozilla estão promovendo ativamente o codec VP8, enquanto Microsoft, Apple e Cisco estão promovendo ativamente o H.264 (para garantir a compatibilidade com sistemas tradicionais de videoconferência). E aqui surge um problema muito grande para os desenvolvedores de soluções WebRTC baseadas em nuvem, porque se todos os participantes da conferência usarem o mesmo navegador, basta misturar a conferência uma vez com um codec e se os navegadores forem diferentes e entre eles há Safari/Edge, então a conferência terá que ser codificada duas vezes codecs diferentes, o que dobrará os requisitos do sistema para o servidor de mídia e, como resultado, o custo das assinaturas dos serviços WebRTC.

API WebRTC

A tecnologia WebRTC é baseada em três APIs principais:

  • (responsável pelo navegador web para receber sinais de áudio e vídeo das câmeras ou do desktop do usuário).
  • RTCPeerConnection(responsável pela conexão entre navegadores para a “troca” de dados de mídia recebidos da câmera, microfone e desktop. Além disso, as “tarefas” desta API incluem processamento de sinal (limpando-o de ruídos estranhos, ajustando o volume do microfone) e controle sobre os codecs de áudio e vídeo usados).
  • Canal de dados RTC(fornece transferência de dados bidirecional em uma conexão estabelecida).

Antes de acessar o microfone e a câmera do usuário, o navegador solicita essa permissão. No Google Chrome, você pode pré-configurar o acesso na seção “Configurações”, no Opera e Firefox, a escolha dos dispositivos é realizada diretamente no momento do acesso, a partir da lista suspensa. A solicitação de permissão sempre aparecerá ao usar o protocolo HTTP e uma vez ao usar HTTPS:


RTCPeerConnection. Cada navegador participante de uma conferência WebRTC deve ter acesso a este objeto. Graças ao uso do RTCPeerConnection, os dados de mídia de um navegador para outro podem até passar por NAT e firewalls. Para transmitir fluxos de mídia com sucesso, os participantes devem trocar os seguintes dados usando um transporte, como soquetes da web:

  • o participante iniciador envia ao segundo participante uma Oferta-SDP (estrutura de dados, com as características do fluxo de mídia que ele transmitirá);
  • o segundo participante gera uma “resposta” - Answer-SDP e a envia ao iniciador;
  • então, uma troca de candidatos ICE é organizada entre os participantes, se algum for encontrado (se os participantes estiverem atrás de NAT ou firewalls).

Após a conclusão bem-sucedida dessa troca entre os participantes, a transferência de fluxos de mídia (áudio e vídeo) é organizada diretamente.

Canal de dados RTC. O suporte para o protocolo Data Channel apareceu nos navegadores há relativamente pouco tempo, portanto, essa API só pode ser considerada nos casos em que o WebRTC é usado nos navegadores Mozilla Firefox 22+ e Google Chrome 26+. Com ele, os participantes podem trocar mensagens de texto no navegador.

Conexão WebRTC

Navegadores de desktop compatíveis

  • Google Chrome (17+) e todos os navegadores baseados no motor Chromium;
  • Mozilla Firefox (18+);
  • Ópera (12+);
  • Safári (11+);

Navegadores móveis suportados para Android

  • Google Chrome (28+);
  • Mozilla Firefox (24+);
  • Opera Móvel (12+);
  • Safári (11+).

WebRTC, Microsoft e Internet Explorer

Por muito tempo, a Microsoft ficou em silêncio sobre o suporte WebRTC no Internet Explorer e em seu novo navegador Edge. Os caras de Redmond realmente não gostam de colocar tecnologia nas mãos de usuários que eles não controlam, esse é o tipo de política. Mas aos poucos as coisas decolaram, porque. Não era mais possível ignorar o WebRTC, e o projeto ORTC, derivado do padrão WebRTC, foi anunciado.

Segundo os desenvolvedores, o ORTC é uma extensão do padrão WebRTC com um conjunto aprimorado de APIs baseadas em JavaScript e HTML5, o que, traduzido em linguagem comum, significa que tudo será igual, apenas a Microsoft, e não o Google, controlará o padrão e seu desenvolvimento. O conjunto de codecs foi expandido com suporte para H.264 e alguns codecs de áudio da série G.7XX usados ​​em sistemas de telefonia e videoconferência de hardware. Talvez haja suporte embutido para RDP (para transferência de conteúdo) e mensagens. A propósito, os usuários do Internet Explorer estão sem sorte, o suporte ao ORTC estará apenas no Edge. Bem, e, claro, esse conjunto de protocolos e codecs se encaixa facilmente no Skype for Business, o que abre ainda mais aplicativos de negócios para WebRTC.

WebRTC é uma API fornecida pelo navegador que permite organizar uma conexão P2P e transferir dados diretamente entre navegadores. Existem vários tutoriais na Internet sobre como escrever seu próprio bate-papo por vídeo usando WebRTC. Por exemplo, aqui está um artigo sobre Habré. No entanto, todos eles estão limitados a conectar dois clientes. Neste artigo, tentarei falar sobre como organizar uma conexão e troca de mensagens entre três ou mais usuários utilizando WebRTC.

A interface RTCPeerConnection é uma conexão ponto a ponto entre dois navegadores. Para conectar três ou mais usuários, teremos que organizar uma rede mesh (uma rede na qual cada nó está conectado a todos os outros nós).
Usaremos o seguinte esquema:

  1. Ao abrir a página, verificamos a presença do ID do quarto no local.hash
  2. Se o ID do quarto não for especificado, gere um novo
  3. Enviamos a um servidor de sinalização "uma mensagem de que queremos entrar na sala especificada
  4. O servidor de sinalização envia uma nova notificação de usuário para outros clientes nesta sala
  5. Clientes que já estão na sala enviam uma oferta SDP para o recém-chegado
  6. O recém-chegado responde à oferta "s

0. Servidor de sinalização

Como você sabe, embora o WebRTC forneça a possibilidade de conexão P2P entre navegadores, ele ainda requer um transporte adicional para troca de mensagens de serviço. Neste exemplo, o transporte é um servidor WebSocket escrito em Node.JS usando socket.io:

var socket_io = require("socket.io"); module.exports = function (server) ( var users = (); var io = socket_io(server); io.on("connection", function(socket) ( // Deseja que um novo usuário entre na sala socket.on( "room ", function(message) ( var json = JSON. parse(message); // Adiciona o socket à lista de usuários users = socket; if (socket.room !== undefined) ( // Se o socket for já em algum quarto , deixe socket.leave(socket.room); ) // Digite o quarto solicitado socket.room = json.room; socket.join(socket.room); socket.user_id = json.id; // Enviar para outros clientes esta sala tem uma mensagem sobre como ingressar em um novo participante socket.broadcast.to(socket.room).emit("new", json.id); )); // Mensagem relacionada ao WebRTC (oferta SDP, resposta SDP ou ICE candidate) socket.on("webrtc", function(message) ( var json = JSON.parse(message); if (json.to !== undefined && users !== undefined) ( // Se a mensagem tiver um destinatário e este destinatário conhecido pelo servidor, envie uma mensagem apenas para ele... users.emit("webrtc", mensagem); ) else ( // ...caso contrário, considere a mensagem como um broadcast socket.broadcast.to(socket.room).emit("webrtc", message); ) )); // Alguém desconectou socket.on("disconnect", function() ( // Quando um cliente se desconecta, notifica os outros socket.broadcast.to(socket.room).emit("leave", socket.user_id); delete users; )); )); );

1. index.html

O código-fonte da página em si é bastante simples. Eu deliberadamente não prestei atenção ao layout e outras coisas bonitas, já que este artigo não é sobre isso. Se alguém quiser deixá-la bonita, não será difícil.

Demonstração de bate-papo WebRTC

conectado a 0 pares

2.main.js

2.0. Obtendo links para elementos de página e interfaces WebRTC
var chatlog = document.getElementById("chatlog"); var mensagem = document.getElementById("message"); var connection_num = document.getElementById("connection_num"); var room_link = document.getElementById("room_link");

Ainda temos que usar prefixos de navegador para acessar interfaces WebRTC.

Var PeerConnection = window.mozRTCPeerConnection || window.webkitRTCPeerConnection; var SessionDescription = window.mozRTCSessionDescription || window.RTCSessionDescription; var IceCandidate = window.mozRTCIceCandidate || window.RTCIceCandidate;

2.1. Determinando o ID do quarto

Aqui precisamos de uma função para gerar uma sala e um ID de usuário exclusivos. Usaremos UUID para esta finalidade.

Function uuid() ( var s4 = function() ( return Math.floor(Math.random() * 0x10000).toString(16); ); return s4() + s4() + "-" + s4() + "-" + s4() + "-" + s4() + "-" + s4() + s4() + s4(); )

Agora vamos tentar extrair o ID do quarto do endereço. Se isso não estiver definido, geraremos um novo. Mostraremos um link para a sala atual na página e, ao mesmo tempo, geraremos um identificador para o usuário atual.

VarROOM = localização.hash.substr(1); if (!ROOM) ( ROOM = uuid(); ) room_link.innerHTML = "Link para a sala"; varME = uuid();

2.2. soquete da web

Imediatamente ao abrir a página, nos conectaremos ao nosso servidor de sinalização, enviaremos uma solicitação para entrar na sala e especificaremos os manipuladores de mensagens.

// Especificamos que quando a mensagem for fechada, precisamos enviar uma notificação ao servidor sobre esta var socket = io.connect("", ("sincronizar desconexão ao descarregar": true)); socket.on("webrtc", socketReceived); socket.on("novo", socketNewPeer); // Envia imediatamente uma solicitação para entrar na sala socket.emit("room", JSON.stringify((id: ME, room: ROOM))); // Função auxiliar para enviar mensagens de endereço relacionadas à função WebRTC sendViaSocket(type, message, to) ( socket.emit("webrtc", JSON.stringify((id: ME, to: to, type: type, data: message ) )); )

2.3. Configurações de conexão de peer

A maioria dos ISPs fornece conectividade com a Internet por meio de NAT. Por causa disso, uma conexão direta torna-se não tão trivial. Ao criar uma conexão, precisamos especificar uma lista de servidores STUN e TURN que o navegador tentará usar para ignorar o NAT. Também indicaremos algumas opções adicionais para conexão.

Var server = ( iceServers: [ (url: "stun:23.21.150.121"), (url: "stun:stun.l.google.com:19302"), (url: "turn:numb.viagenie.ca", credencial: "sua senha vai aqui", nome de usuário: " [e-mail protegido]") ] ); var options = ( opcional: [ (DtlsSrtpKeyAgreement: true), // necessário para conexão entre Chrome e Firefox (RtpDataChannels: true) // necessário no Firefox para usar a API DataChannels ] )

2.4. Conectando um novo usuário

Quando um novo peer é adicionado à sala, o servidor nos envia uma mensagem novo. De acordo com os manipuladores de mensagens acima, a função será chamada socketNewPeer.

var pares = (); function socketNewPeer(data) ( peers = (candidateCache: ); // Cria uma nova conexão var pc = new PeerConnection(server, options); // Inicializa initConnection(pc, data, "offer"); // Armazena o peer na lista peers peers.connection = pc; // Cria um DataChannel através do qual as mensagens serão trocadas var channel = pc.createDataChannel("mychannel", ()); channel.owner = data; peers.channel = channel; // Definir manipuladores de eventos bindEvents(channel); // Cria uma oferta SDP pc.createOffer(function(offer) ( pc.setLocalDescription(offer); )); ) function initConnection(pc, id, sdpType) ( pc.onicecandidate = function ( event) ( if (event.candidate) ( // Quando um novo candidato ICE for encontrado, adicione-o à lista para envio adicional peers.candidateCache.push(event.candidate); ) else ( // Quando a descoberta de candidatos for completado, o handler será chamado novamente, mas sem candidato // Neste caso, enviamos primeiro ao peer uma oferta SDP, ou Resposta do SDP (dependendo do parâmetro da função)... sendViaSocket(sdpType, pc.localDescription, id); // ...e então todos os candidatos ICE encontrados anteriormente para (var i = 0; i< peers.candidateCache.length; i++) { sendViaSocket("candidate", peers.candidateCache[i], id); } } } pc.oniceconnectionstatechange = function (event) { if (pc.iceConnectionState == "disconnected") { connection_num.innerText = parseInt(connection_num.innerText) - 1; delete peers; } } } function bindEvents (channel) { channel.onopen = function () { connection_num.innerText = parseInt(connection_num.innerText) + 1; }; channel.onmessage = function (e) { chatlog.innerHTML += "

O par diz: " + e.data + "
"; }; }

2.5. Oferta SDP, resposta SDP, candidato ICE

Quando uma dessas mensagens é recebida, chamamos o manipulador de mensagens correspondente.

Função socketReceived(data) ( var json = JSON.parse(data); switch (json.type) ( case "candidate": remoteCandidateReceived(json.id, json.data); break; case "offer": remoteOfferReceived(json. id, json.data); break; case "answer": remoteAnswerReceived(json.id, json.data); break; ) )

2.5.0 oferta SDP
function remoteOfferReceived(id, data) ( createConnection(id); var pc = peers.connection; pc.setRemoteDescription(new SessionDescription(data)); pc.createAnswer(function(answer) ( pc.setLocalDescription(answer); )); ) function createConnection(id) ( if (peers === undefined) ( peers = (candidateCache: ); var pc = new PeerConnection(server, options); initConnection(pc, id, "answer"); peers.connection = pc ; pc.ondatachannel = function(e) ( peers.channel = e.channel; peers.channel.owner = id; bindEvents(peers.channel); ) ) )
2.5.1 Respostas SDP
function remoteAnswerReceived(id, data) ( var pc = peers.connection; pc.setRemoteDescription(new SessionDescription(data)); )
2.5.2 Candidato ICE
function remoteCandidateReceived(id, data) ( createConnection(id); var pc = peers.connection; pc.addIceCandidate(new IceCandidate(data)); )
2.6. Enviando uma mensagem

Ao pressionar o botão mandar função é chamada enviar mensagem. Tudo o que ele faz é percorrer a lista de pares e tentar enviar a mensagem especificada para todos.