{"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\/cs\/blog\/administrirovanie\/oblachnyj-gejming-s-otkrytym-ishodnym-kodom-na-webrtc-p2p-multipleer-zero-latency","title":{"rendered":"Cloud gaming s otev\u0159en\u00fdm zdrojov\u00fdm k\u00f3dem na WebRTC: p2p, multiplayer, nulov\u00e1 latence","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 s otev\u0159en\u00fdm zdrojov\u00fdm k\u00f3dem na WebRTC: p2p, multiplayer, nulov\u00e1 latence\" src=\"\/wp-content\/uploads\/2020\/07\/22dbf7665d7fded15671d98a2afe599b.png\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><br \/>\nSlu\u017eba jako produkt, infrastruktura jako slu\u017eba, platforma jako slu\u017eba, komunika\u010dn\u00ed platforma jako slu\u017eba, videokonference jako slu\u017eba, a co cloudov\u00e9 hry jako slu\u017eba? Bylo u\u010din\u011bno n\u011bkolik pokus\u016f o vytvo\u0159en\u00ed cloudov\u00fdch her (Cloud Gaming), nap\u0159\u00edklad Stadia, kter\u00e1 ned\u00e1vno byla spu\u0161t\u011bna spole\u010dnost\u00ed Google. Stadia <noindex><a rel=\"nofollow\" href=\"https:\/\/youtu.be\/avtlQeaxd_I?t=440\">nen\u00ed nov\u00e1\u010dek ve WebRTC<\/a><\/noindex>, ale mohou ostatn\u00ed tak\u00e9 vyu\u017e\u00edvat WebRTC stejn\u011b jako?<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>Thanh Nguyen se rozhodl prov\u011b\u0159it tuto mo\u017enosti ve sv\u00e9m open-source projektu CloudRetro. CloudRetro je zalo\u017een na Pion, <noindex><a rel=\"nofollow\" href=\"https:\/\/webrtchacks.com\/webrtc-open-source-most-popular\/\">popul\u00e1rn\u00ed<\/a><\/noindex> knihovn\u011b WebRTC napsan\u00e9 v Go (d\u011bkuji <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/Sean-Der\">Shonovi<\/a><\/noindex> z t\u00fdmu v\u00fdvoj\u00e1\u0159\u016f Pion za pomoc p\u0159i p\u0159\u00edprav\u011b tohoto \u010dl\u00e1nku). V tomto \u010dl\u00e1nku Thanh p\u0159ehledn\u011b popisuje architekturu sv\u00e9ho projektu, a tak\u00e9 sd\u00edl\u00ed, co se nau\u010dil a s jak\u00fdmi v\u00fdzvami se b\u011bhem pr\u00e1ce setkal.<\/p>\n<h2>\u00davod<\/h2>\n<p>\nLoni, kdy\u017e Google ozn\u00e1mil Stadia, jsem byl naprosto ohromen. My\u0161lenka je tak unik\u00e1tn\u00ed a inovativn\u00ed, \u017ee jsem se neust\u00e1le ptal, jak je to v\u016fbec mo\u017en\u00e9 p\u0159i st\u00e1vaj\u00edc\u00edch technologi\u00edch. Touha l\u00e9pe porozum\u011bt tomuto t\u00e9matu m\u011b podn\u00edtila k vytvo\u0159en\u00ed vlastn\u00ed verze open-source cloudov\u00e9 hry. V\u00fdsledek byl prost\u011b fantastick\u00fd. N\u00ed\u017ee bych cht\u011bl sd\u00edlet proces pr\u00e1ce na sv\u00e9m ro\u010dn\u00edm <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/giongto35\/cloud-game\">projektu<\/a><\/noindex>.<\/p>\n<p><i>TLDR: kr\u00e1tk\u00e1 prezentace se z\u00e1kladn\u00edmi body<\/i><\/p>\n<h3>Pro\u010d maj\u00ed cloudov\u00e9 hry budoucnost<\/h3>\n<p>\nV\u011b\u0159\u00edm, \u017ee Cloud Gaming brzy bude novou generac\u00ed nejen her, ale i dal\u0161\u00edch oblast\u00ed informatiky. Cloudov\u00e9 hry jsou vrchol klient-server modelu. Tento model maximalizuje \u0159\u00edzen\u00ed backendu a minimalizuje pr\u00e1ci frontend t\u00edm, \u017ee um\u00edst\u00ed hern\u00ed logiku na vzd\u00e1len\u00fd server a streamuje obr\u00e1zky\/audi\u00f3 klientovi. Server prov\u00e1d\u00ed n\u00e1ro\u010dn\u00e9 zpracov\u00e1n\u00ed, tak\u017ee klient u\u017e nen\u00ed z\u00e1visl\u00fd na hardwarov\u00fdch omezen\u00edch.<\/p>\n<p>Google Stadia vlastn\u011b umo\u017e\u0148uje hr\u00e1t <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 hry<\/a><\/noindex> (tj. vysoce kvalitn\u00ed blockbusterov\u00e9 hry) na rozhran\u00ed podobn\u00e9m YouTube. Stejn\u00e1 metodologie m\u016f\u017ee b\u00fdt tak\u00e9 aplikov\u00e1na na jin\u00e9 n\u00e1ro\u010dn\u00e9 offline aplikace, jako je opera\u010dn\u00ed syst\u00e9m nebo 2D\/3D grafick\u00fd design, atd., abychom je mohli stabiln\u011b spou\u0161t\u011bt na za\u0159\u00edzen\u00edch s n\u00edzk\u00fdmi technick\u00fdmi specifikacemi nap\u0159\u00ed\u010d r\u016fzn\u00fdmi platformami.<\/p>\n<p><img decoding=\"async\" alt=\"Cloud gaming s otev\u0159en\u00fdm zdrojov\u00fdm k\u00f3dem na WebRTC: p2p, multiplayer, nulov\u00e1 latence\" src=\"\/wp-content\/uploads\/2020\/07\/d6ca3e47db5c8e3d9880b304cc3be33b.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nBudoucnost t\u00e9to technologie: p\u0159edstavte si, kdyby Microsoft Windows 10 b\u011b\u017eel v prohl\u00ed\u017ee\u010di Chrome?<\/p>\n<h3>Cloudov\u00e9 hry jsou technicky slo\u017eit\u00e9<\/h3>\n<p>\nHran\u00ed je jednou z t\u011bch vz\u00e1cn\u00fdch oblast\u00ed, kde je vy\u017eadov\u00e1na neust\u00e1l\u00e1 rychl\u00e1 reakce u\u017eivatele. Pokud ob\u010das naraz\u00edme na zpo\u017ed\u011bn\u00ed 2 sekundy p\u0159i kliknut\u00ed na str\u00e1nce, je to p\u0159ijateln\u00e9. Video streamy na\u017eivu obvykle zpo\u017e\u010fuj\u00ed o n\u011bkolik sekund, ale st\u00e1le nab\u00edzej\u00ed dostate\u010dn\u00e9 pohodl\u00ed p\u0159i pou\u017e\u00edv\u00e1n\u00ed. Nicm\u00e9n\u011b, pokud hra \u010dasto zpo\u017e\u010fuje o 500 ms, je hran\u00ed prost\u011b nemo\u017en\u00e9. Na\u0161\u00edm c\u00edlem je dos\u00e1hnout extr\u00e9mn\u011b n\u00edzk\u00e9ho zpo\u017ed\u011bn\u00ed, aby byl rozd\u00edl mezi vstupem a m\u00e9diem co nejmen\u0161\u00ed. Proto tradi\u010dn\u00ed p\u0159\u00edstup k streamov\u00e1n\u00ed videa zde nen\u00ed pou\u017eiteln\u00fd.<\/p>\n<p><img decoding=\"async\" alt=\"Cloud gaming s otev\u0159en\u00fdm zdrojov\u00fdm k\u00f3dem na WebRTC: p2p, multiplayer, nulov\u00e1 latence\" src=\"\/wp-content\/uploads\/2020\/07\/d73765a3c9277c026f407883e1091473.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nObecn\u00e1 \u0161ablona cloudov\u00e9ho hran\u00ed<\/p>\n<h2>Otev\u0159en\u00fd projekt CloudRetro<\/h2>\n<p>\nRozhodl jsem se vytvo\u0159it testovac\u00ed vzorek cloudov\u00e9ho hran\u00ed, abych zjistil, zda je to mo\u017en\u00e9 za tak p\u0159\u00edsn\u00fdch s\u00ed\u0165ov\u00fdch podm\u00ednek. Pro ov\u011b\u0159en\u00ed konceptu jsem zvolil Golang, proto\u017ee to je jazyk, kter\u00fd nejl\u00e9pe zn\u00e1m a je tak\u00e9 vhodn\u00fd pro tuto implementaci z mnoha dal\u0161\u00edch d\u016fvod\u016f, jak se pozd\u011bji uk\u00e1zalo. Go je jednoduch\u00fd a rychle se rozv\u00edj\u00ed; kan\u00e1ly v Go jsou skv\u011bl\u00e9 pro \u0159\u00edzen\u00ed v\u00edcetrhu.<\/p>\n<p>Projekt <noindex><a rel=\"nofollow\" href=\"http:\/\/cloudretro.io\/\">CloudRetro.io<\/a><\/noindex> \u2013 cloudov\u00e1 hern\u00ed slu\u017eba s otev\u0159en\u00fdm zdrojov\u00fdm k\u00f3dem pro retro hry. C\u00edlem projektu je p\u0159in\u00e9st do tradi\u010dn\u00edch retro her co nejpohodln\u011bj\u0161\u00ed hern\u00ed z\u00e1\u017eitky a p\u0159idat v\u00edce hr\u00e1\u010d\u016f.<br \/>\nPodrobn\u011b se seznamte s projektem zde: <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/giongto35\/cloud-game\">https:\/\/github.com\/giongto35\/cloud-game<\/a><\/noindex>.<\/p>\n<h3>Funk\u010dnost CloudRetro<\/h3>\n<p>\nPro demonstrov\u00e1n\u00ed s\u00edly cloudov\u00e9ho hran\u00ed se v CloudRetro pou\u017e\u00edvaj\u00ed retro hry. To umo\u017e\u0148uje z\u00edskat mno\u017estv\u00ed jedine\u010dn\u00fdch hern\u00edch z\u00e1\u017eitk\u016f.<\/p>\n<ul>\n<li>P\u0159enositelnost hry\n<ul>\n<li>Okam\u017eit\u00e9 p\u0159ehr\u00e1v\u00e1n\u00ed p\u0159i otev\u0159en\u00ed str\u00e1nky; nen\u00ed t\u0159eba stahovat ani instalovat<\/li>\n<li>Funguje v mobiln\u00edm prohl\u00ed\u017ee\u010di, tak\u017ee pro spu\u0161t\u011bn\u00ed nen\u00ed pot\u0159eba \u017e\u00e1dn\u00fd software<\/li>\n<\/ul>\n<p>\n<\/li>\n<li>Hern\u00ed seance lze sd\u00edlet na n\u011bkolika za\u0159\u00edzen\u00edch a ukl\u00e1dat do cloudu pro dal\u0161\u00ed p\u0159ihl\u00e1\u0161en\u00ed<\/li>\n<li>Hru lze streamovat, nebo v n\u00ed mohou hr\u00e1t najednou n\u011bkolik u\u017eivatel\u016f:\n<ul>\n<li>Crowdplay typu TwitchPlayPokemon, jen je to v\u00edce multiplatformn\u00ed a real-time<\/li>\n<li>Offline hry online. Mnoho u\u017eivatel\u016f m\u016f\u017ee hr\u00e1t bez nutnosti nastavov\u00e1n\u00ed s\u00edt\u011b. V Samurai Shodown nyn\u00ed mohou hr\u00e1t 2 hr\u00e1\u010di prost\u0159ednictv\u00edm CloudRetro<\/li>\n<\/ul>\n<p>\n<img decoding=\"async\" alt=\"Cloud gaming s otev\u0159en\u00fdm zdrojov\u00fdm k\u00f3dem na WebRTC: p2p, multiplayer, nulov\u00e1 latence\" src=\"\/wp-content\/uploads\/2020\/07\/bdc715971755d669a026f830ce888520.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nDemo verze multiplayerov\u00e9 online hry na r\u016fzn\u00fdch za\u0159\u00edzen\u00edch<\/p>\n<h2>Infrastruktura<\/h2>\n<p><\/p>\n<h3>Po\u017eadavky a technick\u00fd stack<\/h3>\n<p>\nN\u00ed\u017ee je uveden seznam po\u017eadavk\u016f, kter\u00e9 jsem stanovil p\u0159ed zah\u00e1jen\u00edm projektu.<\/p>\n<p><b>1. Jeden hr\u00e1\u010d<\/b><br \/>\nTato po\u017eadavek se m\u016f\u017ee zd\u00e1t zde jako nep\u0159\u00edli\u0161 d\u016fle\u017eit\u00fd a z\u0159ejm\u00fd, ale je to jedno z m\u00fdch kl\u00ed\u010dov\u00fdch zji\u0161t\u011bn\u00ed, kter\u00e9 umo\u017e\u0148uje cloudov\u00fdm hr\u00e1m se co nejv\u00edce distancovat od tradi\u010dn\u00edch streamovac\u00edch slu\u017eeb. Pokud se zam\u011b\u0159\u00edme na hru pro jednoho hr\u00e1\u010de, m\u016f\u017eeme se zbavit centralizovan\u00e9ho serveru nebo CDN, proto\u017ee nen\u00ed pot\u0159eba streamovat k mas\u00e1m. M\u00edsto toho, abychom nahr\u00e1vali streamy na n\u00e1ro\u010dn\u00fd server nebo pos\u00edlali bal\u00ed\u010dky na centralizovan\u00fd server WebSocket, jsou streamy slu\u017eeb p\u0159ed\u00e1v\u00e1ny u\u017eivateli p\u0159\u00edmo prost\u0159ednictv\u00edm peer-to-peer spojen\u00ed WebRTC.<\/p>\n<p><b>2. Medi\u00e1ln\u00ed stream s n\u00edzkou latenc\u00ed<\/b><br \/>\nP\u0159i \u010dten\u00ed o Stadia se \u010dasto v n\u011bkter\u00fdch \u010dl\u00e1nc\u00edch setk\u00e1v\u00e1m s zm\u00ednkou o WebRTC. Uv\u011bdomil jsem si, \u017ee WebRTC je vynikaj\u00edc\u00ed technologie, kter\u00e1 je skv\u011ble p\u0159izp\u016fsobena pro pou\u017eit\u00ed v cloudov\u00fdch hr\u00e1ch. WebRTC je projekt, kter\u00fd poskytuje webov\u00fdm prohl\u00ed\u017ee\u010d\u016fm a mobiln\u00edm aplikac\u00edm komunikaci v re\u00e1ln\u00e9m \u010dase prost\u0159ednictv\u00edm jednoduch\u00e9ho API. Zaji\u0161\u0165uje peer-to-peer spojen\u00ed optimalizovan\u00e9 pro m\u00e9dia a m\u00e1 vestav\u011bn\u00e9 standardn\u00ed kodeky, jako jsou VP8 a H264.<\/p>\n<p>D\u00e1val jsem p\u0159ednost zaji\u0161t\u011bn\u00ed maxim\u00e1ln\u00edho komfortu u\u017eivatel\u016f p\u0159ed zachov\u00e1n\u00edm vysok\u00e9 kvality grafiky. V algoritmu jsou povoleny ur\u010dit\u00e9 ztr\u00e1ty. V Google Stadia existuje dal\u0161\u00ed krok ke sn\u00ed\u017een\u00ed velikosti obr\u00e1zku na serveru, a sn\u00edmky jsou \u0161k\u00e1lov\u00e1ny do vy\u0161\u0161\u00ed kvality p\u0159ed p\u0159ed\u00e1n\u00edm peer-to-peer uzl\u016fm.<\/p>\n<p><b>3. Distribuovan\u00e1 infrastruktura s geografick\u00fdm sm\u011brov\u00e1n\u00edm<\/b><br \/>\nBez ohledu na to, jak je optimalizov\u00e1n kompresn\u00ed algoritmus a k\u00f3d, s\u00ed\u0165 z\u016fst\u00e1v\u00e1 rozhoduj\u00edc\u00edm faktorem, kter\u00fd nejv\u00edce p\u0159isp\u00edv\u00e1 k latenci. Architektura by m\u011bla m\u00edt mechanismus p\u0159ipojen\u00ed nejbli\u017e\u0161\u00edho serveru k u\u017eivateli pro sn\u00ed\u017een\u00ed doby p\u0159\u00edjmu a p\u0159enosu (RTT). Architektura by m\u011bla m\u00edt 1 koordin\u00e1tora a n\u011bkolik streamovac\u00edch server\u016f rozlo\u017een\u00fdch po cel\u00e9m sv\u011bt\u011b: Z\u00e1pad USA, V\u00fdchod USA, Evropa, Singapur, \u010c\u00edna. V\u0161echny streamovac\u00ed servery by m\u011bly b\u00fdt zcela izolov\u00e1ny. Syst\u00e9m m\u016f\u017ee regulovat sv\u00e9 rozd\u011blen\u00ed, kdy\u017e se server p\u0159ipojuje do s\u00edt\u011b nebo z n\u00ed vystupuje. T\u00edmto zp\u016fsobem, p\u0159i vysok\u00e9m provozu, p\u0159id\u00e1n\u00ed dal\u0161\u00edch server\u016f umo\u017e\u0148uje prov\u00e1d\u011bt horizont\u00e1ln\u00ed \u0161k\u00e1lov\u00e1n\u00ed.<\/p>\n<p><b>4. Kompatibilita prohl\u00ed\u017ee\u010de<\/b><br \/>\nCloud gaming shines best when it demands as little as possible from users. This means that it can be launched in a browser. Browsers help make the gaming experience as comfortable as possible for users, freeing them from the need to install software and hardware. Browsers also help ensure cross-platform compatibility for mobile and desktop versions. Fortunately, WebRTC is well-supported across various browsers.<\/p>\n<p><b>5. Jasn\u00e9 odd\u011blen\u00ed hern\u00edho rozhran\u00ed a slu\u017eby<\/b><br \/>\nPova\u017euji cloudovou hern\u00ed slu\u017ebu za platformu. Ka\u017ed\u00fd by m\u011bl m\u00edt mo\u017enost p\u0159ipojit k platform\u011b cokoliv. V sou\u010dasnosti jsem integroval <noindex><a rel=\"nofollow\" href=\"http:\/\/LibRetro\">LibRetro<\/a><\/noindex> s cloudovou hern\u00ed slu\u017ebou, proto\u017ee LibRetro nab\u00edz\u00ed kr\u00e1sn\u00e9 rozhran\u00ed hern\u00edho emul\u00e1toru pro retro hry, jako jsou SNES, GBA, PS.<\/p>\n<p><b>6. M\u00edstnosti pro multiplayer, crowd play a extern\u00ed propojen\u00ed (deep-link) se hrou<\/b><br \/>\nCloudRetro podporuje \u0159adu nov\u00fdch hern\u00edch styl\u016f, jako jsou CrowdPlay a Online MultiPlayer pro retro hry. Kdy\u017e n\u011bkolik u\u017eivatel\u016f otev\u0159e stejn\u00fd deep-link na r\u016fzn\u00fdch po\u010d\u00edta\u010d\u00edch, uvid\u00ed stejnou spu\u0161t\u011bnou hru a dokonce se k n\u00ed mohou p\u0159ipojit.<\/p>\n<p>Nav\u00edc se stavy hry ukl\u00e1daj\u00ed v cloudov\u00e9m \u00falo\u017ei\u0161ti. To umo\u017e\u0148uje u\u017eivatel\u016fm pokra\u010dovat ve h\u0159e kdykoliv na jak\u00e9mkoli jin\u00e9m za\u0159\u00edzen\u00ed.<\/p>\n<p><b>7. Horizont\u00e1ln\u00ed \u0161k\u00e1lovatelnost<\/b><br \/>\nStejn\u011b jako jak\u00fdkoli SAAS dnes, cloudov\u00e9 hry mus\u00ed b\u00fdt navr\u017eeny tak, aby byly horizont\u00e1ln\u011b \u0161k\u00e1lovateln\u00e9. Konstrukce \"koordina\u010dn\u00ed pracovn\u00edk\" umo\u017e\u0148uje p\u0159id\u00e1vat v\u00edce pracovn\u00edk\u016f, aby obsluhovali v\u011bt\u0161\u00ed provoz.<\/p>\n<p><b>8. \u017d\u00e1dn\u00e1 vazba na jedno cloudov\u00e9 prost\u0159ed\u00ed<\/b><br \/>\nInfrastruktura CloudRetro je um\u00edst\u011bna u r\u016fzn\u00fdch cloudov\u00fdch poskytovatel\u016f (Digital Ocean, Alibaba, u\u017eivatelsk\u00fd poskytovatel) pro r\u016fzn\u00e9 regiony. Aktivuji spu\u0161t\u011bn\u00ed v Docker kontejneru pro infrastrukturu a nastav\u00edm s\u00ed\u0165ov\u00e9 parametry pomoc\u00ed bash skriptu, aby se avoided z\u00e1vislost na jednom cloudov\u00e9m poskytovateli. Kombinac\u00ed toho s NAT Traversal v WebRTC m\u016f\u017eeme z\u00edskat flexibilitu pro nasazen\u00ed CloudRetro na jak\u00e9koli cloudov\u00e9 platform\u011b a dokonce na stroj\u00edch jak\u00e9hokoli u\u017eivatele.<\/p>\n<h3>Architektonick\u00fd design<\/h3>\n<p>\n<b>Pracovn\u00edk:<\/b> (nebo streamovac\u00ed server zm\u00edn\u011bn\u00fd v\u00fd\u0161e) n\u00e1sob\u00ed hry, spou\u0161t\u00ed k\u00f3dovac\u00ed pipeline a p\u0159en\u00e1\u0161\u00ed zak\u00f3dovan\u00e1 m\u00e9dia u\u017eivatel\u016fm. Instance pracovn\u00edka jsou rozprost\u0159eny po cel\u00e9m sv\u011bt\u011b a ka\u017ed\u00fd pracovn\u00edk m\u016f\u017ee zpracov\u00e1vat v\u00edce u\u017eivatelsk\u00fdch relac\u00ed z\u00e1rove\u0148.<\/p>\n<p><b>Koordin\u00e1tor:<\/b> se star\u00e1 o p\u0159i\u0159azen\u00ed nov\u00e9ho u\u017eivatele k nejvhodn\u011bj\u0161\u00edmu pracovn\u00edkovi pro streamov\u00e1n\u00ed. Koordin\u00e1tor komunikuje s pracovn\u00edky prost\u0159ednictv\u00edm WebSocket.<\/p>\n<p><b>\u00dalo\u017ei\u0161t\u011b hern\u00edch stav\u016f:<\/b> centr\u00e1ln\u00ed vzd\u00e1len\u00e9 \u00falo\u017ei\u0161t\u011b v\u0161ech hern\u00edch stav\u016f. Toto \u00falo\u017ei\u0161t\u011b poskytuje d\u016fle\u017eit\u00e9 funkce, jako je vzd\u00e1len\u00e9 ukl\u00e1d\u00e1n\u00ed\/nahr\u00e1v\u00e1n\u00ed.<\/p>\n<p><img decoding=\"async\" alt=\"Cloud gaming s otev\u0159en\u00fdm zdrojov\u00fdm k\u00f3dem na WebRTC: p2p, multiplayer, nulov\u00e1 latence\" src=\"\/wp-content\/uploads\/2020\/07\/985447b81350a640b0bd1344b5705113.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nVrchovat\u00e1 architektura CloudRetro<\/p>\n<h3>U\u017eivatelsk\u00fd sc\u00e9n\u00e1\u0159<\/h3>\n<p>\nKdy\u017e nov\u00fd u\u017eivatel otev\u0159e CloudRetro na kroc\u00edch 1 a 2 zobrazen\u00fdch n\u00ed\u017ee, koordin\u00e1tor spolu se seznamem dostupn\u00fdch pracovn\u00edk\u016f po\u017eaduje prvn\u00ed str\u00e1nku. Pot\u00e9 ve kroku 3 klient vypo\u010d\u00edt\u00e1 latence pro v\u0161echny kandid\u00e1ty pomoc\u00ed HTTP po\u017eadavku ping. Tento seznam latenc\u00ed je n\u00e1sledn\u011b odesl\u00e1n zp\u011bt koordin\u00e1torovi, aby mohl ur\u010dit nejvhodn\u011bj\u0161\u00edho pracovn\u00edka pro obsluhu u\u017eivatele. Ve kroku 4 n\u00ed\u017ee se vytv\u00e1\u0159\u00ed hra. Mezi u\u017eivatelem a p\u0159id\u011blen\u00fdm pracovn\u00edkem se vytv\u00e1\u0159\u00ed streamovac\u00ed spojen\u00ed WebRTC.<br \/>\n<img decoding=\"async\" alt=\"Cloud gaming s otev\u0159en\u00fdm zdrojov\u00fdm k\u00f3dem na WebRTC: p2p, multiplayer, nulov\u00e1 latence\" src=\"\/wp-content\/uploads\/2020\/07\/00199b5942e3e4314609ec0e70ea7162.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nU\u017eivatelsk\u00fd sc\u00e9n\u00e1\u0159 po z\u00edsk\u00e1n\u00ed p\u0159\u00edstupu<\/p>\n<h3>Co je uvnit\u0159 pracovn\u00edka<\/h3>\n<p>\nHern\u00ed a streamovac\u00ed pipeline jsou uvnit\u0159 pracovn\u00edka uchov\u00e1v\u00e1ny izolovan\u011b a vym\u011b\u0148uj\u00ed si tam informace prost\u0159ednictv\u00edm rozhran\u00ed. V sou\u010dasn\u00e9 dob\u011b je tato komunikace zaji\u0161t\u011bna prost\u0159ednictv\u00edm p\u0159enosu dat v pam\u011bti pomoc\u00ed <noindex><a rel=\"nofollow\" href=\"https:\/\/tour.golang.org\/concurrency\/2\">kan\u00e1l\u016f Golang<\/a><\/noindex> ve stejn\u00e9ho procesu. Dal\u0161\u00edm c\u00edlem je segregace, tj. nez\u00e1visl\u00e9 spu\u0161t\u011bn\u00ed hry v jin\u00e9m procesu.<\/p>\n<p><img decoding=\"async\" alt=\"Cloud gaming s otev\u0159en\u00fdm zdrojov\u00fdm k\u00f3dem na WebRTC: p2p, multiplayer, nulov\u00e1 latence\" src=\"\/wp-content\/uploads\/2020\/07\/7a90ec2638344467a34604cd4322165c.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nInterakce komponent pracovn\u00edka<\/p>\n<p>Hlavn\u00ed slo\u017eky:<\/p>\n<ul>\n<li><b>WebRTC:<\/b> klientsk\u00e1 komponenta, kter\u00e1 p\u0159ij\u00edm\u00e1 u\u017eivatelsk\u00fd vstup a v\u00fdstup zak\u00f3dovan\u00e9ho m\u00e9dia ze serveru.\n<\/li>\n<li><b>Hern\u00ed emul\u00e1tor:<\/b> hern\u00fd komponent. D\u00edky knihovn\u011b Libretro je syst\u00e9m schopen spustit hru uvnit\u0159 t\u00e9ho\u017e procesu a intern\u011b zachytit m\u00e9dia a tok vstupu.\n<\/li>\n<li>In-game sn\u00edmky jsou zachyceny a odesl\u00e1ny do enkod\u00e9ru.\n<\/li>\n<li><b>Obr\u00e1zkov\u00fd\/audio enkod\u00e9r:<\/b> k\u00f3dovac\u00ed pipeline, kter\u00e1 p\u0159ij\u00edm\u00e1 medi\u00e1ln\u00ed sn\u00edmky, zak\u00f3duje je na pozad\u00ed a v\u00fdstupy zak\u00f3dovan\u00e9 obr\u00e1zky\/audio.\n<\/li>\n<\/ul>\n<p><\/p>\n<h2>Implementace<\/h2>\n<p>\nCloudRetro se spol\u00e9h\u00e1 na WebRTC jako na kl\u00ed\u010dovou technologii, a proto jsem se p\u0159ed t\u00edm, ne\u017e se pono\u0159\u00edm do podrobnost\u00ed implementace v Golangu, rozhodl nejprve p\u0159ibl\u00ed\u017eit samotn\u00fd WebRTC. To je ohromuj\u00edc\u00ed technologie, kter\u00e1 mi v\u00fdrazn\u011b pomohla dos\u00e1hnout latence streamov\u00e1n\u00ed dat jen na zlomek sekundy.<\/p>\n<h3>WebRTC<\/h3>\n<p>\nWebRTC je navr\u017een tak, aby poskytoval vysoce kvalitn\u00ed peer-to-peer spojen\u00ed v nativn\u00edch mobiln\u00edch aplikac\u00edch a v prohl\u00ed\u017ee\u010d\u00edch pomoc\u00ed jednoduch\u00fdch API.<\/p>\n<h4>NAT Traversal <\/h4>\n<p>\nWebRTC je zn\u00e1m\u00fd svou funkcionalitou NAT Traversal. WebRTC je ur\u010den pro peer-to-peer komunikaci. Jeho c\u00edlem je naj\u00edt nejvhodn\u011bj\u0161\u00ed p\u0159\u00edmou trasu, aby se vyhnulo NAT br\u00e1n\u00e1m a firewall\u016fm pro peer-to-peer spojen\u00ed prost\u0159ednictv\u00edm procesu zvan\u00e9ho <noindex><a rel=\"nofollow\" href=\"https:\/\/webrtchacks.com\/trickle-ice\/\">ICE<\/a><\/noindex>. V r\u00e1mci tohoto procesu API WebRTC zjist\u00ed va\u0161i ve\u0159ejnou IP adresu pomoc\u00ed STUN server\u016f a p\u0159esm\u011bruj\u00ed ji na server p\u0159enosu (<noindex><a rel=\"nofollow\" href=\"https:\/\/webrtchacks.com\/?s=turn\">TURN<\/a><\/noindex>), kdy\u017e nem\u016f\u017ee b\u00fdt nav\u00e1z\u00e1no p\u0159\u00edm\u00e9 spojen\u00ed.<\/p>\n<p>Nicm\u00e9n\u011b CloudRetro tuto mo\u017enost nevyu\u017e\u00edv\u00e1 zcela. Jeho peer-to-peer spojen\u00ed neexistuj\u00ed mezi u\u017eivateli, ale mezi u\u017eivateli a cloudov\u00fdmi servery. Serverov\u00e1 \u010d\u00e1st modelu m\u00e1 m\u00e9n\u011b omezen\u00ed na p\u0159\u00edmou komunikaci ne\u017e b\u011b\u017en\u00e9 u\u017eivatelsk\u00e9 za\u0159\u00edzen\u00ed. To umo\u017e\u0148uje p\u0159edb\u011b\u017en\u011b otev\u0159\u00edt p\u0159\u00edchoz\u00ed porty nebo pou\u017e\u00edvat ve\u0159ejn\u00e9 IP adresy p\u0159\u00edmo, proto\u017ee server nen\u00ed za NAT.<\/p>\n<p>D\u0159\u00edve jsem cht\u011bl prom\u011bnit projekt na platformu pro \u0161\u00ed\u0159en\u00ed her pro Cloud Gaming. My\u0161lenka byla umo\u017enit tv\u016frc\u016fm her poskytovat hry a streamov\u00e9 zdroje. U\u017eivatel\u00e9 by pak interagovali p\u0159\u00edmo s poskytovateli. V t\u00e9to decentralizovan\u00e9 form\u011b je CloudRetro jen prost\u0159ed\u00edm pro p\u0159ipojen\u00ed extern\u00edch streamov\u00fdch zdroj\u016f k u\u017eivatel\u016fm, co\u017e z n\u011bj \u010din\u00ed \u0161k\u00e1lovateln\u011bj\u0161\u00ed, kdy\u017e na n\u011bm u\u017e nen\u00ed hostov\u00e1n\u00ed. Role WebRTC NAT Traversal je zde velmi d\u016fle\u017eit\u00e1 pro usnadn\u011bn\u00ed iniciace peer-to-peer spojen\u00ed na extern\u00edch streamov\u00fdch zdroj\u00edch, co\u017e zjednodu\u0161uje p\u0159ipojen\u00ed tv\u016frce k s\u00edti.<\/p>\n<h4>Kompresi videa<\/h4>\n<p>\nKompresia videa je nezbytnou sou\u010d\u00e1st\u00ed pipeliningu, kter\u00e1 v\u00fdrazn\u011b p\u0159isp\u00edv\u00e1 k plynulosti toku. I kdy\u017e nen\u00ed nutn\u00e9 zn\u00e1t v\u0161echny detaily k\u00f3dov\u00e1n\u00ed videa ve form\u00e1tu VP8\/H264, pochopen\u00ed konceptu pom\u00e1h\u00e1 porozum\u011bt parametr\u016fm rychlosti streamovan\u00e9ho videa, ladit neo\u010dek\u00e1van\u00e9 chov\u00e1n\u00ed a nastavovat zpo\u017ed\u011bn\u00ed.<\/p>\n<p>Kompresia videa pro streamovac\u00ed slu\u017ebu je slo\u017eit\u00fd \u00fakol, proto\u017ee algoritmus mus\u00ed zajistit, \u017ee celkov\u00fd \u010das k\u00f3dov\u00e1n\u00ed + \u010das p\u0159enosu po s\u00edti + \u010das dek\u00f3dov\u00e1n\u00ed je co nejmen\u0161\u00ed. Krom\u011b toho mus\u00ed b\u00fdt proces k\u00f3dov\u00e1n\u00ed konzistentn\u00ed a nep\u0159etr\u017eit\u00fd. N\u011bkter\u00e9 vz\u00e1jemn\u00e9 \u00fastupky p\u0159i k\u00f3dov\u00e1n\u00ed nejsou pou\u017eiteln\u00e9 \u2013 nap\u0159\u00edklad nem\u016f\u017eeme up\u0159ednostnit del\u0161\u00ed \u010das k\u00f3dov\u00e1n\u00ed p\u0159ed men\u0161\u00ed velikost\u00ed souboru a \u010dasem dek\u00f3dov\u00e1n\u00ed, nebo pou\u017e\u00edt nekonzistentn\u00ed kompresi.<\/p>\n<p>My\u0161lenka komprese videa spo\u010d\u00edv\u00e1 v tom, \u017ee se vylou\u010d\u00ed zbyte\u010dn\u00e9 bity informac\u00ed, p\u0159i\u010dem\u017e se zachov\u00e1v\u00e1 p\u0159ijateln\u00e1 \u00farove\u0148 p\u0159esnosti pro u\u017eivatele. Krom\u011b k\u00f3dov\u00e1n\u00ed jednotliv\u00fdch statick\u00fdch sn\u00edmk\u016f algoritmus odvozuje aktu\u00e1ln\u00ed sn\u00edmek z p\u0159edchoz\u00edho a n\u00e1sleduj\u00edc\u00edho, tak\u017ee se p\u0159en\u00e1\u0161\u00ed pouze jejich rozd\u00edl. Jak je vid\u011bt na p\u0159\u00edkladu s Pacmanem, p\u0159en\u00e1\u0161ej\u00ed se pouze diferenci\u00e1ln\u00ed body.<\/p>\n<p><img decoding=\"async\" alt=\"Cloud gaming s otev\u0159en\u00fdm zdrojov\u00fdm k\u00f3dem na WebRTC: p2p, multiplayer, nulov\u00e1 latence\" src=\"\/wp-content\/uploads\/2020\/07\/e452c54c53ab7797b610620aefbba8d2.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nSrovn\u00e1n\u00ed videokadru na p\u0159\u00edkladu Pacmana<\/p>\n<h4>Kompresia audia<\/h4>\n<p>\nPodobn\u011b jako u videa, algoritmus komprese zvuku vynech\u00e1v\u00e1 data, kter\u00e1 nemohou b\u00fdt vn\u00edm\u00e1na \u010dlov\u011bkem. Opus je v sou\u010dasnosti audio kodek s nejlep\u0161\u00edmi v\u00fdkony. Byl navr\u017een pro p\u0159enos zvukov\u00e9 vlny prost\u0159ednictv\u00edm protokolu uspo\u0159\u00e1dan\u00fdch datagram\u016f, jako je RTP (Real-Time Transport Protocol \u2013 protokol pro p\u0159enos v re\u00e1ln\u00e9m \u010dase). Jeho zpo\u017ed\u011bn\u00ed je men\u0161\u00ed ne\u017e u mp3 a aac, a kvalita je vy\u0161\u0161\u00ed. Zpo\u017ed\u011bn\u00ed obvykle \u010din\u00ed kolem 5~66,5 ms.<\/p>\n<h4>Pion, WebRTC v Golangu<\/h4>\n<p>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/pion\/webrtc\">Pion<\/a><\/noindex> je projekt s otev\u0159en\u00fdm zdrojov\u00fdm k\u00f3dem, kter\u00fd p\u0159en\u00e1\u0161\u00ed WebRTC na Golang. M\u00edsto obvykl\u00e9ho wrapperu nativn\u00edch C++ knihoven WebRTC je Pion nativn\u00ed implementac\u00ed WebRTC v Golangu s nejlep\u0161\u00edmi v\u00fdkony, integrac\u00ed s Go a tak\u00e9 spr\u00e1vou verz\u00ed protokol\u016f WebRTC.<\/p>\n<p>Knihovna tak\u00e9 poskytuje streamov\u00e1n\u00ed dat s mnoha skv\u011bl\u00fdmi vestav\u011bn\u00fdmi moduly s latenc\u00ed m\u00e9n\u011b ne\u017e jednu sekundu. M\u00e1 vlastn\u00ed implementaci STUN, DTLS, SCTP atd. a n\u011bkter\u00e9 experimenty s QUIC a WebAssembly. Tato open-source knihovna je sama o sob\u011b opravdu dobr\u00fdm zdrojem pro u\u010den\u00ed s vynikaj\u00edc\u00ed dokumentac\u00ed, implementac\u00ed s\u00ed\u0165ov\u00fdch protokol\u016f a skv\u011bl\u00fdmi p\u0159\u00edklady.<\/p>\n<p>Komunita Pion, veden\u00e1 velmi v\u00e1\u0161niv\u00fdm tv\u016frcem, je pom\u011brn\u011b \u017eiv\u00e1, prob\u00edh\u00e1 zde mnoho kvalitn\u00edch diskus\u00ed o WebRTC. Pokud v\u00e1s tato technologie zaj\u00edm\u00e1, p\u0159ipojte se k <noindex><a rel=\"nofollow\" href=\"http:\/\/pion.ly\/slack\">http:\/\/pion.ly\/slack<\/a><\/noindex> \u2013 nau\u010d\u00edte se mnoho nov\u00e9ho.<\/p>\n<h3>Ps\u00e1n\u00ed CloudRetro v Golangu<\/h3>\n<p>\n<img decoding=\"async\" alt=\"Cloud gaming s otev\u0159en\u00fdm zdrojov\u00fdm k\u00f3dem na WebRTC: p2p, multiplayer, nulov\u00e1 latence\" src=\"\/wp-content\/uploads\/2020\/07\/f85f7b8ea579fab964d870aad698c7e7.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nImplementace pracovn\u00edka v Go<\/p>\n<h4>Kan\u00e1ly Go v akci<\/h4>\n<p>\nD\u00edky kr\u00e1sn\u00e9mu designu kan\u00e1l\u016f Go se probl\u00e9my se streamov\u00e1n\u00edm ud\u00e1lost\u00ed a paralelismem v\u00fdrazn\u011b zjednodu\u0161uj\u00ed. Jak ukazuje diagram, v r\u016fzn\u00fdch GoRoutine b\u011b\u017e\u00ed paraleln\u011b n\u011bkolik komponent. Ka\u017ed\u00e1 komponenta spravuje sv\u016fj stav a komunikuje prost\u0159ednictv\u00edm kan\u00e1l\u016f. V\u00fdb\u011brov\u00e9 tvrzen\u00ed Golang nut\u00ed zpracov\u00e1vat jedno atomov\u00e9 ud\u00e1lost v ka\u017ed\u00e9m hern\u00edm taktu. To znamen\u00e1, \u017ee pro takov\u00fd design nen\u00ed pot\u0159eba z\u00e1mek. Nap\u0159\u00edklad, kdy\u017e u\u017eivatel ukl\u00e1d\u00e1, je zapot\u0159eb\u00ed kompletn\u00ed sn\u00edmek stavu hry. Tento stav mus\u00ed z\u016fstat kontinu\u00e1ln\u00ed, vykon\u00e1vaj\u00edc\u00ed vstup, dokud nen\u00ed ulo\u017een\u00ed dokon\u010deno. B\u011bhem ka\u017ed\u00e9ho hern\u00edho taktu m\u016f\u017ee backend zpracov\u00e1vat pouze operaci ukl\u00e1d\u00e1n\u00ed nebo vstupu, co\u017e \u010din\u00ed proces thread-safe.<\/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>\nTento Golang vzor je skv\u011ble vhodn\u00fd pro m\u00e9 sc\u00e9n\u00e1\u0159e pou\u017eit\u00ed CrowdPlay a Multiple Player. N\u00e1sledov\u00e1n\u00edm tohoto vzoru se v\u0161echny u\u017eivatelsk\u00e9 vstupy v jedn\u00e9 m\u00edstnosti skl\u00e1daj\u00ed do centr\u00e1ln\u00edho vstupn\u00edho kan\u00e1lu. Hern\u00ed m\u00e9dia se pot\u00e9 rozes\u00edlaj\u00ed v\u0161em u\u017eivatel\u016fm v jedn\u00e9 m\u00edstnosti. Takto dosahujeme rozd\u011blen\u00ed stavu hry mezi n\u011bkolika hern\u00edmi sezen\u00edmi r\u016fzn\u00fdch u\u017eivatel\u016f.<\/p>\n<p><img decoding=\"async\" alt=\"Cloud gaming s otev\u0159en\u00fdm zdrojov\u00fdm k\u00f3dem na WebRTC: p2p, multiplayer, nulov\u00e1 latence\" src=\"\/wp-content\/uploads\/2020\/07\/000a495d7f214246a8a396aab11a3ac5.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nSynchronizace mezi r\u016fzn\u00fdmi sezen\u00edmi<\/p>\n<h4>Nev\u00fdhody Golangu<\/h4>\n<p>\nGolang nen\u00ed dokonal\u00fd. Kan\u00e1l je pomal\u00fd. Ve srovn\u00e1n\u00ed s blokov\u00e1n\u00edm kan\u00e1l Go p\u0159edstavuje jednodu\u0161\u0161\u00ed metodu zpracov\u00e1n\u00ed paraleln\u00edch a streamovan\u00fdch ud\u00e1lost\u00ed, ale kan\u00e1l neposkytuje nejlep\u0161\u00ed v\u00fdkon. Pod kan\u00e1lem se skr\u00fdv\u00e1 slo\u017eit\u00e1 logika blokov\u00e1n\u00ed. Proto jsem provedl n\u011bkter\u00e9 \u00fapravy v implementaci, znovu pou\u017eil blokace a atomick\u00e9 hodnoty p\u0159i n\u00e1hrad\u011b kan\u00e1l\u016f pro optimalizaci v\u00fdkonu.<\/p>\n<p>Krom\u011b toho je garbage collector v Golangu ne\u0159\u00edzen\u00fd, co\u017e ob\u010das zp\u016fsobuje podez\u0159ele dlouh\u00e9 pauzy. To v\u00fdrazn\u011b br\u00e1n\u00ed v\u00fdkonu streamovac\u00ed aplikace v re\u00e1ln\u00e9m \u010dase.<\/p>\n<h4>CGO<\/h4>\n<p>\nV projektu je pou\u017eita existuj\u00edc\u00ed open source knihovna VP8\/H264 golangu pro kompresi m\u00e9di\u00ed a Libretro pro hern\u00ed emul\u00e1tory. V\u0161echny tyto knihovny jsou jen ob\u00e1lky C knihovny v Go s vyu\u017eit\u00edm <noindex><a rel=\"nofollow\" href=\"https:\/\/golang.org\/cmd\/cgo\/\">CGO<\/a><\/noindex>. N\u011bkter\u00e9 z nedostatk\u016f jsou uvedeny v <noindex><a rel=\"nofollow\" href=\"https:\/\/dave.cheney.net\/2019\/10\/06\/use-internal-packages-to-reduce-your-public-api-surface\">tomto p\u0159\u00edsp\u011bvku Davea Cheneya<\/a><\/noindex>. Probl\u00e9my, se kter\u00fdmi jsem se setkal:<\/p>\n<ul>\n<li>nemo\u017enost zachytit p\u00e1d v CGO, i s pomoc\u00ed Golang RecoveryCrash;<\/li>\n<li>nemo\u017enost ur\u010dit \u00fazk\u00e9 m\u00edsto v v\u00fdkonu, kdy\u017e nem\u016f\u017eeme odhalit detailn\u00ed probl\u00e9my v CGO.<\/li>\n<\/ul>\n<p><\/p>\n<h2>Z\u00e1v\u011br<\/h2>\n<p>\nDos\u00e1hl jsem sv\u00e9ho c\u00edle \u2013 porozum\u011bl jsem cloudov\u00fdm hern\u00edm slu\u017eb\u00e1m a vytvo\u0159il platformu, kter\u00e1 pom\u00e1h\u00e1 hr\u00e1t nostalgick\u00e9 retro hry online s m\u00fdmi p\u0159\u00e1teli. Vytvo\u0159en\u00ed tohoto projektu by nebylo mo\u017en\u00e9 bez knihovny Pion a podpory komunity Pion. Jsem velmi vd\u011b\u010dn\u00fd za jej\u00ed intenzivn\u00ed rozvoj. Jednoduch\u00e1 API poskytnut\u00e1 WebRTC a Pion zajistila plynulou integraci. M\u016fj prvn\u00ed d\u016fkaz konceptu byl vyd\u00e1n ve stejn\u00e9 t\u00fddny, p\u0159esto\u017ee jsem p\u0159edem nev\u011bd\u011bl o peer-to-peer (P2P) p\u0159ipojen\u00ed.<\/p>\n<p>Navzdory snadnosti integrace je P2P streamov\u00e1n\u00ed opravdu velmi komplexn\u00ed oblast v po\u010d\u00edta\u010dov\u00e9 v\u011bd\u011b. Mus\u00ed se vypo\u0159\u00e1dat se slo\u017eitost\u00ed mnohalet\u00fdch s\u00ed\u0165ov\u00fdch architektur, jako je IP a NAT, aby vytvo\u0159ilo peer-to-peer relaci. B\u011bhem pr\u00e1ce na tomto projektu jsem z\u00edskal mnoho cenn\u00fdch znalost\u00ed o s\u00edt\u00edch a optimalizaci v\u00fdkonu, a proto doporu\u010duji v\u0161em, aby se pokusili vytvo\u0159it P2P produkty pomoc\u00ed WebRTC.<\/p>\n<p>CloudRetro spl\u0148uje v\u0161echny sc\u00e9n\u00e1\u0159e pou\u017eit\u00ed, kter\u00e9 jsem o\u010dek\u00e1val, jako\u017eto retro hr\u00e1\u010d. Nicm\u00e9n\u011b si mysl\u00edm, \u017ee existuje mnoho oblast\u00ed v projektu, kter\u00e9 mohu zlep\u0161it, nap\u0159\u00edklad u\u010dinit s\u00ed\u0165 spolehliv\u011bj\u0161\u00ed a v\u00fdkonn\u011bj\u0161\u00ed, zajistit vy\u0161\u0161\u00ed kvalitu grafiky her nebo mo\u017enost sd\u00edlen\u00ed her mezi u\u017eivateli. Usilovn\u011b na tom pracuji. Pros\u00edm, sledujte <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/giongto35\/cloud-game\">projektu<\/a><\/noindex> a podpo\u0159te ho, pokud se v\u00e1m l\u00edb\u00ed.<\/li>\n<\/ul>\n<p>Zdroj: <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\/cs\/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=\"cs_CZ\" \/>\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\/cs\/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\udd47Cloudov\u00e9 hran\u00ed s otev\u0159en\u00fdm zdrojov\u00fdm k\u00f3dem na WebRTC: p2p, multiplayer, nulov\u00e1 latence | ProHoster","description":"","canonical_url":"https:\/\/prohoster.info\/cs\/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":"cs_CZ","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\/cs\/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\/cs\/wp-json\/wp\/v2\/posts\/89303","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/comments?post=89303"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/posts\/89303\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/media\/89304"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/media?parent=89303"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/categories?post=89303"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/tags?post=89303"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}