搭建流媒体服务器:一次推流,任意多人观看

发布于 阅读时间 13 分钟

您只向服务器推送一路流,服务器再把它分发给所有观众。无论是十个人还是一千个人在看,您自己的线路始终只承担一路上传。本文讲清搭建方式、协议选择,以及背后的带宽计算。

不用自己的服务器直播,就得把画面分别发给每一位观众。十位观众意味着同样的数据发十遍,一百位就是一百遍。于是家里或办公室的上传带宽在几位观众之后就被塞满,画面开始卡顿,而电脑其实闲得发慌。

流媒体服务器把这件事反过来:您只向服务器推送一路流,服务器再用它供应所有观众。这样您自己的线路永远只承担一路上传,无论是十个人还是一万个人在看。本文说明这为什么如此有效、怎么把这样一台服务器搭起来、哪种协议要付出多大延迟,以及实际会产生多少流量。

问题所在:您的上传就是瓶颈

视频是持续不断的数据流。一路 1080p、每秒 60 帧的直播,视内容不同需要 4.5 到 8 Mbit/s,720p 大约是 3 到 5 Mbit/s。这个码率是按每位观众计算的,全程不间断。

德国一条普通家庭宽带的上传在 10 到 50 Mbit/s 之间,即便是不少光纤接入,上传也只有 50 到 100 Mbit/s。所以这笔账很快就算到头了:

观众数按 3 Mbit/s按 6 Mbit/s家庭宽带够吗?
515 Mbit/s30 Mbit/s勉强
2060 Mbit/s120 Mbit/s不够
100300 Mbit/s600 Mbit/s不够
10003 Gbit/s6 Gbit/s不够

还有第二个常被忽略的问题:您的宽带要和家里或办公室里的其他所有东西共用这条线路。只要有人上传一个大文件,或者某个备份开始跑,直播就会掉。机房里的服务器没有这个问题,那里的网络接入只归您一个人用。

原理:上传一次,下发无数次

整个架构由三部分组成:

  • 推流端,也就是 OBS、ffmpeg 或者一台硬件编码器,把一路流发到服务器。这一步叫 Ingest(接入)。
  • 服务器接收这一路流,把它转成需要的分发格式并随时待取。
  • 观众从服务器把流拉走。这一步叫 Egress(出口流量),也正是随观众数量增长的那部分。

关键在于这种不对称:从您到服务器的路只走一次,从服务器到观众的路要走上千次。所以您的宽带只需要够一路流的上传,而服务器需要一条跟得上观众规模的网络接入。

实际会产生多少流量

带宽只是这笔账的一半。更值得关心的是流量总量,因为很多服务商是按它收费的。公式很简单:

流量(GB) = 码率(Mbit/s) × 秒数 × 观众数 ÷ 8000

几个现实中的例子:

场景码率时长观众数流量
每周一次的讲座3 Mbit/s2 小时50135 GB
每天一档节目6 Mbit/s3 小时200每天 1.6 TB
24 小时不间断频道4 Mbit/s24 小时30每天 1.3 TB
一次性大型活动6 Mbit/s4 小时200021.6 TB

最后一列的数字,正是直播和按量计费合不来的原因。一场人气不错的转播就可能把整个月的包含流量用光,之后每一个 TB 都要单独付钱。换成无限流量的套餐,这笔账就彻底不用算了:月费固定,无论线路上跑的是 200 GB 还是 50 TB。

哪款软件适合您

软件长处适合
nginx 加 RTMP 模块轻量、稳定,能同时提供 RTMP 和 HLS经典的入门选择,转发到各平台
MediaMTX单个二进制文件,原生支持 SRT 和 WebRTC不想折腾又要低延迟
SRS功能非常多,支持集群多节点的较大规模架构
Owncast带网页界面和聊天的一体化方案自己的小型直播站

入门阶段,nginx 加 RTMP 模块是最顺手的选择:到处都能装,文档齐全,而且以后不用改造,同一台服务器就能顺带当观众页面的 Web 服务器。

用 nginx 和 RTMP 搭一台流媒体服务器

安装

在 Debian 和 Ubuntu 上,libnginx-mod-rtmp 这个包自带该模块,不需要自己编译:

apt update
apt install -y nginx libnginx-mod-rtmp ffmpeg

在 AlmaLinux 和 Rocky Linux 上,模块来自 EPEL 仓库:

dnf install -y epel-release
dnf install -y nginx nginx-mod-rtmp ffmpeg

配置

RTMP 部分在 nginx.conf 里要写在 http 块之外,这是新手最常犯的错。一份精简且能跑的配置是这样:

rtmp {
    server {
        listen 1935;
        chunk_size 4096;

        application live {
            live on;
            record off;

            # HLS 给普通观众
            hls on;
            hls_path /var/www/stream/hls;
            hls_fragment 2s;
            hls_playlist_length 12s;

            # 只允许从自己的地址推流
            allow publish 203.0.113.10;
            deny publish all;

            # 观看不限制
            allow play all;
        }
    }
}

HLS 文件随后由普通的 Web 服务器分发。为此在 http 部分加一小段就够了:

server {
    listen 80;
    server_name stream.example.com;

    location /hls {
        types {
            application/vnd.apple.mpegurl m3u8;
            video/mp2t ts;
        }
        root /var/www/stream;
        add_header Cache-Control no-cache;
        add_header Access-Control-Allow-Origin *;
    }
}

建目录、检查配置、重新加载:

mkdir -p /var/www/stream/hls
chown -R www-data:www-data /var/www/stream
nginx -t && systemctl reload nginx

放行端口

RTMP 跑在 1935 端口,分发走 80 和 443。用 nftables 或 ufw:

ufw allow from 203.0.113.10 to any port 1935 proto tcp
ufw allow 80/tcp
ufw allow 443/tcp

注意第一行:推流端口只对您自己的地址开放。一个对全世界开放的 RTMP 端口几天之内就会被找到,因为整段地址范围都会被自动扫描,接着就有别人拿您的线路推流了。

用 OBS 推流

在 OBS 的设置、直播里,把服务填成“自定义”:

字段值
服务器rtmp://stream.example.com/live
推流密钥一个自己取的名字,例如 kanal1

码率在输出里设置。参考值:1080p60 用 6000 kbit/s,1080p30 用 4500 kbit/s,720p30 用 3000 kbit/s。把关键帧间隔设为 2 秒,否则 HLS 会切出长短不齐的分片,播放器在切换时会卡。

观看

之后这路流就在 https://stream.example.com/hls/kanal1.m3u8,任何支持 HLS 的播放器都能打开,浏览器里例如可以用 hls.js 或 Video.js。想快速验证,用 VLC 的“打开网络串流”就够了。

同时推到多个平台

这是自建服务器的第二大好处。不必用三路并行上传把线路撑爆,您只向服务器推一次,由它继续分发。为此在 application 块里给每个目标加一行:

application live {
    live on;
    record off;

    push rtmp://live.plattform-a.example/app/STREAM_KEY;
    push rtmp://live.plattform-b.example/app/STREAM_KEY;
}

这期间您的上传始终只有一路流。复制的活儿由服务器接下,而带宽正是它存在的意义。

延迟:哪种协议用在哪里

延迟几乎全部产生在分发环节,而不是推流环节。这一点很重要,因为很多人找错了地方:

分发方式延迟适合
HLS,默认设置20 到 30 秒讲座、礼拜、不涉及下注的体育
HLS,分片缩短6 到 10 秒常见的折中
低延迟 HLS2 到 5 秒带聊天的直播
SRT1 秒以内站点之间的信号回传
WebRTC0.5 秒以内对话、拍卖、远程操控

延迟越低,单个观众的成本越高。HLS 最便宜,因为它就是一堆普通文件,任何 Web 服务器和任何缓存都能分发。WebRTC 则要为每位观众维持一条独立连接,算力开销明显更大。只在真正需要的地方才用低延迟。

转码:什么时候才值得

只要服务器只是转发这路流,它几乎不需要算力。这样一个现代核心就能服务好几百位观众,瓶颈只有网络接入。

一旦您想提供多个画质档位,让网络条件差的观众也看得了,情况就变了。每增加一个档位都要重新计算一遍:

ffmpeg -i rtmp://127.0.0.1/live/kanal1 \
  -c:v libx264 -preset veryfast -b:v 3000k -s 1280x720 -c:a copy -f flv rtmp://127.0.0.1/live/kanal1_720 \
  -c:v libx264 -preset veryfast -b:v 1200k -s 854x480  -c:a copy -f flv rtmp://127.0.0.1/live/kanal1_480

每个档位按两到四个核心算。三个档位就会长期占住八到十二个核心。所以要想清楚是否真的需要:如果观众大多坐在电脑前或连着 Wi-Fi,一个选得好的档位往往就够了。

加固:谁有权推流

流媒体服务器在外网是可见的,迟早会被找到。日常用三条措施就够了:

  • 给推流端口加防火墙。只有您自己的地址能访问 1935。如果您的地址会变,就改用一条到服务器的 VPN 通道。
  • 校验推流密钥。通过 on_publish,nginx 会在每次推流尝试时调用一个小脚本,把密钥和一份名单比对,不符就拒绝。
  • 基本的抗过载防护。流媒体服务器是个值得攻击的目标,因为一掉线马上就能看出来。在 KernelHost,每台服务器都带有 3.2 Tbps 容量的洪水防护,您不需要做任何配置。详情见DDoS 防护页面。

选址与多台服务器

服务器不该放在离您近的地方,而该放在离观众近的地方。您到服务器的连接只建立一次,之后就稳定地跑着,即便跨半个大洲也无妨。而到观众的连接才决定加载时间和流失率。

如果观众主要在欧洲,机房放在德国就对了。如果观众分散在多个大洲,就值得加第二台服务器,并通过 DNS 分流,让每位观众落到最近的那一台。KernelHost 为此提供德国、美国西海岸、美国东海岸以及新加坡和韩国的机房,概览见服务器机房位置。

如果您分发的是文件而不是实时画面,比如更新包、图片或视频存档,那合适的工具不是流媒体服务器,而是放在前面的缓存。具体做法见文章自建 CDN 服务器。

该选哪种服务器

对流媒体服务器来说,重要性的排序和 Web 服务器不一样:

  1. 网络接入与流量。这永远是瓶颈。一条不限速的真千兆接入,按 6 Mbit/s 算大约能承载 160 位观众。
  2. 无限流量。按量计费的套餐对直播几乎无法估算,因为一个成功的晚上就能把月流量用光。
  3. CPU。只要不转码,它是次要的。一旦转码,它就成为第二个瓶颈。
  4. 内存与硬盘。最不关键。只有在保留录像时,硬盘空间才成为问题。

我们的无限流量根服务器正是为这种场景准备的:每台服务器真正的 2 × 1 Gbit/s 接入,不限量、不限速,月费固定且与传输量无关,并自带 3.2 Tbps 洪水防护。服务器在 30 秒内开通,带完整 Root 权限、IPv4 和一个 /64 的 IPv6 网段。计费采用预付费、按月可退订,所以您可以先从小套餐起步,等观众变多再往上走。

常见问题

我到底为什么需要一台流媒体服务器?
没有服务器时,您的电脑要把同一路流分别发给每一位观众。十位观众、每路 6 Mbit/s,就是 60 Mbit/s 的上传,一百位就是 600 Mbit/s。而普通家庭宽带的上传只有 10 到 50 Mbit/s。有了流媒体服务器,您只推送一次,分发的活儿交给服务器。
服务器需要多少带宽?
把码率乘以同时在线的观众数。500 位观众、每路 6 Mbit/s 就是 3 Gbit/s。但比峰值更重要的是月流量:同样这 500 位观众看两个小时,就会产生约 2.7 TB。所以对直播来说,决定性的条件是无限流量,而不是 CPU。
软件该选哪一个?
入门用 nginx 配 RTMP 模块最合适,它足够轻量,而且能同时提供 RTMP 和 HLS。MediaMTX 是更现代的替代方案,原生支持 SRT 和 WebRTC。SRS 功能最全,但上手要花更多时间。Owncast 则是带网页界面和聊天的一体化方案。
延迟有多大?
推流到服务器这一段不到一秒。延迟几乎全部产生在分发环节:HLS 用默认设置是 20 到 30 秒,缩短分片后是 6 到 10 秒,低延迟 HLS 是 2 到 5 秒。SRT 和 WebRTC 能做到一秒以内,代价是每位观众消耗更多算力。
我需要转码吗,成本有多高?
只有在您想提供多个画质档位时才需要。单纯转发而不重新编码几乎不吃 CPU,一个核心就能服务几百位观众。一旦要把 1080p 的流额外输出成 720p 和 480p,每个档位大约需要两到四个现代核心。等真正需要时再规划转码。
我可以同时推到 Twitch 和 YouTube 吗?
可以,服务器正好擅长这件事。您只向自己的服务器推一次,它会把同一路流转发到任意多个平台。用 nginx-RTMP 时,每个目标只要一行 push 指令。您自己的线路依然只承担一路上传。
怎么防止陌生人往我的服务器推流?
在防火墙里把推流端口只对您自己的地址开放,另外用 on_publish 校验推流密钥。两者缺一,任何开放的 RTMP 服务器几天之内就会被塞进陌生的直播流,因为整段地址范围都会被扫描。
服务器应该放在哪里?
不是放在离您近的地方,而是放在离观众近的地方。从您到服务器的路只走一次,从服务器到观众的路要走上千次。观众在欧洲,服务器就放欧洲。观众分散在多个大洲,就值得加第二台服务器,并通过 DNS 分流。
一台 VPS 够用,还是需要独立服务器?
只做转发、不转码时,几个核心的 VPS 完全够用,瓶颈在网络接入而不在算力。只有在给多个画质档位转码,或者同时跑很多路频道时,独立硬件才值得。
我怎么测试服务器扛不扛得住?
开始推流,然后用多个工具同时拉流,例如让 ffmpeg 空转。同时观察网络吞吐和负载。如果在 CPU 还没热起来之前就先打满了网络接入,说明这笔账算对了:您需要的是更多带宽,而不是更多核心。

Streaming RTMP HLS SRT nginx OBS Restream Unlimited Traffic