ffmpeg+nginx-rtmp-module+flv实现不基于flash无插件播放监控视频

导言

目前flash在浏览器的支持越来越差,谷歌新版本已经抛弃flash支持,常规rtmp视频流播放基本没法满足技术要求。目前解决方案是将rtmp转为hls之后进行播放,常规情况下hls播放延迟比较大,平均在5-6s延迟左右,本章采用的是利用flv进行视频播放,谷歌浏览器,IE没有测试。测试延迟基本小于5s左右,延迟较大情况可在前端进行校验跳帧来保证延迟。这类传统的流媒体平台还是比较成熟的,如果想搭建GB28181监控对接平台可以参照:https://blog.csdn.net/mokeily99/article/details/115657823

正文

所需工具包含

ffmpeg

ffmpeg:https://download.csdn.net/download/mokeily99/16629192

nginx-rtmp-module编译后的:https://download.csdn.net/download/mokeily99/16629289

flv.min.js:https://download.csdn.net/download/mokeily99/16629251

vlc播放器:https://download.csdn.net/download/mokeily99/1662901

如果闲麻烦可可直接下载全量包,包含前端测试页面:https://download.csdn.net/download/mokeily99/16630141

步骤:

1、下载编译后的nginx-rtmp-module文件,配置nginx.conf如下
 

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服务
http {
    include       mime.types;
    default_type  application/octet-stream;

    #access_log  logs/access.log  main;

    server {
        listen       8088; # 监听端口
 
        location /stat.xsl {
            root html;
        }
        location /stat {
            rtmp_stat all;
            rtmp_stat_stylesheet stat.xsl;
        }
        location / {
            root html;
        }
        location /rtmpLive {
            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';
        }
    }
}

如果是从上面地址下载的配置文件是已经修改完的,不需要动。注意配置文件中的几个监听端口,避免和其他程序冲突,1935是ffmpeg转码时用到的端口,需要和此处对应。8088是flv前端展示端口,后文会说明。

启动nginx,双击nginx.exe程序,cmd窗口一闪而过,启动任务管理器查看下nginx是否启动,出现nginx.exe就说明已经启动了。

2、启动ffmpeg

下载上面地址的ffmpeg,配置环境变量,path中加入ffmpeg的bin目录地址,我的是D:\workSpace\live\ffmpeg\ffmpeg-4.3.1-2021-01-01-essentials_build\bin

之后以管理员身份运行cmd,输入ffmpeg回车会出现一堆东西,说明配置完成

之后测试ffmpeg拉流解码,本次用的是大华监控,测试主码流,命令如下

ffmpeg -i "rtsp://admin:admin123@192.168.110.108:554/cam/realmonitor?channel=1&subtype=0" -vcodec copy -f flv -an rtmp://localhost:1935/live/1000000001

注释:

admin是监控登录页面的账号

admin123是监控登录页面密码

192.168.110.108:554为监控地址和端口,监控如果没做端口修改基本大华的都是554

subtype是码流类型,0是主码流1是副码流,如果使用副码流需要在监控管理页面启动副码流

channel是通道编号,都是默认配置,没有修改就写1

-vcodec copy -f flv -an:视频解码参数-vcodec copy为拷贝原视频,建议不要改动,我试过其他参数,也尝试修改视频尺寸都没有成功,不是特别卡就是不显示,只能通过监控页面修改码流的分辨率来实现视频尺寸。flv解码格式,对应前端的flv

rtmp://localhost:1935/live/1000000001:rtmp输出地址,本机测试就用localhost就可以,或替换本机IP

运行后会不停的输出拉流转码日志,如下图

3、测试rtmp视频流

打开vlc播放器,媒体-打开网络串流,输入上步中的rtmp://localhost:1935/live/1000000001地址,播放测试是否有图像,有图像说明拉流转码成功。

4、前端flv展示监控视频

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>播放页面</title>
    </head>
    <body>
        <script src="https://cdn.bootcdn.net/ajax/libs/flv.js/1.5.0/flv.min.js"></script>
        <video style="height: 400px;width: 600px;" id="videoElement" muted autoplay controls></video>
        <script>
            var flvPlayer = null;
            if (flvjs.isSupported()) {
                var videoElement = document.getElementById('videoElement');
                flvPlayer = flvjs.createPlayer({
                    type: 'flv',
                    // 8080 对应Nginx监听的端口
                    // rtmpLive 对应Nginx的路径
                    url: 'http://localhost:8088/rtmpLive?app=live&stream=1000000001',
                    enableWorker: true,     //浏览器端开启flv.js的worker,多进程运行flv.js
                    isLive: true,           //直播模式
                    hasAudio: false,        //关闭音频             
                    hasVideo: true,
                    stashInitialSize: 128,
                    enableStashBuffer: false
                });
                flvPlayer.attachMediaElement(videoElement);
                flvPlayer.load();
            }
        </script>
    </body>
</html>

 

注意url地址,http://localhost:8088/rtmpLive?app=live&stream=1000000001,8088对应nginx配置文件中的监听端口,上文中配置的是8088。rtmpLive也是nginx配置文件末尾的配置标识符,app=live&stream=1000000001是ffmpeg拉流转码后的标识符,如果以上都是按照稳中内容写的话就不需要修改地址

前端播放成功,延迟基本在5s以内,如果想修改延迟,可进行前端时间校正,前端js加入代码

setInterval(function() {
            console.log("时延校正判断");

            if (!videoElement.buffered.length) {
                return;
            }
            var end = videoElement.buffered.end(0);
            var diff = end - videoElement.currentTime;
            console.log(diff);
            if (diff >= 2) {
                console.log("进行时延校正");
                videoElement.currentTime = (end - 1);
            }
        }, 3000);

延迟大于2s自动进行时间校正,跳转到当前时间,但是跳转时会出现视频加载现象,不太美观,建议判断时间在4s左右diff >= 4

扩展

java集成ffmpeg拉流转码,web启动自动进行拉流转码:springboot项目

PubListener.java,启动执行任务

package com.hs.job;

import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import com.hs.Rtsp.RtspFactory;

@Component
public class PubListener implements CommandLineRunner {
 
    public void run(String... strings) throws Exception {
    	RtspFactory rtspFy = new RtspFactory();
    	rtspFy.initRtspInfo();
    }
}

RtspFactory.java

package com.hs.Rtsp;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


import com.hs.trans.bean.CameraInfo;
import com.hs.trans.service.CameraService;
import com.hs.util.FFmpegConfig;
import com.hs.util.PropertiesUtil;
import com.hs.util.SpringUtils;

public class RtspFactory {

    private CameraService cameraService;
    
    private static FFmpegConfig config = (FFmpegConfig) PropertiesUtil.load("defaultFFmpegConfig.properties",  FFmpegConfig.class);//ffmpeg转码配置文件,配置了各类监控的转码方式,目前配置了大华、海康等设备
    
    
    public void initRtspInfo(){
        List<CameraInfo> cameraList = getCameraList();//getCameraList为获取监控列表方法,需要自己实现,测试可写死
        for(CameraInfo camera : cameraList){
            //String rtspUrl = "rtsp://admin:admin123@192.168.110.108:554/cam/realmonitor?channel=1&subtype=1";
            //rtsp://[username]:[password]@[ip]:554/cam/realmonitor?channel=1&subtype=1
            String rtspUrl = loadRtspUrl(camera);
            // Nginx rtmp地址
            // 1935 对应Nginx配置文件中rtmp所监听的端口
            // live 对应Nginx配置文件中rtmp下application的值
            // rtmpStream 对应播放页面中16行参数stream的值
            if(rtspUrl != null){
                String nginxRtmpUrl = "rtmp://localhost:1935/live/" + camera.getMaxaccept();
                RtspThread rtsp;
                try {
                    rtsp = new RtspThread(rtspUrl, nginxRtmpUrl);
                    rtsp.start();
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    public String loadRtspUrl(CameraInfo camera){
        String rtspUrl = null;
        
        String comTypeLists = config.getCameraComType();
        String[] comTypeArr = comTypeLists.split(",");
        
        for(String comTypes : comTypeArr){
            String[] comArr = comTypes.split("-");
            if(comArr[0].equals(camera.getComType())){
                rtspUrl = comArr[1];
                break;
            }
        }
        
        if(rtspUrl != null){
            rtspUrl = rtspUrl.replace("[username]", camera.getUserName()).replace("[password]", camera.getPassWord()).replace("[ip]", camera.getIp());
        }
        return rtspUrl;
    }
    
    public List<CameraInfo> getCameraList(){
        cameraService = SpringUtils.getBean(CameraService.class);
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("deleteFlag", 0);
        return cameraService.getCameraList(param);
    }
}

RtspThread.java

package com.hs.Rtsp;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;

import com.hs.util.FFmpegConfig;
import com.hs.util.PropertiesUtil;


public class RtspThread extends Thread {
	
	private static FFmpegConfig config = (FFmpegConfig) PropertiesUtil.load("defaultFFmpegConfig.properties",  FFmpegConfig.class);
	
	private String rtspUrl;
	
	private String nginxRtmpUrl;
	
	public RtspThread(String rtspUrl, String nginxRtmpUrl) throws UnsupportedEncodingException {
		this.rtspUrl = rtspUrl;
		this.nginxRtmpUrl = nginxRtmpUrl;
	}

	@Override
	public void run() {
		super.run();
		try {
			// ffmpeg 已经在系统环境变量中配置好了
			String command = config.getFfpmegPath() + "ffmpeg.exe";
			command += " -i \"" + rtspUrl + "\"";
			command += " -vcodec copy -f flv -s 100x50 -an " + nginxRtmpUrl;
			System.out.println("ffmpeg推流命令:" + command);

			Process process = Runtime.getRuntime().exec(command);
			BufferedReader br = new BufferedReader(new InputStreamReader(process.getErrorStream()));
			String line = "";
			while ((line = br.readLine()) != null) {
				
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {// 建立连接失败的话不会执行socket.close();
			
		}
	}
}

defaultFFmpegConfig.properties,放到resources目录下,10900对应大华、10901对应海康,“,”分割。ffpmegPath对应ffmpeg目录bin目录

#设备厂家映射
cameraComType=10900-rtsp\://[username]\:[password]@[ip]\:554/cam/realmonitor?channel\=1&subtype\=0,10901-rtsp\://[username]\:[password]@[ip]\:554/h264/ch1/main/av_stream,10902-rtsp\://[ip]\:3000

#ffpmeg路径
ffpmegPath=D\:\\workSpace\\live\\ffmpeg\\ffmpeg-4.3.1-2021-01-01-essentials_build\\bin\\

表结构

启动nginx后,启动springboot项目自动进行推拉流。集成写的比较粗略,有问题邮箱联系mokeily99@126.com,vx:18686530251

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Nginx是一个高性能的开源Web服务器,同时也可以用作反向代理服务器、负载均衡器和流媒体服务器。NginxRtmp-Module是一个第三方模块,它为Nginx服务器添加了RTMP(Real-Time Messaging Protocol)支持,使其可以充当一个流媒体服务器。FFmpeg是一个跨平台的音视频处理工具,它可以用来进行多媒体文件的转码、编解码、录制和流媒体传输等操作。 引用中提到了使用Nginx Nginx-Rtmp-Module Ffmpeg搭建流媒体服务器的方法。具体配置可以查看conf/nginx.conf文件。首先需要解压文件,然后运行nginx_start.bat文件来启动Nginx服务器。这样就可以使用Nginx服务器提供的RTMP服务,通过FFmpeg推送一个RTMP流到Nginx,然后客户端可以通过访问Nginx来收看实时视频流。还可以使用HLS(HTTP Live Streaming)协议,通过HTTP协议来访问Nginx服务器并收看视频流,但是FFmpeg推送流仍然是RTMP的。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [nginx+nginx-rtmp-module+ffmpeg搭建流媒体服务器服务器](https://blog.csdn.net/sinat_16643223/article/details/115108327)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [ffmpeg+nginx+nginx-rtmp-module搭建个人直播平台](https://download.csdn.net/download/qq_29114677/13012815)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十年一梦惊觉醒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值