Open source cloudgaming op WebRTC: p2p, multiplayer, nul latentie

Open source cloudgaming op WebRTC: p2p, multiplayer, nul latentie
Software as a service, infrastructuur as a service, platform as a service, communicatieplatform as a service, videoconferenties as a service, hoe zit het met cloud gaming as a service? Er zijn al meerdere pogingen gedaan om cloud gaming (Cloud Gaming) te creëren, zoals Stadia, onlangs gelanceerd door Google. Stadions niet nieuw voor WebRTC, maar kunnen anderen WebRTC op dezelfde manier gebruiken?

Thanh Nguyen besloot deze mogelijkheid te testen in zijn open source-project CloudRetro. CloudRetro is gebaseerd op Pion, populair WebRTC-bibliotheek gebaseerd op Go (bedankt getoondnu van het ontwikkelteam van Pion voor hun hulp bij het voorbereiden van dit artikel). In dit artikel geeft Thanh een overzicht van de architectuur van zijn project, en vertelt hij ook welke nuttige dingen hij heeft geleerd en welke uitdagingen hij tijdens zijn werk tegenkwam.

Toegang

Toen Google vorig jaar Stadia aankondigde, stond ik versteld. Het idee is zo uniek en innovatief dat ik me voortdurend afvroeg hoe dit überhaupt mogelijk was met de bestaande technologie. De wens om dit onderwerp beter te begrijpen, bracht mij ertoe mijn eigen versie van een open-source cloudgame te maken. Het resultaat was gewoonweg fantastisch. Hieronder deel ik graag het proces van werken aan mijn jaar projecteren.

TLDR: korte diaversie met hoogtepunten

Waarom cloudgamen de toekomst is

Ik geloof dat Cloud Gaming binnenkort de volgende generatie zal worden, niet alleen op het gebied van gaming, maar ook op andere gebieden van de informatica. Cloudgaming is het toppunt van het client/server-model. Dit model maximaliseert het backend-beheer en minimaliseert het frontend-werk door gamelogica op een externe server te hosten en afbeeldingen/audio naar de client te streamen. De server doet de zware verwerking, zodat de client niet langer afhankelijk is van hardwarebeperkingen.

Met Google Stadia kun je in wezen spelen AAA-spellen (d.w.z. high-end blockbuster-games) op een interface zoals YouTube. Dezelfde methodologie kan worden toegepast op andere zware offline toepassingen zoals besturingssystemen of 2D/3D grafisch ontwerp, enz. zodat we ze consistent kunnen uitvoeren op apparaten met lage specificaties op meerdere platforms.

Open source cloudgaming op WebRTC: p2p, multiplayer, nul latentie
De toekomst van deze technologie: stel je voor dat Microsoft Windows 10 in de Chrome-browser zou draaien?

Cloudgaming is technisch uitdagend

Gamen is een van die zeldzame gebieden waar een constante, snelle reactie van de gebruiker vereist is. Als we af en toe een vertraging van 2 seconden tegenkomen bij het klikken op een pagina, is dit acceptabel. Live videostreams hebben de neiging een paar seconden achter te blijven, maar bieden nog steeds een redelijke bruikbaarheid. Als het spel echter vaak 500 ms achterblijft, is het simpelweg onspeelbaar. Ons doel is om een ​​extreem lage latentie te bereiken, zodat de kloof tussen invoer en media zo klein mogelijk is. Daarom is de traditionele benadering van videostreaming hier niet van toepassing.

Open source cloudgaming op WebRTC: p2p, multiplayer, nul latentie
Algemene cloudgamesjabloon

Open source-project CloudRetro

Ik besloot een testexemplaar van een cloudgame te maken om te zien of dit allemaal mogelijk was met zulke strenge netwerkbeperkingen. Ik koos Golang voor het proof of concept omdat dit de taal was waarmee ik het meest vertrouwd was en om vele andere redenen zeer geschikt was voor deze implementatie, zoals ik later ontdekte. Go is eenvoudig en ontwikkelt zich zeer snel; Kanalen in Go zijn ideaal voor het beheren van multithreading.

Project CloudRetro.io is een open source cloud-gamingservice voor retro-gaming. Het doel van het project is om de meest comfortabele game-ervaring te bieden aan traditionele retro-games en multiplayer toe te voegen.
Meer informatie over het project vindt u hier: https://github.com/giongto35/cloud-game.

CloudRetro-functionaliteit

CloudRetro gebruikt retrogames om de kracht van cloudgaming te demonstreren. Hierdoor kun je veel unieke game-ervaringen opdoen.

  • Draagbaarheid van het spel
    • Direct afspelen bij het openen van de pagina; geen download of installatie nodig
    • Werkt in een mobiele browser, dus er is geen software nodig om het uit te voeren

  • Gamesessies kunnen op meerdere apparaten worden gedeeld en in de cloud worden opgeslagen voor de volgende keer dat u inlogt
  • De game kan worden gestreamd of door meerdere gebruikers tegelijk worden gespeeld:
    • Crowdplay zoals TwitchPlayPokemon, alleen meer platformonafhankelijk en meer realtime
    • Offline-spellen online. Veel gebruikers kunnen spelen zonder een netwerk op te zetten. Samurai Shodown kan nu door 2 spelers worden gespeeld via het CloudRetro-netwerk

    Open source cloudgaming op WebRTC: p2p, multiplayer, nul latentie
    Demoversie van online multiplayer-game op verschillende apparaten

    Infrastructuur

    Vereisten en technologiestapel

    Hieronder staat een lijst met eisen die ik heb gesteld voordat ik aan het project begon.

    1. Eén speler
    Deze vereiste lijkt hier misschien niet zo belangrijk of voor de hand liggend, maar het is een van mijn belangrijkste inzichten: het zorgt ervoor dat cloudgaming zo ver mogelijk weg blijft van traditionele streamingdiensten. Als we ons concentreren op een spel voor één speler, kunnen we af van een gecentraliseerde server of CDN omdat we niet naar de massa hoeven te streamen. In plaats van het uploaden van streams naar een sink-server of het doorgeven van pakketten aan een gecentraliseerde WebSocket-server, worden servicestreams rechtstreeks aan de gebruiker geleverd via een peer-to-peer WebRTC-verbinding.

    2. Mediastream met lage latentie
    Als ik over Stadia lees, zie ik vaak dat WebRTC in sommige artikelen wordt genoemd. Ik realiseerde me dat WebRTC een uitstekende technologie is en perfect is voor gebruik in cloudgaming. WebRTC is een project dat webbrowsers en mobiele applicaties voorziet van realtime communicatie via een eenvoudige API. Het biedt peer-to-peer-connectiviteit, is geoptimaliseerd voor media en heeft standaardcodecs ingebouwd, zoals VP8 en H264.

    Ik gaf prioriteit aan het garanderen van de best mogelijke gebruikerservaring boven het behouden van grafische afbeeldingen van hoge kwaliteit. Sommige verliezen zijn acceptabel in het algoritme. Google Stadia heeft een extra stap om de afbeeldingsgrootte op de server te verkleinen, en frames worden opgeschaald naar een hogere kwaliteit voordat ze naar peers worden verzonden.

    3. Gedistribueerde infrastructuur met geografische routing
    Hoe geoptimaliseerd het compressie-algoritme en de code ook zijn, het netwerk is nog steeds de beslissende factor die het meest bijdraagt ​​aan de latentie. De architectuur moet een mechanisme hebben om de server die het dichtst bij de gebruiker staat te koppelen om de round-trip time (RTT) te verkorten. De architectuur moet 1 coördinator hebben en meerdere streamingservers verspreid over de hele wereld: US West, US East, Europa, Singapore, China. Alle streamingservers moeten volledig geïsoleerd zijn. Het systeem kan de distributie aanpassen wanneer een server zich bij het netwerk aansluit of deze verlaat. Bij veel verkeer maakt het toevoegen van extra servers dus horizontale schaalvergroting mogelijk.

    4. Browsercompatibiliteit
    Cloudgaming is op zijn best als het het minst van gebruikers vraagt. Dit betekent dat het mogelijk is om in een browser te draaien. Browsers helpen de game-ervaring voor gebruikers zo comfortabel mogelijk te maken, waardoor ze geen software en hardware hoeven te installeren. Browsers helpen ook bij het bieden van platformonafhankelijke functionaliteit tussen mobiele en desktopversies. Gelukkig wordt WebRTC goed ondersteund in verschillende browsers.

    5. Duidelijke scheiding tussen de spelinterface en service
    Ik beschouw de cloudgamingdienst als een platform. Iedereen moet alles op het platform kunnen aansluiten. Nu ben ik geïntegreerd LibRetro met cloudgamingservice omdat LibRetro een prachtige game-emulatorinterface biedt voor retrogames zoals SNES, GBA, PS.

    6. Kamers voor multiplayer, crowdplay en externe koppeling (deeplink) met het spel
    CloudRetro ondersteunt veel nieuwe gameplays zoals CrowdPlay en Online MultiPlayer voor retrogames. Als meerdere gebruikers dezelfde deeplink op verschillende computers openen, zien ze hetzelfde spel draaien en kunnen ze er zelfs aan deelnemen.

    Bovendien worden spelstatussen opgeslagen in cloudopslag. Hierdoor kunnen gebruikers op elk gewenst moment op elk ander apparaat blijven spelen.

    7. Horizontale schaling
    Zoals elke SAAS tegenwoordig moet cloudgaming zo worden ontworpen dat het horizontaal schaalbaar is. Met het coördinator-werknemer-ontwerp kunt u meer werknemers toevoegen om meer verkeer te bedienen.

    8. Geen verbinding met één cloud
    De infrastructuur van CloudRetro wordt gehost op verschillende cloudproviders (Digital Ocean, Alibaba, aangepaste provider) voor verschillende regio's. Ik schakel het draaien in een Docker-container in voor de infrastructuur en configureer netwerkinstellingen met behulp van een bash-script om te voorkomen dat ik vastzit aan één enkele cloudprovider. Door dit te combineren met NAT Traversal in WebRTC kunnen we de flexibiliteit hebben om CloudRetro op elk cloudplatform en zelfs op de machines van elke gebruiker te implementeren.

    Architectueel ontwerp

    Arbeider: (of de hierboven genoemde streamingserver) vermenigvuldigt de games, voert de coderingspijplijn uit en streamt de gecodeerde media naar gebruikers. Werknemersinstanties zijn over de hele wereld verspreid en elke werker kan meerdere gebruikerssessies tegelijkertijd afhandelen.

    Coördinator: is verantwoordelijk voor het koppelen van de nieuwe gebruiker aan de meest geschikte medewerker voor streaming. De coördinator communiceert met werknemers via WebSocket.

    Opslag van spelstatus: centrale externe opslag voor alle spelstatussen. Deze opslag biedt belangrijke functies zoals opslaan/laden op afstand.

    Open source cloudgaming op WebRTC: p2p, multiplayer, nul latentie
    Architectuur op het hoogste niveau van CloudRetro

    Aangepast script

    Wanneer een nieuwe gebruiker CloudRetro opent in stap 1 en 2, weergegeven in onderstaande figuur, wordt de coördinator samen met de lijst met beschikbare medewerkers naar de eerste pagina gevraagd. Hierna berekent de client in stap 3 de vertragingen voor alle kandidaten met behulp van een HTTP-pingverzoek. Deze lijst met vertragingen wordt vervolgens teruggestuurd naar de coördinator, zodat hij kan bepalen welke medewerker het meest geschikt is om de gebruiker te bedienen. Stap 4 hieronder maakt het spel. Er wordt een WebRTC-streamingverbinding tot stand gebracht tussen de gebruiker en de toegewezen medewerker.
    Open source cloudgaming op WebRTC: p2p, multiplayer, nul latentie
    Gebruikersscript na het verkrijgen van toegang

    Wat zit er in de werknemer

    Game- en streamingpijplijnen worden geïsoleerd in de worker opgeslagen en wisselen daar via de interface informatie uit. Momenteel wordt deze communicatie uitgevoerd door gegevens in het geheugen over te dragen via Golang-kanalen in hetzelfde proces. Het volgende doel is segregatie, d.w.z. onafhankelijke lancering van het spel in een ander proces.

    Open source cloudgaming op WebRTC: p2p, multiplayer, nul latentie
    Interactie van werknemerscomponenten

    Hoofd onderdelen:

    • WebRTC: een clientcomponent die gebruikersinvoer accepteert en gecodeerde media van de server uitvoert.
    • Spelemulator: spelcomponent. Dankzij de Libretro-bibliotheek kan het systeem het spel binnen hetzelfde proces uitvoeren en intern media en invoerstromen onderscheppen.
    • In-game frames worden vastgelegd en naar de encoder gestuurd.
    • Beeld-/audio-encoder: een coderingspijplijn die mediaframes neemt, deze op de achtergrond codeert en gecodeerde afbeeldingen/audio uitvoert.

    uitvoering

    CloudRetro vertrouwt op WebRTC als ruggengraattechnologie, dus voordat ik in de details van de Golang-implementatie duik, besloot ik het over WebRTC zelf te hebben. Dit is een geweldige technologie die mij enorm heeft geholpen bij het bereiken van een latentie van minder dan een seconde voor het streamen van gegevens.

    WebRTC

    WebRTC is ontworpen om peer-to-peer-verbindingen van hoge kwaliteit te bieden op native mobiele apps en browsers met behulp van eenvoudige API's.

    NAT-traversal

    WebRTC staat bekend om zijn NAT Traversal-functionaliteit. WebRTC is ontworpen voor peer-to-peer-communicatie. Het doel is om de meest geschikte directe route te vinden, waarbij NAT-gateways en firewalls worden vermeden voor peer-to-peer-communicatie via een proces dat ICE. Als onderdeel van dit proces vinden de WebRTC API's uw openbare IP-adres met behulp van STUN-servers en sturen dit door naar de relay-server (BEURT) wanneer er geen directe verbinding tot stand kan worden gebracht.

    CloudRetro maakt echter niet volledig gebruik van deze functie. De peer-to-peer-verbindingen bestaan ​​niet tussen gebruikers, maar tussen gebruikers en cloudservers. De serverkant van het model heeft minder directe communicatiebeperkingen dan een typisch gebruikersapparaat. Hierdoor kunt u inkomende poorten vooraf openen of openbare IP-adressen rechtstreeks gebruiken, aangezien de server niet achter NAT staat.

    Eerder wilde ik van het project een gamedistributieplatform voor Cloud Gaming maken. Het idee was om gamemakers de mogelijkheid te bieden games en streamingbronnen aan te bieden. En gebruikers zouden rechtstreeks met providers communiceren. Op deze gedecentraliseerde manier is CloudRetro slechts een raamwerk voor het verbinden van streamingbronnen van derden met gebruikers, waardoor het schaalbaarder wordt wanneer het niet langer wordt gehost. De rol van WebRTC NAT Traversal is hier erg belangrijk om de initialisatie van peer-to-peer-verbindingen op streamingbronnen van derden te vergemakkelijken, waardoor het voor de maker gemakkelijker wordt om verbinding te maken met het netwerk.

    Video compressie

    Videocompressie is een onmisbaar onderdeel van de pijplijn en draagt ​​in hoge mate bij aan een soepele doorstroming. Hoewel het niet nodig is om elk detail van VP8/H264-videocodering te kennen, kan het begrijpen van de concepten u helpen de snelheidsopties voor streaming video te begrijpen, onverwacht gedrag op te sporen en de latentie aan te passen.

    Het comprimeren van video voor een streamingdienst is een uitdaging omdat het algoritme ervoor moet zorgen dat de totale coderingstijd + netwerktransmissietijd + decoderingstijd zo laag mogelijk is. Bovendien moet het codeerproces consistent en continu zijn. Sommige afwegingen bij het coderen zijn niet van toepassing. We kunnen bijvoorbeeld geen voorkeur geven aan lange codeertijden boven kleinere bestandsgroottes en decodeertijden, of gebruik maken van inconsistente compressie.

    Het idee achter videocompressie is het elimineren van onnodige stukjes informatie, terwijl een acceptabel nauwkeurigheidsniveau voor gebruikers behouden blijft. Naast het coderen van individuele statische beeldframes, leidt het algoritme het huidige frame af uit de vorige en volgende, zodat alleen hun verschil wordt verzonden. Zoals uit het voorbeeld met Pacman blijkt, worden alleen differentiële punten verzonden.

    Open source cloudgaming op WebRTC: p2p, multiplayer, nul latentie
    Vergelijking van videoframes met Pacman als voorbeeld

    Audiocompressie

    Op dezelfde manier laat het audiocompressie-algoritme gegevens weg die niet door mensen kunnen worden waargenomen. Opus is momenteel de best presterende audiocodec. Het is ontworpen om een ​​audiogolf te verzenden via een geordend datagramprotocol zoals RTP (Real Time Transport Protocol). De latentie is lager dan die van mp3 en aac, en de kwaliteit is hoger. De latentie bedraagt ​​gewoonlijk ongeveer 5~66,5 ms.

    Pion, WebRTC in Golang

    Verticaal is een open source-project dat WebRTC naar Golang brengt. In plaats van de gebruikelijke verpakking van native C++ WebRTC-bibliotheken, is Pion een native Golang-implementatie van WebRTC met betere prestaties, Go-integratie en versiebeheer op WebRTC-protocollen.

    De bibliotheek maakt ook streaming mogelijk met veel geweldige ingebouwde ins met een latentie van minder dan een seconde. Het heeft een eigen implementatie van STUN, DTLS, SCTP, etc. en enkele experimenten met QUIC en WebAssembly. Deze open source-bibliotheek zelf is echt een goed leermiddel met uitstekende documentatie, netwerkprotocolimplementaties en coole voorbeelden.

    De Pion-gemeenschap, geleid door een zeer gepassioneerde maker, is behoorlijk levendig, met veel kwaliteitsdiscussies over WebRTC. Als u geïnteresseerd bent in deze technologie, sluit u dan aan http://pion.ly/slack – je leert veel nieuwe dingen.

    CloudRetro schrijven in Golang

    Open source cloudgaming op WebRTC: p2p, multiplayer, nul latentie
    Implementatie van een worker in Go

    Ga naar kanalen in actie

    Dankzij het prachtige kanaalontwerp van Go worden de problemen met het streamen van evenementen en gelijktijdigheid aanzienlijk vereenvoudigd. Net als in het diagram hebben verschillende GoRoutines meerdere componenten die parallel lopen. Elke component beheert zijn status en communiceert via kanalen. De selectieve bewering van Golang dwingt dat elke keer in het spel één atomaire gebeurtenis wordt verwerkt (game tick). Dit betekent dat er bij dit ontwerp geen vergrendeling nodig is. Wanneer een gebruiker bijvoorbeeld opslaat, is een volledige momentopname van de spelstatus vereist. Deze status moet continu blijven en inloggen totdat het opslaan is voltooid. Tijdens elke speltick kan de backend alleen een opslag- of invoerbewerking uitvoeren, waardoor de procesthread veilig is.

    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-uit

    Deze Golang-sjabloon past perfect bij mijn CrowdPlay- en Multiple Player-gebruiksscenario. Volgens dit patroon worden alle gebruikersingangen in één kamer ingebouwd in het centrale toegangskanaal. Gamemedia worden vervolgens ingezet voor alle gebruikers in dezelfde kamer. Op deze manier bereiken we de verdeling van de spelstatus tussen verschillende spelsessies van verschillende gebruikers.

    Open source cloudgaming op WebRTC: p2p, multiplayer, nul latentie
    Synchronisatie tussen verschillende sessies

    Nadelen van Golang

    Golang is niet perfect. Het kanaal is traag. Vergeleken met blokkeren is het Go-kanaal eenvoudigweg een eenvoudigere manier om gelijktijdige en gekoppelde gebeurtenissen af ​​te handelen, maar het kanaal levert niet de beste prestaties. Er zit complexe blokkeerlogica onder het kanaal. Daarom heb ik een aantal aanpassingen aan de implementatie aangebracht, door vergrendelingen en atomaire waarden opnieuw toe te passen bij het vervangen van kanalen om de prestaties te optimaliseren.

    Bovendien wordt de vuilnisman in Golang niet beheerd, wat soms voor verdacht lange pauzes zorgt. Dit interfereert enorm met de real-time streaming-applicatie.

    CGO

    Het project maakt gebruik van de bestaande open source Golang VP8/H264-bibliotheek voor mediacompressie en Libretro voor game-emulators. Al deze bibliotheken zijn eenvoudigweg wrappers van de C-bibliotheek die in Go wordt gebruikt CGO. Enkele van de nadelen staan ​​vermeld in dit bericht van Dave Cheney. Problemen die ik tegenkwam:

    • onvermogen om een ​​crash op te vangen in CGO, zelfs met Golang RecoveryCrash;
    • het onvermogen om prestatieknelpunten te identificeren wanneer we niet in staat zijn om gedetailleerde problemen in CGO op te sporen.

    Conclusie

    Ik heb mijn doel bereikt om cloudgamingdiensten te begrijpen en een platform te creëren waarmee ik online nostalgische retrogames met mijn vrienden kan spelen. Dit project zou niet mogelijk zijn geweest zonder de Pion-bibliotheek en de steun van de Pion-gemeenschap. Ik ben enorm dankbaar voor de intensieve ontwikkeling ervan. De eenvoudige API’s van WebRTC en Pion zorgden voor een naadloze integratie. Mijn eerste proof of concept werd diezelfde week uitgebracht, ook al had ik geen voorkennis van peer-to-peer (P2P) communicatie.

    Ondanks het gemak van integratie is P2P-streaming inderdaad een zeer complex gebied in de informatica. Ze moet omgaan met de complexiteit van al lang bestaande netwerkarchitecturen zoals IP en NAT om een ​​peer-to-peer-sessie te creëren. Terwijl ik aan dit project werkte, heb ik veel waardevolle kennis opgedaan over netwerken en prestatie-optimalisatie, dus ik moedig iedereen aan om te proberen P2P-producten te bouwen met behulp van WebRTC.

    CloudRetro is geschikt voor alle gebruiksscenario's die ik vanuit mijn perspectief als retro-gamer verwachtte. Ik denk echter dat er veel gebieden in het project zijn die ik kan verbeteren, zoals het betrouwbaarder en performanter maken van het netwerk, het bieden van game-graphics van hogere kwaliteit of de mogelijkheid om games tussen gebruikers te delen. Ik werk hier hard aan. Volg alsjeblieft projecteren en steun het als je het leuk vindt.

Bron: www.habr.com

Voeg een reactie