Java视频抽取图片ffmpeg

package com.highsoft.video.processing.utils;

import org.apache.commons.lang3.RandomStringUtils;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.File;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class VideoProcessingUtil {

    /**
     * 判断是不是视频
     */
    public static boolean isVideo(String path) {
        //设置视频后缀
        List<String> typeList = new ArrayList<String>();
        typeList.add("mp4");
        typeList.add("flv");
        typeList.add("avi");
        typeList.add("rmvb");
        typeList.add("rm");
        typeList.add("wmv");
        //获取文件名和后缀
        String suffix = path.substring(path.lastIndexOf(".") + 1);
        for (String type : typeList) {
            //统一为大写作比较
            if (type.toUpperCase().equals(suffix.toUpperCase())) {
                return true;
            }
        }
        return false;
    }

    private static RenderedImage FrameToBufferedImage(Frame frame) {
        //创建BufferedImage对象
        Java2DFrameConverter converter = new Java2DFrameConverter();
        return converter.getBufferedImage(frame);
    }

    public static boolean getTempPath(String filePath) throws Exception {
        String path = "E:/images/";
        int count = 3;
        int sum = 0;
        System.out.println("确认文件是否是视频...");
        //判断文件是否为视频
        if (VideoProcessingUtil.isVideo(filePath)) {
            System.out.println("确认成功!");
            //判断文件是否存在
            FFmpegFrameGrabber ff = FFmpegFrameGrabber.createDefault(filePath);
            ff.start();
            int width = ff.getImageWidth();
            int height = ff.getImageHeight();
            System.out.println("宽:" + width + ";高:" + height);
            // 视频帧数
            int ftp = ff.getLengthInFrames();
            System.out.println("一共有:" + ftp + "帧");
            // 视频帧率
            double videoFrameRate = ff.getVideoFrameRate();
            System.out.println("帧率:" + videoFrameRate);
            System.out.println("秒数:" + ff.getLengthInTime() / 1000000.00);


//            ff.start();

            int step = ftp / (count + 1);
            System.out.println("每隔:" + step + "帧取一帧");
            int flag = 0;
            Frame frame;
            List<String> images = new ArrayList<>();
            boolean isFirst = true;
            // 生成文件名称
            // 获取当前日期
            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd");
            LocalDateTime now = LocalDateTime.now();
            Java2DFrameConverter java2dFrameConverter = new Java2DFrameConverter();
            Random random = new Random();
            long delayedTime = ff.getLengthInTime() / 1000000;
            long sep = delayedTime / (count+1);
            System.out.println(delayedTime + "." + sep);
            for(int i = 0; i < count; i++){
                long time = (sep * (i + 1)) * 1000000L;
                System.out.println(time);
                ff.setTimestamp(time);
                Frame f = ff.grabImage();
                BufferedImage bi = java2dFrameConverter.getBufferedImage(f);
                String fileName = now.format(dtf) + "/" + System.currentTimeMillis() + RandomStringUtils.randomAlphanumeric(8) + ".jpg";
                File out = Paths.get(path, fileName).toFile();
                ImageIO.write(bi, "jpg", out);
                images.add(fileName);
            }

            /*for (int i = 1; i <= ftp; i++) {
                frame = ff.grabImage();
                if ((i > 3 && frame != null && isFirst) || (i % step == 0 && frame != null)) {
                    sum++;
                    System.out.println(i);
                    String fileName = now.format(dtf) + "/" + System.currentTimeMillis() + RandomStringUtils.randomAlphanumeric(8) + ".jpg";
                    File file = new File(path + fileName);
                    if(!file.getParentFile().exists()){
                        file.getParentFile().mkdirs();
                    }
                    BufferedImage image = java2dFrameConverter.convert(frame);
                    // 存储抽取到的图片
                    boolean isSuccess = ImageIO.write(image, "jpg", file);
                    if(isSuccess){
                        images.add(fileName);
                    }
                    // 取首帧 过滤前3帧,避免出现全黑图片
                    isFirst = false;
                    if(sum == (count + 1)){
                        break;
                    }
                }
            }*/
            System.out.println(images);
            ff.stop();
            ff.release();
            return true;
        } else {
            System.out.println("确认失败!");
            return false;
        }
    }


    public static void main(String[] args) throws Exception {
//        boolean tempPath = VideoProcessingUtil.getTempPath("E:/images/542.jpg", "http://pinxls.zlzbgj.com/uploads/videos/202208/23/6fdd53665bf6f7aa847daca49b684436.mp4");
//        System.out.println("获取首帧是否成功!"+tempPath);
//        VideoProcessingUtil.getTempPath("http://pinxls.zlzbgj.com/uploads/videos/202208/23/5763bccd10bfb2be2a827d940cbb5b4d.mp4");

        long time = 12000000 / 1000; // 获取ms时长
        long step = time / (3 + 2); // 获取按照count拆分后的每段时长 为了去掉前一段和后一段 取中间段来截取图片
        System.out.println(step);
        Random random = new Random();
        for(int i = 0; i<3;i++){
            int randomInt = random.nextInt(Math.toIntExact(step));// 随机取一个点
            System.out.println(randomInt);
            long jumpTime = (step * (i+1) + randomInt) * 1000L;
            System.out.println(jumpTime);
        }
    }
}



public class ProcessingServiceImpl implements IProcessingService {

    // 视频格式
    private static final String[] VIDEO_TYPES = {"mp4", "flv", "avi", "rmvb", "rm", "wmv"};
    // 文件存储路径
    @Value("${video.images.path:/www/wwwroot/supply_chain/images/}")
    private String path;
    // 图片展示路径前缀
    @Value("${video.images.url_prefix:http://images.kdfff.com/images/}")
    private String url_prefix;
    // 截取截图数量
    @Value("${video.images.count:3}")
    private Integer count;

    @Override
    public ResultDTO processing(String videoUrl) {
//        String videoUrl = params.get("video");
        if (StringUtils.isBlank(videoUrl)) {
            // 传入的视频路径为空
            log.info("传入的视频路径为空");
            return ResultDTO.fail("未传入视频路径!");
        }
        if (!isVideo(videoUrl)) {
            // 文件不为视频文件
            log.info("文件不为视频文件");
            return ResultDTO.fail("文件不为视频文件!");
        }
        String suffix = videoUrl.substring(videoUrl.lastIndexOf(".") + 1);
        log.info("开始获取视频,并抓取视频信息,url:【{}】, 后缀:【{}】", videoUrl, suffix);
        FFmpegFrameGrabber grabber = null;
        VideoInfoRespDTO respDTO = new VideoInfoRespDTO(); // 返回视频信息
        try {
            grabber = FFmpegFrameGrabber.createDefault(videoUrl); // 获取视频
            grabber.start(); // 启动视频
            respDTO.setUrlPrefix(url_prefix); // 设置图片展示前缀
            respDTO.setHeight(grabber.getImageHeight()); // 获取高度
            respDTO.setWidth(grabber.getImageWidth());  // 获取宽度
            respDTO.setBitrate(grabber.getVideoBitrate()); // 获取视频码率
            respDTO.setFps(grabber.getVideoFrameRate()); // 获取视频流帧率
            respDTO.setDuration(grabber.getLengthInTime() / 1000000); // 获取视频流长度: 单位s
            respDTO.setFormat(suffix); // 获取视频流格式
            // 生成文件名称 具体为 /日期/时间戳+随机字符串.jpg
            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd");
            String now = LocalDateTime.now().format(dtf);
            Java2DFrameConverter java2dFrameConverter = new Java2DFrameConverter();
            // 获取首帧图片
            int ftp = grabber.getLengthInFrames();
            int flag = 0;
            Frame firstFrame;
            while (flag <= 10) {
                firstFrame = grabber.grabImage();
                //过滤前3帧,避免出现全黑图片
                if ((flag > 5) && (firstFrame != null)) {
                    BufferedImage bi = java2dFrameConverter.getBufferedImage(firstFrame);
                    String fileName = now + "/" + System.currentTimeMillis() + RandomStringUtils.randomAlphanumeric(8) + ".jpg";
                    File out = new File(path + fileName);
                    if(!out.getParentFile().exists()){
                        out.getParentFile().mkdirs();
                    }
                    if (ImageIO.write(bi, "jpg", out)) {
                        // 图片保存成功!
                        respDTO.setCover_url(url_prefix + fileName);
                        break;
                    }
                }
                flag++;
            }
            // 随机获取 count 帧图片
            long time = grabber.getLengthInTime() / 1000; // 获取ms时长
            long step = time / (count + 2); // 获取按照count拆分后的每段时长 为了去掉前一段和后一段 取中间段来截取图片
            Random random = new Random();
            List<String> images = new ArrayList<>();
            for (int i = 0; i < count; i++) {
                int randomInt = random.nextInt(Math.toIntExact(step));// 随机取一个点
                long jumpTime = (step * (i + 1) + randomInt) * 1000L;
                grabber.setTimestamp(jumpTime);
                Frame f = grabber.grabImage();
                BufferedImage bi = java2dFrameConverter.getBufferedImage(f);
                String fileName = now + "/" + System.currentTimeMillis() + RandomStringUtils.randomAlphanumeric(8) + ".jpg";
                File out = Paths.get(path, fileName).toFile();
                if(!out.getParentFile().exists()){
                    out.getParentFile().mkdirs();
                }
                ImageIO.write(bi, "jpg", out);
                images.add(url_prefix + fileName);
            }
            respDTO.setSnapshots(images);
            log.info("处理结果:【{}】", JSONObject.toJSONString(respDTO));
            return ResultDTO.success(respDTO);
        } catch (Exception e) {
            log.error("处理发生异常!msg:{}", e);
        } finally {
            if (grabber != null) {
                try {
                    grabber.release();
                    grabber.stop();
                    grabber.close();
                } catch (FrameGrabber.Exception e) {
                    log.error("关闭grabber发生异常!msg:{}", e);
                }
            }
        }
        return ResultDTO.error();
    }

    /**
     * 判断是不是视频
     */
    private static boolean isVideo(String path) {
        //获取文件名和后缀
        String suffix = path.substring(path.lastIndexOf(".") + 1);
        for (String type : VIDEO_TYPES) {
            //统一为大写作比较
            if (type.equalsIgnoreCase(suffix)) {
                return true;
            }
        }
        return false;
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值