SpringBoot - 使用javaCV截取RTMP、RTSP视频流图片
作者:hangge | 2024-05-09 08:20
有时我们需要在后台自动拉取 rtsp、rtmp 等视频流并进行截图,这个使用 javaCV 库即可实现。javaCV 之所以叫 javaCV 就是因为 openCV 而得名,不过 javaCV 的功能远远大于 openCV,openCV 只能用于处理图像,而 javacv 不仅包含 openCV 全套 api,还支持 ffmpeg 音视频编解码,tensflow、caffe 等深度学习库,tessrac ocr 等字符识别,矩阵计算库。下面我通过样例演示如何使用 javaCV。
(2)运行结构如下,可以看到视频图片已经成功保存到本地:
(2)运行结果如下:
(2)运行效果如下:
1,安装配置
在项目 pom.xml 文件中添加 javaCV 依赖配置即可:
<dependency> <groupId>org.bytedeco</groupId> <artifactId>javacv-platform</artifactId> <version>1.5.7</version> </dependency>
2,使用样例
(1)下面样例中我们获取一个 RTSP 视频流并截取视频图片:
public class VideoCapture { public static void main(String[] args) { // 视频路径 String url = "rtmp://ns8.indexforce.com/home/mystream"; // 保存路径 String savePath = "/Users/hangge/Desktop/" + System.currentTimeMillis() + ".jpg"; try { // 开始截图 startCaputre(url, savePath); } catch (IOException e) { throw new RuntimeException(e); } catch (InterruptedException e) { throw new RuntimeException(e); } } /** * 开始截图 */ public static void startCaputre(String url, String savePath) throws IOException, InterruptedException{ FFmpegFrameGrabber grabber = FFmpegFrameGrabber.createDefault(url); grabber.setOption("rtsp_transport", "tcp"); // 使用tcp的方式,不然会丢包很严重 //grabber.setImageWidth(960); //设置宽高尺寸(不设置则使用视频流原始宽高) //grabber.setImageHeight(540); System.out.println("--- grabber start ---"); grabber.start(); while (true){ Frame frame = grabber.grabImage(); if (frame != null) { File outPut = new File(savePath); ImageIO.write(frameToBufferedImage(frame), "jpg", outPut); grabber.stop(); grabber.release(); System.out.println("图片已保存:" + outPut.getPath()); System.out.println("--- grabber end ---"); break; } } } /** * 创建BufferedImage对象 */ public static BufferedImage frameToBufferedImage(Frame frame) { Java2DFrameConverter converter = new Java2DFrameConverter(); BufferedImage bufferedImage = converter.getBufferedImage(frame); return bufferedImage; } }
(2)运行结构如下,可以看到视频图片已经成功保存到本地:
附一:实现视频的连续截图
(1)下面对样例稍作修改,可以通过设置时间间隔(秒)和最大截图张数来实现连续截图:
public class VideoCapture { public static void main(String[] args) { // 视频路径 String url = "rtmp://ns8.indexforce.com/home/mystream"; // 保存路径 String savePath = "/Users/hangge/Desktop/"; try { // 开始截图(每5秒截取一张图片,总共10张) startCaputre(url, savePath, 5, 10); } catch (IOException e) { throw new RuntimeException(e); } catch (InterruptedException e) { throw new RuntimeException(e); } } /** * 开始截图 */ public static void startCaputre(String url, String savePath, int interval, int total) throws IOException, InterruptedException{ FFmpegFrameGrabber grabber = FFmpegFrameGrabber.createDefault(url); grabber.setOption("rtsp_transport", "tcp"); // 使用tcp的方式,不然会丢包很严重 //grabber.setImageWidth(960); //设置宽高尺寸(不设置则使用视频流原始宽高) //grabber.setImageHeight(540); System.out.println("--- grabber start ---"); grabber.start(); while (total>0){ Frame frame = grabber.grabImage(); if (frame != null) { File outPut = new File(savePath + System.currentTimeMillis() + ".jpg"); ImageIO.write(frameToBufferedImage(frame), "jpg", outPut); System.out.println("图片已保存:" + outPut.getPath()); total--; Thread.sleep(interval * 1000); } } grabber.stop(); grabber.release(); System.out.println("--- grabber end ---"); } /** * 创建BufferedImage对象 */ public static BufferedImage frameToBufferedImage(Frame frame) { Java2DFrameConverter converter = new Java2DFrameConverter(); BufferedImage bufferedImage = converter.getBufferedImage(frame); return bufferedImage; } }
(2)运行结果如下:
附二:对外提供接口服务
(1)下面样例将截图功能封装成一个 API 接口服务,通过 Get 请求方式传入视频流地址后返回截图:
@RestController public class VideoCaptureController { @GetMapping(value = "/capture",produces = MediaType.IMAGE_PNG_VALUE) public byte[] capture(@RequestParam("url") String url) { try { return startCapture(url); } catch (IOException e) { throw new RuntimeException(e); } catch (InterruptedException e) { throw new RuntimeException(e); } } /** * 开始截图 */ public byte[] startCapture(String url) throws IOException, InterruptedException{ FFmpegFrameGrabber grabber = FFmpegFrameGrabber.createDefault(url); grabber.setOption("rtsp_transport", "tcp"); // 使用tcp的方式,不然会丢包很严重 //grabber.setImageWidth(960); //设置宽高尺寸(不设置则使用视频流原始宽高) //grabber.setImageHeight(540); System.out.println("--- grabber start ---"); grabber.start(); while (true){ Frame frame = grabber.grabImage(); if (frame != null) { //获取BufferedImage对象 BufferedImage bufferedImage = frameToBufferedImage(frame); //将获取BufferedImage转成byte[]返回 ByteArrayOutputStream out = new ByteArrayOutputStream(); ImageIO.write(bufferedImage, "png", out); grabber.stop(); grabber.release(); System.out.println("--- grabber end ---"); return out.toByteArray(); } } } /** * 创建BufferedImage对象 */ public BufferedImage frameToBufferedImage(Frame frame) { Java2DFrameConverter converter = new Java2DFrameConverter(); BufferedImage bufferedImage = converter.getBufferedImage(frame); return bufferedImage; } }
(2)运行效果如下:
全部评论(0)