WebRTC. Videokonferanser i nettleseren. Multi-user chat ved hjelp av WebRTC Webrtc stemmechat

Innledning. P2P-videochat på WebRTC-base er et alternativ til Skype og andre kommunikasjonsmidler. Hovedelementene i p2p-videochat basert på WebRTC er en nettleser og en kontaktserver. P2P-videochatter er peer-to-peer videochatter der serveren ikke tar del i overføringen av informasjonsstrømmer. Informasjon overføres direkte mellom brukernes nettlesere (peers) uten noen tilleggsprogrammer. I tillegg til nettlesere, bruker p2p-videochatter kontaktservere, som er designet for å registrere brukere, lagre data om dem og sikre veksling mellom brukere. Nettlesere som støtter de nyeste WebRTC- og HTML5-teknologiene gir umiddelbar tekstmeldinger og filoverføring, samt tale- og videokommunikasjon over IP-nettverk.

Så chatter, nettchatter, tale- og videochatter i et nettgrensesnitt, IMS, VoIP er tjenester som tilbyr nettbasert kommunikasjon gjennom sammensatte pakkesvitsjede nettverk. Kommunikasjonstjenester krever som regel enten installasjon av klientapplikasjoner på brukerenheter (PCer, smarttelefoner osv.) eller installasjon av plugins og utvidelser i nettlesere. Tjenester har egne kommunikasjonsnettverk, hvorav de fleste er bygget på en klient-server-arkitektur.

Kommunikasjonstjenester er andre applikasjoner enn IMS, der tale-, video-, data- og tekstkanalene ikke er integrert. I nettverkene til hver tjeneste, . Det skal bemerkes at disse applikasjonene ikke kan fungere samtidig i flere kommunikasjonsnettverk, dvs. Applikasjoner kan vanligvis ikke kommunisere med hverandre, og krever at en separat applikasjon installeres for hvert kommunikasjonsnettverk.

Problemet med å integrere sanntidskommunikasjonstjenester (chat, telefoni, videokonferanser), dvs. integrering av tale-, video-, datakanaler og tilgang til dem ved hjelp av én applikasjon (nettleser) kan løses i peer-to-peer eller p2p videochatter (peer-to-peer, punkt-til-punkt) basert på WebRTC-protokollen. I hovedsak blir en nettleser som støtter WebRTC et enkelt grensesnitt for alle brukerenheter (PCer, smarttelefoner, iPader, IP-telefoner, mobiltelefoner etc.) som jobber med kommunikasjonstjenester.

Det er WebRTC som sikrer implementering i nettleseren av alle teknologier som gir sanntidskommunikasjon. Essensen av p2p-videochatter er at multimedia- og tekstdata overføres direkte mellom brukernes nettlesere (ekstern peering) uten deltagelse av en server eller tilleggsprogrammer. Dermed gir nettlesere ikke bare tilgang til nesten alle informasjonsressurser Internett, som er lagret på servere, men som også blir et middel for tilgang til alle sanntidskommunikasjonstjenester og posttjenester (voicemail, e-post, SMS osv.)

Servere (kontaktservere) for p2p-videochatter er kun ment for å registrere brukere, lagre data om brukere og etablere en forbindelse (bytte) mellom brukernes nettlesere. De første p2p-videochattene ble implementert ved hjelp av flash-teknologier. Flash p2p videochatter brukes for eksempel i i sosiale nettverk. Flash p2p videochatter gir ikke høy kvalitet overføring av multimediedata. I tillegg, for å sende ut tale- og videostrøm fra mikrofonen og videokameraet i p2p flash-videochatter, må du installere flash plugin inn i en nettleser.

Men den nye generasjonen av telekommunikasjonstjenester inkluderer nettkommunikasjon, som kun bruker nettlesere og kontaktservere som støtter WebRTC-protokoller og HTML5-spesifikasjonen for å kommunisere over Internett. Enhver brukerenhet (PC, iPad, smarttelefoner, etc.) utstyrt med en slik nettleser kan gi høykvalitets tale- og videosamtaler, samt overføring av øyeblikkelige tekstmeldinger og filer.

Så den nye teknologien for nettkommunikasjon (p2p-chatter, videochatter) er WebRTC-protokollen. WebRTC sammen med HTML5, CSS3 og JavaScript lar deg lage ulike webapplikasjoner. WebRT er designet for å organisere nettkommunikasjon (peer-to-peer-nettverk) i sanntid ved å bruke en peer-to-peer-arkitektur. P2P-chatter basert på WebRTC gir filoverføring, samt tekst-, tale- og videokommunikasjon mellom brukere over Internett ved bruk av kun nettlesere uten bruk av eksterne tillegg og plug-ins i nettleseren.

I p2p-chatter brukes serveren kun til å etablere en p2p-forbindelse mellom to nettlesere. For å lage klientdelen av en p2p-chat basert på WebRTC-protokollen, brukes HTML5, CSS3 og JavaScript. Klientapplikasjonen samhandler med nettlesere via WebRTC API.

WebRTC er implementert av tre JavaScript APIer:

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

Nettlesere overfører mediedata ved hjelp av SRTP-protokollen, som kjører på toppen av UDP. Siden NAT skaper problemer for nettlesere (klienter) bak NAT-rutere som bruker p2p-tilkoblinger over Internett, brukes STUN til å omgå NAT-oversettere. STUN er en klient-server-protokoll som kjører på toppen av UDP-transportprotokollen. I p2p-chatter brukes som regel en offentlig STUN-server, og informasjonen som mottas fra den brukes til en UDP-forbindelse mellom to nettlesere hvis de står bak NAT.

Eksempler på implementering av WebRTC-applikasjoner (p2p-chatter, tale- og videonettchatter):
1. P2P videochat Bistri (ett-klikks videochat, p2p chat), basert på WebRTC, kan åpnes på Bistri. Bistri fungerer i nettleseren uten å installere tilleggsprogrammer og plugins. Essensen av arbeidet er som følger: åpne en p2p-videochat ved å bruke den angitte lenken, etter å ha registrert deg i grensesnittet som åpnes, inviter partnere, velg deretter partneren som er online og klikk på "videosamtale fra listen over jevnaldrende klienter "-knappen.

Som et resultat vil MediaStream (getUserMedia) fange opp mikrofonen + webkameraet, og serveren vil utveksle signalmeldinger med den valgte partneren. Etter å ha utvekslet signalmeldinger, oppretter PeerConnection API kanaler for overføring av tale- og videostrømmer. I tillegg overfører Bistri øyeblikkelige tekstmeldinger og filer. I fig. 1 viser et skjermbilde av Bistri p2p videochat-grensesnittet.


Ris. 1. P2P videochat Bistri

2. Twelephone (p2p videochat, p2p chat, SIP Twelephone) - denne klientapplikasjonen er bygget på grunnlag av HTML5 og WebRTC, som lar deg foreta tale- og videosamtaler, samt sende øyeblikkelige tekstmeldinger, dvs. Twelephone inkluderer test p2p chat, videochat og SIP Twelephone. Det skal bemerkes at Twelephone støtter SIP-protokollen og nå kan du ringe og motta tale- og videosamtaler fra SIP-telefoner ved å bruke Twitter-kontoen din som telefonnummer. I tillegg, tekstmeldinger du kan gå inn med stemmen gjennom mikrofonen, og stemmegjenkjenningsprogrammet skriver inn teksten i «Send en melding»-linjen.

Twelephone er en nettleserbasert netttelefoni Google Chrome, fra og med versjon 25, uten tillegg programvare. Twelephone ble utviklet av Chris Matthieu. Twelephone-backend er bygget på Node.js. Serveren (kontaktserveren) brukes kun til å etablere en p2p-forbindelse mellom to nettlesere eller WebRTC-klienter. Twelephone-applikasjonen har ikke egne autorisasjonsverktøy, men er fokusert på å koble til en konto ( regnskap) på Twitter.

I fig. 2 viser et skjermbilde av Twelephone p2p-videochatgrensesnittet.



Ris. 2. P2P Twelephone

3. Gruppe p2p videochat Conversat.io er bygget på de nyeste WebRTC- og HTML5-teknologiene. Conversat videochat er utviklet basert på SimpleWebRTC-biblioteket og er beregnet for kommunikasjon mellom opptil 6 peer-klienter i ett rom (for kommunikasjon, angi navnet på fellesrommet for peer-klienter i linjen "Nevn samtalen"). P2P videochat Conversat tilbyr kommunikasjonstjenester til brukere uten å registrere seg på kontaktserveren. I fig. Figur 3 viser et skjermbilde av Conversat p2p videochat-grensesnittet.



Ris. 3. Gruppe P2P videochat Conversat.io

For å delta i P2P-videochatter basert på WebRTC, må brukere ha en nettleser installert som støtter WebRTC-protokollen og HTML5-spesifikasjonen. For øyeblikket er Google Chrome-nettlesere, fra og med versjon 25, og Mozilla Firefox Nightly støtter WebRTC-protokollen og HTML5-spesifikasjonen. WebRTC-applikasjoner er overlegne Flash-applikasjoner når det gjelder bilde- og lydoverføringskvalitet.

Det meste av materialet på WebRTC er fokusert på applikasjonsnivået for koding og bidrar ikke til å forstå teknologien. La oss prøve å gå dypere og finne ut hvordan forbindelsen oppstår, hva en øktbeskrivelse og kandidater er, hvorfor STUN- og TURN-servere er nødvendig.

WebRTC-introduksjon

WebRTC er en nettleserorientert teknologi som lar deg koble til to klienter for videodataoverføring. Hovedfunksjonene er intern nettleserstøtte (det er ikke behov for tredjeparts implementerte teknologier som adobe flash) og muligheten til å koble til klienter uten bruk av ekstra servere - peer-to-peer-tilkobling (heretter p2p).

Å etablere en p2p-tilkobling er en ganske vanskelig oppgave, siden datamaskiner ikke alltid har offentlige IP-adresser, det vil si adresser på Internett. På grunn av det lille antallet IPv4-adresser (og for sikkerhetsformål), ble NAT-mekanismen utviklet, som lar deg opprette private nettverk, for eksempel for hjemmebruk. Mange hjemmerutere støtter nå NAT og takket være dette har alle hjemmeenheter tilgang til Internett, selv om Internett-leverandører vanligvis oppgir én IP-adresse. Offentlige IP-adresser er unike på Internett, men private er det ikke. Derfor er det vanskelig å koble til p2p.

For å forstå dette bedre, vurder tre situasjoner: begge nodene er på samme nettverk (Figur 1), begge nodene er på forskjellige nettverk (en privat, den andre i offentlig) (Figur 2) og begge nodene er i forskjellige private nettverk med de samme IP-adressene (Figur 3).

Figur 1: Begge noder på samme nettverk

Figur 2: Noder i forskjellige nettverk (en privat, en offentlig)

Figur 3: Noder i ulike private nettverk, men med numerisk like adresser

I figurene ovenfor indikerer den første bokstaven i to-tegns notasjonen nodetypen (p = peer, r = ruter). I det første bildet er situasjonen gunstig: noder i nettverket deres er fullstendig identifisert av nettverkets IP-adresser og kan derfor kobles direkte til hverandre. I den andre figuren har vi to forskjellige nettverk med like nodenummer. Det er her rutere (rutere) vises, som har to nettverksgrensesnitt– innenfor nettverket og utenfor nettverket. Det er derfor de har to IP-adresser. Vanlige noder har bare ett grensesnitt som de bare kan kommunisere gjennom i nettverket. Hvis de overfører data til noen utenfor nettverket deres, bruker de kun NAT inne i ruteren (ruteren) og er derfor synlig for andre under ruterens IP-adresse - det er deres utvendig IP adresse. Så node p1 har interiør IP = 192.168.0.200 Og utvendig IP = 10.50.200.5 , og den siste adressen vil også være ekstern i forhold til alle andre noder i nettverket. Situasjonen er lik for node p2. Derfor er kommunikasjonen deres umulig hvis bare deres interne (egne) IP-adresser brukes. Du kan bruke eksterne adresser, det vil si ruteradresser, men siden alle noder i samme private nettverk har samme eksterne adresse, er dette ganske vanskelig. Dette problemet kan løses ved hjelp av NAT-mekanismen

Hva vil skje hvis vi bestemmer oss for å koble noder gjennom deres interne adresser? Dataene vil ikke forlate nettverket. For å forsterke effekten kan du forestille deg situasjonen vist i den siste figuren - begge nodene har de samme interne adressene. Hvis de bruker dem til å kommunisere, vil hver node kommunisere med seg selv.

WebRTC takler slike problemer med suksess ved å bruke ICE-protokollen, som imidlertid krever bruk av ekstra servere (STUN, TURN). Mer om alt dette nedenfor.

To faser av WebRTC

For å koble til to noder via WebRTC-protokollen (eller ganske enkelt RTC, hvis to iPhones kommuniserer), må du utføre noen foreløpige trinn for å etablere forbindelsen. Dette er den første fasen - å etablere en forbindelse. Den andre fasen er videodataoverføring.

Det er verdt å si med en gang at selv om WebRTC-teknologi bruker mange på ulike måter kommunikasjon (TCP og UDP) og har fleksibel veksling mellom dem, denne teknologien har ikke en protokoll for overføring av tilkoblingsdata. Ikke overraskende, siden det ikke er så lett å koble to p2p-noder. Derfor er det nødvendig å ha noen ytterligere en metode for dataoverføring som på ingen måte er relatert til WebRTC. Det kan være en socketoverføring, HTTP-protokoll, det kan til og med være det SMTP-protokoll eller russisk post. Denne overføringsmekanismen første data kalles signal. Ikke mye informasjon trenger å formidles. Alle data overføres i tekstform og er delt inn i to typer - SDP og Ice Candidate. Den første typen brukes til å etablere en logisk forbindelse, og den andre for en fysisk forbindelse. Mer om alt dette senere, men foreløpig er det bare viktig å huske at WebRTC vil gi oss noe informasjon som må overføres til en annen node. Så snart vi overfører all nødvendig informasjon, vil nodene kunne koble seg sammen og vår hjelp vil ikke lenger være nødvendig. Så signalmekanismen vi må implementere er hver for seg, vil bli brukt bare når tilkoblet, men vil ikke brukes ved overføring av videodata.

Så la oss vurdere den første fasen - fasen for etablering av forbindelse. Den består av flere punkter. La oss først se på denne fasen for noden som starter forbindelsen, og deretter for den som venter.

  • Initiativtaker (oppringer):
  • Tilby om å starte videodataoverføring (createOffer)
  • Få din SDP SDP)
  • Motta din is-kandidat Is-kandidat)
  • Samtale venter (callee):
  • Motta en lokal (din) mediestrøm og sette den for overføring (getUserMediaStream)
  • Motta et tilbud om å starte videodataoverføring og lage et svar (createAnswer)
  • Mottar SDP-objektet og sender det gjennom signalmekanismen (SDP)
  • Motta dine Ice-kandidat-objekter og sende dem gjennom en signalmekanisme (Iskandidat)
  • Motta en ekstern (utenlandsk) mediestrøm og vise den på skjermen (onAddStream)

Den eneste forskjellen er i det andre punktet.

Til tross for den tilsynelatende kompleksiteten til trinnene, er det faktisk tre av dem: sende din egen mediestrøm (element 1), angi tilkoblingsparametere (elementer 2-4), motta andres mediestrøm (element 5). Det vanskeligste trinnet er det andre trinnet, fordi det består av to deler: etablering fysisk Og logisk forbindelser. Den første indikerer sti, langs hvilke pakker må reise for å komme fra en nettverksnode til en annen. Den andre indikerer video/lyd parametere– hvilken kvalitet du skal bruke, hvilke kodeker du skal bruke.

Mentalt sett bør createOffer eller createAnswer-stadiet være koblet til stadiene for å sende SDP- og Ice-kandidatobjekter.

Grunnleggende enheter Mediestrømmer (MediaStream)

Hovedenheten er mediestrømmen, det vil si strømmen av video- og lyddata, bilde og lyd. Det finnes to typer mediestrømmer - lokale og eksterne. Den lokale mottar data fra inndataenheter (kamera, mikrofon), og den eksterne via nettverket. Dermed har hver node både en lokal og en ekstern tråd. I WebRTC er det et MediaStream-grensesnitt for strømmer, og det er også et LocalMediaStream-undergrensesnitt spesifikt for en lokal strøm. I JavaScript kan du bare støte på den første, men hvis du bruker libjingle kan du også støte på den andre.

WebRTC har et ganske forvirrende hierarki i en tråd. Hver strøm kan bestå av flere mediespor (MediaTrack), som igjen kan bestå av flere mediekanaler (MediaChannel). Og det kan også være flere mediestrømmer selv.

La oss se på alt i rekkefølge. For å gjøre dette, la oss ha et eksempel i tankene. La oss si at vi ikke bare vil overføre en video av oss selv, men også en video av bordet vårt, der det ligger et stykke papir som vi skal skrive noe på. Vi trenger to videoer (oss + bord) og en lyd (oss). Det er klart at vi og tabellen bør deles inn i ulike tråder, fordi disse dataene sannsynligvis er svakt avhengige av hverandre. Derfor vil vi ha to MediaStreams – en for oss og en for bordet. Den første vil inneholde både video- og lyddata, og den andre vil kun inneholde video (Figur 4).

Figur 4: To forskjellige mediestrømmer. En for oss, en for bordet vårt

Det er umiddelbart klart at en mediestrøm som et minimum må inneholde muligheten til å inneholde data forskjellige typer- video og lyd. Dette tas hensyn til i teknologien og derfor implementeres hver type data gjennom et mediespor MediaTrack. Mediesporet har en spesiell egenskapstype , som bestemmer om det er video eller lyd (Figur 5)

Figur 5: Mediestrømmer består av mediespor

Hvordan vil alt skje i programmet? Vi skal lage to mediestrømmer. Deretter vil vi lage to videospor og ett lydspor. La oss få tilgang til kameraene og mikrofonen. La oss fortelle hvert spor hvilken enhet de skal bruke. La oss legge til et video- og lydspor til den første mediestrømmen og et videospor fra et annet kamera til den andre mediestrømmen.

Men hvordan skiller vi mediestrømmer i den andre enden av forbindelsen? For å gjøre dette har hver mediestrøm en etikettegenskap - etiketten til strømmen, dens navn (Figur 6). Mediespor har samme egenskap. Selv om det ved første øyekast ser ut til at video kan skilles fra lyd på andre måter.

Figur 6: Mediestrømmer og spor er identifisert med etiketter

Så hvis mediespor kan identifiseres gjennom en tag, hvorfor må vi da bruke to mediestrømmer for vårt eksempel, i stedet for én? Tross alt kan du overføre én mediestrøm, men bruke forskjellige spor i den. Vi har nådd en viktig egenskap ved mediestrømmer – de synkronisere mediespor. Ulike mediestrømmer er ikke synkronisert med hverandre, men innenfor hver mediestrøm alle spor spilles samtidig.

Derfor, hvis vi vil at ordene våre, ansiktsfølelsene og papiret vårt skal spilles av samtidig, er det verdt å bruke én mediestrøm. Hvis dette ikke er så viktig, er det mer lønnsomt å bruke forskjellige strømmer - bildet blir jevnere.

Hvis et spor må deaktiveres under overføring, kan du bruke egenskapen enabled for mediasporet.

Til slutt er det verdt å tenke på stereolyd. Som du vet er stereolyd to forskjellige lyder. Og de må også overføres separat. Mediakanaler brukes til dette. Et medielydspor kan ha mange kanaler (for eksempel 6 hvis du trenger 5+1 lyd). Det er også kanaler inne i mediesporene, selvfølgelig. synkronisert. For video brukes vanligvis bare én kanal, men flere kan brukes, for eksempel til overleggsannonsering.

Å oppsummere: Vi bruker en mediestrøm for å overføre video- og lyddata. Innenfor hver mediestrøm synkroniseres dataene. Vi kan bruke flere mediestrømmer hvis vi ikke trenger synkronisering. Inne i hver mediestrøm er det to typer mediespor - for video og for lyd. Det er vanligvis ikke mer enn to spor, men det kan være flere hvis du trenger å overføre flere forskjellige videoer (av samtalepartneren og bordet hans). Hvert spor kan bestå av flere kanaler, som vanligvis bare brukes til stereolyd.

I den enkleste videochatsituasjonen vil vi ha én lokal mediestrøm, som vil bestå av to spor – et videospor og et lydspor, som hver vil bestå av én hovedkanal. Videosporet er ansvarlig for kameraet, lydsporet er for mikrofonen, og mediestrømmen er beholderen for dem begge.

Sesjonsbeskrivelse (SDP)

Ulike datamaskiner vil alltid ha forskjellige kameraer, mikrofoner, skjermkort og annet utstyr. Det er mange alternativer de har. Alt dette må koordineres for medieoverføring av data mellom to nettverksnoder. WebRTC gjør dette automatisk og lager spesiell gjenstand– SDP-sesjonsbeskrivelse. Send dette objektet til en annen node, og mediedata kan overføres. Bare det er ingen forbindelse med en annen node ennå.

Enhver signalmekanisme brukes til dette. SDP kan overføres enten gjennom stikkontakter, eller av en person (fortell det til en annen node på telefon), eller med russisk post. Alt er veldig enkelt - du vil få en ferdig SDP, og du må sende den. Og når den mottas på den andre siden, overfør den til WebRTC-avdelingen. Sesjonsbeskrivelsen lagres som tekst og kan endres i applikasjonene dine, men dette er vanligvis ikke nødvendig. Som et eksempel, når du kobler til stasjonær ↔ telefon, må du noen ganger tvinge valget av ønsket lydkodek.

Vanligvis, når du oppretter en tilkobling, må du spesifisere en type adresse, for eksempel en URL. Dette er ikke nødvendig her, siden du gjennom signalmekanismen selv vil sende dataene til destinasjonen. For å indikere til WebRTC at vi ønsker å etablere en p2p-forbindelse, må vi kalle opp createOffer-funksjonen. Etter å ha kalt denne funksjonen og spesifisert en spesiell tilbakeringing 'a, vil et SDP-objekt bli opprettet og sendt til samme tilbakeringing. Alt som kreves av deg er å overføre dette objektet over nettverket til en annen node (samtaler). Etter dette vil data komme til den andre enden gjennom signalmekanismen, nemlig dette SDP-objektet. Denne sesjonsbeskrivelsen er fremmed for denne noden og inneholder derfor nyttig informasjon. Å motta dette objektet er et signal om å starte tilkoblingen. Derfor må du godta dette og kalle opp createAnswer-funksjonen. Det er en komplett analog av createOffer. Igjen vil den lokale sesjonsbeskrivelsen sendes til tilbakeringingen din, og den må sendes tilbake gjennom signalmekanismen.

Det er verdt å merke seg at du kun kan kalle createAnswer-funksjonen etter å ha mottatt en annens SDP-objekt. Hvorfor? Fordi det lokale SDP-objektet som vil bli generert når du kaller createAnswer, må stole på det eksterne SDP-objektet. Bare i dette tilfellet er det mulig å koordinere videoinnstillingene dine med innstillingene til samtalepartneren din. Du bør heller ikke ringe createAnswer og createOffer før du mottar den lokale mediestrømmen - de vil ikke ha noe å skrive til SDP-objektet.

Siden WebRTC har muligheten til å redigere et SDP-objekt, må det installeres etter å ha mottatt en lokal deskriptor. Det kan virke litt rart at vi trenger å overføre til WebRTC det det selv ga oss, men det er protokollen. Når et fjernhåndtak mottas, må det også installeres. Derfor må du installere to deskriptorer på en node - din og noen andres (det vil si lokal og ekstern).

Etter dette håndtrykk noder vet om hverandres ønsker. For eksempel, hvis node 1 støtter kodeker A og B, og node 2 støtter kodeker B og C, da, siden hver node kjenner sine egne og den andres deskriptorer, vil begge nodene velge kodek B (Figur 7). Forbindelseslogikken er nå etablert og mediestrømmer kan overføres, men det er et annet problem - nodene er fortsatt bare koblet sammen med en signalmekanisme.


Figur 7: Codec-forhandling

Is-kandidat

WebRTC-teknologien prøver å forvirre oss med sin nye metodikk. Når du oppretter en tilkobling, angis ikke adressen til noden du vil koble til. Installert først logisk forbindelse, ikke fysisk, selv om det motsatte alltid ble gjort. Men dette vil ikke virke rart hvis vi ikke glemmer at vi bruker en tredjeparts signalmekanisme.

Så tilkoblingen er allerede opprettet (logisk tilkobling), men det er fortsatt ingen vei som nettverksnodene kan overføre data langs. Det er ikke så enkelt, men la oss starte enkelt. La nodene være på det samme private nettverket. Som vi allerede vet, kan de enkelt koble til hverandre ved å bruke deres interne IP-adresser (eller kanskje noen andre, hvis ikke TCP/IP brukes).

Gjennom noen tilbakeringing og WebRTC informerer oss om Ice-kandidatobjekter. De kommer også i tekstform, og i likhet med øktbeskrivelser må de ganske enkelt sendes gjennom en signalmekanisme. Hvis øktbeskrivelsen inneholdt informasjon om våre innstillinger på kamera- og mikrofonnivå, så inneholder kandidatene informasjon om vår plassering på nettverket. Send dem videre til en annen node, og den vil fysisk kunne koble til oss, og siden den allerede har en sesjonsbeskrivelse, vil den logisk sett kunne koble til og dataene vil "flyte." Hvis han husker å sende oss kandidatobjektet sitt, det vil si informasjon om hvor han selv er på nettverket, så vil vi kunne få kontakt med ham. La oss her merke enda en forskjell fra den klassiske klient-server-interaksjonen. Kommunikasjon med HTTP-serveren skjer i henhold til forespørsel-svar-skjemaet, klienten sender data til serveren, som behandler det og sender det via adressen angitt i forespørselspakken. I WebRTC må du vite to adresser og koble dem på begge sider.

Forskjellen fra sesjonsbeskrivelser er at bare eksterne kandidater må installeres. Redigering her er forbudt og kan ikke gi noen fordel. I noen WebRTC-implementeringer må kandidater kun installeres etter at øktbeskrivelser er satt.

Hvorfor var det bare én sesjonsbeskrivelse, men det kunne være mange kandidater? Fordi plasseringen på nettverket ikke bare kan bestemmes av dens interne IP-adresse, men også av den eksterne adressen til ruteren, og ikke nødvendigvis bare én, samt adressene til TURN-servere. Resten av avsnittet vil bli viet til en detaljert diskusjon av kandidatene og hvordan man kobler sammen noder fra forskjellige private nettverk.

Så to noder er på samme nettverk (Figur 8). Hvordan identifisere dem? Bruker IP-adresser. Ingen annen vei. Riktignok kan du fortsatt bruke forskjellige transporter (TCP og UDP) og forskjellige porter. Dette er informasjonen som finnes i kandidatobjektet - IP, PORT, TRANSPORT og noen andre. La for eksempel bruke UDP-transport og port 531.

Figur 8: To noder er på samme nettverk

Så, hvis vi er i node p1, vil WebRTC gi oss et slikt kandidatobjekt - . Dette er ikke et eksakt format, bare et diagram. Hvis vi er på node p2, så er kandidaten . Gjennom signaleringsmekanismen vil p1 motta p2s kandidat (det vil si plasseringen av noden p2, nemlig dens IP og PORT). Da kan p1 kobles til p2 direkte. Mer korrekt vil p1 sende data til 10.50.150.3:531 i håp om at den når p2. Det spiller ingen rolle om denne adressen tilhører node p2 eller en mellomledd. Det eneste viktige er at data sendes via denne adressen og kan nå p2.

Så lenge noder er på samme nettverk, er alt enkelt og greit - hver node har bare ett kandidatobjekt (alltid betyr sitt eget, det vil si plasseringen i nettverket). Men det vil være mange flere kandidater når nodene er inne annerledes nettverk.

La oss gå videre til en mer kompleks sak. En node vil være plassert bak ruteren (mer presist, bak NAT), og den andre noden vil være plassert på samme nettverk med denne ruteren (for eksempel på Internett) (Figur 9).

Figur 9: En node er bak NAT, den andre er ikke

Denne saken har en spesiell løsning på problemet, som vi nå skal vurdere. Hjemmeruter inneholder vanligvis en NAT-tabell. Dette er en spesiell mekanisme designet for å gi noder inne i ruterens private nettverk tilgang til for eksempel nettsteder.

La oss anta at webserveren er koblet til Internett direkte, det vil si at den har en offentlig IP *-adresse. La dette være node p2. Node p1 (webklient) sender en forespørsel til adressen 10.50.200.10. Først går dataene til ruteren r1, eller rettere sagt til dens interiør grensesnitt 192.168.0.1. Deretter husker ruteren kildeadressen (adresse p1) og legger den inn i en spesiell NAT-tabell, og endrer deretter kildeadressen til sin egen (p1 → r1). Videre, på min egen måte utvendig grensesnitt, sender ruteren data direkte til p2 webserveren. Nettserveren behandler dataene, genererer et svar og sender det tilbake. Sender r1 til ruteren, siden den er i returadressen (ruteren erstattet adressen med sin egen). Ruteren mottar dataene, ser på NAT-tabellen og videresender dataene til node p1. Ruteren fungerer som mellomledd her.

Hva om flere noder fra det interne nettverket samtidig får tilgang til det eksterne nettverket? Hvordan vil ruteren forstå hvem den skal sende svaret tilbake til? Dette problemet løses ved hjelp av havner. Når en ruter erstatter vertsadressen med sin egen, erstatter den også porten. Hvis to noder får tilgang til Internett, erstatter ruteren deres kildeporter med annerledes. Så, når pakken fra webserveren kommer tilbake til ruteren, vil ruteren forstå ved porten hvem pakken er tildelt. Eksempel nedenfor.

La oss gå tilbake til WebRTC-teknologien, eller mer presist, til den delen av den som bruker ICE-protokollen (derav Ice-kandidatene). Node p2 har én kandidat (dens plassering i nettverket er 10.50.200.10), og node p1, som ligger bak ruteren med NAT, vil ha to kandidater - lokal (192.168.0.200) og ruterkandidat (10.50.200.5). Den første er ikke nyttig, men den genereres likevel, siden WebRTC ennå ikke vet noe om den eksterne noden - den kan være på samme nettverk eller ikke. Den andre kandidaten vil komme godt med, og som vi allerede vet vil havnen (for å komme gjennom NAT) spille en viktig rolle.

En oppføring i NAT-tabellen genereres bare når data forlater det interne nettverket. Derfor må node p1 overføre dataene først og først etter det kan data fra node p2 nå node p1.

På praksis begge nodene vil stå bak NAT. For å opprette en oppføring i hver ruters NAT-tabell, må vertene sende noe til den eksterne verten, men denne gangen kan verken førstnevnte nå sistnevnte eller omvendt. Dette skyldes det faktum at noder ikke kjenner sine eksterne IP-adresser, og det er meningsløst å sende data til interne adresser.

Men hvis de eksterne adressene er kjente, vil forbindelsen enkelt opprettes. Hvis den første noden sender data til ruteren til den andre noden, vil ruteren ignorere det, siden NAT-tabellen fortsatt er tom. Imidlertid, i ruteren til den første noden, dukket det opp en nødvendig oppføring i NAT-tabellen. Hvis nå den andre noden sender data til ruteren til den første noden, vil ruteren overføre dem til den første noden. Nå har NAT-tabellen til den andre ruteren også de nødvendige dataene.

Problemet er at for å finne ut din eksterne IP-adresse, trenger du en node i delt nettverk. For å løse dette problemet brukes ekstra servere som er direkte koblet til Internett. Med deres hjelp opprettes også dyrebare oppføringer i NAT-tabellen.

STUN og TURN servere

Når du initialiserer WebRTC, må du spesifisere tilgjengelige STUN- og TURN-servere, som vi heretter vil kalle ICE-servere. Hvis servere ikke er spesifisert, vil bare noder på samme nettverk (koblet til det uten NAT) kunne koble til. Det er umiddelbart verdt å merke seg at for 3g-nettverk er bruk av TURN-servere obligatorisk.

STUN server er ganske enkelt en server på Internett som returnerer en returadresse, det vil si adressen til avsenderens node. Verten bak ruteren kontakter STUN-serveren for å krysse NAT. Pakken som kom til STUN-serveren inneholder kildeadressen - ruteradressen, det vil si den eksterne adressen til noden vår. Dette er adressen STUN serveren sender tilbake. Dermed mottar noden sin eksterne IP-adresse og porten som den er tilgjengelig via nettverket. Deretter bruker WebRTC denne adressen til å opprette en ekstra kandidat (ekstern ruteradresse og port). Nå er det en oppføring i ruterens NAT-tabell som lar pakker sendt til ruteren på den nødvendige porten nå noden vår.

La oss se på denne prosessen med et eksempel.

Eksempel (STUN-serverdrift)

STUN-serveren vil bli merket med s1. Ruteren, som før, er gjennom r1, og noden er gjennom p1. Du må også overvåke NAT-tabellen - vi betegner den som r1_nat. Dessuten inneholder denne tabellen vanligvis mange poster fra forskjellige noder i undernettet - de vil ikke bli gitt.

Så i begynnelsen har vi en tom tabell r1_nat.

Tabell 2: Pakkehode

Node p1 sender denne pakken til ruter r1 (uansett hvordan, forskjellige undernett kan bruke ulike teknologier). Ruteren må erstatte kildeadressen Src IP, siden adressen spesifisert i pakken åpenbart ikke er egnet for et eksternt subnett; dessuten er adresser fra et slikt område reservert, og ikke en eneste adresse på Internett har en slik adresse. Ruteren gjør en erstatning i pakken og lager Ny inngang i tabellen r1_nat. For å gjøre dette, må han komme opp med et portnummer. Husk at siden flere verter i et subnett kan få tilgang til et eksternt nettverk, må NAT-tabellen lagre Tilleggsinformasjon, slik at ruteren kan bestemme hvilken av disse flere nodene som er bestemt for returpakken fra serveren. La ruteren komme med port 888.

Endret pakkeoverskrift:

Tabell 4: NAT-tabellen har blitt oppdatert med en ny oppføring

Her er IP-adressen og porten for subnettet nøyaktig det samme som originalpakken. Faktisk, når vi postbacking, må vi ha en måte å fullstendig gjenopprette dem. IP-adressen til det eksterne nettverket er adressen til ruteren, og porten er endret til den som ruteren har oppfunnet.

Den virkelige porten som node p1 aksepterer tilkoblingen på er selvfølgelig 35777, men serveren sender data til fiktiv port 888, som vil bli endret av ruteren til den ekte 35777.

Så ruteren erstattet kildeadressen og porten i pakkeoverskriften og la til en oppføring i NAT-tabellen. Nå sendes pakken over nettverket til serveren, det vil si node s1. Ved inngangen har s1 følgende pakke:

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

Tabell 5: STUN-server mottatt pakke

Totalt vet STUN-serveren at den mottok en pakke fra adressen 10.50.200.5:888. Nå sender serveren denne adressen tilbake. Det er verdt å stoppe her og ta en ny titt på det vi nettopp så på. Tabellene ovenfor er et utdrag fra Overskrift pakken, ikke i det hele tatt fra den innhold. Vi snakket ikke om innholdet, siden det ikke er så viktig - det er på en eller annen måte beskrevet i STUN-protokollen. Nå skal vi vurdere, i tillegg til tittelen, innholdet. Det vil være enkelt og inneholde ruteradressen - 10.50.200.5:888, selv om vi tok den fra Overskrift pakke. Dette gjøres ikke ofte; protokoller bryr seg vanligvis ikke om informasjon om nodeadresser; det er bare viktig at pakkene leveres til den tiltenkte destinasjonen. Her ser vi på en protokoll som etablerer en vei mellom to noder.

Så nå har vi en andre pakke som går i motsatt retning:

Tabell 7: STUN-server sender en pakke med dette innholdet

Deretter går pakken over nettverket til den når det eksterne grensesnittet til ruteren r1. Ruteren forstår at pakken ikke er ment for den. Hvordan forstår han dette? Dette kan kun bestemmes av havnen. Han bruker ikke port 888 til sine personlige formål, men bruker den til NAT-mekanismen. Derfor ser ruteren på denne tabellen. Ser på Ekstern PORT-kolonnen og ser etter en linje som samsvarer med Dest PORT fra den innkommende pakken, det vil si 888.

Intern IP Intern PORT Ekstern IP Ekstern PORT
192.168.0.200 35777 10.50.200.5 888

Tabell 8: NAT-tabell

Vi er heldige, en slik linje finnes. Hvis vi var uheldige, ville pakken rett og slett bli kastet. Nå må du forstå hvilken node på subnettet som skal sende denne pakken. Ingen grunn til å haste, la oss igjen huske viktigheten av porter i denne mekanismen. Samtidig kunne to noder på subnettet sende forespørsler til det eksterne nettverket. Så, hvis ruteren kom opp med port 888 for den første noden, ville den for den andre komme opp med port 889. La oss anta at dette skjedde, det vil si at r1_nat-tabellen ser slik ut:

Tabell 10: Ruteren erstatter mottakeradressen

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

Tabell 11: Ruteren endret mottakeradressen

Pakken ankommer med suksess til node p1, og ved å se på innholdet i pakken lærer noden om sin eksterne IP-adresse, det vil si adressen til ruteren på det eksterne nettverket. Han kjenner også porten som ruteren går gjennom NAT.

Hva blir det neste? Hva er nytten med alt dette? En fordel er en oppføring i tabellen r1_nat. Hvis nå noen sender en pakke med port 888 til ruter r1, så vil ruteren videresende denne pakken til node p1. Dette skapte en liten smal passasje til den skjulte noden p1.

Fra eksemplet ovenfor kan du få en ide om hvordan NAT fungerer og essensen av en STUN-server. Generelt er ICE-mekanismen og STUN/TURN-servere nøyaktig rettet mot å overvinne NAT-restriksjoner.

Mellom noden og serveren kan det ikke være én ruter, men flere. I dette tilfellet vil noden motta adressen til ruteren som er den første som får tilgang til samme nettverk som serveren. Med andre ord vil vi få adressen til ruteren koblet til STUN-serveren. For p2p-kommunikasjon er dette akkurat det vi trenger, hvis vi ikke glemmer det faktum at hver ruter vil legge til linjen vi trenger til NAT-tabellen. Derfor blir veien tilbake like jevn igjen.

TURN server er en forbedret STUN server. Herfra bør du umiddelbart ta bort at enhver TURN-server også kan fungere som en STUN-server. Men det er også fordeler. Hvis p2p-kommunikasjon er umulig (som for eksempel i 3g-nettverk), bytter serveren til relémodus, det vil si at den fungerer som en mellommann. Da snakker vi selvfølgelig ikke om noen p2p, men utenfor ICE-mekanismen tror noder at de kommuniserer direkte.

I hvilke tilfeller er en TURN-server nødvendig? Hvorfor er det ikke nok STUN-server? Faktum er at det finnes flere typer NAT. De erstatter IP-adressen og porten på samme måte, men noen av dem har ekstra beskyttelse mot "forfalskning" innebygd. For eksempel i symmetrisk NAT-tabellen lagrer ytterligere 2 parametere - IP og port til den eksterne verten. En pakke fra det eksterne nettverket går gjennom NAT til det interne nettverket bare hvis kildeadressen og porten samsvarer med de som er registrert i tabellen. Derfor mislykkes trikset med STUN-serveren - NAT-tabellen lagrer adressen og porten til STUN-serveren, og når ruteren mottar en pakke fra WebRTC-samtaleren, forkaster den den fordi den er "forfalsket". Den kom ikke fra STUN-serveren.

Dermed trengs en TURN-server i tilfellet når begge samtalepartnerne er bak symmetrisk NAT (hver til sin egen).

Kort oppsummering

Her er noen utsagn om WebRTC-enheter som du alltid bør huske på. De er beskrevet i detalj ovenfor. Hvis noen av utsagnene ikke virker helt klare for deg, les de relevante avsnittene på nytt.

  • Mediestrøm
    • Video- og lyddata pakkes inn i mediestrømmer
    • Mediestrømmer synkroniserer mediesporene som utgjør
    • Ulike mediestrømmer er ikke synkronisert med hverandre
    • Mediestrømmer kan være lokale og eksterne, den lokale er vanligvis koblet til et kamera og mikrofon, de eksterne mottar data fra nettverket i kryptert form
    • Det finnes to typer mediespor - for video og for lyd.
    • Mediespor har muligheten til å slå på/av
    • Mediespor består av mediekanaler
    • Mediespor synkroniserer mediekanalene som utgjør
    • Mediestrømmer og mediespor har etiketter som de kan skilles fra
  • Sesjonshåndtak
    • Sesjonsbeskrivelsen brukes til å logisk koble to nettverksnoder
    • Sesjonsbeskrivelsen lagrer informasjon om tilgjengelige måter koding av video- og lyddata
    • WebRTC bruker en ekstern signaleringsmekanisme - oppgaven med å videresende øktbeskrivelser (sdp) faller på applikasjonen
    • Den logiske koblingsmekanismen består av to trinn - tilbud (tilbud) og svar (svar)
    • Generering av en sesjonsbeskrivelse er umulig uten å bruke en lokal mediestrøm i tilfelle et tilbud og er umulig uten å bruke en ekstern sesjonsbeskrivelse i tilfelle et svar.
    • Den resulterende beskrivelsen må gis til WebRTC-implementeringen, og det spiller ingen rolle om denne deskriptoren mottas eksternt eller lokalt fra den samme WebRTC-implementeringen
    • Det er mulig å redigere øktbeskrivelsen litt
  • Kandidater
    • Iskandidat er adressen til en node i nettverket
    • Nodeadressen kan være din egen, eller den kan være adressen til en ruter eller TURN-server
    • Det er alltid mange kandidater
    • Kandidaten består av en IP-adresse, port og transporttype (TCP eller UDP)
    • Kandidater brukes til å etablere en fysisk forbindelse mellom to noder i et nettverk
    • Kandidater må også sendes gjennom en signalmekanisme
    • Kandidater må også overføres til WebRTC-implementeringer, men bare eksterne
    • I noen WebRTC-implementeringer kan kandidater bare overføres etter at en øktbeskrivelse er satt
  • STUN/TURN/ICE/NAT
    • NAT er en mekanisme for å gi tilgang til et eksternt nettverk
    • Hjemmerutere støtter en spesiell NAT-tabell
    • Ruteren erstatter adressene i pakkene - kildeadressen med sin egen, hvis pakken går til et eksternt nettverk, og mottakeradressen med vertsadressen på det interne nettverket, hvis pakken kom fra et eksternt nettverk
    • For å gi flerkanalstilgang til et eksternt nettverk, bruker NAT porter
    • ICE - NAT Traversal Engine
    • STUN- og TURN-servere – assistentservere for NAT-traversering
    • STUN-server lar deg opprette de nødvendige oppføringene i NAT-tabellen, og returnerer også den eksterne adressen til verten
    • TURN-serveren generaliserer STUN-mekanismen og gjør at den alltid fungerer
    • I de verste tilfellene brukes TURN-serveren som mellomledd (relé), det vil si at p2p blir til en klient-server-klient-forbindelse.

I dag er WebRTC den "hotte" teknologien for streaming av lyd og video i nettlesere. Konservative teknologier, som HTTP Streaming og Flash, er mer egnet for å distribuere innspilt innhold (video on demand) og er betydelig dårligere enn WebRTC når det gjelder sanntids- og nettsendinger, dvs. hvor minimal videoforsinkelse kreves for å la seerne se hva som skjer "live".

Muligheten for høykvalitets sanntidskommunikasjon kommer fra selve WebRTC-arkitekturen, der UDP-protokollen brukes til å transportere videostrømmer, som er standardgrunnlaget for overføring av video med minimale forsinkelser og er mye brukt i sanntidskommunikasjonssystemer.

Kommunikasjonsforsinkelse er viktig i nettbaserte kringkastingssystemer, webinarer og andre applikasjoner som krever interaktiv kommunikasjon med videokilden, sluttbrukere og krever en løsning.

En annen god grunn til å prøve WebRTC er at det definitivt er en trend. I dag hver Android Chrome-nettleser støtter denne teknologien, som garanterer at millioner av enheter er klare til å se sendingen uten å installere ekstra programvare eller konfigurasjoner.

For å teste WebRTC-teknologi i aksjon og kjøre en enkel nettsending, brukte vi Flashphoner WebRTC Media & Broadcasting Server serverprogramvare. Funksjonene angir muligheten til å kringkaste WebRTC-strømmer i en-til-mange-modus, samt støtte for IP-kameraer og videoovervåkingssystemer via RTSP-protokollen; I denne anmeldelsen vil vi fokusere på nett-nettsendinger og deres funksjoner.

Installere WebRTC Media & Broadcasting Server

Fordi for Windows-systemer det var ingen serverversjon, og jeg ville ikke installere en virtuell maskin som VMWare+Linux, så jeg kunne teste nettsendinger hjemme Windows-datamaskin Det gikk ikke. For å spare tid bestemte vi oss for å ta et eksempel på nettskyvert som dette:

Det var Centos x86_64 versjon 6.5 uten noen forhåndsinstallert programvare i Amsterdams datasenter. Alt vi har til rådighet er altså serveren og ssh-tilgangen til den. For de som er kjent med konsollkommandoer Linux, å installere en WebRTC-server lover å være enkelt og smertefritt. Så hva vi gjorde:

1. Last ned arkivet:

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

2. Pakk ut:

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

3. Installer:

$cd FlashphonerWebCallServer

Under installasjonen, skriv inn serverens IP-adresse: XXX.XXX.XXX.XXX

4. Aktiver lisensen:

$cd /usr/local/FlashphonerWebCallServer/bin

$./activation.sh

5. Start WCS-serveren:

$service webanropsserver start

6. Sjekk loggen:

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

7. Sjekk at de to prosessene er på plass:

$ps aux | grep Flashphoner

Installasjonsprosessen er fullført.

Testing av WebRTC-nettsendinger

Å teste sendingene viste seg å være en enkel sak. I tillegg til serveren er det en webklient, som består av et dusin Javascript-, HTML- og CSS-filer og ble distribuert av oss til /var/www/html-mappen under installasjonsfasen. Det eneste jeg måtte gjøre var å skrive inn serverens IP-adresse i flashphoner.xml-konfigurasjonen slik at webklienten kunne opprette en tilkobling til serveren via HTML5 Websockets. La oss beskrive testprosessen.

1. Åpne index.html testklientsiden i Chrome-nettleseren:

2. For å starte kringkastingen må du klikke på "Start"-knappen midt på skjermen.
Før du gjør dette, må du sørge for at webkameraet er tilkoblet og klart til bruk. Det er ingen spesielle krav til webkameraet; for eksempel brukte vi et standardkamera innebygd i en bærbar PC med en oppløsning på 1280x800.

Chrome-nettleseren vil definitivt be om tilgang til kameraet og mikrofonen slik at brukeren forstår at videoen hans vil bli sendt til Internett-serveren og tillater det.

3. Grensesnittet representerer en vellykket kringkasting av videostrømmen fra kameraet til WebRTC-serveren. I øvre høyre hjørne indikerer en indikator at strømmen går til serveren; i nedre hjørne er det en "Stopp"-knapp for å stoppe sendingen av videoen.

Legg merke til linken i boksen nedenfor. Den inneholder en unik identifikator for denne strømmen, slik at alle kan bli med på visningen. Bare åpne denne lenken i nettleseren din. For å kopiere den til utklippstavlen, klikk på "Kopier"-knappen.

I virkelige applikasjoner som webinarer, forelesninger, online videosendinger eller interaktiv TV, må utviklere implementere distribusjonen av denne identifikatoren til visse grupper av seere slik at de kan koble seg til de ønskede strømmene, men dette er allerede logikken til applikasjonen . WebRTC Media & Broadcasting Server påvirker ikke den, men distribuerer kun video.

5. Forbindelsen er opprettet og seeren ser strømmen på skjermen. Nå kan han sende en lenke til noen andre, stoppe strømmen eller aktivere fullskjermmodus ved å bruke kontrollene i nedre høyre hjørne.

Resultater av testing av WebRTC online kringkastingsserver

Under testene virket latensen perfekt. Pingen til datasenteret var på omtrent 100 millisekunder og forsinkelsen var usynlig for øyet. Herfra kan vi anta at den reelle forsinkelsen er den samme 100 pluss eller minus noen titalls millisekunder for buffertiden. Sammenlignet med Flash-video: i slike tester oppfører ikke Flash seg like bra som WebRTC. Så hvis du beveger hånden på et lignende nettverk, kan bevegelsen på skjermen bare sees etter ett eller to sekunder.

Når det gjelder kvalitet, merker vi at terninger noen ganger kan skilles ut ved bevegelser. Dette er i samsvar med naturen til VP8-kodeken og dens hovedformål - å gi sanntids videokommunikasjon med akseptabel kvalitet og uten kommunikasjonsforsinkelser.

Serveren er ganske enkel å installere og konfigurere; å kjøre den krever ingen seriøse ferdigheter annet enn kunnskap om Linux på nivået til en avansert bruker som kan utføre kommandoer fra konsollen via ssh og bruke tekstredigerer. Som et resultat klarte vi å sette opp en en-til-mange nettsending mellom nettlesere. Å koble flere seere til strømmen ga heller ingen problemer.

Kringkastingskvaliteten viste seg å være ganske akseptabel for webinarer og nettsendinger. Det eneste som reiste noen spørsmål var videooppløsningen. Kameraet støtter 1280x800, men oppløsningen i testbildet er veldig lik 640x480. Tilsynelatende må dette problemet avklares med utviklerne.

Video om testsending fra et webkamera
via WebRTC-server

Teknologier for å ringe fra nettleseren har eksistert i mange år: Java, ActiveX, Adobe Flash...I de siste årene har det blitt klart at plugins og venstre virtuelle maskiner De skinner ikke med bekvemmelighet (hvorfor skal jeg installere noe i det hele tatt?) og, viktigst av alt, med sikkerhet. Hva å gjøre? Det er en utgang!

Inntil nylig brukte IP-nettverk flere protokoller for IP-telefoni eller video: SIP, den vanligste protokollen, H.323 og MGCP som kommer fra scenen, Jabber/Jingle (brukt i Gtalk), halvåpen Adobe RTMP* og selvfølgelig , lukket Skype. WebRTC-prosjektet, initiert av Google, prøver å endre tingenes tilstand i verden av IP og netttelefoni, noe som gjør at alle softphones, inkludert Skype. WebRTC implementerer ikke bare alle kommunikasjonsmuligheter direkte inne i nettleseren, som nå er installert på nesten alle enheter, men prøver også å samtidig løse et mer generelt problem med kommunikasjon mellom nettleserbrukere (utveksling av ulike data, skjermkringkasting, samarbeid med dokumenter og mye mer).

WebRTC fra webutviklerens perspektiv

Fra en webutviklers synspunkt består WebRTC av to hoveddeler:

  • kontroll av mediestrømmer fra lokale ressurser (kamera, mikrofon eller skjerm lokal datamaskin) er implementert av navigator.getUserMedia-metoden, som returnerer et MediaStream-objekt;
  • peer-to-peer-kommunikasjon mellom enheter som genererer mediestrømmer, inkludert definering av kommunikasjonsmetoder og direkte overføring av dem - RTCPeerConnection-objekter (for sending og mottak av lyd- og videostrømmer) og RTCDataChannel (for sending og mottak av data fra nettleseren).
Hva skal vi gjøre?

Vi vil finne ut hvordan du organiserer en enkel flerbruker videochat mellom nettlesere basert på WebRTC ved å bruke nettsockets. Vi begynner å eksperimentere med Chrome/Chromium, som de mest avanserte nettleserne når det gjelder WebRTC, selv om Firefox 22, utgitt 24. juni, nesten har innhentet dem. Det skal sies at standarden ennå ikke er tatt i bruk, og API kan endres fra versjon til versjon. Alle eksemplene ble testet i Chromium 28. For enkelhets skyld vil vi ikke overvåke rensligheten av koden og kompatibilitet på tvers av nettlesere.

MediaStream

Den første og enkleste WebRTC-komponenten er MediaStream. Det gir nettleseren tilgang til mediestrømmer fra den lokale datamaskinens kamera og mikrofon. I Chrome må du for dette kalle funksjonen navigator.webkitGetUserMedia() (siden standarden ennå ikke er ferdigstilt, kommer alle funksjoner med et prefiks, og i Firefox kalles samme funksjon navigator.mozGetUserMedia()). Når du ringer det, vil brukeren bli bedt om å gi tilgang til kameraet og mikrofonen. Det vil være mulig å fortsette samtalen først etter at brukeren har gitt sitt samtykke. Parametrene til den nødvendige mediestrømmen og to tilbakeringingsfunksjoner sendes som parametere til denne funksjonen: den første vil bli kalt hvis tilgang til kameraet/mikrofonen er oppnådd, den andre - i tilfelle feil. La oss først lage en HTML-fil rtctest1.html med en knapp og et element:

WebRTC - første introduksjonsvideo (høyde: 240px; bredde: 320px; kantlinje: 1px solid grå; ) getUserMedia

Microsoft CU-RTC-Web

Microsoft ville ikke vært Microsoft hvis det ikke umiddelbart svarte på Googles initiativ ved å gi ut sitt eget inkompatible ikke-standardalternativ kalt CU-RTC-Web (html5labs.interoperabilitybridges.com/cu-rtc-web/cu-rtc-web. htm). Selv om andelen av IE, som allerede er liten, fortsetter å synke, gir antallet Skype-brukere Microsoft håp om å fortrenge Google, og det kan antas at denne spesielle standarden vil bli brukt i nettleseren Skype-versjoner. Google-standarden fokuserer først og fremst på kommunikasjon mellom nettlesere; samtidig forblir hoveddelen av taletrafikken fortsatt på det vanlige telefonnettverket, og gatewayer mellom det og IP-nettverk er ikke bare nødvendig for brukervennlighet eller raskere distribusjon, men også som et middel for inntektsgenerering som vil tillate flere spillere å utvikle dem. Fremveksten av en annen standard kan ikke bare føre til det ubehagelige behovet for utviklere å støtte to inkompatible teknologier samtidig, men også i fremtiden gi brukeren et bredere utvalg av mulig funksjonalitet og tilgjengelige tekniske løsninger. Vent og se.

Aktiverer lokal strøm

Inne i kodene til HTML-filen vår, la oss erklære en global variabel for mediestrømmen:

Var localStream = null;

Den første parameteren til getUserMedia-metoden må spesifisere parameterne for den forespurte mediestrømmen - for eksempel, aktiver ganske enkelt lyd eller video:

Var streamConstraints = ("lyd": sant, "video": sant); // Be om tilgang til både lyd og video

Eller spesifiser flere parametere:

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

Den andre parameteren til getUserMedia-metoden må sendes til tilbakeringingsfunksjonen, som vil bli kalt hvis den er vellykket:

Funksjon getUserMedia_success(stream) ( console.log("getUserMedia_success():", stream); localVideo1.src = URL.createObjectURL(stream); // Koble mediestrømmen til HTML-elementet localStream = stream; // og lagre den i en global variabel for videre bruk)

Den tredje parameteren er en tilbakeringingsfunksjon, en feilbehandler som vil bli kalt i tilfelle feil

Funksjon getUserMedia_error(error) ( console.log("getUserMedia_error():", error); )

Selve anropet til getUserMedia-metoden er en forespørsel om tilgang til mikrofonen og kameraet når den første knappen trykkes

Funksjon getUserMedia_click() ( console.log("getUserMedia_click()"); navigator.webkitGetUserMedia(streamConstraints, getUserMedia_success, getUserMedia_error); )

Det er ikke mulig å få tilgang til en mediestrøm fra en fil som er åpnet lokalt. Hvis vi prøver å gjøre dette, får vi feilmeldingen:

NavigatorUserMediaError (kode: 1, PERMISSION_DENIED: 1)"

La oss laste opp den resulterende filen til serveren, åpne den i nettleseren og, som svar på forespørselen som vises, gi tilgang til kameraet og mikrofonen.

Du kan velge enhetene som Chrome skal ha tilgang til i Innstillinger, Vis koblingen for avanserte innstillinger, Personvern-delen, Innhold-knappen. I nettlesere Firefox og Opera velges enheter fra en rullegardinliste direkte når tilgang er tillatt.

Når du bruker HTTP-protokollen, vil tillatelse bli bedt om hver gang mediestrømmen åpnes etter at siden er lastet inn. Ved å bytte til HTTPS kan du vise forespørselen én gang, bare den aller første gangen du får tilgang til mediestrømmen.

Legg merke til den pulserende sirkelen i bokmerkeikonet og kameraikonet på høyre side av adressefeltet:

RTCMediaConnection

RTCMediaConnection er et objekt designet for å etablere og overføre mediestrømmer over nettverket mellom deltakere. I tillegg er dette objektet ansvarlig for å generere en media session description (SDP), innhente informasjon om ICE-kandidater for å krysse NAT eller brannmurer(lokalt og bruker STUN) og interaksjon med TURN-serveren. Hver deltaker må ha én RTCMediaConnection per tilkobling. Mediestrømmer overføres ved hjelp av den krypterte SRTP-protokollen.

TURN servere

Det er tre typer ICE-kandidater: vert, srflx og stafett. Host inneholder informasjon mottatt lokalt, srflx - hvordan noden ser ut til en ekstern server (STUN), og relé - informasjon for proxying av trafikk gjennom TURN-serveren. Hvis noden vår er bak NAT, vil vertskandidater inneholde lokale adresser og vil være ubrukelig, vil srflx-kandidater bare hjelpe med visse typer NAT og relé vil være det siste håpet for å sende trafikk gjennom en mellomserver.

Eksempel på en ICE-kandidat av typen vert, med adresse 192.168.1.37 og port udp/34022:

A=kandidat:337499441 2 udp 2113937151 192.168.1.37 34022 type vertsgenerasjon 0

Generelt format for å spesifisere STUN/TURN-servere:

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

Det er mange offentlige STUN-servere på Internett. Det er en stor liste, for eksempel. Dessverre løser de for få problemer. Det er praktisk talt ingen offentlige TURN-servere, i motsetning til STUN. Dette skyldes at TURN-serveren går gjennom mediestrømmer, som kan belaste både nettverkskanalen og selve serveren betydelig. Derfor er den enkleste måten å koble til TURN-servere på å installere den selv (selvfølgelig trenger du en offentlig IP). Av alle serverne, etter min mening, er den beste rfc5766-turn-server. Det er til og med et ferdig bilde for Amazon EC2.

Med TURN er ikke alt så bra som vi ønsker, men aktiv utvikling er i gang, og jeg vil gjerne håpe at WebRTC etter en tid, om ikke lik Skype når det gjelder kvalitet på passasje gjennom adresseoversettelse (NAT) og brannmurer , er i hvert fall merkbart vil komme nærmere.

RTCMediaConnection krever en ekstra mekanisme for å utveksle kontrollinformasjon for å etablere en forbindelse - selv om den genererer disse dataene, overfører den ikke den, og overføring til andre deltakere må implementeres separat.


Valget av overføringsmetode ligger hos utvikleren – i hvert fall manuelt. Så snart utveksling av nødvendige data finner sted, vil RTCMediaConnection installere mediestrømmer automatisk (hvis mulig, selvfølgelig).

tilbud-svar-modell

For å etablere og endre mediestrømmer brukes tilbud/svar-modellen (beskrevet i RFC3264) og SDP (Session Description Protocol). De brukes også av SIP-protokollen. I denne modellen er det to agenter: Tilbyder - den som genererer SDP-beskrivelsen av sesjonen for å opprette en ny eller endre en eksisterende (Offer SDP), og Answerer - den som mottar SDP-beskrivelsen av sesjonen fra en annen agent og svarer med sin egen sesjonsbeskrivelse (Answer SDP). Samtidig krever spesifikasjonen en protokoll på høyere nivå (for eksempel SIP eller egne over web-sockets, som i vårt tilfelle), som er ansvarlig for å overføre SDP mellom agenter.

Hvilke data må sendes mellom to RTCMediaConnections slik at de kan etablere mediestrømmer:

  • Den første deltakeren som starter forbindelsen danner et tilbud der den overfører en SDP-datastruktur (den samme protokollen brukes til samme formål i SIP) som beskriver de mulige egenskapene til mediestrømmen som den er i ferd med å begynne å sende. Denne blokken med data må overføres til den andre deltakeren. Den andre deltakeren danner et svar, med sin SDP, og sender det til den første.
  • Både den første og andre deltakeren utfører prosedyren for å bestemme mulige ICE-kandidater ved hjelp av hvilken den andre deltakeren kan overføre en mediestrøm til dem. Etter hvert som kandidater blir identifisert, bør informasjon om dem gis videre til en annen deltaker.

Formasjonstilbud

For å generere et tilbud trenger vi to funksjoner. Den første vil bli kalt hvis den er vellykket dannet. Den andre parameteren til createOffer()-metoden er en tilbakeringingsfunksjon som kalles i tilfelle en feil under kjøringen (forutsatt at den lokale tråden allerede er tilgjengelig).

I tillegg er det nødvendig med to hendelsesbehandlere: én kandidat når man definerer en ny ICE-kandidat og onaddstream når man kobler til en mediestrøm fra den andre siden. La oss gå tilbake til filen vår. La oss legge til en til i HTML-en etter linjene med elementer:

oppretteTilbud

Og etter linjen med elementet (for fremtiden):


Også i begynnelsen av JavaScript-koden vil vi deklarere en global variabel for RTCPeerConnection:

Var pc1;

Når du kaller RTCPeerConnection-konstruktøren, må du spesifisere STUN/TURN-servere. For mer informasjon om dem, se sidefeltet; så lenge alle deltakerne er på samme nettverk, er de ikke påkrevd.

Var servere = null;

Parametre for å utarbeide tilbuds-SDP

Var offerConstraints = ();

Den første parameteren til createOffer()-metoden er en tilbakeringingsfunksjon som kalles ved vellykket dannelse av et tilbud

Funksjon pc1_createOffer_success(desc) ( console.log("pc1_createOffer_success(): \ndesc.sdp:\n"+desc.sdp+"desc:", desc); pc1.setLocalDescription(desc); // Sett RTCPeerConnection generert av Offer SDP ved å bruke setLocalDescription-metoden. // Når den andre siden sender sin Answer SDP, må den angis med setRemoteDescription-metoden // Inntil den andre siden er implementert, gjør vi ingenting // pc2_receivedOffer(desc); )

Den andre parameteren er en tilbakeringingsfunksjon som vil bli kalt i tilfelle en feil

Funksjon pc1_createOffer_error(error)( console.log("pc1_createOffer_success_error(): error:", error); )

Og la oss erklære en tilbakeringingsfunksjon som ICE-kandidater vil bli sendt til etter hvert som de bestemmes:

Funksjon pc1_onicecandidate(event)( if (event.candidate) ( console.log("pc1_onicecandidate():\n"+ event.candidate.candidate.replace("\r\n", ""), event.candidate); // Inntil den andre siden er implementert, gjør vi ingenting // pc2.addIceCandidate(new RTCIceCandidate(event.candidate)); ) )

Og også en tilbakeringingsfunksjon for å legge til en mediestrøm fra den andre siden (for fremtiden, siden vi foreløpig bare har én RTCPeerConnection):

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

Når du klikker på "createOffer"-knappen, vil vi opprette en RTCPeerConnection, angi onicecandidate og onaddstream-metodene og be om dannelsen av en Offer SDP ved å kalle createOffer()-metoden:

Funksjon createOffer_click() ( console.log("createOffer_click()"); pc1 = new webkitRTCPeerConnection(servere); // Create RTCPeerConnection pc1.onicecandidate = pc1_onicecandidate; // Tilbakeringingsfunksjon for behandling av ICE-kandidater pc1.onaddstream = pc1/onaddstream Tilbakeringingsfunksjon kalles når en mediestrøm dukker opp fra den andre siden. Det er ingen ennå pc1.addStream(localStream); // La oss overføre den lokale mediestrømmen (forutsatt at den allerede er mottatt) pc1.createOffer(// Og faktisk be om dannelsen av tilbudet pc1_createOffer_success , pc1_createOffer_error, offerConstraints); )

La oss lagre filen som rtctest2.html, laste den opp til serveren, åpne den i en nettleser og se i konsollen hvilke data som genereres under driften. Den andre videoen vil ikke vises ennå, siden det bare er én deltaker. La oss huske at SDP er en beskrivelse av parametrene til en medieøkt, tilgjengelige kodeker, mediestrømmer og ICE-kandidater er mulige alternativer for å koble til en gitt deltaker.

Dannelse av svar SDP og utveksling av ICE-kandidater

Både Offer SDP og hver av ICE-kandidatene må overføres til den andre siden, og der, etter å ha mottatt dem, kaller RTCPeerConnection opp setRemoteDescription-metodene for Offer SDP og addIceCandidate for hver ICE-kandidat mottatt fra den andre siden; tilsvarende i motsatt side for Answer SDP og eksterne ICE-kandidater. Selve Answer SDP er utformet på samme måte som Tilbudet; forskjellen er at det ikke er createOffer-metoden som kalles, men createAnswer-metoden, og før det sendes RTCPeerConnection-metoden setRemoteDescription til Offer SDP mottatt fra den som ringer.

La oss legge til et annet videoelement i HTML-en:

Og en global variabel for den andre RTCPeerConnection under erklæringen til den første:

Var pc2;

Behandler tilbud og svar SDP

Dannelsen av Answer SDP er veldig lik Offer. I tilbakeringingsfunksjonen som kalles på vellykket dannelse av et svar, som ligner på tilbud, vil vi gi en lokal beskrivelse og sende den mottatte svar-SDP til den første deltakeren:

Funksjon pc2_createAnswer_success(desc) ( pc2.setLocalDescription(desc); console.log("pc2_createAnswer_success()", desc.sdp); pc1.setRemoteDescription(desc); )

Tilbakeringingsfunksjonen, kalt i tilfelle en feil ved generering av svar, er fullstendig lik Tilbud:

Funksjon pc2_createAnswer_error(error) ( console.log("pc2_createAnswer_error():", error); )

Parametre for å danne svar-SDP:

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

Når den andre deltakeren mottar tilbudet, vil vi opprette en RTCPeerConnection og danne et svar på samme måte som tilbudet:

Funksjon pc2_receivedOffer(desc) ( console.log("pc2_receiveOffer()", desc); // Opprett et RTCPeerConnection-objekt for den andre deltakeren på samme måte som den første pc2 = new webkitRTCPeerConnection(servere); pc2.onicecandidate = pc2_onicecandidate ; // Angi hendelsesbehandleren når den vises ICE-kandidat pc2.onaddstream = pc_onaddstream; // Når en strøm vises, koble den til HTML pc2.addStream(localStream); // Overfør den lokale mediestrømmen (i vårt eksempel, den andre deltaker har den samme som den første) // Nå, når den andre RTCPeerConnection er klar, sender vi den mottatte Offer SDP (vi sendte den lokale strømmen til den første) pc2.setRemoteDescription(new RTCSessionDescription(desc)); // Be den andre tilkoblingen om å generere data for svarmeldingen pc2.createAnswer(pc2_createAnswer_success, pc2_createAnswer_error, answerConstraints); )

For å overføre Offer SDP fra den første deltakeren til den andre i vårt eksempel, la oss fjerne kommentarer i pc1-funksjonen oppretteTilbud suksess() anropslinje:

Pc2_receivedOffer(desc);

For å implementere behandlingen av ICE-kandidater, la oss fjerne kommentarer i ICE-kandidtil den første deltakeren pc1_onicecandidate() dens overføring til den andre:

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

Den andre deltakerens ICE-kander speillignende til den første:

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

Tilbakeringingsfunksjon for å legge til en mediestrøm fra den første deltakeren:

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

Avslutter forbindelsen

La oss legge til en annen knapp i HTML-en

Legg på

Og en funksjon for å avslutte forbindelsen

Funksjon btnHangupClick() ( // Koble lokal video fra HTML-elementer, stopp den lokale mediestrømmen, set = null localVideo1.src = ""; localStream.stop(); localStream = null; // For hver deltaker, deaktiver video fra HTML elementer, lukk tilkoblingen, sett pekeren = null remoteVideo1.src = ""; pc1.close(); pc1 = null; remoteVideo2.src = ""; pc2.close(); pc2 = null; )

La oss lagre det som rtctest3.html, laste det opp til serveren og åpne det i nettleseren. Dette eksemplet implementerer toveis overføring av mediestrømmer mellom to RTCPeerConnections i samme nettleserfane. For å organisere utvekslingen av Offer and Answer SDP, ICE-kandidater mellom deltakere og annen informasjon gjennom nettverket, i stedet for å ringe prosedyrer direkte, vil det være nødvendig å implementere utvekslingen mellom deltakere ved å bruke en slags transport, i vårt tilfelle - web-sockets.

Skjermsending

GetUserMedia-funksjonen kan også fange skjermen og streame som en MediaStream ved å spesifisere følgende parametere:

Var mediaStreamConstraints = ( lyd: falsk, video: ( obligatorisk: ( chromeMediaSource: "skjerm"), valgfritt: ) );

For å få tilgang til skjermen må flere betingelser være oppfylt:

  • aktiver skjermbildeflagg i getUserMedia() i chrome://flags/,chrome://flags/;
  • kildefilen må lastes ned via HTTPS (SSL origin);
  • lydstrømmen skal ikke etterspørres;
  • Flere forespørsler skal ikke utføres i én nettleserfane.
Biblioteker for WebRTC

Selv om WebRTC ennå ikke er ferdig, har flere biblioteker basert på det allerede dukket opp. JsSIP er designet for å lage nettleserbaserte softphones som fungerer med SIP-svitsjer som Asterisk og Camalio. PeerJS vil gjøre det enklere å lage P2P-nettverk for datautveksling, og Holla vil redusere mengden utvikling som kreves for P2P-kommunikasjon fra nettlesere.

Node.js og socket.io

For å organisere utvekslingen av SDP- og ICE-kandidater mellom to RTCPeerConnections via nettverket, bruker vi Node.js med socket.io-modulen.

Installering av den siste stabile versjonen av Node.js (for Debian/Ubuntu) er beskrevet

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

Installasjon for andre OS beskrevet

La oss sjekke:

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

Ved å bruke npm (Node Package Manager) vil vi installere socket.io og den ekstra ekspressmodulen:

$ npm installer socket.io express

La oss teste det ved å lage en nodetest2.js-fil for serversiden:

$ nano nodetest2.js var app = require("express")() , server = require("http").createServer(app) , io = require("socket.io").listen(server); server.lytt(80); // Hvis port 80 er gratis app.get("/", function (req, res) ( // Når du får tilgang til rotsiden res.sendfile(__dirname + "/nodetest2.html"); // send HTML-filen ) ) ; io.sockets.on("tilkobling", funksjon (socket) ( // Når du kobler til socket.emit("serverhendelse", ( hallo: "verden" )); // send en melding socket.on("klienthendelse" , funksjon (data) ( // og erklære en hendelsesbehandler når en melding kommer fra klientkonsollen.log(data); )); ));

Og nodetest2.html for klientsiden:

$ nano nodetest2.html var socket = io.connect("/"); // Websocket server URL (rotsiden til serveren som siden ble lastet fra) socket.on("server hendelse", funksjon (data) ( console.log(data); socket.emit("klienthendelse", ( "navn": "verdi" )); ));

La oss starte serveren:

$ sudo nodejs nodetest2.js

og åpne siden http://localhost:80 (hvis den kjøres lokalt på port 80) i nettleseren. Hvis alt er vellykket, vil vi i nettleserens JavaScript-konsoll se utvekslingen av hendelser mellom nettleseren og serveren ved tilkobling.

Utveksling av informasjon mellom RTCPeerConnection via web-sockets Klientdel

La oss lagre hovedeksemplet vårt (rtcdemo3.html) under det nye navnet rtcdemo4.html. La oss inkludere socket.io-biblioteket i elementet:

Og i begynnelsen av JavaScript-skriptet - koble til websockets:

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

La oss erstatte det direkte anropet til funksjonene til en annen deltaker ved å sende ham en melding via nettsockets:

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

I hangup()-funksjonen, i stedet for å direkte kalle funksjonene til den andre deltakeren, vil vi sende en melding via web-sockets:

Funksjon btnHangupClick() ( ... // remoteVideo2.src = ""; pc2.close(); pc2 = null; socket.emit("hangup", ()); )

Og legg til behandlere for meldingsmottak:

Socket.on("tilbud", funksjon (data) ( console.log("socket.on("tilbud"):", data); pc2_receivedOffer(data); )); socket.on("svar", funksjon (data) (е console.log("socket.on("svar"):", data); pc1.setRemoteDescription(ny RTCSessionDescription(data)); )); socket.on("ice1", funksjon (data) ( console.log("socket.on("ice1"):", data); pc2.addIceCandidate(ny RTCIceCandidate(data)); )); socket.on("ice2", funksjon (data) ( console.log("socket.on("ice2"):", data); pc1.addIceCandidate(ny RTCIceCandidate(data)); )); socket.on("hangup", function (data) ( console.log("socket.on("hangup"):", data); remoteVideo2.src = ""; pc2.close(); pc2 = null; ) );

Server del

På serversiden lagrer du nodetest2-filen under det nye navnet rtctest4.js, og inne i funksjonen io.sockets.on("connection", funksjon (socket) ( ... ) legger vi til mottak og sending av klientmeldinger:

Socket.on("tilbud", funksjon (data) ( // Når vi mottar "tilbud"-meldingen, // siden det bare er én klientforbindelse i dette eksempelet, // vil vi sende meldingen tilbake gjennom samme socket-socket .emit("tilbud" , data); // Hvis det var nødvendig å videresende meldingen over alle forbindelser, // unntatt avsender: // soket.broadcast.emit("tilbud", data); )); socket.on("svar", funksjon (data) ( socket.emit("svar", data); )); socket.on("ice1", funksjon (data) ( socket.emit("ice1", data); )); socket.on("ice2", funksjon (data) ( socket.emit("ice2", data); )); socket.on("legg på", funksjon (data) ( socket.emit("legg på", data); ));

La oss i tillegg endre navnet på HTML-filen:

// res.sendfile(__dirnavn + "/nodetest2.html"); // Send HTML-filen res.sendfile(__dirname + "/rtctest4.html");

Starte serveren:

$ sudo nodejs nodetest2.js

Til tross for at koden til begge klientene kjøres i samme nettleserfane, utføres all interaksjon mellom deltakerne i vårt eksempel fullstendig over nettverket, og å "separere" deltakerne krever ingen spesielle vanskeligheter. Det vi gjorde var imidlertid også veldig enkelt – disse teknologiene er gode fordi de er enkle å bruke. Selv om noen ganger villedende. Spesielt, la oss ikke glemme at uten STUN/TURN-servere vil ikke vårt eksempel kunne fungere i nærvær av adresseoversettelse og brannmurer.

Konklusjon

Det resulterende eksemplet er veldig konvensjonelt, men hvis vi litt universaliserer hendelsesbehandlerne slik at de ikke skiller seg mellom den som ringer og den som ringte, i stedet for to objekter pc1 og pc2, lag en RTCPeerConnection-array og implementer dynamisk skapelse og fjerner elementer, vil du få en fullstendig brukbar videochat. Det er ingen spesielle detaljer knyttet til WebRTC, og et eksempel på en enkel videochat for flere deltakere (samt tekstene til alle eksemplene i artikkelen) ligger på disken som følger med bladet. Imidlertid kan du allerede finne ganske mye på Internett. gode eksempler. Spesielt ble følgende brukt i utarbeidelsen av artikkelen: simpl.info getUserMedia, simpl.info RTCPeerConnection, WebRTC Reference App.

Det kan antas at det veldig snart, takket være WebRTC, vil skje en revolusjon ikke bare i vår forståelse av tale- og videokommunikasjon, men også i måten vi oppfatter Internett som helhet. WebRTC er ikke bare posisjonert som en teknologi for nettleser-til-nettleser-samtaler, men også som en sanntidskommunikasjonsteknologi. Videokommunikasjonen vi diskuterte er bare en liten del mulige alternativer dens bruk. Det er allerede eksempler på screencasting og samarbeid, og til og med et nettleserbasert P2P-innholdsleveringsnettverk som bruker RTCDataChannel.




Topp