问题描述

为了压测公司开发的某视频服务,需要配置一个后端推流服务,以flv over http的方式进行推送,可能要承载一千个连接(512码率的视频)。

步骤

安装ffmpeg

默认给我的机子是Cent OS 7.6,系统有点陈旧,内核也有点老,一开始想直接升级成Cent OS 8,但是换了个5.x的内核导致一些依赖出错,索性直接一键DD成Debian 10(运维那边也没有现成的系统)。

# 萌咖大佬的脚本
wget --no-check-certificate -qO InstallNET.sh 'https://moeclub.org/attachment/LinuxShell/InstallNET.sh'
# 华为云镜像站对公司网络友好些
bash InstallNET.sh -d 10 -v 64 -a --mirror 'https://mirrors.huaweicloud.com/debian/'

一键DD后的默认密码是MoeClub.org
让后换源

deb http://mirrors.huaweicloud.com/debian buster main contrib non-free
deb http://mirrors.huaweicloud.com/debian buster-updates main contrib non-free
deb http://mirrors.huaweicloud.com/debian buster-backports main contrib non-free
deb http://mirrors.huaweicloud.com/debian-security/ buster/updates main contrib non-free

换源之后安装ca-certificates,可以将上面的http换成https
随后安装ffmepg apt install ffmepg,成功后验证一下,输入ffmpeg

ffmpeg version 4.1.8-0+deb10u1 Copyright (c) 2000-2021 the FFmpeg developers
  built with gcc 8 (Debian 8.3.0-6)
  configuration: --prefix=/usr --extra-version=0+deb10u1 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --enable-gpl --disable-stripping --enable-avresample --disable-filter=resample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librsvg --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opengl --enable-sdl2 --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libx264 --enable-shared
  libavutil      56. 22.100 / 56. 22.100
  libavcodec     58. 35.100 / 58. 35.100
  libavformat    58. 20.100 / 58. 20.100
  libavdevice    58.  5.100 / 58.  5.100
  libavfilter     7. 40.101 /  7. 40.101
  libavresample   4.  0.  0 /  4.  0.  0
  libswscale      5.  3.100 /  5.  3.100
  libswresample   3.  3.100 /  3.  3.100
  libpostproc    55.  3.100 / 55.  3.100
Hyper fast Audio and Video encoder
usage: ffmpeg [options] [[infile options] -i infile]... {[outfile options] outfile}...

ffmpeg推流

推流命令是ffmpeg -re -i ./test.flv -c copy -f flv "rtmp://<IP地址>/live/http"./test.flv是flv文件的位置,"rtmp://<IP地址>/live/http" 则是推流的位置。

NGINX + nginx-http-flv-module 编译

下载NGINX 及 nginx-http-flv-module

wget http://nginx.org/download/nginx-1.20.2.tar.gz
wget https://github.com/winshining/nginx-http-flv-module/archive/refs/tags/v1.2.10.zip
tar -zxvf nginx-1.20.2.tar.gz
unzip nginx-http-flv-module-1.2.10.zip

随后编译

./configure 
    --prefix= /opt/nginx 
    --with-http_ssl_module \
    --with-http_secure_link_module \
    --add-module= ../nginx-http-flv-module-1.2.10
make -j$(($(nproc) + 1))
make install

安装成功后,启动nginx,输入命令/opt/nginx/sbin/nginx,测试一下。
随后修改配置文件/opt/nginx/conf/nginx.conf

worker_processes  4;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;
    server {
        listen       80;
        server_name  <IP地址>;

        location / {
            root   html;
            index  index.html index.htm;
        }

        location /flv {
            flv_live on;
            chunked_transfer_encoding on;
            add_header 'Access-Control-Allow-Origin' '*';
            add_header 'Access-Control-Allow-Credentials' 'true';
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

    }

}

rtmp_auto_push on;
rtmp {
    server {
        listen 1935;
        server_name 127.0.0.1;
        notify_method get;
        access_log  /var/log/nginx/access.log;
        chunk_size 4096;
        application live {
            live on;
            allow publish all;
            allow play all;
        }
    }
}

上述<IP地址>是希望监听的地址,如可以是localhost,或者是0.0.0.0,又或者是局域网IP/公网IP。

出现问题

以上方案进行推流,效果不是很理想,用VLC进行播放也会存在一定程度的卡顿,猜想原因可能是nginx对flv进行了切分,且nginx默认设置的buffer太大,导致buffer满了才发,然而对nginx动手脚也不是啥好办法,且还剩四小时就要验收(接的烂摊子)着实来不及。再网上重新调研后,我认为用srs搭建这个环境可能是比较不错的选择,抱着这种心态开始了进一步的尝试。

编译srs

srs比上面的方案好折腾地多。

# 直接下载最新的v4 beta 10
wget https://github.com/ossrs/srs/releases/download/v4.0-b10/srs-server-4.0-b10.tar.gz
tar -zxvf srs-server-4.0-b10.tar.gz
cd srs-4.0-b10/trunk && ./configure && make && make install

结束后,srs就会安装在/usr/local/srs下(想换个目录就去修改Makefile中的安装目录)。
写几个小脚本控制启动、关闭和状态查看。
start.sh

#!/bin/bash
./objs/srs -c conf/srs.conf

stop.sh

#!/bin/bash
./etc/init.d/srs stop

status.sh

#!/bin/bash
./etc/init.d/srs status

ffmpeg 推流遇到的问题

如上面所示,我一开始采用的推流,不过是重复播放一个test.flv文件,这才另一边播放时,就会产生一个问题,会读到flv文件的末尾,导致播放器认为视频中止。
对于这个问题,可以去修改srs的源码,在复制流时去掉flv文件的头和尾,或者用一种更加方便的方案,复制别的rtmp流,推送给srs。
可见以下命令
ffmpeg -i "rtmp://<某个RTMP流的IP地址>/live/http.flv" -c copy -f flv "rtmp://<IP地址>/live/http"
需要注意的时,如果ffmpeg推送了一个错误的/有问题的/空的流给srs,可能导致srs崩溃。

总结

直接糊nginx一时爽,糊完火葬场。srs部署简单,承载力也不错,经测试,完全能跑满服务器的带宽,同时对CPU和内存的占用也不大。