Bootstrap

nginx实现,一推多用(rtmp推流,rtmp+flv+hls(m3u8)同时拉流),使用案例+使用方法

最近做到的项目使用nginx,要将一个摄像头的视频流推送给前端,并要求同时支持3种推流方式——rtmp,http-flv,hls(m3u8)。在使用nginx时,也是遇到了诸多问题,一度差点放弃,在此做个记录,同时也方便后来人。

使用案例

我是在tx2上做的,所以例子中使用的是gstreamer进行推流,你可以使用其他推流方式,比如ffmpeg或者obs。
由于nginx本身不支持http-flv,所以需要单独下载nginx-http-flv-module,重新进行编译,编译方式按照官网说明即可。https://github.com/winshining/nginx-http-flv-module

推流地址:rtmp://localhost:1935/live/stream_key
rtmp拉流地址:rtmp://localhost/live/stream_key
http-flv拉流地址:http://localhost:88/flv_live?port=1935&app=live&stream=stream_key
hls-m3u8拉流地址:http://localhost:88/hls/stream_key.m3u8

我使用的nginx.config,因为我使用的是动态编译(add-dynamic-module),所以第一行引入了load_module,静态编译是不需要的。

load_module /opt/nginx-1.19.1-rtmp/inst/modules/ngx_http_flv_live_module.so;

#user  nobody;
worker_processes  1;

error_log  logs/error.log;
error_log  logs/error.log  notice;
error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


rtmp {
    out_queue		4096;
    out_cork	        8;
    max_streams 	128;
    timeout		15s;
    drop_idle_publisher 15s;
    log_interval	5s; #interval used by log module to log in access.log, it is very useful for debug
    log_size		1m; #buffer size used by log module to log in access.log

    server {
        listen 1935;
	#chunk_size 4096;
	server_name localhost; #for suffix wildcard matching of virtual host

        application live {
            live on;
	    gop_cache on; #open GOP cache for reducing the wating time for the first picture of video
	
	    #live on;
	    hls on;
	    hls_path /tmp/hls;
	    hls_fragment 10s;
	    # hls_playlist_length 60s;
	    #hls_continuous on;
	    #hls_cleanup on;
	    #hls_nested on;
	    wait_key on;
	    #meta off;
	    #allow play all;
        }
	
    }
}

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

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    server {
        listen       88;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;
	location /stat {
	    rtmp_stat all;
	    rtmp_stat_stylesheet stat.xsl;
	}
	
	location /stat.xsl {
	    root /opt/nginx-1.19.1-rtmp/nginx-http-flv-module/;
	}
        location /flv_live {
            flv_live on;
            chunked_transfer_encoding on;
            add_header 'Access-Control-Allow-Origin' '*';
            add_header 'Access-Control-Allow-Credentials' 'true';
	}

	location /hls {
	    types {
              application/vnd.apple.mpegurl m3u8;
              video/mp2t ts;
            }
	    alias /tmp/hls;   
	    expires -1;
	    add_header 'Cache-Control' 'no-cache'; 
	}
	location / {
	    root html;
	    index index.html index.htm;
	}
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}
使用方法

有些经验的朋友,通过上面的成功案例,应该可以自己推导出使用方法。所以我把方法分开写到了下面。我将分成两部分说明,第一部分作为上面案例的使用指导,第二部分作为nginx的使用拓展(不会很深,只是我就了解到这里,已经比csdn上绝大多数帖子详细了)。

第一部分
  1. 在config中主要有两部分——rtmp和http,原则上,我们认为rtmp是推流,http是拉流。(并不完全正确,下面说明)
    直接见注释。rtmp配置好以后,就可以接受推流了,如果不加http结构,直接使用rtmp拉流也是完全可以的,因为rtmp的推拉流地址本就是一个,都不走其他端口的(如果你想要的这样的功能,可以完全去掉推流上的其他支持)
rtmp {
    out_queue		4096;
    out_cork	        8;
    max_streams 	128;
    timeout		15s;
    drop_idle_publisher 15s;
    log_interval	5s; #interval used by log module to log in access.log, it is very useful for debug
    log_size		1m; #buffer size used by log module to log in access.log

    server {
    	listen 1935;	# 推流使用的端口,默认1935端口在推流拉流时都可以省略,改为其他端口需要指定
		#chunk_size 4096;
		server_name localhost; #for suffix wildcard matching of virtual host

        application live {
        live on;		#开启直播
	    gop_cache on; #open GOP cache for reducing the wating time for the first picture of video
	
	    #live on;
	    hls on;		# 支持m3u8
	    hls_path /tmp/hls;	# m3u8 文件的保存位置,检验配置是否成功,可以推流后cd到该目录下,看一下有没有文件生成,有文件的话就可以判定不是推流配置的问题。
	    hls_fragment 10s;	# 每个视频保存10s
	    # hls_playlist_length 60s;
	    #hls_continuous on;
	    #hls_cleanup on;
	    #hls_nested on;
	    wait_key on;
	    #meta off;
	    #allow play all;
        }
    }
}

http拉流配置,http协议的拉流需要走http下面配置的端口,所以在地址中也有体现。

http://localhost:88/flv_live?port=1935&app=live&stream=stream_key
规则(注意两个port、dir、appname):http://example.com[:port]/dir?[port=xxx&]app=appname&stream=streamname

http://localhost:88/hls/stream_key.m3u8
规则:http://example.com[:port]/dir/streamname

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

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    server {
        listen       88;		# 拉流使用的端口,使用默认端口80时,拉流时可不指定
        server_name  localhost;

        #charset koi8-r;

   	#access_log  logs/host.access.log  main;
   	
   	# 查看状态的部分,下部分介绍,不需要可去掉
	location /stat {
	    rtmp_stat all;
	    rtmp_stat_stylesheet stat.xsl;
	}
	# 查看状态的部分,下部分介绍,不需要可去掉
	location /stat.xsl {
	    root /opt/nginx-1.19.1-rtmp/nginx-http-flv-module/;
	}
	# 拉http-flv的配置
    location /flv_live {	
            flv_live on;
            chunked_transfer_encoding on;
            add_header 'Access-Control-Allow-Origin' '*';
            add_header 'Access-Control-Allow-Credentials' 'true';
	}
	# 拉hls的配置
	location /hls {
	    types {
              application/vnd.apple.mpegurl m3u8;
              video/mp2t ts;
            }
	    alias /tmp/hls;   # 读取文件的位置,应和上面rtmp中的配置一样
	    expires -1;
	    add_header 'Cache-Control' 'no-cache'; 
	}
	location / {
	    root html;
	    index index.html index.htm;
	}
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
        }
    }
}
第二部分
  1. 可直接查看实时的推流状态,在地址栏直接输入http中配置到的stat部分,地址+stat
    http://localhost:88/stat
;