最近在调研云游戏架构,一个比较基本的方式是在云服务器上运行游戏,数据流从云服务器到客户端,控制流从客户端到云服务器。
数据流是指音视频流,通过屏幕录制,声音抓取,将音视频推流发布出来,玩家和观战用户可以播放这些音视频流;
控制流是指玩家操控触屏、键盘、鼠标、游戏杆的指令序列,通过客户端发给云服务器,进而操控游戏。
当前云服务主流是用容器实现的,那用docker怎样录屏和推流呢?我查阅了一些资料,做了一些实验,描述如下:
首先启动Docker实例:
docker run -it -p 1935:1935 --mount type=bind,source=$(PWD)/../games,destination=/mnt gameserver:0.0.1
注意要端口映射一下,将实例中的1935端口映射到本地;
在Docker实例中安装必要软件:
apt-get install -y ffmpeg xvfb pulseaudio socat nginx libnginx-mod-rtmp
用Unity3D开发游戏:
输出成Linux x86_64格式,挂载到Docker实例中;
(注:在Edit菜单->
Project Settings...菜单项->
Player页->
Resolution and Presentation段->
Standalone Player Options节中,
将Display Resolution Dialog
设置成Disabled,否则每次运行游戏都弹出分辨率选择对话框)
启动虚拟的X Server:
Xvfb :44 -screen 0 800x600x24
其中800x600x24是设置分辨率和色彩,44是Server Number,这里使用44作为一个例子,后面会用到;
配置和启动带rtmp模块的nginx:
在/etc/nginx/nginx.conf中http段前加入
rtmp { server { listen 1935; chunk_size 4096; application live { live on; } }}
定义rtmp服务,端口1935已经在启动Docker实例的时候映射到Host机上了;
启动nginx服务
service nginx start
用普通用户身份运行如下命令:
pulseaudio -D --exit-idle-time=-1pacmd load-module module-virtual-sink sink_name=v1pacmd set-default-sink v1pacmd set-default-source v1.monitor
执行这些命令的目的是保证游戏使用声卡时不出问题(网上搜的,没仔细研究,本实验不涉及声音方面,游戏执行不因为声音出错就行);
启动游戏:
DISPLAY=:44 ./game_demo.x86_64
其中44是前面启动Xvfb时指定的Server Number,这样游戏就把图像通过虚拟的X Server输出了;
推流:
ffmpeg -f x11grab -s 800x600 -framerate 12 -i :44 -preset ultrafast -s 800x600 -threads 10 -codec:v h264 -f flv rtmp://localhost:1935/live/game_demo
其中x11grab表示录屏,两个800x600表示输入和输出的分辨率,framerate是帧率,44就是刚才启动游戏时使用的DISPLAY环境变量值,ultrafast是指定编码策略,threads表示线程数,视频编码用h264,输出rtmp流到nginx服务中;
也可以通过ffmpeg截取声音,加到rtmp推流中,这里省略了;
这个命令就把X中的桌面截取成视频流,发布出来,用支持rtmp的播放器就可以播放游戏视频了。
流程算是跑通了,效率真的是没法忍受,启动视频需要1分钟。由于没有控制流,游戏延迟就不能测试了(也不用测了,这么慢)。
上述实验用到了多个开源和免费的软件,仅为测试流程,性能优化不在实验范围之内。当然架构中还可以用更加高效的编码、推流技术,比如RTSP,WebRTC等,由于本人不是很熟悉,留待以后考察吧。
还有声音抓取,GPU加速,GPU虚拟化等等许多问题,都没有包含在本实验中,留待。。。
据报道,商用的云游戏服务已经开展起来了,专业的架构能够把延迟缩短到几十毫秒。相信云游戏的未来就在不远处。