1. 从“AnyPS5”这个名字说起:它到底想解决什么问题
第一次看到“AnyPS5”这个标题,我脑子里蹦出来的第一个念头是:这大概率是一个围绕“跨平台串流”或者“远程访问”做文章的项目。为什么这么判断?因为“Any”这个前缀在技术圈里几乎已经成了一个约定俗成的信号——它暗示着“打破边界”“跨设备”“不受限于原生环境”。而“PS5”则明确指向了游戏主机这个具体场景。把这两个词拼在一起,核心诉求就呼之欲出了:让玩家在非原生设备上也能访问和操作PS5的内容。
但这里必须先把话说清楚。我写这篇东西,不是要教任何人去绕过什么限制,也不是在讨论任何灰色地带的操作。我要聊的是这个标题背后所折射出的一个真实且普遍的技术需求:如何在不同硬件平台之间实现低延迟、高画质的音视频传输与交互控制。这个需求在云游戏、远程办公、在线教育、远程协助等领域都存在,而游戏主机场景只是其中对延迟和画质要求最苛刻的那一类。
所以,AnyPS5这个标题,我把它理解为一个“跨设备游戏串流方案”的代称。它要解决的问题很具体:你有一台性能强劲的主机放在客厅或者书房,但你人可能在卧室、在书房另一角、甚至在外地出差,你想用笔记本、平板、手机或者另一台显示器继续玩,不想搬主机,也不想再买一台。这个需求催生了一整套技术栈——从视频编码、网络传输、输入回传,到设备发现、配对认证、画面渲染,每一个环节都有讲究。
适合谁来参考这篇内容?三类人。第一类是对串流技术感兴趣、想自己动手搭一套低延迟远程游戏环境的技术爱好者。第二类是正在做远程桌面、云游戏、远程控制类产品的开发者,想了解游戏场景下的特殊优化点。第三类就是普通玩家,想搞清楚为什么有些串流方案用起来“跟本地一样”,有些却“卡成幻灯片”,以及自己该怎么选、怎么调。
接下来的内容,我会从整体设计思路、核心技术细节、实操搭建过程、常见问题排查四个大方向展开,中间会穿插大量我在实际折腾过程中踩过的坑和总结出来的参数经验。所有涉及具体工具和配置的地方,我都会给出可复现的步骤,但不会涉及任何违规或敏感的操作方式。
2. 整体设计思路与方案选型:为什么这样搭才靠谱
2.1 串流方案的核心矛盾:画质、延迟、成本三者不可兼得
任何串流方案,本质上都在解一道三元方程:画质、延迟、成本。你想要4K HDR 60帧,那码率至少得往30Mbps以上走,网络稍有波动就卡顿;你想要延迟低于20毫秒,那编码器必须用硬件加速,网络传输得走低延迟协议,缓冲队列要压到极小;你不想花钱升级网络和设备,那就只能在画质和延迟上做妥协。
我试过很多种组合,最后发现一个比较务实的平衡点是:1080P 60帧,码率15到20Mbps,端到端延迟控制在30到50毫秒之间。这个配置下,大部分快节奏游戏(比如射击、赛车)都能玩,画质也足够清晰,对网络的要求也不会太离谱。如果你追求4K,那网络必须非常稳定,而且客户端设备的解码能力也得跟上,否则解码延迟反而会成为瓶颈。
这里有个关键认知:串流的总延迟 = 采集延迟 + 编码延迟 + 网络传输延迟 + 解码延迟 + 显示延迟。很多人只盯着网络延迟,觉得换个好路由器就万事大吉,其实编码和解码的延迟往往才是大头。硬件编码器(比如显卡上的NVENC、AMF、QSV)能把编码延迟压到个位数毫秒,而软件编码(比如x264)在高质量预设下延迟可能超过20毫秒。解码端同理,客户端设备如果有硬件解码器,延迟会低很多。
2.2 为什么选择“主机端编码、客户端解码”的架构
AnyPS5这类方案,几乎都采用“主机端负责采集和编码,客户端负责解码和显示”的架构。这个选择不是随便定的,而是由物理条件决定的。主机的GPU性能远强于大多数客户端设备,让主机来做视频编码,效率最高。客户端只需要做解码和输入回传,负担轻,适配范围广。
具体到实现层面,主机端需要做几件事:抓取画面帧、编码成视频流、通过网络发送出去、接收客户端的输入指令并注入到系统。客户端需要做:接收视频流、解码、渲染显示、采集本地输入并回传。这个过程中,输入回传的延迟经常被忽略。你按下一个键,这个信号要经过网络传到主机,主机再注入,游戏再响应,这一圈下来如果网络不好,操作就会“粘手”。
我实测下来,输入回传走UDP比TCP好,因为TCP的重传机制在丢包时会导致输入延迟突然飙升,而UDP丢一两个包对操作的影响远小于延迟抖动。当然,UDP需要自己处理丢包和乱序,这是实现上的难点,但为了低延迟,这个代价值得。
2.3 工具选型:为什么我不推荐“一键包”
网上有很多“一键搭建串流”的脚本或者整合包,下载下来双击就能用。我早期也图省事用过,但后来全弃了。原因很简单:你不知道它背后做了什么,出了问题你无从排查。比如它可能默认用了软件编码,延迟高得离谱;可能开了垂直同步,导致画面撕裂或者额外延迟;可能网络缓冲区设得很大,平时看着流畅,一丢包就卡半天。
所以我更推荐手动搭建,哪怕多花点时间。手动搭建的好处是,每一个参数你都知道它为什么在那里,出了问题你能顺着链路一步步排查。常用的组件包括:视频采集用系统自带的桌面复制API或者第三方采集库,编码用FFmpeg或者各显卡厂商的SDK,传输用自研的UDP协议或者现成的低延迟传输库,客户端解码用FFmpeg或者系统原生解码器。
这里要特别提一下编码器的选择。如果你主机是N卡,优先用NVENC;A卡用AMF;Intel核显用QSV。这三个硬件编码器的延迟和画质各有千秋,NVENC的延迟最低,AMF的画质稍好但延迟略高,QSV介于两者之间。具体选哪个,得看你主机的显卡型号和驱动版本。我个人的经验是,NVENC在低码率下的画质损失比AMF小,但AMF在高码率下的细节保留更好。如果你用的是较新的显卡,三者差距其实不大,选你驱动支持最好的那个就行。
3. 核心细节解析与实操要点:从采集到显示的完整链路
3.1 视频采集:别小看这一步,坑最多
视频采集听起来很简单——把屏幕画面抓下来就行。但实际操作中,采集方式的选择直接影响延迟和兼容性。Windows平台上常见的采集方式有GDI、DXGI桌面复制、Windows Graphics Capture三种。GDI最老,兼容性最好,但性能最差,延迟高,而且抓不到全屏独占的游戏画面。DXGI桌面复制性能好,延迟低,但某些全屏独占游戏会黑屏。Windows Graphics Capture是较新的API,兼容性和性能都不错,但需要较新的系统版本。
我一般推荐用DXGI桌面复制,因为它在大多数场景下延迟最低。如果你玩的是全屏独占游戏,遇到黑屏问题,可以改成无边框窗口模式,或者换用Windows Graphics Capture。这里有个小技巧:采集帧率不要设得比显示器刷新率还高,比如你显示器是60Hz,采集设60帧就够了,设120帧只会增加编码负担,不会让画面更流畅。
还有一个容易被忽略的点:采集区域的裁剪。如果你只玩一个游戏,可以把采集区域限定在游戏窗口范围内,而不是全屏采集。这样编码器处理的像素少了,编码延迟和码率都会下降。我试过,在1080P屏幕上只采集一个720P的游戏窗口,编码延迟能降低30%左右。
3.2 视频编码:参数调优是门手艺
编码环节是延迟的大头,也是画质的关键。以NVENC为例,关键参数有这几个:码率控制模式、预设、GOP长度、B帧数量、参考帧数量。
码率控制模式我推荐CBR(恒定码率),而不是VBR。为什么?因为VBR在画面复杂时码率会飙升,网络扛不住就卡顿;画面简单时码率又降得很低,画质突然变糊。CBR虽然平均画质略低,但码率稳定,网络传输更可控。如果你网络特别好,可以用CBR加一个较高的码率上限,兼顾稳定和画质。
预设方面,NVENC有P1到P7七个预设,P1最快但画质最差,P7最慢但画质最好。串流场景我推荐P3或P4,延迟和画质的平衡点。P1虽然延迟最低,但画质损失肉眼可见,尤其是暗部细节和快速运动场景。P7的延迟增加明显,但画质提升在串流场景下感知不强,因为网络传输本身就会损失一些细节。
GOP长度建议设成帧率的一半到一倍。比如60帧,GOP设30到60。GOP太长,丢包时恢复慢;GOP太短,编码效率低,码率浪费在关键帧上。B帧数量建议设0到2,B帧能提升压缩效率,但会增加编码延迟。如果你追求极致低延迟,B帧设0;如果网络带宽紧张,B帧设2。
参考帧数量建议设1到3。参考帧越多,压缩效率越高,但解码端需要的缓冲也越大,延迟会增加。串流场景下,1到2个参考帧就够了。
3.3 网络传输:UDP是唯一的选择吗
网络传输环节,TCP和UDP的取舍是绕不开的话题。TCP有重传机制,丢包时会等待重传,导致延迟突然增大。对于游戏串流来说,延迟的稳定性比绝对延迟更重要。你宁可一直保持30毫秒延迟,也不要平时20毫秒、一丢包就跳到200毫秒。所以UDP是更合适的选择。
但UDP不保证可靠交付,需要自己处理丢包、乱序、重复包。常见的做法是:给每个包编号,接收端按编号重组,发现丢包时不是请求重传,而是直接丢弃那一帧,继续解码下一帧。因为视频流里相邻帧之间有关联,丢一帧会导致后续几帧也解不出来,所以通常需要定期发送关键帧(I帧)来恢复。关键帧的间隔就是前面说的GOP长度。
我实测下来,GOP设30到60,配合UDP传输,在5%丢包率下仍然能保持可玩的体验。如果丢包率超过10%,那就不是传输协议的问题了,得检查网络硬件或者换信道。
还有一个优化点:前向纠错(FEC)。在UDP基础上加一层FEC,发送端额外发送一些冗余包,接收端在丢包时可以用冗余包恢复出丢失的数据。FEC的代价是增加带宽消耗,但能显著降低丢包对画质的影响。我一般设10%到20%的FEC冗余,具体看网络质量。
3.4 输入回传:手感的关键
输入回传的延迟直接影响操作手感。你按下按键,到画面上出现反应,这个时间越短越好。我实测过,输入回传延迟超过50毫秒,就能感觉到明显的“粘手”;超过100毫秒,基本没法玩快节奏游戏。
输入回传的数据量很小,一个按键事件也就几个字节,所以带宽不是问题,关键是传输频率和注入方式。传输频率建议至少100Hz,也就是每10毫秒发送一次输入状态。注入方式上,Windows平台可以用SendInput API,Linux平台可以用uinput。注入延迟通常在1到5毫秒之间,可以接受。
这里有个坑:输入回传和视频传输最好走不同的端口或者不同的网络通道。如果混在一起,视频流的大包可能会阻塞输入小包,导致输入延迟抖动。我一般把输入回传走单独的UDP端口,并且设置更高的优先级。
4. 实操过程与核心环节实现:一步步搭一套可用的串流环境
4.1 主机端环境准备与配置
先说主机端。我假设你用的是一台Windows主机,显卡是N卡(其他显卡流程类似,只是编码器参数不同)。
第一步,确认你的显卡驱动是最新的。NVENC的功能和性能跟驱动版本关系很大,老驱动可能不支持某些编码特性。去显卡官网下载最新驱动,安装时选择“自定义安装”,勾选“执行清洁安装”,避免旧驱动残留。
第二步,安装FFmpeg。FFmpeg是整套方案的核心工具,负责采集、编码、传输。去官网下载Windows编译版,解压到一个没有中文和空格的路径下,比如C:\tools\ffmpeg。然后把C:\tools\ffmpeg\bin加到系统环境变量Path里,这样在命令行里直接输ffmpeg就能调用。
第三步,测试采集和编码。打开命令行,输入以下命令:
ffmpeg -f gdigrab -framerate 60 -i desktop -c:v h264_nvenc -preset p4 -tune ll -rc cbr -b:v 15M -g 60 -bf 0 -refs 1 -f mpegts udp://192.168.1.100:1234这条命令的意思是:用gdigrab采集桌面,60帧,用NVENC编码H.264,预设P4,低延迟调优,CBR模式,码率15Mbps,GOP 60,无B帧,1个参考帧,输出MPEG-TS格式到UDP地址192.168.1.100:1234。
注意,192.168.1.100要改成你客户端设备的IP地址。如果你只是想本地测试,可以改成127.0.0.1,然后用ffplay接收:
ffplay -fflags nobuffer -flags low_delay -framedrop udp://127.0.0.1:1234如果能看到画面,说明采集和编码没问题。如果报错,大概率是NVENC不可用,检查显卡是否支持NVENC,驱动是否安装正确。
4.2 客户端环境准备与配置
客户端可以是Windows、Linux、macOS,甚至是一些嵌入式设备。我以Windows客户端为例。
第一步,安装FFmpeg,步骤和主机端一样。
第二步,用ffplay接收视频流。命令就是上面那条:
ffplay -fflags nobuffer -flags low_delay -framedrop udp://192.168.1.100:1234-fflags nobuffer禁用缓冲,-flags low_delay启用低延迟模式,-framedrop在解码跟不上时丢帧而不是卡住。这三个参数是低延迟串流的关键。
第三步,测试延迟。最简单的办法是主机和客户端同时打开一个秒表网页,然后对比两个屏幕上的时间差。我实测下来,局域网内1080P 60帧的端到端延迟大概在40到60毫秒之间,其中编码延迟约10毫秒,网络传输约5毫秒,解码和显示约25到45毫秒。如果你用的是性能较弱的客户端设备,解码延迟可能会更高。
4.3 输入回传的实现
输入回传需要自己写一点代码,因为FFmpeg本身不处理输入注入。我用Python写了一个简单的示例,主机端监听UDP端口,收到输入事件后用pynput库注入。
主机端代码:
import socket from pynput.keyboard import Controller as KeyboardController from pynput.mouse import Controller as MouseController keyboard = KeyboardController() mouse = MouseController() sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.bind(('0.0.0.0', 1235)) while True: data, addr = sock.recvfrom(1024) event = data.decode('utf-8') if event.startswith('key:'): key = event.split(':')[1] keyboard.press(key) keyboard.release(key) elif event.startswith('mouse:'): x, y = map(int, event.split(':')[1].split(',')) mouse.position = (x, y)客户端代码:
import socket from pynput import keyboard, mouse sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) server_addr = ('192.168.1.100', 1235) def on_press(key): try: sock.sendto(f'key:{key.char}'.encode('utf-8'), server_addr) except AttributeError: pass def on_move(x, y): sock.sendto(f'mouse:{x},{y}'.encode('utf-8'), server_addr) keyboard_listener = keyboard.Listener(on_press=on_press) mouse_listener = mouse.Listener(on_move=on_move) keyboard_listener.start() mouse_listener.start() keyboard_listener.join()这段代码只是演示原理,实际使用中需要处理更多细节,比如按键的按下和释放要分开、鼠标移动要压缩、网络丢包要处理等等。但核心思路就是这样:客户端采集输入事件,通过UDP发给主机,主机注入。
4.4 参数调优实战:从“能看”到“能玩”
搭起来能看画面只是第一步,要调到“能玩”还需要不少调优。我列几个关键参数和我的推荐值:
| 参数 | 推荐值 | 说明 |
|---|---|---|
| 分辨率 | 1920x1080 | 4K对网络和解码要求太高,1080P是甜点 |
| 帧率 | 60 | 30帧在快节奏游戏里明显不够 |
| 码率 | 15-20Mbps | 低于10Mbps画质明显下降,高于30Mbps网络压力大 |
| 编码预设 | P4 | P1画质太差,P7延迟太高 |
| GOP | 60 | 对应60帧,每秒一个关键帧 |
| B帧 | 0 | 追求低延迟就关掉 |
| 参考帧 | 1 | 够用,多了增加解码延迟 |
| 传输协议 | UDP | TCP延迟抖动太大 |
| FEC冗余 | 10% | 网络好可以关,网络差可以加到20% |
调优的顺序建议是:先保证网络稳定,再调编码参数,最后微调客户端解码。网络不稳定的话,怎么调编码都没用。我一般先用ping和iperf测一下主机到客户端的网络质量,延迟低于5毫秒、丢包率低于1%才算合格。
5. 常见问题与排查技巧实录:那些年我踩过的坑
5.1 画面卡顿、花屏、黑屏
这是最常见的问题,原因可能有很多。我整理了一个排查表:
| 现象 | 可能原因 | 排查方法 | 解决方法 |
|---|---|---|---|
| 画面卡顿但声音正常 | 网络带宽不足或丢包 | 用iperf测带宽,用ping测丢包 | 降低码率,加FEC,换有线网络 |
| 画面花屏 | 丢包导致解码错误 | 看丢包率 | 加FEC,缩短GOP,换UDP |
| 全屏游戏黑屏 | 采集方式不兼容 | 换窗口模式测试 | 改无边框窗口,或换采集API |
| 画面延迟突然增大 | TCP重传或缓冲过大 | 检查传输协议和缓冲设置 | 换UDP,减小缓冲 |
| 客户端解码卡顿 | 客户端性能不足 | 看CPU/GPU占用 | 降低分辨率或帧率,启用硬件解码 |
我遇到最多的是网络丢包导致的花屏。一开始我以为是编码问题,调了半天编码参数没用,后来用Wireshark抓包才发现是无线网络丢包。换成有线之后,问题直接消失。所以排查问题一定要从底层往上查,先确认网络没问题,再查编码和解码。
5.2 输入延迟高、操作粘手
输入延迟高,通常有三个原因:网络传输延迟高、输入注入延迟高、视频延迟高导致的感觉偏差。
网络传输延迟高,检查主机和客户端之间的网络路径。如果是无线,换成有线;如果必须无线,确保信号强度足够,信道不拥挤。我实测过,2.4G频段的无线网络延迟抖动很大,5G频段好很多,但还是不如有线稳定。
输入注入延迟高,检查注入方式。SendInput API在大多数情况下延迟很低,但如果你用的是更老的keybd_event或者mouse_event,延迟会高一些。另外,如果主机CPU占用很高,注入线程可能被调度延迟,导致输入响应慢。
视频延迟高导致的感觉偏差,这个容易被忽略。如果视频延迟是50毫秒,你按下按键后,画面上要50毫秒后才出现反应,你会觉得是输入延迟,其实是视频延迟。解决办法就是降低视频延迟,前面说的编码参数调优就是干这个的。
5.3 画质模糊、暗部细节丢失
画质问题通常跟码率和编码参数有关。码率太低,画面细节会被压缩掉,尤其是快速运动的场景和暗部区域。我试过,1080P 60帧在10Mbps码率下,快速转动视角时画面会明显糊掉;提到15Mbps就好很多;20Mbps以上基本看不出区别。
暗部细节丢失是H.264编码的通病,因为人眼对暗部细节不敏感,编码器会把码率分配给亮部。如果你玩的游戏有很多暗场景(比如恐怖游戏),可以适当提高码率,或者换用H.265编码。H.265在相同码率下画质更好,但编码和解码延迟都更高,对客户端性能要求也更高。
还有一个技巧:在编码前对画面做轻微的锐化或者对比度增强,这样编码后的画面看起来更清晰。FFmpeg可以用unsharp滤镜:
ffmpeg -f gdigrab -framerate 60 -i desktop -vf "unsharp=5:5:0.8:3:3:0.4" -c:v h264_nvenc ...这个滤镜的参数需要根据你的显示器和游戏画面微调,调过头了会出现白边或者噪点。
5.4 音频不同步、爆音
音频问题在串流里也很常见。音频不同步通常是因为音频和视频走了不同的传输路径,延迟不一致。解决办法是把音频和视频混在一个流里传输,或者用时间戳做同步。
爆音通常是音频缓冲设置不当导致的。缓冲太小,网络抖动时音频会断;缓冲太大,延迟高而且容易爆音。我一般设20到50毫秒的音频缓冲,具体看网络质量。
FFmpeg采集音频可以用dshow或者wasapi:
ffmpeg -f dshow -i audio="你的音频设备名" -c:a aac -b:a 128k -f mpegts udp://...音频设备名可以在“声音设置”里查看,或者用ffmpeg -list_devices true -f dshow -i dummy列出所有设备。
6. 进阶优化与扩展思路:让串流更接近本地体验
6.1 硬件加速解码:客户端性能的关键
客户端解码如果走软件解码,CPU占用会很高,而且延迟大。启用硬件解码能显著降低CPU占用和解码延迟。FFmpeg支持多种硬件解码器,Windows上可以用D3D11VA或者DXVA2:
ffplay -hwaccel d3d11va -fflags nobuffer -flags low_delay -framedrop udp://...Linux上可以用VAAPI:
ffplay -hwaccel vaapi -vaapi_device /dev/dri/renderD128 -fflags nobuffer -flags low_delay -framedrop udp://...启用硬件解码后,客户端CPU占用能从50%以上降到10%以下,解码延迟也能降低10到20毫秒。如果你的客户端设备支持硬件解码,一定要开。
6.2 动态码率调整:应对网络波动
网络质量不是一成不变的,尤其是无线网络。动态码率调整可以根据网络状况实时调整编码码率,网络好时提高码率保证画质,网络差时降低码率保证流畅。
实现动态码率调整需要主机端和客户端之间有反馈通道。客户端定期把网络状况(丢包率、延迟)发回主机,主机根据这些信息调整编码器的码率参数。FFmpeg本身不直接支持动态码率调整,但可以通过发送信号或者重启编码器来实现。更优雅的方式是用FFmpeg的zmq滤镜或者自己写一个控制层。
我试过一个简单的方案:客户端每秒钟发一次丢包率给主机,主机如果发现丢包率超过5%,就把码率降低20%;如果丢包率低于1%持续5秒,就把码率提高10%。这个方案实现简单,效果也不错。
6.3 多客户端支持:一人串流,多人观看
有时候你可能想让多个设备同时观看同一个主机的画面。比如你在客厅玩游戏,卧室的电视也想显示同样的画面。这个需求可以通过多播或者多个UDP输出实现。
FFmpeg支持同时输出到多个UDP地址:
ffmpeg -f gdigrab -framerate 60 -i desktop -c:v h264_nvenc ... -f mpegts udp://192.168.1.100:1234 -f mpegts udp://192.168.1.101:1234但这样每个客户端都会占用一份带宽,如果客户端多了,网络压力会很大。更好的方式是用多播,主机只发一份数据,网络设备负责复制给多个客户端。但多播需要网络设备支持,配置也复杂一些。
6.4 录制与回放:串流之外的附加价值
串流环境搭好之后,顺便加个录制功能是很自然的扩展。FFmpeg可以在串流的同时把视频流保存到文件:
ffmpeg -f gdigrab -framerate 60 -i desktop -c:v h264_nvenc ... -f mpegts udp://... -c copy -f mp4 output.mp4-c copy表示不重新编码,直接复制视频流到文件,这样几乎不增加CPU负担。录制的文件可以用任何播放器回放,方便你回顾精彩操作或者排查问题。
我一般会把录制文件按时间分片,比如每10分钟一个文件,避免单个文件太大。FFmpeg的segment格式可以做到:
ffmpeg ... -f segment -segment_time 600 -reset_timestamps 1 output_%03d.mp4这样每10分钟生成一个文件,文件名带序号,管理起来很方便。
7. 我个人的一些经验体会
折腾串流这几年,最大的感受是:没有一套参数是万能的。不同的游戏、不同的网络、不同的设备,最优参数都不一样。你必须理解每个参数背后的原理,然后根据实际情况去调。比如同样是射击游戏,竞技类游戏对延迟极度敏感,你可以把码率降到10Mbps、关掉所有画质增强,只求最低延迟;而单人剧情游戏对画质要求高,你可以把码率提到25Mbps、开B帧和更多参考帧,延迟稍微高一点也能接受。
另一个体会是:网络质量比什么都重要。我见过太多人花大价钱升级显卡和CPU,结果用着几十块钱的路由器和劣质网线,串流体验一塌糊涂。如果你真的想认真搞串流,先把网络搞好——千兆有线网络、支持QoS的路由器、质量过关的网线,这些投入比升级显卡划算得多。
最后分享一个小技巧:用手机热点做应急串流。有时候出差在外,想用笔记本连家里的主机玩两把,手机热点虽然带宽不高,但延迟通常比酒店WiFi稳定。把码率降到5Mbps、分辨率降到720P,还是能玩的。当然,流量消耗要注意,一小时大概2到3GB。
这个方案后续还可以扩展的方向很多,比如加入手柄支持、做一套Web端的客户端、用WebRTC替代UDP传输以获得更好的NAT穿透能力。每一个方向都够写一篇长文,有机会再慢慢聊。