java获取视频封面

pom.xml
     <!--javacv 处理视频-->
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacv</artifactId>
            <version>0.8</version>
        </dependency>
------------        
application.yml(这个是自己命名的)
-----------------
image-config:
  #输入路径
  inputUrl: D:/video/a1.mp4
  #输出路径
  outputUrl: D:/video/frame.jpg
  #输出格式
  outputFormat: jpg
  # 截取第 n 帧
  frameNum: 1
----------
controller

    @Resource
    private ImagePathConfig imagePathConfig;

 /**
     * 获取视频的第一帧图片
     * @return
     * EG: DealVideo.fetchFrameToFile(" D : / video / a1.mp4 ", " D : / video / a0.jpg ", " jpg ", 1);
     */
    @GetMapping("/getvideoFirstPic")
    @Validated
    @ApiOperation(value = "getvideoFirstPic", notes = "获取视频的第一帧图片")
    public void getvideoFirstPic () throws Exception {
        DealVideo.fetchFrameToFile(imagePathConfig.getInputUrl(),imagePathConfig.getOutputUrl(),imagePathConfig.getOutputFormat(),imagePathConfig.getFrameNum());
    }
--------------
DealVideo.java (视频处理工具类)
public class DealVideo {

    /*默认图片格式 jpg*/
    public static String DEFAULT_IMG_FORMAT = "jpg";

    /**
     * 获取指定视频的帧并保存为图片JPG格式至指定文件
     *
     * @param videoFile  源视频文件路径
     * @param targetFile 截取帧的图片存放路径
     * @param frameNum   截取第几帧
     * @throws Exception
     */
    public static void fetchFrameToFile(String videoFile, String targetFile, int frameNum) throws FrameGrabber.Exception, IOException {
        //校验输入和输出
        checkInAnOut(videoFile, targetFile);
        try {
            File frameFile = new File(targetFile);
            FFmpegFrameGrabber ff = new FFmpegFrameGrabber(videoFile);
            ff.start();
            int length = ff.getLengthInFrames();
            /*第几帧判断设置*/
            if (frameNum < 0) {
                frameNum = 0;
            }
            if (frameNum > length) {
                frameNum = length - 5;
            }
            //指定第几帧
            ff.setFrameNumber(frameNum);
            int i = 0;
            Frame f = null;
            while (i < length) {
                // 过滤前5帧,避免出现全黑的图片,依自己情况而定
                f = ff.grabFrame();
                if ((i >= 5) && (f.image != null)) {
                    break;
                }
                i++;
            }
            opencv_core.IplImage img = f.image;
            int width = img.width();
            int height = img.height();
            BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
            bi.getGraphics().drawImage(f.image.getBufferedImage().getScaledInstance(width, height, Image.SCALE_SMOOTH),
                    0, 0, null);
            ff.flush();
            ff.stop();
            ImageIO.write(bi, DEFAULT_IMG_FORMAT, frameFile);
        } catch (Exception e) {
            throw new RuntimeException("转换视频图片异常");
        }

    }

    /**
     * 获取指定视频的帧并保存为图片自定义类型至指定文件
     *
     * @param videoFile  源视频文件路径
     * @param targetFile 截取帧的图片存放文件路径
     * @param outImgFormat 输出图片格式
     * @param frameNum   截取第几帧
     * @throws Exception
     */
    public static void fetchFrameToFile(String videoFile, String targetFile, String outImgFormat, int frameNum) throws FrameGrabber.Exception, IOException {
        //校验输入和输出
        checkInAnOut(videoFile, targetFile);
        try {
            File frameFile = new File(targetFile);
            FFmpegFrameGrabber ff = new FFmpegFrameGrabber(videoFile);
            ff.start();
            int length = ff.getLengthInFrames();
            /*第几帧判断设置*/
            if (frameNum < 0) {
                frameNum = 0;
            }
            if (frameNum > length) {
                frameNum = length - 5;
            }
            //指定第几帧
            ff.setFrameNumber(frameNum);
            int i = 0;
            Frame f = null;
            while (i < length) {
                // 过滤前5帧,避免出现全黑的图片,依自己情况而定
                f = ff.grabFrame();
                if ((i >= 5) && (f.image != null)) {
                    break;
                }
                i++;
            }
            opencv_core.IplImage img = f.image;
            int width = img.width();
            int height = img.height();
            BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
            bi.getGraphics().drawImage(f.image.getBufferedImage().getScaledInstance(width, height, Image.SCALE_SMOOTH),
                    0, 0, null);
            ff.flush();
            ff.stop();
            // ImageUtils2 工具类旋转图片
            BufferedImage ret = ImageUtils2.rotateClockwise0(bi);
            ImageIO.write(ret, outImgFormat, frameFile);
        } catch (Exception e) {
            throw new RuntimeException("转换视频图片异常");
        }
    }

    /**
     * 获取指定视频的帧图片,并转换为base64字符串
     *
     * @param videoFile 源视频文件路径
     * @param frameNum  截取第几帧
     * @throws Exception
     */
    public static String fetchFrameToBase64(String videoFile, int frameNum) throws FrameGrabber.Exception, IOException {
        //校验输入
        checkVideoFile(videoFile);
        try (ByteArrayOutputStream output = new ByteArrayOutputStream();) {
            FFmpegFrameGrabber ff = new FFmpegFrameGrabber(videoFile);
            ff.start();
            int length = ff.getLengthInFrames();
            /*第几帧判断设置*/
            if (frameNum < 0) {
                frameNum = 0;
            }
            if (frameNum > length) {
                frameNum = length - 5;
            }
            //指定第几帧
            ff.setFrameNumber(frameNum);
            int i = 0;
            Frame f = null;
            while (i < length) {
                // 过滤前5帧,避免出现全黑的图片,依自己情况而定
                f = ff.grabFrame();
                if ((i >= 5) && (f.image != null)) {
                    break;
                }
                i++;
            }
            opencv_core.IplImage img = f.image;
            int width = img.width();
            int height = img.height();
            BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
            bi.getGraphics().drawImage(f.image.getBufferedImage().getScaledInstance(width, height, Image.SCALE_SMOOTH),
                    0, 0, null);
            ImageIO.write(bi, DEFAULT_IMG_FORMAT, output);
            // 这里需要获取图片的base64数据串,所以将图片写到流里面
            ff.flush();
            ff.stop();
            return new BASE64Encoder().encode(output.toByteArray());
        } catch (Exception e) {
            throw new RuntimeException("转换视频图片异常");
        }
    }


    /**
     * 校验输入输出
     *
     * @param videoFile
     * @param targetFile
     */
    public static void checkInAnOut(String videoFile, String targetFile) {
        checkVideoFile(videoFile);
        checkTargetFileDir(targetFile);
    }

    /**
     * 验证文件目录是否存在,不存在就创建
     *
     * @param targetFile 文件路径
     * @return
     */
    public static void checkTargetFileDir(String targetFile) {
        String dirPath = targetFile.substring(0, targetFile.lastIndexOf(File.separator) + 1);
        File dir = new File(dirPath);
        if (!dir.exists()) {
            dir.mkdirs();
        }
    }

    /**
     * 检验文件是否存在
     *
     * @param videoFile
     */
    public static void checkVideoFile(String videoFile) {
        File file = new File(videoFile);
        if (!file.exists()) {
            throw new RuntimeException("文件不存在");
        }
    }

}

------------
ImagePathConfig.java(配置文件读取工具类)
@Data
@Configuration
@ConfigurationProperties(prefix = "image-config")
public class ImagePathConfig {

    //输入路径
    private  String inputUrl;
    //输出路径
    private  String outputUrl;
    //输出格式
    private  String outputFormat;
    //帧数
    private  Integer frameNum;

}
----------
ImageUtils2.java (图片旋转工具类,辅助类)
//图片旋转工具类
public class ImageUtils2 {

    //保持原图不变
    public static BufferedImage rotateClockwise0(BufferedImage bi) {
        return bi;
    }

    //顺时针旋转90度(通过交换图像的整数像素RGB 值)
    public static BufferedImage rotateClockwise90(BufferedImage bi) {
        int width = bi.getWidth();
        int height = bi.getHeight();
        BufferedImage bufferedImage = new BufferedImage(height, width, bi.getType());
        for (int i = 0; i < width; i++)
            for (int j = 0; j < height; j++)
                bufferedImage.setRGB(height - 1 - j, width - 1 - i, bi.getRGB(i, j));
        return bufferedImage;
    }

    //逆时针旋转90度(通过交换图像的整数像素RGB 值)
    public static BufferedImage rotateCounterclockwise90(BufferedImage bi) {
        int width = bi.getWidth();
        int height = bi.getHeight();
        BufferedImage bufferedImage = new BufferedImage(height, width, bi.getType());
        for (int i = 0; i < width; i++)
            for (int j = 0; j < height; j++)
                bufferedImage.setRGB(j, i, bi.getRGB(i, j));
        return bufferedImage;
    }

    //旋转180度(通过交换图像的整数像素RGB 值)
    public static BufferedImage rotate180(BufferedImage bi) {
        int width = bi.getWidth();
        int height = bi.getHeight();
        BufferedImage bufferedImage = new BufferedImage(width,height,bi.getType());
        for (int i = 0; i < width; i++)
            for (int j = 0; j < height; j++)
                bufferedImage.setRGB( width - i-1,height-j-1, bi.getRGB(i, j));
        return bufferedImage;
    }

    //水平翻转
    public static BufferedImage rotateHorizon(BufferedImage bi) {
        int width = bi.getWidth();
        int height = bi.getHeight();
        BufferedImage bufferedImage = new BufferedImage(width,height,bi.getType());
        for (int i = 0; i < width; i++)
            for (int j = 0; j < height; j++)
                bufferedImage.setRGB( width - i-1,j, bi.getRGB(i, j));
        return bufferedImage;
    }
    //垂直翻转
    public static BufferedImage rotateVertical(BufferedImage bi) {
        int width = bi.getWidth();
        int height = bi.getHeight();
        BufferedImage bufferedImage = new BufferedImage(width,height,bi.getType());
        for (int i = 0; i < width; i++)
            for (int j = 0; j < height; j++)
                bufferedImage.setRGB(i,height-1-j, bi.getRGB(i, j));
        return bufferedImage;
    }
}

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值