Java通过javacv获取视频、音频、图片等元数据信息(分辨率、大小、帧等信息)

相信我们都会或多或少需要给前端返回视频或者音频的一些信息,那么今天这篇文章通过Java语言使用javacv来获取视频、音频、图片等元数据信息(分辨率、大小、帧等信息)

一、首先导入依赖

可以先导入javacv/javacv-platform依赖,由于依赖比较大,所以我们可以先去除部分不需要的依赖如下:

            org.bytedeco
            javacv
            1.4.4
            
                
                    org.bytedeco
                    javacpp
                
                
                    org.bytedeco.javacpp-presets
                    flycapture
                
                
                    org.bytedeco.javacpp-presets
                    libdc1394
                
                
                    org.bytedeco.javacpp-presets
                    libfreenect
                
                
                    org.bytedeco.javacpp-presets
                    libfreenect2
                
                
                    org.bytedeco.javacpp-presets
                    librealsense
                
                
                    org.bytedeco.javacpp-presets
                    videoinput
                
                
                    org.bytedeco.javacpp-presets
                    opencv
                
                
                    org.bytedeco.javacpp-presets
                    tesseract
                
                
                    org.bytedeco.javacpp-presets
                    leptonica
                
                
                    org.bytedeco.javacpp-presets
                    flandmark
                
                
                    org.bytedeco.javacpp-presets
                    artoolkitplus
                
            
        
        
            org.bytedeco
            javacv-platform
            1.4.4
            
                
                    org.bytedeco
                    javacv
                
                
                    org.bytedeco.javacpp-presets
                    flycapture-platform
                
                
                    org.bytedeco.javacpp-presets
                    libdc1394-platform
                
                
                    org.bytedeco.javacpp-presets
                    libfreenect-platform
                
                
                    org.bytedeco.javacpp-presets
                    libfreenect2-platform
                
                
                    org.bytedeco.javacpp-presets
                    librealsense-platform
                
                
                    org.bytedeco.javacpp-presets
                    videoinput-platform
                
                
                    org.bytedeco.javacpp-presets
                    opencv-platform
                
                
                    org.bytedeco.javacpp-presets
                    tesseract-platform
                
                
                    org.bytedeco.javacpp-presets
                    leptonica-platform
                
                
                    org.bytedeco.javacpp-presets
                    flandmark-platform
                
                
                    org.bytedeco.javacpp-presets
                    artoolkitplus-platform
                
            
        

二、获取视频、音频或图片实体元信息

FFmpegUtil实体
@Slf4j
@Service
public class FFmpegUtil {

    private static final String IMAGE_SUFFIX = "png";

    /**
     * 获取视频时长,单位为秒S
     * @param file 视频源
     * @return
     */
    @SuppressWarnings("resource")
    public static long videoDuration(File file) {
        long duration = 0L;
        FFmpegFrameGrabber ff = new FFmpegFrameGrabber(file);
        try {
            ff.start();
            duration = ff.getLengthInTime() / (1000 * 1000);
            ff.stop();
        } catch (java.lang.Exception e) {
            e.printStackTrace();
        }
        return duration;
    }

    /**
     * 获取视频帧图片
     * @param file 视频源
     * @param number 第几帧
     * @param dir 文件存放根目录
     * @param args 文件存放根目录
     * @return
     */
    @SuppressWarnings("resource")
    public static String videoImage(File file, Integer number, String dir, String args) {
        String picPath = StringUtils.EMPTY;
        FFmpegFrameGrabber ff = new FFmpegFrameGrabber(file);
        try {
            ff.start();
            int i = 0;
            int length = ff.getLengthInFrames();
            Frame frame = null;
            while (i  number) && (frame.image != null)) {
                    //获取生成图片的路径
                    picPath = getImagePath(args);
                    //执行截图并放入指定位置
                    doExecuteFrame(frame, dir + File.separator + picPath);
                    break;
                }
                i++;
            }
            ff.stop();
        } catch (FrameGrabber.Exception e) {
            e.printStackTrace();
        }
        return picPath;
    }

    /**
     * 截取缩略图
     * @param frame
     * @param targerFilePath 图片存放路径
     */
    public static void doExecuteFrame(Frame frame, String targerFilePath) {
        //截取的图片
        if (null == frame || null == frame.image) {
            return;
        }
        Java2DFrameConverter converter = new Java2DFrameConverter();
        BufferedImage srcImage = converter.getBufferedImage(frame);
        int srcImageWidth = srcImage.getWidth();
        int srcImageHeight = srcImage.getHeight();
        //对帧图片进行等比例缩放(缩略图)
        int width = 480;
        int height = (int) (((double) width / srcImageWidth) * srcImageHeight);
        BufferedImage thumbnailImage = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
        thumbnailImage.getGraphics().drawImage(srcImage.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0, 0, null);

        File output = new File(targerFilePath);
        try {
            ImageIO.write(thumbnailImage, IMAGE_SUFFIX, output);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成图片的相对路径
     * @param args 传入生成图片的名称、为空则用UUID命名
     * @return 例如 upload/images.png
     */
    public static String getImagePath(String args) {
        if (StringUtils.isNotEmpty(args)) {
            return args + "." + IMAGE_SUFFIX;
        }
        return getUUID() + "." + IMAGE_SUFFIX;
    }

    /**
     * 生成唯一的uuid
     * @return uuid
     */
    public static String getUUID(){
        return UUID.randomUUID().toString().replace("-","");
    }

    /**
     * 时长格式换算
     * @param duration 时长
     * @return HH:mm:ss
     */
    public static String formatDuration(Long duration) {
        String formatTime = StringUtils.EMPTY;
        double time = Double.valueOf(duration);
        if (time > -1) {
            int hour = (int) Math.floor(time / 3600);
            int minute = (int) (Math.floor(time / 60) % 60);
            int second = (int) (time % 60);

            if (hour < 10) {
                formatTime = "0";
            }
            formatTime += hour + ":";

            if (minute < 10) {
                formatTime += "0";
            }
            formatTime += minute + ":";

            if (second  1)
//            return (returnValue + "MB");
//        BigDecimal kilobyte = new BigDecimal(1024);
//        returnValue = filesize.divide(kilobyte, 2, BigDecimal.ROUND_UP).floatValue();
//        return (returnValue + "KB");
        return filesize.toString();
    }



    public static String getImageFormat(String imagePath) throws IOException {
        // 字节数组
        byte[] data = null;
        String format = null;
        // 输入流
        InputStream is = null;
        // Http连接对象
        HttpURLConnection conn = null;
        ImageInputStream imageInputStream = null;
        try {
            // Url对象
            URL url = new URL(imagePath);
            // 打开连接
            conn = (HttpURLConnection) url.openConnection();
            // 打开读取 写入是setDoOutput
//	        conn.setDoOutput(true);
            conn.setDoInput(true);
            // 设置请求方式
            conn.setRequestMethod("GET");
            // 设置超时时间
            conn.setConnectTimeout(6000);
            // 得到访问的数据流
            is = conn.getInputStream();

            // 验证访问状态是否是200 正常
            if (conn.getResponseCode() == 200) {
                imageInputStream = ImageIO.createImageInputStream(is);
                ImageReader imageReader = ImageIO.getImageReaders(imageInputStream).next();
                format = imageReader.getFormatName();
            } else {
                format = null;
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (is != null) {
                    // 关闭流
                    is.close();
                }
                if(imageInputStream != null){
                    imageInputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            // 关闭连接
            conn.disconnect();
        }
        return format;
    }



    /**
     * 将inputStream转化为file
     * @param is
     * @param file 要输出的文件目录
     */
    public static void inputStream2File(InputStream is, File file) throws IOException {
        OutputStream os = null;
        try {
            os = new FileOutputStream(file);
            int len = 0;
            byte[] buffer = new byte[8192];

            while ((len = is.read(buffer)) != -1) {
                os.write(buffer, 0, len);
            }
        } finally {
            os.close();
            is.close();
        }
    }

    /**
     * 获取时长
     */
    public static long getDuration(String filePath) throws Exception {
        FFmpegFrameGrabber ff = FFmpegFrameGrabber.createDefault(filePath);
        ff.start();
        long duration = ff.getLengthInTime() / (1000 * 1000);
        ff.stop();
        return duration;
    }


    /**
     * 获取视频详情
     * @param file
     * @return
     */
    public static VideoInfoVO getVideoInfo(String file) {
        VideoInfoVO videoInfoVO = new VideoInfoVO();
        FFmpegFrameGrabber grabber = null;
        try {
            grabber = FFmpegFrameGrabber.createDefault(file);
            // 启动 FFmpeg
            grabber.start();

            // 读取视频帧数
            videoInfoVO.setLengthInFrames(grabber.getLengthInVideoFrames());

            // 读取视频帧率
            videoInfoVO.setFrameRate(grabber.getVideoFrameRate());

            // 读取视频秒数
            videoInfoVO.setDuration(grabber.getLengthInTime() / 1000000.00);

            // 读取视频宽度
            videoInfoVO.setWidth(grabber.getImageWidth());

            // 读取视频高度
            videoInfoVO.setHeight(grabber.getImageHeight());


            videoInfoVO.setAudioChannel(grabber.getAudioChannels());

            videoInfoVO.setVideoCode(grabber.getVideoCodecName());

            videoInfoVO.setAudioCode(grabber.getAudioCodecName());
            // String md5 = MD5Util.getMD5ByInputStream(new FileInputStream(file));

            videoInfoVO.setSampleRate(grabber.getSampleRate());
            return videoInfoVO;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            try {
                if (grabber != null) {
                    // 此处代码非常重要,如果没有,可能造成 FFmpeg 无法关闭
                    grabber.stop();
                    grabber.release();
                }
            } catch (FFmpegFrameGrabber.Exception e) {
                log.error("getVideoInfo grabber.release failed 获取文件信息失败:{}", e.getMessage());
            }
        }
    }


}

VideoInfoVO实体
@Getter
@Setter
public class VideoInfoVO {
    /**
     * 总帧数
     **/
    private int lengthInFrames;

    /**
     * 帧率
     **/
    private double frameRate;

    /**
     * 时长
     **/
    private double duration;

    /**
     * 视频编码
     */
    private String videoCode;
    /**
     * 音频编码
     */
    private String audioCode;

    private int width;
    private int height;
    private int audioChannel;
    private String md5;
    /**
     * 音频采样率
     */
    private Integer sampleRate;
    private Double fileSize;

    public String toJson() {
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            return objectMapper.writeValueAsString(this);
        } catch (Exception e) {
            return "";
        }
    }
}
InputStream转FileInputStream
    /**
     * inputStream转FileInputStream
     * @param inputStream
     * @return
     * @throws IOException
     */
    public static FileInputStream convertToFileInputStream(InputStream inputStream) throws IOException {
        File tempFile = File.createTempFile("temp", ".tmp");
        tempFile.deleteOnExit();
        try (FileOutputStream outputStream = new FileOutputStream(tempFile)) {
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
        }
        return new FileInputStream(tempFile);
    }
获取文件大小
/**
     * 获取文件大小
     * @param inputStream
     * @return
     */
    public String getFileSize(InputStream inputStream){
        FileChannel fc = null;
        String size = "0";
        try {
            FileInputStream fis = convertToFileInputStream(inputStream);
            fc = fis.getChannel();
            BigDecimal fileSize = new BigDecimal(fc.size());
            size = String.valueOf(fileSize);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != fc) {
                try {
                    fc.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return size;
    }
截取视频帧封面
/**
     * 截取视频获得指定帧的图片
     *
     * @param video   源视频文件
     * @param picPath 截图存放路径
     */
    public String getVideoPic(InputStream video, String picPath) {
        FFmpegFrameGrabber ff = new FFmpegFrameGrabber(video);
        try {
            ff.start();

            // 截取中间帧图片(具体依实际情况而定)
            int i = 0;
            int length = ff.getLengthInFrames();
//            int middleFrame = length / 2;
            int middleFrame = 5;
            Frame frame = null;
            while (i  middleFrame) && (frame.image != null)) {
                    break;
                }
                i++;
            }

            // 截取的帧图片
            Java2DFrameConverter converter = new Java2DFrameConverter();
            BufferedImage srcImage = converter.getBufferedImage(frame);
            int srcImageWidth = srcImage.getWidth();
            int srcImageHeight = srcImage.getHeight();

            // 对截图进行等比例缩放(缩略图)
            int width = 480;
            int height = (int) (((double) width / srcImageWidth) * srcImageHeight);
            BufferedImage thumbnailImage = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
            thumbnailImage.getGraphics().drawImage(srcImage.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0, 0, null);

            InputStream inputStream = bufferedImageToInputStream(thumbnailImage);
//            File picFile = new File(picPath);
//            ImageIO.write(thumbnailImage, "jpg", picFile);
//            int available = inputStream.available();
            String imgUrl = ossUtils.putThumbInputStream(inputStream, picPath);
            ff.stop();
            return imgUrl;
        } catch (java.lang.Exception e) {
            e.printStackTrace();
            System.out.println(e);
            return null;
        }
    }

本文来自网络,不代表协通编程立场,如若转载,请注明出处:https://www.net2asp.com/2f32ed4faf.html