{"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\/pt\/blog\/administrirovanie\/oblachnyj-gejming-s-otkrytym-ishodnym-kodom-na-webrtc-p2p-multipleer-zero-latency","title":{"rendered":"Jogos em nuvem com c\u00f3digo aberto no WebRTC: p2p, multiplayer, zero lat\u00eancia","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=\"Jogos em nuvem com c\u00f3digo aberto no WebRTC: p2p, multiplayer, zero lat\u00eancia\" src=\"\/wp-content\/uploads\/2020\/07\/22dbf7665d7fded15671d98a2afe599b.png\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><br \/>\nSaaS, IaaS, PaaS, plataforma de comunica\u00e7\u00e3o como servi\u00e7o, videoconfer\u00eancias como servi\u00e7o, e quanto aos jogos em nuvem como servi\u00e7o? J\u00e1 houve v\u00e1rias tentativas de criar jogos em nuvem, como o Stadia, recentemente lan\u00e7ado pela Google. Stadia <noindex><a rel=\"nofollow\" href=\"https:\/\/youtu.be\/avtlQeaxd_I?t=440\">n\u00e3o \u00e9 um novato no WebRTC<\/a><\/noindex>, mas outros podem usar o WebRTC da mesma forma?<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>Thanh Nguyen decidiu investigar essa possibilidade em seu projeto de c\u00f3digo aberto, CloudRetro. CloudRetro \u00e9 baseado no Pion, <noindex><a rel=\"nofollow\" href=\"https:\/\/webrtchacks.com\/webrtc-open-source-most-popular\/\">uma popular<\/a><\/noindex> biblioteca WebRTC escrita em Go (agradecimentos a <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/Sean-Der\">Shawn<\/a><\/noindex> do grupo de desenvolvedores do Pion pela ajuda na prepara\u00e7\u00e3o deste artigo). Neste artigo, Thanh faz uma vis\u00e3o geral da arquitetura de seu projeto e tamb\u00e9m compartilha o que aprendeu e quais desafios enfrentou durante o trabalho.<\/p>\n<h2>Introdu\u00e7\u00e3o<\/h2>\n<p>\nNo ano passado, quando a Google anunciou o Stadia, eu simplesmente fiquei impressionado. A ideia \u00e9 t\u00e3o \u00fanica e inovadora que eu continuamente me perguntava como isso era poss\u00edvel com as tecnologias atuais. O desejo de entender melhor o assunto me levou a criar minha pr\u00f3pria vers\u00e3o de um jogo em nuvem de c\u00f3digo aberto. O resultado foi simplesmente fant\u00e1stico. Abaixo, gostaria de compartilhar o processo de trabalho sobre meu projeto de um ano <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/giongto35\/cloud-game\">projeto<\/a><\/noindex>.<\/p>\n<p><i>TLDR: uma vers\u00e3o resumida dos principais pontos<\/i><\/p>\n<h3>Por que os jogos em nuvem s\u00e3o o futuro<\/h3>\n<p>\nAcredito que Cloud Gaming logo se tornar\u00e1 a nova gera\u00e7\u00e3o n\u00e3o apenas de jogos, mas tamb\u00e9m de outros campos da inform\u00e1tica. Jogos em nuvem representam o auge do modelo cliente\/servidor. Esse modelo maximiza o controle do backend e minimiza o trabalho do frontend, colocando a l\u00f3gica do jogo em um servidor remoto e transmitindo imagens\/\u00e1udio para o cliente. O servidor realiza o processamento pesado, portanto o cliente n\u00e3o depende mais das limita\u00e7\u00f5es de hardware.<\/p>\n<p>O Google Stadia, em ess\u00eancia, permite jogar <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)\">jogos AAA<\/a><\/noindex> (ou seja, games de alto n\u00edvel) em uma interface como o YouTube. A mesma metodologia pode ser aplicada a outros aplicativos pesados offline, como sistemas operacionais ou design gr\u00e1fico 2D\/3D, etc., permitindo que os executemos de forma est\u00e1vel em dispositivos com especifica\u00e7\u00f5es t\u00e9cnicas baixas em v\u00e1rias plataformas.<\/p>\n<p><img decoding=\"async\" alt=\"Jogos em nuvem com c\u00f3digo aberto no WebRTC: p2p, multiplayer, zero lat\u00eancia\" src=\"\/wp-content\/uploads\/2020\/07\/d6ca3e47db5c8e3d9880b304cc3be33b.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nO futuro dessa tecnologia: imagine se o Microsoft Windows 10 funcionasse no navegador Chrome?<\/p>\n<h3>Jogos em nuvem s\u00e3o tecnicamente complexos<\/h3>\n<p>\nO gaming \u00e9 uma das raras \u00e1reas em que uma r\u00e1pida rea\u00e7\u00e3o do usu\u00e1rio \u00e9 constantemente necess\u00e1ria. Se ocasionalmente encontramos um atraso de 2 segundos ao clicar na p\u00e1gina, isso \u00e9 aceit\u00e1vel. As transmiss\u00f5es de v\u00eddeo ao vivo geralmente t\u00eam um atraso de alguns segundos, mas ainda assim oferecem um uso suficientemente confort\u00e1vel. No entanto, se o jogo frequentemente demora 500 ms, jogar se torna imposs\u00edvel. Nosso objetivo \u00e9 alcan\u00e7ar uma lat\u00eancia extremamente baixa, para que a diferen\u00e7a entre a entrada e a m\u00eddia seja a menor poss\u00edvel. Portanto, a abordagem tradicional para transmiss\u00f5es de v\u00eddeo n\u00e3o se aplica aqui.<\/p>\n<p><img decoding=\"async\" alt=\"Jogos em nuvem com c\u00f3digo aberto no WebRTC: p2p, multiplayer, zero lat\u00eancia\" src=\"\/wp-content\/uploads\/2020\/07\/d73765a3c9277c026f407883e1091473.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nModelo geral de jogo em nuvem<\/p>\n<h2>Projeto de c\u00f3digo aberto CloudRetro<\/h2>\n<p>\nDecidi criar um prot\u00f3tipo de jogo em nuvem para testar se isso \u00e9 poss\u00edvel com restri\u00e7\u00f5es de rede t\u00e3o r\u00edgidas. Para a prova de conceito, escolhi Golang, pois \u00e9 a linguagem com a qual estou mais familiarizado e se adequa bem a essa implementa\u00e7\u00e3o por muitas raz\u00f5es, como se mostrou mais tarde. Go \u00e9 simples e se desenvolve rapidamente; os canais em Go s\u00e3o \u00f3timos para gerenciar a multitarefa.<\/p>\n<p>Projeto <noindex><a rel=\"nofollow\" href=\"http:\/\/cloudretro.io\/\">CloudRetro.io<\/a><\/noindex> \u2013 servi\u00e7o de jogos em nuvem de c\u00f3digo aberto para jogos retro. O objetivo do projeto \u00e9 trazer uma experi\u00eancia de jogo mais confort\u00e1vel para os tradicionais jogos retro e adicionar um modo multiplayer.<br \/>\nVoc\u00ea pode saber mais sobre o projeto aqui: <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/giongto35\/cloud-game\">https:\/\/github.com\/giongto35\/cloud-game<\/a><\/noindex>.<\/p>\n<h3>Funcionalidade do CloudRetro<\/h3>\n<p>\nPara demonstrar todo o poder dos jogos em nuvem, o CloudRetro utiliza jogos retro. Isso permite obter uma variedade de experi\u00eancias de jogo exclusivas.<\/p>\n<ul>\n<li>Portabilidade do jogo\n<ul>\n<li>Reprodu\u00e7\u00e3o instant\u00e2nea ao abrir a p\u00e1gina; downloads e instala\u00e7\u00f5es n\u00e3o s\u00e3o necess\u00e1rios<\/li>\n<li>Funciona em navegadores m\u00f3veis, portanto, nenhum software \u00e9 necess\u00e1rio para a execu\u00e7\u00e3o<\/li>\n<\/ul>\n<p>\n<\/li>\n<li>As sess\u00f5es de jogo podem ser compartilhadas em v\u00e1rios dispositivos e armazenadas na nuvem para o pr\u00f3ximo login<\/li>\n<li>O jogo pode ser transmitido, ou pode ser jogado instantaneamente por v\u00e1rios usu\u00e1rios:\n<ul>\n<li>Crowdplay tipo TwitchPlayPokemon, apenas mais multiplataforma e mais em tempo real<\/li>\n<li>Jogos offline online. Muitos usu\u00e1rios podem jogar sem configurar a rede. Em Samurai Shodown agora dois jogadores podem jogar pela rede CloudRetro<\/li>\n<\/ul>\n<p>\n<img decoding=\"async\" alt=\"Jogos em nuvem com c\u00f3digo aberto no WebRTC: p2p, multiplayer, zero lat\u00eancia\" src=\"\/wp-content\/uploads\/2020\/07\/bdc715971755d669a026f830ce888520.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nVers\u00e3o demo de um jogo multiplayer online em v\u00e1rios dispositivos<\/p>\n<h2>Infraestrutura<\/h2>\n<p><\/p>\n<h3>Requisitos e stack tecnol\u00f3gico<\/h3>\n<p>\nAbaixo est\u00e1 uma lista de requisitos que estabeleci antes do in\u00edcio do projeto.<\/p>\n<p><b>1. Um jogador<\/b><br \/>\nEste requisito pode parecer menos importante e \u00f3bvio aqui, mas \u00e9 uma das minhas principais conclus\u00f5es, permitindo que os jogos na nuvem se distanciem dos servi\u00e7os de streaming tradicionais. Se nos concentrarmos em jogos para um \u00fanico jogador, podemos nos livrar de um servidor centralizado ou CDN, pois n\u00e3o precisamos fazer streaming para um grande p\u00fablico. Em vez de carregar streams em um servidor massivo ou transmitir pacotes para um servidor WebSocket centralizado, os streams de servi\u00e7o s\u00e3o entregues diretamente ao usu\u00e1rio atrav\u00e9s de uma conex\u00e3o ponto a ponto usando WebRTC.<\/p>\n<p><b>2. Stream de m\u00eddia com baixa lat\u00eancia<\/b><br \/>\nAo ler sobre o Stadia, frequentemente encontro em alguns artigos men\u00e7\u00f5es ao WebRTC. Eu percebi que o WebRTC \u00e9 uma tecnologia excepcional e se encaixa perfeitamente no uso em jogos na nuvem. O WebRTC \u00e9 um projeto que fornece comunica\u00e7\u00e3o em tempo real para navegadores da web e aplicativos m\u00f3veis atrav\u00e9s de uma API simples. Ele proporciona uma conex\u00e3o ponto a ponto, otimizada para m\u00eddia, com codecs padr\u00e3o embutidos, como VP8 e H264.<\/p>\n<p>Eu priorizei garantir o m\u00e1ximo conforto para os usu\u00e1rios em vez de manter uma alta qualidade gr\u00e1fica. No algoritmo, algumas perdas s\u00e3o aceit\u00e1veis. O Google Stadia possui um passo adicional para reduzir o tamanho da imagem no servidor, e os quadros s\u00e3o escalonados para uma qualidade superior antes de serem enviados para os n\u00f3s ponto a ponto.<\/p>\n<p><b>3. Infraestrutura distribu\u00edda com roteamento geogr\u00e1fico<\/b><br \/>\nIndependentemente de qu\u00e3o otimizado seja o algoritmo de compress\u00e3o e o codec, a rede continua sendo um fator decisivo que mais contribui para a lat\u00eancia. A arquitetura deve ter um mecanismo de emparelhamento para o servidor mais pr\u00f3ximo do usu\u00e1rio, a fim de reduzir o tempo de ida e volta (RTT). A arquitetura deve ter 1 coordenador e v\u00e1rios servidores de streaming distribu\u00eddos pelo mundo: Oeste dos EUA, Leste dos EUA, Europa, Cingapura, China. Todos os servidores de streaming devem ser completamente isolados. O sistema pode ajustar sua distribui\u00e7\u00e3o quando um servidor ingressa ou sai da rede. Assim, em caso de grande tr\u00e1fego, a adi\u00e7\u00e3o de servidores adicionais permite a escalabilidade horizontal.<\/p>\n<p><b>4. Compatibilidade do navegador<\/b><br \/>\nOs jogos em nuvem brilham quando exigem o m\u00ednimo dos usu\u00e1rios. Isso significa que \u00e9 poss\u00edvel execut\u00e1-los no navegador. Navegadores ajudam a tornar a experi\u00eancia de jogo o mais confort\u00e1vel poss\u00edvel para os usu\u00e1rios, livrando-os da instala\u00e7\u00e3o de software e hardware. Eles tamb\u00e9m ajudam a garantir a compatibilidade entre plataformas para vers\u00f5es m\u00f3veis e desktop. Felizmente, o WebRTC \u00e9 bem suportado em v\u00e1rios navegadores.<\/p>\n<p><b>5. Separa\u00e7\u00e3o clara entre a interface de jogo e o servi\u00e7o<\/b><br \/>\nEu vejo o servi\u00e7o de jogos em nuvem como uma plataforma. Cada um deve ter a possibilidade de conectar o que quiser \u00e0 plataforma. No momento, integrei <noindex><a rel=\"nofollow\" href=\"http:\/\/LibRetro\">LibRetro<\/a><\/noindex> com o servi\u00e7o de jogos em nuvem, porque o LibRetro oferece uma bela interface de emulador de jogos para jogos retro, como SNES, GBA, PS.<\/p>\n<p><b>6. Salas para multiplayer, crowd play e link profundo com o jogo<\/b><br \/>\nCloudRetro suporta muitos novos estilos de jogo, como CrowdPlay e Multiplayer Online para jogos retro. Se v\u00e1rios usu\u00e1rios abrirem o mesmo link profundo em computadores diferentes, eles ver\u00e3o o mesmo jogo em execu\u00e7\u00e3o e at\u00e9 poder\u00e3o se juntar a ele.<\/p>\n<p>Al\u00e9m disso, os estados dos jogos s\u00e3o armazenados na nuvem. Isso permite que os usu\u00e1rios continuem jogando a qualquer momento em qualquer outro dispositivo.<\/p>\n<p><b>7. Escalabilidade horizontal<\/b><br \/>\nAssim como qualquer SAAS atualmente, os jogos em nuvem devem ser projetados para serem escal\u00e1veis horizontalmente. A estrutura 'coordenador-trabalhador' permite adicionar mais trabalhadores para atender a um tr\u00e1fego maior.<\/p>\n<p><b>8. Sem depend\u00eancia de uma \u00fanica nuvem<\/b><br \/>\nA infraestrutura do CloudRetro \u00e9 hospedada em v\u00e1rios provedores de nuvem (Digital Ocean, Alibaba, provedor personalizado) para diferentes regi\u00f5es. Eu ativo a execu\u00e7\u00e3o em um cont\u00eainer Docker para a infraestrutura e configuro os par\u00e2metros de rede usando um script Bash, para evitar a depend\u00eancia de um \u00fanico provedor de nuvem. Combinando isso com a travessia NAT no WebRTC, conseguimos obter flexibilidade para implantar o CloudRetro em qualquer plataforma de nuvem e at\u00e9 mesmo em m\u00e1quinas de qualquer usu\u00e1rio.<\/p>\n<h3>Design arquitet\u00f4nico<\/h3>\n<p>\n<b>Trabalhador:<\/b> (ou servidor de streaming mencionado acima) multiplica jogos, inicia o pipeline de codifica\u00e7\u00e3o e transmite a m\u00eddia codificada para os usu\u00e1rios. As inst\u00e2ncias do trabalhador s\u00e3o distribu\u00eddas globalmente, e cada trabalhador pode processar v\u00e1rias sess\u00f5es de usu\u00e1rio simultaneamente.<\/p>\n<p><b>Coordenador:<\/b> \u00e9 respons\u00e1vel por emparelhar um novo usu\u00e1rio com o trabalhador mais apropriado para o streaming. O coordenador interage com os trabalhadores via WebSocket.<\/p>\n<p><b>Armazenamento dos estados do jogo:<\/b> um armazenamento remoto central para todos os estados do jogo. Este armazenamento fornece fun\u00e7\u00f5es essenciais, como, por exemplo, salvar\/carregar remotamente.<\/p>\n<p><img decoding=\"async\" alt=\"Jogos em nuvem com c\u00f3digo aberto no WebRTC: p2p, multiplayer, zero lat\u00eancia\" src=\"\/wp-content\/uploads\/2020\/07\/985447b81350a640b0bd1344b5705113.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nArquitetura de alto n\u00edvel do CloudRetro<\/p>\n<h3>Cen\u00e1rio do usu\u00e1rio<\/h3>\n<p>\nQuando um novo usu\u00e1rio abre o CloudRetro nos passos 1 e 2 mostrados na figura abaixo, o coordenador junto com a lista de trabalhadores dispon\u00edveis \u00e9 chamado para a primeira p\u00e1gina. Em seguida, no passo 3, o cliente calcula as lat\u00eancias para todos os candidatos usando uma solicita\u00e7\u00e3o HTTP ping. Esta lista de lat\u00eancias \u00e9 ent\u00e3o enviada de volta ao coordenador, para que ele possa determinar o trabalhador mais apropriado para atender o usu\u00e1rio. No passo 4 abaixo, o jogo \u00e9 criado. Uma conex\u00e3o de streaming WebRTC \u00e9 estabelecida entre o usu\u00e1rio e o trabalhador designado.<br \/>\n<img decoding=\"async\" alt=\"Jogos em nuvem com c\u00f3digo aberto no WebRTC: p2p, multiplayer, zero lat\u00eancia\" src=\"\/wp-content\/uploads\/2020\/07\/00199b5942e3e4314609ec0e70ea7162.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nCen\u00e1rio do usu\u00e1rio ap\u00f3s receber acesso<\/p>\n<h3>O que h\u00e1 dentro do trabalhador<\/h3>\n<p>\nOs pipelines de jogos e streaming s\u00e3o armazenados dentro do trabalhador de forma isolada e trocam informa\u00e7\u00f5es l\u00e1 por meio de uma interface. Atualmente, essa comunica\u00e7\u00e3o \u00e9 realizada pela transmiss\u00e3o de dados na mem\u00f3ria atrav\u00e9s de <noindex><a rel=\"nofollow\" href=\"https:\/\/tour.golang.org\/concurrency\/2\">canais Golang<\/a><\/noindex> no mesmo processo. O pr\u00f3ximo objetivo \u00e9 a segrega\u00e7\u00e3o, ou seja, a execu\u00e7\u00e3o independente do jogo em outro processo.<\/p>\n<p><img decoding=\"async\" alt=\"Jogos em nuvem com c\u00f3digo aberto no WebRTC: p2p, multiplayer, zero lat\u00eancia\" src=\"\/wp-content\/uploads\/2020\/07\/7a90ec2638344467a34604cd4322165c.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nIntera\u00e7\u00e3o entre componentes do trabalhador<\/p>\n<p>Componentes principais:<\/p>\n<ul>\n<li><b>WebRTC:<\/b> componente do cliente, que recebe a entrada do usu\u00e1rio e transmite a m\u00eddia codificada do servidor.\n<\/li>\n<li><b>Emulador de jogo:<\/b> componente de jogo. Gra\u00e7as \u00e0 biblioteca Libretro, o sistema \u00e9 capaz de executar o jogo dentro do mesmo processo e interceptar internamente a m\u00eddia e o fluxo de entrada.\n<\/li>\n<li>Frames dentro do jogo s\u00e3o capturados e enviados ao codificador.\n<\/li>\n<li><b>Codificador de imagem\/audio:<\/b> pipeline de codifica\u00e7\u00e3o que recebe frames de m\u00eddia, os codifica em segundo plano e produz imagens\/audio codificados.\n<\/li>\n<\/ul>\n<p><\/p>\n<h2>Implementa\u00e7\u00e3o<\/h2>\n<p>\nO CloudRetro depende do WebRTC como sua tecnologia central; portanto, antes de me aprofundar nos detalhes da implementa\u00e7\u00e3o em Golang, decidi falar sobre o pr\u00f3prio WebRTC. \u00c9 uma tecnologia incr\u00edvel que me ajudou bastante a alcan\u00e7ar uma lat\u00eancia de transmiss\u00e3o de dados de apenas uma fra\u00e7\u00e3o de segundo.<\/p>\n<h3>WebRTC<\/h3>\n<p>\nWebRTC foi projetado para fornecer conex\u00f5es peer-to-peer de alta qualidade em aplicativos m\u00f3veis nativos e navegadores por meio de APIs simples.<\/p>\n<h4>NAT Traversal <\/h4>\n<p>\nO WebRTC \u00e9 conhecido por sua funcionalidade de NAT Traversal. Ele \u00e9 voltado para comunica\u00e7\u00e3o peer-to-peer. Seu objetivo \u00e9 encontrar a rota direta mais adequada, evitando gateways NAT e firewalls para comunica\u00e7\u00e3o peer-to-peer atrav\u00e9s de um processo chamado <noindex><a rel=\"nofollow\" href=\"https:\/\/webrtchacks.com\/trickle-ice\/\">ICE<\/a><\/noindex>. Durante esse processo, a API do WebRTC localiza seu endere\u00e7o IP p\u00fablico usando servidores STUN e o redireciona para um servidor de retransmiss\u00e3o (<noindex><a rel=\"nofollow\" href=\"https:\/\/webrtchacks.com\/?s=turn\">TURN<\/a><\/noindex>), quando uma conex\u00e3o direta n\u00e3o pode ser estabelecida.<\/p>\n<p>No entanto, o CloudRetro n\u00e3o utiliza completamente essa capacidade. Suas conex\u00f5es peer-to-peer n\u00e3o existem entre os usu\u00e1rios, mas entre os usu\u00e1rios e os servidores em nuvem. A parte do servidor do modelo tem menos restri\u00e7\u00f5es para a comunica\u00e7\u00e3o direta do que um dispositivo de usu\u00e1rio comum. Isso permite a abertura pr\u00e9via de portas de entrada ou o uso de endere\u00e7os IP p\u00fablicos diretamente, j\u00e1 que o servidor n\u00e3o est\u00e1 atr\u00e1s de um NAT.<\/p>\n<p>Eu j\u00e1 quis transformar o projeto em uma plataforma de distribui\u00e7\u00e3o de jogos para Cloud Gaming. A ideia era permitir que criadores de jogos oferecessem jogos e recursos de streaming, enquanto os usu\u00e1rios interagissem diretamente com os provedores. De uma maneira descentralizada, o CloudRetro \u00e9 apenas um meio de conectar recursos de streaming de terceiros aos usu\u00e1rios, tornando-o mais escal\u00e1vel quando n\u00e3o depende mais de hospedagem. O papel do NAT Traversal do WebRTC \u00e9 muito importante para facilitar a inicializa\u00e7\u00e3o da conex\u00e3o peer-to-peer com recursos de streaming de terceiros, simplificando a conex\u00e3o do criador \u00e0 rede.<\/p>\n<h4>Compress\u00e3o de v\u00eddeo<\/h4>\n<p>\nA compress\u00e3o de v\u00eddeo \u00e9 uma parte essencial do pipeline, que contribui significativamente para a fluidez do fluxo. Embora n\u00e3o seja necess\u00e1rio conhecer todos os detalhes da codifica\u00e7\u00e3o de v\u00eddeo em VP8\/H264, entender o conceito ajuda a lidar com as configura\u00e7\u00f5es de taxa de v\u00eddeo, depurar comportamentos inesperados e ajustar a lat\u00eancia.<\/p>\n<p>A compress\u00e3o de v\u00eddeo para servi\u00e7os de streaming \u00e9 uma tarefa complexa, pois o algoritmo deve garantir que o tempo total de codifica\u00e7\u00e3o + tempo de transmiss\u00e3o pela rede + tempo de decodifica\u00e7\u00e3o seja o menor poss\u00edvel. Al\u00e9m disso, o processo de codifica\u00e7\u00e3o deve ser cont\u00ednuo e consistente. Algumas concess\u00f5es no processo de codifica\u00e7\u00e3o n\u00e3o s\u00e3o aplic\u00e1veis \u2013 por exemplo, n\u00e3o podemos preferir um longo tempo de codifica\u00e7\u00e3o a um tamanho de arquivo menor e um tempo de decodifica\u00e7\u00e3o, ou utilizar uma compress\u00e3o inconsistente.<\/p>\n<p>A ideia da compress\u00e3o de v\u00eddeo \u00e9 eliminar bits desnecess\u00e1rios de informa\u00e7\u00e3o, mantendo um n\u00edvel aceit\u00e1vel de precis\u00e3o para os usu\u00e1rios. Al\u00e9m de codificar quadros de imagem est\u00e1ticos individuais, o algoritmo obt\u00e9m informa\u00e7\u00f5es sobre o quadro atual a partir do anterior e do pr\u00f3ximo, de forma que apenas suas diferen\u00e7as s\u00e3o enviadas. Como pode ser visto no exemplo com o Pacman, apenas os pontos diferenciais s\u00e3o transmitidos.<\/p>\n<p><img decoding=\"async\" alt=\"Jogos em nuvem com c\u00f3digo aberto no WebRTC: p2p, multiplayer, zero lat\u00eancia\" src=\"\/wp-content\/uploads\/2020\/07\/e452c54c53ab7797b610620aefbba8d2.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nCompara\u00e7\u00e3o de quadros de v\u00eddeo usando o exemplo do Pacman<\/p>\n<h4>Compress\u00e3o de \u00e1udio<\/h4>\n<p>\nDe maneira semelhante, o algoritmo de compress\u00e3o de \u00e1udio descarta dados que n\u00e3o podem ser percebidos pelo ser humano. O Opus \u00e9 atualmente o codec de \u00e1udio com o melhor desempenho. Ele foi projetado para transmitir ondas sonoras atrav\u00e9s de um protocolo de datagrama ordenado, como o RTP (Protocolo de Transporte em Tempo Real). Sua lat\u00eancia \u00e9 menor que a do mp3 e aac, e sua qualidade \u00e9 superior. A lat\u00eancia geralmente \u00e9 de cerca de 5~66,5 ms.<\/p>\n<h4>Pion, WebRTC em Golang<\/h4>\n<p>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/pion\/webrtc\">Pion<\/a><\/noindex> \u00e9 um projeto de c\u00f3digo aberto que traz WebRTC para o Golang. Em vez de simplesmente envolver bibliotecas nativas C++ do WebRTC, o Pion \u00e9 uma implementa\u00e7\u00e3o nativa do WebRTC em Golang, com melhor desempenho, integra\u00e7\u00e3o com Go e controle de vers\u00f5es nos protocolos WebRTC.<\/p>\n<p>A biblioteca tamb\u00e9m oferece streaming de dados com uma ampla gama de excelentes m\u00f3dulos embutidos, com uma lat\u00eancia de menos de um segundo. Ela possui sua pr\u00f3pria implementa\u00e7\u00e3o de STUN, DTLS, SCTP, etc., e algumas experimenta\u00e7\u00f5es com QUIC e WebAssembly. Essa biblioteca open source \u00e9 realmente uma boa fonte de aprendizado com documenta\u00e7\u00e3o excelente, implementa\u00e7\u00e3o de protocolos de rede e exemplos interessantes.<\/p>\n<p>A comunidade Pion, liderada por um criador muito apaixonado, \u00e9 bastante ativa, com muitas discuss\u00f5es de qualidade sobre WebRTC. Se voc\u00ea est\u00e1 interessado nessa tecnologia, junte-se a <noindex><a rel=\"nofollow\" href=\"http:\/\/pion.ly\/slack\">http:\/\/pion.ly\/slack<\/a><\/noindex> \u2013 voc\u00ea aprender\u00e1 muito.<\/p>\n<h3>Escrevendo CloudRetro em Golang<\/h3>\n<p>\n<img decoding=\"async\" alt=\"Jogos em nuvem com c\u00f3digo aberto no WebRTC: p2p, multiplayer, zero lat\u00eancia\" src=\"\/wp-content\/uploads\/2020\/07\/f85f7b8ea579fab964d870aad698c7e7.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nImplementa\u00e7\u00e3o de um worker em Go<\/p>\n<h4>Canais Go em a\u00e7\u00e3o<\/h4>\n<p>\nGra\u00e7as ao design elegante dos canais Go, problemas de streaming de eventos e paralelismo s\u00e3o significativamente simplificados. Como mostrado no diagrama, v\u00e1rios componentes operam em paralelo em diferentes GoRoutines. Cada componente gerencia seu pr\u00f3prio estado e se comunica atrav\u00e9s de canais. A afirma\u00e7\u00e3o seletiva do Golang for\u00e7a o processamento de um evento at\u00f4mico por vez a cada momento do jogo (game tick). Isso significa que, para esse design, n\u00e3o \u00e9 necess\u00e1ria nenhuma blokagem. Por exemplo, ao salvar, \u00e9 necess\u00e1rio um snapshot completo do estado do jogo. Esse estado deve permanecer cont\u00ednuo, realizando entradas at\u00e9 que o salvamento seja conclu\u00eddo. Durante cada game tick, o backend pode processar apenas a opera\u00e7\u00e3o de salvamento ou entrada, tornando o processo seguro para m\u00faltiplas threads.<\/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>\nEsse padr\u00e3o Golang se adapta perfeitamente ao meu caso de uso CrowdPlay e M\u00faltiplos Jogadores. Seguindo esse padr\u00e3o, todas as entradas dos usu\u00e1rios em uma sala s\u00e3o integradas em um canal de entrada central. A m\u00eddia do jogo \u00e9 ent\u00e3o distribu\u00edda para todos os usu\u00e1rios em uma \u00fanica sala. Isso nos permite compartilhar o estado do jogo entre v\u00e1rias sess\u00f5es de jogo de diferentes usu\u00e1rios.<\/p>\n<p><img decoding=\"async\" alt=\"Jogos em nuvem com c\u00f3digo aberto no WebRTC: p2p, multiplayer, zero lat\u00eancia\" src=\"\/wp-content\/uploads\/2020\/07\/000a495d7f214246a8a396aab11a3ac5.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nSincroniza\u00e7\u00e3o entre diferentes sess\u00f5es<\/p>\n<h4>Desvantagens do Golang<\/h4>\n<p>\nO Golang n\u00e3o \u00e9 perfeito. O canal \u00e9 lento. Comparado ao bloqueio, o canal Go \u00e9 simplesmente uma maneira mais f\u00e1cil de lidar com eventos paralelos e de fluxo, mas o canal n\u00e3o oferece o melhor desempenho. Sob o canal, h\u00e1 uma l\u00f3gica de bloqueio complexa. Portanto, fiz algumas altera\u00e7\u00f5es na implementa\u00e7\u00e3o, reaplicando bloqueios e valores at\u00f4micos ao substituir canais para otimizar o desempenho.<\/p>\n<p>Al\u00e9m disso, o coletor de lixo no Golang \u00e9 n\u00e3o gerenciado, o que \u00e0s vezes provoca pausas longas e suspeitas. Isso afeta significativamente o desempenho de um aplicativo de fluxo em tempo real.<\/p>\n<h4>CGO<\/h4>\n<p>\nO projeto utiliza uma biblioteca existente de c\u00f3digo aberto VP8\/H264 em Golang para compress\u00e3o de m\u00eddia e Libretro para emuladores de jogos. Todas essas bibliotecas s\u00e3o, na verdade, wrappers da biblioteca C em Go usando <noindex><a rel=\"nofollow\" href=\"https:\/\/golang.org\/cmd\/cgo\/\">CGO<\/a><\/noindex>. Algumas das desvantagens est\u00e3o listadas em <noindex><a rel=\"nofollow\" href=\"https:\/\/dave.cheney.net\/2019\/10\/06\/use-internal-packages-to-reduce-your-public-api-surface\">este post de Dave Cheney<\/a><\/noindex>. Os problemas que enfrentei:<\/p>\n<ul>\n<li>impossibilidade de capturar falhas no CGO, mesmo com o uso do Golang RecoveryCrash;<\/li>\n<li>impossibilidade de identificar o gargalo de desempenho quando n\u00e3o conseguimos detectar problemas detalhados no CGO.<\/li>\n<\/ul>\n<p><\/p>\n<h2>Conclus\u00e3o<\/h2>\n<p>\nAlcancei meu objetivo \u2013 entendi os servi\u00e7os de jogos em nuvem e criei uma plataforma que ajuda a jogar jogos retro nost\u00e1lgicos com meus amigos online. A cria\u00e7\u00e3o deste projeto seria imposs\u00edvel sem a biblioteca Pion e o apoio da comunidade Pion. Estou extremamente grato pelo seu intenso desenvolvimento. As APIs simples fornecidas pelo WebRTC e Pion permitiram uma integra\u00e7\u00e3o suave. Minha primeira prova de conceito foi lan\u00e7ada na mesma semana, mesmo sem saber com anteced\u00eancia sobre a conex\u00e3o peer-to-peer (P2P).<\/p>\n<p>Apesar da facilidade de integra\u00e7\u00e3o, streaming P2P \u00e9 de fato uma \u00e1rea muito complexa na ci\u00eancia da computa\u00e7\u00e3o. Tem que lidar com a complexidade de arquiteturas de rede que existem h\u00e1 anos, como IP e NAT para estabelecer uma sess\u00e3o peer-to-peer. Durante o trabalho neste projeto, acumulei muitos conhecimentos valiosos sobre redes e otimiza\u00e7\u00e3o de desempenho, por isso recomendo a todos que tentem construir produtos P2P usando WebRTC.<\/p>\n<p>O CloudRetro atende todos os cen\u00e1rios de uso que eu esperava, do ponto de vista de um jogador retro. No entanto, acredito que h\u00e1 muitas \u00e1reas no projeto que posso melhorar, como tornar a rede mais confi\u00e1vel e eficiente, garantir uma melhor qualidade gr\u00e1fica dos jogos ou a possibilidade de compartilhar jogos entre os usu\u00e1rios. Estou trabalhando arduamente nisso. Por favor, acompanhe <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/giongto35\/cloud-game\">projeto<\/a><\/noindex> e apoie-o se voc\u00ea gostar.<\/li>\n<\/ul>\n<p>Fonte: <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\/pt\/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=\"pt_PT\" \/>\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\/pt\/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\udd47Gaming em nuvem de c\u00f3digo aberto no WebRTC: p2p, multiplayer, zero lat\u00eancia | ProHoster","description":"","canonical_url":"https:\/\/prohoster.info\/pt\/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":"pt_PT","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\/pt\/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\/pt\/wp-json\/wp\/v2\/posts\/89303","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/comments?post=89303"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts\/89303\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/media\/89304"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/media?parent=89303"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/categories?post=89303"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/tags?post=89303"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}