Oopbronwolkspeletjies op WebRTC: p2p, multiplayer, nul latency

Oopbronwolkspeletjies op WebRTC: p2p, multiplayer, nul latency
Sagteware as 'n diens, infrastruktuur as 'n diens, platform as 'n diens, kommunikasieplatform as 'n diens, videokonferensies as 'n diens, en wat van wolkspeletjies as 'n diens? Daar was reeds verskeie pogings om wolkspeletjies (Cloud Gaming) te skep, soos Stadia, wat onlangs deur Google bekendgestel is. Stadia nie nuut vir WebRTC nie, maar kan ander WebRTC op dieselfde manier gebruik?

Thanh Nguyen het besluit om hierdie moontlikheid op sy oopbronprojek CloudRetro te toets. CloudRetro is gebaseer op Pion, gewild WebRTC-biblioteek gebaseer op Go (dankie Shownu van die Pion-ontwikkelingspan vir hul hulp met hierdie artikel). In hierdie artikel gee Thanh 'n oorsig van die argitektuur van sy projek, en praat ook oor wat hy nuttig geleer het en watter uitdagings hy teëgekom het terwyl hy gewerk het.

Entry

Verlede jaar, toe Google Stadia aangekondig het, was ek weggewaai. Die idee is so uniek en innoverend dat ek heeltyd gewonder het hoe dit selfs moontlik is met bestaande tegnologie. Die begeerte om hierdie onderwerp beter te verstaan, het my aangespoor om my eie weergawe van 'n oopbronwolkspeletjie te skep. Die resultaat was net fantasties. Hieronder wil ek graag die proses van werk aan my jaarlikse deel projek.

TLDR: kort skyfie weergawe met hoogtepunte

Waarom wolkspeletjies die toekoms is

Ek glo dat Cloud Gaming binnekort 'n nuwe generasie van nie net speletjies sal word nie, maar ook ander areas van rekenaarwetenskap. Wolkspeletjies is die toppunt van die kliënt/bedienermodel. Hierdie model maksimeer backend-bestuur en minimaliseer frontend-werk deur speletjielogika op 'n afgeleë bediener te huisves en beelde/klank na die kliënt te stroom. Die bediener doen die swaar verwerking sodat die kliënt nie meer onderhewig is aan hardewarebeperkings nie.

Met Google Stadia kan jy basies speel AAA speletjies (d.w.s. hoë-end blockbuster-speletjies) op 'n koppelvlak soos YouTube. Dieselfde metodologie kan toegepas word op ander swaar vanlyn toepassings soos bedryfstelsel of 2D/3D grafiese ontwerp, ens. sodat ons hulle stabiel op lae-spesifikasie toestelle oor platforms kan laat loop.

Oopbronwolkspeletjies op WebRTC: p2p, multiplayer, nul latency
Die toekoms van hierdie tegnologie: stel jou voor of Microsoft Windows 10 in die Chrome-blaaier gehardloop het?

Wolkspeletjies is tegnies moeilik

Speletjies is een van daardie seldsame gebiede waar 'n konstante vinnige reaksie van die gebruiker vereis word. As ons soms 'n vertraging van 2 sekondes teëkom wanneer ons op 'n bladsy klik, is dit aanvaarbaar. Regstreekse videostrome is geneig om 'n paar sekondes agter te wees, maar bied steeds 'n redelike mate van bruikbaarheid. As die speletjie egter dikwels met 500 ms vertraag word, is dit eenvoudig nie moontlik om te speel nie. Ons doelwit is om uiters lae latency te bereik sodat die gaping tussen insette en media so klein as moontlik is. Daarom is die tradisionele benadering tot die stroom van video nie hier van toepassing nie.

Oopbronwolkspeletjies op WebRTC: p2p, multiplayer, nul latency
Algemene wolkspeletjiesjabloon

Oopbronprojek CloudRetro

Ek het besluit om 'n toetsmonster van 'n wolkspeletjie te skep om te sien of dit alles moontlik is met sulke ernstige netwerkbeperkings. Ek het Golang gekies vir die bewys van konsep omdat dit die taal is waarmee ek die meeste vertroud is en om baie ander redes geskik is vir hierdie implementering, soos ek later uitgevind het. Go is eenvoudig en ontwikkel baie vinnig; Kanale in Go is ideaal vir die bestuur van multithreading.

Project CloudRetro.io is 'n oopbron-wolkspeletjiediens vir retro-speletjies. Die doel van die projek is om die mees gemaklike spelervaring na tradisionele retro-speletjies te bring en multiplayer by te voeg.
Jy kan meer oor die projek hier uitvind: https://github.com/giongto35/cloud-game.

CloudRetro-funksie

CloudRetro gebruik retro-speletjies om die krag van wolkspeletjies ten toon te stel. Dit laat jou toe om baie unieke spelervarings te kry.

  • Spel oordraagbaarheid
    • Onmiddellike terugspeel wanneer 'n bladsy oopgemaak word; geen aflaai en installasie nodig nie
    • Werk op 'n mobiele blaaier so geen sagteware is nodig om te loop nie

  • Spelsessies kan oor verskeie toestelle gedeel word en in die wolk gestoor word vir volgende aanmelding
  • Die speletjie kan gestroom word, of jy kan dit met verskeie gebruikers gelyktydig speel:
    • Crowdplay soos TwitchPlayPokemon, net meer kruisplatform en meer intyds
    • Vanlyn speletjies aanlyn. Baie gebruikers kan speel sonder netwerkopstelling. Samurai Shodown kan nou met 2 spelers oor die CloudRetro-netwerk gespeel word

    Oopbronwolkspeletjies op WebRTC: p2p, multiplayer, nul latency
    Demo-weergawe van aanlyn multiplayer-speletjie op verskillende toestelle

    Infrastruktuur

    Vereistes en tegnologie stapel

    Hieronder is 'n lys van vereistes wat ek stel voor die aanvang van die projek.

    1. Een speler
    Hierdie vereiste lyk dalk nie te belangrik en voor die hand liggend hier nie, maar dit is een van my belangrikste wegneemetes, dit hou wolkspeletjies so ver as moontlik van tradisionele stroomdienste af. As ons op die enkelspeler-speletjie fokus, kan ons ontslae raak van die gesentraliseerde bediener of CDN omdat ons nie na die massas hoef te stroom nie. In plaas daarvan om strome na 'n inneembediener op te laai of pakkies na 'n gesentraliseerde WebSocket-bediener deur te gee, word diensstrome direk na die gebruiker gestroom via 'n WebRTC eweknie-verbinding.

    2. Lae latency media stroom
    As ek oor Stadia lees, sien ek dikwels dat WebRTC in sommige artikels genoem word. Ek het besef dat WebRTC 'n uitstekende tegnologie is, en dit is ideaal vir gebruik in wolkspeletjies. WebRTC is 'n projek wat webblaaiers en mobiele toepassings voorsien van intydse kommunikasie deur 'n eenvoudige API. Dit bied eweknie-konnektiwiteit, is geoptimaliseer vir media, en het ingeboude standaardkodeks soos VP8 en H264.

    Ek het geprioritiseer om die beste moontlike gebruikerservaring te bied bo die handhawing van hoë kwaliteit grafika. Sommige verliese word in die algoritme toegelaat. Google Stadia het 'n bykomende stap om die beeldgrootte op die bediener te verminder en die rame word tot 'n hoër gehalte opgeskaal voordat dit aan die eweknieë oorgedra word.

    3. Verspreide infrastruktuur met geografiese roetering
    Ongeag hoe geoptimaliseer die kompressie-algoritme en -kode is, is die netwerk steeds die deurslaggewende faktor wat die meeste tot latensie bydra. Die argitektuur moet 'n meganisme hê om die bediener naaste aan die gebruiker te koppel om heenreistyd (RTT) te verminder. Die argitektuur moet 1 koördineerder en verskeie stroombedieners hê wat oor die hele wêreld versprei word: VSA-Wes, VSA-Oos, Europa, Singapoer, China. Alle stroombedieners moet heeltemal geïsoleer wees. Die stelsel kan sy verspreiding aanpas wanneer die bediener by die netwerk aansluit of verlaat. Dus, met hoë verkeer, maak die byvoeging van bykomende bedieners horisontale skaal moontlik.

    4. Blaaierversoenbaarheid
    Wolkspeletjies is op sy beste wanneer dit die minimum van gebruikers vereis. Dit beteken dat dit moontlik is om in die blaaier te hardloop. Blaaiers help om die spelervaring so gemaklik as moontlik vir gebruikers te maak deur hulle te spaar om sagteware en hardeware te installeer. Blaaiers help ook om kruisplatforms vir mobiele en rekenaarweergawes te verskaf. Gelukkig word WebRTC goed ondersteun in verskeie blaaiers.

    5. Duidelike skeiding van die spelkoppelvlak en diens
    Ek beskou wolkspeletjiediens as 'n platform. Almal behoort enigiets aan die platform te kan koppel. Ek het nou geïntegreer LibRetro met wolkspeletjiediens, want LibRetro bied pragtige speletjie-emulator-koppelvlak vir retro-speletjies soos SNES, GBA, PS.

    6. Kamers vir multispeler, skare speel en eksterne skakeling (diepskakel) met die speletjie
    CloudRetro ondersteun baie nuwe speletjies soos CrowdPlay en Online MultiPlayer vir retro-speletjies. As verskeie gebruikers dieselfde diepskakel op verskillende rekenaars oopmaak, sal hulle dieselfde speletjie sien loop en selfs daarby kan aansluit.

    Boonop word speltoestande in die wolkberging gestoor. Dit stel gebruikers in staat om die speletjie enige tyd op enige ander toestel voort te sit.

    7. Horisontale skaal
    Soos enige SAAS deesdae, moet wolkspeletjies ontwerp word om horisontaal skaalbaar te wees. Die koördineerder-werker-ontwerp laat jou toe om meer werkers by te voeg om meer verkeer te bedien.

    8. Nie gekoppel aan een wolk nie
    Die CloudRetro-infrastruktuur word deur verskillende wolkverskaffers (Digital Ocean, Alibaba, pasgemaakte verskaffer) vir verskillende streke aangebied. Ek maak dit moontlik om in 'n infrastruktuur Docker-houer te hardloop en stel netwerkinstellings in met 'n bash-skrif om te verhoed dat ek van 'n enkele wolkverskaffer afhanklik is. Deur dit te kombineer met NAT Traversal in WebRTC, kan ons die buigsaamheid hê om CloudRetro op enige wolkplatform en selfs enige gebruiker se masjien te ontplooi.

    Argitektoniese ontwerp

    Werker: (of die stroombediener hierbo genoem) vermenigvuldig die speletjies, loop die enkoderingspyplyn en stroom die geënkodeerde media na die gebruikers. Werkergevalle word oor die hele wêreld versprei, en elke werker kan verskeie gebruikersessies op dieselfde tyd hanteer.

    Koördineerder: is verantwoordelik om die nuwe gebruiker met die mees geskikte stroomwerker te koppel. Die koördineerder kommunikeer met die werkers via WebSocket.

    Spelstaatberging: sentrale afgeleë berging vir alle speletjiestate. Hierdie berging bied belangrike kenmerke soos afstand stoor/laai.

    Oopbronwolkspeletjies op WebRTC: p2p, multiplayer, nul latency
    CloudRetro top-vlak argitektuur

    Pasgemaakte Skrip

    Wanneer 'n nuwe gebruiker CloudRetro oopmaak in stappe 1 en 2 wat in die figuur hieronder getoon word, word die koördineerder, saam met 'n lys van beskikbare werkers, na die eerste bladsy versoek. Daarna, in stap 3, bereken die kliënt vertragings vir alle kandidate deur 'n HTTP-ping-versoek te gebruik. Hierdie lys van vertragings word dan teruggestuur na die koördineerder sodat hy die mees geskikte werker kan bepaal om die gebruiker te bedien. Stap 4 hieronder skep 'n speletjie. 'n WebRTC-stroomverbinding word tussen die gebruiker en die toegewysde werker tot stand gebring.
    Oopbronwolkspeletjies op WebRTC: p2p, multiplayer, nul latency
    Pasgemaakte skrip nadat u toegang verkry het

    Wat is in die werker

    Spel- en stroompyplyne word in isolasie binne die werker gestoor en ruil inligting daar uit deur die koppelvlak. Tans word hierdie kommunikasie uitgevoer deur data in die geheue oor te dra golang kanale in dieselfde proses. Die volgende doelwit is segregasie, m.a.w. onafhanklike bekendstelling van die spel in 'n ander proses.

    Oopbronwolkspeletjies op WebRTC: p2p, multiplayer, nul latency
    Interaksie van werkerkomponente

    Hoofkomponente:

    • WebRTC: 'n kliëntkomponent wat gebruikersinsette aanvaar en die geënkodeerde media vanaf die bediener uitvoer.
    • Spelemulator: spel komponent. Danksy die Libretro-biblioteek kan die stelsel die speletjie binne dieselfde proses laat loop en die media- en invoerstroom intern onderskep.
    • In-speletjie-rame word vasgelê en na die enkodeerder gestuur.
    • Beeld-/klankkodeerder: 'n enkoderingspyplyn wat mediarame ontvang, dit in die agtergrond enkodeer en geënkodeerde beelde/klank uitvoer.

    Implementering

    CloudRetro maak staat op WebRTC as 'n ruggraattegnologie, so voordat ek in die besonderhede van die Golang-implementering duik, het ek besluit om oor WebRTC self te praat. Dit is 'n wonderlike stuk tegnologie wat my geweldig gehelp het om sub-sekonde latency streaming te bereik.

    WebRTC

    WebRTC is ontwerp om eweknie-verbindings van hoë gehalte op inheemse mobiele toepassings en blaaiers te verskaf deur eenvoudige API's te gebruik.

    NAT Traversal

    WebRTC is bekend vir sy NAT Traversal-funksie. WebRTC is ontwerp vir eweknie-kommunikasie. Die doel daarvan is om die mees geskikte direkte roete te vind, deur NAT-poorte en brandmure te vermy, na eweknie deur 'n proses genaamd ICE. As deel van hierdie proses vind die WebRTC API's jou publieke IP-adres met behulp van STUN-bedieners en stuur dit aan na 'n aflosbediener (DRAAI) wanneer 'n direkte verbinding nie bewerkstellig kan word nie.

    CloudRetro ontgin egter nie hierdie vermoë ten volle nie. Die eweknie-verbindings bestaan ​​nie tussen gebruikers nie, maar tussen gebruikers en wolkbedieners. Die bedienerkant van die model het minder beperkings op direkte kommunikasie as 'n tipiese gebruikertoestel. Dit laat jou toe om inkomende poorte vooraf oop te maak of openbare IP-adresse direk te gebruik, aangesien die bediener nie agter NAT is nie.

    Voorheen wou ek die projek omskep in 'n speletjieverspreidingsplatform vir Cloud Gaming. Die idee was om speletjieskeppers toe te laat om speletjies en stroombronne te verskaf. En gebruikers sal direk met verskaffers kommunikeer. Op hierdie gedesentraliseerde manier is CloudRetro net 'n medium om derdepartystroombronne aan gebruikers te koppel, wat dit meer skaalbaar maak wanneer hosting nie meer daaraan hang nie. Die rol van WebRTC NAT Traversal is hier baie belangrik om die inisialisering van 'n eweknie-verbinding op derdeparty-stroombronne te fasiliteer, wat dit makliker maak vir die skepper om aan die netwerk te koppel.

    Video kompressie

    Video-kompressie is 'n onontbeerlike deel van die pyplyn en dra grootliks by tot die gladheid van die stroom. Alhoewel dit nie nodig is om al die besonderhede van VP8/H264-video-enkodering te ken nie, help die begrip van die konsep om videostroomspoedparameters te verstaan, onverwagte gedrag te ontfout en latensie aan te pas.

    Om video vir 'n stroomdiens saam te komprimeer is uitdagend omdat die algoritme moet verseker dat die totale enkoderingstyd + netwerkoordragtyd + dekoderingstyd so klein as moontlik is. Daarbenewens moet die enkoderingsproses konsekwent en deurlopend wees. Sommige afwykings in enkodering is nie van toepassing nie - ons kan byvoorbeeld nie 'n lang enkoderingstyd bo 'n kleiner lêergrootte en dekoderingstyd verkies nie, of inkonsekwente kompressie gebruik.

    Die idee agter video-kompressie is om onnodige stukkies inligting uit te skakel terwyl 'n aanvaarbare vlak van getrouheid vir gebruikers gehandhaaf word. Benewens die kodering van individuele statiese beeldrame, lei die algoritme die huidige raam af van die vorige en volgende, dus word slegs hul verskil gestuur. Soos u uit die Pacman-voorbeeld kan sien, word slegs differensiële punte oorgedra.

    Oopbronwolkspeletjies op WebRTC: p2p, multiplayer, nul latency
    Vergelyking van videorame met Pacman as voorbeeld

    Oudio kompressie

    Net so laat die klankkompressie-algoritme data weg wat nie deur mense waargeneem kan word nie. Opus is tans die oudio-kodek wat die beste presteer. Dit is ontwerp om 'n oudiogolf oor 'n geordende datagramprotokol soos RTP (Real Time Transport Protocol) uit te stuur. Die vertraging is minder as dié van mp3 en aac, en die kwaliteit is hoër. Die latensie is gewoonlik ongeveer 5 ~ 66,5ms.

    Pion, WebRTC in Golang

    pion is 'n oopbronprojek wat WebRTC na Golang bring. In plaas van die gewone omvou van inheemse C++ WebRTC-biblioteke, is Pion 'n inheemse Golang WebRTC-implementering met beter werkverrigting, Go-integrasie en weergawebeheer op WebRTC-protokolle.

    Die biblioteek verskaf ook stroomdata met baie wonderlike ingeboude modules met 'n vertraging van minder as 'n sekonde. Dit het sy eie implementering van STUN, DTLS, SCTP, ens. en 'n bietjie eksperimentering met QUIC en WebAssembly. Op sigself is hierdie oopbron-biblioteek 'n baie goeie bron van leer met uitstekende dokumentasie, netwerkprotokolimplementerings en koel voorbeelde.

    Die Pion-gemeenskap, gelei deur 'n baie passievolle skepper, is redelik lewendig en het baie kwaliteitgesprekke oor WebRTC. As jy belangstel in hierdie tegnologie, sluit aan http://pion.ly/slack - jy sal baie nuwe dinge leer.

    Skryf CloudRetro in Golang

    Oopbronwolkspeletjies op WebRTC: p2p, multiplayer, nul latency
    Werker Implementering in Go

    Gaan kanale in aksie

    Met die pragtige ontwerp van Go's-kanale word die kwessies van gebeurtenisstroming en gelyktydigheid aansienlik vereenvoudig. Soos in die diagram, is daar verskeie komponente wat parallel in verskillende GoRoutines loop. Elke komponent bestuur sy eie staat en kommunikeer deur kanale. Golang se selektiewe bewering veroorsaak dat een atoomgebeurtenis elke keer in die speletjie verwerk word (speletjie-merk). Dit beteken dat geen blokkering vir hierdie ontwerp nodig is nie. Byvoorbeeld, wanneer 'n gebruiker gestoor word, word 'n volledige speltoestand-momentopname vereis. Hierdie toestand moet aaneenlopend bly en aanmeld totdat die stoor voltooi is. Tydens elke speletjie-merk kan die agterkant slegs 'n stoor- of invoerbewerking verwerk, wat die proses draadveilig maak.

    func (e *gameEmulator) gameUpdate() {
    for {
    	select {
    		case <-e.saveOperation:
    			e.saveGameState()
    		case key := <-e.input:
    			e.updateGameState(key)
    		case <-e.done:
    			e.close()
    			return
    	}
        }
    }

    fan-in / fan-out

    Hierdie Golang-sjabloon is ideaal vir my CrowdPlay- en Multiple Player-gebruiksgeval. Volgens hierdie patroon word alle gebruikersinsette in dieselfde kamer in die middelste invoerkanaal ingebou. Die speletjiemedia word dan na alle gebruikers in dieselfde kamer ontplooi. Op hierdie manier bereik ons ​​die verdeling van die speltoestand tussen verskeie speletjiesessies van verskillende gebruikers.

    Oopbronwolkspeletjies op WebRTC: p2p, multiplayer, nul latency
    Sinchronisasie tussen verskillende sessies

    Nadele van Golang

    Golang is nie perfek nie. Die kanaal is stadig. In vergelyking met blokkering, is 'n Go-kanaal eenvoudig 'n makliker manier om gelyktydige en stroomgebeurtenisse te hanteer, maar 'n kanaal lewer nie die beste prestasie nie. Onder die kanaal is daar 'n komplekse blokkeringslogika. Daarom het ek 'n paar aanpassings aan die implementering gemaak deur slotte en atoomwaardes weer toe te pas wanneer kanale vervang word om werkverrigting te optimaliseer.

    Boonop is Golang se vullisverwyderaar onhanteerbaar, wat soms verdagte lang pouses veroorsaak. Dit meng baie in met die intydse stroomtoepassing.

    COG

    Die projek gebruik die bestaande VP8/H264 oopbron Golang-biblioteek vir mediakompressie en Libretro vir speletjie-emulators. Al hierdie biblioteke is net omhulsels vir die C-biblioteek in Go-gebruik COG. Sommige van die nadele word in gelys hierdie pos Dave Cheney. Probleme wat ek in die gesig gestaar het:

    • onvermoë om 'n ongeluk in CGO te vang, selfs met Golang RecoveryCrash;
    • die onvermoë om 'n prestasie-bottelnek te identifiseer wanneer ons nie korrelkwessies in CGO kan opspoor nie.

    Gevolgtrekking

    Ek het my doel bereik om wolkspeletjiedienste uit te vind en 'n platform te skep wat my help om nostalgiese retrospeletjies met my vriende aanlyn te speel. Hierdie projek sou nie moontlik gewees het sonder die Pion-biblioteek en die ondersteuning van die Pion-gemeenskap nie. Ek is uiters dankbaar vir sy intensiewe ontwikkeling. Die eenvoudige API's wat deur WebRTC en Pion verskaf word, het naatlose integrasie verseker. My eerste bewys van konsep is dieselfde week vrygestel, ten spyte daarvan dat ek nie vooraf bewus was van eweknie-kommunikasie (P2P) nie.

    Ten spyte van die gemak van integrasie, is P2P-stroming inderdaad 'n baie komplekse area in rekenaarwetenskap. Dit moet die kompleksiteit van meerjarige netwerkargitekture soos IP en NAT hanteer om 'n eweknie-sessie te skep. Terwyl ek aan hierdie projek gewerk het, het ek baie waardevolle kennis oor netwerk- en prestasieoptimalisering opgehoop, so ek beveel almal aan om P2P-produkte te probeer bou deur WebRTC te gebruik.

    CloudRetro maak voorsiening vir al die gebruiksgevalle wat ek uit my oogpunt as 'n retro-speler verwag het. Ek dink egter daar is baie areas in die projek wat ek kan verbeter, soos om die netwerk meer betroubaar en werksaam te maak, die verskaffing van hoër gehalte spelgrafika, of die vermoë om speletjies tussen gebruikers te deel. Ek werk hard hieraan. Volg asseblief projek en ondersteun hom as jy van hom hou.

Bron: will.com

Voeg 'n opmerking