Облачни игри с отворен код на WebRTC: p2p, мултиплейър, нулево забавяне

Облачни игри с отворен код на WebRTC: p2p, мултиплейър, нулево забавяне
Софтуер като услуга, инфраструктура като услуга, платформа като услуга, комуникационна платформа като услуга, видеоконференция като услуга и какво ще кажете за облачните игри като услуга? Вече има няколко опита за създаване на облачни игри (Cloud Gaming), като например Stadia, наскоро стартирана от Google. Стадии не е нов за WebRTC, но могат ли други да използват WebRTC по същия начин?

Thanh Nguyen реши да тества тази възможност в своя проект с отворен код CloudRetro. CloudRetro е базиран на Pion, популярен WebRTC библиотека, базирана на Go (благодаря Шоуну от екипа за разработка на Pion за помощта им с тази статия). В тази статия Thanh прави общ преглед на архитектурата на своя проект и също така говори за това какво полезно е научил и какви предизвикателства е срещнал, докато е работил.

Влизане

Миналата година, когато Google обяви Stadia, бях поразен. Идеята е толкова уникална и новаторска, че постоянно се чудех как това изобщо е възможно със съществуващите технологии. Желанието да разбера по-добре тази тема ме подтикна да създам моя собствена версия на облачна игра с отворен код. Резултатът беше просто фантастичен. По-долу бих искал да споделя процеса на работа върху моя годишен проект.

TLDR: версия с кратък слайд с акценти

Защо облачните игри са бъдещето

Вярвам, че Cloud Gaming скоро ще се превърне в ново поколение не само игри, но и други области на компютърните науки. Облачните игри са върхът на модела клиент/сървър. Този модел максимизира управлението на задния край и минимизира работата на интерфейса чрез хостване на логиката на играта на отдалечен сървър и поточно предаване на изображения/аудио към клиента. Сървърът извършва тежката обработка, така че клиентът вече не е обект на хардуерни ограничения.

Google Stadia ви позволява да играете AAA игри (т.е. хитови игри от висок клас) на интерфейс като YouTube. Същата методология може да се приложи към други тежки офлайн приложения като операционна система или 2D/3D графичен дизайн и др. така че да можем да ги изпълняваме стабилно на устройства с ниски спецификации на различни платформи.

Облачни игри с отворен код на WebRTC: p2p, мултиплейър, нулево забавяне
Бъдещето на тази технология: представете си, ако Microsoft Windows 10 работеше ли в браузъра Chrome?

Облачните игри са технически трудни

Игрите са една от онези редки области, където се изисква постоянна бърза реакция на потребителя. Ако от време на време срещнем забавяне от 2 секунди при кликване върху страница, това е приемливо. Видео потоците на живо са склонни да изостават с няколко секунди, но все пак предлагат доста голяма използваемост. Въпреки това, ако играта често се забавя с 500ms, просто не е възможно да се играе. Нашата цел е да постигнем изключително ниска латентност, така че разликата между входа и медията да е възможно най-малка. Следователно традиционният подход за поточно видео не е приложим тук.

Облачни игри с отворен код на WebRTC: p2p, мултиплейър, нулево забавяне
Общ шаблон за облачна игра

Проект с отворен код CloudRetro

Реших да създам тестова проба на облачна игра, за да видя дали всичко това е възможно с толкова строги мрежови ограничения. Избрах Golang за доказателство на концепцията, защото това е езикът, с който съм най-запознат и е подходящ за тази реализация поради много други причини, както по-късно разбрах. Go е проста и се развива много бързо; Каналите в Go са чудесни за управление на многопоточност.

Проект CloudRetro.io е услуга за облачни игри с отворен код за ретро игри. Целта на проекта е да внесе най-удобното игрово изживяване в традиционните ретро игри и да добави мултиплейър.
Повече за проекта можете да научите тук: https://github.com/giongto35/cloud-game.

CloudRetro функционалност

CloudRetro използва ретро игри, за да покаже силата на облачните игри. Това ви позволява да получите много уникални игрови изживявания.

  • Преносимост на играта
    • Незабавно възпроизвеждане при отваряне на страница; не е необходимо изтегляне и инсталиране
    • Работи на мобилен браузър, така че не е необходим софтуер за стартиране

  • Игровите сесии могат да се споделят между множество устройства и да се съхраняват в облака за следващо влизане
  • Играта може да се предава поточно или можете да я играете с няколко потребители наведнъж:
    • Crowdplay като TwitchPlayPokemon, само повече междуплатформени и повече в реално време
    • Офлайн игри онлайн. Много потребители могат да играят без настройка на мрежата. Samurai Shodown вече може да се играе с 2 играчи през мрежата CloudRetro

    Облачни игри с отворен код на WebRTC: p2p, мултиплейър, нулево забавяне
    Демо версия на онлайн мултиплейър игра на различни устройства

    Инфраструктура

    Изисквания и технологичен стек

    По-долу е даден списък с изисквания, които поставих, преди да започна проекта.

    1. Един играч
    Това изискване може да не изглежда твърде важно и очевидно тук, но е един от моите ключови изводи, то държи облачните игри възможно най-далеч от традиционните стрийминг услуги. Ако се съсредоточим върху играта за един играч, можем да се отървем от централизирания сървър или CDN, защото не е нужно да предаваме поточно към масите. Вместо да качват потоци към поглъщащ сървър или да предават пакети към централизиран WebSocket сървър, потоците от услуги се предават директно към потребителя чрез WebRTC партньорска връзка.

    2. Медиен поток с ниска латентност
    Когато чета за Stadia, често виждам WebRTC споменат в някои статии. Разбрах, че WebRTC е изключителна технология и е чудесна за използване в облачни игри. WebRTC е проект, който предоставя на уеб браузъри и мобилни приложения комуникация в реално време чрез прост API. Той осигурява peer-to-peer свързаност, оптимизиран е за медии и има вградени стандартни кодеци като VP8 и H264.

    Дадох приоритет на осигуряването на възможно най-доброто потребителско изживяване пред поддържането на висококачествена графика. В алгоритъма се допускат някои загуби. Google Stadia има допълнителна стъпка за намаляване на размера на изображението на сървъра и кадрите се увеличават до по-високо качество, преди да бъдат предадени на партньорите.

    3. Разпределена инфраструктура с географско маршрутизиране
    Независимо колко оптимизирани са алгоритъмът за компресиране и кодът, мрежата все още е решаващият фактор, който допринася най-много за латентността. Архитектурата трябва да има механизъм за сдвояване на сървъра, който е най-близо до потребителя, за да се намали времето за двупосочно пътуване (RTT). Архитектурата трябва да има 1 координатор и няколко стрийминг сървъра, разпределени по целия свят: САЩ Запад, САЩ Изток, Европа, Сингапур, Китай. Всички стрийминг сървъри трябва да бъдат напълно изолирани. Системата може да коригира разпространението си, когато сървърът се присъедини или напусне мрежата. По този начин, при голям трафик, добавянето на допълнителни сървъри позволява хоризонтално мащабиране.

    4. Съвместимост с браузър
    Облачните игри са най-добри, когато изискват минимума от потребителите. Това означава, че е възможно да се стартира в браузъра. Браузърите помагат да се направи игровото изживяване възможно най-удобно за потребителите, като им спестяват инсталирането на софтуер и хардуер. Браузърите също помагат да се осигури крос-платформа за мобилни и настолни версии. За щастие, WebRTC се поддържа добре в различни браузъри.

    5. Ясно разделяне на интерфейса на играта и услугата
    Гледам на услугата за облачни игри като на платформа. Всеки трябва да може да свърже всичко към платформата. Сега съм интегрирал LibRetro с облачна услуга за игри, защото LibRetro предлага красив интерфейс за емулатор на игри за ретро игри като SNES, GBA, PS.

    6. Стаи за мултиплейър, групова игра и външно свързване (deep-link) с играта
    CloudRetro поддържа много нови геймплеи като CrowdPlay и Online MultiPlayer за ретро игри. Ако няколко потребители отворят една и съща дълбока връзка на различни компютри, те ще видят една и съща игра да работи и дори ще могат да се присъединят към нея.

    Освен това, състоянията на играта се съхраняват в облачното хранилище. Това позволява на потребителите да продължат играта по всяко време на всяко друго устройство.

    7. Хоризонтално мащабиране
    Като всеки SAAS в днешно време, облачните игри трябва да бъдат проектирани да бъдат хоризонтално мащабируеми. Дизайнът координатор-работник ви позволява да добавяте повече работници, за да обслужвате повече трафик.

    8. Не е обвързан с един облак
    Инфраструктурата CloudRetro се хоства от различни доставчици на облак (Digital Ocean, Alibaba, персонализиран доставчик) за различни региони. Разрешавам работа в инфраструктурен Docker контейнер и конфигурирам мрежови настройки с bash скрипт, за да избегна зависимост от един доставчик на облак. Комбинирайки това с NAT Traversal в WebRTC, можем да имаме гъвкавостта да разположим CloudRetro на всяка облачна платформа и дори машина на всеки потребител.

    Архитектурен дизайн

    работник: (или сървърът за стрийминг, споменат по-горе) умножава игрите, изпълнява тръбопровода за кодиране и предава поточно кодираната медия към потребителите. Worker екземплярите са разпространени по целия свят и всеки worker може да обработва множество потребителски сесии едновременно.

    Координатор: отговаря за сдвояването на новия потребител с най-подходящия стрийминг работник. Координаторът комуникира с работниците чрез WebSocket.

    Съхранение на състоянието на играта: централно отдалечено хранилище за всички състояния на играта. Това хранилище предоставя важни функции като дистанционно запазване/зареждане.

    Облачни игри с отворен код на WebRTC: p2p, мултиплейър, нулево забавяне
    Архитектура от най-високо ниво на CloudRetro

    Персонализиран скрипт

    Когато нов потребител отвори CloudRetro в стъпки 1 и 2, показани на фигурата по-долу, координаторът, заедно със списък с налични работници, се изисква на първата страница. След това, в стъпка 3, клиентът изчислява закъсненията за всички кандидати, използвайки HTTP ping заявка. След това този списък със закъснения се изпраща обратно на координатора, за да може той да определи най-подходящия работник, който да обслужва потребителя. Стъпка 4 по-долу създава игра. Установява се WebRTC стрийминг връзка между потребителя и назначения работник.
    Облачни игри с отворен код на WebRTC: p2p, мултиплейър, нулево забавяне
    Персонализиран скрипт след получаване на достъп

    Какво има вътре в работника

    Тръбопроводите за игри и стрийминг се съхраняват изолирано вътре в работника и обменят информация там чрез интерфейса. В момента тази комуникация се осъществява чрез прехвърляне на данни в паметта Голанг канали в същия процес. Следващата цел е сегрегацията, т.е. самостоятелно стартиране на играта в друг процес.

    Облачни игри с отворен код на WebRTC: p2p, мултиплейър, нулево забавяне
    Взаимодействие на работните компоненти

    Главни компоненти:

    • WebRTC: клиентски компонент, който приема въвеждане от потребителя и извежда кодираната медия от сървъра.
    • Емулатор на играта: компонент на играта. Благодарение на библиотеката Libretro, системата е в състояние да стартира играта в същия процес и да прихване вътрешно медиите и входния поток.
    • Кадрите в играта се улавят и изпращат към енкодера.
    • Кодер за изображения/аудио: тръбопровод за кодиране, който получава медийни кадри, кодира ги във фонов режим и извежда кодирани изображения/аудио.

    Изпълнение

    CloudRetro разчита на WebRTC като основна технология, така че преди да се потопя в детайлите на изпълнението на Golang, реших да говоря за самия WebRTC. Това е невероятна част от технологията, която ми помогна изключително много за постигането на поточно предаване със закъснение под секунди.

    WebRTC

    WebRTC е проектиран да осигурява висококачествени връзки между равностойни потребители в собствено мобилно приложение и браузъри, използващи прости API.

    NAT преминаване

    WebRTC е известен със своята функционалност NAT Traversal. WebRTC е предназначен за peer-to-peer комуникация. Неговата цел е да намери най-подходящия директен маршрут, избягвайки NAT шлюзове и защитни стени, за peer-to-peer чрез процес, наречен ICE. Като част от този процес приложните програмни интерфейси (API) на WebRTC намират вашия публичен IP адрес с помощта на STUN сървъри и го препращат към релейен сървър (ВЪРВЕТЕ), когато не може да се установи директна връзка.

    CloudRetro обаче не използва напълно тази възможност. Неговите peer-to-peer връзки не съществуват между потребители, а между потребители и облачни сървъри. Сървърната страна на модела има по-малко ограничения за директна комуникация, отколкото типично потребителско устройство. Това ви позволява да отваряте предварително входящи портове или да използвате директно публични IP адреси, тъй като сървърът не е зад NAT.

    Преди това исках да превърна проекта в платформа за разпространение на игри за Cloud Gaming. Идеята беше да се позволи на създателите на игри да предоставят игри и ресурси за стрийминг. И потребителите ще взаимодействат директно с доставчиците. По този децентрализиран начин CloudRetro е просто средство за свързване на стрийминг ресурси на трети страни към потребителите, което го прави по-мащабируем, когато хостингът вече не виси на него. Ролята на WebRTC NAT Traversal е много важна тук, за да улесни инициализирането на peer-to-peer връзка на ресурси за стрийминг на трети страни, което улеснява свързването на създателя към мрежата.

    Видео компресия

    Компресията на видео е незаменима част от тръбопровода и допринася значително за плавността на потока. Въпреки че не е необходимо да знаете всички подробности за кодирането на видео VP8/H264, разбирането на концепцията помага да се разберат параметрите на скоростта на поточно видео, да се отстранят грешки при неочаквано поведение и да се коригира латентността.

    Компресирането на видео за стрийминг услуга е предизвикателство, тъй като алгоритъмът трябва да гарантира, че общото време за кодиране + времето за мрежов трансфер + времето за декодиране е възможно най-малко. Освен това процесът на кодиране трябва да бъде последователен и непрекъснат. Някои компромиси при кодирането не се прилагат - например не можем да предпочетем дълго време за кодиране пред по-малък размер на файла и време за декодиране или да използваме непоследователна компресия.

    Идеята зад видео компресията е да се елиминират ненужните битове информация, като същевременно се поддържа приемливо ниво на вярност за потребителите. В допълнение към кодирането на отделни кадри от статично изображение, алгоритъмът извежда текущия кадър от предишния и следващия, така че се изпраща само тяхната разлика. Както можете да видите от примера с Pacman, се предават само диференциални точки.

    Облачни игри с отворен код на WebRTC: p2p, мултиплейър, нулево забавяне
    Сравнение на видео кадри с помощта на Pacman като пример

    Аудио компресия

    По подобен начин алгоритъмът за аудио компресия пропуска данни, които не могат да бъдат възприети от хората. В момента Opus е най-добрият аудио кодек. Той е проектиран да предава аудио вълна през подреден протокол за дейтаграма като RTP (протокол за транспорт в реално време). Забавянето му е по-малко от това на mp3 и aac, а качеството е по-високо. Забавянето обикновено е около 5~66,5ms.

    Pion, WebRTC в Golang

    Пион е проект с отворен код, който пренася WebRTC в Golang. Вместо обичайното обвиване на нативни C++ WebRTC библиотеки, Pion е нативна реализация на Golang WebRTC с по-добра производителност, Go интеграция и контрол на версиите на WebRTC протоколи.

    Библиотеката също така предоставя поточно предаване на данни с много страхотни вградени модули със закъснение от по-малко от секунда. Има собствена реализация на STUN, DTLS, SCTP и др. и някои експерименти с QUIC и WebAssembly. Сама по себе си тази библиотека с отворен код е наистина добър източник на обучение със страхотна документация, реализации на мрежови протоколи и страхотни примери.

    Общността на Pion, водена от много страстен създател, е доста оживена и има много качествени дискусии за WebRTC. Ако се интересувате от тази технология, присъединете се http://pion.ly/slack - ще научите много нови неща.

    Писане на CloudRetro в Golang

    Облачни игри с отворен код на WebRTC: p2p, мултиплейър, нулево забавяне
    Работно внедряване в Go

    Go channels в действие

    С красивия дизайн на каналите на Go, проблемите с потока на събития и едновременността са значително опростени. Както на диаграмата, има няколко компонента, работещи паралелно в различни GoRoutine. Всеки компонент управлява собственото си състояние и комуникира чрез канали. Избирателното твърдение на Golang кара едно атомно събитие да се обработва всеки път в играта (отметка на играта). Това означава, че не е необходимо блокиране за този дизайн. Например, когато даден потребител е запазен, е необходима пълна моментна снимка на състоянието на играта. Това състояние трябва да остане непрекъснато, като влизате, докато записът приключи. По време на всеки тик на игра, бекендът може да обработва само операция за запазване или влизане, което прави процеса безопасен за нишката.

    func (e *gameEmulator) gameUpdate() {
    for {
    	select {
    		case <-e.saveOperation:
    			e.saveGameState()
    		case key := <-e.input:
    			e.updateGameState(key)
    		case <-e.done:
    			e.close()
    			return
    	}
        }
    }

    вентилатор навътре / вентилатор навън

    Този шаблон на Golang е чудесен за моя случай на използване на CrowdPlay и Multiple Player. Следвайки този модел, всички потребителски входове в една и съща стая са вградени в централния входен канал. След това медията на играта се разгръща за всички потребители в една и съща стая. По този начин постигаме разделяне на състоянието на играта между няколко игрови сесии на различни потребители.

    Облачни игри с отворен код на WebRTC: p2p, мултиплейър, нулево забавяне
    Синхронизация между различни сесии

    Недостатъци на Golang

    Голанг не е съвършен. Каналът е бавен. В сравнение с блокирането, Go каналът е просто по-лесен начин за обработка на едновременни и поточни събития, но каналът не осигурява най-добрата производителност. Под канала има сложна блокираща логика. Поради това направих някои корекции на внедряването чрез повторно прилагане на ключалки и атомарни стойности при смяна на канали, за да оптимизирам производителността.

    В допълнение, събирачът на боклук на Golang е неуправляем, което понякога причинява подозрително дълги паузи. Това значително пречи на приложението за стрийминг в реално време.

    COG

    Проектът използва съществуващата библиотека Golang с отворен код VP8/H264 за компресиране на медии и Libretro за емулатори на игри. Всички тези библиотеки са само обвивки за библиотеката C в Go COG. Някои от недостатъците са изброени в тази публикация Дейв Чейни. Проблеми, с които се сблъсках:

    • невъзможност за улавяне на срив в CGO, дори с Golang RecoveryCrash;
    • невъзможността да идентифицираме затруднение в производителността, когато не можем да открием детайлни проблеми в CGO.

    Заключение

    Постигнах целта си да разбера услугите за облачни игри и да създам платформа, която ми помага да играя носталгични ретро игри с моите приятели онлайн. Този проект не би бил възможен без библиотеката на Pion и подкрепата на общността на Pion. Изключително съм благодарен за интензивното му развитие. Простите API, предоставени от WebRTC и Pion, гарантират безпроблемна интеграция. Първото ми доказателство за концепцията беше пуснато същата седмица, въпреки че не бях наясно с комуникациите peer-to-peer (P2P) предварително.

    Въпреки лесната интеграция, P2P стриймингът наистина е много сложна област в компютърните науки. Той трябва да се справи със сложността на многогодишните мрежови архитектури като IP и NAT, за да създаде peer-to-peer сесия. Докато работих по този проект, натрупах много ценни знания за работата в мрежа и оптимизирането на производителността, така че препоръчвам на всеки да опита да изгради P2P продукти с помощта на WebRTC.

    CloudRetro се грижи за всички случаи на употреба, които очаквах от моята гледна точка на ретро геймър. Мисля обаче, че има много области в проекта, които мога да подобря, като например да направя мрежата по-надеждна и производителна, да предоставя по-високо качество на графиката на играта или възможността за споделяне на игри между потребителите. Работя усилено върху това. Моля последвайте проект и го подкрепете, ако го харесвате.

Източник: www.habr.com

Купете надежден хостинг за сайтове с DDoS защита, VPS VDS сървъри 🔥 Купете надежден уеб хостинг със защита от DDoS атаки, VPS VDS сървъри | ProHoster