问题描述

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

步骤

安装ffmpeg

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

1
2
3
4
# 萌咖大佬的脚本
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
让后换源

1
2
3
4
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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

1
2
3
4
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

随后编译

1
2
3
4
5
6
7
./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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
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比上面的方案好折腾地多。

1
2
3
4
# 直接下载最新的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

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

stop.sh

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

status.sh

1
2
#!/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和内存的占用也不大。