获取视频某一帧工具类

需要引入依赖

        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacv-platform</artifactId>
            <version>1.5.2</version>
        </dependency>
<!--        <dependency>
            <groupId>org.bytedeco.javacpp-presets</groupId>
            <artifactId>ffmpeg-platform</artifactId>
            <version>4.0.2-1.4.3</version>
        </dependency>-->

工具类 

@Slf4j
public class VideoUtils {

    // 获取要取得的帧数
    private static final int GET_FRAMES_LENGTH = 5;
    //截取视频图片格式
    private static final String CONTENT_TYPE = "image/jpg";

    /**
     * zhangsk
     * 获取视频第五帧图片,并转换成multipartFile流
     * @param filePath  视频路径
     * @return
     */
    public static MultipartFile getScreenshot(String filePath) {

        FFmpegFrameGrabber grabber;
        MultipartFile multipartFile = null;
        try {
            log.info("开始处理视频获取第一帧");
            log.info("视频文件地址"+filePath);
            grabber = FFmpegFrameGrabber.createDefault(filePath);
            // 第一帧图片存储位置(也是视频路径)
            String targerFilePath = filePath.substring(0, filePath.lastIndexOf("/"));
            log.info("第一帧图片存储位置"+targerFilePath);
            // 视频文件名
            String fileName = filePath.substring(filePath.lastIndexOf("/") + 1);
            log.info("视频文件名"+fileName);
            // 图片名称
            String targetFileName = fileName.substring(0, fileName.lastIndexOf("."));
            log.info("图片名称"+targetFileName);
            grabber.start();
            // 视频总帧数
            int videoLength = grabber.getLengthInFrames();

            Frame frame = null;
            int i = 0;
            while (i < videoLength) {
                // 过滤前5帧,避免出现全黑的图片,依自己情况而定(每循环一次取一帧)
                frame = grabber.grabFrame();
                if ((i > GET_FRAMES_LENGTH) && (frame.image != null)) {
                    break;
                }
                i++;
            }
            Java2DFrameConverter converter = new Java2DFrameConverter();
            // 绘制图片
            BufferedImage bi = converter.getBufferedImage(frame);
            // 图片的类型
            String imageMat = "jpg";
            // 图片的完整路径
            String imagePath = targerFilePath + File.separator + targetFileName + "." + imageMat;
            // 创建文件
            File output = new File(imagePath);
            ImageIO.write(bi, imageMat, output);
            multipartFile = new MockMultipartFile("file", output.getName(), imageMat, new FileInputStream(output));

            grabber.stop();
            log.info("获取视频第一帧结束");
            return multipartFile;

        } catch (IOException e) {

            e.printStackTrace();
        }
        return multipartFile;
    }

    /**
     * zhangsk
     * 根据路径采用url链接方式获取视频输入流来处理    推荐使用  推荐使用
     * @param path  视频链接地址
     * @return
     */
    public static MultipartFile grabberVideoFramer(String path ,Integer frameLength) {
        if (null == frameLength) {
            frameLength = GET_FRAMES_LENGTH;
        }
        log.info("截取视频第几帧+"+frameLength);
        // 视频文件名
        String fileName = path.substring(path.lastIndexOf("/") + 1);
        log.info("视频文件名"+fileName);
        // 图片名称
        String targetFileName = fileName.substring(0, fileName.lastIndexOf("."));
        log.info("图片名称"+targetFileName);
        // Frame对象
        Frame frame = null;
        MultipartFile multipartFile = null;
        // 标识
        int flag = 0;
        try {
            log.info("开始处理视频获取截图");
            /*
            获取视频文件
            */
            URL url =new URL(path);
            //利用HttpURLConnection对象,我们可以从网络中获取网页数据.
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setDoInput(true);
            conn.connect();
            log.info("建立connect链接");
            InputStream inputStream= conn.getInputStream();
            FFmpegFrameGrabber fFmpegFrameGrabber = new FFmpegFrameGrabber(inputStream);
            fFmpegFrameGrabber.start();
            log.info("fFmpegFrameGrabber启动");
            // 获取视频总帧数
            int ftp = fFmpegFrameGrabber.getLengthInFrames();
            log.info("时长 " + ftp / fFmpegFrameGrabber.getFrameRate() / 60);

            while (flag <= ftp) {
                frame = fFmpegFrameGrabber.grabImage();
                /*
                对视频的第五帧进行处理
                 */
                if (frame != null && flag == frameLength) {
                    log.info("获取第" + flag + "帧");
                    BufferedImage  bufferedImage= FrameToBufferedImage(frame);
                    ByteArrayOutputStream out = new ByteArrayOutputStream();
                    ImageIO.write(bufferedImage, "jpg", out);
                    byte[] b = out.toByteArray();
                    fFmpegFrameGrabber.stop();
                    multipartFile = new MockMultipartFile("file",targetFileName,CONTENT_TYPE, b);
                    fFmpegFrameGrabber.close();
                    log.info("获取视频第一帧结束");
                    return multipartFile;
                }
                flag++;
            }

        } catch (Exception E) {
            log.info("视频处理工具里失败:{}",E);
            E.printStackTrace();
        }
        return multipartFile;
    }

    /**
     * 创建缓冲流
     * @param frame
     * @return
     */
    public static BufferedImage FrameToBufferedImage(Frame frame) {
        // 创建BufferedImage对象
        Java2DFrameConverter converter = new Java2DFrameConverter();
        BufferedImage bufferedImage = converter.getBufferedImage(frame);
        return bufferedImage;
    }

    /**
     *
     * 一体化处理视频获取视频第一帧图片方式
     * @param fileUrl
     * @return
     * @throws IOException
     */
    public static  MultipartFile fetchFrame(String fileUrl) throws IOException {
        MultipartFile multipartFile = null;
        String picPath = fileUrl.substring(0, fileUrl.indexOf("."));
        String videoPic = picPath.concat(".jpg");
        FFmpegFrameGrabber ff = new FFmpegFrameGrabber(fileUrl);
        ff.start();
        int length = ff.getLengthInFrames();
        int i = 0;
        Frame f = null;
        while (i < length) {
            f = ff.grabFrame();
            if ((i > 5) && (f.image != null)) {
                break;
            }
            i++;
        }
        int owidth = f.imageWidth;
        int oheight = f.imageHeight;
        // 对截取的帧进行等比例缩放
        int width = 800;
        int height = (int) (((double) width / owidth) * oheight);
        Java2DFrameConverter converter = new Java2DFrameConverter();
        BufferedImage fecthedImage = converter.getBufferedImage(f);
        BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        bi.getGraphics().drawImage(fecthedImage.getScaledInstance(width, height, Image.SCALE_SMOOTH),
                0, 0, null);
        ImageIO.write(bi, "jpg", out);
        byte[] bytes = out.toByteArray();
        multipartFile = new MockMultipartFile("file", bytes);
        ff.flush();
        ff.stop();

        return multipartFile;
    }

    /**
     * zhangsk
     * 直接采用视频输入流进行处理
     * @param inputStream 视频输入流
     * @param fileUrl 视频路径
     * @return  返回multipartfile流
     * @throws IOException io异常
     */
    public static MultipartFile grabberVideoFramer02(InputStream inputStream ,String fileUrl) throws IOException {
        log.info("开始处理视频获取截图");
        // 视频文件名
        String fileName = fileUrl.substring(fileUrl.lastIndexOf("/") + 1);
        log.info("视频文件名"+fileName);
        // 图片名称
        String targetFileName = fileName.substring(0, fileName.lastIndexOf("."));
        log.info("图片名称"+targetFileName);
        MultipartFile multipartFile = null;
        // 最后获取到的视频的图片缓存
        BufferedImage bufferedImage = null;
        // Frame对象
        Frame frame = null;
        // 标识
        int flag = 0;
        FFmpegFrameGrabber fFmpegFrameGrabber = null;
        try {
            //获取视频文件
            fFmpegFrameGrabber = new FFmpegFrameGrabber(inputStream);
            fFmpegFrameGrabber.start();
            log.info("fFmpegFrameGrabber启动");
            // 获取视频总帧数
            int ftp = fFmpegFrameGrabber.getLengthInFrames();
            log.info("视频总帧数"+ftp);
            //对视屏 帧数处理
            while (flag <= ftp) {
                frame = fFmpegFrameGrabber.grabImage();
                //对视频的第5帧进行处理
                if (frame != null && flag == ftp/GET_FRAMES_LENGTH) {
                    // 图片缓存对象
                    bufferedImage = FrameToBufferedImage(frame);
                    ByteArrayOutputStream out = new ByteArrayOutputStream();
                    ImageIO.write(bufferedImage, "jpg", out);
                    byte[] b = out.toByteArray();
                    multipartFile = new MockMultipartFile("file",targetFileName,CONTENT_TYPE, b);
                    log.info("获取到图片multipartFile流"+multipartFile);
                    return multipartFile;
                }
                flag++;
            }
        }finally {
            if(fFmpegFrameGrabber != null) {
                fFmpegFrameGrabber.stop();
                fFmpegFrameGrabber.close();
                log.info("视频处理结束");
            }
        }
        log.info("无法获取,出现异常");
        return multipartFile;
    }

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值