SSD Nodes Learn Hosting plans →
指南 Matt Connor作者: Matt Connor · 更新于 2026-09-28

如何在 VPS 上自托管视频会议系统?

自托管视频会议的核心挑战在于 SFU 架构导致的带宽二次方增长。本文详细对比 Jitsi、BigBlueButton 和 Galène 的内存需求与 NAT 穿透问题,并提供带宽计算公式,助你根据参会人数精准选择 VPS 配置,避免会议中途卡顿或掉线。

在 VPS 上自托管视频会议面临带宽瓶颈

在小型服务器上自托管视频会议失败,原因通常只有一个,且几乎从不是安装过程的问题。现代工具普遍使用的核心组件是 SFU(选择性转发单元)。它接收每位参与者的一路视频流,并将其副本转发给其他所有参与者,因此服务器的出口流量会随着参与人数的平方呈指数级增长。1 GB 或 2 GB 内存的 VPS 在共享上行链路下运行软件本身没问题,但无法承载你所预想的全员会议。

因此,请按以下顺序开展工作:先统计人数,计算所需带宽(Mbps),再选择服务器规格。安装过程只需 20 分钟的复制粘贴,但上行链路带宽决定了会议是否能够正常进行。

为什么带宽需求会随参与者人数的平方增长?

从 Mesh 架构开始分析。每个浏览器都会对摄像头画面进行编码,并直接向其他所有浏览器发送一份副本,中间没有任何媒体服务器处理视频。两人间的 Mesh 通话仅需一个信令服务器,因此一对一通话的托管成本几乎为零。当参与者达到四到五人时,Mesh 架构便无法正常工作,因为家用网络环境下的笔记本电脑必须同时上传四到五份独立的视频副本。

SFU(选择性转发单元)的工作方式则不同。每个浏览器仅向服务器上传一份副本。服务器读取 RTP(实时传输协议)报头,并在不解码视频的情况下将数据包转发给其他参与者。这就是 SFU 的核心机制,也是它 CPU 占用低但网络负载高的原因。

较旧的架构是 MCU(多点控制单元)。它会解码每一个传入的流,将其合成一张画面,并重新编码该画面。其出站带宽需求极小,但 CPU 开销巨大。目前几乎没有任何视频服务使用 MCU,本指南中也不涉及。

现在计算 SFU 的带宽需求。假设每个人发送的视频码率为 1.2 Mbps,且没有人关闭摄像头。服务器接收的总流量为 N 乘以 1.2 Mbps,这是线性的,不会造成问题。但服务器发送的总流量为 N 乘以 (N 减 1) 乘以 1.2 Mbps,因为 N 个参与者中的每一个人都需要接收其他 N 减 1 个流。正是这个二次方增长的数值决定了项目的成败。

ChartSFU outbound traffic, arithmetic model at 1.2 Mbps per sender
The data behind this chart
[
  {
    "label": "4 people",
    "sfu_egress_mbps": 14.4,
    "egress_gb_per_hour": 6.5,
    "monthly_volume_tb": 0.13
  },
  {
    "label": "8 people",
    "sfu_egress_mbps": 67.2,
    "egress_gb_per_hour": 30.2,
    "monthly_volume_tb": 0.6
  },
  {
    "label": "15 people",
    "sfu_egress_mbps": 252,
    "egress_gb_per_hour": 113.4,
    "monthly_volume_tb": 2.3
  },
  {
    "label": "30 people",
    "sfu_egress_mbps": "1,044",
    "egress_gb_per_hour": 469.8,
    "monthly_volume_tb": 9.4
  },
  {
    "label": "50 people",
    "sfu_egress_mbps": "2,940",
    "egress_gb_per_hour": "1,323",
    "monthly_volume_tb": 26.5
  }
]

上述表格中的数据为算术计算结果,并非针对特定服务器的测量值。月度流量列假设每月通话时长为 20 小时。请先查看最后一行。50 人同时开启摄像头需要单台机器提供 2,940 Mbps 的持续出站流量。30 人需要 1,044 Mbps。4 人仅需 14.4 Mbps,任何 VPS 都能轻松处理。从 4 人到 30 人,参与人数增长了 7.5 倍,而出站流量却增长了 70 多倍。

实际部署中的流量通常低于这些数值,了解原因至关重要。Jitsi 和 LiveKit 都使用联播(Simulcast):发送端同时发布多个质量层,SFU 仅向未在屏幕上显示的用户转发低质量层。Jitsi 还具有 last-N 设置,仅转发最近发言者的视频。两者都能显著节省流量。但它们都无法改变流量增长曲线的形态,且一旦所有人开启摄像头并相互固定显示,这些优化措施将不再起作用。

VPS 上行链路的实际意义是什么?

套餐页面标注的 “1 Gbps 端口” 指的是虚拟网卡的速率,而非对下一跳带宽的承诺。该链路与同一物理宿主机上的其他租户共享,因此高峰时段的持续吞吐量会低于端口速率,而视频会议正是典型的持续负载。大多数套餐还设有每月流量限额,超出后会被限速或额外计费。

该限额是账单中成本激增的来源。一个月内进行 20 小时 30 人的通话,服务器将产生 9.4 TB 的出站流量,即每小时 469.8 GB。而 20 小时 50 人的通话则会产生 26.5 TB 的流量。在查看内存配置前,请务必先确认流量限额;如果套餐页面对此描述模糊,这种模糊本身就是答案。对于此类工作负载,正确解读廉价 VPS 套餐比其他任何因素都更为重要。

Jitsi Meet:默认选择及其需求

大多数人应从 Jitsi Meet 开始。它通过项目自带的 Debian 软件源安装,安装过程中会自动配置 Nginx 和证书,且视频桥(JVB)仅使用单个 UDP 端口,这简化了防火墙规则。它需要 Debian 11 或更高版本,或者 Ubuntu 22.04 或更高版本。

sudo apt update
sudo apt install -y apt-transport-https curl gnupg
sudo add-apt-repository universe
sudo apt update
sudo curl -sL https://prosody.im/files/prosody-debian-packages.key -o /usr/share/keyrings/prosody-debian-packages.key
echo "deb [signed-by=/usr/share/keyrings/prosody-debian-packages.key] http://packages.prosody.im/debian $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/prosody-debian-packages.list
sudo apt install -y lua5.2
curl -sL https://download.jitsi.org/jitsi-key.gpg.key | sudo sh -c 'gpg --dearmor > /usr/share/keyrings/jitsi-keyring.gpg'
echo "deb [signed-by=/usr/share/keyrings/jitsi-keyring.gpg] https://download.jitsi.org stable/" | sudo tee /etc/apt/sources.list.d/jitsi-stable.list
sudo apt update
sudo apt install -y jitsi-meet

安装程序会询问主机名,随后提供证书选项。请选择 Let's Encrypt 选项,并提供一个已解析到该服务器公网地址的域名。证书通过 HTTP 挑战进行签发,因此如果域名指向其他地址,该步骤将会失败。

接着开放端口。以下是手册中记录的端口,请先开放 SSH,以免 ufw enable 将你锁定在系统之外:

sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 10000/udp
sudo ufw allow 3478/udp
sudo ufw allow 5349/tcp
sudo ufw enable

TCP 80 和 443 端口用于提供 Web 应用服务并允许证书续期。UDP 10000 端口承载所有音视频流量,这是最容易被遗忘的端口。UDP 3478 和 TCP 5349 属于 Jitsi 软件包随桥接器一同安装的 coturn 服务器,这是当用户网络屏蔽 UDP 时的备用路径。

sudo systemctl status jitsi-videobridge2
sudo ss -ulnp | grep 10000

第一条命令应显示服务处于 active 状态。第二条命令应显示桥接器正在监听 UDP 10000 端口。如果没有任何输出,说明桥接器未启动,此时 /var/log/jitsi/jvb.log 将会说明原因。

关于规模估算,Jitsi 手册发布了其建议的起始配置,而 BigBlueButton 则发布了规模更大的建议:

ChartSizing each project publishes for one production server
The data behind this chart
[
  {
    "label": "Jitsi Meet",
    "ram_gb": 8,
    "cpu_cores": 4,
    "uplink_mbps": "1,000"
  },
  {
    "label": "BigBlueButton 3.0",
    "ram_gb": 16,
    "cpu_cores": 8,
    "uplink_mbps": 250
  }
]

Jitsi 手册建议生产级服务器配置 8 GB 内存和 4 个专用核心,通常 1,000 Mbps 的网络带宽即可满足需求;手册同时指出,较小规模的部署可在 4 GB 或 2 GB 内存下运行。该页面中有一个细节值得注意:负责处理信令的 XMPP 服务器 Prosody 仅能使用一个核心。增加核心数对桥接器有帮助,但对信令处理没有提升。

为什么所有人都能加入通话但看不到视频?

这是 Jitsi 在 VPS 上常见的故障。参与者列表正常显示,聊天功能可用,但所有视频窗口均为黑色。videobridge 会广播其在自身接口上发现的地址。如果服务商为虚拟机分配了私有地址并将其映射到公网地址,JVB 只能识别到私有地址。因此,所有客户端都会尝试将媒体流发送到类似 10.0.0.5 的地址,导致数据包无法送达。

需要告知网桥这两个地址。在 /etc/jitsi/videobridge/jvb.conf 中添加静态映射:

ice4j {
  harvest {
    mapping {
      static-mappings = [
        {
          local-address = "10.0.0.5"
          public-address = "203.0.113.10"
        }
      ]
    }
  }
}

使用 sudo systemctl restart jitsi-videobridge2 重启服务。从 ip -4 addr show 获取本地地址,从服务商控制面板获取公网地址。旧版指南在 /etc/jitsi/videobridge/sip-communicator.properties 中通过 org.ice4j.ice.harvest.NAT_HARVESTER_LOCAL_ADDRESS 和 org.ice4j.ice.harvest.NAT_HARVESTER_PUBLIC_ADDRESS 键进行相同设置。这些设置依然有效,但新安装应使用上述映射块。

另一个原因是防火墙未配置。大多数服务商在控制面板中提供独立于系统内 ufw 的网络防火墙,必须确保 UDP 10000 端口在两者中均已开放。要确定是哪一层丢弃了数据包,请在有人从外部加入时在服务器上运行 sudo tcpdump -ni any udp port 10000。如果完全没有数据包,说明流量未到达机器,阻断发生在操作系统上游。如果数据包已到达但视频窗口仍为黑色,说明网桥返回的地址客户端无法访问,这是映射问题。如果您不确定 ufw 本身的配置,VPS 实际所需的 ufw 规则 涵盖了容易导致问题的规则排序。

BigBlueButton:体量庞大、架构固化,且需独占服务器

BigBlueButton 专为教学场景设计。它内置白板、分组讨论室、投票和演示区域,录制流水线是其核心功能而非附加组件。它是此处所有选项中资源消耗最大的,且不能作为软件包安装在现有服务器上。

截至 2026 年 8 月,官方支持的路径是在 Ubuntu 22.04 上部署 BigBlueButton 3.0,需使用 jammy-300 版本标志进行选择。该项目的生产环境要求为 16 GB 内存(需开启 swap)、8 个高单核性能的 CPU 核心、250 Mbps 对称带宽,以及 500 GB 磁盘空间(若禁用录制功能则需 50 GB)。所需端口为 TCP 80 和 443,以及 UDP 16384 到 32768 范围。

wget -q https://raw.githubusercontent.com/bigbluebutton/bbb-install/v3.0.x-release/bbb-install.sh
less bbb-install.sh
bash bbb-install.sh -w -v jammy-300 -s bbb.example.com -e info@example.com -g

该项目提供的示例直接将脚本通过管道传输给 bash。请务必先下载并阅读脚本内容,因为它会重写 nginx 配置、安装专属的媒体和音频栈、锁定软件包版本并接管主机名。这是其设计使然而非缺陷:BigBlueButton 要求独占整台机器。-w 标志用于配置防火墙,-s 为主机名,-e 为 Let's Encrypt 注册的地址,-g 用于添加 Greenlight 前端。如果同一台服务器还为其他服务处理 TLS 终止,请将 BigBlueButton 迁移至其他机器,或在脚本修改配置前确保你完全理解 你的 nginx 反向代理配置逻辑。

请仔细对比图表中的两行数据。BigBlueButton 对内存和 CPU 核心的要求是 Jitsi 建议值的两倍,而带宽要求仅为后者的四分之一。由于两者的衡量标准不同且假设的会议室规模有异,请将这些数据视为各自项目的起点,而非直接的同类对比。CPU 性能差距是客观存在的,这源于 BigBlueButton 在视频转发之外执行的大量额外任务。

Galène:轻量级方案

Galène 是一个用 Go 编写的紧凑型 SFU。它编译为单个静态二进制文件,自带 Web 客户端,并内置了 TURN 服务器,因此无需维护 XMPP 服务器、Java 运行时或 Rails 应用。如果你的需求是在一台配置一般的机器上进行可靠的 10 人通话,请先尝试此方案,再考虑是否需要更高性能的硬件。

sudo apt update && sudo apt install -y git golang-go
git clone https://github.com/jech/galene
cd galene
CGO_ENABLED=0 go build -ldflags='-s -w'
mkdir groups

Ubuntu 24.04 上的 golang-go 软件包版本为 Go 1.22。如果 go build 提示模块需要更新版本的 Go,请直接从 go.dev 安装当前的工具链,不要试图去适配发行版自带的软件包。

“组”(group)是 Galène 对房间的称呼,每个组对应一个 JSON 文件:

echo '{"users": {"vimes": {"password":"sybil", "permissions":"op"}}}' > groups/night-watch.json
./galene &

打开 https://your.server:8443/group/night-watch/ 并以 vimes 身份登录。这些凭据直接来自项目的 README,因此在端口对外开放前请务必修改它们。对于正式部署,项目文档提供了 systemd 单元文件:

[Unit]
Description=Galene
After=network.target

[Service]
Type=simple
WorkingDirectory=/home/galene
User=galene
Group=galene
ExecStart=/home/galene/galene
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

所需的端口包括:用于 Web 界面的 TCP 8443,用于内置 TURN 服务器的 TCP 和 UDP 1194,以及用于媒体传输的一系列高位 UDP 端口。请固定该端口范围,以便编写防火墙规则:

./galene -udp-range 40000-40100

在 VPS 上,-turn 选项至关重要。-turn ':1194' 会监听所有公网 IPv4 地址。-turn '203.0.113.1:1194' 用于告知 Galène 客户端实际看到的地址,当机器本身处于私有网络时,必须配置此项。-turn '' 用于禁用内置服务器,以便通过 data/ice-servers.json 指向外部服务器。默认值为 auto,在不存在 ice-servers.json 时,其行为与 :1194 一致。

你可以通过在 data/config.json 中设置 proxyURL,并使用 WebSocket 升级头代理 /ws 路径,将 nginx 置于 Web 界面前端。请注意其覆盖范围:客户端仍会直接发起 UDP 流并连接到 TURN 端口,因此反向代理仅处理页面和信令。媒体流不会经过代理。

Galène 的文档指出它仅需极少的服务器资源,且未发布具体指标,因此不要期待有明确的数值。上述带宽计算逻辑依然完全适用。你节省的是除 SFU 之外所有组件的内存占用和维护成本。

Owncast:一对多直播,带宽消耗呈线性增长

许多“视频会议”需求本质上是一个人进行演示,而观众通过聊天室互动。如果您的需求属于此类,SFU(选择性转发单元)并非合适的工具,且经济成本完全不同。Owncast 接收来自 OBS 或类似编码器的 RTMP 流,并通过常规 HTTPS 提供 HLS 服务。每个观众占用的带宽是线性的,而非二次方的。由于输出的是标准 HTTP 分片,您可以将其部署在对象存储或 CDN 之后,从而无需在源服务器上支付流量费用。

curl -sL https://owncast.online/install.sh -o install-owncast.sh
less install-owncast.sh
bash install-owncast.sh

项目文档建议不要以 root 用户身份运行此程序,并在执行任何远程脚本前进行检查,因此上述下载步骤是独立的。安装程序会获取当前版本以及 ffmpeg 二进制文件(如果您尚未安装)。在安装目录下运行 ./owncast,并通过端口 8080 访问 /admin 处的管理面板。默认登录用户为 admin,默认流密钥(stream key)即为密码 abc123。在将域名指向服务器之前,请务必修改此密码。

HLS 设计会带来两个结果。首先,由于 HLS 传输的是完整分片,观众看到的画面会比直播实时画面滞后几秒或几分钟,因此无法进行实时双向对话。其次,整个路径中不涉及 UDP 和 TURN,因此它可以在 WebRTC 通话无法连接的网络环境下正常工作。

Owncast 也是此处唯一专门进行转码的工具。您启用的每一种输出质量,都意味着对输入流进行一次额外的 ffmpeg 编码,且编码过程贯穿整个直播时长。在小型 VPS 上,建议仅提供一到两种质量选项。若设置五种质量,CPU 将会过载,而网络带宽却处于闲置状态。

在现有 Matrix 服务器上部署 Element Call

如果您已经在运行 Matrix,视频功能属于现有服务的扩展,而非需要独立运维的第二个产品。不过,它仍涉及多个软件包。Element Call 需要在您的 homeserver 后端部署两个组件。第一个是 LiveKit SFU,负责媒体转发。第二个是 MatrixRTC 授权服务 element-hq/lk-jwt-service,它负责向客户端提供 LiveKit WebSocket URL 以及用于连接的签名 JWT(JSON Web Token)。该服务使用 Matrix 联邦 API,因此需要在其前端配置 TLS 反向代理,并分配一个联邦可访问的域名。

LiveKit 的标准端口要求如下:

  • TCP 7880:用于 API 和客户端 WebSocket,需置于终止 TLS 的代理之后
  • TCP 7881:用于 ICE over TCP,在客户端无法通过 UDP 连接时使用
  • UDP 50000 到 60000:用于媒体传输,房间内每位参与者占用两个端口
  • UDP 3478 和 TCP 5349:若启用内置 TURN 服务器则需开启;除非前端有负载均衡器,否则 5349 端口必须改为 443

每位参与者占用两个端口听起来很多,实则不然。10000 个端口的范围足以覆盖数千名参与者,您的上行带宽耗尽的速度远快于端口耗尽的速度。请务必开放整个范围,因为端口范围开放不全会导致部分用户无法连接,而这种故障最难排查。关于 homeserver 侧的配置属于独立任务,详见 在 VPS 上运行 Synapse homeserver。

为什么总有一个人无法连接?TURN 与阻断 UDP 的网络

首先介绍几个术语,每个术语仅使用一次。ICE(交互式连接建立)是两个 WebRTC 端点用于寻找可用通信路径的过程。STUN(NAT 会话穿透工具)是一个小型服务,用于告知客户端其公网地址在外部看来是什么样。TURN(使用中继绕过 NAT)是一个中继服务:当不存在直接路径时,双方将媒体数据发送至 TURN 服务器,由其进行转发。

对于那些处于你无法探测的网络环境中的参与者,你需要使用 TURN。其中一种情况是参与者位于企业或校园网内,这些网络完全阻断了出站 UDP 流量。另一种情况是参与者位于运营商级 NAT 之后,该 NAT 会为每个目标地址分配不同的源端口,这被称为对称 NAT,它使得 STUN 报告的地址失效。

其症状非常典型。大多数人可以正常加入并使用,但某一个人虽然能看到参与者列表和聊天内容,却只能看到黑屏和加载转圈。他们的浏览器收集了候选地址,但没有一对能够成功连接,导致 ICE 进入失败状态。在 Chrome 中,在尝试连接期间打开 chrome://webrtc-internals 可以看到候选地址对及其失败情况。请让该用户尝试切换到移动数据网络。如果此时可以正常工作,则说明是其网络环境导致的问题,而 TURN 是解决方案。

在 443 或 5349 端口上使用 TCP 传输的 TURN 是几乎在任何地方都有效的备选方案,因为如果一个网络阻断了 443 端口上的 TLS,那么它也就阻断了整个 Web。Jitsi 的安装包会自动为你安装并配置 coturn,这正是其防火墙规则文档中包含 UDP 3478 和 TCP 5349 的原因。Galène 在 1194 端口内置了 TURN。LiveKit 拥有一个嵌入式 TURN 服务器,你可以在配置中将其开启。如果你自行运行 coturn:

sudo apt install -y coturn
sudo systemctl enable --now coturn
listening-port=3478
tls-listening-port=5349
fingerprint
use-auth-secret
static-auth-secret=REPLACE_WITH_A_LONG_RANDOM_STRING
realm=turn.example.com
cert=/etc/letsencrypt/live/turn.example.com/fullchain.pem
pkey=/etc/letsencrypt/live/turn.example.com/privkey.pem
min-port=49152
max-port=65535
no-multicast-peers

这些设置需要写入 /etc/turnserver.conf。在 Debian 和 Ubuntu 上,安装包在安装完成后会立即使用该文件的默认配置启动 coturn,因此上述 enable --now 会发现它已经在运行,且不会产生任何更改。你的设置在运行 sudo systemctl restart coturn 后才会生效,后续对该文件的每次修改都需要执行相同的重启操作。旧版指南还会建议在 /etc/default/coturn 中设置 TURNSERVER_ENABLED=1。只有旧版的 init 脚本会读取该开关。当前安装包所使用的 systemd 单元不会读取它,因此该行配置无效,且如果你从未重启过 coturn,它依然在使用默认文件运行。

现在谈谈无人提及的成本问题。中继服务器需要承载每一位通过中继连接的参与者的完整双向媒体流量。当 coturn 与 SFU 部署在同一台机器上时,大部分流量会通过回环接口(loopback),这主要消耗 CPU 而非上行带宽,且 TLS 监听器会在媒体数据已有的 DTLS 加密之上,对每个数据包进行二次加密。当你将 TURN 迁移到独立机器时,该机器需要具备与 SFU 规模相当的带宽规划。此外,基于 TCP 的 TURN 会将实时媒体转换为可靠流,这意味着丢失的数据包会被重传而不是被跳过,因此在丢包严重的链路上,通过中继连接的参与者会产生延迟累积,而不是短暂的卡顿。中继是一种能够建立连接的备选方案,但其质量通常不如直接路径。

SFU 何时进行转码,以及成本如何?

SFU 只负责转发数据包,从不解码视频,这就是为什么 4 核 CPU 就能支撑起理论上看似不可能的会议室规模。但有两项功能会打破这一特性,且这两项功能往往被用户在勾选复选框开启后感到意外。

第一项是录制。Jitsi 使用 Jibri 进行录制,Jibri 的官方文档明确描述了其工作原理:它会启动一个在虚拟帧缓冲区中渲染的 Chrome 实例,并使用 ffmpeg 捕获和编码输出内容。这意味着在通话期间,系统会持续运行一个完整的浏览器来渲染整个会议,外加一个视频编码器。同一文档指出,单个 Jibri 实例一次仅支持一路录制,且 Jibri 应运行在独立的物理机或虚拟机上,且该机器上不得有其他应用占用显示或音频设备。录制本质上是第二个服务器,而非简单的复选框功能。

第二项是电话拨入。将电话线路桥接到会议中,意味着需要将 48 kHz 的 Opus 音频转换为电话网络所接受的格式(通常为 8 kHz 的 G.711),且需在通话全程双向持续进行。音频转码的成本远低于视频转码,但它按通话链路计费且永不暂停,因此成本会随通话人数增加而线性增长。如果您需要拨入号码,自托管 VoIP 服务器 是执行此项工作的组件,出于与 Jibri 相同的原因,它应当部署在独立的服务器上。

你需要多大的服务器?

对于两个人,几乎不需要什么资源。当参与者恰好为两人时,Jitsi 默认启用点对点模式。在此模式下,会议将停止通过视频桥(videobridge)传输数据,转而使用直接连接。当第三人加入时,系统会切回桥接模式。因此,1 GB 内存的 VPS 作为一对一通话服务器绰绰有余,但承载四人会议则表现不佳,这就是为什么 “我测试时明明能用” 成为常见反馈的原因。

对于最多约十人且开启摄像头的情况,当有八名参与者时,67.2 Mbps 的带宽处于普通 VPS 上行链路的承载范围内。只要不进行录制,2 个虚拟 CPU 和 4 GB 内存的配置足以运行 Jitsi 或 Galène。此时应重点监控流量计数器,而非 CPU 使用率。

对于三十人规模,最坏情况下的持续带宽需求为 1,044 Mbps,二十小时的流量即达到 9.4 TB。在这个规模下,带宽成本比服务器硬件成本更重要。请开启 last-N 功能,使视频桥仅转发近期发言者的画面,将默认设置改为关闭参会者摄像头,并将 SFU 部署在流量配额足以支撑上述计算量的环境中。

超过此规模,单台 VPS 已不再适用。如果该活动本质上是广播,那么使用 Owncast 配合 CDN 的成本远低于此;或者,你需要在一个信令层后部署多个视频桥,这属于比你当前项目更复杂的工程。

最后谈谈路由规划。大多数团队使用聊天工具的时间远多于视频会议,且聊天服务的托管成本低廉、运行稳定。将 自托管的 Slack 替代方案 用于日常沟通,仅在预定通话时使用会议服务器,这种架构最能适应小型 VPS 的预算限制。

FAQ

为什么用户可以加入我的 Jitsi 会议,但无法看到或听到彼此?

聊天信息和参会者列表通过信令通道传输(即 TCP 443 端口),而音视频流则通过 UDP 10000 端口传输至视频桥(videobridge)。如果参会者列表已更新但所有画面均为黑色,说明信令通道正常,但媒体路径中断。请检查防火墙(包括服务器本地防火墙以及云服务商控制台的外部网络防火墙)是否放行了 UDP 10000 端口。随后确认视频桥是否识别其公网地址:如果虚拟机使用私有地址并通过映射获取公网 IP,需在 /etc/jitsi/videobridge/jvb.conf 的 ice4j.harvest.mapping 下添加静态映射并重启 jitsi-videobridge2。在有人加入会议时运行 sudo tcpdump -ni any udp port 10000 可以判断故障点,如果完全没有数据包,说明拦截发生在操作系统层面之上。

30 人的视频通话需要多少带宽?

在最坏情况下,即所有人都开启摄像头且 SFU 向每个人转发全质量视频流时,服务器的出口带宽约为 1,044 Mbps,即每小时 469.8 GB。这是基于 N 乘以 (N 减 1) 个流(每个 1.2 Mbps)的理论计算值,而非实际测量值。在实际使用中,由于大多数参会者并非时刻出现在屏幕上,Simulcast(联播)和 last-N 设置会大幅降低带宽消耗。但规划容量时仍应参考最坏情况,因为全员会议时每个人都可能同时开启摄像头。

我可以在 1 GB 内存的 VPS 上运行 Jitsi Meet 吗?

可以安装,且两人通话可以正常进行,这是因为 Jitsi 在仅有两名参会者时会使用点对点(peer to peer)模式,完全绕过视频桥。但它不适合作为群组通话服务器。Prosody、视频桥和 Java 运行时都需要占用内存,手册建议生产环境至少配置 8 GB 内存。此外,带宽限制通常比内存瓶颈更早出现。如果只有 1 GB 内存的服务器,Galène 比 Jitsi 更合适。

如果我的 VPS 拥有公网 IP,还需要 TURN 服务器吗?

需要。TURN 解决的是通话另一端的问题。如果参会者位于禁止出站 UDP 的企业网络中,或者处于会为不同目标分配不同源端口的运营商级 NAT(CGNAT)后方,无论你的服务器地址多么公开,他们都无法建立直接的媒体路径。通过 TCP 443 或 5349 端口运行的 TURN 服务器可以提供中继,使其在防火墙看来就像普通的网页流量。Jitsi 的软件包安装程序默认会配置 coturn,这也是为什么文档要求防火墙放行 UDP 3478 和 TCP 5349 端口的原因。

为什么 BigBlueButton 比 Jitsi Meet 需要更多的硬件资源?

因为它不仅负责转发视频。其官方发布的生产环境要求为 16 GB 内存和 8 核 CPU,而 Jitsi 手册的要求为 8 GB 内存和 4 核 CPU。BigBlueButton 在同一台机器上运行了完整的音频会议栈、共享白板和演示层、录制与后期处理流水线,以及带有用户账户的 Web 前端。它对平台环境有严格要求:截至 2026 年 8 月,支持的安装版本为 Ubuntu 22.04 上的 3.0 版本。上述数据均来自各项目的官方文档,仅作为参考起点,而非针对你实际工作负载的测量值。

#jitsi#webrtc#video-conferencing#自托管#bandwidth