java抓取rtmp流的图像

it2024-04-02  65

最近项目都在跟摄像头打交道,对录制视频流以及抓取图片这一块做了详细的研究,由于目前的摄像头支持可见光以及红外光,之前录制可见光直播流可以见博客使用ffmpeg录制直播流,这两天由于需要对红外光通道进行图像抓取,后面用人像识别算法来识别,所以本文介绍一下如何抓取视频流图像。

方法一:使用javacv进行图像抓取

项目依赖 <dependency> <groupId>org.bytedeco</groupId> <artifactId>javacv</artifactId> <version>1.5.1</version> </dependency> <dependency> <groupId>org.bytedeco</groupId> <artifactId>ffmpeg-platform</artifactId> <version>4.1.3-1.5.1</version> </dependency> 上代码,复制即可使用(方法参数自己稍作修改) /** * 按帧录制视频 * * @param inputFile-该地址可以是网络直播/录播地址,也可以是远程/本地文件路径 * @param outputFile -该地址只能是文件地址,如果使用该方法推送流媒体服务器会报错,原因是没有设置编码格式 * @throws FrameGrabber.Exception * @throws FrameRecorder.Exception * @throws org.bytedeco.javacv.FrameRecorder.Exception */ public void frameRecordImage(String inputFile, String outputFile, String imgMat, String frameRate,String imageName) throws Exception { avutil.av_log_set_level(avutil.AV_LOG_FATAL); // 获取视频源 // FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputFile); MyFFmpegFrameGrabber grabber = new MyFFmpegFrameGrabber(inputFile); grabber.setOption("rtsp_transport", "tcp"); grabber.setImageWidth(640); grabber.setImageHeight(360); grabber.setTimeout(3000); grabber.setFrameRate(frameRate); grabber.setVideoBitrate(3000000); Java2DFrameConverter converter = new Java2DFrameConverter(); recordByFrame(grabber, converter, outputFile, imgMat, imageName); } private void recordByFrame(MyFFmpegFrameGrabber grabber, Java2DFrameConverter converter, String outputFile, String imgMat,String imageName) throws Exception { try {//建议在线程中使用该方法 log.info("the code {} grab start"); grabber.start(); imageByframe(grabber, converter, outputFile, imgMat, imageName); grabber.stop(); log.info("the code {} grab stop"); } finally { if (grabber != null) { grabber.stop(); log.info("the code {} grab stop"); } } } private void imageByframe(MyFFmpegFrameGrabber grabber, Java2DFrameConverter converter, String outputFile, String imgMat,String imageName) throws IOException { Frame frame = grabber.grabImage(); BufferedImage bi = converter.convert(frame); // 每个frameRate帧进行一次抓取 outputFile = outputFile + SLASH + imageName + Field.DOT + imgMat; ImageIO.write(bi, imgMat, new File(outputFile)); } public static void main(String[] args) { RecordUtil recordUtil = new RecordUtil(); recordUtil.frameRecordImage("rtmp流地址", "图片输出路径", "图片后缀", "帧率", "图片名"); }

方法二:使用ffmpeg进行图像抓取

首先在服务器安装ffmpeg工具,见文章Linux安装ffmpeg详细教程(超细)上代码,复制即可用 /** * @param videoFilename 红外视频流地址 * @param imageName 图片名 * @param outFile 图片存储路径 * @param width:图片长 * @param height:图片宽 * @param hour:指定时 * @param min:指定分 * @param sec:指定秒 * @param device 设备 * @param eventTime 报警时间 * @throws IOException * @throws InterruptedException */ public void grabImage(String videoFilename, String imageName, String outFile, int width, int height, int hour, int min, float sec, Device device, long eventTime) throws IOException, InterruptedException { createFile(outFile); ProcessBuilder processBuilder = getProcessBuilder(videoFilename, imageName, outFile, width, height, hour, min, sec); log.info("抓取红外图片... start"); Process process = processBuilder.start(); InputStream stderr = process.getErrorStream(); InputStreamReader isr = new InputStreamReader(stderr); BufferedReader br = new BufferedReader(isr); while (br.readLine() != null) ; process.waitFor(); log.info("抓取红外图片... end"); outFile = outFile + SLASH + imageName; addEventHWImage(device, eventTime, outFile); if (br != null) br.close(); if (isr != null) isr.close(); if (stderr != null) stderr.close(); } /** * 抓取图片ffmpeg命令 * * @param videoFilename * @param imageName * @param outFile * @param width * @param height * @param hour * @param min * @param sec * @return */ @NotNull private ProcessBuilder getProcessBuilder(String videoFilename, String imageName, String outFile, int width, int height, int hour, int min, float sec) { String rtmpTool = "ffmpeg"; return new ProcessBuilder(rtmpTool, "-y", "-i", videoFilename, "-vframes", "1", "-ss", hour + ":" + min + ":" + sec, "-f", "mjpeg", "-s", width + "*" + height, "-an", outFile.concat(File.separator).concat(imageName)); } public static void main(String[] args) { recordUtil.grabImage(liveInfraRed, eventTime + PNG_LAST, VIDEO_URL + device.getDeviceId(), 1920, 1080, 0, 0, 0, device, eventTime); }

两种方法自行选择 网上找到一个开放的rtmp流地址供大家测试:rtmp://58.200.131.2:1935/livetv/hunantv

最新回复(0)