通过FFmpeg和Nginx进行摄像头直播推流

@TOC总结

1.环境

ffmpeg、nginx(代理服务器)nginx-rtmp-module(nginx服务器的流媒体插件)、vlc(播放器)
原理:nginx通过rtmp模块提供rtmp服务,ffmpeg推送一个rtmp流到nginx,然后客户端通过访问nginx来收看实时视频流

准备安装文件

链接:网盘链接
密码:2t88

启动nginx服务器

  1. 进入windows的cmd;
  2. cd nginx-1.7.11.3-Gryphon,进入nginx的目录
  3. nginx.exe -c conf\nginx-win-rtmp.conf //运行rtmp配置文件
    注意:命令行窗口不能关闭
    在浏览器上输入localhost:80,查看是否启动成功!

配置FFmpeg

  1. 解压:将ffmpeg解压到指定目录 C:\ffmpeg
  2. 环境配置:高级系统设置中,环境变量,打开Path,将C:\ffmpeg\bin(ffmpeg解压目录下的bin目录的绝对路径)添加到Path路径下
  3. 测试,重新打开一个cmd窗口,输入ffmpeg

在这里插入图片描述

运行

在cmd中输入ffmpeg -i “rtsp://账号:密码@IP地址:544/cam/realmonitor?channel=1&subtype=0” -vcodec h264 -f flv -an “rtmp://localhost/live”

回车后控制台持续打印转流信息,证明ffmpeg转流成功

整合java代码

package com.java.controller;
 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
 
import cc.eguid.FFmpegCommandManager.FFmpegManager;
import cc.eguid.FFmpegCommandManager.FFmpegManagerImpl;
 
@Controller
public class ControllerCamera {
	public static Map<String, String> maps = new HashMap<>();
	public static FFmpegManager manager = new FFmpegManagerImpl();
 
	// 开转流
	@RequestMapping(value = "/ffmpegs")
	public void ffmpegs(HttpServletResponse response, HttpServletRequest request) {
		InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("ffmpeg.properties");
		Properties p = new Properties();
		try {
			p.load(inputStream);
		} catch (IOException e1) {
			e1.printStackTrace();
		}
 
		String number = p.getProperty("number");
		int num = Integer.valueOf(number);
		// System.out.println("ip:" + p.getProperty("ip") + ",port:" +
		// p.getProperty("port"));
		for (int i = 1; i <= num; i++) {
			// maps.remove("a");
 
			Map<String, String> map = new HashMap<>();
			map.put("appName", p.getProperty("code" + i));// code为客户端编码
			// map.put("input", "\"rtsp://admin:dsgbridge@" + ip +
			// "/cam/realmonitor?channel=1&subtype=0\"");
			map.put("output", p.getProperty("output" + i));
			map.put("codec", p.getProperty("codec" + i));
			map.put("fmt", p.getProperty("fmt" + i));
			map.put("fps", p.getProperty("fps" + i));
			map.put("rs", p.getProperty("rs" + i));
			map.put("kb", p.getProperty("kb" + i));
			map.put("twoPart", p.getProperty("twoPart" + i));// twoPart:0-推一个元码流;1-推一个自定义推流;2-推两个流(一个是自定义,一个是元码)
 
			map.put("input", p.getProperty("input" + i));
 
			if(maps.containsKey(p.getProperty("code" + i))==false){
				// 执行任务,id就是appName,如果执行失败返回为null
				String id = manager.start(map);
				// 将转流放入静态map中用于关转流
				maps.put(p.getProperty("code" + i), id);
				System.out.println("appName: " + p.getProperty("code" + i));
				System.out.println("input: " + p.getProperty("input" + i));
				System.out.println("output: " + p.getProperty("output" + i));
				System.out.println("codec: " + p.getProperty("codec" + i));
				System.out.println("fmt: " + p.getProperty("fmt" + i));
				System.out.println("fps: " + p.getProperty("fps" + i));
				System.out.println("rs: " + p.getProperty("rs" + i));
				System.out.println("kb" + p.getProperty("kb" + i));
				System.out.println("twoPart:" + p.getProperty("twoPart" + i));
				System.out.println();
				System.out.println(p.getProperty("code" + i) + ":  流已开启");
			}
		}
	}
 
	// 关闭转流
	@RequestMapping(value = "/offall")
	public void offall(HttpServletResponse response, HttpServletRequest request) {
		InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("ffmpeg.properties");
		Properties p = new Properties();
		try {
			p.load(inputStream);
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		String number = p.getProperty("number");
		int num = Integer.valueOf(number);
		for (int i = 1; i <= num; i++) {
			try {
				manager.stop(maps.get(p.getProperty("code" + i)));
				maps.remove(p.getProperty("code" + i));
				System.out.println(p.getProperty("code" + i) + "流已关闭");
			} catch (Exception e) {
				e.getStackTrace();
			}
		}
	}
}

前端页面采用video.js,进行播放链接

ffmpeg如下

number=5
 
code1=camera1
input1="rtsp\://admin\:12345678A@192.168.1.64\:554//cam/realmonitor?channel\=1&subtype\=0"
output1="rtmp\://192.168.1.109/live/"
codec1=copy
fmt1=flv
fps1=25
kb1=2048k
rs1=640x360
twoPart1=1
 
code2=camera2
input2="rtsp\://admin\:12345678A@192.168.1.64\:554//cam/realmonitor?channel\=1&subtype\=0"
output2="rtmp\://192.168.1.109/live/"
codec2=copy
fmt2=flv
fps2=25
kb2=2048k
rs2=640x360
twoPart2=1
 
code3=camera3
input3="rtsp\://admin\:12345678A@192.168.1.64\:554//cam/realmonitor?channel\=1&subtype\=0"
output3="rtmp\://192.168.1.109/live/"
codec3=copy
fmt3=flv
fps3=25
kb3=2048k
rs3=640x360
twoPart3=1
 
code4=camera4
input4="rtsp\://admin\:12345678A@192.168.1.64\:554//cam/realmonitor?channel\=1&subtype\=0"
output4="rtmp\://192.168.1.109/live/"
codec4=copy
fmt4=flv
fps4=25
kb4=2048k
rs4=640x360
twoPart4=1
 
code5=camera5
input5="rtsp\://admin\:12345678A@192.168.1.64\:554//cam/realmonitor?channel\=1&subtype\=0"
output5="rtmp\://192.168.1.109/live/"
codec5=copy
fmt5=flv
fps5=25
kb5=2048k
rs5=640x360
twoPart5=1
 
code6=camera6
input6="rtsp\://admin\:12345678A@192.168.1.64\:554//cam/realmonitor?channel\=1&subtype\=0"
output6="rtmp\://192.168.1.109/live/"
codec6=copy
fmt6=flv
fps6=25
rs6=640x360
twoPart6=1

在linux下也是可以运行成功的

安装参考:
https://www.cnblogs.com/shook/p/14137221.html
https://blog.csdn.net/weixin_43451928/article/details/114541471?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-0&spm=1001.2101.3001.4242
需要注意在TaskHandlerImpl.java文件下,需要进行几句改动
在这里插入图片描述
在linux下需要/bin/sh -c +参数

参考来源:
https://blog.csdn.net/u011877155/article/details/83750651
https://blog.csdn.net/u011877155/article/details/83750651
https://blog.csdn.net/weixin_40263855/article/details/87917484?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522161646419416780264048858%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=161646419416780264048858&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_v2~rank_v29-7-87917484.pc_search_positive&utm_term=java%E6%8E%A5%E5%85%A5%E5%A4%A7%E5%8D%8E%E8%A7%86%E9%A2%91%E6%B5%81

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值