{"id":89303,"date":"2020-07-22T01:42:30","date_gmt":"2020-07-21T23:42:30","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/oblachnyj-gejming-s-otkrytym-ishodnym-kodom-na-webrtc-p2p-multipleer-zero-latency"},"modified":"2020-07-22T01:42:30","modified_gmt":"2020-07-21T23:42:30","slug":"oblachnyj-gejming-s-otkrytym-ishodnym-kodom-na-webrtc-p2p-multipleer-zero-latency","status":"publish","type":"post","link":"https:\/\/prohoster.info\/da\/blog\/administrirovanie\/oblachnyj-gejming-s-otkrytym-ishodnym-kodom-na-webrtc-p2p-multipleer-zero-latency","title":{"rendered":"Cloud gaming med \u00e5bne kilder p\u00e5 WebRTC: p2p, multiplayer, zero latency.","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/Voximplant\/blog\/511626\/\"><img decoding=\"async\" alt=\"Cloud gaming med \u00e5bne kilder p\u00e5 WebRTC: p2p, multiplayer, zero latency.\" src=\"\/wp-content\/uploads\/2020\/07\/22dbf7665d7fded15671d98a2afe599b.png\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><br \/>\nSom software som service, infrastruktur som service, platform som service, kommunikationsplatform som service, videokonferencer som service, men hvad med skyspil som service? Der er allerede gjort flere fors\u00f8g p\u00e5 at skabe skyspil (Cloud Gaming), s\u00e5som Stadia, som blev lanceret af Google for nylig. Stadia <noindex><a rel=\"nofollow\" href=\"https:\/\/youtu.be\/avtlQeaxd_I?t=440\">er ikke en nybegynder inden for WebRTC<\/a><\/noindex>, men kan andre bruge WebRTC p\u00e5 samme m\u00e5de?<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>Thanh Nguyen besluttede at teste denne mulighed i sit open source-projekt CloudRetro. CloudRetro er bygget p\u00e5 Pion, <noindex><a rel=\"nofollow\" href=\"https:\/\/webrtchacks.com\/webrtc-open-source-most-popular\/\">et popul\u00e6rt<\/a><\/noindex> WebRTC-bibliotek baseret p\u00e5 Go (tak til <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/Sean-Der\">Shawn<\/a><\/noindex> fra Pion-udviklerteamet for hj\u00e6lpen til at forberede denne artikel). I denne artikel giver Thanh et overblik over arkitekturen af sit projekt samt hvad nyttigt han har l\u00e6rt og hvilke udfordringer han st\u00f8dte p\u00e5 under arbejdet.<\/p>\n<h2>Introduktion<\/h2>\n<p>\nSidste \u00e5r, da Google annoncerede Stadia, blev jeg helt buzzet. Ideen er s\u00e5 unik og innovativ, at jeg konstant spurgte mig selv, hvordan det overhovedet var muligt med de eksisterende teknologier. \u00d8nsket om at forst\u00e5 emnet bedre fik mig til at skabe min version af et open source-skyspil. Resultatet var ganske fantastisk. Nedenfor vil jeg gerne dele processen med at arbejde p\u00e5 mit \u00e5rlige <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/giongto35\/cloud-game\">projekt<\/a><\/noindex>.<\/p>\n<p><i>TLDR: en kort slides-version med hovedpunkterne<\/i><\/p>\n<h3>Hvorfor skyspil er fremtiden<\/h3>\n<p>\nJeg tror, at Cloud Gaming snart bliver den nye generation ikke kun af spil, men ogs\u00e5 af andre omr\u00e5der inden for datalogi. Skyspil er toppen af klient\/server-modellen. Denne model maksimerer backend-kontrol og minimerer frontend-arbejde ved at placere spil-logikken p\u00e5 en fjernserver og streame billeder\/lyd til klienten. Serveren udf\u00f8rer den tunge behandling, s\u00e5 klienten ikke l\u00e6ngere er afh\u00e6ngig af hardwarebegr\u00e6nsninger.<\/p>\n<p>Google Stadia giver i bund og grund mulighed for at spille <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/AAA_(%D0%BA%D0%BE%D0%BC%D0%BF%D1%8C%D1%8E%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B5_%D0%B8%D0%B3%D1%80%D1%8B)\">AAA-spil<\/a><\/noindex> (dvs. high-end blockbuster-spil) p\u00e5 en gr\u00e6nseflade som YouTube. Den samme metode kan anvendes p\u00e5 andre kr\u00e6vende offline-applikationer, s\u00e5som operativsystemer eller 2D\/3D grafisk design, s\u00e5 vi kan k\u00f8re dem stabilt p\u00e5 enheder med lave specifikationer p\u00e5 tv\u00e6rs af forskellige platforme.<\/p>\n<p><img decoding=\"async\" alt=\"Cloud gaming med \u00e5bne kilder p\u00e5 WebRTC: p2p, multiplayer, zero latency.\" src=\"\/wp-content\/uploads\/2020\/07\/d6ca3e47db5c8e3d9880b304cc3be33b.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nFremtiden for denne teknologi: forestil dig, hvis Microsoft Windows 10 fungerede i Chrome-browseren?<\/p>\n<h3>Skyspil er teknisk komplekse<\/h3>\n<p>\nGaming er et af de sj\u00e6ldne omr\u00e5der, hvor brugeren kr\u00e6ver en konstant hurtig reaktion. Hvis vi lejlighedsvis oplever en forsinkelse p\u00e5 2 sekunder ved et klik p\u00e5 siden, er det acceptabelt. Videostr\u00f8mme i realtid har som regel et eftersl\u00e6b p\u00e5 flere sekunder, men tilbyder stadig en tilstr\u00e6kkelig brugervenlighed. Men hvis et spil ofte har en forsinkelse p\u00e5 500 ms, er det simpelthen umuligt at spille. Vores m\u00e5l er at opn\u00e5 en ekstremt lav forsinkelse, s\u00e5 kl\u00f8ften mellem input og medier er s\u00e5 lille som muligt. Derfor er den traditionelle tilgang til streamingvideo ikke anvendelig her.<\/p>\n<p><img decoding=\"async\" alt=\"Cloud gaming med \u00e5bne kilder p\u00e5 WebRTC: p2p, multiplayer, zero latency.\" src=\"\/wp-content\/uploads\/2020\/07\/d73765a3c9277c026f407883e1091473.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nGenerelt skabelon for cloud gaming<\/p>\n<h2>Open source-projektet CloudRetro<\/h2>\n<p>\nJeg besluttede at skabe et testeksempel p\u00e5 cloud gaming for at unders\u00f8ge, om dette overhovedet er muligt under s\u00e5danne strenge netv\u00e6rksbetingelser. Til konceptets validering valgte jeg Golang, da det er det sprog, jeg kender bedst, og som viste sig at v\u00e6re velegnet til denne implementering af mange andre grunde. Go er enkelt og udvikler sig meget hurtigt; Go-kanaler er fremragende til at h\u00e5ndtere multitr\u00e5dning.<\/p>\n<p>Projekt <noindex><a rel=\"nofollow\" href=\"http:\/\/cloudretro.io\/\">CloudRetro.io<\/a><\/noindex> \u2013 en cloud gaming service med open source for retro-spil. Projektets m\u00e5l er at bringe de mest behagelige spilleoplevelser til traditionelle retro-spil og tilf\u00f8je multiplayer.<br \/>\nDu kan f\u00e5 en detaljeret indsigt i projektet her: <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/giongto35\/cloud-game\">https:\/\/github.com\/giongto35\/cloud-game<\/a><\/noindex>.<\/p>\n<h3>CloudRetro-funktionalitet<\/h3>\n<p>\nFor at demonstrere kraften af cloud gaming anvendes retro-spil i CloudRetro. Dette giver mulighed for at opn\u00e5 mange unikke spilleoplevelser.<\/p>\n<ul>\n<li>Portabilitet af spil\n<ul>\n<li>Sofortspil ved \u00e5bning af siden; download og installation er ikke n\u00f8dvendige<\/li>\n<li>Fungerer i mobilbrowseren, s\u00e5 ingen softwareinstallation er n\u00f8dvendig for at starte<\/li>\n<\/ul>\n<p>\n<\/li>\n<li>Spilsessioner kan deles p\u00e5 flere enheder og gemmes i skyen til n\u00e6ste indlogning<\/li>\n<li>Spillet kan streames, eller det kan spilles af flere brugere samtidigt:\n<ul>\n<li>Crowdplay som TwitchPlayPokemon, blot mere tv\u00e6rplatforms og mere realtid<\/li>\n<li>Offline spil online. Mange brugere kan spille uden netv\u00e6rksindstillinger. I Samurai Shodown kan nu 2 spillere spille via CloudRetro-netv\u00e6rket<\/li>\n<\/ul>\n<p>\n<img decoding=\"async\" alt=\"Cloud gaming med \u00e5bne kilder p\u00e5 WebRTC: p2p, multiplayer, zero latency.\" src=\"\/wp-content\/uploads\/2020\/07\/bdc715971755d669a026f830ce888520.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nDemo-version af multiplayer online-spillet p\u00e5 tv\u00e6rs af enheder<\/p>\n<h2>Infrastruktur<\/h2>\n<p><\/p>\n<h3>Krav og teknologistack<\/h3>\n<p>\nNedenfor er en liste over kravene, jeg opstillede, inden jeg begyndte p\u00e5 projektet.<\/p>\n<p><b>1. En spiller<\/b><br \/>\nDette krav kan synes ubetydeligt og \u00e5benlyst her, men det er en af mine vigtigste konklusioner; det g\u00f8r det muligt for cloud gaming at holde sig s\u00e5 langt v\u00e6k fra traditionelle streamingtjenester som muligt. Hvis vi fokuserer p\u00e5 enspiller-spil, kan vi undg\u00e5 et centraliseret server eller CDN, fordi vi ikke beh\u00f8ver at streame til masserne. I stedet for at uploade streams til en omfavnende server eller sende pakker til en centraliseret WebSocket-server, leveres service streams direkte til brugeren gennem en peer-to-peer WebRTC-forbindelse.<\/p>\n<p><b>2. Lav-latens mediestr\u00f8m<\/b><br \/>\nN\u00e5r jeg l\u00e6ser om Stadia, st\u00f8der jeg ofte p\u00e5 omtale af WebRTC i nogle artikler. Jeg har indset, at WebRTC er en bem\u00e6rkelsesv\u00e6rdig teknologi, og det passer perfekt til at blive brugt i cloud gaming. WebRTC er et projekt, der giver web-browsere og mobile applikationer realtidskommunikation gennem et enkelt API. Det tilbyder en peer-to-peer forbindelse, optimeret til medier og har indbyggede standardkodecs som VP8 og H264.<\/p>\n<p>Jeg har prioriteret at sikre en s\u00e5 komfortabel brugeroplevelse som muligt frem for at bevare h\u00f8j billedkvalitet. Der er acceptable tab i algoritmen. Google Stadia har et ekstra trin til at reducere billedst\u00f8rrelsen p\u00e5 serveren, og billederne skaleres til en h\u00f8jere kvalitet f\u00f8r de sendes til peer-noder.<\/p>\n<p><b>3. Fordelt infrastruktur med geografisk routing<\/b><br \/>\nUanset hvor optimal kompressionsalgoritmen og koden er, er netv\u00e6rket stadig en afg\u00f8rende faktor, der bidrager mest til latens. Arkitekturen skal have en mekanisme til at forbinde til den n\u00e6rmeste server til brugeren for at reducere round-trip-tiden (RTT). Arkitekturen skal have \u00e9n koordinator og flere streaming-servere distribueret globalt: Vestlige USA, \u00d8stlige USA, Europa, Singapore, Kina. Alle streaming-servere skal v\u00e6re helt isolerede. Systemet kan justere sin distribution, n\u00e5r en server tilsluttes eller frakobles netv\u00e6rket. S\u00e5ledes g\u00f8r tilf\u00f8jelsen af yderligere servere ved h\u00f8j trafik mulighed for horisontal skalering.<\/p>\n<p><b>4. Browserkompatibilitet<\/b><br \/>\nCloud gaming shines brightest when it demands minimal from users. This means that there's an opportunity to launch directly in the browser. Browsers help create a comfortable gaming experience for users, freeing them from the need to install software and hardware. Browsers also support cross-platform compatibility for both mobile and desktop versions. Fortunately, WebRTC is well-supported across various browsers.<\/p>\n<p><b>5. Klart adskilt mellem gaming interface og service<\/b><br \/>\nJeg betragter cloud gaming service som en platform. Alle skal have mulighed for at forbinde hvad som helst til platformen. Jeg har nu integreret <noindex><a rel=\"nofollow\" href=\"http:\/\/LibRetro\">LibRetro<\/a><\/noindex> med cloud gaming servizio, fordi LibRetro tilbyder et flot interface til en spille emulator for retro-spil som SNES, GBA, PS.<\/p>\n<p><b>6. V\u00e6relser til multiplayer, crowd play og deep-linking med spillet<\/b><br \/>\nCloudRetro underst\u00f8tter mange nye gameplay-funktioner, s\u00e5som CrowdPlay og Online MultiPlayer til retro-spil. Hvis flere brugere \u00e5bner det samme deep-link p\u00e5 forskellige computere, vil de se det samme k\u00f8rende spil og endda kunne deltage i det.<\/p>\n<p>Desuden gemmes spiltilstande i det cloud-baserede lager. Dette giver brugerne mulighed for at forts\u00e6tte spillet n\u00e5r som helst p\u00e5 enhver anden enhed.<\/p>\n<p><b>7. Horisontal skalering<\/b><br \/>\nSom enhver SaaS-l\u00f8sning i dag, skal cloud gaming designes til at v\u00e6re horisontalt skalerbar. Arkitekturen 'koordinator-arbejder' giver mulighed for at tilf\u00f8je flere arbejdere for at h\u00e5ndtere st\u00f8rre trafik.<\/p>\n<p><b>8. Ingen binding til et enkelt cloud<\/b><br \/>\nCloudRetro's infrastruktur hostes p\u00e5 forskellige cloud-udbydere (Digital Ocean, Alibaba, brugerdefineret udbyder) for forskellige regioner. Jeg aktiverer lanceringen i Docker-containere for infrastrukturen og konfigurerer netv\u00e6rksindstillingerne med en bash-script for at undg\u00e5 afh\u00e6ngighed af en enkelt cloud-udbyder. Ved at kombinere dette med NAT Traversal i WebRTC kan vi opn\u00e5 fleksibilitet til at implementere CloudRetro p\u00e5 enhver cloud-platform og endda p\u00e5 maskiner fra enhver bruger.<\/p>\n<h3>Arkitektonisk design<\/h3>\n<p>\n<b>Arbejder:<\/b> (eller den streamende server, n\u00e6vnt ovenfor) multiplicerer spil, starter en kodningspipeline og sender det kodede media til brugerne. Arbejdsinstanser er distribueret globalt, og hver arbejder kan h\u00e5ndtere flere brugersessioner samtidigt.<\/p>\n<p><b>Koordinator:<\/b> ansvarlig for at tilslutte en ny bruger til den mest passende arbejder for streaming. Koordinatoren interagerer med arbejderne via WebSocket.<\/p>\n<p><b>Lager af spiltilstande:<\/b> et centralt fjerntilgangslager for alle spiltilstande. Dette lager sikrer vigtige funktioner s\u00e5som fjerntilgang til gemte\/spillede tilstande.<\/p>\n<p><img decoding=\"async\" alt=\"Cloud gaming med \u00e5bne kilder p\u00e5 WebRTC: p2p, multiplayer, zero latency.\" src=\"\/wp-content\/uploads\/2020\/07\/985447b81350a640b0bd1344b5705113.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nOverordnet arkitektur for CloudRetro<\/p>\n<h3>Brugsscenario<\/h3>\n<p>\nN\u00e5r en ny bruger \u00e5bner CloudRetro i trin 1 og 2, som vist nedenfor, anmodes koordinatoren sammen med en liste over tilg\u00e6ngelige arbejdere p\u00e5 den f\u00f8rste side. Derefter beregner klienten i trin 3 latenserne for alle kandidater ved hj\u00e6lp af en HTTP ping-anmodning. Denne liste over latenser sendes tilbage til koordinatoren, s\u00e5 han kan bestemme den mest passende arbejder til at betjene brugeren. I trin 4 nedenfor oprettes spillet. Et streaming WebRTC-forbindelse etableres mellem brugeren og den tildelte arbejder.<br \/>\n<img decoding=\"async\" alt=\"Cloud gaming med \u00e5bne kilder p\u00e5 WebRTC: p2p, multiplayer, zero latency.\" src=\"\/wp-content\/uploads\/2020\/07\/00199b5942e3e4314609ec0e70ea7162.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nBrugsscenario efter adgang<\/p>\n<h3>Hvad er inde i arbejderens komponent?<\/h3>\n<p>\nSpil- og streamingpipelines opbevares isoleret indeni arbejdere og udveksler information gennem et interface. I \u00f8jeblikket sker denne forbindelse via datatransmission i hukommelsen via <noindex><a rel=\"nofollow\" href=\"https:\/\/tour.golang.org\/concurrency\/2\">Golang-kanaler<\/a><\/noindex> i den samme proces. Det n\u00e6ste m\u00e5l er segmentering, dvs. uafh\u00e6ngig k\u00f8rsel af spillet i en anden proces.<\/p>\n<p><img decoding=\"async\" alt=\"Cloud gaming med \u00e5bne kilder p\u00e5 WebRTC: p2p, multiplayer, zero latency.\" src=\"\/wp-content\/uploads\/2020\/07\/7a90ec2638344467a34604cd4322165c.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nInteraktion mellem arbejds-komponenter<\/p>\n<p>De vigtigste komponenter:<\/p>\n<ul>\n<li><b>WebRTC:<\/b> klientkomponenten, der modtager brugerinput og outputter det kodede media fra serveren.\n<\/li>\n<li><b>Spil emulator:<\/b> spilkoden. Takket v\u00e6re Libretro-biblioteket kan systemet k\u00f8re spillet inden for samme proces og internt opfange media og inputstr\u00f8m.\n<\/li>\n<li>Spillens interne frames opfanges og sendes til koderen.\n<\/li>\n<li><b>Billede-\/lydkoder:<\/b> kodningspipeline, der modtager mediac frames, koder dem i baggrunden og sender de kodede billeder\/lyd.\n<\/li>\n<\/ul>\n<p><\/p>\n<h2>Implementering<\/h2>\n<p>\nCloudRetro bygger p\u00e5 WebRTC som dens grundl\u00e6ggende teknologi, s\u00e5 f\u00f8r jeg dykker ned i detaljerne omkring implementeringen i Golang, vil jeg fort\u00e6lle om WebRTC selv. Det er en fantastisk teknologi, der har hjulpet mig med at opn\u00e5 en forsinkelse i datastreaming p\u00e5 kun en br\u00f8kdel af et sekund.<\/p>\n<h3>WebRTC<\/h3>\n<p>\nWebRTC er designet til at sikre h\u00f8j-kvalitets peer-to-peer forbindelser p\u00e5 native mobilapplikationer og i browsere gennem enkle API'er.<\/p>\n<h4>NAT Traversal <\/h4>\n<p>\nWebRTC er kendt for sin NAT Traversal funktionalitet. WebRTC er designet til peer-to-peer kommunikation. Dets m\u00e5l er at finde den mest passende direkte rute, der undg\u00e5r NAT-gateways og firewalls for peer-to-peer kommunikation gennem en proces kaldet <noindex><a rel=\"nofollow\" href=\"https:\/\/webrtchacks.com\/trickle-ice\/\">ICE<\/a><\/noindex>. I denne proces finder WebRTC API'en din offentlige IP-adresse ved hj\u00e6lp af STUN-servere og videresender den til en relay-server (<noindex><a rel=\"nofollow\" href=\"https:\/\/webrtchacks.com\/?s=turn\">TURN<\/a><\/noindex>), n\u00e5r en direkte forbindelse ikke kan etableres.<\/p>\n<p>CloudRetro udnytter dog ikke denne mulighed fuldt ud. Dets peer-to-peer forbindelser findes ikke mellem brugere, men mellem brugere og cloud-servere. Serverdelen af modellen har f\u00e6rre begr\u00e6nsninger for direkte forbindelser end en typisk brugerenhed. Dette muligg\u00f8r p\u00e5 forh\u00e5nd at \u00e5bne indg\u00e5ende porte eller bruge offentlige IP-adresser direkte, da serveren ikke er bag NAT.<\/p>\n<p>Tidligere \u00f8nskede jeg at omdanne projektet til en distribueringsplatform for spil til Cloud Gaming. Ideen var at lade spiludviklere tilbyde deres spil og streamingsressourcer. Og brugerne ville interagere direkte med udbyderne. P\u00e5 en s\u00e5dan decentraliseret m\u00e5de er CloudRetro kun et middel til at forbinde tredjeparts streamingsressourcer med brugerne, hvilket g\u00f8r det mere skalerbart, n\u00e5r det ikke l\u00e6ngere har hosting. Rollen af WebRTC NAT Traversal er her meget vigtig for at lette initialiseringen af peer-to-peer forbindelsen til tredjeparts streamingsressourcer, hvilket g\u00f8r det lettere for udvikleren at forbinde til netv\u00e6rket.<\/p>\n<h4>Video komprimering<\/h4>\n<p>\nVideokompression er en uundg\u00e5elig del af pipeline, som i h\u00f8j grad bidrager til flowets glathed. Selvom det ikke er n\u00f8dvendigt at kende alle detaljer om videokodning i VP8\/H264, hj\u00e6lper forst\u00e5elsen af konceptet med at h\u00e5ndtere parametrene for streaminghastighed, fejlfinde uventet adf\u00e6rd og justere forsinkelse.<\/p>\n<p>Videokompression til streamingtjenester er en kompleks opgave, da algoritmen skal sikre, at den samlede kodningstid + netv\u00e6rksoverf\u00f8rselstid + dekodningstid er s\u00e5 lav som muligt. Derudover skal kodningsprocessen v\u00e6re konsistent og kontinuerlig. Nogle indbyrdes kompromiser ved kodning er ikke anvendelige \u2013 for eksempel kan vi ikke prioritere l\u00e6ngere kodningstid over mindre filst\u00f8rrelse og dekodningstid eller anvende inkonsistent kompression.<\/p>\n<p>Ideen med videokompression er at udelade un\u00f8dvendige bits af information, samtidig med at et acceptabelt niveau af n\u00f8jagtighed for brugerne opretholdes. Ud over at kode individuelle statiske billedrammer laver algoritmen en antagelse for det aktuelle billede baseret p\u00e5 det foreg\u00e5ende og det n\u00e6ste, s\u00e5 kun forskellen mellem dem sendes. Som det ses i eksemplet med Pacman, sendes kun de differentielle punkter.<\/p>\n<p><img decoding=\"async\" alt=\"Cloud gaming med \u00e5bne kilder p\u00e5 WebRTC: p2p, multiplayer, zero latency.\" src=\"\/wp-content\/uploads\/2020\/07\/e452c54c53ab7797b610620aefbba8d2.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nSammenligning af videorammer med Pacman-eksemplet<\/p>\n<h4>Kompresion af lyd<\/h4>\n<p>\nP\u00e5 samme m\u00e5de udelader lyddatakompresseringsalgoritmen data, der ikke kan opfattes af mennesker. Opus er i \u00f8jeblikket den lydkodek med den bedste ydelse. Den er udviklet til at transmittere lydsignaler via protokoller til ordnet datagram, s\u00e5som RTP (Real Time Transport Protocol \u2013 protokol til transmission af realtids trafik). Dens latens er lavere end mp3 og aac, og kvaliteten er h\u00f8jere. Latensen ligger normalt omkring 5~66,5 ms.<\/p>\n<h4>Pion, WebRTC i Golang<\/h4>\n<p>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/pion\/webrtc\">Pion<\/a><\/noindex> \u2013 er et open source-projekt, der bringer WebRTC til Golang. I stedet for den s\u00e6dvanlige indpakning af native C++ WebRTC-biblioteker er Pion en native Golang-implementering af WebRTC med bedre ydeevne, integration med Go samt versionskontrol p\u00e5 WebRTC-protokoller.<\/p>\n<p>Biblioteket tilbyder ogs\u00e5 streaming med mange fremragende indbyggede moduler med mindre end et sekunds forsinkelse. Det har sin egen implementering af STUN, DTLS, SCTP osv. og nogle eksperimenter med QUIC og WebAssembly. Selve denne open source-bibliotek er en virkelig god l\u00e6ringskilde med fremragende dokumentation, implementering af netv\u00e6rksprotokoller og flotte eksempler.<\/p>\n<p>Pion-f\u00e6llesskabet, ledet af en meget passioneret skaber, er ret livligt, der er mange kvalitetsdiskussioner om WebRTC. Hvis du er interesseret i denne teknologi, s\u00e5 tilslut dig <noindex><a rel=\"nofollow\" href=\"http:\/\/pion.ly\/slack\">http:\/\/pion.ly\/slack<\/a><\/noindex> \u2013 du vil l\u00e6re meget nyt.<\/p>\n<h3>Skrivning af CloudRetro i Golang<\/h3>\n<p>\n<img decoding=\"async\" alt=\"Cloud gaming med \u00e5bne kilder p\u00e5 WebRTC: p2p, multiplayer, zero latency.\" src=\"\/wp-content\/uploads\/2020\/07\/f85f7b8ea579fab964d870aad698c7e7.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nImplementering af en worker i Go<\/p>\n<h4>Go-kanaler i aktion<\/h4>\n<p>\nTakket v\u00e6re det smukke design af Go-kanaler bliver problemer med begivenhedsstreaming og parallelisme betydeligt forenklet. Som vist i diagrammet, arbejder flere komponenter parallelt i forskellige GoRoutines. Hver komponent styrer sin egen tilstand og kommunikerer via kanaler. Den selektive udsagn i Golang tvinger os til at behandle \u00e9t atomar begivenhed ad gangen i hvert \u00f8jeblik i spillet (game tick). Det betyder, at der ikke er behov for l\u00e5sning i et s\u00e5dant design. For eksempel, n\u00e5r en bruger gemmer, kr\u00e6ves et fuldt snapshot af spillets tilstand. Denne tilstand skal forblive kontinuerlig, mens den logger ind, indtil gemmingen er fuldf\u00f8rt. Under hvert game tick kan backend kun h\u00e5ndtere enten gemme- eller inputoperationen, hvilket g\u00f8r processen tr\u00e5dsikker.<\/p>\n<pre><code class=\"go\">func (e *gameEmulator) gameUpdate() {\nfor {\n\tselect {\n\t\tcase &lt;-e.saveOperation:\n\t\t\te.saveGameState()\n\t\tcase key := &lt;-e.input:\n\t\t\te.updateGameState(key)\n\t\tcase &lt;-e.done:\n\t\t\te.close()\n\t\t\treturn\n\t}\n    }\n}<\/code><\/pre>\n<p><\/p>\n<h4>Fan-in \/ Fan-out<\/h4>\n<p>\nDenne Golang-skabelon passer perfekt til mit brugsscenarie med CrowdPlay og Multiple Player. Ved at f\u00f8lge denne skabelon integreres alle brugerindgange i et enkelt rum i en central indgangskanal. Spilmedierne distribueres derefter til alle brugere i det samme rum. P\u00e5 denne m\u00e5de opn\u00e5r vi en opdeling af spillets tilstand mellem flere spilsessioner fra forskellige brugere.<\/p>\n<p><img decoding=\"async\" alt=\"Cloud gaming med \u00e5bne kilder p\u00e5 WebRTC: p2p, multiplayer, zero latency.\" src=\"\/wp-content\/uploads\/2020\/07\/000a495d7f214246a8a396aab11a3ac5.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nSynkronisering mellem forskellige sessioner<\/p>\n<h4>Ulemper ved Golang<\/h4>\n<p>\nGolang er ikke perfekt. Kanalen er langsom. I forhold til kan blokkering af Go \u2013 det er blot en enklere m\u00e5de at h\u00e5ndtere parallelle og str\u00f8mlinede h\u00e6ndelser p\u00e5, men kanalen giver ikke den bedste ydeevne. Under kanalen findes der kompleks blokkeringslogik. Derfor har jeg lavet nogle justeringer i implementeringen ved at genanvende blokeringer og atomare v\u00e6rdier, n\u00e5r jeg erstatter kanaler for at optimere ydeevnen.<\/p>\n<p>Desuden er garbage collector i Golang ukontrolleret, hvilket nogle gange f\u00f8rer til mist\u00e6nkeligt lange pauser. Dette er en stor hindring for realtidsapplikationer.<\/p>\n<h4>CGO<\/h4>\n<p>\nProjektet bruger den eksisterende VP8\/H264 Golang open source-bibliotek til mediekomprimering og Libretro til spille-emulatorer. Alle disse biblioteker er blot indpakninger af C-biblioteket i Go ved at bruge <noindex><a rel=\"nofollow\" href=\"https:\/\/golang.org\/cmd\/cgo\/\">CGO<\/a><\/noindex>. Nogle af manglerne er n\u00e6vnt i <noindex><a rel=\"nofollow\" href=\"https:\/\/dave.cheney.net\/2019\/10\/06\/use-internal-packages-to-reduce-your-public-api-surface\">denne post af Dave Cheney<\/a><\/noindex>. Problemerne, jeg har st\u00f8dt p\u00e5:<\/p>\n<ul>\n<li>umuligheden af at fange crashes i CGO, selv med Golang RecoveryCrash;<\/li>\n<li>umuligheden af at identificere flaskehalse i ydeevnen, n\u00e5r vi ikke kan opdage detaljerede problemer i CGO.<\/li>\n<\/ul>\n<p><\/p>\n<h2>Konklusion<\/h2>\n<p>\nJeg n\u00e5ede mit m\u00e5l \u2013 at forst\u00e5 cloud gaming-tjenester og skabe en platform, der g\u00f8r det muligt at spille nostalgiske retro-spil med mine venner online. Oprettelsen af dette projekt ville ikke have v\u00e6ret muligt uden Pion-biblioteket og Pion-f\u00e6llesskabets st\u00f8tte. Jeg er ekstremt taknemmelig for den intensive udvikling. De enkle API'er, der tilbydes af WebRTC og Pion, sikrede en glidende integration. Mit f\u00f8rste proof of concept blev frigivet i den samme uge, selvom jeg ikke p\u00e5 forh\u00e5nd kendte til peer-to-peer-forbindelse (P2P).<\/p>\n<p>P\u00e5 trods af den enkle integration er P2P-streaming faktisk et meget komplekst omr\u00e5de inden for computervidenskab. Det m\u00e5 h\u00e5ndtere kompleksiteten af mange\u00e5rige netv\u00e6rksarkitekturer som IP og NAT for at etablere en peer-to-peer-session. I l\u00f8bet af mit arbejde med dette projekt har jeg opsamlet mange v\u00e6rdifulde indsigter om netv\u00e6rk og performanceoptimering, s\u00e5 jeg anbefaler alle at pr\u00f8ve at bygge P2P-produkter ved hj\u00e6lp af WebRTC.<\/p>\n<p>CloudRetro d\u00e6kker alle brugsscenarier, som jeg forventede, set fra mit perspektiv som retro-gamer. Jeg mener dog, at der er mange omr\u00e5der i projektet, jeg kan forbedre, s\u00e5som at g\u00f8re netv\u00e6rket mere p\u00e5lideligt og effektivt, sikre en bedre grafisk kvalitet i spillene, eller muligheden for at dele spil mellem brugere. Jeg arbejder h\u00e5rdt p\u00e5 dette. F\u00f8lg venligst med <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/giongto35\/cloud-game\">projekt<\/a><\/noindex> og st\u00f8t det, hvis du kan lide det.<\/li>\n<\/ul>\n<p>Kilde: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/Voximplant\/blog\/511626\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041f\u041e \u043a\u0430\u043a \u0443\u0441\u043b\u0443\u0433\u0430, \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043a\u0430\u043a \u0443\u0441\u043b\u0443\u0433\u0430, \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 \u043a\u0430\u043a \u0443\u0441\u043b\u0443\u0433\u0430, \u043a\u043e\u043c\u043c\u0443\u043d\u0438\u043a\u0430\u0446\u0438\u043e\u043d\u043d\u0430\u044f \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 \u043a\u0430\u043a \u0443\u0441\u043b\u0443\u0433\u0430, \u0432\u0438\u0434\u0435\u043e\u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0438 \u043a\u0430\u043a \u0443\u0441\u043b\u0443\u0433\u0430, \u0430 \u0447\u0442\u043e \u043d\u0430\u0441\u0447\u0435\u0442 \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0445 \u0438\u0433\u0440 \u043a\u0430\u043a \u0443\u0441\u043b\u0443\u0433\u0438? \u0423\u0436\u0435 \u0431\u044b\u043b\u043e \u043f\u0440\u0435\u0434\u043f\u0440\u0438\u043d\u044f\u0442\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043f\u044b\u0442\u043e\u043a \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0445 \u0438\u0433\u0440 (Cloud Gaming), \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, Stadia, \u043d\u0435\u0434\u0430\u0432\u043d\u043e \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043d\u0430\u044f \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0435\u0439 Google. Stadia \u043d\u0435 \u043d\u043e\u0432\u0438\u0447\u043e\u043a \u0432 WebRTC, \u043d\u043e \u043c\u043e\u0433\u0443\u0442 \u043b\u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c WebRTC \u0442\u0430\u043a \u0436\u0435? \u0422\u0445\u0430\u043d\u044c \u041d\u0433\u0443\u0435\u043d (Thanh [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":89304,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-89303","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.3 - aioseo.com -->\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/da\/blog\/administrirovanie\/oblachnyj-gejming-s-otkrytym-ishodnym-kodom-na-webrtc-p2p-multipleer-zero-latency\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"da_DK\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041e\u0431\u043b\u0430\u0447\u043d\u044b\u0439 \u0433\u0435\u0439\u043c\u0438\u043d\u0433 \u0441 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c \u043d\u0430 WebRTC: p2p, \u043c\u0443\u043b\u044c\u0442\u0438\u043f\u043b\u0435\u0435\u0440, zero latency | ProHoster\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/da\/blog\/administrirovanie\/oblachnyj-gejming-s-otkrytym-ishodnym-kodom-na-webrtc-p2p-multipleer-zero-latency\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-07-21T23:42:30+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-07-21T23:42:30+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Cloud gaming med open source p\u00e5 WebRTC: p2p, multiplayer, zero latency | ProHoster","description":"","canonical_url":"https:\/\/prohoster.info\/da\/blog\/administrirovanie\/oblachnyj-gejming-s-otkrytym-ishodnym-kodom-na-webrtc-p2p-multipleer-zero-latency","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"da_DK","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041e\u0431\u043b\u0430\u0447\u043d\u044b\u0439 \u0433\u0435\u0439\u043c\u0438\u043d\u0433 \u0441 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c \u043d\u0430 WebRTC: p2p, \u043c\u0443\u043b\u044c\u0442\u0438\u043f\u043b\u0435\u0435\u0440, zero latency | ProHoster","og:url":"https:\/\/prohoster.info\/da\/blog\/administrirovanie\/oblachnyj-gejming-s-otkrytym-ishodnym-kodom-na-webrtc-p2p-multipleer-zero-latency","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-07-21T23:42:30+00:00","article:modified_time":"2020-07-21T23:42:30+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"89303","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 13:12:27","updated":"2022-09-29 13:03:06","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts\/89303","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/comments?post=89303"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts\/89303\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/media\/89304"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/media?parent=89303"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/categories?post=89303"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/tags?post=89303"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}