1、了解 RTMP 协议
RTMP(Real Time Messaging Protocol)实时消息传输协议,基于TCP协议,一种流媒体协议,默认使用端口1935。用来解决多媒体数据传输流的多路复用(Multiplexing)和分包(packetizing)的问题。
RTMP 是应用层协议,要靠传输层协议(通常是TCP)来提供可靠传输,传输层建立连接之后,RTMP 也要通过 “握手” 来建立 RTMP connection。
2、了解 Nginx
Nginx 是一个高性能的 HTTP 和反向代理 Web 服务器。占有内存小,并发能力强,性能效率高,稳定性强,支持热部署。
热部署:程序在运行状态时,如果修改源码了,不用重新启动即可生效。
了解下面几个概念:
(1)正向代理&反向代理
- 正向代理
典型的例子就是VPN。当我们电脑登录了VPN之后,代理服务器就代理了我们的电脑,由它来向真正的服务器发起请求,真正的服务器将请求的内容发给代理服务器,代理服务器再将请求内容发给我们的电脑。在这个过程中,我们电脑(client)知道 server的存在,但是 server 不知道我们的电脑,server 不知道我们是通过 VPN 来访问的,对于 server 来说,就是代理服务器向它发起请求而已。
- 反向代理
例如我们访问百度都是通过同一个域名 www.baidu.com,但是背后真正被访问的服务器可能是广州的服务器,可能是杭州的服务器等等,所以域名为 www.baidu.com 的这台服务器就是一个反向代理,代理了背后真正的服务器。所以对于用户来说,感知的只有域名为 www.baidu.com 这台服务器,背后的服务器不管怎么动态扩容,用户都是不感知的。
(2)负载均衡
随着业务的不断增长和用户的不断增多,一台服务已经满足不了系统要求了,这个时候就出现了服务器集群。
那发起的请求到底分给哪台服务器来处理?怎么个分配法? 这就需要使用到负载均衡,负载均衡可以将工作分配到不同服务器上处理。有轮询法也有加权轮询法。
Nginx 还带有**健康检查**(服务器心跳检查)功能,会定期轮询向集群里的所有服务器发送健康检查请求,来检查集群中是否有服务器处于异常状态。
(3)动静分离
将静态内容(如HTML,css,jpg等)动态内容分离。对静态内容,可以先进行缓存。
3、nginx-rtmp-module
是 Nginx 中的一个模块,使 Nginx 可以支持 RTMP,用于音视频的点播、直播。
Nginx 加上 nginx-rtmp-module 模块作为 RTMP 服务端。
4、Linux 下搭建 RTMP 服务器
环境:Ubuntu 16.04
4.1 安装 Nginx
(1)安装依赖库
源码编译依赖gcc环境,并且部分 nginx 模块依赖于3个以上的库,其中包括:zlib,pcre,openssl,如果没有安装这3个库,则需要先安装
首先使用 dpkg 命令查看自己需要的软件是否安装。
例如查看zlib是否安装:dpkg -l | grep zlib
- 依赖包 openssl 安装:
sudo apt-get install openssl libssl-dev
- 依赖包 pcre 安装:
sudo apt-get install libpcre3 libpcre3-dev
- 依赖包 zlib 安装:
sudo apt-get install zlib1g-dev
(2)下载编译
将安装包下载到指定目录文件夹
cd /opt/nginx //进入目录
wget http://nginx.org/download/nginx-1.12.2.tar.gz //下载安装包
tar zxvf nginx-1.12.2.tar.gz //解压
(3)配置
cd nginx-1.12.2
./configure --help //列出大部分常用模块和编译选项
./configure //配置
默认情况下nginx将被配置到 /usr/local/nginx 目录下
(4)编译安装
make&&make install
(5)验证是否安装成功
/usr/local/nginx/sbin/nginx -v
如果有跟下图一样输出版本号,则安装成功啦!
(6)启动 nginx 服务
/usr/local/nginx/sbin/nginx
查看nginx进程信息
ps -ef|grep nginx
其中 master process 是主进程,1416 为主进程号,worker process 是工作进程。
nginx有一个主进程,多个工作进程,主进程主要用于读取和评估配置,维护工作进程;工作进程是对请求进行实际处理,工作进程的数量可以进行配置。
(7)加入自启动服务和系统服务
- 在 /etc/init.d 目录下创建名为 ”nginx” 的脚本文件,内容如下:
#!/bin/bash
set -e
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DESC="nginx daemon"
NAME=nginx
DAEMON=/usr/local/nginx/sbin/$NAME
SCRIPTNAME=/etc/init.d/$NAME
# If the daemon file is not found, terminate the script.
test -x $DAEMON || exit 0
d_start() {
$DAEMON || echo -n " already running"
}
d_stop() {
$DAEMON –s quit || echo -n " not running"
}
d_reload() {
$DAEMON –s reload || echo -n " could not reload"
}
case "$1" in
start)
echo -n "Starting $DESC: $NAME"
d_start
echo "."
;;
stop)
echo -n "Stopping $DESC: $NAME"
d_stop
echo "."
;;
reload)
echo -n "Reloading $DESC configuration..."
d_reload
echo "reloaded."
;;
restart)
echo -n "Restarting $DESC: $NAME"
d_stop
# Sleep for two seconds before starting again, this should give the
# Nginx daemon some time to perform a graceful stop.
sleep 2
d_start
echo "."
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|restart|reload}" >&2
exit 3
;;
esac
exit 0
注意上述的路径,如果和默认配置的不同则需要修改!
- 修改脚本文件的权限
chmod a+x /etc/init.d/nginx
- 修改 /etc/bash.bashrc 文件
在末尾添加一句 export PATH=/usr/local/nginx/sbin:$PATH
- 使更改配置生效
source /etc/bash.bashrc
- 加入开机自启动
此时需要 chkconfig 命令,如果没有此命令可以在终端输入以下命令安装
sudo apt install sysv-rc-conf
sudo cp /usr/sbin/sysv-rc-conf /usr/sbin/chkconfig
- 将服务加到自启
chkconfig nginx on
重启虚拟机,进行测试!
(8)检测服务是否可用
启动
service nginx start
停止
service nginx stop
重启
service nginx restart
查看状态
service nginx status
出现的问题:
使用 service nginx start 来启动 nginx 时出现 Failed to start nginx.service:unit not found
原因:没有添加 nginx.service
解决:安装 chkconfig,用 sysv-rc-conf 替代,但是没有 add 和 del 命令。
使用 on 选项将服务加到自启
chkconfig nginx on
这时需要重启虚拟机,才能生效!!!
4.2 Linux 安装 nginx-rtmp-module(NRM)
(1)浏览器打开 https://github.com/arut/nginx-rtmp-module 网址下载 nginx-rtmp-module 插件
或直接使用以下命令下载到 ubuntu 指定的目录下:
cd /opt/nginx/
wget -O nginx-rtmp-module.tar.gz https://codeload.github.com/arut/nginx-rtmp-module/legacy.tar.gz/master
tar zxvf nginx-rtmp-module.tar.gz
(2)重新进入之前解压过的 nginx 文件夹,配置 makefile,加入 NRM 模块
./configure --add-module=/opt/nginx/nginx-rtmp-module --prefix=/usr/local/nginx/ --with-debug
注意:/opt/nginx/nginx-rtmp-module 要替换成你自己的路径
(3)编译安装
make&&make install
(4)启动nginx
./nginx
至此 NRM 组件安装完成!
5、 Linux 使用 ffmpeg 将本地 mp4 文件推流到 RTMP 服务器,并用 ffplay 来拉流播放
前提:Linux 下安装有 ffmpeg(Ubuntu下使用 apt install ffmpeg 命令来安装)
(1)配置 Nginx
打开 Nginx 的配置文件:vi /usr/local/nginx/conf/nginx.conf
在对应位置添加如下内容:
#RTMP服务器的配置信息
rtmp {
server {
listen 1935; #监听的端口(默认)
chunk_size 4096; #数据传输块的大小(默认)
application video {
play /opt/nginx/video; #视频文件存放的位置,访问方式:rtmp://localhost:1935/video
}
}
}
注意:存放视频文件的文件夹包括里面的文件以及访问此文件所经过的文件层级都需要具有可读和可进入的权限,否则无法播放
(2)新建文件夹video,用于存放推流的音视频文件。并且拷贝一个MP4文件到该目录下,后面推流要用
mkdir /opt/nginx/video
(3)设置权限指令
chmod -R 555 /opt/nginx/video
(4)设置好之后需要对配置文件重新加载
service nginx reload
service nginx restart
如果无效,则还需重新启动 ubuntu 系统!!!
另外:在对配置文件重新加载前,可以先验证配置文件的正确性。
如果修改了配置文件 /usr/local/nginx/conf/nginx.conf,则在 nginx 启动之前,最好检查一下配置文件是否正确,以免在重启 nginx 之后出现错误,影响服务器的稳定运行,具体执行命令如下:
/usr/local/nginx/sbin/nginx -t
如果配置文件被正确执行则结果如下图所示:
(5)用 ffplay 进行接流播放
ffplay rtmp://192.168.137.9:1935/video/test.mp4
其中,192.168.137.9 改成你的虚拟机的IP地址
如果播放不成功,检查一下是否 url 路径编写出错,如果还是不行可以重新启动再做尝试。
出现的问题:
用 ffplay 播放时,出现下面的一些错误:
① RTMP_Connect0, failed to connect socket. 111 (Connection refused)
原因:没有开启nginx服务,或者是因为配置没有生效。如果 reload 和 restart 后还是不行,就重启虚拟机!
② [h264 @ 0x7fd620007dc0] missing picture in access unit with size 13705
[h264 @ 0x7fd620007dc0] no frame!
RTMP_ReadPacket, failed to read RTMP packet header
我觉得出现上述问题,要么是 URL 写错,如果检查之后,URL 并没有错误,那就是 mp4 视频文件有问题。我就是换了个文件来播放就可以了。😒无语,搞了我好久。
6、Linux 下使用 ffmpeg 推送摄像头画面到 RTMP 服务器,并用 ffplay 拉流播放
虚拟机下不能使用电脑自带的摄像头,所以需要自己额外连接一个摄像头,连接成功后,在 /dev 目录下会有一个字符设备文件 /dev/video0,这个文件就是指摄像头设备。
(1)配置 nginx
vi /usr/local/nginx/conf/nginx.conf
在对应位置添加如下内容:
application live {
live on; #开启直播
}
(2)设置好之后需要对配置文件重新加载
service nginx reload
service nginx restart
如果无效,则还需重新启动 ubuntu 系统!!!
(3)执行推流命令
ffmpeg -i /dev/video0 -codec libx264 -g 10 -f flv rtmp://192.168.137.9:1935/live/stream0
推流的 rtmp 格式:rtmp://192.168.xxx.xxx/live/streamname(IP地址修改为你的虚拟机的IP地址)
live 要与上面配置文件 nginx.conf 设置的直播标签名一致,streamname 是自己为流取的名称(任意名称)
只需要在接流时 url 格式与推流对应设置的 url 相同即可。
(4)ffplay 接流播放
ffplay rtmp://192.168.137.9:1935/live/stream0
出现的问题:
拉流的时候一直接收不到,一直没反应
解决:不要用 root 用户登录虚拟机,使用普通用户登录再来拉流
也不知道到底是不是这原因,反正切换普通用户登录后来拉流,确实就接收到流了。只是延时太长了,5s以上的延时。
注意:在 root 用户登录下,不要直接 su xxx 来切换用户,这时候会报错:No protocol specified
解决:关闭虚拟机,重新开启后用普通用户来登录。
7、Ubuntu 20.04 搭建 RTMP 服务器时出现的问题
(1)使用 apt-get 安装软件包时出现 E:Unable to locate package libssl-dev
解决:初次使用阿里云服务器,需要执行 apt-get update 更新软件包
(2)执行 make&&make install 安装 Nginx 时报错 src/os/unix/ngx_user.c:36:7: error: ‘struct crypt_data’ has no member named ‘current_salt’
可能是系统版本太高了。
解决:把报错的那一行代码注释掉
(3)接着编译,报错 src/core/ngx_murmurhash.c:37:11: error: this statement may fall through [-Werror=implicit-fallthrough=] 等信息
解决:进入到 nginx-1.12.2 目录下(即解压的目录),再进入当前目录下的 objs 文件夹,打开文件 Makefile,把下面这一行的 -Werror 去掉
-Werror: gcc将所有的警告当成错误进行处理
(4)Ubuntu20 下安装 sysv-rc-conf 报错:E: Unable to locate package sysv-rc-conf
解决:
- 编辑sources.list文件
sudo vi /etc/apt/sources.list
- 在软件源 sources.list 文件中添加如下一列文本
deb http://archive.ubuntu.com/ubuntu/ trusty main universe restricted multiverse
- 更新 apt-get
sudo apt-get update