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),在较短的时间内知道自己将要学习的是什么内容;同时可以标记出难理解的知识点。这样做有以下两个好…...
全网疯传「.SKILL」:只要一句话,就能把任何人蒸馏成 AI,前任、老板、乔布斯。。。
不用懂代码、不用学复杂操作,只要一个SKILL,就能把任何人蒸馏成专属AI——同事、老板、前任,甚至乔布斯、张一鸣,都能被你炼入token,随叫随到陪你对话、帮你干活,实用性直接拉满!最近刷X的朋友&…...
C语言是什么?初学者必看的通俗解释
由于微型计算机越来越普及,C语言成了世界上极为流行、运用颇为广泛的高级程序设计语言当中的一种。C语言是程序语言的根基,要是掌握了C语言,再去学别的语言便容易许多。那么,什么是C语言呢?对于从事编程工作的朋友而言…...
Plink核心命令解析:从--bfile到--make-bed的基因组数据处理全流程
1. Plink工具入门:基因组数据处理的基础利器 第一次接触Plink这个工具时,我正面临着一个典型的生物信息学难题:如何高效处理GWAS研究中的海量基因型数据。当时实验室的前辈随手写下一行命令plink --bfile mydata --freq --out result…...
5分钟精通抖音批量下载神器:douyin-downloader完整使用指南
5分钟精通抖音批量下载神器:douyin-downloader完整使用指南 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallback …...
告别Appium!用这5个AI视觉自动化工具,让你的手机脚本不再怕App更新
告别Appium!5个AI视觉自动化工具重塑手机脚本开发 每次应用更新后,那些精心编写的自动化测试脚本突然失效的场景,测试工程师们再熟悉不过了。传统基于元素定位的工具如Appium,让团队陷入无休止的脚本维护泥潭。而今天,…...
Pixel Epic · Wisdom Terminal 构建AI Agent:自主任务规划与执行框架
Pixel Epic Wisdom Terminal 构建AI Agent:自主任务规划与执行框架 1. 为什么需要自主规划的AI Agent 想象一下,你有一个能听懂复杂指令、自动拆解任务、调用各种工具完成工作的数字助手。它不仅能回答简单问题,还能处理"帮我分析上季…...
高级算法面试五十题深度解析,算法工程师面试必备
高级算法工程师面试50题深度解析与举一反三 难度警告:本系列题目专为冲击顶级技术岗位(如L5及以上算法工程师、研究员)的候选人设计。题目深度结合前沿论文、复杂系统设计与高难度竞赛题,要求候选人不仅精通经典算法,更…...
【FDTD - 1D、2D、3D自由空间】位于模拟域中心的点源会产生电磁辐射,然后这种辐射在真空中传播附Matlab代码
✅作者简介:热爱科研的Matlab仿真开发者,擅长数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。🍎 往期回顾关注个人主页:Matlab科研工作室🍊个人信条:格物致知,完整Matlab代码及仿真咨询…...
语言的边界,与软件的命运憾
1. 引入 在现代 AI 工程中,Hugging Face 的 tokenizers 库已成为分词器的事实标准。不过 Hugging Face 的 tokenizers 是用 Rust 来实现的,官方只提供了 python 和 node 的绑定实现。要实现与 Hugging Face tokenizers 相同的行为,最好的办法…...
个人开发者如何评估一个AI Token代理服务商的技术实力?
作为个人开发者,评估 AI Token 代理服务商(API 中转平台)的技术实力,核心是“把黑盒变灰盒”。不要只看价格和宣传,要通过可观测性、兼容性、容错机制三个维度进行实战验证。一、基础兼容性:接口规范与模型…...
