Java 实现Rtsp 转rtmp,hls,flv
服务支撑:FFmpeg + srs(流媒体服务器)
整个流程是 FFmpeg 收流转码 推 rtmp 到流媒体服务 流媒体服务再 分发流到公网
搭建流媒体服务:
1. SRS (Simple Realtime Server) | SRS (本例子使用的是SrS 安装使用docker )
2.GitHub - ZLMediaKit/ZLMediaKit: WebRTC/RTSP/RTMP/HTTP/HLS/HTTP-FLV/WebSocket-FLV/HTTP-TS/HTTP-fMP4/WebSocket-TS/WebSocket-fMP4/GB28181/SRT server and client framework based on C++11
3.nginx实现 (自己百度)
4. 其他的还有收费的那种
2.服务器安装FFmpeg yum 可以安装
java 服务实现调用ffmpeg
1.ProcessManager 用于执行指令以及 关闭这个流等操作
package io.renren.common.live;import cn.hutool.core.thread.ThreadUtil;
import org.springframework.beans.factory.DisposableBean;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;/*** @author chenkang* @date 2023年8月3日09:43:21*/
public class ProcessManager implements DisposableBean {private Map<String, WeakReference<Process>> processMap=new HashMap<>();/*** 启动一个进程* @param processName 进程名称key* @param command 执行指令*/public void startProcess(String processName, String command) {ThreadUtil.execAsync(() -> {try {ProcessBuilder processBuilder = new ProcessBuilder(command.split(" "));Process process = processBuilder.start();processMap.put(processName, new WeakReference<>(process));BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()));String line;while ((line = reader.readLine()) != null) {System.out.println(processName + ": " + line);}int exitCode = process.waitFor();System.out.println(processName + ": Process execution completed with exit code: " + exitCode);} catch (IOException | InterruptedException e) {e.printStackTrace();}});}/*** 销毁* @param processName key*/public void terminateProcess(String processName) {WeakReference<Process> weakRef = processMap.get(processName);if (weakRef != null) {Process process = weakRef.get();if (process != null) {process.destroy();}processMap.remove(processName);}}private void terminateAllProcesses() {for (WeakReference<Process> weakRef : processMap.values()) {Process process = weakRef.get();if (process != null) {process.destroy();}}}@Overridepublic void destroy() throws Exception {this.terminateAllProcesses();this.processMap.clear();}
}
对接的是大华的摄像头
/**
* 开始推流
* 备注:现在客户的设备是NVR NVR 下大概有54个摄像头 公网映射rtsp 554 端口 根据channel 开区分是那个摄像头
* 必须条件:1.服务端要安装好 ffmpeg 2.要搭建一个流媒体服务器 这个使用的是 srs
* 流程:用户端想要查看某个摄像头->查询到设备信息获取到摄像头的channel 这个是提前维护好的
* ->拿到channel走如下方法 调用FFmpeg 执行转码推流指令(客户的摄像头是h265)-》rtsp流会被转码 重新设定分辨率 码率转h264 并把转码流推向流媒体服务器 srs
* ->客户想看的时候就 拉取 流媒体服务端的rtmp流 完成播放
*
* 其他:
* 1.用户再播放的时候 要先确定这个摄像头有没有别的人在观看 观看了就不在执行了 (1.可以调用srs 接口查询流是不是存在 这个比较稳妥 2.或者是 processManager 判断是否在推了)
* 2.有时候用户强制关闭客户端 无法感知用户不在观看了,这面还要 定时的去调用srs 接口查询闲置的流及时的给关闭 同时也要 把服务的process 给主动关闭不然一直推
* 这个要先去关闭process再调用接口关闭srs服务的流
*
*
* http://127.0.0.1:1985/api/v1/streams 查询服务端所有流
*{
* "code": 0,
* "server": "vid-f1gt8j3",
* "streams": [
* {
* "id": "vid-143p019",
* //streamName
* "name": "3",
* "vhost": "vid-5847096",
* "app": "live",
* "live_ms": 1691039306435,
* //客户端数量 这个要注意 默认就有1 个客户端是推流
* "clients": 1,
* "frames": 0,
* "send_bytes": 0,
* "recv_bytes": 1068,
* "kbps": {
* "recv_30s": 0,
* "send_30s": 0
* },
* "publish": {
* //是否正在推流 有时候服务端流停推了 但是还有客户端在看 这个流还能查到 但是 active 为false
* "active": false,
* "cid": ""
* },
* "video": null,
* "audio": null
* }
* ]
* }
*
*
*
* http://127.0.0.1:1985/api/v1/clients
*
*{
* "code": 0,
* "server": "vid-f1gt8j3",
* "clients": [
* {
* "id": "868249e9",
* "vhost": "vid-5847096",
* "stream": "vid-778ujy0",
* "ip": "172.17.0.1",
* "pageUrl": "",
* "swfUrl": "",
* "tcUrl": "rtmp://127.0.0.1:1935/live",
* "url": "/live/9",
* //类型是 fmle-publish 推流 删除掉这个推流就会停止
* //类型是 rtmp-play 拉流 删除掉这个拉流就会停止
* //剔除方法 Method DELETE api /api/v1/clients/{id} 停止推流/踢掉用户端
* "type": "fmle-publish",
* "publish": true,
* "alive": 16.18,
* "kbps": {
* "recv_30s": 0,
* "send_30s": 0
* }
* }
* ]
* }
*
*
* @param channel
*/
@GetMapping("/start")@ResponseBodypublic void start(@RequestParam(defaultValue = "1") String channel){RtspUrlBuilder builder = new RtspUrlBuilder();RtmpUrlBuilder rtmpUrlBuilder = new RtmpUrlBuilder();//构建 rtsp 这个是客户的nvr rtsp 地址 只有channel 是灵活的 他们是64路 现在接了50多摄像头对应50 多路channelString rstp = builder.setUsername("admin").setPassword("xx").setIpAddress("xx").setChannel(channel).build();//这个是流媒体服务器的rtmp 推流地址String rtmp = rtmpUrlBuilder.setApplication("live").setStreamName(channel).build();final String vcodec="libx264";String camera1=String.format(RTSP_RTMP, rstp,vcodec,rtmp);//TODO 判断是否已经再推了 推就直接返回拉流地址processManager.startProcess(channel,camera1);//拉流地址和推流地址是一至的 除非 java 服务和srs 在一台服务器 那么 推流地址 rtmp ip为127.0.0.1 拉流 rtmp ip 为公网// 就是java通过ffmpeg 收流转发到本地 rtmp srs分发流 到公网去System.out.println("拉流地址:"+rtmp);}@GetMapping("/end")@ResponseBodypublic void end(String channel){processManager.terminateProcess(channel);}
两个辅助类:
package io.renren.common.live;/*** @author chenkang* @date 2023-8-3 12:27*/
public class RtspUrlBuilder {private String username;private String password;private String ipAddress;private int port;private String channel;private int subtype;public RtspUrlBuilder() {// 默认端口为554this.port = 554;// 默认子类型为0this.subtype = 0;}public RtspUrlBuilder setUsername(String username) {this.username = username;return this;}public RtspUrlBuilder setPassword(String password) {this.password = password;return this;}public RtspUrlBuilder setIpAddress(String ipAddress) {this.ipAddress = ipAddress;return this;}public RtspUrlBuilder setPort(int port) {this.port = port;return this;}public RtspUrlBuilder setChannel(String channel) {this.channel = channel;return this;}public RtspUrlBuilder setSubtype(int subtype) {this.subtype = subtype;return this;}public String build() {return "rtsp://" + username + ":" + password + "@" + ipAddress + ":" + port +"/cam/realmonitor?channel=" + channel + "&subtype=" + subtype;}
}
package io.renren.common.live;/*** @author chenkang* @date 2023-8-3 12:30*/
public class RtmpUrlBuilder {private String ipAddress;private int port;private String application;private String streamName;public RtmpUrlBuilder() {// 默认IP地址为127.0.0.1this.ipAddress = "127.0.0.1";// 默认端口为1935this.port = 1935;}public RtmpUrlBuilder setIpAddress(String ipAddress) {this.ipAddress = ipAddress;return this;}public RtmpUrlBuilder setPort(int port) {this.port = port;return this;}public RtmpUrlBuilder setApplication(String application) {this.application = application;return this;}public RtmpUrlBuilder setStreamName(String streamName) {this.streamName = streamName;return this;}public String build() {return "rtmp://" + ipAddress + ":" + port + "/" + application + "/" + streamName;}
}
相关文章:
Java 实现Rtsp 转rtmp,hls,flv
服务支撑:FFmpeg srs(流媒体服务器) 整个流程是 FFmpeg 收流转码 推 rtmp 到流媒体服务 流媒体服务再 分发流到公网 搭建流媒体服务: 1. SRS (Simple Realtime Server) | SRS (本例子使用的是SrS 安装使用docker ) 2.GitHub - ZLMedi…...
机器学习基础(三)
逻辑回归 场景 垃圾邮件分类 预测肿瘤是良性还是恶性 预测某人的信用是否良好 正确率与召回率 正确率与召回率(Precision & Recall)是广泛应用于信息检索和统计学分类领域的两个度量值,用来评价结果的质量。 一般来说,正确率就是检索出来的条目有多少是正确的,召回率就…...

Kubeadm安装K8s集群
一、硬件环境 准备3台Linux服务器,此处用Vmware虚拟机。 主机名CPU内存k8smaster2核4Gk8snode12核4Gk8snode22核4G 二、系统前置准备 配置三台主机的hosts文件 cat << EOF > /etc/hosts 192.168.240.130 k8smaster 192.168.240.132 k8snode1 192.168.…...

【C++】开源:spdlog跨平台日志库配置使用
😏★,:.☆( ̄▽ ̄)/$:.★ 😏 这篇文章主要介绍spdlog日志库配置使用。 无专精则不能成,无涉猎则不能通。——梁启超 欢迎来到我的博客,一起学习,共同进步。 喜欢的朋友可以关注一下,下…...
[Azkaban] No active executors found
没有找到活动的executors,需在MySQL数据库里设置端口为12321的executors表的active为1: select * from executors;如果显示active0 则需要进行处理: update azkaban.executors set active1;当active0,更新为1时,用 n…...

无涯教程-Perl - recv函数
描述 This function receives a message on SOCKET attempting to read LENGTH bytes, placing the data read into variable SCALAR.The FLAGS argument takes the same values as the recvfrom( ) system function, on which the function is based. When communicating wit…...
算法练习-搜索 相关
文章目录 迷宫问题 迷宫问题 定义一个二维数组 m行 * n列 ,如 4 5 数组下所示: int arr[5][5] { 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, }; 它表示一个迷宫,1表示墙壁,0表示可以走的路,只…...

PyQt5控件布局管理
Qt Designer提供了四种窗口布局:Vertical Layout(垂直布局) ,Horizontal Layout(水平布局),Grid Layout(栅格布局),Form Layout(表单布局),以及一种隐藏的布局—绝对布局 一般进行布局有两种方式: 一是通…...
TypeScript 一分钟让你理解泛型是什么
TypeScript 一分钟让你理解 泛型是什么 TS的泛型是指在定义函数、接口或类型时,不预先指定具体的类型,而是在使用时指定类型限制的一种特性。 泛型和函数中的参数比较类似,我们定义一个函数的时候有时会给它留一个参数名,在使用这…...

PatchMatchNet 训练dtu数据集、训练曲线查看、实操教程图图文详解、
文章目录 1 查看要求 下载数据集2 训练2.1 路径配置2.2 训练2.3 模型输出 与 训练曲线查看2.4 输出训练 log文件1 查看要求 下载数据集 在代码文件加下打开 README.md文件找到训练说明,查看那要求、下载训练集、训练方法 ## Training Download pre-processed [DTUs trainin…...
怎样制定测试计划和设计测试用例?
测试工作贯穿于整个软件开发生命周期,是一项庞大而复杂的工作,需要制订一个完整且详细的测试计划作为指导。测试计划是整个测试工作的导航图,但它并不是一成不变的,随着项目推进或需求变更,测试计划也会不断发生改变&a…...

教你如何为博客网站申请阿里云的免费域名HTTPS证书
如何为博客网站申请阿里云的免费域名HTTPS证书 文章目录 如何为博客网站申请阿里云的免费域名HTTPS证书前置条件:步骤1 例如阿里云控制台,选择SSL证书步骤2 申请购买免费证书步骤3 创建证书步骤3.1 证书申请步骤3.2 DNS域名验证 步骤4 等待证书审核成功&…...

在线Word怎么转换成PDF?Word无法转换成PDF文档原因分析
不同的文件格式使用方法是不一样的,而且也需要使用不同的工具才可以打开编辑内容,针对不同的场合用户们难免会用到各种各样的文件格式,要想在不修改内容的前提下提高工作效率,那就需要用到文件格式转换,那么在线Word怎…...

计算机网络:网络通信相关概念入门
目录 一、网络发展背景二、理解网络通信三、理解IP地址1.简述IP地址2.IP地址的版本3.提高地址利用率的技术 四、理解端口1.简述端口2.使用端口的原因 五、理解网络通信协议 一、网络发展背景 网络发展背景: 最初的计算机是单机,那么单机是这样传输数据的…...

Spring-2-透彻理解Spring 注解方式创建Bean--IOC
今日目标 学习使用XML配置第三方Bean 掌握纯注解开发定义Bean对象 掌握纯注解开发IOC模式 1. 第三方资源配置管理 说明:以管理DataSource连接池对象为例讲解第三方资源配置管理 1.1 XML管理Druid连接池(第三方Bean)对象【重点】 数据库准备 -- 创建数据库 create …...

LeetCode150道面试经典题--单词规律(简单)
1.题目 给定一种规律 pattern 和一个字符串 s ,判断 s 是否遵循相同的规律。 这里的 遵循 指完全匹配,例如, pattern 里的每个字母和字符串 s 中的每个非空单词之间存在着双向连接的对应规律。 2.示例 pattern"abba" s "c…...

uniapp把城市换成26个字母和城市排序
后端返回的数据 我们要得效果 <template><view><view v-for"(value,key) in cities" :key"key"><view style"color: red;"> {{ key }} </view><view style"border: 1rpx solid black;"><tex…...

Flv格式视频怎么转MP4?视频格式转换方法分享
FLV格式的视频是一种早期的视频格式,不支持更高的分辨率和比特率,这意味着视频的清晰度和质量受限制,无法很好地保留细节和质量,这种格式的视频已经逐渐被更高质量的视频格式所替代,例如MP4格式,不仅具有很…...

Java类与对象详解(3)
目录 封装 封装的概念 访问限定符 封装扩展之包 包的概念 导入包中的类 自定义包 基本规则 包的访问权限控制举例 常见的包 static 成员 static 修饰成员变量 static修饰成员方法 static 成员变量的初始化 代码块 代码块的概念及其分类 普通代码块 构造代码块…...

PMP备考指南来啦!
第一步:通读教材,了解学习内容 在正式开始课程的学习前,可以先快速简单地阅览一遍教材(PMBOK),在较短的时间内知道自己将要学习的是什么内容;同时可以标记出难理解的知识点。这样做有以下两个好…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...

Mac软件卸载指南,简单易懂!
刚和Adobe分手,它却总在Library里给你写"回忆录"?卸载的Final Cut Pro像电子幽灵般阴魂不散?总是会有残留文件,别慌!这份Mac软件卸载指南,将用最硬核的方式教你"数字分手术"࿰…...

基于Docker Compose部署Java微服务项目
一. 创建根项目 根项目(父项目)主要用于依赖管理 一些需要注意的点: 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件,否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...
鸿蒙HarmonyOS 5军旗小游戏实现指南
1. 项目概述 本军旗小游戏基于鸿蒙HarmonyOS 5开发,采用DevEco Studio实现,包含完整的游戏逻辑和UI界面。 2. 项目结构 /src/main/java/com/example/militarychess/├── MainAbilitySlice.java // 主界面├── GameView.java // 游戏核…...
Windows 下端口占用排查与释放全攻略
Windows 下端口占用排查与释放全攻略 在开发和运维过程中,经常会遇到端口被占用的问题(如 8080、3306 等常用端口)。本文将详细介绍如何通过命令行和图形化界面快速定位并释放被占用的端口,帮助你高效解决此类问题。 一、准…...

MySQL体系架构解析(三):MySQL目录与启动配置全解析
MySQL中的目录和文件 bin目录 在 MySQL 的安装目录下有一个特别重要的 bin 目录,这个目录下存放着许多可执行文件。与其他系统的可执行文件类似,这些可执行文件都是与服务器和客户端程序相关的。 启动MySQL服务器程序 在 UNIX 系统中,用…...

GAN模式奔溃的探讨论文综述(一)
简介 简介:今天带来一篇关于GAN的,对于模式奔溃的一个探讨的一个问题,帮助大家更好的解决训练中遇到的一个难题。 论文题目:An in-depth review and analysis of mode collapse in GAN 期刊:Machine Learning 链接:...