云游戏与边缘计算

用生活化的比喻,让你理解云游戏的技术架构、延迟挑战和边缘计算的价值

前置知识:网络基础、2_2_h5-rendering-mastery(渲染管线)


阅读指南(初学者必看)

为什么你需要了解云游戏?

你可能觉得云游戏离自己很远,但"不用下载就能玩"正在成为游戏分发的趋势。微信小游戏、抖音小游戏都已经在探索云端运行模式。理解云游戏架构,能帮你在游戏设计时做出更好的技术选择——哪些逻辑放客户端,哪些可以放云端。

学完本章,你能回答:

  • 云游戏的技术架构是怎样的?为什么延迟是最大挑战?
  • 视频编码(H.264/H.265/AV1)各有什么优劣?
  • WebRTC 在云游戏中扮演什么角色?
  • 边缘计算如何降低云游戏延迟?

本文结构

第一部分:云游戏架构(数据流与延迟分析)
第二部分:编码与传输(视频编码 + WebRTC + 边缘计算)
第三部分:客户端与服务端代码架构
第四部分:边缘调度与网络自适应

一、云游戏架构

生活类比:云游戏就像"远程桌面游戏"。游戏在远端服务器运行,画面像看直播一样传给你,你的操作像遥控器一样传回去。

云游戏数据流:

玩家设备                     云端服务器
────────                    ──────────
输入(按键/触屏)──────────▶ 游戏逻辑 → 渲染 → 编码
                                                  │
画面 ◀──────────────────── 视频流(H.264/H.265)
音频 ◀──────────────────── 音频流

关键指标:
- 编码延迟 <5ms
- 网络延迟 <30ms(边缘节点)
- 解码延迟 <5ms
- 总延迟 <50ms(可接受)

延迟拆解

用户按下按键 ──▶ 游戏响应 ──▶ 用户看到画面
     │              │              │
     │              │              │
  输入采集       游戏计算         视频解码
  (~1ms)        (~5ms)          (~5ms)
     │              │              │
  网络上行       渲染+编码        网络下行
  (~10ms)       (~15ms)         (~10ms)
     │              │              │
     └──────────────┴──────────────┘
              总延迟 ≈ 46ms(理想情况)
              实际通常 60~100ms

延迟感知:
< 50ms  → 几乎感觉不到
50~100ms → 动作游戏可感知,但可玩
100~200ms → 明显卡顿,不适合动作游戏
> 200ms → 无法正常游玩

云游戏 vs 本地游戏

维度 本地游戏 云游戏
硬件要求 需要好的GPU/CPU 只需解码能力
安装大小 几GB到几十GB 无需安装
网络要求 不需要/低 高(>20Mbps)
延迟 极低(<16ms) 较高(50~100ms)
画质 取决于本地硬件 取决于云端和带宽
作弊 容易修改本地数据 很难(逻辑在云端)
开发适配 多种硬件兼容 只需云端一套

二、编码与传输

2.1 视频编码对比

视频编码对比:
| 编码 | 压缩率 | 延迟 | 硬件支持 |
|------|--------|------|---------|
| H.264 | 基准 | 低 | 广泛 |
| H.265 | +50% | 中 | 较新 |
| AV1 | +30% | 高 | 新 |

生活类比:视频编码就像打包行李。H.264 是普通打包(快但占空间),H.265 是真空压缩(省空间但要时间),AV1 是最新的压缩黑科技(最省空间但要更多时间)。

编码格式 压缩效率 编码延迟 解码延迟 浏览器支持 游戏推荐
H.264 基准 ~3ms ~2ms ✅ 全部 ✅ 首选(兼容性好)
H.265 +50% ~5ms ~3ms ⚠️ 部分需硬件 大型3D游戏
AV1 +30% vs H.265 ~10ms ~5ms ⚠️ Chrome/Edge 未来方向

2.2 WebRTC 在云游戏中的角色

WebRTC 在云游戏中的角色:
- 传输协议:SRTP/DTLS
- 拥塞控制:自适应码率
- NAT 穿透:ICE/STUN/TURN

WebRTC 数据通道 vs 媒体通道:
┌─────────────────────────────────────┐
│            WebRTC 连接               │
│                                     │
│  媒体通道(SRTP)                    │
│  ├─ 视频流:游戏画面                  │
│  └─ 音频流:游戏音效                  │
│                                     │
│  数据通道(SCTP)                    │
│  ├─ 上行:玩家输入(按键/触屏)       │
│  └─ 下行:游戏状态同步               │
└─────────────────────────────────────┘

为什么用 WebRTC 而不是 HTTP?
- HTTP:请求→响应模式,延迟高(每次都要建连接)
- WebSocket:全双工,但没有内置拥塞控制和NAT穿透
- WebRTC:全双工 + 拥塞控制 + NAT穿透 + 低延迟编码

2.3 边缘计算

边缘计算:
- 部署离玩家最近的服务器
- 减少网络延迟
- CDN 节点 + GPU 渲染

传统云游戏 vs 边缘云游戏:

传统(中心化):           边缘化:
玩家 ──── 云端(北京)     玩家 ──── 边缘节点(本地机房)
  │         │                        │
  └── 延迟 50~100ms ──┘             └── 延迟 10~30ms ──┘

边缘节点部署策略:
1. 一线城市:延迟 <20ms
2. 二线城市:延迟 <40ms
3. 三线及以下:回源到最近节点,延迟 40~80ms

生活类比:边缘计算就像"外卖前置仓"。以前所有订单都从中央厨房出,现在在各社区设前置仓,离你更近,送得更快。


三、客户端与服务端代码架构

3.1 云游戏客户端架构

class CloudGameClient {
  constructor() {
    this.videoDecoder = new VideoDecoder();
    this.inputHandler = new InputHandler();
    this.display = new Display();
    this.frameBuffer = [];
    this.maxBufferSize = 3;
  }

  connect(serverUrl) {
    this.connection = new WebSocket(serverUrl);
    this.connection.onmessage = (event) => {
      this.handleMessage(JSON.parse(event.data));
    };
  }

  handleMessage(message) {
    switch (message.type) {
      case 'frame': this.handleFrame(message.data); break;
      case 'audio': this.handleAudio(message.data); break;
      case 'state': this.handleState(message.data); break;
    }
  }

  handleFrame(frameData) {
    this.frameBuffer.push(frameData);
    if (this.frameBuffer.length > this.maxBufferSize) {
      this.frameBuffer.shift();
    }
    this.displayFrame();
  }

  displayFrame() {
    if (this.frameBuffer.length === 0) return;
    let frame = this.frameBuffer.shift();
    this.videoDecoder.decode(frame).then(decoded => {
      this.display.render(decoded);
    });
  }

  sendInput(input) {
    if (this.connection?.readyState === WebSocket.OPEN) {
      this.connection.send(JSON.stringify({
        type: 'input', data: input, timestamp: Date.now()
      }));
    }
  }
}

3.2 云游戏服务端架构

class CloudGameServer {
  constructor() {
    this.gameEngine = new GameEngine();
    this.videoEncoder = new VideoEncoder();
    this.clients = new Map();
    this.frameRate = 60;
    this.resolution = { width: 1920, height: 1080 };
  }

  startGameLoop() {
    let frameInterval = 1000 / this.frameRate;
    setInterval(() => {
      this.processInputs();
      this.gameEngine.update();
      let frame = this.gameEngine.render(this.resolution);
      let encoded = this.videoEncoder.encode(frame);
      this.broadcastFrame(encoded);
    }, frameInterval);
  }

  broadcastFrame(encodedFrame) {
    for (let client of this.clients.values()) {
      client.connection.send(JSON.stringify({
        type: 'frame', data: encodedFrame, timestamp: Date.now()
      }));
    }
  }
}

四、边缘调度与网络自适应

4.1 边缘调度器

class EdgeScheduler {
  constructor() {
    this.nodes = new Map();
    this.clientAssignments = new Map();
  }

  addNode(node) {
    this.nodes.set(node.id, node);
  }

  findBestNode(clientLocation, requirements) {
    let candidates = [];
    for (let node of this.nodes.values()) {
      if (!node.canAccept()) continue;
      let latency = node.measureLatency(clientLocation);
      if (latency <= requirements.maxLatency) {
        candidates.push({ node, latency });
      }
    }
    candidates.sort((a, b) => a.latency - b.latency || a.node.currentLoad - b.node.currentLoad);
    return candidates[0]?.node;
  }

  assignClient(clientId, clientLocation, requirements) {
    let node = this.findBestNode(clientLocation, requirements);
    if (!node) return null;
    let gameId = `${clientId}_${Date.now()}`;
    let instance = node.startGameInstance(gameId, requirements);
    if (instance) {
      this.clientAssignments.set(clientId, { nodeId: node.id, gameId, startTime: Date.now() });
      return { nodeId: node.id, gameId, endpoint: `edge://${node.id}/${gameId}` };
    }
    return null;
  }
}

4.2 网络自适应码率

class NetworkAdaptation {
  constructor() {
    this.bandwidth = 0;
    this.latency = 0;
    this.packetLoss = 0;
    this.history = [];
  }

  measure(stats) {
    this.bandwidth = stats.bandwidth;
    this.latency = stats.latency;
    this.packetLoss = stats.packetLoss;
    this.history.push({ timestamp: Date.now(), ...stats });
    if (this.history.length > 30) this.history.shift();
  }

  getQuality() {
    let score = 100;
    if (this.latency > 50) score -= (this.latency - 50) / 2;
    if (this.packetLoss > 0.01) score -= this.packetLoss * 1000;
    return Math.max(0, Math.min(100, score));
  }

  getRecommendedSettings() {
    let quality = this.getQuality();
    if (quality >= 80) return { resolution: { width: 1920, height: 1080 }, bitrate: 8000000, fps: 60 };
    if (quality >= 60) return { resolution: { width: 1280, height: 720 }, bitrate: 4000000, fps: 60 };
    if (quality >= 40) return { resolution: { width: 854, height: 480 }, bitrate: 2000000, fps: 30 };
    return { resolution: { width: 640, height: 360 }, bitrate: 1000000, fps: 30 };
  }
}

自问自答

Q:云游戏会取代本地游戏吗? A:短期内不会。云游戏解决了硬件门槛和分发问题,但延迟是物理限制(光速)。对延迟敏感的动作游戏、竞技游戏,本地运行仍然是最优解。云游戏更适合 RPG、策略等对延迟不敏感的类型。

Q:5G 能解决云游戏延迟问题吗? A:部分解决。5G 降低了空口延迟(14ms),但端到端延迟还包括编解码和服务器处理。5G 让移动端云游戏成为可能,但总延迟仍在 3060ms 范围。

Q:H5 游戏和云游戏有什么关系? A:H5 游戏是在浏览器本地运行的,云游戏是在服务器运行、浏览器只负责解码视频。两者是不同的技术路线。但"即点即玩"的体验是相同的——云游戏是 H5 游戏在复杂3D场景下的补充方案。

Q:为什么云游戏不容易作弊? A:因为游戏逻辑完全在云端运行,客户端只接收视频流。玩家无法修改游戏内存、注入代码或截获网络包来作弊。这也是云游戏的一个安全优势。

Q:云游戏需要多少带宽? A:720p@30fps 约 35Mbps,1080p@60fps 约 1015Mbps,4K@60fps 约 25~35Mbps。编码效率越高,同等画质所需带宽越低。


实践任务

  • 任务1:体验腾讯 START 或网易云游戏平台,记录延迟感知和画质表现
  • 任务2:用 WebRTC 的 getDisplayMedia() 实现简易屏幕共享,理解媒体通道的工作方式
  • 任务3:对比 H.264 和 H.265 编码的视频质量和文件大小(用 FFmpeg 转码同一段视频)
  • 任务4:用 ping 测试你到不同云服务节点的延迟,理解边缘计算的位置优势
  • 任务5:设计一个简单的云游戏架构图(包含客户端、信令服务器、边缘渲染节点)
  • 任务6:实现一个网络自适应码率调节器,根据延迟和丢包率动态调整分辨率和码率

与其他章节的关联

本章内容 关联章节 关联点
视频编解码 第01章 WebAssembly深度 Wasm 可用于浏览器端软解码
延迟优化 第04章 图形学前沿 渲染优化减少编码前处理时间
WebRTC 4_1_game-architecture 网络通信架构设计
边缘计算 第05章 微信小游戏开发 小游戏的云端运行模式
串流架构 2_2_h5-rendering-mastery 渲染管线在云端的运行

上一章:01-WebAssembly深度 | 下一章:03-AI与游戏