SeventySevenChina

nginx-rtmp 实现直播

需求描述:海康NVR内网摄像头在外网进行播放.

问题原因:由于海康布置在无法转入/映射的内网环境,仅能通过内部网络发送出来,所以需要对海康RTSP视频流进行拉取转推送,以下是解决办法.

一.内网转发服务器安装nginx-rtmp for docker

这里之所以使用docker 主要是我懒,有现成的可以用.

#拉取镜像
docker pull alfg/nginx-rtmp # docker 拉取已经封装好的nginx-rtmp镜像
docker pull tiangolo/nginx-rtmp # 这个镜像也可以 看你喜欢 
#启动demo
docker run -d --name de tiangolo/nginx-rtmp  # 后台启动镜像 这里不用管他端口问题 反正一会就删了
docker ps #查看启动成功没有
#复制配置文件到本地
mkdir /seventyseven/nginx-rtmp #建立docker nginx 配置文件存放位置
cd /seventyseven/nginx-rtmp #进入目录
mkdir conf #配置文件地址
mkdir data #映射data文件地址(访问页面位置)
docker cp de:/etc/nginx /seventyseven/nginx-rtmp/conf #将demo中的配置文件复制到本机/seventyseven/nginx-rtmp/conf目录 之所以这样做是因为直接-v映射总是启动失败,配置文件不见了,可能有更好的解决办法,但是我这样解决了就不管他了
#删除demo
docker stop de #停止容器
docker rm de #删除容器
#正式启动nginx-rtmp
docker run -d --name my_nginx_rtmp -p [直播推流端口]:1935 -p [http浏览端口]:80 -v /seventyseven/nginx-rtmp/conf:/etc/nginx -v /seventyseven/nginx-rtmp/data:/nginxdata tiangolo/nginx-rtmp #启动nginx
#注意↑:1935为nginx默认配置端口,如果你要自己改 可以这里随便写,之后改配置文件即可
docker ps #查看启动是否完成

看到这个结果则说明启动完成

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
63da tiangolo/nginx-rtmp "ngin of…" 5 days ago Up 2 hours 0.0.0.0:1935->1935/tcp, 0.0.0.0:50001->80/tcp nginx-rtmp

然后打开配置文件我们来改一下配置

cd /seventyseven/nginx-rtmp/conf #进入配置文件目录
vi nginx.conf  #配置文件如下
# rtmp conf
worker_processes auto;
rtmp_auto_push on;
events {}
rtmp {
    server {
        listen 1935; 
        listen [::]:1935 ipv6only=on; 
        application live { 
            live on;       
            record off;
        }
application hls {          
            live on; 
            hls on;
            hls_path /nginxdata; # 这里跟启动命令-v /seventyseven/nginx-rtmp/data:/nginxdata 对应上
            hls_fragment 5s;
            record off;
        }
    }
}

后面会对rtmp.conf做全配置详解 这里仅展示demo使用的conf

二.启动OBS进行模拟推流

OBS软件怎么用这里就不作介绍了.

推流地址:rtmp://[你的ip]:1935/hls

obs中有一个密钥的东西,虽然这个软件叫做密钥,实质上就是给你的视频流取一个名称比如demo123

等待obs推流成功后,则 服务器/seventyseven/nginx/data 文件中则会出现demo123.m3u8 文件 出现文件则说明流已经推送成功 跳转五.VLC播放器验证推流是否成功 进行验证流是否可以播放

此处播放地址为: rtmp://[你的ip]:1935/hls/demo123

三.转发服务器安装ffmpeg for windows

ffmpeg下载地址:http://ffmpeg.org/download.html

这里贴出的是其官网地址,没有贴github主要是因为这玩意源码我不会打包,C++写的我看的很懵逼

由于前面需求的原因,这里我使用的是windows版本,直接下载解压到任意目录即可.

其目录树为:

ffmpeg-N-103179-gac0408522a-win64-gpl

  • bin

    • doc

此处将bin目录添加windows环境变量

cmd ->  ffmpeg -version
ffmpeg version N-103179-gac0408522a-20210808 Copyright (c) 2000-2021 the FFmpeg developers #看到这个则说明安装完成

四.首次转发推流

ffmpeg 命令:

ffmpeg -i rtsp://原流地址 -vcodec copy -acodec copy -c:v libx264 -f flv rtmp://[你的ip]:1935/hls/demo123

如果启动成功则转发推流完成 附录有ffmpeg 详细说明 附录.ffmpeg使用详解

这里主要说一下这个 -c:v libx264 之所以要加上这一串,由于海康摄像头过来的流是h264的 直接转flv会失败,各种百度最后找到的解决办法

正常情况不需要加

转发成功后五.VLC播放器验证推流是否成功 进行验证

五.VLC播放器验证推流是否成功

VLC->媒体->打开网络串流->播放地址

等待播放即可

如果播放失败,检查

1.是否是rtmp/rtsp/http/https开头

2.服务器端口是否开启

3.是否已经有了***.M3U8文件

4.文件名称即obs说的密钥是否正确

附录.nginx-rtmp配置文件详解

# rtmp conf
worker_processes auto;
rtmp_auto_push on;
events {}
rtmp {       # rtmp主块 所有rtmp配置均需要写在这里面
    server { # 声明一个rtmp实例/nginx中监听某某端口一个意思
        listen 1935;  # 监听端口 1935
        listen [::]:1935 ipv6only=on; #配置访问请求限制 
        timeout 60s; # 配置访问超时时间 这个值主要用于写数据时,如果推过来的流死卡死卡可以在这里被关闭 如果想要快速关闭可以配置ping
        ping 3m; #配置socket心跳ping 这里是3分钟一次 
        ping_timeout 30s; #ping完回复时间这里设置成30s 默认为1min 如果超时则断开本次连接
        max_streams 32; #设置 RTMP 流的最大数目。数据流被整合到一个单一的数据流里。不同的频道用于发送命令、音频、视频等。默认值为32,适用于大多数情况。
        ack_window 5000000;#设置 RTMP 确认视窗大小。这是对端发送确认包到远端后应该收到的字节数量。默认值为 5000000。
        chunk_size 4096;#流整合的最大的块大小。默认值为 4096。这个值设置的越大 CPU 负载就越小。这个值不能低于 128。
        max_message 1M;#输入数据报文最大尺寸。所有输入数据会被分割成报文(然后进一步分割为块)。报文在处理结束之前会放在内存里。理论上讲,接收到的报文很大的话对于服务器的稳定性可能会有影响。默认值 1M 对于大多数情况就足够了。 没看懂?那就别碰她默认的挺好
        on_connect http://baidu.com;#设置 HTTP 连接回调。当客户分发连接命令一个连接命令时,一个 HTTP 请求异步发送,命令处理将被暂停,直到它返回结果代码。当 HTTP 2XX 码(成功状态码)返回时,RTMP 会话继续。返回码 3XX (重定向状态码)会使 RTMP 重定向到另一个从 HTTP 返回头里获取到的 application。否则(其他状态码)连接丢弃。注意这一指令在 application 域是不允许的,因为 application 在连接阶段还是未知的。
        #HTTP 请求接收到一些参数。在 application/x-www-form-urlencoded MIME 类型下使用 POST 方法。以下参数将被传给调用者:
		# call=connect。
		# addr - 客户端 IP 地址。
		# app - application 名。
		# flashVer - 客户端 flash 版本。
		# swfUrl - 客户端 swf url。
		# tcUrl - tcUrl。
		# pageUrl - 客户端页面 url。
		#除了上述参数以外,所有显式传递给连接命令的参数也由回调发送。你应该将连接参数和 play/publish 参数区分开。播放器常常有独特的方式设置连接字符串不同于 play/publish 流名字。这里是 JWPayer 是如何设置这些参数的一个示例:
        
        application live { #新建rtmp应用 说人话 启动一个具体的直播间 命名为live 
            live on;       #开启直播即一对多播放
            allow publish 127.0.0.1; #允许什么地址的流进行推送
            deny publish all; # 不允许什么地址的流进行推送
            allow play 192.168.0.0/24; #允许什么ip的人进行播放
            deny play all; # 不允许什么ip的人进行播放
            exec ffmpeg -i rtmp://localhost/src/$name -vcodec libx264 -vprofile baseline -g 10 -s 300x200 -acodec libfaac -ar 44100 -ac 1 -f flv rtmp://localhost/hls/$name; # exec 命令 定义每个流发布时要执行的带有参数的外部命令。发布结束时进程终止。第一个参数应该是二进制可执行文件的完整路径。关于这个进程将会做些什么事没有任何假定。但这一特点在使用 ffmpeg 进行流转换时是很有用的。FFmpeg 被假定作为客户端连接到 nginx-rtmp 然后作为发布者输出转换流到 nginx-rtmp。类似于 $var/${var} 形式的替换可以在命令行使用:以上为ffmpeg 调用将输入流转码为 HLS-ready 流(H264/AAC)。运行这个示例,FFmpeg 须编译为支持 libx264 & libfaac。
            #替换列表 
          # $name - 流的名字。
		 # $app - 应用名。
		 # $addr - 客户端地址。
		 # $flashver - 客户端 flash 版本。
		 # $swfurl - 客户端 swf url。
		 # $tcurl - 客户端 tc url。
		 # $pageurl - 客户端页面 url。
可以在 exec 指令中定义 Shell 格式的转向符用于写输出和接收输入。支持如下
            
            exec_static ffmpeg -i http://example.com/video.ts -c copy -f flv rtmp://localhost/myapp/mystream; #类似于 exec 指令,但在 nginx 启动时将运行定义的命令。因为(启动时)尚无会话上下文,不支持替换。
            exec_kill_signal term;#设置进程终止信号。默认为 kill(SIGKILL)。你可以定义为数字或者符号名(POSIX.1-1990 信号)。
            respawn off;#如果打开 respawn 子进程,进程终止时发布会仍然继续。默认为打开。
            respawn_timeout 10s;#启动新的子实例之前,设置 respawn 超时时间。默认为五秒
            meta off;#切换发送元数据到客户端。默认为 on。
            interleave on;#切换交叉模式。在这个模式下,音频和视频数据会在同一个 RTMP chunk 流中传输。默认为 off。
            wait_key on;#使视频流从一个关键帧开始。默认为 off
            wait_video on;#在第一个视频帧发送之前禁用音频。默认为 off。可以和 wait_key 进行组合以使客户端可以收到具有所有其他数据的视频关键帧。然而这通常增加连接延迟。您可以通过在编码器中调整关键帧间隔来减少延迟。
            publish_notify on;#发送 NetStream.Publish.Start 和 NetStream.Publish.Stop 给用户。默认为 off。
            drop_idle_publisher 10s;#终止指定时间内闲置(没有音频/视频数据)的发布连接。默认为 off。注意这个仅仅对于发布模式的连接起作用(发送 publish 命令之后)。
            sync 10ms;#同步音频和视频流。如果用户带宽不足以接收发布率,服务器会丢弃一些帧。这将导致同步问题。当时间戳差超过 sync 指定的值,将会发送一个绝对帧来解决这个问题。默认为 300 ms。
            play_restart off;#使 nginx-rtmp 能够在发布启动或停止时发送 NetStream.Play.Start 和 NetStream.Play.Stop 到每个用户。如果关闭的话,那么每个用户就只能在回放的开始和结束时收到这些通知了。默认为 on。
            
            record off;#切换录制模式。流可以被记录到 flv 文件。本指令指定应该被记录的:
					# off - 什么也不录制
					# all - 音频和视频(所有)
					# audio - 音频
					# video - 视频
					# keyframes - 只录制关键视频帧
					# manual - 用不自动启动录制,使用控制接口来启动/停止
					#在单个记录指令中可以有任何兼容的组合键。
			on_play http://baidu.com;#设置 HTTP 播放回调。每次一个客户分发播放命令时,一个 HTTP 请求异步发送,命令处理会挂起 - 直到它返回结果码。之后再解析 HTTP 结果码。
				# HTTP 2XX 返回码的话继续 RTMP 会话。
				# HTTP 3XX 返回码的话 重定向 RTMP 到另一个流,这个流的名字在 HTTP 返回头的 Location 获取。如果新流的名字起始于 rtmp:// 然后远程 relay 会被创建。relay 要求 IP 地址是指定的而不是域名,并且只工作在 1.3.10 版本以上的 nginx。另请参考 notify_relay_redirect。
				# 其他返回码的话 RTMP 连接丢弃。
			#HTTP 请求接收到一些个参数。在 application/x-www-form-urlencoded MIME 类型下使用 POST 方法。以下参数会被传送给调用者:
				# call=play。
				# addr - 客户端 IP 地址。
				# app - application 名。
				# flashVer - 客户端 flash 版本。
				# swfUrl - 客户端 swf url。
				# tcUrl - tcUrl。
				# pageUrl - 客户端页面 url。
				# name - 流名。
		#出了上述参数之外其他所有播放命令参数显式地发送回调。例如如果一个流由 url rtmp://localhost/app/movie?a=100&b=face&foo=bar 访问,然后呢 a,b 和 foo 发送回调。
		    on_publish url;	#同上面提到的 on_play 一样,唯一的不同点在于这个指令在发布命令设置回调。不同于远程 pull,push 在这里是可以的。
		    on_done url;#播放禁止回调
		    on_play_done url;#播放结束回调
		    on_publish_done url#推送结束回调
		    ...
		    #更多请见 https://www.cnblogs.com/surplus/p/12632549.html
        }
application hls {          
            live on; 
            hls_path /nginxdata; # 这里跟启动命令-v /seventyseven/nginx-rtmp/data:/nginxdata 对应上
            hls_fragment 5s;
            record off;
        }
    }
}

附录.ffmpeg使用详解

详见:https://www.jianshu.com/p/f07f0be088d0

附录.nginx-rtmp鉴权播放

详见:

https://www.cnblogs.com/zkfopen/p/11764127.html

https://www.cnblogs.com/luoc83/p/8412649.html

参考资料: CDSN GITHUB 博客园 具体资料太多了看了百多篇就不列举了

分类:

技术点:

相关文章: