springboot(JavaCV )实现视频截取第N帧并保存图片

这篇具有很好参考价值的文章主要介绍了springboot(JavaCV )实现视频截取第N帧并保存图片。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

springboot(JavaCV )实现视频截取第N帧并保存图片

现在视频网站展示列表都是用img标签展示的,动图用的是gif,但是我们上传视频时并没有视屏封面,就这需要上传到服务器时自动生成封面并保存

本博客使用jar包的方式实现上传视频文件并且截取视频第一帧,保存到阿里云的OSS(也可以保存到本地获取其他任何地方)。

JavaCV 是一款开源的视觉处理库,基于GPLv2协议,对各种常用计算机视觉库封装后的一组jar包,

封装了OpenCV、libdc1394、OpenKinect、videoInput和ARToolKitPlus等计算机视觉编程人员常用库的接口。

此方法的好处是不需要再服务器上安装插件,直接代码中就可以实现视频截取。

我们需要截取视频第一帧,主要用到了ffmpeg和opencv。

一 , 引入jar包
我用到的maven的目前最新javacv版本,1.4.3,它应该支持jdk1.7及以上,我项目用的还是jdk1.8.

不过需要注意的是在使用的过程当中 , maven引入jar的时候 会引入所有平台的版本

全部引入大小在五百兆左右(不建议使用)

<!--视频截取第一帧-->
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacv</artifactId>
            <version>1.4.3</version>
        </dependency>
        <dependency>
            <groupId>org.bytedeco.javacpp-presets</groupId>
            <artifactId>ffmpeg-platform</artifactId>
            <version>4.0.2-1.4.3</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>RELEASE</version>
        </dependency>

二 , java 代码实现文章来源地址https://www.toymoban.com/news/detail-664082.html

public class ImgTools {
    //util调用application.properties
    private final static ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle("application");
    private final static String aliyuVideonImg = RESOURCE_BUNDLE.getString("aliyun.video.img");
 
//    public static void main(String[] args) throws Exception {
//        ImgTools imgTools = new ImgTools();
//        System.out.println(imgTools.randomGrabberFFmpegVideoImage
//                ("视频地址,可以是网络视频,也可以是本地视频"));
//    }
 
    /**
     * 获取视频缩略图
     *
     * @param filePath:视频路径
     * @throws Exception
     */
    public String randomGrabberFFmpegVideoImage(String filePath) throws Exception {
        String targetFilePath = "";
        FFmpegFrameGrabber ff = FFmpegFrameGrabber.createDefault(filePath);
        ff.start();
        //判断是否是竖屏小视频
        String rotate = ff.getVideoMetadata("rotate");
        int ffLength = ff.getLengthInFrames();
        Frame f;
        int i = 0;
        int index = 3;//截取图片第几帧
        while (i < ffLength) {
            f = ff.grabImage();
            if (i == index) {
                if (null != rotate && rotate.length() > 1) {
                    targetFilePath = doExecuteFrame(f, true);   //获取缩略图
                } else {
                    targetFilePath = doExecuteFrame(f, false);   //获取缩略图
                }
                break;
            }
            i++;
        }
        ff.stop();
        return targetFilePath;  //返回的是视频第N帧
    }
 
    /**
     * 截取缩略图,存入阿里云OSS(按自己的上传类型自定义转换文件格式)
     *
     * @param f
     * @return
     * @throws Exception
     */
    public String doExecuteFrame(Frame f, boolean bool) throws Exception {
        if (null == f || null == f.image) {
            return "";
        }
        Java2DFrameConverter converter = new Java2DFrameConverter();
        BufferedImage bi = converter.getBufferedImage(f);
        if (bool == true) {
            Image image = (Image) bi;
            bi = rotate(image, 90);//图片旋转90度
        }
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        ImageIO.write(bi, "png", os);
        byte[] sdf = os.toByteArray();
        InputStream input = new ByteArrayInputStream(os.toByteArray());
        MultipartFile multipartFile = new MockMultipartFile("temp.jpg", "temp.jpg", "temp.jpg", input);
        Aliyunoss aliyunoss = new Aliyunoss();
        //如需了解阿里云OSS,请详读我的另一篇博客("https://blog.csdn.net/weixin_44401989/article/details/105732856")
        String url = aliyunoss.uploadAli(multipartFile, aliyuVideonImg);
        return url;
    }
 
    /**
     * 图片旋转角度
     *
     * @param src   源图片
     * @param angel 角度
     * @return 目标图片
     */
    public static BufferedImage rotate(Image src, int angel) {
        int src_width = src.getWidth(null);
        int src_height = src.getHeight(null);
        // calculate the new image size
        Rectangle rect_des = CalcRotatedSize(new Rectangle(new Dimension(
                src_width, src_height)), angel);
 
        BufferedImage res = null;
        res = new BufferedImage(rect_des.width, rect_des.height,
                BufferedImage.TYPE_INT_RGB);
        Graphics2D g2 = res.createGraphics();
        // transform(这里先平移、再旋转比较方便处理;绘图时会采用这些变化,绘图默认从画布的左上顶点开始绘画,源图片的左上顶点与画布左上顶点对齐,然后开始绘画,修改坐标原点后,绘画对应的画布起始点改变,起到平移的效果;然后旋转图片即可)
 
        //平移(原理修改坐标系原点,绘图起点变了,起到了平移的效果,如果作用于旋转,则为旋转中心点)
        g2.translate((rect_des.width - src_width) / 2, (rect_des.height - src_height) / 2);
 
 
        //旋转(原理transalte(dx,dy)->rotate(radians)->transalte(-dx,-dy);修改坐标系原点后,旋转90度,然后再还原坐标系原点为(0,0),但是整个坐标系已经旋转了相应的度数 )
        g2.rotate(Math.toRadians(angel), src_width / 2, src_height / 2);
 
//        //先旋转(以目标区域中心点为旋转中心点,源图片左上顶点对准目标区域中心点,然后旋转)
//        g2.translate(rect_des.width/2,rect_des.height/ 2);
//        g2.rotate(Math.toRadians(angel));
//        //再平移(原点恢复到源图的左上顶点处(现在的右上顶点处),否则只能画出1/4)
//        g2.translate(-src_width/2,-src_height/2);
 
 
        g2.drawImage(src, null, null);
        return res;
    }
 
    /**
     * 计算转换后目标矩形的宽高
     *
     * @param src   源矩形
     * @param angel 角度
     * @return 目标矩形
     */
    private static Rectangle CalcRotatedSize(Rectangle src, int angel) {
        double cos = Math.abs(Math.cos(Math.toRadians(angel)));
        double sin = Math.abs(Math.sin(Math.toRadians(angel)));
        int des_width = (int) (src.width * cos) + (int) (src.height * sin);
        int des_height = (int) (src.height * cos) + (int) (src.width * sin);
        return new java.awt.Rectangle(new Dimension(des_width, des_height));
    }
}
public class ImgTools {
    //util调用application.properties
    private final static ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle("application");
    private final static String aliyuVideonImg = RESOURCE_BUNDLE.getString("aliyun.video.img");
 
//    public static void main(String[] args) throws Exception {
//        ImgTools imgTools = new ImgTools();
//        System.out.println(imgTools.randomGrabberFFmpegVideoImage
//                ("视频地址,可以是网络视频,也可以是本地视频"));
//    }
 
    /**
     * 获取视频缩略图
     *
     * @param filePath:视频路径
     * @throws Exception
     */
    public String randomGrabberFFmpegVideoImage(String filePath) throws Exception {
        String targetFilePath = "";
        FFmpegFrameGrabber ff = FFmpegFrameGrabber.createDefault(filePath);
        ff.start();
        //判断是否是竖屏小视频
        String rotate = ff.getVideoMetadata("rotate");
        int ffLength = ff.getLengthInFrames();
        Frame f;
        int i = 0;
        int index = 3;//截取图片第几帧
        while (i < ffLength) {
            f = ff.grabImage();
            if (i == index) {
                if (null != rotate && rotate.length() > 1) {
                    targetFilePath = doExecuteFrame(f, true);   //获取缩略图
                } else {
                    targetFilePath = doExecuteFrame(f, false);   //获取缩略图
                }
                break;
            }
            i++;
        }
        ff.stop();
        return targetFilePath;  //返回的是视频第N帧
    }
 
    /**
     * 截取缩略图,存入阿里云OSS(按自己的上传类型自定义转换文件格式)
     *
     * @param f
     * @return
     * @throws Exception
     */
    public String doExecuteFrame(Frame f, boolean bool) throws Exception {
        if (null == f || null == f.image) {
            return "";
        }
        Java2DFrameConverter converter = new Java2DFrameConverter();
        BufferedImage bi = converter.getBufferedImage(f);
        if (bool == true) {
            Image image = (Image) bi;
            bi = rotate(image, 90);//图片旋转90度
        }
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        ImageIO.write(bi, "png", os);
        byte[] sdf = os.toByteArray();
        InputStream input = new ByteArrayInputStream(os.toByteArray());
        MultipartFile multipartFile = new MockMultipartFile("temp.jpg", "temp.jpg", "temp.jpg", input);
        Aliyunoss aliyunoss = new Aliyunoss();
        //如需了解阿里云OSS,请详读我的另一篇博客("https://blog.csdn.net/weixin_44401989/article/details/105732856")
        String url = aliyunoss.uploadAli(multipartFile, aliyuVideonImg);
        return url;
    }
 
    /**
     * 图片旋转角度
     *
     * @param src   源图片
     * @param angel 角度
     * @return 目标图片
     */
    public static BufferedImage rotate(Image src, int angel) {
        int src_width = src.getWidth(null);
        int src_height = src.getHeight(null);
        // calculate the new image size
        Rectangle rect_des = CalcRotatedSize(new Rectangle(new Dimension(
                src_width, src_height)), angel);
 
        BufferedImage res = null;
        res = new BufferedImage(rect_des.width, rect_des.height,
                BufferedImage.TYPE_INT_RGB);
        Graphics2D g2 = res.createGraphics();
        // transform(这里先平移、再旋转比较方便处理;绘图时会采用这些变化,绘图默认从画布的左上顶点开始绘画,源图片的左上顶点与画布左上顶点对齐,然后开始绘画,修改坐标原点后,绘画对应的画布起始点改变,起到平移的效果;然后旋转图片即可)
 
        //平移(原理修改坐标系原点,绘图起点变了,起到了平移的效果,如果作用于旋转,则为旋转中心点)
        g2.translate((rect_des.width - src_width) / 2, (rect_des.height - src_height) / 2);
 
 
        //旋转(原理transalte(dx,dy)->rotate(radians)->transalte(-dx,-dy);修改坐标系原点后,旋转90度,然后再还原坐标系原点为(0,0),但是整个坐标系已经旋转了相应的度数 )
        g2.rotate(Math.toRadians(angel), src_width / 2, src_height / 2);
 
//        //先旋转(以目标区域中心点为旋转中心点,源图片左上顶点对准目标区域中心点,然后旋转)
//        g2.translate(rect_des.width/2,rect_des.height/ 2);
//        g2.rotate(Math.toRadians(angel));
//        //再平移(原点恢复到源图的左上顶点处(现在的右上顶点处),否则只能画出1/4)
//        g2.translate(-src_width/2,-src_height/2);
 
 
        g2.drawImage(src, null, null);
        return res;
    }
 
    /**
     * 计算转换后目标矩形的宽高
     *
     * @param src   源矩形
     * @param angel 角度
     * @return 目标矩形
     */
    private static Rectangle CalcRotatedSize(Rectangle src, int angel) {
        double cos = Math.abs(Math.cos(Math.toRadians(angel)));
        double sin = Math.abs(Math.sin(Math.toRadians(angel)));
        int des_width = (int) (src.width * cos) + (int) (src.height * sin);
        int des_height = (int) (src.height * cos) + (int) (src.width * sin);
        return new java.awt.Rectangle(new Dimension(des_width, des_height));
    }
}

到了这里,关于springboot(JavaCV )实现视频截取第N帧并保存图片的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • JS 截取视频某一帧图片 实现视频截图

    第一步:创建video用于存放需要截取的视频文件 第二步:创建canvas画布,用于绘制截取到的图片 1,定义创建一个 canvas 标签; 2,指定 canvas 标签的宽高; 3, 调用canvas元素中的 getContext() 方法(返回一个用于在画布上绘图的环境)。 要注意的是 drawImage() 的第一个参数不再是player而

    2024年02月12日
    浏览(45)
  • halcon截取图片并保存为图片

    halcon截取图片并保存为图片,代码如下: 关键代码 ,截取图片,并保存到文件夹中,代码如下: lib_convert_point (Cross, String, Point)函数,通过String获取某个点位置坐标。 String=[\\\'1676.714,1319.375\\\'] lib_white_balance (TabImage, TabImage, 80, 80, 80)自定义函数,处理截取的图片。 需要处理的图片

    2024年02月13日
    浏览(42)
  • python+opencv实现显示摄像头,截取相关图片,录取相关视频

    实时显示摄像头图像 按下空格键,截取图片 按下tab键,开始录制摄像内容,再次按下,结束录制  按下Esc键,关闭窗口 截图:  可以添加函数来使图像的显示效果改变(边缘检测效果): 自行在对应的帧显示处调用:  

    2024年02月14日
    浏览(40)
  • Python截取图片区域并保存03

    Python + OpenCV图片基本操作02 目录 系列文章目录 前言 一、获取感兴趣图片坐标 二、剪切图片坐标区域并保存图片 总结 提供一张图片,如何截剪其中的某一部分的区域? 我的思路是分两步: 1. 找到要裁剪区域的坐标 2. 根据图片坐标进行剪切,并保存 1. cv2.COLOR_BGR2GRAY 将BG

    2024年02月08日
    浏览(76)
  • 已实现:JS如何根据视频的http(s)地址,来截取帧图片,并实现大图压缩的功能

    现在,我们已经有了视频的http地址,我们怎么截取帧图片呢?我以Vue为基础架构,来写写代码。 1、先写布局,先得有video,然后得有canvas 界面上很简单,就一个视频容器,一个画布canvas还不让它显示,还有一个就是截取帧图片了。 接下来是js关键方法部分: 以上的代码就是

    2024年01月17日
    浏览(39)
  • Python相机自动采集图像,然后模板匹配、自动截取保存图片

    通过python调用相机然后间隔一段时间进行拍摄图片,进行识别提取。 提示:以下是本篇文章正文内容,下面案例可供参考 我的电脑没有相机硬件设备,于是我通过手机在局域网的状态下进行图像传输到电脑上,在这里特别推荐软件:DroidCam Client    建议大家按照情况自行安

    2024年02月12日
    浏览(35)
  • javacv和opencv对图文视频编辑-裸眼3D图片制作

    通过斗鸡眼,将左右两张相似的图片叠加到一起看,就会有3D效果。 3D图片,3D眼镜,3D视频等原理类似,都是通过两眼视觉差引起脑补产生3D效果。 图片:  图片来源: 一些我拍摄的真*裸眼3D照片 - 哔哩哔哩 https://www.bilibili.com/read/cv13066106/?spm_id_from=333.999.0.0 上边两幅图片在

    2024年01月18日
    浏览(46)
  • 从视频中截取指定帧图片

    前言: 我们在很多时候需要对视频文件进行分析,或者对视频产生缩略图。因此视频截取技术必不可少。

    2024年01月24日
    浏览(31)
  • Java通过javacv获取视频、音频、图片等元数据信息(分辨率、大小、帧等信息)

    相信我们都会或多或少需要给前端返回视频或者音频的一些信息,那么今天这篇文章通过Java语言使用javacv来获取视频、音频、图片等元数据信息(分辨率、大小、帧等信息) 一、首先导入依赖 可以先导入javacv/javacv-platform依赖,由于依赖比较大,所以我们可以先去除部分不需

    2024年02月04日
    浏览(52)
  • video截取视频第一帧作为播放前默认图片

    重要!不设置会导致第一帧图片不显示 实现js 附上全部代码

    2024年02月12日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包