Malfermfonta nuba videoludado sur WebRTC: p2p, multiludanto, nula latenco

Malfermfonta nuba videoludado sur WebRTC: p2p, multiludanto, nula latenco
Programaro kiel servo, infrastrukturo kiel servo, platformo kiel servo, komunika platformo kiel servo, videokonferenco kiel servo, kio pri nuba videoludado kiel servo? Jam estis pluraj provoj krei nuban videoludadon (Cloud Gaming), kiel Stadia, ĵus lanĉita de Guglo. Stadio ne nova al WebRTC, sed ĉu aliaj povas uzi WebRTC same?

Thanh Nguyen decidis testi ĉi tiun ŝancon en sia malfermfonta projekto CloudRetro. CloudRetro estas bazita sur Pion, populara WebRTC-biblioteko bazita sur Go (dankon Montrita de la Pion-disvolva teamo pro ilia helpo en la preparado de ĉi tiu artikolo). En ĉi tiu artikolo, Thanh donas superrigardon de la arkitekturo de sia projekto, kaj ankaŭ parolas pri kiaj utilaj aferoj li lernis kaj kiajn defiojn li renkontis dum sia laboro.

eniro

Pasintjare, kiam Google anoncis Stadia, ĝi blovis mian menson. La ideo estas tiel unika kaj noviga, ke mi konstante scivolis, kiel tio eĉ eblis kun ekzistanta teknologio. La deziro pli bone kompreni ĉi tiun temon instigis min krei mian propran version de malfermfonta nuba ludo. La rezulto estis simple mirinda. Ĉi-sube mi ŝatus konigi la procezon labori pri mia jaro projekto.

TLDR: mallonga glita versio kun kulminaĵoj

Kial nuba videoludado estas la estonteco

Mi kredas, ke Cloud Gaming baldaŭ fariĝos la venonta generacio de ne nur videoludado, sed ankaŭ aliaj areoj de komputiko. Nuba videoludado estas la pinto de la modelo de kliento/servilo. Ĉi tiu modelo maksimumigas backend-administradon kaj minimumigas fasan laboron gastigante ludlogikon sur fora servilo kaj fluante bildojn/aŭdon al la kliento. La servilo faras la pezan prilaboradon, do la kliento ne plu estas sub la merced de aparataj limigoj.

Google Stadia esence permesas vin ludi AAA-ludoj (t.e. altnivelaj furorludoj) sur interfaco kiel Jutubo. La sama metodaro povas esti aplikita al aliaj pezaj senretaj aplikoj kiel ekzemple operaciumo aŭ 2D/3D grafika dezajno, ktp. por ke ni povu ruli ilin konstante sur malaltaj specifaj aparatoj tra pluraj platformoj.

Malfermfonta nuba videoludado sur WebRTC: p2p, multiludanto, nula latenco
La estonteco de ĉi tiu teknologio: Imagu ĉu Microsoft Windows 10 funkciis per la retumilo Chrome?

Nuba videoludado estas teknike malfacila

Ludado estas unu el tiuj maloftaj areoj kie konstanta, rapida uzantrespondo estas postulata. Se foje ni renkontas 2 sekundajn prokraston klakante sur paĝo, tio estas akceptebla. Vivaj videofluoj tendencas malfrui kelkajn sekundojn, sed tamen ofertas akcepteblan uzeblecon. Tamen, se la ludo ofte postrestas je 500ms, ĝi estas simple neludebla. Nia celo estas atingi ekstreme malaltan latentecon por ke la interspaco inter enigo kaj amaskomunikilaro estu kiel eble plej malgranda. Tial, la tradicia aliro al videofluado ne aplikeblas ĉi tie.

Malfermfonta nuba videoludado sur WebRTC: p2p, multiludanto, nula latenco
Ĝenerala Nuba Ludo Ŝablono

Malfermfonta projekto CloudRetro

Mi decidis krei provan specimenon de nuba ludo por vidi, ĉu ĉio ĉi eblis kun tiel striktaj retaj limigoj. Mi elektis Golangon por la pruvo de koncepto ĉar ĝi estis la lingvo kun kiu mi plej konis kaj estis bone taŭga por ĉi tiu efektivigo pro multaj aliaj kialoj, kiel mi poste malkovris. Go estas simpla kaj evoluas tre rapide; Kanaloj en Go estas bonegaj por administri multfadenadon.

La projekto CloudRetro.io estas malfermfonta nuba videoludado servo por retro videoludado. La celo de la projekto estas alporti la plej komfortan ludsperton al tradiciaj retroludoj kaj aldoni multiludanton.
Vi povas lerni pli pri la projekto ĉi tie: https://github.com/giongto35/cloud-game.

CloudRetro-funkcio

CloudRetro uzas retroajn ludojn por pruvi la potencon de nuba videoludado. Kiu permesas vin akiri multajn unikajn ludajn spertojn.

  • Portebleco de la ludo
    • Tuja reproduktado dum malfermado de la paĝo; neniu elŝuto aŭ instalado necesas
    • Funkcias en movebla retumilo, do neniu programaro necesas por ruli ĝin

  • Ludaj sesioj povas esti dividitaj tra pluraj aparatoj kaj konservitaj en la nubo por venontfoje kiam vi ensalutas
  • La ludo povas esti elsendita, aŭ ĝi povas esti ludita de pluraj uzantoj samtempe:
    • Crowdplay kiel TwitchPlayPokemon, nur pli transplatforma kaj pli realtempa
    • Senretaj ludoj interrete. Multaj uzantoj povas ludi sen starigi reton. Samurai Shodown nun povas esti ludita de 2 ludantoj per la reto CloudRetro

    Malfermfonta nuba videoludado sur WebRTC: p2p, multiludanto, nula latenco
    Demoversio de interreta plurludanta ludo sur malsamaj aparatoj

    Infrastrukturo

    Postuloj kaj teknologia stako

    Malsupre estas listo de postuloj, kiujn mi starigis antaŭ ol komenci la projekton.

    1. Unu ludanto
    Ĉi tiu postulo eble ne ŝajnas tro grava aŭ evidenta ĉi tie, sed ĝi estas unu el miaj ŝlosilaj elprenaĵoj, ĝi permesas al nuba videoludado resti kiel eble plej malproksime de tradiciaj streaming-servoj. Se ni koncentriĝas pri unu-ludanta ludo, ni povas forigi centralizitan servilon aŭ CDN ĉar ni ne devas flui al la amasoj. Anstataŭ alŝutado de riveretoj al lavujservilo aŭ pasado de pakaĵetoj al alcentrigita WebSocket-servilo, servriveretoj estas liveritaj rekte al la uzanto per kunul-al-kunula WebRTC-ligo.

    2. Malalta latencia amaskomunikiloj rivereto
    Legante pri Stadia, mi ofte vidas WebRTC menciita en iuj artikoloj. Mi rimarkis, ke WebRTC estas elstara teknologio kaj estas perfekta por uzo en nuba videoludado. WebRTC estas projekto kiu provizas TTT-legilojn kaj moveblajn aplikaĵojn per realtempa komunikado per simpla API. Ĝi provizas samrangan konekteblecon, estas optimumigita por amaskomunikilaro kaj havas normajn kodekojn enkonstruitajn kiel ekzemple VP8 kaj H264.

    Mi prioritatis certigi la plej bonan eblan sperton de uzanto super konservi altkvalitajn grafikojn. Kelkaj perdoj estas akcepteblaj en la algoritmo. Google Stadia havas plian paŝon redukti la bildgrandecon sur la servilo, kaj kadroj estas plialtigitaj al pli alta kvalito antaŭ ol esti transdonitaj al kunuloj.

    3. Distribuita infrastrukturo kun geografia vojigo
    Kiom ajn optimumigitaj estas la kunprema algoritmo kaj kodo, la reto ankoraŭ estas la decida faktoro, kiu plej kontribuas al latencia. La arkitekturo devas havi mekanismon por parigi la servilon plej proksiman al la uzanto por redukti rondveturan tempon (RTT). La arkitekturo devas havi 1 kunordiganton kaj plurajn streaming-servilojn distribuitajn tra la mondo: Usona Okcidento, Usono-Oriento, Eŭropo, Singapuro, Ĉinio. Ĉiuj fluaj serviloj devas esti tute izolitaj. La sistemo povas ĝustigi sian distribuon kiam servilo aliĝas aŭ forlasas la reton. Tiel, kun granda trafiko, aldoni pliajn servilojn ebligas horizontalan skaladon.

    4. Retumilo kongruo
    Nuba videoludado estas plej bona kiam ĝi postulas la malplej de uzantoj. Ĉi tio signifas, ke eblas ruli en retumilo. Retumiloj helpas fari la videoludadan sperton kiel eble plej komforta por uzantoj, ŝparante ilin de instalado de programaro kaj aparataro. Retumiloj ankaŭ helpas provizi multiplatforman funkciecon inter poŝtelefonaj kaj labortablaj versioj. Feliĉe, WebRTC estas bone subtenata tra diversaj retumiloj.

    5. Klara disiĝo de la ludinterfaco kaj servo
    Mi rigardas la nuban videoludadan servon kiel platformon. Ĉiuj devus povi konekti ion ajn al la platformo. Nun mi integriĝis LibRetro kun nuba videoludada servo ĉar LibRetro ofertas belan ludemulinterfacon por retroludoj kiel SNES, GBA, PS.

    6. Ĉambroj por plurludanto, amasludado kaj ekstera ligo (profunda ligo) kun la ludo
    CloudRetro subtenas multajn novajn ludadon kiel CrowdPlay kaj Online MultiPlayer por retroludoj. Se pluraj uzantoj malfermas la saman profundan ligon en malsamaj komputiloj, ili vidos la saman ludon funkcii kaj eĉ povos aliĝi al ĝi.

    Plie, ludŝtatoj estas stokitaj en nuba stokado. Ĉi tio permesas al uzantoj daŭrigi ludi iam ajn en iu ajn alia aparato.

    7. Horizontala skalo
    Kiel ajna SAAS nuntempe, nuba videoludado devas esti desegnita por esti horizontale skalebla. La dezajno de kunordiganto-laboristo permesas vin aldoni pli da laboristoj por servi pli da trafiko.

    8. Neniu konekto al unu nubo
    La infrastrukturo de CloudRetro estas gastigita sur malsamaj nubaj provizantoj (Cifereca Oceano, Alibaba, kutima provizanto) por malsamaj regionoj. Mi ebligas ruladon en Docker-ujo por la infrastrukturo kaj agordas retajn agordojn per bash-skripto por eviti esti ŝlosita en ununura nuba provizanto. Kombinante ĉi tion kun NAT Traversal en WebRTC, ni povas havi la flekseblecon por deploji CloudRetro sur ajna nuba platformo kaj eĉ sur la maŝinoj de iu ajn uzanto.

    Arkitektura dezajno

    Laboristo: (aŭ la fluanta servilo menciita supre) multobligas la ludojn, prizorgas la kodan dukton kaj fluas la kodigitan amaskomunikilaron al uzantoj. Laboristaj petskriboj estas distribuitaj tra la mondo, kaj ĉiu laboristo povas trakti plurajn uzantsesiojn samtempe.

    Kunordiganto: respondecas pri parigo de la nova uzanto kun la plej taŭga laboristo por streaming. La kunordiganto interagas kun laboristoj per WebSocket.

    Ludŝtata stokado: centra fora stokado por ĉiuj ludŝtatoj. Ĉi tiu stokado disponigas gravajn funkciojn kiel fora konservado/ŝarĝo.

    Malfermfonta nuba videoludado sur WebRTC: p2p, multiludanto, nula latenco
    Pintnivela arkitekturo de CloudRetro

    Propra Skripto

    Kiam nova uzanto malfermas CloudRetro en paŝoj 1 kaj 2 montritaj en la suba figuro, la kunordiganto kune kun la listo de disponeblaj laboristoj estas petita al la unua paĝo. Post ĉi tio, en la paŝo 3 la kliento kalkulas la prokrastojn por ĉiuj kandidatoj uzante HTTP-ping-peton. Ĉi tiu listo de prokrastoj tiam estas sendita reen al la kunordiganto por ke li determini la plej taŭgan laboriston por servi la uzanton. Paŝo 4 sube kreas la ludon. WebRTC fluanta konekto estas establita inter la uzanto kaj la asignita laboristo.
    Malfermfonta nuba videoludado sur WebRTC: p2p, multiludanto, nula latenco
    Uzanta skripto post akiri aliron

    Kio estas ene de la laboristo

    Ludaj kaj fluantaj duktoj estas konservitaj ene de la laboristo izole kaj interŝanĝas informojn tie per la interfaco. Nuntempe, ĉi tiu komunikado estas efektivigita per transdono de datumoj en memoro tra Golang-kanaloj en la sama procezo. La sekva celo estas apartigo, t.e. sendependa lanĉo de la ludo en alia procezo.

    Malfermfonta nuba videoludado sur WebRTC: p2p, multiludanto, nula latenco
    Interago de laboristaj komponantoj

    Ĉefaj komponantoj:

    • WebRTC: klientkomponento kiu akceptas uzantan enigon kaj eligas ĉifritan amaskomunikilaron de la servilo.
    • Ludomulilo: ludkomponento. Danke al la biblioteko Libretro, la sistemo povas ruli la ludon ene de la sama procezo kaj interne kapti amaskomunikilaron kaj enigfluon.
    • En-matĉaj kadroj estas kaptitaj kaj senditaj al la kodilo.
    • Bildo/Audiokodilo: kodiga dukto kiu prenas amaskomunikilajn kadrojn, kodas ilin en la fono, kaj eligas kodigitajn bildojn/aŭdon.

    Реализация

    CloudRetro fidas je WebRTC kiel ĝia spina teknologio, do antaŭ ol plonĝi en la detalojn de la Golang-efektivigo, mi decidis paroli pri WebRTC mem. Ĉi tio estas mirinda teknologio, kiu multe helpis min atingi sub-sekundan latentecon por fluado de datumoj.

    WebRTC

    WebRTC estas desegnita por provizi altkvalitajn kunulajn konektojn en indiĝenaj moveblaj programoj kaj retumiloj uzante simplajn APIojn.

    NAT Traversal

    WebRTC estas konata pro sia NAT Traversal-funkcio. WebRTC estas dizajnita por kunul-al-kunula komunikado. Ĝia celo estas trovi la plej taŭgan rektan vojon, evitante NAT-enirejojn kaj fajroŝirmilojn por samulo-al-kunula komunikado per procezo nomata ICE. Kiel parto de ĉi tiu procezo, la WebRTC-APIoj trovas vian publikan IP-adreson uzante STUN-servilojn kaj plusendas ĝin al la relajsa servilo (TURNU) kiam rekta ligo ne povas esti establita.

    Tamen, CloudRetro ne plene ekspluatas ĉi tiun funkcion. Ĝiaj samnivelaj rilatoj ne ekzistas inter uzantoj, sed inter uzantoj kaj nubaj serviloj. La servilflanko de la modelo havas malpli da rektaj komunikadlimigoj ol tipa uzant-aparato. Ĉi tio ebligas al vi antaŭmalfermi envenajn havenojn aŭ uzi publikajn IP-adresojn rekte, ĉar la servilo ne estas malantaŭ NAT.

    Antaŭe, mi volis transformi la projekton en luddistribuan platformon por Cloud Gaming. La ideo estis permesi al ludkreintoj disponigi ludojn kaj fluajn rimedojn. Kaj uzantoj rekte interagus kun provizantoj. En ĉi tiu malcentralizita maniero, CloudRetro estas nur kadro por konekti triajn fluajn rimedojn al uzantoj, farante ĝin pli skalebla kiam ĝi ne plu estas gastigita. La rolo de WebRTC NAT Traversal ĉi tie estas tre grava por faciligi kunul-al-kunulan konekton inicialigon sur triaj fluaj rimedoj, faciligante por la kreinto konekti al la reto.

    Video kunpremo

    Videokunpremo estas nemalhavebla parto de la dukto kaj multe kontribuas al glata fluo. Kvankam ne necesas koni ĉiun detalon de VP8/H264-kodigo de video, kompreni la konceptojn povas helpi vin kompreni la opciojn pri fluado de video-rapideco, sencimigi neatenditan konduton kaj ĝustigi latencian.

    Kunpremado de video por streaming-servo estas defia ĉar la algoritmo devas certigi, ke la tuta koda tempo + rettransdona tempo + malkoda tempo estas kiel eble plej malalta. Krome, la kodiga procezo devas esti konsekvenca kaj kontinua. Kelkaj kodaj kompromisoj ne validas—ekzemple, ni ne povas preferi longajn kodadajn tempojn super pli malgrandaj dosiergrandoj kaj malkodigotempojn, aŭ uzi malkonsekvencan kunpremadon.

    La ideo malantaŭ videokunpremado estas forigi nenecesajn pecetojn da informo konservante akcepteblan nivelon de precizeco por uzantoj. Krom kodi individuajn senmovajn bildkadrojn, la algoritmo konkludas la nunan kadron el la antaŭaj kaj sekvaj, do nur ilia diferenco estas sendita. Kiel videblas el la ekzemplo kun Pacman, nur diferencigaj punktoj estas transdonitaj.

    Malfermfonta nuba videoludado sur WebRTC: p2p, multiludanto, nula latenco
    Komparo de videokadroj uzante Pacman kiel ekzemplon

    Aŭdiokunpremo

    Same, la aŭdkunprema algoritmo preterlasas datumojn, kiuj ne povas esti perceptitaj de homoj. Opus estas nuntempe la plej bone rezultanta sonkodeko. Ĝi estas dizajnita por elsendi sonondon super ordigita datagrama protokolo kiel RTP (Real Time Transport Protocol). Ĝia latenco estas pli malalta ol mp3 kaj aac, kaj la kvalito estas pli alta. La latencia estas kutime ĉirkaŭ 5~66,5ms.

    Pion, WebRTC en Golang

    Peono estas malfermkoda projekto kiu alportas WebRTC al Golang. Anstataŭ la kutima envolviĝo de indiĝenaj C++ WebRTC-bibliotekoj, Pion estas denaska Golang-efektivigo de WebRTC kun pli bona efikeco, Go-integriĝo kaj versiokontrolo pri WebRTC-protokoloj.

    La biblioteko ankaŭ ebligas fluadon kun multaj bonegaj enkonstruaĵoj kun sub-sekunda latenco. Ĝi havas sian propran efektivigon de STUN, DTLS, SCTP, ktp. kaj kelkaj eksperimentoj kun QUIC kaj WebAssembly. Ĉi tiu malfermkoda biblioteko mem estas vere bona lernada rimedo kun bonega dokumentaro, retaj protokolaj realigoj kaj bonegaj ekzemploj.

    La komunumo de Pion, gvidata de tre pasia kreinto, estas sufiĉe vigla, kun multaj kvalitaj diskutoj pri WebRTC. Se vi interesiĝas pri ĉi tiu teknologio, aliĝu http://pion.ly/slack – vi lernos multajn novajn aferojn.

    Skribante CloudRetro en Golang

    Malfermfonta nuba videoludado sur WebRTC: p2p, multiludanto, nula latenco
    Efektivigo de laboristo en Go

    Iru Kanaloj en Agado

    Danke al la bela kanala dezajno de Go, la problemoj de evento-fluado kaj samtempeco estas tre simpligitaj. Kiel en la diagramo, malsamaj GoRoutines havas plurajn komponentojn kurantajn paralele. Ĉiu komponanto administras sian staton kaj komunikas per kanaloj. La selektema aserto de Golang devigas unu atomokazaĵon esti prilaborita ĉiun fojon en la ludo (ludtiktako). Ĉi tio signifas, ke por ĉi tiu dezajno ne necesas ŝlosado. Ekzemple, kiam uzanto ŝparas, estas bezonata plena momentfoto de la ludstato. Ĉi tiu stato devas resti daŭra, ensalutu ĝis la konservado finiĝos. Dum ĉiu ludtajkto, la backend povas nur pritrakti konservadon aŭ enigoperacion, igante la procezan fadenon sekura.

    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-en/Fan-el

    Ĉi tiu Golang-ŝablono perfekte konvenas al mia uzokazo de CrowdPlay kaj Multoblaj Ludantoj. Sekvante ĉi tiun ŝablonon, ĉiuj uzantenigaĵoj en unu ĉambro estas konstruitaj en la centran enirejan kanalon. Ludmedio tiam estas deplojita al ĉiuj uzantoj en la sama ĉambro. Tiamaniere ni atingas la dividon de la ludstato inter pluraj ludsesioj de malsamaj uzantoj.

    Malfermfonta nuba videoludado sur WebRTC: p2p, multiludanto, nula latenco
    Sinkronigo inter malsamaj sesioj

    Malavantaĝoj de Golang

    Golang ne estas perfekta. La kanalo estas malrapida. Kompare al blokado, Go-kanalo estas simple pli facila maniero trakti samtempajn kaj fadenigitajn eventojn, sed kanalo ne provizas la plej bonan rendimenton. Estas kompleksa blokada logiko sub la kanalo. Do mi faris kelkajn ĝustigojn al la efektivigo, reaplikante serurojn kaj atomajn valorojn anstataŭante kanalojn por optimumigi rendimenton.

    Krome, la rubkolektanto en Golang estas neadministrata, kio foje kaŭzas suspektinde longajn paŭzojn. Ĉi tio multe malhelpas la realtempan fluan aplikaĵon.

    COG

    La projekto uzas la ekzistantan malfermfontan bibliotekon Golang VP8/H264 por amaskomunikila kunpremado kaj Libretro por ludemuloj. Ĉiuj ĉi tiuj bibliotekoj estas simple envolvaĵoj de la C-biblioteko en Go uzante COG. Kelkaj el la malavantaĝoj estas listigitaj en ĉi tiu afiŝo de Dave Cheney. Problemoj kiujn mi renkontis:

    • malkapablo kapti kraŝon en CGO, eĉ kun Golang RecoveryCrash;
    • malsukceso identigi rendimentajn proplempunktojn kiam ni ne kapablas detekti detalajn problemojn en CGO.

    konkludo

    Mi atingis mian celon kompreni nubajn videoludadajn servojn kaj krei platformon, kiu helpas min ludi nostalgiajn retroajn ludojn kun miaj amikoj interrete. Tiu ĉi projekto ne estus ebla sen la Pion-biblioteko kaj la subteno de la Pion-komunumo. Mi estas ege dankema pro ĝia intensa disvolviĝo. La simplaj API-oj provizitaj de WebRTC kaj Pion certigis senjuntan integriĝon. Mia unua pruvo de koncepto estis publikigita tiun saman semajnon, kvankam mi havis neniun antaŭan scion pri samulo-al-kunulo (P2P) komunikado.

    Malgraŭ la facileco de integriĝo, P2P-fluado ja estas tre kompleksa areo en komputiko. Ŝi devas trakti la kompleksecon de multjaraj retaj arkitekturoj kiel IP kaj NAT por krei kunulan sesion. Laborante pri ĉi tiu projekto, mi akiris multajn valorajn sciojn pri retoj kaj agado-optimumigo, do mi instigas ĉiujn provi konstrui P2P-produktojn per WebRTC.

    CloudRetro servas ĉiujn uzkazojn, kiujn mi atendis de mia perspektivo kiel retroludanto. Tamen, mi pensas, ke estas multaj areoj en la projekto, kiujn mi povas plibonigi, kiel fari la reton pli fidinda kaj efika, havigi pli altkvalitajn ludajn grafikojn aŭ la eblon dividi ludojn inter uzantoj. Mi multe laboras pri tio. Bonvolu sekvi projekto kaj subtenu ĝin se vi ŝatas ĝin.

fonto: www.habr.com

Aldoni komenton