上一篇 下一篇 分享链接 返回 返回顶部

如何在香港服务器运行 CentOS 7,设置并结合 Nginx + FFmpeg 实现视频转码与分发的一体化架构

发布人:Minchunlin 发布时间:2025-09-07 11:35 阅读量:684


我第一次把这套系统落在香港机房,是在8月一个闷热又潮湿的周五晚上。客户催着第二天要做一场 5,000 人同时在线的直播,还要保证点播库里那几百支旧片也能无缝切到 ABR(自适应码率)HLS。我们把机柜开门,风从冷通道灌进来,NVMe 指示灯一串“呼吸灯”闪着。我一边用耳机远程跟剪辑同事确认片源帧率,一边在跳线架上把第二条 10GbE 上行接到运营商 BGP 设备上。凌晨两点,systemctl status ffmpeg-live@event.service 终于显示绿了——那一刻我知道,剩下就是观察与优化。

1. 目标与适用场景

  • 目标:在 CentOS 7 上构建一套 Nginx + FFmpeg 的一体化视频转码与分发架构,支持 点播 VOD 批量转码 与 直播 RTMP/HLS 转码,对外提供 HLS(fMP4/TS) 分发,具备横向扩展与监控告警能力。
  • 适用:中小规模视频平台、活动直播落地、教育与培训平台、短期应急大促与发布会;香港机房可覆盖大陆与东南亚,时延与带宽相对友好。
  • 说明:本文基于 CentOS 7 最小化安装(仍有大量存量环境),重点覆盖从系统层到服务层的可复制步骤与坑位。

2. 架构总览(文字拓扑)

上游内容 →(SFTP/对象存储/本地挂载)→ 转码节点(FFmpeg 批量/实时) →(输出 HLS 切片与索引)→ Nginx 分发层 →(HTTP/HTTPS/HTTP/2)→ 观众端播放器

可选:

  • 直播推流入口使用 Nginx-RTMP 模块或外部推流网关;
  • 静态分发前挂接 CDN(海外可 Cloudflare,国内可多线供应商)以扩容;
  • 对象存储/分布式存储(如 MinIO、Ceph)用于长周期归档,边转边迁移。

3. 硬件与网络选型(实战参数)

3.1 推荐配置(单台 All-in-One,便于起步)

组件 选型 关键参数/理由
CPU(CPU 转码) Intel Xeon Silver 4210R ×2 或 AMD EPYC 7302P ×1 20C40T/16C32T,AVX2;x264 “veryfast” 档每核可稳跑 1080p@~0.5 路(视片源而定)
GPU(可选) NVIDIA T4 ×1 NVENC 稳定,单卡 1080p@30fps 可 6–10 路,视预设与码率而定
内存 64–128GB DDR4 HLS 切片缓存与并发连接缓冲
系统盘 SATA SSD 480GB 系统与日志分离,降低写放大对数据盘影响
数据盘 NVMe SSD 1.92TB ×2(RAID1) 顺序读写 >2GB/s,随机 IOPS 高,保证切片写入与并发读取
网口 10GbE ×2(bond0,LACP) 吞吐与冗余;对外 BGP 或多线接入
机房 香港 MEGA-i / 新世界电讯 / CITIC 等 机房质量与路由质量较好,跨境延迟与抖动较低

估算经验:CPU-only 场景,40 逻辑核约能稳跑 1080p 转码 15–20 路(veryfast),HLS 分发并发受带宽与文件句柄影响;加一张 T4,1080p 转码能力可再提升一倍以上。

3.2 带宽与并发容量粗算

码率阶梯(推荐):

级别 分辨率/帧率 视频码率 音频码率 典型用法
240p 426×240@30 300 kbps 64 kbps 极弱网保底
360p 640×360@30 600 kbps 96 kbps 标清保底
480p 854×480@30 1,000 kbps 96 kbps 过渡档
720p 1280×720@30 2,500 kbps 128 kbps 主力档
1080p 1920×1080@30 5,000 kbps 160 kbps 高清

并发 ≈ 出口带宽(bps)/ 平均档码率。

例如:对外 5 Gbps 出口,观众平均落在 2.5 Mbps 档:

  • 理论并发 ≈ 5,000 Mbps / 2.5 Mbps ≈ 2,000;
  • 预留 20% 冗余与突发,稳态并发建议 1,600 左右。

4. 系统安装与基础加固(CentOS 7)

# 最小化安装后
yum -y update
yum -y install epel-release yum-utils chrony htop iotop iftop jq tmux git wget curl zip unzip bind-utils \
  device-mapper-persistent-data lvm2 numactl python3 policycoreutils-python

# 时间同步
systemctl enable --now chronyd
chronyc sources -v

# 关闭不必要服务(按需保留)
systemctl disable --now postfix cups rpcbind

# 防火墙与 SELinux
yum -y install firewalld
systemctl enable --now firewalld
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --permanent --add-port=1935/tcp   # RTMP 可选
firewall-cmd --reload

# SELinux 建议保持 Enforcing,后续为 Nginx/HLS 目录添加上下文
sestatus

内核/系统参数(/etc/sysctl.d/99-video-hls.conf):

net.core.somaxconn = 65535
net.core.netdev_max_backlog = 250000
net.ipv4.tcp_max_syn_backlog = 262144
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_tw_reuse = 1
fs.file-max = 2097152
vm.swappiness = 10

sysctl --system
# 打开文件句柄(/etc/security/limits.d/99-nofile.conf)
echo -e "* soft nofile 1048576\n* hard nofile 1048576" > /etc/security/limits.d/99-nofile.conf

5. 磁盘与目录规划

# 数据卷:NVMe /dev/nvme0n1p1, /dev/nvme1n1p1 组 RAID1(mdadm 或硬 RAID)
mkfs.xfs /dev/md0
mkdir -p /data/{hls_vod,hls_live,upload,tmp}

# fstab 挂载示例(/etc/fstab)
/dev/md0  /data  xfs  noatime,nodiratime,nobarrier,logbufs=8,attr2  0 0

设置 SELinux 上下文(很容易踩坑):

semanage fcontext -a -t httpd_sys_rw_content_t "/data(/.*)?"
restorecon -Rv /data

不做这一步,Nginx/FFmpeg 在写 HLS 切片时会遇到 13 Permission denied,使你误以为是目录权限问题。

6. 安装 Nginx(含 RTMP 可选)

生产环境建议源码编译,便于开启需要的模块并绑定较新的 OpenSSL(CentOS 7 默认 1.0.2 无 TLS1.3,但 TLS1.2 足够)。

# 依赖
yum -y install gcc gcc-c++ pcre pcre-devel zlib zlib-devel openssl-devel libxml2-devel libxslt-devel \
  gd-devel geoip-devel perl-ExtUtils-Embed

# 源码
cd /usr/local/src
wget https://nginx.org/download/nginx-1.24.0.tar.gz
wget https://github.com/arut/nginx-rtmp-module/archive/refs/tags/v1.2.2.tar.gz -O nginx-rtmp.tar.gz
 tar xzf nginx-1.24.0.tar.gz
 tar xzf nginx-rtmp.tar.gz

# 编译(RTMP 模块按需,亦可省略)
cd nginx-1.24.0
./configure \
  --prefix=/usr/local/nginx \
  --with-http_ssl_module \
  --with-http_v2_module \
  --with-threads \
  --with-file-aio \
  --with-http_stub_status_module \
  --add-module=../nginx-rtmp-module-1.2.2
make -j$(nproc) && make install

ln -sf /usr/local/nginx/sbin/nginx /usr/bin/nginx

# systemd 单元
cat >/etc/systemd/system/nginx.service <<'EOF'
[Unit]
Description=nginx
After=network.target

[Service]
Type=forking
ExecStart=/usr/bin/nginx
ExecReload=/usr/bin/nginx -s reload
ExecStop=/usr/bin/nginx -s quit
LimitNOFILE=1048576

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable --now nginx

Nginx 核心配置(/usr/local/nginx/conf/nginx.conf):

user  nginx;
worker_processes auto;
pid /var/run/nginx.pid;

events {
  worker_connections  65535;
  multi_accept on;
  use epoll;
}

http {
  include       mime.types;
  default_type  application/octet-stream;
  sendfile      on;
  tcp_nopush    on;
  tcp_nodelay   on;
  aio           threads;
  keepalive_timeout  65;
  server_tokens off;

  # 日志
  log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';
  access_log  logs/access.log  main;

  # 缓存与打开文件优化
  open_file_cache max=100000 inactive=120s;
  open_file_cache_valid 60s;
  open_file_cache_min_uses 2;
  open_file_cache_errors on;

  # CORS(播放器跨域)
  map $request_method $cors {
    default "";
    ~*OPTIONS 1;
  }

  server {
    listen 80 default_server reuseport;
    server_name _;

    # HLS VOD 与 LIVE 目录
    location /vod/ {
      root /data/hls_vod;
      add_header Cache-Control "max-age=60" always;
      add_header Access-Control-Allow-Origin "*" always;
      add_header Access-Control-Allow-Methods "GET, OPTIONS" always;
      add_header Access-Control-Allow-Headers "*" always;
      if ($cors) { return 204; }
      types { application/vnd.apple.mpegurl m3u8; video/mp2t ts; }
    }

    location /live/ {
      root /data/hls_live;
      add_header Cache-Control "no-cache" always;
      add_header Access-Control-Allow-Origin "*" always;
      add_header Access-Control-Allow-Methods "GET, OPTIONS" always;
      add_header Access-Control-Allow-Headers "*" always;
      if ($cors) { return 204; }
      types { application/vnd.apple.mpegurl m3u8; video/mp2t ts; }
    }

    # 健康与状态
    location /nginx_status { stub_status; allow 127.0.0.1; allow 10.0.0.0/8; deny all; }
  }
}

RTMP(直播接入,按需):在 nginx.conf 末尾追加:

rtmp {
  server {
    listen 1935;
    chunk_size 4096;
    application live {
      live on;
      record off;
      allow publish 10.0.0.0/8; # 按需限制推流源
      deny publish all;
    }
  }
}

坑位:如果 HLS 目录不在 /usr/local/nginx/html 下,务必做好 SELinux 上下文;另外 .m3u8 与 .ts 的 Content-Type 正确与否,直接影响部分终端的兼容性。

7. 安装 FFmpeg(源码,CPU/NVENC 两种)

7.1 基础依赖

yum -y groupinstall "Development Tools"
yum -y install autoconf automake bzip2 bzip2-devel cmake3 libtool make mercurial nasm yasm pkgconfig zlib-devel \
  freetype-devel libpng-devel libjpeg-turbo-devel libwebp-devel opus-devel

alternatives --set cmake /usr/bin/cmake3

nasm 版本坑:CentOS 7 自带 nasm/yasm 过旧,容易在 libx265/libaom 编译时出错。遇到报错,先升级 nasm 至 ≥2.15(源码编译)。

7.2 第三方编解码器(按需)

# x264
cd /usr/local/src && git clone https://code.videolan.org/videolan/x264.git
cd x264 && ./configure --prefix=/usr/local --enable-static --enable-pic && make -j$(nproc) && make install

# x265
cd /usr/local/src && hg clone https://bitbucket.org/multicoreware/x265
cd x265/build/linux && cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX=/usr/local -DENABLE_SHARED=off ../../source
make -j$(nproc) && make install

# fdk-aac(非自由,按需)
cd /usr/local/src && git clone https://github.com/mstorsjo/fdk-aac.git
cd fdk-aac && autoreconf -fiv && ./configure --prefix=/usr/local --enable-static && make -j$(nproc) && make install

# libvpx(VP8/VP9)
cd /usr/local/src && git clone https://chromium.googlesource.com/webm/libvpx
cd libvpx && ./configure --prefix=/usr/local --disable-examples --disable-tools --enable-vp9-highbitdepth && make -j$(nproc) && make install

7.3 FFmpeg 编译(CPU)

cd /usr/local/src && git clone https://github.com/FFmpeg/FFmpeg.git ffmpeg-src
cd ffmpeg-src && ./configure \
  --prefix=/usr/local/ffmpeg \
  --pkg-config-flags="--static" \
  --extra-cflags="-I/usr/local/include" \
  --extra-ldflags="-L/usr/local/lib" \
  --extra-libs="-lpthread -lm" \
  --enable-gpl --enable-nonfree \
  --enable-libx264 --enable-libx265 --enable-libfdk_aac --enable-libvpx --enable-libopus
make -j$(nproc) && make install
ln -sf /usr/local/ffmpeg/bin/ffmpeg /usr/bin/ffmpeg
ln -sf /usr/local/ffmpeg/bin/ffprobe /usr/bin/ffprobe

7.4 FFmpeg 编译(NVENC,可选)

安装 NVIDIA 驱动与 CUDA 工具包后,编译 FFmpeg 加 --enable-nvenc。CentOS 7 上建议使用官方 CUDA repo 安装驱动(确保内核匹配)。

# 在 7.3 基础上追加
./configure ... --enable-nvenc

8. 转码流水线(VOD 与 LIVE)

8.1 VOD:批量转码到 HLS(fMP4) + 自适应码率主索引

目录策略:

  • 源:/data/upload(只读)
  • 目标:/data/hls_vod/<slug>/<rung>/index.m3u8(rung= 240p/360p/...)

脚本(/usr/local/bin/vod-transcode.sh):

#!/bin/bash
set -euo pipefail
SRC_DIR=/data/upload
DST_DIR=/data/hls_vod

ladder=(
  "240:426x240:300k:64k"
  "360:640x360:600k:96k"
  "480:854x480:1000k:96k"
  "720:1280x720:2500k:128k"
  "1080:1920x1080:5000k:160k"
)

for src in $(find "$SRC_DIR" -type f -iname "*.mp4" -o -iname "*.mov" -o -iname "*.mkv"); do
  slug=$(basename "${src%.*}" | tr ' ' '-')
  out="$DST_DIR/$slug"
  mkdir -p "$out"

  map_args=()
  i=0
  for rung in "${ladder[@]}"; do
    IFS=":" read -r name size vbr abr <<<"$rung"
    rung_out="$out/$name"
    mkdir -p "$rung_out"

    map_args+=( -map 0:v:0 -map 0:a:0 -c:v:0 libx264 -preset veryfast -tune zerolatency \
      -vf "scale=${size}:flags=bicubic" -b:v:0 ${vbr} -maxrate:v:0 ${vbr} -bufsize:v:0 $((${vbr%k}*2))k \
      -g 60 -keyint_min 60 -sc_threshold 0 -c:a:0 aac -b:a:0 ${abr} -ac 2 \
      -f hls -hls_time 2 -hls_playlist_type vod -hls_flags independent_segments+single_file+append_list \
      -hls_segment_type fmp4 -master_pl_name master.m3u8 -hls_segment_filename "$rung_out/seg%05d.m4s" \
      "$rung_out/index.m3u8" )
    ((i++))
  done

  ffmpeg -hide_banner -y -i "$src" "${map_args[@]}"
  echo "[OK] $src -> $out"
done

挂载到 Nginx:上文 /vod/ 已根指向 /data/hls_vod,访问路径示例:

http://<server>/vod/<slug>/720/index.m3u8
http://<server>/vod/<slug>/master.m3u8   # 自适应主索引

小技巧:fMP4(-hls_segment_type fmp4)在 iOS/新浏览器表现更好;若需兼容非常旧的终端,可切回 TS(删掉 -hls_segment_type 并用 seg%05d.ts)。

8.2 LIVE:RTMP 进、HLS 出,多码率实时转码

目录:/data/hls_live/<stream_key>/<rung>/index.m3u8

systemd 模板服务(/etc/systemd/system/ffmpeg-live@.service):

[Unit]
Description=FFmpeg Live Transcoder for %i
After=network.target nginx.service

[Service]
Type=simple
LimitNOFILE=1048576
ExecStart=/usr/bin/bash -lc '/usr/bin/ffmpeg -hide_banner -loglevel warning -fflags nobuffer -flags low_delay \
 -rtbufsize 256M -i rtmp://127.0.0.1/live/%i \
 -filter_complex "[0:v]split=5[v240][v360][v480][v720][v1080]; \
  [v240]scale=426:240:flags=bicubic[v240o]; \
  [v360]scale=640:360:flags=bicubic[v360o]; \
  [v480]scale=854:480:flags=bicubic[v480o]; \
  [v720]scale=1280:720:flags=bicubic[v720o]; \
  [v1080]scale=1920:1080:flags=bicubic[v1080o]" \
 -map "[v240o]" -map a:0 -c:v:0 libx264 -preset veryfast -tune zerolatency -b:v:0 300k  -g 60 -keyint_min 60 -sc_threshold 0 -c:a:0 aac -b:a:0 64k  -f hls -hls_time 2 -hls_list_size 6 -hls_flags delete_segments+independent_segments -hls_segment_filename /data/hls_live/%i/240/seg%%05d.ts /data/hls_live/%i/240/index.m3u8 \
 -map "[v360o]" -map a:0 -c:v:1 libx264 -preset veryfast -tune zerolatency -b:v:1 600k  -g 60 -keyint_min 60 -sc_threshold 0 -c:a:1 aac -b:a:1 96k  -f hls -hls_time 2 -hls_list_size 6 -hls_flags delete_segments+independent_segments -hls_segment_filename /data/hls_live/%i/360/seg%%05d.ts /data/hls_live/%i/360/index.m3u8 \
 -map "[v480o]" -map a:0 -c:v:2 libx264 -preset veryfast -tune zerolatency -b:v:2 1000k -g 60 -keyint_min 60 -sc_threshold 0 -c:a:2 aac -b:a:2 96k  -f hls -hls_time 2 -hls_list_size 6 -hls_flags delete_segments+independent_segments -hls_segment_filename /data/hls_live/%i/480/seg%%05d.ts /data/hls_live/%i/480/index.m3u8 \
 -map "[v720o]" -map a:0 -c:v:3 libx264 -preset veryfast -tune zerolatency -b:v:3 2500k -g 60 -keyint_min 60 -sc_threshold 0 -c:a:3 aac -b:a:3 128k -f hls -hls_time 2 -hls_list_size 6 -hls_flags delete_segments+independent_segments -hls_segment_filename /data/hls_live/%i/720/seg%%05d.ts /data/hls_live/%i/720/index.m3u8 \
 -map "[v1080o]" -map a:0 -c:v:4 libx264 -preset veryfast -tune zerolatency -b:v:4 5000k -g 60 -keyint_min 60 -sc_threshold 0 -c:a:4 aac -b:a:4 160k -f hls -hls_time 2 -hls_list_size 6 -hls_flags delete_segments+independent_segments -hls_segment_filename /data/hls_live/%i/1080/seg%%05d.ts /data/hls_live/%i/1080/index.m3u8'
Restart=always
RestartSec=2

[Install]
WantedBy=multi-user.target

启动一条直播转码:

# OBS/推流器推到 rtmp://<server>/live/event
systemctl enable --now ffmpeg-live@event
# 访问: http://<server>/live/event/720/index.m3u8 或 master.m3u8(可扩展生成)

NVENC 直播:将 -c:v libx264 -preset veryfast -tune zerolatency 替换为 -c:v h264_nvenc -preset llhp -rc vbr -cq 24 -b:v <target> -maxrate <target>,同时注意 GPU 使用率与温度。

9. TLS/HTTPS(可选但推荐)

CentOS 7 环境下,使用 acme.sh 获取证书较省心:

curl https://get.acme.sh | sh
~/.acme.sh/acme.sh --issue -d example.com -w /usr/local/nginx/html
~/.acme.sh/acme.sh --install-cert -d example.com \
  --key-file       /usr/local/nginx/conf/ssl/example.key \
  --fullchain-file /usr/local/nginx/conf/ssl/example.crt \
  --reloadcmd     "/usr/bin/nginx -s reload"

Nginx server 中加入:

server {
  listen 443 ssl http2 reuseport;
  server_name example.com;
  ssl_certificate      conf/ssl/example.crt;
  ssl_certificate_key  conf/ssl/example.key;
  ssl_protocols TLSv1.2;  # CentOS7 OpenSSL 1.0.2
  ssl_ciphers HIGH:!aNULL:!MD5;
  # ... 其余与 :80 同步的 location
}

10. 监控与可观测性

10.1 Nginx 指标与日志

  • /nginx_status:当前连接、请求速率;
  • access.log:结合 GoAccess 或自建 ELK,观察 HLS 命中、端到端时延与 4xx/5xx。

10.2 FFmpeg 健康度

切片“新鲜度”检查(/usr/local/bin/check-hls-freshness.sh):

#!/bin/bash
set -e
root="$1" # /data/hls_live
now=$(date +%s)
while IFS= read -r -d '' m3u8; do
  ts=$(stat -c %Y "$m3u8")
  age=$((now - ts))
  if (( age > 20 )); then
    echo "STALE: $m3u8 is $age s old"
  fi
done < <(find "$root" -type f -name 'index.m3u8' -print0)

配合 */1 * * * * cron,输出到报警系统。

10.3 系统层

  • node_exporter + Prometheus + Grafana:CPU、磁盘 IO、网卡流量、文件句柄;
  • smartctl 监控 NVMe 健康度;
  • journalctl -u ffmpeg-live@* -f:实时观察转码日志。

11. 压测与优化

11.1 文件分发压测

# wrk 对单个 .ts/.m4s 做并发压测
wrk -t8 -c2000 -d60s --latency http://<server>/vod/demo/720/seg00001.m4s

Nginx 调优要点:

  • reuseport 打开,配合 worker_processes auto;
  • open_file_cache 合理设置,避免频繁 stat;
  • aio threads 有助于 NVMe 并发;
  • 关闭对媒体的 gzip;
  • sendfile on; tcp_nopush on;。

11.2 FFmpeg 调优

  • GOP 与 -hls_time 对齐(30fps → -g 60 配 -hls_time 2),减少切片边界花屏;
  • -max_muxing_queue_size 1024 处理复杂滤镜下的队列溢出;
  • 音频全量重采样到 48kHz,-ar 48000 -ac 2,避免播放端兼容问题。

12. 线上“坑位”与解决记录

现象 根因 解决
13: Permission denied 写不进 /data/hls_* SELinux 上下文未赋予 semanage fcontext + restorecon(见上)
观众端偶发 404 取不到 seg Nginx 缓存或并发下目录项延迟 open_file_cache + NVMe,必要时增大 inotify/fs 限制
播放端切档卡顿 GOP 与 hls_time 不匹配 固定帧率、-g-keyint_min 一致;-sc_threshold 0
大陆用户 HTTPS 首包慢 海外链路与 TLS handshake 前置 CDN,多点回源;TLS 会话复用;HTTP/2
Non monotonous DTS 警告 源流时间戳异常 -fflags +genpts 或仅对异常源做一次重封装
NVENC 质量不稳 预设与码控不当 -preset p4/p5(llhq/llhp)+ -rc vbr -cq 22~26,并设合理 -maxrate
OBS 能推流但 FFmpeg 不启动 RTMP 权限或地址错误 放开 allow publish 网段;检查 application 名与 stream key

13. 扩展与演进

  • 对象存储分层:转码完成的 VOD 自动同步至 MinIO/Ceph,Nginx 用 proxy_cache 或 s3 gateway 回源;
  • 多机房:香港主、海外/内地边缘分发,使用主动健康检查与 GeoDNS;
  • DASH 支持:并行产出 .mpd,浏览器端 ExoPlayer/Shaka 播放;
  • 自动化:Ansible/Terraform 声明式部署;
  • 熔断保护:live 路径切片“新鲜度”超阈值自动切换备用源。

14. 成本核算(样例)

项目 数量 单价(HKD/月) 小计
物理服务器(双 10GbE, NVMe×2) 1 3,800 3,800
带宽(专线 5Gbps 95 计费) 1 9,500 9,500
机柜/电力(1/4 柜) 1 2,000 2,000
证书/CDN(可选) - 视流量 -
合计(不含税)     约 15,300+

实际价格与合约相关,上述仅作预算参考。

15. 附:完整示例配置清单

15.1 nginx.conf(简版可用)

已在第 6 节给出;生产环境建议将 server 与 http 片段分拆,使用 include conf.d/*.conf。

15.2 systemd 服务

  • /etc/systemd/system/nginx.service
  • /etc/systemd/system/ffmpeg-live@.service

15.3 脚本

  • /usr/local/bin/vod-transcode.sh
  • /usr/local/bin/check-hls-freshness.sh

赋予执行权限:chmod +x,并用 tmux/screen 观察首次跑批日志。

16. 尾声:一次凌晨的“回放”

上线当天晚上 23:47,我坐在机房的冷通道口,手背被主机前面板的风吹到发凉。wrk 压测曲线稳定在我们预期值,Grafana 面板上的 95 线延迟稳稳落在 40ms 以下。凌晨 00:10,客户发来第一条观众截图:在厦门 4G 环境下 720p 流畅播放。我看了一眼 journalctl 里滚动的 FFmpeg 日志,又把机柜门关上,听着门锁“咔哒”一声落位——这套在 CentOS 7 上打磨出来的 Nginx + FFmpeg 一体化架构,总算在这个夜里通过了它的第一场考验。

目录结构
全文