WebRTC. Conferință video în browser. Chat cu mai mulți utilizatori folosind chatul vocal WebRTC Webrtc

Preambul. Chat video P2P activat Baza WebRTC este o alternativă la Skype și alte mijloace de comunicare. Elementele principale ale chat-ului video p2p bazat pe WebRTC sunt un browser și un server de contact. Chat-urile video P2P sunt chat-uri video peer-to-peer în care serverul nu ia parte la transmiterea fluxurilor de informații. Informațiile sunt transferate direct între browserele utilizatorilor (peer) fără niciuna programe suplimentare. În plus față de browsere, chat-urile video p2p folosesc servere de contact, care sunt concepute pentru a înregistra utilizatori, pentru a stoca date despre aceștia și pentru a asigura comutarea între utilizatori. Browserele care acceptă cele mai recente tehnologii WebRTC și HTML5 oferă mesaje text instant și transmisie de fișiere, precum și comunicații vocale și video prin rețele IP.

Deci, chat-urile, chat-urile web, chat-urile vocale și video într-o interfață web, IMS, VoIP sunt servicii care oferă comunicații online prin rețele compozite cu comutare de pachete. De regulă, serviciile de comunicare necesită fie instalarea de aplicații client pe dispozitivele utilizatorului (PC-uri, smartphone-uri etc.), fie instalarea de pluginuri și extensii în browsere. Serviciile au propriile lor rețele de comunicații, majoritatea fiind construite pe o arhitectură client-server.

Serviciile de comunicații sunt aplicații, altele decât IMS, în care canalele de voce, video, date și text nu sunt integrate. În rețelele fiecărui serviciu, . Trebuie remarcat faptul că aceste aplicații nu pot funcționa simultan în mai multe rețele de comunicații, adică. De obicei, aplicațiile nu pot comunica între ele, necesitând instalarea unei aplicații separate pentru fiecare rețea de comunicații.

Problema integrării serviciilor de comunicare în timp real (chat, telefonie, videoconferință), i.e. integrarea canalelor de voce, video, date și accesul la acestea folosind o singură aplicație (browser) pot fi rezolvate în chat-uri video peer-to-peer sau p2p (peer-to-peer, point-to-point) bazate pe protocolul WebRTC. În esență, un browser care acceptă WebRTC devine o interfață unică pentru toate dispozitivele utilizatorului (PC-uri, smartphone-uri, iPad-uri, telefoane IP, telefoane mobile etc.) care lucrează cu servicii de comunicații.

Este WebRTC care asigură implementarea în browser a tuturor tehnologiilor care asigură comunicații în timp real. Esența chat-urilor video p2p este că datele multimedia și text sunt transferate direct între browserele utilizatorilor (peering la distanță) fără participarea unui server sau a unor programe suplimentare. Astfel, browserele nu oferă doar acces la aproape toate resurse informaționale Internet, care sunt stocate pe servere, dar devin și un mijloc de acces la toate serviciile de comunicații în timp real și serviciile de poștă (posta vocală, e-mail, SMS etc.)

Serverele (serverele de contact) ale chat-urilor video p2p sunt destinate doar înregistrării utilizatorilor, stocării datelor despre utilizatori și stabilirii unei conexiuni (comutarea) între browserele utilizatorilor. Primele chat-uri video p2p au fost implementate folosind tehnologii flash. Chaturile video flash p2p sunt folosite, de exemplu, în în rețelele sociale. Chat-urile video flash p2p nu oferă calitate superioară transmiterea de date multimedia. În plus, pentru a scoate fluxul de voce și video de la microfon și camera video în chat-urile video flash p2p, trebuie să instalați plugin flashîntr-un browser web.

Dar noua generație de servicii de telecomunicații include comunicații web, care folosesc doar browsere și servere de contact care acceptă protocoale WebRTC și specificația HTML5 pentru a comunica prin Internet. Orice dispozitiv de utilizator (PC, iPad, smartphone-uri etc.) echipat cu un astfel de browser poate oferi apeluri vocale și video de înaltă calitate, precum și transferul de mesaje text și fișiere instantanee.

Deci, noua tehnologie a comunicațiilor web (chaturi p2p, chat-uri video) este protocolul WebRTC. WebRTC împreună cu HTML5, CSS3 și JavaScript vă permit să creați diverse aplicații web. WebRT este conceput pentru a organiza comunicațiile web (rețele peer-to-peer) în timp real folosind o arhitectură peer-to-peer. Chaturile P2P bazate pe WebRTC oferă transfer de fișiere, precum și comunicare text, voce și video între utilizatori prin Internet folosind numai browsere web, fără utilizarea suplimentelor și pluginurilor externe în browser.

În chat-urile p2p, serverul este folosit doar pentru a stabili o conexiune p2p între două browsere. Pentru a crea partea client a unui chat p2p bazat pe protocolul WebRTC, se folosesc HTML5, CSS3 și JavaScript. Aplicația client interacționează cu browserele prin intermediul API-ului WebRTC.

WebRTC este implementat de trei API-uri JavaScript:

  • RTCPeerConnection;
  • MediaStream(getUserMedia);
  • RTCDataChannel.

Browserele transferă date media utilizând protocolul SRTP, care rulează pe UDP. Deoarece NAT creează probleme pentru browserele (clienții) din spatele routerelor NAT care folosesc conexiuni p2p prin Internet, STUN este folosit pentru a ocoli traducătorii NAT. STUN este un protocol client-server care rulează peste protocolul de transport UDP. În chat-urile p2p, de regulă, se folosește un server STUN public, iar informațiile primite de la acesta sunt folosite pentru o conexiune UDP între două browsere dacă acestea sunt în spatele NAT.

Exemple de implementare a aplicațiilor WebRTC (chaturi p2p, chat-uri web voce și video):
1. Chat video P2P Bistri (chat video cu un singur clic, chat p2p), bazat pe WebRTC, poate fi deschis pe Bistri. Bistri funcționează în browser fără a instala programe și plugin-uri suplimentare. Esența lucrării este următoarea: deschideți un chat video p2p folosind link-ul specificat, după înregistrarea în interfața care se deschide, invitați parteneri, apoi din lista clienților egali selectați partenerul care este online și faceți clic pe „apel video butonul ”.

Drept urmare, MediaStream (getUserMedia) va captura microfonul + camera web, iar serverul va schimba mesaje de semnalizare cu partenerul selectat. După schimbul de mesaje de semnalizare, API-ul PeerConnection creează canale pentru transmiterea fluxurilor de voce și video. In plus, Bistri transfera mesaje text instant si fisiere. În fig. 1 arată o captură de ecran a interfeței de chat video Bistri p2p.


Orez. 1. P2P video chat Bistri

2. Twelephone (p2p video chat, p2p chat, SIP Twelephone) - această aplicație client este construită pe baza HTML5 și WebRTC, care vă permite să efectuați apeluri vocale și video, precum și să trimiteți mesaje text instant, de ex. Twelephone include chat p2p de testare, chat video și SIP Twelephone. Trebuie remarcat faptul că Twelephone acceptă protocolul SIP și acum puteți efectua și primi apeluri vocale și video de pe telefoanele SIP folosind contul dvs. de Twitter ca număr de telefon. In afara de asta, mesaje text poți intra prin voce prin microfon, iar programul de recunoaștere vocală introduce textul în linia „Trimite un mesaj”.

Twelephone este o telefonie web bazată pe browser Google Chrome, începând cu versiunea 25, fără suplimentar software. Twelephone a fost dezvoltat de Chris Matthieu. Backend-ul Twelephone este construit pe Node.js. Serverul (server de contact) este folosit doar pentru a stabili o conexiune p2p între două browsere sau clienți WebRTC. Aplicația Twelephone nu are propriile instrumente de autorizare, dar este axată pe conectarea la un cont ( cont) pe Twitter.

În fig. 2 arată o captură de ecran a interfeței de chat video p2p Twelephone.



Orez. 2. Telefon P2P

3. Chat video p2p de grup Conversat.io este construit pe cele mai recente tehnologii WebRTC și HTML5. Chat-ul video Conversat este dezvoltat pe baza bibliotecii SimpleWebRTC și este destinat comunicării între până la 6 clienți de la egal la egal într-o cameră (pentru comunicare, indicați numele camerei comune pentru clienții de la egal la linia „Denumește conversația”). Chat video P2P Conversat oferă utilizatorilor servicii de comunicare fără a se înregistra pe serverul de contact. În fig. Figura 3 arată o captură de ecran a interfeței de chat video Conversat p2p.



Orez. 3. Chat video P2P de grup Conversat.io

Pentru a participa la chat-urile video P2P bazate pe WebRTC, utilizatorii trebuie să aibă instalat un browser care acceptă protocolul WebRTC și specificația HTML5. În prezent, browserele Google Chrome, începând cu versiunea 25, și Mozilla Firefox Nightly acceptă protocolul WebRTC și specificația HTML5. Aplicațiile WebRTC sunt superioare aplicațiilor Flash în ceea ce privește calitatea transmisiei imaginii și sunetului.

Majoritatea materialului de pe WebRTC este axat pe nivelul aplicației de codare și nu contribuie la înțelegerea tehnologiei. Să încercăm să mergem mai profund și să aflăm cum are loc conexiunea, ce descriptor de sesiune și candidații sunt, de ce sunt necesare serverele STUN și TURN.

WebRTC Introducere

WebRTC este o tehnologie orientată spre browser care vă permite să conectați doi clienți pentru transferul de date video. Principalele caracteristici sunt suportul intern de către browsere (nu este nevoie de tehnologii implementate de terți, cum ar fi Adobe Flash) și capacitatea de a conecta clienți fără utilizarea de servere suplimentare - conexiune peer-to-peer (în continuare, p2p).

Stabilirea unei conexiuni p2p este o sarcină destul de dificilă, deoarece computerele nu au întotdeauna adrese IP publice, adică adrese de pe Internet. Datorită numărului mic de adrese IPv4 (și din motive de securitate), a fost dezvoltat mecanismul NAT, care vă permite să creați rețele private, de exemplu, pentru uz casnic. Multe routere de acasă acceptă acum NAT și datorită acestui lucru, toate dispozitivele de acasă au acces la Internet, deși furnizorii de internet oferă de obicei o singură adresă IP. Adresele IP publice sunt unice pe Internet, dar cele private nu. Prin urmare, conectarea p2p este dificilă.

Pentru a înțelege mai bine acest lucru, luați în considerare trei situații: ambele noduri sunt în aceeași rețea (Figura 1), ambele noduri sunt pe rețele diferite (unul în privat, celălalt în public) (Figura 2) și ambele noduri sunt în rețele private diferite cu aceleași adrese IP (Figura 3).

Figura 1: Ambele noduri din aceeași rețea

Figura 2: Noduri în diferite rețele (unul în privat, unul în public)

Figura 3: Noduri în rețele private diferite, dar cu adrese egale numeric

În figurile de mai sus, prima literă din notația cu două caractere indică tipul de nod (p = peer, r = router). În prima imagine, situația este favorabilă: nodurile din rețeaua lor sunt complet identificate prin adresele IP ale rețelei și, prin urmare, se pot conecta direct între ele. În a doua figură avem două rețele diferite cu numere de noduri similare. Aici apar routerele (routere), care au două interfata retea– în interiorul rețelei și în afara rețelei. De aceea au două adrese IP. Nodurile obișnuite au o singură interfață prin care pot comunica doar în cadrul rețelei lor. Dacă transmit date către cineva din afara rețelei lor, atunci folosind numai NAT în interiorul routerului (routerului) și, prin urmare, vizibil pentru alții sub adresa IP a routerului - este a lor extern Adresa IP. Deci nodul p1 are interior IP = 192.168.0.200 Și extern IP = 10.50.200.5 , iar ultima adresă va fi, de asemenea, externă tuturor celorlalte noduri din rețeaua sa. Situația este similară pentru nodul p2. Prin urmare, comunicarea lor este imposibilă dacă sunt folosite doar adresele IP interne (proprii). Puteți utiliza adrese externe, adică adrese de router, dar deoarece toate nodurile din aceeași rețea privată au aceeași adresă externă, acest lucru este destul de dificil. Această problemă poate fi rezolvată folosind mecanismul NAT

Ce se va întâmpla dacă decidem să conectăm nodurile prin adresele lor interne? Datele nu vor părăsi rețeaua. Pentru a spori efectul, vă puteți imagina situația prezentată în ultima figură - ambele noduri au aceleași adrese interne. Dacă le folosesc pentru a comunica, atunci fiecare nod va comunica cu el însuși.

WebRTC face față cu succes acestor probleme folosind protocolul ICE, care, totuși, necesită utilizarea de servere suplimentare (STUN, TURN). Mai multe despre toate acestea mai jos.

Două faze ale WebRTC

Pentru a conecta două noduri prin protocolul WebRTC (sau doar RTC, dacă două iPhone-uri comunică), trebuie să efectuați câțiva pași preliminari pentru a stabili conexiunea. Aceasta este prima fază - stabilirea unei conexiuni. A doua fază este transmisia de date video.

Merită spus imediat că, deși tehnologia WebRTC folosește multe în diverse moduri comunicații (TCP și UDP) și are comutare flexibilă între ele, această tehnologie nu are un protocol pentru transmiterea datelor de conexiune. Nu este surprinzător, deoarece conectarea a două noduri p2p nu este atât de ușoară. Prin urmare, este necesar să aveți câteva adiţional o metodă de transmitere a datelor care nu are nicio legătură cu WebRTC. Ar putea fi un transfer de socket, un protocol HTTP, chiar ar putea fi protocol SMTP sau Poșta Rusă. Acest mecanism de transmisie iniţială se numesc date semnal. Nu trebuie transmise multe informații. Toate datele sunt transmise sub formă de text și sunt împărțite în două tipuri - SDP și Ice Candidate. Primul tip este folosit pentru a stabili o conexiune logică, iar al doilea pentru o conexiune fizică. Mai multe despre toate acestea mai târziu, dar deocamdată este important să ne amintim că WebRTC ne va oferi câteva informații care vor trebui să fie transmise către un alt nod. Imediat ce vom transmite toate informațiile necesare, nodurile se vor putea conecta și ajutorul nostru nu va mai fi nevoie. Deci mecanismul de semnalizare pe care trebuie să-l implementăm este separat, va fi folosit numai atunci când este conectat, dar nu va fi folosit la transmiterea datelor video.

Deci, să luăm în considerare prima fază - faza de stabilire a conexiunii. Este format din mai multe puncte. Să ne uităm la această fază mai întâi pentru nodul care inițiază conexiunea și apoi pentru cel care așteaptă.

  • Inițiator (apelant):
  • Oferiți să începeți transferul de date video (createOffer)
  • Obținerea SDP SDP)
  • Primirea candidatului tău Ice Candidatul Ice)
  • Apel în așteptare (apelat):
  • Primirea unui flux media local (dvs.) și setarea acestuia pentru transmisie (getUserMediaStream)
  • Primirea unei oferte pentru a începe transferul de date video și crearea unui răspuns (createAnswer)
  • Primirea obiectului său SDP și trecerea acestuia prin mecanismul de semnalizare (SDP)
  • Primirea obiectelor dvs. Ice candidate și trecerea lor printr-un mecanism de semnalizare (Ice candidate)
  • Primirea unui flux media de la distanță (străin) și afișarea lui pe ecran (onAddStream)

Singura diferență este în al doilea punct.

În ciuda complexității aparente a pașilor, există de fapt trei dintre ei: trimiterea propriului flux media (articolul 1), setarea parametrilor de conexiune (articolele 2-4), primirea fluxului media altcuiva (articolul 5). Pasul cel mai dificil este cel de-al doilea pas, deoarece este format din două părți: stabilirea fizicȘi logic conexiuni. Primul indică cale, de-a lungul căruia pachetele trebuie să călătorească pentru a ajunge de la un nod de rețea la altul. Al doilea indică parametrii video/audio– ce calitate să folosești, ce codecuri să folosești.

Din punct de vedere mental, etapa createOffer sau createAnswer ar trebui să fie conectată la etapele de trecere a obiectelor candidate SDP și Ice.

Entități de bază Fluxuri media (MediaStream)

Entitatea principală este fluxul media, adică fluxul de date video și audio, imagine și sunet. Există două tipuri de fluxuri media - locale și la distanță. Cel local primește date de la dispozitivele de intrare (cameră, microfon), iar cel la distanță prin rețea. Astfel, fiecare nod are atât un fir local, cât și unul la distanță. În WebRTC, există o interfață MediaStream pentru fluxuri și există, de asemenea, o subinterfață LocalMediaStream special pentru un flux local. În JavaScript îl puteți întâlni doar pe primul, dar dacă utilizați libjingle îl puteți întâlni și pe al doilea.

WebRTC are o ierarhie destul de confuză în cadrul unui fir. Fiecare flux poate consta din mai multe piese media (MediaTrack), care la rândul lor pot consta din mai multe canale media (MediaChannel). Și pot exista, de asemenea, mai multe fluxuri media în sine.

Să privim totul în ordine. Pentru a face acest lucru, să ținem cont de un exemplu. Să spunem că vrem să transmitem nu doar un videoclip cu noi înșine, ci și un videoclip al mesei noastre, pe care se află o bucată de hârtie pe care urmează să scriem ceva. Vom avea nevoie de două videoclipuri (noi + tabel) și unul audio (noi). Este clar că noi și tabelul ar trebui să fim împărțiți în fire diferite, deoarece aceste date sunt probabil puțin dependente unele de altele. Prin urmare, vom avea două MediaStream-uri - unul pentru noi și unul pentru masă. Primul va conține atât date video, cât și audio, iar al doilea va conține doar video (Figura 4).

Figura 4: Două fluxuri media diferite. Unul pentru noi, unul pentru masa noastră

Este imediat clar că un flux media trebuie să includă cel puțin capacitatea de a conține date tipuri diferite- video și audio. Acest lucru este luat în considerare în tehnologie și, prin urmare, fiecare tip de date este implementat printr-o pistă media MediaTrack. Piesa media are un tip de proprietate specială, care determină dacă este video sau audio (Figura 5)

Figura 5: Fluxurile media constau din piese media

Cum se va întâmpla totul în program? Vom crea două fluxuri media. Apoi vom crea două piese video și o pistă audio. Să obținem acces la camere și microfon. Să spunem fiecărei piese ce dispozitiv să folosească. Să adăugăm o pistă video și audio la primul flux media și o pistă video de la o altă cameră la al doilea flux media.

Dar cum distingem fluxurile media la celălalt capăt al conexiunii? Pentru a face acest lucru, fiecare flux media are o proprietate etichetă - eticheta fluxului, numele acestuia (Figura 6). Piesele media au aceeași proprietate. Deși la prima vedere pare că videoclipul poate fi distins de sunet în alte moduri.

Figura 6: Fluxurile și melodiile media sunt identificate prin etichete

Deci, dacă melodiile media pot fi identificate printr-o etichetă, atunci de ce trebuie să folosim două fluxuri media pentru exemplul nostru, în loc de unul? La urma urmei, puteți transmite un flux media, dar utilizați diferite piese în el. Am ajuns la o proprietate importantă a fluxurilor media - ei sincroniza piese media. Diferitele fluxuri media nu sunt sincronizate între ele, dar în cadrul fiecărui flux media toate piesele sunt redate simultan.

Astfel, dacă vrem ca cuvintele noastre, emoțiile noastre faciale și bucata noastră de hârtie să fie redate simultan, atunci merită să folosiți un flux media. Dacă acest lucru nu este atât de important, atunci este mai profitabil să folosiți diferite fluxuri - imaginea va fi mai netedă.

Dacă o melodie trebuie dezactivată în timpul transmisiei, puteți utiliza proprietatea activată a melodiei media.

În cele din urmă, merită să ne gândim la sunetul stereo. După cum știți, sunetul stereo este două sunete diferite. Și trebuie să fie transferate și separat. MediaChannels sunt folosite pentru aceasta. O pistă audio media poate avea mai multe canale (de exemplu, 6 dacă aveți nevoie de 5+1 audio). Există și canale în interiorul pieselor media, desigur. sincronizate. Pentru video, de obicei este utilizat un singur canal, dar mai multe pot fi folosite, de exemplu, pentru suprapunerea publicității.

A rezuma: Folosim un flux media pentru a transmite date video și audio. În cadrul fiecărui flux media, datele sunt sincronizate. Putem folosi mai multe fluxuri media dacă nu avem nevoie de sincronizare. În interiorul fiecărui flux media există două tipuri de piese media - pentru video și pentru audio. De obicei, nu există mai mult de două piese, dar pot fi mai multe dacă trebuie să transmiteți mai multe videoclipuri diferite (ale interlocutorului și a mesei sale). Fiecare piesă poate consta din mai multe canale, care este de obicei folosit doar pentru sunet stereo.

În cea mai simplă situație de chat video, vom avea un flux media local, care va consta din două piese - o pistă video și o pistă audio, fiecare dintre acestea fiind compusă dintr-un canal principal. Piesa video este responsabilă pentru cameră, pista audio este pentru microfon, iar fluxul media este containerul pentru ambele.

Descriptor de sesiune (SDP)

Calculatoarele diferite vor avea întotdeauna camere, microfoane, plăci video și alte echipamente diferite. Există multe opțiuni pe care le au. Toate acestea trebuie coordonate pentru transferul media de date între două noduri de rețea. WebRTC face acest lucru automat și creează obiect special– Descriptor de sesiune SDP. Treceți acest obiect către alt nod și datele media pot fi transferate. Numai că nu există încă nicio legătură cu un alt nod.

Pentru aceasta este folosit orice mecanism de semnalizare. SDP poate fi transmis fie prin prize, fie de către o persoană (spuneți-l unui alt nod prin telefon), fie prin Russian Post. Totul este foarte simplu - vi se va da un SDP gata făcut și trebuie să îl trimiteți. Și când este primit pe cealaltă parte, transferați-l în departamentul WebRTC. Descriptorul de sesiune este stocat ca text și poate fi modificat în aplicațiile dvs., dar acest lucru nu este în general necesar. De exemplu, atunci când conectați desktop ↔ telefon, uneori trebuie să forțați selectarea codecului audio dorit.

De obicei, atunci când stabiliți o conexiune, trebuie să specificați un fel de adresă, cum ar fi o adresă URL. Acest lucru nu este necesar aici, deoarece prin mecanismul de semnalizare tu însuți vei trimite datele la destinație. Pentru a indica lui WebRTC că dorim să stabilim o conexiune p2p, trebuie să apelăm funcția createOffer. După apelarea acestei funcții și specificarea unui callback special 'a, un obiect SDP va fi creat și transmis aceluiași callback. Tot ceea ce vă este necesar este să transferați acest obiect prin rețea către un alt nod (interlocutor). După aceasta, datele vor ajunge la celălalt capăt prin mecanismul de semnalizare, și anume acest obiect SDP. Acest descriptor de sesiune este străin acestui nod și, prin urmare, conține informații utile. Primirea acestui obiect este un semnal de pornire a conexiunii. Prin urmare, trebuie să fiți de acord cu acest lucru și să apelați funcția createAnswer. Este un analog complet al createOffer. Din nou, descriptorul de sesiune local va fi transmis callback-ului și va trebui să fie transmis înapoi prin mecanismul de semnalizare.

Este demn de remarcat faptul că puteți apela funcția createAnswer numai după ce primiți obiectul SDP al altcuiva. De ce? Deoarece obiectul SDP local care va fi generat la apelarea createAnswer trebuie să se bazeze pe obiectul SDP la distanță. Numai în acest caz este posibil să vă coordonați setările video cu setările interlocutorului dvs. De asemenea, nu ar trebui să apelați createAnswer și createOffer înainte de a primi fluxul media local - nu vor avea nimic de scris în obiectul SDP.

Deoarece WebRTC are capacitatea de a edita un obiect SDP, după ce a primit un descriptor local, acesta trebuie să fie instalat. Poate părea puțin ciudat că trebuie să transferăm la WebRTC ceea ce ne-a dat, dar acesta este protocolul. Când se primește un mâner de la distanță, acesta trebuie de asemenea instalat. Prin urmare, trebuie să instalați doi descriptori pe un nod - al dvs. și al altcuiva (adică, local și la distanță).

Dupa asta strângeri de mână nodurile știu unul despre dorințele celuilalt. De exemplu, dacă nodul 1 acceptă codecurile A și B, iar nodul 2 acceptă codecurile B și C, atunci, deoarece fiecare nod își cunoaște descriptorii proprii și ai celuilalt, ambele noduri vor alege codecul B (Figura 7). Logica de conectare este acum stabilită și fluxurile media pot fi transmise, dar există o altă problemă - nodurile sunt încă conectate doar printr-un mecanism de semnalizare.


Figura 7: Negocierea codecului

Candidat de gheață

Tehnologia WebRTC încearcă să ne confunde cu noua sa metodologie. La stabilirea unei conexiuni, adresa nodului la care doriți să vă conectați nu este specificată. Instalat mai întâi logic conexiune, nu fizic, deși întotdeauna s-a făcut invers. Dar acest lucru nu va părea ciudat dacă nu uităm că folosim un mecanism de semnalizare terță parte.

Deci, conexiunea a fost deja stabilită (conexiune logică), dar încă nu există o cale pe care nodurile rețelei să poată transmite date. Nu este chiar atât de simplu, dar să începem simplu. Lăsați nodurile să fie în aceeași rețea privată. După cum știm deja, se pot conecta cu ușurință unul la altul folosind adresele lor IP interne (sau poate altele, dacă nu se utilizează TCP/IP).

Prin intermediul unor apeluri inverse și WebRTC ne informează despre obiectele candidate Ice. Ele vin, de asemenea, sub formă de text și, ca și descriptorii de sesiune, pur și simplu trebuie să fie trimise printr-un mecanism de semnalizare. Dacă descriptorul de sesiune conținea informații despre setările noastre la nivel de cameră și microfon, atunci candidații conțin informații despre locația noastră în rețea. Transmite-le la un alt nod și se va putea conecta fizic la noi și, deoarece are deja un descriptor de sesiune, se va putea conecta în mod logic și datele vor „fluge”. Dacă își amintește să ne trimită obiectul său candidat, adică informații despre locul în care se află el însuși în rețea, atunci vom putea să ne conectăm cu el. Să remarcăm aici încă o diferență față de interacțiunea clasică client-server. Comunicarea cu serverul HTTP are loc conform schemei cerere-răspuns, clientul trimite date către server, care le prelucrează și le trimite prin adresa specificată în pachetul de solicitare. În WebRTC trebuie să știți două adreseși conectați-le pe ambele părți.

Diferența față de descriptorii de sesiune este că doar candidații la distanță trebuie să fie instalați. Editarea aici este interzisă și nu poate aduce niciun beneficiu. În unele implementări WebRTC, candidații trebuie instalați numai după ce au fost setați descriptorii de sesiune.

De ce a existat un singur descriptor de sesiune, dar ar putea fi mulți candidați? Pentru că locația în rețea poate fi determinată nu numai de adresa IP internă, ci și de adresa externă a routerului, și nu neapărat doar una, precum și de adresele serverelor TURN. Restul paragrafului va fi dedicat unei discuții detaliate despre candidați și despre modul de conectare a nodurilor din diferite rețele private.

Deci, două noduri sunt în aceeași rețea (Figura 8). Cum să le identificăm? Utilizarea adreselor IP. Nici o alta cale. Adevărat, puteți utiliza în continuare transporturi diferite (TCP și UDP) și porturi diferite. Acestea sunt informațiile care sunt conținute în obiectul candidat - IP, PORT, TRANSPORT și altele. Să folosim, de exemplu, transportul UDP și portul 531.

Figura 8: Două noduri sunt în aceeași rețea

Apoi, dacă ne aflăm în nodul p1, atunci WebRTC ne va oferi un astfel de obiect candidat - . Acesta nu este un format exact, doar o diagramă. Dacă ne aflăm la nodul p2, atunci candidatul este . Prin mecanismul de semnalizare, p1 va primi candidatul lui p2 (adică locația nodului p2, și anume IP și PORT-ul acestuia). Apoi p1 se poate conecta direct la p2. Mai corect, p1 va trimite date la 10.50.150.3:531 în speranța că va ajunge p2. Nu contează dacă această adresă aparține nodului p2 sau unui intermediar. Singurul lucru important este că datele vor fi trimise prin această adresă și pot ajunge la p2.

Atâta timp cât nodurile sunt în aceeași rețea, totul este simplu și ușor - fiecare nod are un singur obiect candidat (însemnând întotdeauna propriul său, adică locația sa în rețea). Dar vor fi mult mai mulți candidați când nodurile vor fi introduse diferit retelelor.

Să trecem la un caz mai complex. Un nod va fi situat în spatele routerului (mai precis, în spatele NAT), iar al doilea nod va fi situat în aceeași rețea cu acest router (de exemplu, pe Internet) (Figura 9).

Figura 9: Un nod este în spatele NAT, celălalt nu

Acest caz are o soluție specială la problemă, pe care acum o vom lua în considerare. Router de acasă de obicei conține un tabel NAT. Acesta este un mecanism special conceput pentru a permite nodurilor din interiorul rețelei private a routerului să acceseze, de exemplu, site-uri web.

Să presupunem că serverul web este conectat direct la Internet, adică are o adresă IP publică *. Fie acesta nodul p2. Nodul p1 (client web) trimite o solicitare la adresa 10.50.200.10. În primul rând, datele merg către routerul r1, sau mai degrabă către acesta interior interfață 192.168.0.1. După care, routerul își amintește adresa sursă (adresa p1) și o introduce într-un tabel NAT special, apoi schimbă adresa sursă în propria sa (p1 → r1). Mai departe, în felul meu extern interfață, routerul trimite date direct către serverul web p2. Serverul web prelucrează datele, generează un răspuns și îl trimite înapoi. Trimite r1 către router, deoarece se află în adresa de retur (routerul a înlocuit adresa cu propria sa). Routerul primește datele, se uită la tabelul NAT și transmite datele către nodul p1. Routerul acţionează ca un intermediar aici.

Ce se întâmplă dacă mai multe noduri din rețeaua internă accesează simultan rețeaua externă? Cum va înțelege routerul cui să trimită răspunsul înapoi? Această problemă este rezolvată folosind porturi. Când un router înlocuiește adresa gazdă cu propria sa, acesta înlocuiește și portul. Dacă două noduri accesează Internetul, atunci routerul își înlocuiește porturile sursă cu diferit. Apoi, când pachetul de la serverul web revine la router, routerul va înțelege după port cui este alocat pachetul. Exemplu de mai jos.

Să revenim la tehnologia WebRTC, sau mai exact, la partea din ea care folosește protocolul ICE (de unde și candidatii Ice). Nodul p2 are un singur candidat (locația sa în rețea este 10.50.200.10), iar nodul p1, care se află în spatele routerului cu NAT, va avea doi candidați - local (192.168.0.200) și candidat router (10.50.200.5). Primul nu este util, dar este generat totuși, deoarece WebRTC nu știe încă nimic despre nodul la distanță - poate fi sau nu în aceeași rețea. Al doilea candidat va veni la îndemână și, după cum știm deja, portul (pentru a trece prin NAT) va juca un rol important.

O intrare în tabelul NAT este generată numai atunci când datele părăsesc rețeaua internă. Prin urmare, nodul p1 trebuie să transmită datele mai întâi și numai după aceea datele de la nodul p2 pot ajunge la nodul p1.

La practică ambele noduri va fi în spatele NAT. Pentru a crea o intrare în tabelul NAT al fiecărui router, gazdele trebuie să trimită ceva gazdei la distanță, dar de data aceasta nici prima nu poate ajunge la cea din urmă și nici invers. Acest lucru se datorează faptului că nodurile nu își cunosc adresele IP externe, iar trimiterea datelor către adrese interne este inutilă.

Cu toate acestea, dacă adresele externe sunt cunoscute, conexiunea se va stabili cu ușurință. Dacă primul nod trimite date către routerul celui de-al doilea nod, routerul le va ignora, deoarece tabelul său NAT este încă gol. Cu toate acestea, în routerul primului nod, a apărut o intrare necesară în tabelul NAT. Dacă acum al doilea nod trimite date către routerul primului nod, atunci routerul le va transfera cu succes la primul nod. Acum tabelul NAT al celui de-al doilea router are și datele necesare.

Problema este că pentru a afla adresa IP externă, aveți nevoie de un nod localizat în rețea partajată. Pentru a rezolva această problemă, sunt folosite servere suplimentare care sunt conectate direct la Internet. Cu ajutorul lor, în tabelul NAT sunt create și intrări apreciate.

Servere STUN și TURN

Când inițializați WebRTC, trebuie să specificați serverele STUN și TURN disponibile, pe care de acum înainte le vom numi servere ICE. Dacă serverele nu sunt specificate, atunci numai nodurile din aceeași rețea (conectate la aceasta fără NAT) se vor putea conecta. Este imediat de remarcat faptul că pentru rețelele 3g utilizarea serverelor TURN este obligatorie.

STUN Server este pur și simplu un server de pe Internet care returnează o adresă de retur, adică adresa nodului expeditorului. Gazda din spatele routerului contactează serverul STUN pentru a traversa NAT. Pachetul care a ajuns la serverul STUN conține adresa sursă - adresa routerului, adică adresa externă a nodului nostru. Aceasta este adresa STUN pe care serverul o trimite înapoi. Astfel, nodul își primește adresa IP externă și portul prin care este accesibil din rețea. În continuare, WebRTC folosește această adresă pentru a crea un candidat suplimentar (adresă și port de ruter extern). Acum există o intrare în tabelul NAT al routerului care permite pachetelor trimise către router pe portul necesar să ajungă la nodul nostru.

Să ne uităm la acest proces cu un exemplu.

Exemplu (operare server STUN)

Serverul STUN va fi notat cu s1. Routerul, ca mai înainte, trece prin r1, iar nodul trece prin p1. De asemenea, va trebui să monitorizați tabelul NAT - îl vom desemna ca r1_nat. Mai mult, acest tabel conține de obicei multe înregistrări de la diferite noduri ale subrețelei - acestea nu vor fi date.

Deci, la început avem un tabel gol r1_nat.

Tabelul 2: Antet pachet

Nodul p1 trimite acest pachet către routerul r1 (indiferent cum, pot folosi diferite subrețele tehnologii diferite). Routerul trebuie să înlocuiască adresa sursă Src IP, deoarece adresa specificată în pachet nu este în mod evident potrivită pentru o subrețea externă; în plus, adresele dintr-un astfel de interval sunt rezervate și nici o singură adresă de pe Internet nu are o astfel de adresă. Routerul face o înlocuire în pachet și creează intrare nouăîn tabelul tău r1_nat. Pentru a face acest lucru, trebuie să vină cu un număr de port. Amintiți-vă că, deoarece mai multe gazde dintr-o subrețea pot accesa o rețea externă, tabelul NAT trebuie să fie stocat Informații suplimentare, astfel încât routerul să poată determina care dintre aceste câteva noduri este destinat pachetului de returnare de la server. Lăsați routerul să vină cu portul 888.

Antetul pachetului modificat:

Tabelul 4: Tabelul NAT a fost actualizat cu o nouă intrare

Aici adresa IP și portul pentru subrețea sunt exact aceleași cu pachetul original. De fapt, la postback, trebuie să avem o modalitate de a le restaura complet. Adresa IP pentru rețeaua externă este adresa routerului, iar portul s-a schimbat în cel inventat de router.

Portul real pe care nodul p1 acceptă conexiunea este, desigur, 35777, dar serverul trimite date către fictiv portul 888, care va fi schimbat de router în 35777 real.

Deci, routerul a înlocuit adresa sursă și portul din antetul pachetului și a adăugat o intrare la tabelul NAT. Acum pachetul este trimis prin rețea către server, adică nodul s1. La intrare, s1 are următorul pachet:

Src IP Src PORT Dest IP Dest PORT
10.50.200.5 888 12.62.100.200 6000

Tabelul 5: Pachetul primit de serverul STUN

În total, serverul STUN știe că a primit un pachet de la adresa 10.50.200.5:888. Acum serverul trimite această adresă înapoi. Merită să ne oprim aici și să aruncăm o altă privire la ceea ce tocmai ne-am uitat. Tabelele de mai sus sunt un fragment din antet pachet, deloc din el conţinut. Nu am vorbit despre conținut, deoarece nu este atât de important - este descris cumva în protocolul STUN. Acum vom lua în considerare, pe lângă titlu, și conținutul. Va fi simplu și va conține adresa routerului - 10.50.200.5:888, deși am luat-o de la antet pachet. Acest lucru nu se face des; protocoalelor de obicei nu le pasă de informațiile despre adresele nodurilor; este important doar ca pachetele să fie livrate la destinația dorită. Aici ne uităm la un protocol care stabilește o cale între două noduri.

Deci acum avem un al doilea pachet care merge în direcția opusă:

Tabelul 7: Serverul STUN trimite un pachet cu acest conținut

Apoi, pachetul călătorește prin rețea până când ajunge la interfața externă a routerului r1. Routerul înțelege că pachetul nu este destinat acestuia. Cum înțelege el asta? Acest lucru poate fi determinat doar de port. El nu folosește portul 888 în scopuri personale, ci îl folosește pentru mecanismul NAT. Prin urmare, routerul se uită la acest tabel. Se uită la coloana PORT extern și caută o linie care se potrivește cu PORT-ul de destinație din pachetul de intrare, adică 888.

IP intern PORT intern IP extern PORT extern
192.168.0.200 35777 10.50.200.5 888

Tabelul 8: Tabelul NAT

Suntem norocoși, o astfel de linie există. Dacă am avea ghinion, pachetul ar fi pur și simplu aruncat. Acum trebuie să înțelegeți ce nod din subrețea ar trebui să trimită acest pachet. Nu trebuie să ne grăbim, să ne amintim din nou importanța porturilor în acest mecanism. În același timp, două noduri de pe subrețea ar putea trimite cereri către rețeaua externă. Apoi, dacă routerul a venit cu portul 888 pentru primul nod, atunci pentru al doilea ar veni cu portul 889. Să presupunem că acest lucru s-a întâmplat, adică tabelul r1_nat arată astfel:

Tabelul 10: Routerul înlocuiește adresa receptorului

Src IP Src PORT Dest IP Dest PORT
12.62.100.200 6000 192.168.0.200 35777

Tabelul 11: Routerul a schimbat adresa receptorului

Pachetul ajunge cu succes la nodul p1 și, uitându-se la conținutul pachetului, nodul află despre adresa sa IP externă, adică adresa routerului din rețeaua externă. El știe și portul pe care routerul îl trece prin NAT.

Ce urmeaza? La ce folosesc toate astea? Un beneficiu este o intrare în tabelul r1_nat. Dacă acum cineva trimite un pachet cu portul 888 către routerul r1, atunci routerul va trimite acest pachet către nodul p1. Acest lucru a creat un mic pasaj îngust către nodul ascuns p1.

Din exemplul de mai sus vă puteți face o idee despre cum funcționează NAT și despre esența unui server STUN. În general, mecanismul ICE și serverele STUN/TURN au drept scop depășirea restricțiilor NAT.

Între nod și server nu pot exista un singur router, ci mai multe. În acest caz, nodul va primi adresa routerului care este primul care accesează aceeași rețea ca și serverul. Cu alte cuvinte, vom obține adresa routerului conectat la serverul STUN. Pentru comunicarea p2p, exact de asta avem nevoie, dacă nu uităm de faptul că fiecare router va adăuga linia de care avem nevoie la tabelul NAT. Prin urmare, drumul înapoi va fi din nou la fel de lin.

Serverul TURN este un server STUN îmbunătățit. De aici ar trebui să înlăturați imediat că orice server TURN poate funcționa și ca server STUN. Cu toate acestea, există și avantaje. Dacă comunicarea p2p este imposibilă (ca, de exemplu, în rețelele 3g), atunci serverul trece în modul releu, adică funcționează ca intermediar. Bineînțeles, atunci nu vorbim despre niciun p2p, dar în afara mecanismului ICE, nodurile cred că comunică direct.

În ce cazuri este necesar un server TURN? De ce nu există suficient server STUN? Cert este că există mai multe tipuri de NAT. Ele înlocuiesc adresa IP și portul în același mod, dar unele dintre ele au protecție suplimentară împotriva „falsificării” încorporată în ele. De exemplu, în simetric Tabelul NAT stochează încă 2 parametri - IP și portul gazdei la distanță. Un pachet din rețeaua externă trece prin NAT către rețeaua internă numai dacă adresa sursă și portul se potrivesc cu cele înregistrate în tabel. Prin urmare, trucul cu serverul STUN eșuează - tabelul NAT stochează adresa și portul serverului STUN și, atunci când routerul primește un pachet de la interlocutorul WebRTC, îl aruncă pentru că este „falsificat”. Nu a venit de pe serverul STUN.

Astfel, este nevoie de un server TURN în cazul în care ambii interlocutori sunt în urmă simetric NAT (fiecare la el).

Rezumat scurt

Iată câteva afirmații despre entitățile WebRTC pe care ar trebui să le țineți întotdeauna în minte. Ele sunt descrise în detaliu mai sus. Dacă vreuna dintre afirmații nu vi se pare complet clară, recitiți paragrafele relevante.

  • Flux media
    • Datele video și audio sunt împachetate în fluxuri media
    • Fluxurile media sincronizează melodiile media care alcătuiesc
    • Fluxurile media diferite nu sunt sincronizate între ele
    • Fluxurile media pot fi locale și la distanță, cel local este de obicei conectat la o cameră și un microfon, cei la distanță primesc date din rețea în formă criptată
    • Există două tipuri de piese media - pentru video și pentru audio.
    • Piesele media au capacitatea de a activa/dezactiva
    • Piesele media constau din canale media
    • Piesele media sincronizează canalele media care alcătuiesc
    • Fluxurile media și melodiile media au etichete prin care pot fi distinse
  • Mânerul de sesiune
    • Descriptorul de sesiune este folosit pentru a conecta logic două noduri de rețea
    • Descriptorul de sesiune stochează informații despre modalități disponibile codificarea datelor video și audio
    • WebRTC utilizează un mecanism de semnalizare extern - sarcina de a transmite descriptori de sesiune (sdp) revine aplicației
    • Mecanismul de conectare logică constă din două etape - oferta (oferta) și răspunsul (răspunsul)
    • Generarea unui descriptor de sesiune este imposibilă fără utilizarea unui flux media local în cazul unei oferte și este imposibilă fără utilizarea unui descriptor de sesiune la distanță în cazul unui răspuns.
    • Descriptorul rezultat trebuie dat implementării WebRTC și nu contează dacă acest descriptor este primit de la distanță sau local de la aceeași implementare WebRTC
    • Este posibil să editați ușor descriptorul de sesiune
  • Candidați
    • Ice candidate este adresa unui nod din rețea
    • Adresa nodului poate fi propria dvs. sau poate fi adresa unui router sau server TURN
    • Întotdeauna sunt mulți candidați
    • Candidatul constă dintr-o adresă IP, port și tip de transport (TCP sau UDP)
    • Candidații sunt folosiți pentru a stabili o conexiune fizică între două noduri dintr-o rețea
    • De asemenea, candidații trebuie să fie trimiși printr-un mecanism de semnalizare
    • De asemenea, candidații trebuie să fie trecuți la implementările WebRTC, dar numai la cele de la distanță
    • În unele implementări WebRTC, candidații pot fi transmise numai după ce a fost setat un descriptor de sesiune
  • STUN/TURN/ICE/NAT
    • NAT este un mecanism de furnizare a accesului la o rețea externă
    • Routerele de acasă suportă un tabel NAT special
    • Routerul înlocuiește adresele din pachete - adresa sursă cu propria sa, dacă pachetul merge la o rețea externă, iar adresa receptorului cu adresa gazdă în rețeaua internă, dacă pachetul a venit dintr-o rețea externă
    • Pentru a oferi acces multicanal la o rețea externă, NAT utilizează porturi
    • ICE - NAT Traversal Engine
    • Servere STUN și TURN – servere asistente pentru traversarea NAT
    • Serverul STUN vă permite să creați intrările necesare în tabelul NAT și returnează, de asemenea, adresa externă a gazdei
    • Serverul TURN generalizează mecanismul STUN și îl face să funcționeze mereu
    • În cele mai rele cazuri, serverul TURN este folosit ca intermediar (releu), adică p2p se transformă într-o conexiune client-server-client.

Astăzi, WebRTC este tehnologia „fierbinte” pentru streaming audio și video în browsere. Tehnologiile conservatoare, precum HTTP Streaming și Flash, sunt mai potrivite pentru distribuirea conținutului înregistrat (video la cerere) și sunt semnificativ inferioare WebRTC în ceea ce privește transmisiile în timp real și online, de exemplu. unde este necesară o latență video minimă pentru a permite spectatorilor să vadă „în direct” ce se întâmplă.

Posibilitatea unei comunicări de înaltă calitate în timp real provine din arhitectura WebRTC în sine, unde protocolul UDP este utilizat pentru transportul fluxurilor video, care reprezintă baza standard pentru transmiterea video cu întârzieri minime și este utilizat pe scară largă în sistemele de comunicații în timp real.

Latența comunicării este importantă în sistemele de difuzare online, webinarii și alte aplicații care necesită comunicare interactivă cu sursa video, utilizatorii finali și necesită o soluție.

Un alt motiv bun pentru a încerca WebRTC este că este cu siguranță o tendință. Astăzi fiecare Android browser Chrome acceptă această tehnologie, care garantează milioane de dispozitive gata să vizioneze emisiunea fără a instala niciun software sau configurații suplimentare.

Pentru a testa tehnologia WebRTC în acțiune și a rula un simplu difuzare online, am folosit software-ul server Flashphoner WebRTC Media & Broadcasting Server. Caracteristicile indică capacitatea de a difuza fluxuri WebRTC în modul unu-la-mulți, precum și suport pentru camere IP și sisteme de supraveghere video prin protocolul RTSP; În această recenzie ne vom concentra asupra transmisiunilor web-web și a caracteristicilor acestora.

Instalarea WebRTC Media & Broadcasting Server

Deoarece pentru sisteme Windows nu exista o versiune de server și nu am vrut să instalez o mașină virtuală precum VMWare+Linux, astfel încât să pot testa emisiunile online acasă computer Windows Nu a funcționat. Pentru a economisi timp, am decis să luăm un exemplu de găzduire în cloud ca acesta:

Era Centos x86_64 versiunea 6.5 fără niciun software preinstalat în centrul de date din Amsterdam. Astfel, tot ce avem la dispoziție este serverul și accesul ssh la acesta. Pentru cei care sunt familiarizați cu comenzile consolei Linux, instalarea unui server WebRTC promite a fi simplă și nedureroasă. Deci ce am facut:

1. Descărcați arhiva:

$wget https://site/download-wcs5-server.tar.gz

2. Despachetați:

$tar -xzf download-wcs5-server.tar.gz

3. Instalați:

$cd FlashphonerWebCallServer

În timpul instalării, introduceți adresa IP a serverului: XXX.XXX.XXX.XXX

4. Activați licența:

$cd /usr/local/FlashphonerWebCallServer/bin

$./activare.sh

5. Porniți serverul WCS:

$service webcallserver pornire

6. Verificați jurnalul:

$tail - f /usr/local/FlashphonerWebCallServer/logs/flashphoner_manager.log

7. Verificați dacă cele două procese sunt la locul lor:

$ps aux | grep Flashphoner

Procesul de instalare este finalizat.

Testarea emisiunilor online WebRTC

Testarea emisiunilor s-a dovedit a fi o chestiune simplă. Pe lângă server, există un client web, care constă dintr-o duzină de fișiere Javascript, HTML și CSS și a fost implementat de noi în folderul /var/www/html în timpul etapei de instalare. Singurul lucru care trebuia făcut a fost să introduceți adresa IP a serverului în configurația flashphoner.xml, astfel încât clientul web să poată stabili o conexiune cu serverul prin HTML5 Websockets. Să descriem procesul de testare.

1. Deschideți pagina clientului de testare index.html în browserul Chrome:

2. Pentru a începe difuzarea, trebuie să faceți clic pe butonul „Start” din mijlocul ecranului.
Înainte de a face acest lucru, trebuie să vă asigurați că camera web este conectată și gata de utilizare. Nu există cerințe speciale pentru camera web; de exemplu, am folosit o cameră standard încorporată într-un laptop cu o rezoluție de 1280x800.

Browserul Chrome va cere cu siguranță acces la cameră și microfon, astfel încât utilizatorul să înțeleagă că videoclipul său va fi trimis pe serverul de Internet și permite acest lucru.

3. Interfața reprezintă o difuzare cu succes a fluxului video de la cameră către serverul WebRTC. În colțul din dreapta sus, un indicator indică faptul că fluxul merge către server; în colțul de jos există un buton „Oprire” pentru a opri trimiterea videoclipului.

Vă rugăm să rețineți linkul din caseta de mai jos. Conține un identificator unic pentru acest flux, astfel încât oricine se poate alătura vizionarii. Doar deschideți acest link în browser. Pentru a o copia în clipboard, faceți clic pe butonul „Copiere”.

În aplicații reale precum webinarii, prelegeri, transmisii video online sau TV interactiv, dezvoltatorii vor trebui să implementeze distribuirea acestui identificator către anumite grupuri de telespectatori, astfel încât să se poată conecta la fluxurile dorite, dar aceasta este deja logica aplicației. . WebRTC Media & Broadcasting Server nu îl afectează, ci doar distribuie video.

5. Se stabilește conexiunea și spectatorul vede fluxul pe ecran. Acum poate trimite un link către altcineva, poate opri redarea fluxului sau poate activa modul ecran complet folosind comenzile din colțul din dreapta jos.

Rezultatele testării serverului de difuzare online WebRTC

În timpul testelor, latența părea perfectă. Ping-ul către centrul de date a fost de aproximativ 100 de milisecunde, iar întârzierea a fost invizibilă pentru ochi. De aici, putem presupune că întârzierea reală este aceeași 100 plus sau minus câteva zeci de milisecunde pentru timpul de tamponare. Comparativ cu Flash video: în astfel de teste, Flash nu se comportă la fel de bine ca WebRTC. Deci, dacă vă mutați mâna pe o rețea similară, mișcarea de pe ecran poate fi văzută numai după una sau două secunde.

În ceea ce privește calitatea, observăm că cuburile se pot distinge uneori prin mișcări. Acest lucru este în concordanță cu natura codecului VP8 și cu scopul său principal - de a oferi comunicații video în timp real cu o calitate acceptabilă și fără întârzieri de comunicare.

Serverul este destul de ușor de instalat și configurat; rularea acestuia nu necesită abilități serioase, altele decât cunoștințele de Linux la nivelul unui utilizator avansat, care poate executa comenzi din consolă prin ssh și utilizează editor de text. Drept urmare, am reușit să stabilim o difuzare online unu-la-mulți între browsere. Conectarea spectatorilor suplimentari la flux, de asemenea, nu a pus probleme.

Calitatea difuzării s-a dovedit a fi destul de acceptabilă pentru webinarii și transmisiunile online. Singurul lucru care a ridicat câteva întrebări a fost rezoluția video. Camera acceptă 1280x800, dar rezoluția din imaginea de test este foarte asemănătoare cu 640x480. Aparent, această problemă trebuie clarificată cu dezvoltatorii.

Videoclip despre testarea transmisiei de la o cameră web
prin serverul WebRTC

Tehnologiile pentru efectuarea de apeluri din browser există de mulți ani: Java, ActiveX, Adobe Flash...În ultimii câțiva ani a devenit clar că pluginurile și au plecat mașini virtuale Nu strălucesc prin comoditate (de ce ar trebui să instalez nimic?) și, cel mai important, cu securitate. Ce să fac? Există o ieșire!

Până nu demult, rețelele IP foloseau mai multe protocoale pentru telefonia IP sau video: SIP, cel mai comun protocol, H.323 și MGCP care ies din scenă, Jabber/Jingle (utilizat în Gtalk), Adobe RTMP* semi-deschis și, bineînțeles , Skype închis. Proiectul WebRTC, inițiat de Google, încearcă să schimbe starea de fapt în lumea IP și a telefoniei web, făcând toate telefoane soft, inclusiv Skype. WebRTC nu numai că implementează toate capabilitățile de comunicare direct în interiorul browserului, care acum este instalat pe aproape fiecare dispozitiv, dar încearcă și să rezolve simultan o problemă mai generală de comunicare între utilizatorii browserului (schimb de date diverse, difuzare pe ecran, colaborare cu documente și mult mai mult).

WebRTC din perspectiva dezvoltatorului web

Din punctul de vedere al unui dezvoltator web, WebRTC constă din două părți principale:

  • controlul fluxurilor media din resurse locale (camera, microfon sau ecran calculator local) este implementat de metoda navigator.getUserMedia, care returnează un obiect MediaStream;
  • comunicare peer-to-peer între dispozitive care generează fluxuri media, inclusiv definirea metodelor de comunicare și transmiterea lor directă - obiecte RTCPeerConnection (pentru trimiterea și primirea fluxurilor audio și video) și RTCDataChannel (pentru trimiterea și primirea datelor din browser).
Ce facem?

Ne vom da seama cum să organizăm un chat video simplu cu mai mulți utilizatori între browsere bazat pe WebRTC folosind socket-uri web. Vom începe să experimentăm în Chrome/Chromium, ca fiind cele mai avansate browsere în ceea ce privește WebRTC, deși Firefox 22, lansat pe 24 iunie, aproape i-a ajuns din urmă. Trebuie spus că standardul nu a fost încă adoptat, iar API-ul se poate schimba de la o versiune la alta. Toate exemplele au fost testate în Chromium 28. Pentru simplitate, nu vom monitoriza curățenia codului și compatibilitatea între browsere.

MediaStream

Prima și cea mai simplă componentă WebRTC este MediaStream. Oferă browserului acces la fluxurile media de la camera și microfonul computerului local. În Chrome, pentru aceasta trebuie să apelați funcția navigator.webkitGetUserMedia() (întrucât standardul nu este încă finalizat, toate funcțiile vin cu un prefix, iar în Firefox aceeași funcție se numește navigator.mozGetUserMedia()). Când îl suni, utilizatorului i se va cere să permită accesul la cameră și microfon. Va fi posibilă continuarea apelului numai după ce utilizatorul își dă acordul. Parametrii fluxului media necesar și două funcții de apel invers sunt trecuți ca parametri acestei funcție: primul va fi apelat dacă accesul la cameră/microfon este obținut cu succes, al doilea - în cazul unei erori. Mai întâi, să creăm un fișier HTML rtctest1.html cu un buton și un element:

WebRTC - primul videoclip introductiv (înălțime: 240px; lățime: 320px; chenar: 1px gri solid; ) getUserMedia

Microsoft CU-RTC-Web

Microsoft nu ar fi Microsoft dacă nu ar răspunde imediat inițiativei Google prin lansarea propriei opțiuni non-standard incompatibile, numită CU-RTC-Web (html5labs.interoperabilitybridges.com/cu-rtc-web/cu-rtc-web. htm). Deși ponderea IE, deja mică, continuă să scadă, numărul utilizatorilor Skype îi dă Microsoft speranță de a înlocui Google și se poate presupune că acest standard special va fi utilizat în browser. versiuni Skype. Standardul Google se concentrează în primul rând pe comunicarea între browsere; în același timp, cea mai mare parte a traficului de voce rămâne în continuare pe rețeaua de telefonie obișnuită, iar gateway-uri între aceasta și rețelele IP sunt necesare nu numai pentru ușurință în utilizare sau distribuție mai rapidă, ci și ca mijloc de monetizare care va permite mai multor jucători să dezvolta-le. Apariția unui alt standard poate duce nu numai la nevoia neplăcută pentru dezvoltatori de a suporta două tehnologii incompatibile simultan, ci și în viitor să ofere utilizatorului o gamă mai largă de funcționalități posibile și soluții tehnice disponibile. Așteaptă și vezi.

Activarea fluxului local

În interiorul etichetelor fișierului nostru HTML, să declarăm o variabilă globală pentru fluxul media:

Var localStream = null;

Primul parametru al metodei getUserMedia trebuie să specifice parametrii fluxului media solicitat - de exemplu, activați pur și simplu audio sau video:

Var streamConstraints = ("audio": adevărat, "video": adevărat); // Solicită acces atât la audio, cât și la video

Sau specificați parametri suplimentari:

Var streamConstraints = ( „audio”: adevărat, „video”: ( „obligatoriu”: ( „maxWidth”: „320”, „maxHeight”: „240”, „maxFrameRate”: „5”), „opțional”: ) );

Al doilea parametru al metodei getUserMedia trebuie să fie transmis funcției de apel invers, care va fi apelată dacă are succes:

Funcția getUserMedia_success(stream) ( console.log("getUserMedia_success():", stream); localVideo1.src = URL.createObjectURL(stream); // Conectați fluxul media la elementul HTML localStream = stream; // și salvați-l într-o variabilă globală pentru utilizare ulterioară)

Al treilea parametru este o funcție de apel invers, un handler de erori care va fi apelat în cazul unei erori

Funcția getUserMedia_error(eroare) ( console.log("getUserMedia_error():", eroare); )

Apelul propriu-zis la metoda getUserMedia este o solicitare de acces la microfon și cameră atunci când este apăsat primul buton

Funcția getUserMedia_click() ( console.log ("getUserMedia_click()"); navigator.webkitGetUserMedia(streamConstraints, getUserMedia_success, getUserMedia_error); )

Nu este posibil să accesați un flux media dintr-un fișier deschis local. Dacă încercăm să facem acest lucru, vom primi eroarea:

NavigatorUserMediaError (cod: 1, PERMISSION_DENIED: 1)"

Să încărcăm fișierul rezultat pe server, să îl deschidem în browser și, ca răspuns la solicitarea care apare, să permitem accesul la cameră și microfon.

Puteți selecta dispozitivele la care Chrome va avea acces în Setări, Afișați linkul pentru setări avansate, secțiunea Confidențialitate, butonul Conținut. În browserele Firefox și Opera, dispozitivele sunt selectate dintr-o listă derulantă direct atunci când accesul este permis.

Când se utilizează protocolul HTTP, se va solicita permisiunea de fiecare dată când se accesează fluxul media după ce pagina s-a încărcat. Trecerea la HTTPS vă va permite să afișați cererea o dată, doar prima dată când accesați fluxul media.

Observați cercul pulsatoriu din pictograma marcajului și pictograma camerei din partea dreaptă a barei de adrese:

RTCMediaConnection

RTCMediaConnection este un obiect conceput pentru a stabili și transmite fluxuri media prin rețea între participanți. În plus, acest obiect este responsabil pentru generarea unei descriere a sesiunii media (SDP), obținerea de informații despre candidații ICE pentru traversarea NAT sau firewall-uri(local și folosind STUN) și interacțiunea cu serverul TURN. Fiecare participant trebuie să aibă o RTCMediaConnection per conexiune. Fluxurile media sunt transmise folosind protocolul SRTP criptat.

Servere TURN

Există trei tipuri de candidați ICE: gazdă, srflx și releu. Gazda conține informații primite local, srflx - cum arată nodul pentru un server extern (STUN) și releu - informații pentru transmiterea traficului prin serverul TURN. Dacă nodul nostru se află în spatele NAT, atunci candidații gazdă vor conține adrese localeși va fi inutil, candidații srflx vor ajuta doar cu anumite tipuri de NAT și releul va fi ultima speranță de a trece traficul printr-un server intermediar.

Exemplu de candidat ICE de tip gazdă, cu adresa 192.168.1.37 și portul udp/34022:

A=candidat:337499441 2 udp 2113937151 192.168.1.37 34022 tip generație gazdă 0

Format general pentru specificarea serverelor STUN/TURN:

Var servere = ( "iceServers": [ ( "url": "stun:stun.stunprotocol.org:3478" ), ( "url": "turn:user@host:port", "credential": "parolă") ]);

Există multe servere publice STUN pe Internet. Există o listă mare, de exemplu. Din păcate, rezolvă prea puține probleme. Practic nu există servere TURN publice, spre deosebire de STUN. Acest lucru se datorează faptului că serverul TURN trece prin fluxuri media, care pot încărca semnificativ atât canalul de rețea, cât și serverul însuși. Prin urmare, cel mai simplu mod de a vă conecta la serverele TURN este să îl instalați singur (evident, veți avea nevoie de un IP public). Dintre toate serverele, în opinia mea, cel mai bun este rfc5766-turn-server. Există chiar și o imagine gata făcută pentru Amazon EC2.

Cu TURN, nu totul este la fel de bine pe cât ne-am dori, dar dezvoltarea activă este în curs de desfășurare și aș dori să sper că după ceva timp WebRTC, dacă nu este egal cu Skype în ceea ce privește calitatea trecerii prin traducerea adresei (NAT) și firewall-uri , este cel puțin vizibil se va apropia.

RTCMediaConnection necesită un mecanism suplimentar de schimb de informații de control pentru a stabili o conexiune - deși generează aceste date, nu le transmite, iar transmiterea către alți participanți trebuie implementată separat.


Alegerea metodei de transfer revine dezvoltatorului - cel puțin manual. De îndată ce are loc schimbul de date necesare, RTCMediaConnection va instala automat fluxuri media (dacă este posibil, desigur).

model ofertă-răspuns

Pentru a stabili și modifica fluxurile media, se utilizează modelul de ofertă/răspuns (descris în RFC3264) și SDP (Session Description Protocol). Ele sunt, de asemenea, utilizate de protocolul SIP. În acest model, există doi agenți: Ofertantul - cel care generează descrierea SDP a sesiunii pentru a crea una nouă sau a modifica una existentă (Ofertă SDP), și Răspundetor - cel care primește descrierea SDP a sesiunii de la alt agent și răspunde cu propria sa descriere a sesiunii (Răspuns SDP). În același timp, specificația necesită un protocol de nivel superior (de exemplu, SIP sau propriul său peste socket-uri web, ca în cazul nostru), care este responsabil pentru transmiterea SDP între agenți.

Ce date trebuie transmise între două RTCMediaConnections, astfel încât acestea să poată stabili cu succes fluxuri media:

  • Primul participant care inițiază conexiunea formează o Ofertă în care transmite o structură de date SDP (același protocol este folosit în același scop în SIP) care descrie posibilele caracteristici ale fluxului media pe care urmează să-l transmită. Acest bloc de date trebuie transferat celui de-al doilea participant. Al doilea participant formează un Răspuns, cu SDP-ul său, și îl trimite primului.
  • Atât primul, cât și al doilea participant efectuează procedura de determinare a posibililor candidați ICE cu ajutorul cărora al doilea participant le poate transmite un flux media. Pe măsură ce candidații sunt identificați, informațiile despre aceștia ar trebui să fie transmise unui alt participant.

Oferta de formare

Pentru a genera o Ofertă, avem nevoie de două funcții. Primul va fi numit dacă este format cu succes. Al doilea parametru al metodei createOffer() este o funcție de apel invers apelată în cazul unei erori în timpul execuției sale (cu condiția ca thread-ul local să fie deja disponibil).

În plus, sunt necesari doi handlere de evenimente: onicecandidate când se definește un nou candidat ICE și onaddstream când se conectează un flux media din partea îndepărtată. Să revenim la dosarul nostru. Să adăugăm încă unul la HTML după liniile cu elemente:

createOffer

Și după linia cu elementul (pentru viitor):


De asemenea, la începutul codului JavaScript vom declara o variabilă globală pentru RTCPeerConnection:

Var pc1;

Când apelați constructorul RTCPeerConnection, trebuie să specificați serverele STUN/TURN. Pentru mai multe informații despre ele, consultați bara laterală; atâta timp cât toți participanții sunt în aceeași rețea, aceștia nu sunt necesari.

Var servere = nul;

Parametrii de pregătire a ofertei SDP

Var offerConstraints = ();

Primul parametru al metodei createOffer() este o funcție de apel invers apelată la formarea cu succes a unei oferte

Funcția pc1_createOffer_success(desc) ( console.log("pc1_createOffer_success(): \ndesc.sdp:\n"+desc.sdp+"desc:", desc); pc1.setLocalDescription(desc); // Setați RTCPeerConnection generat de Oferta SDP folosind metoda setLocalDescription. // Când partea îndepărtată își trimite SDP-ul de răspuns, va trebui să fie setată folosind metoda setRemoteDescription // Până când a doua parte este implementată, nu facem nimic // pc2_receivedOffer(desc); )

Al doilea parametru este o funcție de apel invers care va fi apelată în cazul unei erori

Funcția pc1_createOffer_error(eroare)( console.log("pc1_createOffer_success_error(): eroare:", eroare); )

Și să declarăm o funcție de apel invers la care candidații ICE vor fi trecuți pe măsură ce sunt determinați:

Funcția pc1_onicecandidate(event)( if (event.candidate) ( console.log("pc1_onicecandidate():\n"+ event.candidate.candidate.replace("\r\n", ""), event.candidate); // Până când a doua parte este implementată, nu facem nimic // pc2.addIceCandidate(new RTCIceCandidate(event.candidate)); ) )

Și, de asemenea, o funcție de apel invers pentru adăugarea unui flux media din partea îndepărtată (pentru viitor, deoarece deocamdată avem doar o singură conexiune RTCPeer):

Funcția pc1_onaddstream(event) ( console.log("pc_onaddstream()"); remoteVideo1.src = URL.createObjectURL(event.stream); )

Când faceți clic pe butonul „createOffer”, vom crea o RTCPeerConnection, vom seta metodele onicecandidate și onaddstream și vom solicita formarea unui Oferta SDP apelând metoda createOffer():

Funcția createOffer_click() ( console.log("createOffer_click()"); pc1 = nou webkitRTCPeerConnection(servere); // Creați RTCPeerConnection pc1.onicecandidate = pc1_onicecandidate; // Funcția de apel invers pentru procesarea candidaților ICE pc1.onaddstream = pc1/onaddstream; Funcția de apel invers apelată atunci când un flux media apare din partea îndepărtată. Încă nu există niciunul pc1.addStream(localStream); // Să transmitem fluxul media local (presupunând că a fost deja primit) pc1.createOffer(// Și de fapt solicităm formarea ofertei pc1_createOffer_success , pc1_createOffer_error, offerConstraints); )

Să salvăm fișierul ca rtctest2.html, să îl încărcăm pe server, să îl deschidem într-un browser și să vedem în consolă ce date sunt generate în timpul funcționării sale. Al doilea videoclip nu va apărea încă, deoarece există un singur participant. Să ne amintim că SDP este o descriere a parametrilor unei sesiuni media, codecurile disponibile, fluxurile media și candidații ICE sunt opțiuni posibile pentru conectarea la un anumit participant.

Formarea Answer SDP și schimbul de candidați ICE

Atât Oferta SDP, cât și fiecare dintre candidații ICE trebuie să fie transferați în cealaltă parte și acolo, după primirea acestora, RTCPeerConnection apelează metodele setRemoteDescription pentru Oferta SDP și addIceCandidate pentru fiecare candidat ICE primit din partea îndepărtată; asemanator in reversul pentru candidații Answer SDP și la distanță ICE. Răspunsul SDP în sine este format în mod similar cu Oferta; diferența este că nu metoda createOffer este apelată, ci metoda createAnswer, iar înainte de aceasta metoda RTCPeerConnection setRemoteDescription este transmisă la Oferta SDP primită de la apelant.

Să adăugăm un alt element video la HTML:

Și o variabilă globală pentru a doua RTCPeerConnection sub declarația primei:

Var pc2;

Procesarea ofertei și a răspunsului SDP

Formarea Answer SDP este foarte asemănătoare cu Oferta. În funcția de apel invers apelată la formarea cu succes a unui răspuns, similar cu Oferta, vom oferi o descriere locală și vom transmite SDP-ul de răspuns primit primului participant:

Funcția pc2_createAnswer_success(desc) ( pc2.setLocalDescription(desc); console.log("pc2_createAnswer_success()", desc.sdp); pc1.setRemoteDescription(desc); )

Funcția de apel invers, apelată în cazul unei erori la generarea răspunsului, este complet similară cu Oferta:

Funcția pc2_createAnswer_error(eroare) ( console.log("pc2_createAnswer_error():", eroare); )

Parametri pentru formarea răspunsului SDP:

Var answerConstraints = ( "obligatoriu": ( "OferToReceiveAudio":true, "OfferToReceiveVideo":true) );

Când al doilea participant primește Oferta, vom crea o Conexiune RTCPeer și vom forma un Răspuns în același mod ca și Oferta:

Funcția pc2_receivedOffer(desc) ( console.log("pc2_receiveOffer()", desc); // Creați un obiect RTCPeerConnection pentru al doilea participant în același mod ca primul pc2 = new webkitRTCPeerConnection(servere); pc2.onicecandidate = pc2_onicecandidate ; // Setați handlerul de evenimente când apare candidatul ICE pc2.onaddstream = pc_onaddstream; // Când apare un flux, conectați-l la HTML pc2.addStream(localStream); // Transferați fluxul media local (în exemplul nostru, al doilea participantul are același ca și primul) // Acum, când a doua RTCPeerConnection este gata, îi vom transmite oferta SDP primită (am trecut fluxul local primului) pc2.setRemoteDescription(new RTCSessionDescription(desc)); // Solicitați a doua conexiune pentru a genera date pentru mesajul de răspuns pc2.createAnswer(pc2_createAnswer_success, pc2_createAnswer_error, answerConstraints); )

Pentru a transfera Oferta SDP de la primul participant la al doilea în exemplul nostru, să o decomentăm în funcția pc1 createOffer succes() linie de apel:

Pc2_receivedOffer(desc);

Pentru a implementa procesarea candidaților ICE, să anulăm comentariul în gestionarea evenimentului de pregătire a candidatului ICE al primului participant pc1_onicecandidate() transferul acestuia către al doilea:

Pc2.addIceCandidate(nou RTCIceCandidate(event.candidate));

Managerul de evenimente de pregătire a candidatului ICE al celui de-al doilea participant este asemănător cu primul:

Funcția pc2_onicecandidate(event) ( if (event.candidate) ( console.log("pc2_onicecandidate():", event.candidate.candidate); pc1.addIceCandidate(nou RTCIceCandidate(event.candidate)); ) )

Funcția de apel invers pentru adăugarea unui flux media de la primul participant:

Funcția pc2_onaddstream(event) ( console.log("pc_onaddstream()"); remoteVideo2.src = URL.createObjectURL(event.stream); )

Încheierea conexiunii

Să adăugăm un alt buton la HTML

Închide

Și o funcție pentru a termina conexiunea

Funcția btnHangupClick() ( // Deconectați videoclipul local de la elementele HTML, opriți fluxul media local, set = null localVideo1.src = ""; localStream.stop(); localStream = null; // Pentru fiecare participant, dezactivați videoclipul din HTML elemente, închideți conexiunea, setați pointerul = null remoteVideo1.src = ""; pc1.close(); pc1 = null; remoteVideo2.src = ""; pc2.close(); pc2 = null; )

Să-l salvăm ca rtctest3.html, să-l încărcăm pe server și să-l deschidem în browser. Acest exemplu implementează transmisia bidirecțională a fluxurilor media între două conexiuni RTCPeerConnections din aceeași filă de browser. Pentru a organiza schimbul de Oferta și Răspuns SDP, candidații ICE între participanți și alte informații prin intermediul rețelei, în loc de proceduri de apelare directă, va fi necesară implementarea schimbului între participanți folosind un fel de transport, în cazul nostru - prize web.

Difuzare pe ecran

Funcția getUserMedia poate captura, de asemenea, ecranul și transmite în flux ca MediaStream, specificând următorii parametri:

Var mediaStreamConstraints = ( audio: fals, video: ( obligatoriu: ( chromeMediaSource: „ecran”), opțional: ) );

Pentru a accesa cu succes ecranul, trebuie îndeplinite câteva condiții:

  • activați semnalizarea capturii de ecran în getUserMedia() în chrome://flags/,chrome://flags/;
  • fișierul sursă trebuie descărcat prin HTTPS (origine SSL);
  • fluxul audio nu trebuie solicitat;
  • Cererile multiple nu trebuie executate într-o singură filă de browser.
Biblioteci pentru WebRTC

Deși WebRTC nu este încă terminat, au apărut deja câteva biblioteci bazate pe acesta. JsSIP este conceput pentru a crea telefoane software bazate pe browser care funcționează cu comutatoare SIP, cum ar fi Asterisk și Camalio. PeerJS va facilita crearea de rețele P2P pentru schimbul de date, iar Holla va reduce cantitatea de dezvoltare necesară pentru comunicarea P2P din browsere.

Node.js și socket.io

Pentru a organiza schimbul de candidați SDP și ICE între două RTCPeerConnections prin intermediul rețelei, folosim Node.js cu modulul socket.io.

Este descrisă instalarea celei mai recente versiuni stabile a Node.js (pentru Debian/Ubuntu).

$ 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

Instalare pentru alții OS descris

Sa verificam:

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

Folosind npm (Node Package Manager) vom instala socket.io și modulul expres suplimentar:

$ npm instalează socket.io express

Să-l testăm creând un fișier nodetest2.js pentru partea serverului:

$ nano nodetest2.js var app = require("express")() , server = require("http").createServer(app) , io = require("socket.io").listen(server); server.listen(80); // Dacă portul 80 este gratuit app.get("/", funcția (req, res) ( // Când accesați pagina rădăcină res.sendfile(__dirname + "/nodetest2.html"); // trimiteți fișierul HTML ) ); io.sockets.on("conexiune", funcția (socket) ( // La conectarea socket.emit ("eveniment server", ( salut: "lume" )); // trimite un mesaj socket.on ("eveniment client" , funcția (date) ( // și declară un handler de evenimente când sosește un mesaj de la client console.log(data); )); ));

Și nodetest2.html pentru partea client:

$ nano nodetest2.html var socket = io.connect("/"); // Adresa URL a serverului Websocket (pagina rădăcină a serverului de pe care a fost încărcată pagina) socket.on("eveniment server", funcția (date) ( console.log(data); socket.emit("eveniment client", ( "nume": "valoare" )); ));

Să pornim serverul:

$ sudo nodejs nodetest2.js

și deschideți pagina http://localhost:80 (dacă rulează local pe portul 80) în browser. Dacă totul are succes, în consola JavaScript a browserului vom vedea schimbul de evenimente între browser și server la conectare.

Schimb de informații între RTCPeerConnection prin intermediul socket-urilor web Partea client

Să salvăm exemplul nostru principal (rtcdemo3.html) sub noul nume rtcdemo4.html. Să includem biblioteca socket.io în elementul:

Și la începutul scriptului JavaScript - conectarea la websocket-uri:

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

Să înlocuim apelul direct la funcțiile altui participant trimițându-i un mesaj prin intermediul socket-urilor web:

Funcția createOffer_success(desc) ( ... // pc2_receivedOffer(desc); socket.emit("ofertă", desc); ... ) function pc2_createAnswer_success(desc) ( ... // pc1.setRemoteDescription(desc); socket .emit("răspuns", desc); ) funcția pc1_onicecandidate(eveniment) ( ... // pc2.addIceCandidate(nou RTCIceCandidate(event.candidate)); socket.emit("ice1", event.candidate); .. . ) funcția pc2_onicecandidate(eveniment) ( ... // pc1.addIceCandidate(nou RTCIceCandidate(event.candidate)); socket.emit("ice2", event.candidate); ... )

În funcția hangup(), în loc să apelăm direct funcțiile celui de-al doilea participant, vom transmite un mesaj prin intermediul socket-urilor web:

Funcția btnHangupClick() ( ... // remoteVideo2.src = ""; pc2.close(); pc2 = null; socket.emit ("închidere", ()); )

Și adăugați handlere de primire a mesajelor:

Socket.on("ofertă", funcție (date) ( console.log ("socket.on("ofertă"):", date); pc2_receivedOffer(date); )); socket.on(„răspuns”, funcție (date) (е console.log(„socket.on(„răspuns”):”, date); pc1.setRemoteDescription(new RTCSessionDescription(date)); )); socket.on("ice1", funcția (date) ( console.log ("socket.on("ice1"):", date); pc2.addIceCandidate(nou RTCIceCandidate(date)); )); socket.on("ice2", function (date) ( console.log ("socket.on("ice2"):", data); pc1.addIceCandidate(new RTCIceCandidate(data)); )); socket.on("închidere", funcție (date) ( console.log ("socket.on("închidere"):", date); remoteVideo2.src = ""; pc2.close(); pc2 = null; ) );

Partea serverului

Pe partea de server, salvați fișierul nodetest2 sub noul nume rtctest4.js și în interiorul funcției io.sockets.on(„connection”, function (socket) ( ... ) vom adăuga primirea și trimiterea mesajelor client:

Socket.on("ofertă", funcția (date) ( // Când primim mesajul "ofertă", // deoarece există o singură conexiune client în acest exemplu, // vom trimite mesajul înapoi prin același socket socket .emit("ofertă", date); // Dacă ar fi fost necesară redirecționarea mesajului peste toate conexiunile, // cu excepția expeditorului: // soket.broadcast.emit("ofertă", date); )); socket.on(„răspuns”, funcția (date) ( socket.emit(„răspuns”, date); )); socket.on("ice1", function (data) ( socket.emit ("ice1", data); )); socket.on("ice2", function (data) ( socket.emit ("ice2", data); )); socket.on(„închidere”, funcția (date) ( socket.emit(„închidere”, date); ));

În plus, să schimbăm numele fișierului HTML:

// res.sendfile(__dirname + "/nodetest2.html"); // Trimite fișierul HTML res.sendfile(__dirname + "/rtctest4.html");

Pornirea serverului:

$ sudo nodejs nodetest2.js

În ciuda faptului că codul ambilor clienți este executat în aceeași filă de browser, toată interacțiunea dintre participanții din exemplul nostru se desfășoară complet prin rețea și „separarea” participanților nu necesită dificultăți speciale. Totuși, ceea ce am făcut a fost și foarte simplu - aceste tehnologii sunt bune pentru că sunt ușor de utilizat. Chiar dacă uneori înșelător. În special, să nu uităm că fără serverele STUN/TURN exemplul nostru nu va putea funcționa în prezența traducerii adreselor și a firewall-urilor.

Concluzie

Exemplul rezultat este foarte convențional, dar dacă universalizăm ușor handlerele de evenimente, astfel încât acestea să nu difere între apelant și partea apelată, în loc de două obiecte pc1 și pc2, faceți o matrice RTCPeerConnection și implementați creație dinamicăși eliminând elemente, veți obține un chat video complet utilizabil. Nu există specificații speciale asociate cu WebRTC și un exemplu de chat video simplu pentru mai mulți participanți (precum și textele tuturor exemplelor din articol) se află pe discul care vine cu revista. Cu toate acestea, puteți găsi deja destul de multe pe internet. exemple bune. În special, la pregătirea articolului au fost folosite următoarele: simpl.info getUserMedia, simpl.info RTCPeerConnection, WebRTC Reference App.

Se poate presupune că foarte curând, datorită WebRTC, va avea loc o revoluție nu numai în înțelegerea noastră a comunicațiilor vocale și video, ci și în modul în care percepem Internetul ca întreg. WebRTC este poziționat nu doar ca o tehnologie pentru apelurile browser-la-browser, ci și ca o tehnologie de comunicare în timp real. Comunicarea video despre care am discutat este doar o mică parte opțiuni posibile utilizarea acestuia. Există deja exemple de screencasting și colaborare și chiar și o rețea de livrare de conținut P2P bazată pe browser folosind RTCDataChannel.




Top