前言
javacv开发包是用于支持java多媒体开发的一套开发包,可以适用于本地多媒体(音视频)调用以及音视频,图片等文件后期操作(图片修改,音视频解码剪辑等等功能),这里只使用javacv来实现一些简单的功能,具体到项目中还需要大家自己磨合
重要:
建议使用最新javaCV1.5版本,该版本已解决更早版本中已发现的大部分bug --博主目前使用的 javaCV1.5.4
javacv系列文章使用6个jar包:
javacv.jar,javacpp.jar,ffmpeg.jar,ffmpeg-系统平台.jar,opencv.jar,opencv-系统平台.jar。
其中ffmpeg-系统平台.jar,opencv-系统平台.jar中的系统平台根据开发环境或者测试部署环境自行更改为对应的jar包,比如windows7 64位系统替换为ffmpeg-x86-x64.jar
为什么要这样做:因为ffmpeg-系统平台.jar中存放的是c/c++本地so/dll库,而ffmpeg.jar就是使用javacpp封装的对应本地库java接口的实现,而javacpp就是基于jni的一个功能性封装包,方便实现jni,javacv.jar就是对9个视觉库进行了二次封装,但是实现的功能有限,所以建议新手先熟悉openCV和ffmpeg这两个C/C++库的API后再来看javaCV思路就会很清晰了。
上一章简单的介绍了 将远程的rtsp视频流录制保存成本地视频文件:javacv-03:录制流媒体服务器的rtsp/rtmp视频内容,保存为本地视频文件
下面将介绍如何 实时转发rtsp视频流至内网rtmp流媒体服务器:
1、依赖配置说明
maven和gradle方式如果想要减小依赖包大小,则需要手动进行排除不需要的平台依赖即可
(注意:从其他地方下载的依赖包请积极开心的替换为官方jar包和博主提供jar包;如果使用其他jar包版本而导致出错,不要急着找博主问为啥会报错,先把jar包替换了再试试看)
(1)使用maven添加依赖
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>1.5.4</version>
</dependency>
(2)使用gradle添加依赖
dependencies {
compile group: 'org.bytedeco', name: 'javacv-platform', version: '1.4.4'
}
(3)使用本地jar包方式
最新版实在太大,需要下载全量包的请到官方github.com/bytedeco/javacv下载
注:博主不太赞同使用这种方式!!!(但还是进行了相关介绍)
jar包使用须知:
1、windows x64平台用到的opencv依赖:opencv.jar;oepncv-windows-x86_64.jar(其他平台替换为对应的jar包即可)
2、苹果mac需要opencv-macosx-x86_64.jar 3、linux平台需要:opencv-linux-x86_64.jar
4、安卓平台arm架构的需要opencv-android-arm.jar ,基于x86的需要opencv-android-x86.jar
2、为什么不需要安装opencv?
从javacv0.8开始,已经不需要本地安装opencv,直接通过引用opencv对应的系统平台的引用包即可。
(比如oepncv-windows-x86_64.jar就是典型的64位windows环境依赖包)
3、代码实现
import javax.swing.JFrame;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.javacv.CanvasFrame;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.FrameGrabber;
import org.bytedeco.javacv.FrameRecorder;
import org.bytedeco.javacv.FrameGrabber.Exception;
/**
* 最大的问题是:远程的rtmp流会出现延迟和丢包的情况 !
*
*
* @author xiaoyutongxue6
* @date 2021-03-11
*/
public class SaveRecordRemote {
public static void main(String[] args)
throws Exception, org.bytedeco.javacv.FrameRecorder.Exception, InterruptedException {
String inputFile = "rtsp://xxx";
String outputFile = "rtmp://xxx";
recordPush(inputFile, outputFile, 25);
}
public static void recordPush(String inputFile, String outputFile, int v_rs)
throws Exception, org.bytedeco.javacv.FrameRecorder.Exception, InterruptedException {
FrameGrabber grabber = new FFmpegFrameGrabber(inputFile);
// FrameGrabber grabber = FrameGrabber.createDefault(0);
grabber.setOption("rtsp_transport", "tcp");// 设置成TCP连接,网络会稳定很多,默认使用的是UDP
try {
grabber.start();
} catch (Exception e) {
throw e;
}
FrameRecorder recorder = FrameRecorder.createDefault(outputFile, 1280, 720);
recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264); // 转码过程,如果不进行转码,则没有办法推送到远程rtmp
recorder.setFormat("flv");
recorder.setFrameRate(v_rs); // 设置最低视频帧率,最低25(即每秒25张图片,低于25就会出现闪屏)
recorder.setGopSize(v_rs);
// 该代码必须设置声频的通道,不然出报错
recorder.setAudioChannels(1);
try {
recorder.start();
} catch (org.bytedeco.javacv.FrameRecorder.Exception e) {
e.printStackTrace();
System.out.println("录制器启动失败");
}
// 本地预览
CanvasFrame cFrame = new CanvasFrame("欢迎来到直播间", CanvasFrame.getDefaultGamma() / grabber.getGamma());
cFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
cFrame.setAlwaysOnTop(true);
Frame frame = null;
while ((frame = grabber.grab()) != null) {
if (cFrame.isVisible()) {
cFrame.showImage(frame);
}
recorder.setTimestamp(frame.timestamp);
recorder.record(frame);
}
cFrame.dispose();
recorder.close();
grabber.close();
}
}
至此,代码已经可以成功运行,在main函数中填写远程提供的rtsp视频流地址,并填写自己搭建的流媒体服务器地址(rtmp):远程直播时则可以通过VLC软件进行观看。 流媒体服务器的搭建可以参考:从零开始搭建流媒体服务器
注:此次代码是基于vscode编辑器进行开发,使用起来很是方便,也是轻量级的;jdk版本为1.8。