前言
前一段时间项目中遇到了网页播放摄像头实时画面的需求,最开始的设计是:
1. 拿到摄像头的rtsp流地址;
2. 通过ffmpeg插件将rtsp流转码为rtmp流,并借助nginx推流;
3. 网页中利用ckplayer.js解析nginx推过来的rtmp流进行展示;
但是由于ckplayer解析rtmp流后要求需要使用Adobe Flash插件才能展示画面,不幸的是Chrome等主流浏览器从2020年12月31日往后就不再支持Adobe Flash。。。。(时间卡的真好),查资料加一顿捣鼓后发现flv.js+nginx-http-flv可以实现相同功能,下面进行一波总结
一.nginx-http-flv配置
下载地址:nginx-http-flv 简单说几点:
1. 我的操作系统环境:windows server 2012
2. 在基于ckplayer.js开发时,只需要rtmp模块足够,但使用flv.js则需要nginx的http-flv模块并配置http服务
3. 注意!!!如果你需要同时展示6个以上画面,建议配多个http服务
我在http模块中配置了两个服务,分别监听8038端口和8039端口,正常来说一个服务足够,但由于浏览器同源策略,同源请求(就是协议,端口(如果有指定)和域名都相同的请求)在Chrome的一个网页中最多存在6个(网站升级为HTTP2.0的略过),后面的会阻塞,因此如果网页中需要同时直播6个以上画面的话(我的需要8个),可以按我的方法配置两个服务分别推流即可

worker_processes  1;

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

#pid        logs/nginx.pid;

events {
    worker_connections  1024;
}

# 添加RTMP服务
rtmp {

    server {
        listen 1935;
        
        chunk_size 4000;
		
        application live {  
            live on;
			gop_cache on;
        }
	}

}

http {
    include        mime.types;
    default_type    application/octet-stream;
    sendfile        on;
    keepalive_timeout    65;

    server {
        listen       8038;
        server_name	 127.0.0.1;
		
		location /live {
			flv_live on;
            chunked_transfer_encoding  on; #open 'Transfer-Encoding: chunked' response
			add_header 'Access-Control-Allow-Credentials' 'true'; #add additional HTTP header
			add_header 'Access-Control-Allow-Origin' '*'; #add additional HTTP header
			add_header Access-Control-Allow-Headers X-Requested-With;
			add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
			add_header 'Cache-Control' 'no-cache';
        }
	}
	
	server {
        listen       8039;
        server_name	 127.0.0.1;
		
		location /live {
			flv_live on;
            chunked_transfer_encoding  on; #open 'Transfer-Encoding: chunked' response
			add_header 'Access-Control-Allow-Credentials' 'true'; #add additional HTTP header
			add_header 'Access-Control-Allow-Origin' '*'; #add additional HTTP header
			add_header Access-Control-Allow-Headers X-Requested-With;
			add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
			add_header 'Cache-Control' 'no-cache';
        }
	}
}

配置文件配好后,双击nginx.exe

二.ffmpeg插件推流
ffmpeg插件的推流办法,网上资料已有很多,本地测试时使用cmd命令即可

D:\\Program Files\\ffmpeg-20200831-4a11a6f-win64-static\\bin\\ffmpeg -thread_queue_size 100000 -i rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov -vcodec libx264 -preset:v medium -tune:v zerolatency -profile:v main -acodec copy -f flv -s 420*260 -an rtmp://127.0.0.1:1935/live/test2

其中:rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov为视频的rtsp流地址(这里引用的是公网上的一个可用测试地址),420*260为我需要的视频尺寸大小,rtmp://127.0.0.1:1935/live/test2为rtmp流地址,D:\Program Files\ffmpeg-20200831-4a11a6f-win64-static\bin\ffmpeg为ffmpeg.exe的路径,这四处在使用时替换为实际需要的即可。

如果项目里需要动态推流,则使用代码动态执行上面命令生成进程,java里执行代码为

try {
	Process process = Runtime.getRuntime().exec("D:\\Program Files\\ffmpeg-20200831-4a11a6f-win64-static\\bin\\ffmpeg -thread_queue_size 100000 -i rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov -vcodec libx264 -preset:v medium -tune:v zerolatency -profile:v main -acodec copy -f flv -s 420*260 -an rtmp://127.0.0.1:1935/live/test2");
} catch (IOException e) {
	e.printStackTrace();
}

可以对process进行监听,获取ffmpeg进程的实时状态来进行异常中断后的重新推流等后续操作。

三.flv.js解析流
前端只需要引入flv.min.js,代码如下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>flv.js test</title>
	<link rel="stylesheet" href="dplayer.css"/>
	<script src="flv.min.js"></script>
</head>
<body>
	<video muted id="videoElement1" width="420" height="260"></video>
	<video muted id="videoElement2" width="420" height="260"></video>
	<video muted id="videoElement3" width="420" height="260"></video>
	<video muted id="videoElement4" width="420" height="260"></video>
	<video muted id="videoElement5" width="420" height="260"></video>
	<video muted id="videoElement6" width="420" height="260"></video>
	<video muted id="videoElement7" width="420" height="260"></video>
	<video muted id="videoElement8" width="420" height="260"></video>
<script>
//flvjs.LoggingControl.enableAll = false;
		for(var i = 1;i < 9;i++){
			var videoElement1 = document.getElementById('videoElement'+i);
			//前6个解析8038端口推过来的流,后两个使用8039端口
			var port = 8038;
			if(i < 7){
				port = 8039;
			}
			var flvPlayer = flvjs.createPlayer({
				type: 'flv',
				isLive: true,
				url: 'http://localhost:'+port+'/live?port=1935&app=live&stream=test2'
			});
			flvPlayer.attachMediaElement(videoElement1);
			flvPlayer.load();
			flvPlayer.play();
		}
</script>
</body>
</html>

其中后两个视频画面是对8039端口的流解析渲染而成,实际浏览器效果如下图

videojs播放m3u8视频流视频监控卡顿 flv.js播放rtsp_前端