搭建rtmp直播流服务之2:使用java实现ffmpeg命令接口化调用(用java执行ffmpeg命令)
欢迎大家积极开心的加入讨论群
一、环境搭建
1、安装ffmpeg
下载对应系统的ffmpeg安装包,个人采用windows平台进行开发,所以安装了windows版本(各平台ffmpeg命令都是一样的,无须纠结)
2、ffmpeg的命令
这里不在详述,在这里会用简单的命令即可,后面我会写篇专门介绍ffmpeg的命令的文章
二、使用Java实现ffmpeg的命令调用的接口化可管理
1、java解析ffmpeg命令解析及动态实现
这是rtmp直播流服务器的发布地址:rtmp://192.168.30.21/live/
如果新发布一个视频,可以增加一个应用名,比如
rtmp://192.168.30.21/live/test2
或者
rtmp://192.168.30.21/live/DahuaCamera
注释写的很全,这里就不在做过多叙述
<span style="font-size:18px;"> /**
* 通过解析参数生成可执行的命令行字符串;
* name:应用名;input:接收地址;output:推送地址;fmt:视频格式;fps:视频帧率;rs:视频分辨率;disableAudio:是否开启音频
*
* @param paramMap
* @return 命令行字符串
*/
protected String getComm4Map(Map<String, Object> paramMap)
{
// -i:输入流地址或者文件绝对地址
StringBuilder comm = new StringBuilder("ffmpeg -i ");
// 是否有必输项:输入地址,输出地址,应用名
if (paramMap.containsKey("input") && paramMap.containsKey("output")
&& paramMap.containsKey("name"))
{
comm.append(paramMap.get("input")).append(" ");
// -f :转换格式,默认flv
comm.append(" -f ").append(paramMap.containsKey("fmt") ? paramMap.get("fmt") : "flv").append(" ");
// -r :帧率,默认25
comm.append("-r ").append(paramMap.containsKey("fps") ? paramMap.get("fps") : "30").append(" ");
// -s 分辨率 默认是原分辨率
comm.append("-s ").append(paramMap.containsKey("rs") ? paramMap.get("rs") : "").append(" ");
// -an 禁用音频
comm.append("-an ").append(paramMap.containsKey("disableAudio") && ((Boolean)paramMap.get("disableAudio")) ? "-an" : "").append(" ");
// 输出地址
comm.append(paramMap.get("output"));
//发布的应用名
comm.append(paramMap.get("name"));
//一个视频源,可以有多个输出,第二个输出为拷贝源视频输出,不改变视频的各项参数
comm.append(" ").append(" -vcodec copy -f flv -an rtmp://192.168.30.21/live/test2");
System.out.println(comm.toString());
return comm.toString();
}
else
{
throw new RuntimeException("输入流地址不能为空!");
} }</span>
2、执行ffmpmeg命令
2.1、上一步已经可以动态的创建ffmpeg的命令了,这一步我们要让命令执行
<span style="font-size:18px;"> final Process proc = Runtime.getRuntime().exec(comm);
System.out.println("执行命令----start commond");
OutHandler errorGobbler = new OutHandler(proc.getErrorStream(), "Error");
OutHandler outputGobbler = new OutHandler(proc.getInputStream(), "Info"); errorGobbler.start();
outputGobbler.start();</span>
2.2、在执行ffmpeg命令时必须开启两个输出线程(上面代码中的OutHandler类)
OutHandler类实现了Thread接口,并且重写了注销该线程的方法(用于关闭该线程)
具体实现是这样的:
<span style="font-size:18px;">import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader; /**
* 用于输出命令行主进程的消息线程(必须开启,否则命令行主进程无法正常执行) 重要:该类重写了destroy方法,用于安全的关闭该线程
*
* @author eguid
* @see OutHandler
* @since jdk1.7
*/ public class OutHandler extends Thread
{
// 控制线程状态
volatile boolean status = true; BufferedReader br = null; String type = null; public OutHandler(InputStream is, String type)
{
br = new BufferedReader(new InputStreamReader(is));
this.type = type;
} /**
* 重写线程销毁方法,安全的关闭线程
*/
@Override
public void destroy()
{
status = false;
} /**
* 执行输出线程
*/
@Override
public void run()
{
String msg = null;
try
{
while (status)
{ if ((msg = br.readLine()) != null)
{
System.out.println(type + "消息:" + msg);
}
}
}
catch (IOException e)
{
e.printStackTrace();
}
} }
</span>
2.3、实现统一关闭命令行主进程和关联的两个输出线程
现在命令行已经可以执行了,但是却没法关闭它和关联的两个输出线程,怎么办?
我们在上面代码中已经重写了输出线程的注销方法,只要能够得到这两个线程我们就能关闭它们;
命令行主进程也是同样,只需要获得该进程Process即可使用destroy()方法进行关闭。
2.3.1、实现(把主进程Process和两个OutHandler返回给上一级,让上一级统一存放并管理他们):
<span style="font-size:18px;"> public ConcurrentMap<String, Object> push(Map<String, Object> paramMap)
throws IOException
{
// 从map里面取数据,组装成命令
String comm = getComm4Map(paramMap);
ConcurrentMap<String, Object> resultMap = null;
// 执行命令行
final Process proc = Runtime.getRuntime().exec(comm);
System.out.println("执行命令----start commond");
OutHandler errorGobbler = new OutHandler(proc.getErrorStream(), "Error");
OutHandler outputGobbler = new OutHandler(proc.getInputStream(), "Info"); errorGobbler.start();
outputGobbler.start();
// 返回参数
resultMap = new ConcurrentHashMap<String, Object>();
resultMap.put("info", outputGobbler);
resultMap.put("error", errorGobbler);
resultMap.put("process", proc);
return resultMap;
}</span>
2.3.2、父级这样实现关闭主进程和两个输出线程(必须先关闭两个输出线程):
<span style="font-size:18px;"> public void removePush(String pushId)
{
if (hd.isHave(pushId))
{
ConcurrentMap<String, Object> map = hd.get(pushId);
//关闭两个线程
((OutHandler)map.get("error")).destroy();
((OutHandler)map.get("info")).destroy(); System.out.println("停止命令-----end commond");
//关闭命令主进程
((Process)map.get("process")).destroy();
hd.delete(pushId);
}
}</span>
2.3.3、简单使用map存放Process和OutHandler
<span style="font-size:18px;"> private static ConcurrentMap<String, ConcurrentMap<String, Object>> handlerMap = new ConcurrentHashMap<String, ConcurrentMap<String, Object>>(20);
</span>
到这里,我们就可以做到动态创建、运行并关闭ffmpeg命令的功能
简单测试一下能不能正常发布视频流到rtmp直播流服务器
<span style="font-size:18px;">//name:应用名;input:接收地址;output:推送地址;fmt:视频格式;fps:视频帧率;rs:视频分辨率;disableAudio:是否开启音频
PushManager pusher = new PushManagerImpl();
Map map=new HashMap();
map.put("name", "test3");
map.put("input", "rtsp://admin:admin@192.168.2.236:37779/cam/realmonitor?channel=1&subtype=0");
map.put("output", "rtmp://192.168.30.21/live/");
map.put("fmt", "flv");
map.put("fps", "25");
map.put("rs", "640x360");
map.put("disableAudio", true);
//推送后会获得该处理器的id,通过该id可关闭推送流
String id = pusher.push(map);
Thread.sleep(100000);
//关闭推送流
pusher.removePush(id);</span>
通过输出线程输出的消息可以看到直播流发布成功了
搭建rtmp直播流服务之2:使用java实现ffmpeg命令接口化调用(用java执行ffmpeg命令)的更多相关文章
- 搭建rtmp直播流服务之3:java开发ffmpeg实现rtsp转rtmp并实现ffmpeg命令的接口化管理架构设计及代码实现
上一篇文章简单介绍了java如何调用ffmpeg的命令:http://blog.csdn.net/eguid_1/article/details/51777716 上上一篇介绍了nginx-rtmp服 ...
- 搭建rtmp直播流服务之1:使用nginx搭建rtmp直播流服务器(nginx-rtmp模块的安装以及rtmp直播流配置)
欢迎大家积极开心的加入讨论群 群号:371249677 (点击这里进群) 一.方案简要 首先通过对开发方案的仔细研究(实时监控.流媒体.直播流方案的数据源-->协议转换-->服务器--&g ...
- 搭建rtmp直播流服务之4:videojs和ckPlayer开源播放器二次开发(播放rtmp、hls直播流及普通视频)
前面几章讲解了使用 nginx-rtmp搭建直播流媒体服务器; ffmpeg推流到nginx-rtmp服务器; java通过命令行调用ffmpeg实现推流服务; 从数据源获取,到使用ffmpeg推流, ...
- 三、直播整体流程 五、搭建Nginx+Rtmp直播流服务
HTML5实现视频直播功能思路详解_html5教程技巧_脚本之家 https://m.jb51.net/html5/587215.html 三.直播整体流程 直播整体流程大致可分为: 视频采集端:可以 ...
- 极速搭建RTMP直播流服务器+webapp (vue) 简单实现直播效果
在尝试使用webRTC实现webapp直播失败后,转移思路开始另外寻找可行的解决方案.在网页上尝试使用webRTC实现视频的直播与看直播,在谷歌浏览器以及safari浏览器上测试是可行的.但是基于基座 ...
- nginx开发(四)调用ffmpeg,搭建rtmp直播流。
1: 修改conf文件,配置rtmp直播 打开usr/local/nginx/conf/nginx.conf,添加红色内容: rtmp {#rtmp点播配置 server { li ...
- 利用docker搭建RTMP直播流服务器实现直播
一.rtmp服务器搭建 环境: centos 7.* 1.先安装docker(省略) 2.下载docker容器 docker pull alfg/nginx-rtmp 3.运行容器(记得打开防火墙端口 ...
- 搭建RTMP直播流服务器
最近项目比较紧张,所以没什么时间写博客,正好这几天没什么事,赶紧记录下自己最近所学. 环境配置 服务器选用 服务器我选择的是小鸟云 ,原因很简单,他的个人用户有3个月免费使用时间. 服务器环境 Win ...
- 实时监控、直播流、流媒体、视频网站开发方案流媒体服务器搭建及配置详解:使用nginx搭建rtmp直播、rtmp点播、,hls直播服务配置详解
注意:这里不会讲到nginx流媒体模块如何安装的问题,只研究rtmp,hls直播和录制相关的nginx服务器配置文件的详细用法和说明.可以对照这些命令详解配置nginx -rtmp服务 一.nginx ...
随机推荐
- Java中Json解析
首先准备一个JSON格式的字符串 * String JsonStr = "{object:{persons:" + "[{name:'呵呵',image:'http:// ...
- [系统启动]Printk与sched_clock_init的一点分析
作者:Younger Liu, 本作品采用知识共享署名-非商业性使用-相同方式共享 3.0 未本地化版本许可协议进行许可. 在分析Linu内核启动的过程中,发现一段"不平常" ...
- 使用vs code实现git同步
用了git最方便的就是项目同步管理,回到家打开vscode只需要点击一下pull就能全部同步过来.是不是很方便....毕竟之前我都是拿u盘拷贝回家或者存到云盘再下载下来.. 我这里用的是国内的码云 ...
- webUI自动化测试框架---”pyswat“介绍
webUI自动化测试框架---"pyswat"介绍 大家好我是lamecho 辣么丑,今天给大家介绍一款web自动化测试框架pyswat. "pyswat"是 ...
- Linux目录与文件的权限
零.Linux中的权限为什么重要? 权限直接关系数据安全! 一.用户基础概念: 所有者(owner):拥有这个文件的用户.一般拥有目录或文件的所有权限. 用户组(group):几个用户组成一个用户组, ...
- Excel 数据导入(OleDb)
@using (Html.BeginForm("Student", "Excel", FormMethod.Post, new { enctype = &quo ...
- 用PHP删除ftp下载导致的文件空行
使用FTP上传下载文件,如果没有设置传输方式为二进制,可能会导致文件出现空行的情况,例如: 使用PHP对文件的空行进行删除,使用正则: <?php $file = './abc.inc.php' ...
- PHP获得上(两)周时间
就不手写了
- 通过BitSet完成对单词使用字母的统计
什么是BitSet BitSet类实现了一组位或标记(flag),这些位可被分别设置或清除.当需要跟踪一组布尔值时,这种类很有用. 您只需让每一位对应一个值,并根据需要设置或清除即可. 标记(flag ...
- .Net程序员学用Oracle系列(25):触发器详解
1.触发器理论 1.1.触发器的应用场景 1.2.触发器的类型 1.3.DML 触发器的触发顺序 2.触发器实战 2.1.创建触发器 2.1.1.创建 DML 触发器 2.1.2.创建 DDL 触发器 ...