{"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\/pl\/blog\/administrirovanie\/oblachnyj-gejming-s-otkrytym-ishodnym-kodom-na-webrtc-p2p-multipleer-zero-latency","title":{"rendered":"Chmurowe granie z otwartym kodem \u017ar\u00f3d\u0142owym na WebRTC: p2p, multiplayer, zerowe op\u00f3\u017anienie","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=\"Chmurowe granie z otwartym kodem \u017ar\u00f3d\u0142owym na WebRTC: p2p, multiplayer, zerowe op\u00f3\u017anienie\" src=\"\/wp-content\/uploads\/2020\/07\/22dbf7665d7fded15671d98a2afe599b.png\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><br \/>\nUs\u0142uga jako oprogramowanie, infrastruktura jako us\u0142uga, platforma jako us\u0142uga, us\u0142uga komunikacyjna jako us\u0142uga, wideokonferencje jako us\u0142uga, a co z grami w chmurze jako us\u0142uga? Ju\u017c podj\u0119to kilka pr\u00f3b stworzenia gier w chmurze (Cloud Gaming), na przyk\u0142ad Stadia, niedawno uruchomiona przez firm\u0119 Google. Stadia <noindex><a rel=\"nofollow\" href=\"https:\/\/youtu.be\/avtlQeaxd_I?t=440\">nie jest nowicjuszem w WebRTC<\/a><\/noindex>, ale czy inni mog\u0105 korzysta\u0107 z WebRTC w ten sam spos\u00f3b?<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>Thanh Nguyen postanowi\u0142 sprawdzi\u0107 t\u0119 mo\u017cliwo\u015b\u0107 w swoim otwartym projekcie CloudRetro. CloudRetro oparty jest na Pion, <noindex><a rel=\"nofollow\" href=\"https:\/\/webrtchacks.com\/webrtc-open-source-most-popular\/\">popularnej<\/a><\/noindex> bibliotece WebRTC napisanej w Go (dzi\u0119ki <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/Sean-Der\">Shonowi<\/a><\/noindex> z zespo\u0142u deweloper\u00f3w Pion za pomoc w przygotowaniu tego artyku\u0142u). W artykule Thanh dokonuje przegl\u0105du architektury swojego projektu oraz opowiada, jakie u\u017cyteczne informacje uzyska\u0142 i z jakimi wyzwaniami si\u0119 zmierzy\u0142 podczas pracy.<\/p>\n<h2>Wprowadzenie<\/h2>\n<p>\nW zesz\u0142ym roku, gdy Google zapowiedzia\u0142o Stadia, by\u0142em kompletnie zaskoczony. Pomys\u0142 jest tak wyj\u0105tkowy i innowacyjny, \u017ce ci\u0105gle zadawa\u0142em sobie pytanie, jak to w og\u00f3le mo\u017cliwe przy istniej\u0105cych technologiach. Ch\u0119\u0107 lepszego zrozumienia tego tematu sk\u0142oni\u0142a mnie do stworzenia w\u0142asnej wersji otwartej gry w chmurze. Efekt by\u0142 po prostu fantastyczny. Poni\u017cej chcia\u0142bym podzieli\u0107 si\u0119 procesem pracy nad moim rocznym <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/giongto35\/cloud-game\">projektem<\/a><\/noindex>.<\/p>\n<p><i>TLDR: kr\u00f3tka wersja slajdowa z najwa\u017cniejszymi punktami<\/i><\/p>\n<h3>Dlaczego przysz\u0142o\u015b\u0107 le\u017cy w grach w chmurze<\/h3>\n<p>\nWierz\u0119, \u017ce Cloud Gaming wkr\u00f3tce stanie si\u0119 nowym pokoleniem nie tylko gier, ale i innych dziedzin informatyki. Gry w chmurze to szczyt modelu klient\/serwer. Taki model maksymalizuje kontrol\u0119 nad backendem i minimalizuje prac\u0119 frontendow\u0105 poprzez umieszczenie logiki gry na zdalnym serwerze i strumieniowe przesy\u0142anie obrazu\/d\u017awi\u0119ku do klienta. Serwer wykonuje ci\u0119\u017ckie obliczenia, wi\u0119c klient nie jest ju\u017c zale\u017cny od ogranicze\u0144 sprz\u0119towych.<\/p>\n<p>Google Stadia w zasadzie pozwala gra\u0107 w <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)\">gry AAA<\/a><\/noindex> (tzn. wysokiej jako\u015bci gry blokbusterowe) w interfejsie podobnym do YouTube. Ta sama metodologia mo\u017ce by\u0107 zastosowana do innych wymagaj\u0105cych aplikacji offline, takich jak system operacyjny czy projektowanie graficzne 2D\/3D, aby m\u00f3c stabilnie uruchamia\u0107 je na urz\u0105dzeniach o niskich parametrach technicznych na r\u00f3\u017cnych platformach.<\/p>\n<p><img decoding=\"async\" alt=\"Chmurowe granie z otwartym kodem \u017ar\u00f3d\u0142owym na WebRTC: p2p, multiplayer, zerowe op\u00f3\u017anienie\" src=\"\/wp-content\/uploads\/2020\/07\/d6ca3e47db5c8e3d9880b304cc3be33b.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nPrzysz\u0142o\u015b\u0107 tej technologii: wyobra\u017cacie sobie, gdyby Microsoft Windows 10 dzia\u0142a\u0142 w przegl\u0105darce Chrome?<\/p>\n<h3>Gry w chmurze s\u0105 technicznie z\u0142o\u017cone<\/h3>\n<p>\nGaming is one of the few areas where a constant fast user reaction is required. If we occasionally experience a two-second delay when clicking on a page, that is acceptable. Live video streams generally lag a few seconds but still offer sufficient usability. However, if a game frequently lags by 500 ms, playing becomes nearly impossible. Our goal is to achieve extremely low latency so that the gap between input and media is as small as possible. Therefore, the traditional approach to streaming video is not applicable here.<\/p>\n<p><img decoding=\"async\" alt=\"Chmurowe granie z otwartym kodem \u017ar\u00f3d\u0142owym na WebRTC: p2p, multiplayer, zerowe op\u00f3\u017anienie\" src=\"\/wp-content\/uploads\/2020\/07\/d73765a3c9277c026f407883e1091473.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nOg\u00f3lny szablon gier w chmurze<\/p>\n<h2>Projekt open source CloudRetro<\/h2>\n<p>\nPostanowi\u0142em stworzy\u0107 testowy prototyp gry w chmurze, aby sprawdzi\u0107, czy jest to mo\u017cliwe przy tak rygorystycznych ograniczeniach sieciowych. Do poweryfikacji koncepcji wybra\u0142em Golang, poniewa\u017c jest to najbardziej znany mi j\u0119zyk i dobrze pasuje do realizacji z wielu innych powod\u00f3w, co p\u00f3\u017aniej si\u0119 okaza\u0142o. Go jest prosty i szybko si\u0119 rozwija; kana\u0142y w Go doskonale nadaj\u0105 si\u0119 do zarz\u0105dzania wielow\u0105tkowo\u015bci\u0105.<\/p>\n<p>Projekt <noindex><a rel=\"nofollow\" href=\"http:\/\/cloudretro.io\/\">CloudRetro.io<\/a><\/noindex> \u2013 chmurowa us\u0142uga gier z otwartym kodem \u017ar\u00f3d\u0142owym dla gier retro. Celem projektu jest przynie\u015b\u0107 do tradycyjnych gier retro najbardziej komfortowe do\u015bwiadczenia w grze i doda\u0107 tryb wieloosobowy.<br \/>\nSzczeg\u00f3\u0142y projektu mo\u017cna znale\u017a\u0107 tutaj: <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/giongto35\/cloud-game\">https:\/\/github.com\/giongto35\/cloud-game<\/a><\/noindex>.<\/p>\n<h3>Funkcjonalno\u015b\u0107 CloudRetro<\/h3>\n<p>\nAby zademonstrowa\u0107 ca\u0142\u0105 moc gier w chmurze, CloudRetro wykorzystuje gry retro. Co pozwala na uzyskanie wielu unikalnych wra\u017ce\u0144 z gry.<\/p>\n<ul>\n<li>Przeno\u015bno\u015b\u0107 gry\n<ul>\n<li>Natychmiastowe odtwarzanie po otwarciu strony; pobieranie i instalacja nie s\u0105 potrzebne<\/li>\n<li>Dzia\u0142a w mobilnej przegl\u0105darce, wi\u0119c do uruchomienia nie jest potrzebne \u017cadne oprogramowanie<\/li>\n<\/ul>\n<p>\n<\/li>\n<li>Sesje gier mo\u017cna wsp\u00f3\u0142dzieli\u0107 na wielu urz\u0105dzeniach i przechowywa\u0107 w chmurze na nast\u0119pne logowanie<\/li>\n<li>Gr\u0119 mo\u017cna streamowa\u0107, a kilka u\u017cytkownik\u00f3w mo\u017ce w ni\u0105 gra\u0107 jednocze\u015bnie:\n<ul>\n<li>Crowdplay stylu TwitchPlayPokemon, tylko bardziej mi\u0119dzyplatformowy i bardziej w czasie rzeczywistym<\/li>\n<li>Offline gry online. Wiele os\u00f3b mo\u017ce gra\u0107 bez konfiguracji sieci. W Samurai Shodown teraz mo\u017cna gra\u0107 2 graczy przez sie\u0107 CloudRetro<\/li>\n<\/ul>\n<p>\n<img decoding=\"async\" alt=\"Chmurowe granie z otwartym kodem \u017ar\u00f3d\u0142owym na WebRTC: p2p, multiplayer, zerowe op\u00f3\u017anienie\" src=\"\/wp-content\/uploads\/2020\/07\/bdc715971755d669a026f830ce888520.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nDemo wieloosobowej gry online na r\u00f3\u017cnych urz\u0105dzeniach<\/p>\n<h2>Infrastruktura<\/h2>\n<p><\/p>\n<h3>Wymagania i stos technologii<\/h3>\n<p>\nPoni\u017cej znajduje si\u0119 lista wymaga\u0144, kt\u00f3re ustanowi\u0142em przed rozpocz\u0119ciem projektu.<\/p>\n<p><b>1. Jeden gracz<\/b><br \/>\nTo wymaganie mo\u017ce wydawa\u0107 si\u0119 ma\u0142o istotne i oczywiste, ale to jeden z moich kluczowych wniosk\u00f3w \u2013 pozwala to grom gromkim grom nad\u0105\u017ca\u0107 z daleka od tradycyjnych us\u0142ug strumieniowych. Je\u015bli skupimy si\u0119 na grze dla jednego gracza, mo\u017cemy pozby\u0107 si\u0119 scentralizowanego serwera lub CDN, poniewa\u017c nie potrzebujemy przesy\u0142a\u0107 strumieni do mas. Zamiast przesy\u0142a\u0107 strumienie na ch\u0142onny serwer lub przekazywa\u0107 pakiety na scentralizowany serwer WebSocket, strumienie us\u0142ugi s\u0105 przesy\u0142ane bezpo\u015brednio do u\u017cytkownika przez po\u0142\u0105czenie peer-to-peer WebRTC.<\/p>\n<p><b>2. Strumie\u0144 medi\u00f3w o niskim op\u00f3\u017anieniu<\/b><br \/>\nCzytaj\u0105c o Stadia, cz\u0119sto napotykam w niekt\u00f3rych artyku\u0142ach wzmianki o WebRTC. Zrozumia\u0142em, \u017ce WebRTC to wybitna technologia i doskonale nadaje si\u0119 do wykorzystania w grach w chmurze. WebRTC to projekt, kt\u00f3ry zapewnia przegl\u0105darkom internetowym i aplikacjom mobilnym komunikacj\u0119 w czasie rzeczywistym przez prosty interfejs API. Oferuje po\u0142\u0105czenie peer-to-peer, zoptymalizowane dla medi\u00f3w, i ma wbudowane standardowe kodeki, takie jak VP8 i H264.<\/p>\n<p>Skupi\u0142em si\u0119 na zapewnieniu jak najbardziej komfortowej pracy dla u\u017cytkownik\u00f3w, a nie na zachowaniu wysokiej jako\u015bci grafiki. W algorytmie dopuszczalne s\u0105 pewne straty. W Google Stadia jest dodatkowy krok zmniejszaj\u0105cy rozmiar obrazu na serwerze, a klatki s\u0105 skalowane do wy\u017cszej jako\u015bci przed przekazaniem peer-to-peer.<\/p>\n<p><b>3. Rozproszona infrastruktura z geograficznym routowaniem<\/b><br \/>\nBez wzgl\u0119du na to, jak bardzo zoptymalizowany jest algorytm kompresji i kod, sie\u0107 nadal stanowi kluczowy czynnik wp\u0142ywaj\u0105cy na op\u00f3\u017anienie. Architektura powinna mie\u0107 mechanizm sparowania najbli\u017cszego serwera do u\u017cytkownika w celu skr\u00f3cenia czasu odbioru (RTT). Architektura powinna mie\u0107 jednego koordynatora i kilka serwer\u00f3w strumieniowych rozmieszczonych na ca\u0142ym \u015bwiecie: Zachodnia USA, Wschodnia USA, Europa, Singapur, Chiny. Wszystkie serwery strumieniowe powinny by\u0107 ca\u0142kowicie izolowane. System mo\u017ce dostosowywa\u0107 swoje rozmieszczenie, gdy serwer do\u0142\u0105cza do sieci lub z niej wychodzi. W ten spos\u00f3b, w przypadku du\u017cego ruchu, dodanie dodatkowych serwer\u00f3w umo\u017cliwia poziome skalowanie.<\/p>\n<p><b>4. Kompatybilno\u015b\u0107 przegl\u0105darki<\/b><br \/>\nGry w chmurze pokazuj\u0105 si\u0119 w najlepszym \u015bwietle, gdy wymagaj\u0105 od u\u017cytkownik\u00f3w jak najmniej. Oznacza to, \u017ce istnieje mo\u017cliwo\u015b\u0107 uruchamiania ich w przegl\u0105darce. Przegl\u0105darki pomagaj\u0105 uczyni\u0107 rozgrywk\u0119 jak najbardziej komfortow\u0105 dla u\u017cytkownik\u00f3w, eliminuj\u0105c potrzeb\u0119 instalacji oprogramowania i sprz\u0119tu. Przegl\u0105darki r\u00f3wnie\u017c zapewniaj\u0105 mo\u017cliwo\u015b\u0107 grania na r\u00f3\u017cnych platformach, zar\u00f3wno mobilnych, jak i desktopowych. Na szcz\u0119\u015bcie WebRTC jest doskonale wspierane w r\u00f3\u017cnych przegl\u0105darkach.<\/p>\n<p><b>5. Wyra\u017any podzia\u0142 interfejsu gry i us\u0142ugi<\/b><br \/>\nPostrzegam us\u0142ug\u0119 gier w chmurze jako platform\u0119. Ka\u017cdy powinien mie\u0107 mo\u017cliwo\u015b\u0107 pod\u0142\u0105czenia do platformy czegokolwiek. Obecnie zintegrowa\u0142em <noindex><a rel=\"nofollow\" href=\"http:\/\/LibRetro\">LibRetro<\/a><\/noindex> z us\u0142ug\u0105 gier w chmurze, poniewa\u017c LibRetro oferuje pi\u0119kny interfejs emulatora gier retro dla takich gier jak SNES, GBA, PS.<\/p>\n<p><b>6. Pokoje do multiplayera, crowd play oraz zewn\u0119trzne linkowanie (deep-link) do gry<\/b><br \/>\nCloudRetro wspiera wiele nowych tryb\u00f3w gry, takich jak CrowdPlay i Online MultiPlayer dla gier retro. Je\u015bli kilku u\u017cytkownik\u00f3w otworzy ten sam deep-link na r\u00f3\u017cnych komputerach, zobacz\u0105 t\u0119 sam\u0105 uruchomion\u0105 gr\u0119 i b\u0119d\u0105 mogli do niej do\u0142\u0105czy\u0107.<\/p>\n<p>Co wi\u0119cej, stany gier s\u0105 przechowywane w chmurze. Umo\u017cliwia to u\u017cytkownikom kontynuowanie gry w dowolnym momencie na dowolnym innym urz\u0105dzeniu.<\/p>\n<p><b>7. Poziome skalowanie<\/b><br \/>\nPodobnie jak ka\u017cde SAAS w dzisiejszych czasach, gry w chmurze musz\u0105 by\u0107 zaprojektowane tak, aby by\u0142y poziomo skalowalne. Konstrukcja \u201ekoordynator-pracownik\u201d pozwala na dodawanie kolejnych pracownik\u00f3w, aby obs\u0142ugiwa\u0107 wi\u0119kszy ruch.<\/p>\n<p><b>8. Brak uzale\u017cnienia od jednego chmury<\/b><br \/>\nInfrastruktura CloudRetro jest hostowana u r\u00f3\u017cnych dostawc\u00f3w chmury (Digital Ocean, Alibaba, dostawca dedykowany) dla r\u00f3\u017cnych region\u00f3w. Aktywuj\u0119 uruchamianie w kontenerze Docker dla infrastruktury i konfiguruj\u0119 parametry sieciowe za pomoc\u0105 skryptu bash, aby unikn\u0105\u0107 uzale\u017cnienia od jednego dostawcy chmury. \u0141\u0105cz\u0105c to z NAT Traversal w WebRTC, mo\u017cemy uzyska\u0107 elastyczno\u015b\u0107 w uruchamianiu CloudRetro na dowolnej platformie chmurowej, a nawet na maszynach jakiegokolwiek u\u017cytkownika.<\/p>\n<h3>Projekt architektoniczny<\/h3>\n<p>\n<b>Pracownik:<\/b> (lub serwer strumieniowy, wspomniany powy\u017cej) rozdziela gry, uruchamia proces kodowania i przesy\u0142a zakodowane media u\u017cytkownikom. Instance robocze s\u0105 rozmieszczone na ca\u0142ym \u015bwiecie, a ka\u017cdy robotnik mo\u017ce obs\u0142ugiwa\u0107 kilka sesji u\u017cytkownik\u00f3w jednocze\u015bnie.<\/p>\n<p><b>Koordynator:<\/b> odpowiada za przyporz\u0105dkowanie nowego u\u017cytkownika do najbardziej odpowiedniego robota do strumieniowania. Koordynator komunikuje si\u0119 z robotnikami za po\u015brednictwem WebSocket.<\/p>\n<p><b>Przechowalnia stan\u00f3w gier:<\/b> centralne zdalne przechowywanie dla wszystkich stan\u00f3w gry. Przechowalnia ta zapewnia tak istotne funkcje, jak zdalne zapisywanie\/\u0142adowanie.<\/p>\n<p><img decoding=\"async\" alt=\"Chmurowe granie z otwartym kodem \u017ar\u00f3d\u0142owym na WebRTC: p2p, multiplayer, zerowe op\u00f3\u017anienie\" src=\"\/wp-content\/uploads\/2020\/07\/985447b81350a640b0bd1344b5705113.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nArchitektura CloudRetro na wysokim poziomie<\/p>\n<h3>Scenariusz u\u017cytkownika<\/h3>\n<p>\nKiedy nowy u\u017cytkownik otwiera CloudRetro, w krokach 1 i 2 pokazanych na poni\u017cszym rysunku, koordynator jest zapytywany wraz z list\u0105 dost\u0119pnych robotnik\u00f3w na pierwszej stronie. Nast\u0119pnie, w kroku 3, klient oblicza op\u00f3\u017anienia dla wszystkich kandydat\u00f3w za pomoc\u0105 \u017c\u0105dania HTTP ping. Ta lista op\u00f3\u017anie\u0144 jest nast\u0119pnie wysy\u0142ana z powrotem do koordynatora, aby m\u00f3g\u0142 okre\u015bli\u0107 najbardziej odpowiedniego robota do obs\u0142ugi u\u017cytkownika. W kroku 4 poni\u017cej gra jest tworzona. Mi\u0119dzy u\u017cytkownikiem a przypisanym robotnikiem ustanawiane jest strumieniowe po\u0142\u0105czenie WebRTC.<br \/>\n<img decoding=\"async\" alt=\"Chmurowe granie z otwartym kodem \u017ar\u00f3d\u0142owym na WebRTC: p2p, multiplayer, zerowe op\u00f3\u017anienie\" src=\"\/wp-content\/uploads\/2020\/07\/00199b5942e3e4314609ec0e70ea7162.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nScenariusz u\u017cytkownika po uzyskaniu dost\u0119pu<\/p>\n<h3>Co znajduje si\u0119 w robocie<\/h3>\n<p>\nPipeline gier i strumieniowania s\u0105 przechowywane w robocie w izolacji i wymieniaj\u0105 si\u0119 informacjami przez interfejs. Obecnie ta komunikacja odbywa si\u0119 poprzez przesy\u0142 danych w pami\u0119ci przez <noindex><a rel=\"nofollow\" href=\"https:\/\/tour.golang.org\/concurrency\/2\">kana\u0142y Golang<\/a><\/noindex> w tym samym procesie. Nast\u0119pnym celem jest segregacja, tj. niezale\u017cne uruchamianie gry w innym procesie.<\/p>\n<p><img decoding=\"async\" alt=\"Chmurowe granie z otwartym kodem \u017ar\u00f3d\u0142owym na WebRTC: p2p, multiplayer, zerowe op\u00f3\u017anienie\" src=\"\/wp-content\/uploads\/2020\/07\/7a90ec2638344467a34604cd4322165c.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nInterakcja komponent\u00f3w robota<\/p>\n<p>G\u0142\u00f3wne sk\u0142adniki:<\/p>\n<ul>\n<li><b>WebRTC:<\/b> komponent kliencki, kt\u00f3ry przyjmuje wej\u015bcie u\u017cytkownika i wyprowadza zakodowane media z serwera.\n<\/li>\n<li><b>Emulator gier:<\/b> komponent gier. Dzi\u0119ki bibliotece Libretro system jest w stanie uruchamia\u0107 gr\u0119 w tym samym procesie i wewn\u0119trznie przechwytywa\u0107 media i strumie\u0144 wej\u015bciowy.\n<\/li>\n<li>Klatki wewn\u0105trz gry s\u0105 przechwytywane i wysy\u0142ane do kodera.\n<\/li>\n<li><b>Koder obrazu\/audio:<\/b> pipeline koduj\u0105cy, kt\u00f3ry przyjmuje klatki medi\u00f3w, koduje je w tle i wyprowadza zakodowane obrazy\/audio.\n<\/li>\n<\/ul>\n<p><\/p>\n<h2>Realizacja<\/h2>\n<p>\nCloudRetro polega na WebRTC jako technologii bazowej, dlatego zanim zanurz\u0119 si\u0119 w szczeg\u00f3\u0142y implementacji w Golang, postanowi\u0142em opowiedzie\u0107 o samej technologii WebRTC. To niesamowita technologia, kt\u00f3ra bardzo pomog\u0142a mi osi\u0105gn\u0105\u0107 op\u00f3\u017anienie transmisji danych wynosz\u0105ce zaledwie u\u0142amki sekundy.<\/p>\n<h3>WebRTC<\/h3>\n<p>\nWebRTC jest zaprojektowany, aby zapewnia\u0107 wysokiej jako\u015bci po\u0142\u0105czenia peer-to-peer w natywnych aplikacjach mobilnych oraz w przegl\u0105darkach za pomoc\u0105 prostych API.<\/p>\n<h4>NAT Traversal <\/h4>\n<p>\nWebRTC jest znany ze swojej funkcjonalno\u015bci NAT Traversal. WebRTC jest przeznaczone do komunikacji peer-to-peer. Jego celem jest znalezienie najbardziej odpowiedniej bezpo\u015bredniej trasy, unikaj\u0105c bram NAT i zap\u00f3r ogniowych w procesie zwanym <noindex><a rel=\"nofollow\" href=\"https:\/\/webrtchacks.com\/trickle-ice\/\">ICE<\/a><\/noindex>. W ramach tego procesu API WebRTC odnajduj\u0105 Tw\u00f3j publiczny adres IP za pomoc\u0105 serwer\u00f3w STUN i przekierowuj\u0105 go na serwer retransmisji (<noindex><a rel=\"nofollow\" href=\"https:\/\/webrtchacks.com\/?s=turn\">TURN<\/a><\/noindex>), gdy nie ma mo\u017cliwo\u015bci nawi\u0105zania bezpo\u015bredniego po\u0142\u0105czenia.<\/p>\n<p>Jednak CloudRetro nie wykorzystuje tej funkcji w pe\u0142ni. Jego po\u0142\u0105czenia peer-to-peer istniej\u0105 nie mi\u0119dzy u\u017cytkownikami, a mi\u0119dzy u\u017cytkownikami a serwerami w chmurze. Cz\u0119\u015b\u0107 serwerowa modelu ma mniej ogranicze\u0144 w bezpo\u015bredniej komunikacji ni\u017c zwyk\u0142e urz\u0105dzenie u\u017cytkownika. Umo\u017cliwia to wst\u0119pne otwieranie przychodz\u0105cych port\u00f3w lub bezpo\u015brednie korzystanie z publicznych adres\u00f3w IP, poniewa\u017c serwer nie znajduje si\u0119 za NAT.<\/p>\n<p>Kiedy\u015b chcia\u0142em przekszta\u0142ci\u0107 projekt w platform\u0119 dystrybucji gier dla Cloud Gaming. Pomys\u0142 polega\u0142 na tym, aby pozwoli\u0107 tw\u00f3rcom gier udost\u0119pnia\u0107 gry i zasoby strumieniowe. U\u017cytkownicy mogliby bezpo\u015brednio wchodzi\u0107 w interakcje z dostawcami. W taki zdecentralizowany spos\u00f3b CloudRetro jest jedynie \u015brodowiskiem do \u0142\u0105czenia zewn\u0119trznych zasob\u00f3w strumieniowych z u\u017cytkownikami, co sprawia, \u017ce jest bardziej skalowalne, gdy nie jest ju\u017c obci\u0105\u017cone hostingiem. Rola NAT Traversal w WebRTC ma tutaj kluczowe znaczenie dla u\u0142atwienia inicjacji po\u0142\u0105czenia peer-to-peer z zewn\u0119trznymi zasobami strumieniowymi, co u\u0142atwia pod\u0142\u0105czenie tw\u00f3rcy do sieci.<\/p>\n<h4>Kompresja wideo<\/h4>\n<p>\nKompresja wideo jest nieod\u0142\u0105czn\u0105 cz\u0119\u015bci\u0105 procesu, kt\u00f3ra znacz\u0105co przyczynia si\u0119 do p\u0142ynno\u015bci strumienia. Chocia\u017c nie jest konieczne zna\u0107 wszystkie szczeg\u00f3\u0142y kodowania wideo w VP8\/H264, zrozumienie koncepcji pomaga w zrozumieniu parametr\u00f3w pr\u0119dko\u015bci strumieni wideo, debugowaniu nieoczekiwanego zachowania oraz dostosowywaniu op\u00f3\u017anienia.<\/p>\n<p>Kompresja wideo dla serwisu streamingowego jest trudnym zadaniem, poniewa\u017c algorytm musi zapewni\u0107, \u017ce ca\u0142kowity czas kodowania + czas transmisji przez sie\u0107 + czas dekodowania jest jak najkr\u00f3tszy. Dodatkowo proces kodowania musi by\u0107 sp\u00f3jny i ci\u0105g\u0142y. Niekt\u00f3re wzajemne ust\u0119pstwa w kodowaniu nie s\u0105 mo\u017cliwe \u2013 na przyk\u0142ad nie mo\u017cemy preferowa\u0107 d\u0142ugiego czasu kodowania kosztem mniejszego rozmiaru pliku i czasu dekodowania lub stosowa\u0107 niesp\u00f3jnej kompresji.<\/p>\n<p>Idea kompresji wideo polega na wykluczeniu zb\u0119dnych bit\u00f3w informacji, zachowuj\u0105c jednocze\u015bnie akceptowalny poziom dok\u0142adno\u015bci dla u\u017cytkownik\u00f3w. Opr\u00f3cz kodowania pojedynczych statycznych klatek obrazu, algorytm wytwarza dane dla aktualnej klatki na podstawie poprzedniej i nast\u0119pnej, dlatego przekazywana jest tylko ich r\u00f3\u017cnica. Jak pokazuje przyk\u0142ad z Pacmanem, przesy\u0142ane s\u0105 tylko punkty r\u00f3\u017cnicowe.<\/p>\n<p><img decoding=\"async\" alt=\"Chmurowe granie z otwartym kodem \u017ar\u00f3d\u0142owym na WebRTC: p2p, multiplayer, zerowe op\u00f3\u017anienie\" src=\"\/wp-content\/uploads\/2020\/07\/e452c54c53ab7797b610620aefbba8d2.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nPor\u00f3wnanie klatek wideo na przyk\u0142adzie Pacmana<\/p>\n<h4>Kompresja audio<\/h4>\n<p>\nPodobnie, algorytm kompresji d\u017awi\u0119ku pomija dane, kt\u00f3re nie mog\u0105 by\u0107 postrzegane przez cz\u0142owieka. Opus jest obecnie kodekiem audio o najlepszej wydajno\u015bci. Zosta\u0142 zaprojektowany do przesy\u0142ania fali d\u017awi\u0119kowej przez protok\u00f3\u0142 uporz\u0105dkowanych datagram\u00f3w, taki jak RTP (Real Time Transport Protocol \u2013 protok\u00f3\u0142 przesy\u0142ania danych w czasie rzeczywistym). Jego op\u00f3\u017anienie jest kr\u00f3tsze ni\u017c w przypadku mp3 i aac, a jako\u015b\u0107 wy\u017csza. Op\u00f3\u017anienie wynosi zazwyczaj oko\u0142o 5~66,5 ms.<\/p>\n<h4>Pion, WebRTC w Golang<\/h4>\n<p>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/pion\/webrtc\">Pion<\/a><\/noindex> to projekt z otwartym kodem \u017ar\u00f3d\u0142owym, kt\u00f3ry implementuje WebRTC w Golang. Zamiast standardowego owija w natywne biblioteki C++ WebRTC, Pion jest natywn\u0105 implementacj\u0105 WebRTC w Golang z lepsz\u0105 wydajno\u015bci\u0105, integracj\u0105 z Go oraz kontrol\u0105 wersji na protoko\u0142ach WebRTC.<\/p>\n<p>Biblioteka r\u00f3wnie\u017c zapewnia przesy\u0142anie strumieniowe z wieloma doskona\u0142ymi wbudowanymi modu\u0142ami z op\u00f3\u017anieniem poni\u017cej sekundy. Ma w\u0142asn\u0105 implementacj\u0119 STUN, DTLS, SCTP itd. oraz eksperymenty z QUIC i WebAssembly. Ta otwarto\u017ar\u00f3d\u0142owa biblioteka jest naprawd\u0119 dobrym \u017ar\u00f3d\u0142em nauki z doskona\u0142\u0105 dokumentacj\u0105, implementacj\u0105 protoko\u0142\u00f3w sieciowych i \u015bwietnymi przyk\u0142adami.<\/p>\n<p>Spo\u0142eczno\u015b\u0107 Pion, kierowana przez bardzo pasjonuj\u0105cego tw\u00f3rc\u0119, jest do\u015b\u0107 o\u017cywiona, odbywa si\u0119 tam wiele warto\u015bciowych dyskusji o WebRTC. Je\u015bli interesuje ci\u0119 ta technologia, do\u0142\u0105cz do <noindex><a rel=\"nofollow\" href=\"http:\/\/pion.ly\/slack\">http:\/\/pion.ly\/slack<\/a><\/noindex> \u2013 dowiesz si\u0119 wielu nowych rzeczy.<\/p>\n<h3>Pisanie CloudRetro w Golang<\/h3>\n<p>\n<img decoding=\"async\" alt=\"Chmurowe granie z otwartym kodem \u017ar\u00f3d\u0142owym na WebRTC: p2p, multiplayer, zerowe op\u00f3\u017anienie\" src=\"\/wp-content\/uploads\/2020\/07\/f85f7b8ea579fab964d870aad698c7e7.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nImplementacja workera w Go<\/p>\n<h4>Kana\u0142y Go w akcji<\/h4>\n<p>\nDzi\u0119ki pi\u0119knemu projektowi kana\u0142\u00f3w Go, problemy z przesy\u0142aniem strumieniowym zdarze\u0144 i r\u00f3wnoleg\u0142o\u015bci\u0105 s\u0105 znacznie uproszczone. Jak pokazano na diagramie, w r\u00f3\u017cnych GoRoutines r\u00f3wnolegle dzia\u0142aj\u0105 r\u00f3\u017cne komponenty. Ka\u017cdy komponent zarz\u0105dza swoim stanem i komunikuje si\u0119 za pomoc\u0105 kana\u0142\u00f3w. Wybrane stwierdzenie Golang wymusza przetwarzanie jednego atomowego zdarzenia w ka\u017cdej chwili czasu w grze (game tick). To oznacza, \u017ce dla takiego projektu blokada nie jest potrzebna. Na przyk\u0142ad, gdy u\u017cytkownik zapisuje, wymagany jest pe\u0142ny zrzut stanu gry. Ten stan musi pozosta\u0107 ci\u0105g\u0142y, wykonuj\u0105c wej\u015bcie, a\u017c zapis zostanie uko\u0144czony. Podczas ka\u017cdego game tick\u2019a backend mo\u017ce obs\u0142ugiwa\u0107 tylko operacj\u0119 zapisu lub wej\u015bcia, co czyni proces bezpiecznym dla w\u0105tk\u00f3w.<\/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>\nTen wz\u00f3r Golang doskonale pasuje do mojego scenariusza u\u017cycia CrowdPlay i Multiplayer. Pod\u0105\u017caj\u0105c za tym wzorem, wszystkie wej\u015bcia u\u017cytkownik\u00f3w w jednym pomieszczeniu s\u0105 wbudowywane w centralny kana\u0142 wej\u015bciowy. Media gry s\u0105 nast\u0119pnie rozpowszechniane w\u015br\u00f3d wszystkich u\u017cytkownik\u00f3w w jednym pomieszczeniu. W ten spos\u00f3b osi\u0105gamy podzia\u0142 stanu gry mi\u0119dzy r\u00f3\u017cnymi sesjami gier r\u00f3\u017cnych u\u017cytkownik\u00f3w.<\/p>\n<p><img decoding=\"async\" alt=\"Chmurowe granie z otwartym kodem \u017ar\u00f3d\u0142owym na WebRTC: p2p, multiplayer, zerowe op\u00f3\u017anienie\" src=\"\/wp-content\/uploads\/2020\/07\/000a495d7f214246a8a396aab11a3ac5.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nSynchronizacja mi\u0119dzy r\u00f3\u017cnymi sesjami<\/p>\n<h4>Wady Golang<\/h4>\n<p>\nGolang nie jest doskona\u0142y. Kana\u0142 jest wolny. W por\u00f3wnaniu do blokady kana\u0142 Go to po prostu prostszy spos\u00f3b obs\u0142ugi r\u00f3wnoleg\u0142ych i strumieniowych zdarze\u0144, ale kana\u0142 nie zapewnia najlepszej wydajno\u015bci. Pod kana\u0142em kryje si\u0119 skomplikowana logika blokady. Dlatego wprowadzi\u0142em pewne poprawki w realizacji, ponownie stosuj\u0105c blokady i atomowe warto\u015bci przy zamianie kana\u0142\u00f3w dla optymalizacji wydajno\u015bci.<\/p>\n<p>Ponadto, garbage collector w Golang jest nieprzewidywalny, co czasami prowadzi do podejrzanie d\u0142ugich przerw. To powa\u017cnie przeszkadza w dzia\u0142aniu aplikacji strumieniowej w czasie rzeczywistym.<\/p>\n<h4>CGO<\/h4>\n<p>\nW projekcie u\u017cywana jest istniej\u0105ca biblioteka VP8\/H264 Golang o otwartym kodzie \u017ar\u00f3d\u0142owym do kompresji medi\u00f3w oraz Libretro do emulator\u00f3w gier. Wszystkie te biblioteki to po prostu opakowania biblioteki C w Go z wykorzystaniem <noindex><a rel=\"nofollow\" href=\"https:\/\/golang.org\/cmd\/cgo\/\">CGO<\/a><\/noindex>. Niekt\u00f3re z wymienionych wad to <noindex><a rel=\"nofollow\" href=\"https:\/\/dave.cheney.net\/2019\/10\/06\/use-internal-packages-to-reduce-your-public-api-surface\">ten post Dave'a Cheney'a<\/a><\/noindex>. Problemy, z kt\u00f3rymi si\u0119 zmierzy\u0142em:<\/p>\n<ul>\n<li>niemo\u017cno\u015b\u0107 uchwycenia awarii w CGO, nawet przy u\u017cyciu Golang RecoveryCrash;<\/li>\n<li>niemo\u017cno\u015b\u0107 zidentyfikowania w\u0105skiego gard\u0142a wydajno\u015bci, gdy nie mo\u017cemy wykrywa\u0107 szczeg\u00f3\u0142owych problem\u00f3w w CGO.<\/li>\n<\/ul>\n<p><\/p>\n<h2>Podsumowanie<\/h2>\n<p>\nOsi\u0105gn\u0105\u0142em sw\u00f3j cel \u2013 zrozumia\u0142em us\u0142ugi gier w chmurze i stworzy\u0142em platform\u0119, kt\u00f3ra pomaga gra\u0107 w nostalgiczne gry retro z moimi przyjaci\u00f3\u0142mi online. Stworzenie tego projektu by\u0142oby niemo\u017cliwe bez biblioteki Pion i wsparcia spo\u0142eczno\u015bci Pion. Jestem niesamowicie wdzi\u0119czny za jej intensywny rozw\u00f3j. Proste interfejsy API oferowane przez WebRTC i Pion zapewni\u0142y p\u0142ynn\u0105 integracj\u0119. Moje pierwsze dowody koncepcji zosta\u0142y wydane w tym samym tygodniu, mimo \u017ce wcze\u015bniej nie zna\u0142em si\u0119 na po\u0142\u0105czeniach typu peer-to-peer (P2P).<\/p>\n<p>Mimo prostoty integracji, P2P streaming naprawd\u0119 jest bardzo skomplikowanym obszarem w informatyce. Musi radzi\u0107 sobie ze z\u0142o\u017cono\u015bci\u0105 wieloletnich architektur sieciowych, takich jak IP i NAT, aby stworzy\u0107 sesj\u0119 peer-to-peer. Pracuj\u0105c nad tym projektem, zdoby\u0142em wiele cennych informacji na temat sieci i optymalizacji wydajno\u015bci, dlatego polecam wszystkim spr\u00f3bowa\u0107 budowa\u0107 produkty P2P z pomoc\u0105 WebRTC.<\/p>\n<p>CloudRetro obs\u0142uguje wszystkie scenariusze u\u017cycia, kt\u00f3rych si\u0119 spodziewa\u0142em jako retro-gracz. Niemniej jednak uwa\u017cam, \u017ce istnieje wiele obszar\u00f3w w projekcie, kt\u00f3re mog\u0119 poprawi\u0107, na przyk\u0142ad uczyni\u0107 sie\u0107 bardziej niezawodn\u0105 i wydajn\u0105, zapewni\u0107 wy\u017csz\u0105 jako\u015b\u0107 grafiki gier, czy umo\u017cliwi\u0107 dzielenie si\u0119 grami mi\u0119dzy u\u017cytkownikami. Ci\u0119\u017cko pracuj\u0119 nad tym. Prosz\u0119, \u015bled\u017acie <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/giongto35\/cloud-game\">projektem<\/a><\/noindex> i wspierajcie go, je\u015bli Wam si\u0119 podoba.<\/li>\n<\/ul>\n<p>\u0179r\u00f3d\u0142o: <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.1.1 - 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\/pl\/blog\/administrirovanie\/oblachnyj-gejming-s-otkrytym-ishodnym-kodom-na-webrtc-p2p-multipleer-zero-latency\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"pl_PL\" \/>\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\/pl\/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\udd47Chmurowe granie z otwartym \u017ar\u00f3d\u0142em na WebRTC: p2p, multiplayer, zero latency | ProHoster","description":"","canonical_url":"https:\/\/prohoster.info\/pl\/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":"pl_PL","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\/pl\/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\/pl\/wp-json\/wp\/v2\/posts\/89303","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/comments?post=89303"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts\/89303\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/media\/89304"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/media?parent=89303"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/categories?post=89303"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/tags?post=89303"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}