{"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\/es\/blog\/administrirovanie\/oblachnyj-gejming-s-otkrytym-ishodnym-kodom-na-webrtc-p2p-multipleer-zero-latency","title":{"rendered":"Gaming en la nube de c\u00f3digo abierto en WebRTC: p2p, multijugador, cero latencia","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=\"Gaming en la nube de c\u00f3digo abierto en WebRTC: p2p, multijugador, cero latencia\" src=\"\/wp-content\/uploads\/2020\/07\/22dbf7665d7fded15671d98a2afe599b.png\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><br \/>\nEl software como servicio, infraestructura como servicio, plataforma como servicio, plataforma de comunicaci\u00f3n como servicio, videoconferencias como servicio, \u00bfy qu\u00e9 tal los juegos en la nube como servicio? Ya se han realizado varios intentos de crear juegos en la nube, como Stadia, que fue lanzado recientemente por Google. Stadia <noindex><a rel=\"nofollow\" href=\"https:\/\/youtu.be\/avtlQeaxd_I?t=440\">no es nuevo en WebRTC<\/a><\/noindex>, pero, \u00bfpueden otros usar WebRTC de la misma manera?<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>Thanh Nguyen decidi\u00f3 comprobar esta posibilidad en su proyecto de c\u00f3digo abierto CloudRetro. CloudRetro se basa en Pion, <noindex><a rel=\"nofollow\" href=\"https:\/\/webrtchacks.com\/webrtc-open-source-most-popular\/\">una biblioteca de<\/a><\/noindex> WebRTC popular basada en Go (gracias a <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/Sean-Der\">Shawn<\/a><\/noindex> del equipo de desarrolladores de Pion por ayudar con la preparaci\u00f3n de este art\u00edculo). En este art\u00edculo, Thanh revisa la arquitectura de su proyecto, as\u00ed como lo que ha aprendido y los desaf\u00edos que ha enfrentado durante su trabajo.<\/p>\n<h2>Introducci\u00f3n<\/h2>\n<p>\nEl a\u00f1o pasado, cuando Google anunci\u00f3 Stadia, simplemente me qued\u00e9 asombrado. La idea es tan \u00fanica e innovadora que me preguntaba constantemente c\u00f3mo era posible con la tecnolog\u00eda existente. El deseo de comprender mejor este tema me llev\u00f3 a crear mi propia versi\u00f3n de un juego en la nube de c\u00f3digo abierto. El resultado fue simplemente fant\u00e1stico. A continuaci\u00f3n, me gustar\u00eda compartir el proceso de trabajo sobre mi proyecto anual <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/giongto35\/cloud-game\">proyecto<\/a><\/noindex>.<\/p>\n<p><i>TLDR: versi\u00f3n corta en diapositivas con los puntos principales<\/i><\/p>\n<h3>Por qu\u00e9 el futuro est\u00e1 en los juegos en la nube<\/h3>\n<p>\nCreo que el Cloud Gaming pronto se convertir\u00e1 en la nueva generaci\u00f3n no solo de juegos, sino de otros campos de la inform\u00e1tica. Los juegos en la nube son la c\u00faspide del modelo cliente\/servidor. Este modelo maximiza el control del backend y minimiza el trabajo del frontend al colocar la l\u00f3gica del juego en un servidor remoto y transmitir im\u00e1genes\/audio al cliente. El servidor realiza el pesado procesamiento, por lo que el cliente ya no depende de las limitaciones de hardware.<\/p>\n<p>Google Stadia, en esencia, permite jugar <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)\">juegos AAA<\/a><\/noindex> (es decir, juegos de alto nivel) en una interfaz como YouTube. La misma metodolog\u00eda puede aplicarse a otras aplicaciones pesadas fuera de l\u00ednea, como sistemas operativos o dise\u00f1o gr\u00e1fico 2D\/3D, etc., para que podamos ejecutarlas de manera estable en dispositivos con caracter\u00edsticas t\u00e9cnicas bajas en diferentes plataformas.<\/p>\n<p><img decoding=\"async\" alt=\"Gaming en la nube de c\u00f3digo abierto en WebRTC: p2p, multijugador, cero latencia\" src=\"\/wp-content\/uploads\/2020\/07\/d6ca3e47db5c8e3d9880b304cc3be33b.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nEl futuro de esta tecnolog\u00eda: imagina si Microsoft Windows 10 funcionara en el navegador Chrome?<\/p>\n<h3>Los juegos en la nube son t\u00e9cnicamente complejos<\/h3>\n<p>\nLos videojuegos son una de esas pocas \u00e1reas donde se requiere una r\u00e1pida respuesta continua del usuario. Si de vez en cuando experimentamos un retraso de 2 segundos al hacer clic en una p\u00e1gina, eso es aceptable. Las transmisiones de video en vivo suelen tener algunos segundos de retraso, pero siguen brindando suficiente comodidad de uso. Sin embargo, si un juego se retrasa frecuentemente 500 ms, simplemente es imposible jugar. Nuestro objetivo es alcanzar una latencia extremadamente baja para que la brecha entre la entrada y el medio sea lo m\u00e1s peque\u00f1a posible. Por lo tanto, el enfoque tradicional de transmisi\u00f3n de video no es aplicable aqu\u00ed.<\/p>\n<p><img decoding=\"async\" alt=\"Gaming en la nube de c\u00f3digo abierto en WebRTC: p2p, multijugador, cero latencia\" src=\"\/wp-content\/uploads\/2020\/07\/d73765a3c9277c026f407883e1091473.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nPlantilla general de juegos en la nube<\/p>\n<h2>Proyecto de c\u00f3digo abierto CloudRetro<\/h2>\n<p>\nDecid\u00ed crear un prototipo de juego en la nube para verificar si esto era posible con tales restricciones de red. Para la prueba de concepto, eleg\u00ed Golang, ya que es el lenguaje que mejor manejo y se adapta bien a esta implementaci\u00f3n por muchas otras razones, como descubr\u00ed m\u00e1s tarde. Go es simple y evoluciona muy r\u00e1pidamente; los canales en Go son ideales para manejar la concurrencia.<\/p>\n<p>Proyecto <noindex><a rel=\"nofollow\" href=\"http:\/\/cloudretro.io\/\">CloudRetro.io<\/a><\/noindex> es un servicio de juegos en la nube de c\u00f3digo abierto para juegos retro. El objetivo del proyecto es aportar las experiencias de juego m\u00e1s agradables a los juegos retro tradicionales y a\u00f1adir multiplayer.<br \/>\nPuedes conocer m\u00e1s sobre el proyecto aqu\u00ed: <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/giongto35\/cloud-game\">https:\/\/github.com\/giongto35\/cloud-game<\/a><\/noindex>.<\/p>\n<h3>Funcionalidad de CloudRetro<\/h3>\n<p>\nPara demostrar todo el potencial de los juegos en la nube, CloudRetro utiliza juegos retro. Lo que permite obtener una gran cantidad de experiencias de juego \u00fanicas.<\/p>\n<ul>\n<li>Portabilidad del juego\n<ul>\n<li>Reproducci\u00f3n instant\u00e1nea al abrir la p\u00e1gina; no se requiere descarga ni instalaci\u00f3n<\/li>\n<li>Funciona en el navegador m\u00f3vil, por lo que no se necesita ning\u00fan software para comenzar<\/li>\n<\/ul>\n<p>\n<\/li>\n<li>Las sesiones de juego se pueden compartir en varios dispositivos y guardar en la nube para el pr\u00f3ximo inicio de sesi\u00f3n<\/li>\n<li>El juego se puede transmitir, y varios usuarios pueden jugarlo simult\u00e1neamente:\n<ul>\n<li>Crowdplay tipo TwitchPlayPokemon, solo que m\u00e1s multiplataforma y m\u00e1s en tiempo real<\/li>\n<li>Juegos offline en l\u00ednea. Muchos usuarios pueden jugar sin necesidad de configurar la red. En Samurai Shodown ahora pueden jugar 2 jugadores a trav\u00e9s de la nube CloudRetro<\/li>\n<\/ul>\n<p>\n<img decoding=\"async\" alt=\"Gaming en la nube de c\u00f3digo abierto en WebRTC: p2p, multijugador, cero latencia\" src=\"\/wp-content\/uploads\/2020\/07\/bdc715971755d669a026f830ce888520.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nVersi\u00f3n demo de un juego multijugador en l\u00ednea en diferentes dispositivos<\/p>\n<h2>Infraestructura<\/h2>\n<p><\/p>\n<h3>Requisitos y stack tecnol\u00f3gico<\/h3>\n<p>\nA continuaci\u00f3n se presenta una lista de requisitos que establec\u00ed antes de comenzar el proyecto.<\/p>\n<p><b>1. Un jugador<\/b><br \/>\nEste requisito puede parecer poco importante y obvio aqu\u00ed, pero es una de mis conclusiones clave, permite que los juegos en la nube se mantengan alejados de los servicios de streaming tradicionales. Si nos centramos en los videojuegos para un solo jugador, podemos prescindir de un servidor centralizado o un CDN, porque no necesitamos hacer streaming a las masas. En lugar de cargar flujos en un servidor absorbente o enviar paquetes a un servidor centralizado de WebSocket, los flujos de servicio se transmiten directamente al usuario a trav\u00e9s de una conexi\u00f3n peer-to-peer de WebRTC.<\/p>\n<p><b>2. Flujo de media de baja latencia<\/b><br \/>\nAl leer sobre Stadia, a menudo encuentro en algunos art\u00edculos menci\u00f3n de WebRTC. Me he dado cuenta de que WebRTC es una tecnolog\u00eda sobresaliente y se adapta perfectamente para su uso en juegos en la nube. WebRTC es un proyecto que proporciona a los navegadores web y aplicaciones m\u00f3viles comunicaci\u00f3n en tiempo real a trav\u00e9s de una API sencilla. Ofrece una conexi\u00f3n peer-to-peer, optimizada para medios y tiene c\u00f3decs est\u00e1ndar incorporados, como VP8 y H264.<\/p>\n<p>He preferido asegurarme de que los usuarios tengan la experiencia m\u00e1s c\u00f3moda posible, en lugar de mantener una alta calidad gr\u00e1fica. El algoritmo permite algunas p\u00e9rdidas. En Google Stadia hay un paso adicional para reducir el tama\u00f1o de la imagen en el servidor, y los fotogramas se escalan a una calidad m\u00e1s alta antes de ser enviados a los nodos peer-to-peer.<\/p>\n<p><b>3. Infraestructura distribuida con enrutamiento geogr\u00e1fico<\/b><br \/>\nSin importar cu\u00e1n optimizado est\u00e9 el algoritmo de compresi\u00f3n y el c\u00f3digo, la red sigue siendo el factor decisivo que m\u00e1s contribuye a la latencia. La arquitectura debe tener un mecanismo que conecte al servidor m\u00e1s cercano al usuario para reducir el tiempo de espera (RTT). La arquitectura debe tener 1 coordinador y varios servidores de streaming distribuidos por todo el mundo: Oeste de EE. UU., Este de EE. UU., Europa, Singapur, China. Todos los servidores de streaming deben estar completamente aislados. El sistema puede ajustar su distribuci\u00f3n cuando un servidor se une o sale de la red. As\u00ed, ante un alto tr\u00e1fico, la adici\u00f3n de servidores adicionales permite la escalabilidad horizontal.<\/p>\n<p><b>4. Compatibilidad del navegador<\/b><br \/>\nLos juegos en la nube brillan en su mejor forma cuando requieren un m\u00ednimo de esfuerzo por parte de los usuarios. Esto significa que es posible iniciar juegos en un navegador. Los navegadores ayudan a que la experiencia de juego sea lo m\u00e1s c\u00f3moda posible para los usuarios, liber\u00e1ndolos de la necesidad de instalar software y hardware. Adem\u00e1s, los navegadores facilitan la compatibilidad entre plataformas para versiones m\u00f3viles y de escritorio. Afortunadamente, WebRTC es ampliamente compatible con varios navegadores.<\/p>\n<p><b>5. Divisi\u00f3n clara entre la interfaz de juego y el servicio<\/b><br \/>\nConsidero el servicio de juegos en la nube como una plataforma. Todos deben tener la posibilidad de conectar cualquier cosa a la plataforma. Actualmente he integrado <noindex><a rel=\"nofollow\" href=\"http:\/\/LibRetro\">LibRetro<\/a><\/noindex> con el servicio de juegos en la nube, porque LibRetro ofrece una hermosa interfaz de emulador de juegos retro, como SNES, GBA, PS.<\/p>\n<p><b>6. Salas para multijugador, juego en grupo y enlace profundo (deep-link) con el juego<\/b><br \/>\nCloudRetro admite m\u00faltiples jugabilidades nuevas, como CrowdPlay y MultiJugador Online para juegos retro. Si varios usuarios abren el mismo deep-link en diferentes computadoras, ver\u00e1n el mismo juego en ejecuci\u00f3n y podr\u00e1n unirse a \u00e9l.<\/p>\n<p>Adem\u00e1s, los estados del juego se almacenan en la nube. Esto permite a los usuarios continuar jugando en cualquier momento desde cualquier otro dispositivo.<\/p>\n<p><b>7. Escalabilidad horizontal<\/b><br \/>\nAl igual que cualquier SAAS en la actualidad, los juegos en la nube deben estar dise\u00f1ados para ser escalables horizontalmente. La arquitectura 'coordinador-trabajador' permite agregar m\u00e1s trabajadores para manejar mayor tr\u00e1fico.<\/p>\n<p><b>8. Sin dependencia de una sola nube<\/b><br \/>\nLa infraestructura de CloudRetro se aloja en diferentes proveedores de la nube (Digital Ocean, Alibaba, proveedor personalizado) para diferentes regiones. Activo la ejecuci\u00f3n en contenedores Docker para la infraestructura y configuro los par\u00e1metros de red mediante un script de bash, evitando as\u00ed la dependencia de un solo proveedor de la nube. Combinando esto con NAT Traversal en WebRTC, podemos lograr flexibilidad para desplegar CloudRetro en cualquier plataforma en la nube e incluso en m\u00e1quinas de cualquier usuario.<\/p>\n<h3>Dise\u00f1o arquitect\u00f3nico<\/h3>\n<p>\n<b>Trabajador:<\/b> (o servidor de flujo mencionado anteriormente) multiplica los juegos, ejecuta el pipeline de codificaci\u00f3n y transmite los medios codificados a los usuarios. Las instancias de trabajo se distribuyen por todo el mundo, y cada trabajador puede manejar m\u00faltiples sesiones de usuario simult\u00e1neamente.<\/p>\n<p><b>Coordinador:<\/b> se encarga de asignar un nuevo usuario al trabajador m\u00e1s adecuado para la transmisi\u00f3n. El coordinador interact\u00faa con los trabajadores a trav\u00e9s de WebSocket.<\/p>\n<p><b>Almacenamiento de estados del juego:<\/b> un almacenamiento remoto central para todos los estados del juego. Este almacenamiento proporciona funciones cr\u00edticas como la carga\/salida remota.<\/p>\n<p><img decoding=\"async\" alt=\"Gaming en la nube de c\u00f3digo abierto en WebRTC: p2p, multijugador, cero latencia\" src=\"\/wp-content\/uploads\/2020\/07\/985447b81350a640b0bd1344b5705113.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nArquitectura de CloudRetro de alto nivel<\/p>\n<h3>Escenario del usuario<\/h3>\n<p>\nCuando un nuevo usuario abre CloudRetro en los pasos 1 y 2, mostrados en la figura a continuaci\u00f3n, se solicita al coordinador, junto con la lista de trabajadores disponibles, que muestre la primera p\u00e1gina. Luego, en el paso 3, el cliente calcula las latencias para todos los candidatos mediante una solicitud HTTP ping. Esta lista de latencias se env\u00eda de vuelta al coordinador, para que pueda determinar el trabajador m\u00e1s adecuado para atender al usuario. En el paso 4 a continuaci\u00f3n, se crea el juego. Se establece una conexi\u00f3n de streaming WebRTC entre el usuario y el trabajador asignado.<br \/>\n<img decoding=\"async\" alt=\"Gaming en la nube de c\u00f3digo abierto en WebRTC: p2p, multijugador, cero latencia\" src=\"\/wp-content\/uploads\/2020\/07\/00199b5942e3e4314609ec0e70ea7162.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nEscenario del usuario despu\u00e9s de obtener acceso<\/p>\n<h3>Qu\u00e9 hay dentro del trabajador<\/h3>\n<p>\nLos pipelines de juegos y streaming se almacenan dentro del trabajador de manera aislada y se intercambian informaci\u00f3n a trav\u00e9s de una interfaz. En este momento, esta conexi\u00f3n se realiza mediante la transmisi\u00f3n de datos en memoria a trav\u00e9s de <noindex><a rel=\"nofollow\" href=\"https:\/\/tour.golang.org\/concurrency\/2\">canales Golang<\/a><\/noindex> en el mismo proceso. El siguiente objetivo es la segregaci\u00f3n, es decir, ejecutar el juego de manera independiente en otro proceso.<\/p>\n<p><img decoding=\"async\" alt=\"Gaming en la nube de c\u00f3digo abierto en WebRTC: p2p, multijugador, cero latencia\" src=\"\/wp-content\/uploads\/2020\/07\/7a90ec2638344467a34604cd4322165c.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nInteracci\u00f3n de componentes del trabajador<\/p>\n<p>Componentes principales:<\/p>\n<ul>\n<li><b>WebRTC:<\/b> componente del cliente que recibe la entrada del usuario y proporciona los medios codificados del servidor.\n<\/li>\n<li><b>Emulador de juegos:<\/b> componente del juego. Gracias a la biblioteca Libretro, el sistema puede ejecutar un juego dentro del mismo proceso y capturar internamente los medios y el flujo de entrada.\n<\/li>\n<li>Los fotogramas dentro del juego son capturados y enviados al codificador.\n<\/li>\n<li><b>Codificador de imagen\/audio:<\/b> pipeline de codificaci\u00f3n que recibe los fotogramas de media, los codifica en segundo plano y produce im\u00e1genes\/audio codificados.\n<\/li>\n<\/ul>\n<p><\/p>\n<h2>Implementaci\u00f3n<\/h2>\n<p>\nCloudRetro se basa en WebRTC como su tecnolog\u00eda principal, por lo que antes de profundizar en los detalles de la implementaci\u00f3n en Golang, decid\u00ed hablar sobre WebRTC. Es una tecnolog\u00eda incre\u00edble que me ha ayudado a lograr una latencia de transmisi\u00f3n de datos de solo una fracci\u00f3n de segundo.<\/p>\n<h3>WebRTC<\/h3>\n<p>\nWebRTC est\u00e1 dise\u00f1ado para proporcionar conexiones P2P de alta calidad en aplicaciones m\u00f3viles nativas y en navegadores a trav\u00e9s de API simples.<\/p>\n<h4>NAT Traversal <\/h4>\n<p>\nWebRTC es conocido por su funcionalidad de NAT Traversal. WebRTC est\u00e1 destinado a la comunicaci\u00f3n entre pares. Su objetivo es encontrar la ruta directa m\u00e1s adecuada, evitando gateways NAT y cortafuegos para la comunicaci\u00f3n P2P a trav\u00e9s de un proceso llamado <noindex><a rel=\"nofollow\" href=\"https:\/\/webrtchacks.com\/trickle-ice\/\">ICE<\/a><\/noindex>. En este proceso, las API de WebRTC encuentran tu direcci\u00f3n IP p\u00fablica a trav\u00e9s de servidores STUN y la reenv\u00edan a un servidor de retransmisi\u00f3n (<noindex><a rel=\"nofollow\" href=\"https:\/\/webrtchacks.com\/?s=turn\">TURN<\/a><\/noindex>), cuando no se puede establecer una conexi\u00f3n directa.<\/p>\n<p>Sin embargo, CloudRetro no utiliza completamente esta capacidad. Sus conexiones P2P no existen entre usuarios, sino entre usuarios y servidores en la nube. La parte del servidor del modelo tiene menos restricciones sobre la comunicaci\u00f3n directa que un dispositivo de usuario t\u00edpico. Esto permite abrir puertos entrantes de manera anticipada o utilizar direcciones IP p\u00fablicas directamente, ya que el servidor no est\u00e1 detr\u00e1s de NAT.<\/p>\n<p>Antes quer\u00eda convertir el proyecto en una plataforma de distribuci\u00f3n de juegos para Cloud Gaming. La idea era permitir a los creadores de juegos proporcionar juegos y recursos de transmisi\u00f3n. Los usuarios interactuar\u00edan directamente con los proveedores. De esta manera descentralizada, CloudRetro es solo un medio para conectar recursos de transmisi\u00f3n de terceros con los usuarios, lo que lo hace m\u00e1s escalable, ya que ya no depende de un hosting. El papel de NAT Traversal de WebRTC es muy importante para facilitar la inicializaci\u00f3n de conexiones P2P en recursos de transmisi\u00f3n de terceros, simplificando la conexi\u00f3n de los creadores a la red.<\/p>\n<h4>Compresi\u00f3n de video<\/h4>\n<p>\nLa compresi\u00f3n de video es una parte indispensable del pipeline, que contribuye significativamente a la fluidez del streaming. Aunque no es necesario conocer todos los detalles de la codificaci\u00f3n de video en VP8\/H264, entender el concepto ayuda a comprender los par\u00e1metros de velocidad del video en streaming, a depurar comportamientos inesperados y a ajustar la latencia.<\/p>\n<p>La compresi\u00f3n de video para servicios de streaming es una tarea compleja, porque el algoritmo debe garantizar que el tiempo total de codificaci\u00f3n + el tiempo de transmisi\u00f3n por la red + el tiempo de decodificaci\u00f3n sea lo m\u00e1s bajo posible. Adem\u00e1s, el proceso de codificaci\u00f3n debe ser consistente y continuo. Algunos compromisos durante la codificaci\u00f3n no son aplicables; por ejemplo, no podemos preferir un largo tiempo de codificaci\u00f3n a un tama\u00f1o de archivo m\u00e1s peque\u00f1o y a un tiempo de decodificaci\u00f3n, o utilizar una compresi\u00f3n inconsistente.<\/p>\n<p>La idea de la compresi\u00f3n de video es eliminar bits de informaci\u00f3n innecesarios, manteniendo al mismo tiempo un nivel aceptable de precisi\u00f3n para los usuarios. Adem\u00e1s de codificar fotogramas est\u00e1ticos individuales, el algoritmo deduce el fotograma actual de los anteriores y siguientes, enviando solo su diferencia. Como se puede ver en el ejemplo con Pacman, solo se env\u00edan los puntos diferenciales.<\/p>\n<p><img decoding=\"async\" alt=\"Gaming en la nube de c\u00f3digo abierto en WebRTC: p2p, multijugador, cero latencia\" src=\"\/wp-content\/uploads\/2020\/07\/e452c54c53ab7797b610620aefbba8d2.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nComparaci\u00f3n de fotogramas de video usando Pacman<\/p>\n<h4>Compresi\u00f3n de audio<\/h4>\n<p>\nDe manera similar, el algoritmo de compresi\u00f3n de audio omite datos que no pueden ser percibidos por el ser humano. Opus es, hasta el momento, el c\u00f3dec de audio con mejor rendimiento. Est\u00e1 dise\u00f1ado para transmitir ondas de audio a trav\u00e9s de un protocolo de datagramas ordenados, como RTP (Protocolo de Transporte en Tiempo Real). Su latencia es menor que la de mp3 y aac, y su calidad es superior. La latencia suele ser de alrededor de 5 a 66,5 ms.<\/p>\n<h4>Pion, WebRTC en Golang<\/h4>\n<p>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/pion\/webrtc\">Pion<\/a><\/noindex> es un proyecto de c\u00f3digo abierto que trae WebRTC a Golang. En lugar de envolver las bibliotecas nativas de C++ de WebRTC, Pion es una implementaci\u00f3n nativa de WebRTC en Golang con mejor rendimiento, integraci\u00f3n con Go, y control de versiones sobre los protocolos de WebRTC.<\/p>\n<p>La biblioteca tambi\u00e9n proporciona transmisi\u00f3n de datos con muchos excelentes m\u00f3dulos integrados y una latencia de menos de un segundo. Tiene su propia implementaci\u00f3n de STUN, DTLS, SCTP, etc. y algunos experimentos con QUIC y WebAssembly. En s\u00ed misma, esta biblioteca de c\u00f3digo abierto es realmente una buena fuente de aprendizaje con excelente documentaci\u00f3n, implementaci\u00f3n de protocolos de red y grandes ejemplos.<\/p>\n<p>La comunidad Pion, liderada por un creador muy apasionado, es bastante activa, se llevan a cabo muchas discusiones de calidad sobre WebRTC. Si te interesa esta tecnolog\u00eda, \u00fanete a <noindex><a rel=\"nofollow\" href=\"http:\/\/pion.ly\/slack\">http:\/\/pion.ly\/slack<\/a><\/noindex> \u2013 aprender\u00e1s mucho nuevo.<\/p>\n<h3>Escribiendo CloudRetro en Golang<\/h3>\n<p>\n<img decoding=\"async\" alt=\"Gaming en la nube de c\u00f3digo abierto en WebRTC: p2p, multijugador, cero latencia\" src=\"\/wp-content\/uploads\/2020\/07\/f85f7b8ea579fab964d870aad698c7e7.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nImplementaci\u00f3n de un worker en Go<\/p>\n<h4>Canales Go en acci\u00f3n<\/h4>\n<p>\nGracias al hermoso dise\u00f1o de los canales Go, los problemas de transmisi\u00f3n de eventos y paralelismo se simplifican significativamente. Como en el diagrama, varios componentes operan en paralelo en diferentes GoRoutines. Cada componente gestiona su propio estado y se comunica a trav\u00e9s de canales. La instrucci\u00f3n selectiva de Golang obliga a procesar un solo evento at\u00f3mico a la vez en el juego (game tick). Esto significa que para este dise\u00f1o no se requiere bloqueo. Por ejemplo, cuando un usuario guarda, se necesita una instant\u00e1nea completa del estado del juego. Este estado debe mantenerse continuo, ejecutando entradas hasta que el proceso de guardado se complete. Durante cada game tick, el backend puede manejar solo la operaci\u00f3n de guardado o entrada, lo que hace que el proceso sea seguro para subprocesos.<\/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>\nEste patr\u00f3n de Golang se adapta perfectamente a mi caso de uso de CrowdPlay y M\u00faltiples Jugadores. Siguiendo este patr\u00f3n, todas las entradas de usuario en una habitaci\u00f3n se integran en un canal de entrada central. Los medios del juego luego se distribuyen a todos los usuarios en la misma habitaci\u00f3n. De este modo, logramos la separaci\u00f3n del estado del juego entre varias sesiones de juego de diferentes usuarios.<\/p>\n<p><img decoding=\"async\" alt=\"Gaming en la nube de c\u00f3digo abierto en WebRTC: p2p, multijugador, cero latencia\" src=\"\/wp-content\/uploads\/2020\/07\/000a495d7f214246a8a396aab11a3ac5.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nSincronizaci\u00f3n entre diversas sesiones<\/p>\n<h4>Desventajas de Golang<\/h4>\n<p>\nGolang no es perfecto. El canal es lento. En comparaci\u00f3n con el bloqueo, el canal Go es simplemente una forma m\u00e1s sencilla de manejar eventos paralelos y de flujo, pero el canal no ofrece el mejor rendimiento. Detr\u00e1s del canal hay una l\u00f3gica de bloqueo compleja. Por lo tanto, hice algunos ajustes en la implementaci\u00f3n, reaplicando bloqueos y valores at\u00f3micos al sustituir canales para optimizar el rendimiento.<\/p>\n<p>Adem\u00e1s, el recolector de basura en Golang es no gestionado, lo que a veces provoca pausas sospechosamente largas. Esto dificulta mucho el rendimiento de aplicaciones en tiempo real.<\/p>\n<h4>CGO<\/h4>\n<p>\nEl proyecto utiliza una biblioteca existente VP8\/H264 de Golang de c\u00f3digo abierto para la compresi\u00f3n de medios y Libretro para emuladores de videojuegos. Todas estas bibliotecas son simplemente envoltorios de la biblioteca C en Go usando <noindex><a rel=\"nofollow\" href=\"https:\/\/golang.org\/cmd\/cgo\/\">CGO<\/a><\/noindex>. Algunos de los inconvenientes se enumeran en <noindex><a rel=\"nofollow\" href=\"https:\/\/dave.cheney.net\/2019\/10\/06\/use-internal-packages-to-reduce-your-public-api-surface\">esta publicaci\u00f3n de Dave Cheney<\/a><\/noindex>. Los problemas que encontr\u00e9:<\/p>\n<ul>\n<li>imposibilidad de capturar un fallo en CGO, incluso con Golang RecoveryCrash;<\/li>\n<li>imposibilidad de identificar el cuello de botella en el rendimiento, cuando no podemos detectar problemas detallados en CGO.<\/li>\n<\/ul>\n<p><\/p>\n<h2>Conclusi\u00f3n<\/h2>\n<p>\nLogr\u00e9 mi objetivo: entend\u00ed los servicios de juegos en la nube y cre\u00e9 una plataforma que ayuda a jugar juegos retro nost\u00e1lgicos con mis amigos en l\u00ednea. La creaci\u00f3n de este proyecto no habr\u00eda sido posible sin la biblioteca Pion y el apoyo de la comunidad Pion. Estoy extremadamente agradecido por su desarrollo intensivo. Las API simples proporcionadas por WebRTC y Pion permitieron una integraci\u00f3n fluida. Mi primera prueba de concepto se lanz\u00f3 en la misma semana, a pesar de que no sab\u00eda con antelaci\u00f3n sobre la conexi\u00f3n punto a punto (P2P).<\/p>\n<p>A pesar de la simplicidad de la integraci\u00f3n, la transmisi\u00f3n P2P es realmente un \u00e1rea muy compleja en la inform\u00e1tica. Se enfrenta a la complejidad de arquitecturas de red de muchos a\u00f1os, como IP y NAT, para crear una sesi\u00f3n peer-to-peer. A lo largo de mi trabajo en este proyecto, acumul\u00e9 mucho conocimiento valioso sobre redes y optimizaci\u00f3n del rendimiento, as\u00ed que recomiendo a todos intentar construir productos P2P utilizando WebRTC.<\/p>\n<p>CloudRetro atiende todos los escenarios de uso que esperaba, desde mi perspectiva como jugador retro. Sin embargo, creo que hay muchas \u00e1reas en el proyecto que puedo mejorar, como hacer la red m\u00e1s confiable y eficiente, proporcionar una mejor calidad gr\u00e1fica en los juegos o permitir el intercambio de juegos entre usuarios. Estoy trabajando arduamente en ello. Por favor, est\u00e9n atentos a <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/giongto35\/cloud-game\">proyecto<\/a><\/noindex> y apoyen el proyecto si les gusta.<\/li>\n<\/ul>\n<p>Fuente: <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.2 - 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\/es\/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.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"es_ES\" \/>\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\/es\/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 en la nube de c\u00f3digo abierto en WebRTC: p2p, multijugador, cero latencia | ProHoster","description":"","canonical_url":"https:\/\/prohoster.info\/es\/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":"es_ES","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\/es\/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\/es\/wp-json\/wp\/v2\/posts\/89303","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/comments?post=89303"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts\/89303\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/media\/89304"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/media?parent=89303"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/categories?post=89303"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/tags?post=89303"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}