docker 怀旧游戏 docker game_ffmpeg rtsp推流


最近在调研云游戏架构,一个比较基本的方式是在云服务器上运行游戏,数据流从云服务器到客户端,控制流从客户端到云服务器。

数据流是指音视频流,通过屏幕录制,声音抓取,将音视频推流发布出来,玩家和观战用户可以播放这些音视频流;

控制流是指玩家操控触屏、键盘、鼠标、游戏杆的指令序列,通过客户端发给云服务器,进而操控游戏。

当前云服务主流是用容器实现的,那用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虚拟化等等许多问题,都没有包含在本实验中,留待。。。

据报道,商用的云游戏服务已经开展起来了,专业的架构能够把延迟缩短到几十毫秒。相信云游戏的未来就在不远处。