OSSRS搭建rtmp推流服务器

2019-10-22 17:21:07 浏览数 (1)

准备

文中测试视频:https://pan.baidu.com/s/1Cs9bULQ26zmDjbNqiIyUow 密码:q839

SRS官网:http://winlinvip.github.io/srs.release/releases/

SRS源码:https://github.com/ossrs/srs

直播方案对比

详见下表:

分发

平台

协议

公司

说明

RTMP

Windows Flash

RTMP

Adobe

主流的低延时分发方式, Adobe对RTMP是Flash原生支持方式, FMS(Adobe Media Server前身), 就是Flash Media Server的简写,可见Flash播放RTMP是多么“原生”, 就像浏览器打开http网页一样“原生”, 经测试,Flash播放RTMP流可以10天以上不间断播放。

HLS

Apple/ Android

HTTP

Apple/ Google

延时一个切片以上(一般10秒以上), Apple平台上HLS的效果比PC的RTMP还要好, 而且Apple所有设备都支持, Android最初不支持HLS,后来也支持了, 但测试发现支持得还不如Apple, 不过观看是没有问题,稳定性稍差, 所以有些公司专门做Android上的流媒体播放器。

便捷安装

当流服务器不涉及ffmpeg操作时用该方式

下面这种方式是直接安装官方编译过的,里面不包含ffmpeg库,

如果需要ffmpeg处理流的话需要自行下载ffmpeg,或者用下文编译源码的方式(推荐)

代码语言:javascript复制
cd /root
wget http://winlinvip.github.io/srs.release/releases/files/SRS-CentOS6-x86_64-2.0.243.zip
unzip -q SRS-CentOS6-x86_64-2.0.243.zip
cd SRS-CentOS6-x86_64-*
sudo bash INSTALL
sudo /etc/init.d/srs start

srs安装后的目录为/usr/local/srs

abort, please install lsb_release

代码语言:javascript复制
yum install -y redhat-lsb

RTMP URL格式:

代码语言:javascript复制
rtmp://ip:[port]/appName/streamName

例如:

代码语言:javascript复制
rtmp://192.168.1.108:1935/live/xiaoming

编译安装

当流服务器涉及ffmpeg操作时用该方式

下面下载官方源码编译,Github下载太慢,我就在gitee上做了个镜像。

这里之所以编译源码是因为之前的直接安装方式并不提供三方的库,比如接下来要用的ffmpeg;

当然我们也可以自己手动安装ffmpeg,然后修改配置文件中默认的ffmpeg路径即可。

注意这里ffmpeg一定要用4.1版本 srs在4.2版本下部分语法不支持 这里坑了我好久 如果之前安装过4.2版本的一定要先删除

查看ffmpeg版本

代码语言:javascript复制
ffmpeg -version

安装srs

代码语言:javascript复制
cd ~
git clone https://gitee.com/psvmc/srs.git
cp -rf srs/trunk /usr/local/srs2
cd /usr/local/srs2
./configure --full
make

这里没有用下面这种方式安装

代码语言:javascript复制
./configure --prefix=/usr/local/srs2 --with-ffmpeg
make && make install

是因为这样安装后ffmpeg的文件夹并没有生成 还要手动再复制过去


我这里安装ffmpeg编译报错

build ffmpeg failed build ffmpeg-4.1 failed, ret=1

本来srs的编译已经包含x264ffmpeg,我这报错就只能自己手动安装了

上面安装成功的就不用再执行以下命令了

安装编译环境

代码语言:javascript复制
yum install -y automake autoconf libtool gcc gcc-c   
yum install -y make

安装yasm插件

代码语言:javascript复制
wget http://www.tortall.net/projects/yasm/releases/yasm-1.3.0.tar.gz
tar -xvf yasm-1.3.0.tar.gz
cd yasm-1.3.0/
./configure && make && make install

安装nasm

代码语言:javascript复制
cd ~
wget https://www.nasm.us/pub/nasm/releasebuilds/2.14.02/nasm-2.14.02.tar.gz
tar -zxvf nasm-2.14.02.tar.gz
cd nasm-2.14.02
./configure
make && make install
cd ..

安装 srs

代码语言:javascript复制
yum install -y git
# 下载
rm -rf /usr/local/srs2
cd ~
git clone https://gitee.com/psvmc/srs.git
cp -rf srs/trunk /usr/local/srs2

# 安装三方依赖
cd /usr/local/srs2/3rdparty/

# 安装 x264:
wget https://code.videolan.org/videolan/x264/-/archive/stable/x264-stable.tar.gz
tar -zxvf x264-stable.tar.gz
cd x264-stable
./configure --enable-static --enable-shared 
make && make install
cd ..

# 安装fdk-aac
wget https://jaist.dl.sourceforge.net/project/opencore-amr/fdk-aac/fdk-aac-0.1.5.tar.gz
tar -zxvf fdk-aac-0.1.5.tar.gz
cd fdk-aac-0.1.5
./configure 
make && make install
cd ..

# 安装 ffmpeg:
unzip ffmpeg-4.1.zip
cd ffmpeg-4.1
./configure --enable-gpl --enable-libx264 --enable-nonfree --enable-libfdk-aac
make && make install

# 安装 srs:
cd /usr/local/srs2
./configure --full
make

测试ffmpeg

代码语言:javascript复制
ffmpeg -version

报错:

ffmpeg: error while loading shared libraries: libx264.so.157: cannot open sh

解决方法

代码语言:javascript复制
vi /etc/ld.so.conf

添加libx264.so所在路径

代码语言:javascript复制
/usr/local/lib

退出后执行

代码语言:javascript复制
ldconfig

低延迟配置运行

代码语言:javascript复制
cd /usr/local/srs
nohup ./objs/srs -c conf/realtime.conf>log.txt &

结束进程

代码语言:javascript复制
lsof -i:1935
kill -9 PID

常用配置

低延迟配置

代码语言:javascript复制
listen              1935;
max_connections     1000;
daemon              off;
srs_log_tank        console;
vhost __defaultVhost__ {
    gop_cache       off;
    queue_length    10;
    min_latency     on;
    mr {
        enabled     off;
    }
    mw_latency      100;
    tcp_nodelay     on;
}

安全策略

详细配置:https://github.com/ossrs/srs/wiki/v2_CN_Security

目前只支持基于IP的安全策略,实用性不大。

代码语言:javascript复制
vhost your_vhost {
    # security for host to allow or deny clients.
    # @see https://github.com/ossrs/srs/issues/211   
    security {
        # whether enable the security for vhost.
        # default: off
        enabled         on;
        # the security list, each item format as:
        #       allow|deny    publish|play    all|<ip>
        # for example:
        #       allow           publish     all;
        #       deny            publish     all;
        #       allow           publish     127.0.0.1;
        #       deny            publish     127.0.0.1;
        #       allow           play        all;
        #       deny            play        all;
        #       allow           play        127.0.0.1;
        #       deny            play        127.0.0.1;
        # SRS apply the following simple strategies one by one:
        #       1. allow all if security disabled.
        #       2. default to deny all when security enabled.
        #       3. allow if matches allow strategy.
        #       4. deny if matches deny strategy.
        allow           play        all;
        allow           publish     all;
    }
}

本地录制FLV

详细配置:https://github.com/ossrs/srs/wiki/v2_CN_DVR

直播流保存本地文件。

代码语言:javascript复制
vhost __defaultVhost__ {
    dvr {
        enabled         on;
        dvr_path        /data/rtmplive/[app]/[stream]/[2006]/[01]_[02]/[15]_[04]_[05]_[999].flv;
        dvr_plan        session;
        dvr_duration    30;
        dvr_wait_keyframe on;
        time_jitter    full;
    }
}

流转发

详细配置:https://github.com/ossrs/srs/wiki/v1_CN_SampleForward

代码语言:javascript复制
vhost __defaultVhost__ {
    forward         127.0.0.1:19350;
}

Forward VS Edge

Forward架构和CDN架构的最大区别在于,CDN属于大规模集群,边缘节点会有成千上万台,源站2台(做热备),还需要有中间层。CDN的客户很多,流也会有很多。所以假若源站将每个流都转发给边缘,会造成巨大的浪费(有很多流只有少数节点需要)。

可见,forward只适用于所有边缘节点都需要所有的流。CDN是某些边缘节点需要某些流。

forward的瓶颈在于流的数目,假设每个SRS只侦听一个端口:

代码语言:javascript复制
系统中流的数目 = 编码器的流数目 × 节点数目 × 端口数目

考虑5个节点,每个节点起4个端口,即有20个SRS边缘。编码器出5路流,则有20 * 5 = 100路流

同样的架构,对于CDN的边缘节点来讲,系统的流数为用户访问边缘节点的流,假设没有用户访问,系统中就没有流量。某个区域的用户访问某个节点上的流,系统中只有一路流,而不是forward广播式的多路流。

另外,forward需要播放器随机访问多个端口,实现负载均衡,或者播放器访问api服务器,api服务器实现负载均衡,对于CDN来讲也不合适(需要客户改播放器)。

总之,forward适用于小型规模的集群,不适用于CDN大规模集群应用。

转封装成FLV流

详细配置:https://github.com/ossrs/srs/wiki/v2_CN_SampleHttpFlv

代码语言:javascript复制
listen              1935;
max_connections     1000;
http_server {
    enabled         on;
    listen          8080;
    dir             ./objs/nginx/html;
}
vhost __defaultVhost__ {
    http_remux {
        enabled     on;
        mount       [vhost]/[app]/[stream].flv;
        hstrs       on;
    }
}

生成的流地址为:

  • RTMP流地址为:rtmp://rtmp.psvmc.cn/live/livestream
  • HTTP FLV: http://rtmp.psvmc.cn:8080/live/livestream.flv

转封装成HLS流

详细配置:https://github.com/ossrs/srs/wiki/v2_CN_SampleHLS

代码语言:javascript复制
listen              1935;
max_connections     1000;
vhost __defaultVhost__ {
    hls {
        enabled         on;
        hls_path        ./objs/nginx/html;
        hls_fragment    10;
        hls_window      60;
    }
}

生成的流地址为:

  • RTMP流地址为:rtmp://rtmp.psvmc.cn/live/livestream
  • HLS流地址为: http://rtmp.psvmc.cn/live/livestream.m3u8

HTTP回调

详细配置:https://github.com/ossrs/srs/wiki/v2_CN_HTTPCallback

代码语言:javascript复制
vhost __defaultVhost__ {
    http_hooks {
        enabled         on;
        on_connect      http://127.0.0.1:8085/api/v1/clients http://localhost:8085/api/v1/clients;
        on_close        http://127.0.0.1:8085/api/v1/clients http://localhost:8085/api/v1/clients;
        on_publish      http://127.0.0.1:8085/api/v1/streams http://localhost:8085/api/v1/streams;
        on_unpublish    http://127.0.0.1:8085/api/v1/streams http://localhost:8085/api/v1/streams;
        on_play         http://127.0.0.1:8085/api/v1/sessions http://localhost:8085/api/v1/sessions;
        on_stop         http://127.0.0.1:8085/api/v1/sessions http://localhost:8085/api/v1/sessions;
        on_dvr          http://127.0.0.1:8085/api/v1/dvrs http://localhost:8085/api/v1/dvrs;
        on_hls 					http://127.0.0.1:8085/api/v1/hls http://localhost:8085/api/v1/hls;
        on_hls_notify 	http://127.0.0.1:8085/api/v1/hls/[app]/[stream]/[ts_url][param];
    }
}

SRS的回调事件包括:

事件

数据

说明

on_connect

{ “action”: “on_connect”, “client_id”: 1985, “ip”: “192.168.1.10”, “vhost”: “video.test.com”, “app”: “live”, “tcUrl”: “rtmp://x/x?key=xxx”, “pageUrl”: “http://x/x.html" }

当客户端连接到指定的vhost和app时

on_close

{ “action”: “on_close”, “client_id”: 1985, “ip”: “192.168.1.10”, “vhost”: “video.test.com”, “app”: “live”, “send_bytes”: 10240, “recv_bytes”: 10240 }

当客户端关闭连接,或者SRS主动关闭连接时

on_publish

{ “action”: “on_publish”, “client_id”: 1985, “ip”: “192.168.1.10”, “vhost”: “video.test.com”, “app”: “live”, “tcUrl”: “rtmp://x/x?key=xxx”, “stream”: “livestream” }

推流到服务器时

on_unpublish

{ “action”: “on_unpublish”, “client_id”: 1985, “ip”: “192.168.1.10”, “vhost”: “video.test.com”, “app”: “live”, “stream”: “livestream” }

当客户端停止发布流时

on_play

{ “action”: “on_play”, “client_id”: 1985, “ip”: “192.168.1.10”, “vhost”: “video.test.com”, “app”: “live”, “stream”: “livestream”, “pageUrl”: “http://a.com/i.html", “param”:”?k=v” }

当客户端开始播放流时

on_stop

{ “action”: “on_stop”, “client_id”: 1985, “ip”: “192.168.1.10”, “vhost”: “video.test.com”, “app”: “live”, “stream”: “livestream” }

当客户端停止播放时。备注:停止播放可能不会关闭连接,还能再继续播放。

on_dvr

{ “action”: “on_dvr”, “client_id”: 1985, “ip”: “192.168.1.10”, “vhost”: “video.test.com”, “app”: “live”, “stream”: “livestream”, “cwd”: “/opt”, “file”: “./l.xxx.flv” }

当DVR录制关闭一个flv文件时

其中:

  • 事件:发生该事件时,即回调指定的HTTP地址。
  • HTTP地址:可以支持多个,以空格分隔,SRS会依次回调这些接口。
  • 数据:SRS将数据POST到HTTP接口。
  • 返回值:SRS要求HTTP服务器返回HTTP200并且response内容为整数错误码(0表示成功),其他错误码会断开客户端连接。

启动自带接口服务器

代码语言:javascript复制
python research/api-server/server.py 8085

启动srs

代码语言:javascript复制
./objs/srs -c conf/http.hooks.callback.conf

测试推流

代码语言:javascript复制
ffmpeg -re -stream_loop -1 -i /data/rtmptest.mp4 -vcodec copy -acodec copy -f flv -y rtmp://127.0.0.1:1935/live/test

FFMpeg转码

详细配置:

  • https://github.com/ossrs/srs/wiki/v2_CN_SampleFFMPEG
  • https://github.com/ossrs/srs/wiki/v2_CN_FFMPEG

用于流处理或处理并转发RTMP服务器。

SRS转码的主要流程包括:

  1. 编码器推送RTMP流到SRS的vhost。
  2. SRS的vhost若配置了转码,则进行转码。
  3. 转码后,按照配置,推送到SRS本身或者其他RTMP服务器。

流处理

代码语言:javascript复制
listen              1935;
max_connections     1000;
daemon              off;
srs_log_tank        console;
vhost __defaultVhost__ {
    transcode {
        enabled     on;
        ffmpeg      ./objs/ffmpeg/bin/ffmpeg;
        engine ff {
            enabled         on;
            vfilter {
            }
            vcodec          libx264;
            vthreads        4;
            vprofile        main;
            vpreset         medium;
            vparams {
            }
            acodec          libfdk_aac;
            aparams {
            }
            output          rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine];
        }
    }
}

处理并转发RTMP服务器

代码语言:javascript复制
vhost __defaultVhost__ {
	transcode {
        enabled     on;
        ffmpeg      ./objs/ffmpeg/bin/ffmpeg;
        engine ff {
            enabled         on;
            vfilter {
            }
            vcodec          copy;
            acodec          copy;
            output          rtmp://livepush.psvmc.cn/live/test;
        }
    }
}

启动

代码语言:javascript复制
cd /usr/local/srs2
./objs/srs -c conf/ffmpeg.transcode.conf
# 或
nohup ./objs/srs -c conf/ffmpeg.transcode.conf>log.txt &

推流

代码语言:javascript复制
ffmpeg -re -stream_loop -1 -i /usr/local/srs2/doc/source.200kbps.768x320.flv -vcodec copy -acodec copy -f flv -y rtmp://127.0.0.1:1935/live/test

测试服务器上ffmpeg是否能处理流成功

代码语言:javascript复制
ffmpeg -f flv -i rtmp://127.0.0.1:1935/live/test -vcodec libx264 -threads 4 -profile:v main -preset medium -acodec copy -f flv -y rtmp://127.0.0.1:1935/live/test2

涉及的流包括:

  • 编码器推送流:rtmp://rtmp.psvmc.cn:1935/live/test
  • 观看原始流:rtmp://rtmp.psvmc.cn:1935/live/test
  • 命令转码流:rtmp://rtmp.psvmc.cn:1935/live/test2
  • 观看转码流:rtmp://rtmp.psvmc.cn:1935/live/test_ff

示例配置

配置路径:/usr/local/srs/conf/z.conf

代码语言:javascript复制
listen              1935;
max_connections     1000;
daemon              off;
srs_log_tank        console;
http_server {
    enabled         on;
    listen          8080;
    dir             ./objs/nginx/html;
}
vhost __defaultVhost__ {
    gop_cache       off;
    queue_length    10;
    min_latency     on;
    mr {
        enabled     off;
    }
    mw_latency      100;
    tcp_nodelay     on;
	  dvr {
        enabled         on;
        dvr_path        /data/rtmplive/[app]/[stream]/[2006]/[01]_[02]/[15]_[04]_[05]_[999].flv;
        dvr_plan        session;
        dvr_duration    30;
        dvr_wait_keyframe       on;
        time_jitter    full;
    }
	  http_remux {
        enabled     on;
        mount       [vhost]/[app]/[stream].flv;
        hstrs       on;
    }
}

结束

代码语言:javascript复制
lsof -i:1935
kill pid

启动

代码语言:javascript复制
cd /usr/local/srs
nohup ./objs/srs -c conf/z.conf>./log.txt &

推流

代码语言:javascript复制
ffmpeg -re -stream_loop -1 -i /data/rtmptest.mp4 -vcodec copy -acodec copy -f flv -y rtmp://rtmp.psvmc.cn:1935/live/test

低版本FFMpeg循环播放

代码语言:javascript复制
for((;;)); do 
  /usr/bin/ffmpeg -re -i /data/rtmptest.mp4 
  -vcodec copy -acodec copy 
  -f flv -y rtmp://rtmp.psvmc.cn:1935/live/test; 
  sleep 1; 
done

播放地址

  • rtmp://rtmp.psvmc.cn:1935/live/test
  • http://rtmp.psvmc.cn:8080/live/test.flv

0 人点赞