使用ffmpeg推流的rtmp协议视频无法在浏览器中播放,因此本文使用Nginx作为一个服务器,将rtmp协议的媒体流转换为http+flv格式

安装Nginx与nginx-http-flv-module

下载nginx-http-flv-module源码

1
git clone https://github.com/winshining/nginx-http-flv-module.git

下载nginx源码

1
2
wget https://nginx.org/download/nginx-1.24.0.tar.gz
tar xzf nginx-1.24.0.tar.gz

也可以在Nginx官网查看需要的版本。

安装pcre、zlib、openssl

1
sudo apt install libpcre3 libpcre3-dev zlib1g-dev openssl libssl-dev

开始编译,需要把/path/to/nginx-http-flv-module替换为nginx-http-flv-module源码的下载目录,我这里是/home/sun/nginx-http-flv-module

1
2
3
4
cd nginx-1.24.0/
./configure --add-module=/path/to/nginx-http-flv-module
make
sudo make install

Nginx配置

打开/usr/local/nginx/conf目录,修改nginx.conf配置文件。

我这里把http服务器设置为8080,rtmp服务器设为1935,这里需要注意的是,如果要访问http://localhost:8080/stat来查看Nginx服务器运行情况,需要把nginx-http-flv-module源码目录下的stat.xsl文件拷贝至/var/www/rtmp/文件夹。

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
worker_processes  1;	#worker进程的数量
error_log logs/error.log error;

events {
worker_connections 1024; #每个worker进程可以接收多少个网络连接
}

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

server {
listen 8080;
server_name localhost;

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

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

location /live {
flv_live on; #open flv live streaming (subscribe)
chunked_transfer_encoding on; #open 'Transfer-Encoding: chunked' response
#不增加以下这两行配置的话,无法使用浏览器获取视频流
add_header 'Access-Control-Allow-Origin' '*'; #add additional HTTP header
add_header 'Access-Control-Allow-Credentials' 'true'; #add additional HTTP header
}

location /stat {
#configuration of streaming & recording statistics

rtmp_stat all;
rtmp_stat_stylesheet stat.xsl;
}

location /stat.xsl {
root /var/www/rtmp; #specify in where stat.xsl located
}

location /control {
rtmp_control all; #configuration of control module of rtmp
}
}
}

rtmp_auto_push on;
rtmp_auto_push_reconnect 1s;
rtmp_socket_dir /tmp;

rtmp {
out_queue 4096;
out_cork 16;
max_streams 128;
timeout 15s;
drop_idle_publisher 15s;

log_interval 5s; #log 模块在 access.log 中记录日志的间隔时间,对调试非常有用
log_size 1m; #log 模块用来记录日志的缓冲区大小

server {
listen 1935;
server_name localhost;

application myapp {
live on;
gop_cache off; #open GOP cache for low latency
}
}
}

推流地址为rtmp://example.com[:port]/appname/streamname,根据以上配置,本机的地址为:

1
rtmp://127.0.0.1:1935/myapp/mystream

拉流地址为http://example.com[:port]/dir?[port=xxx&]app=appname&stream=streamname,根据以上配置,本机的地址为:

1
http://127.0.0.1:8080/live?port=1935&app=myapp&stream=mystream

推流至Nginx服务器

nginx的使用命令如下:

1
2
3
4
sudo /usr/local/nginx/sbin/nginx -t #检查配置文件是否正确
sudo /usr/local/nginx/sbin/nginx #启动nginx服务器
sudo /usr/local/nginx/sbin/nginx -s stop #关闭nginx服务器
sudo /usr/local/nginx/sbin/nginx -s reload #重启nginx服务器

使用ffmpeg读取摄像头的内容并编码成h264格式并使用rtmp协议推流至nginx服务器中

1
~/bin/ffmpeg -input_format mjpeg  -video_size 640x480 -f v4l2  -i /dev/video0 -c:v libx264 -tune zerolatency -preset ultrafast -g 1 -f flv rtmp://127.0.0.1:1935/myapp/mystream

-g 1表示关键帧间隔为1, -tune zerolatency表示编码器的参数配置为低延迟做优化,-preset ultrafast表示降低输出画质以降低cpu利用率、提高编码速度。

这里也可以使用OBS来进行推流,需要注意,此时推流地址为rtmp://127.0.0.1:1935/myapp,推流码为mystream

使用ffplay查看http+flv格式的直播

1
2
~/bin/ffplay "http://127.0.0.1:8080/live?port=1935&app=myapp&stream=mystream"
~/bin/ffplay "http://192.168.164.33:8080/live?port=1935&app=myapp&stream=mystream"

经过测试,这样会有2~3秒的延迟,在ffplay命令中添加-fflags nobuffer选项可以实现1秒左右的延迟

1
2
~/bin/ffplay "http://127.0.0.1:8080/live?port=1935&app=myapp&stream=mystream" -fflags nobuffer
~/bin/ffplay "http://192.168.164.33:8080/live?port=1935&app=myapp&stream=mystream" -fflags nobuffer