I believe that we all need to return some video or audio information to the front end more or less, so today’s article uses javacv to obtain video, audio, picture and other metadata information (resolution, size, frame, etc.) through Java language
1. First import dependencies
You can first import the javacv/javacv-platform dependency. Since the dependency is relatively large, we can first remove some unnecessary dependencies as follows:
<dependency> <groupId>org.bytedeco</groupId> <artifactId>javacv</artifactId> <version>1.4.4</version> <exclusions> <exclusion> <groupId>org.bytedeco</groupId> <artifactId>javacpp</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>flycapture</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>libdc1394</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>libfreenect</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>libfreenect2</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>librealsense</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>videoinput</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>opencv</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>tesseract</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>leptonica</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>flandmark</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>artoolkitplus</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.bytedeco</groupId> <artifactId>javacv-platform</artifactId> <version>1.4.4</version> <exclusions> <exclusion> <groupId>org.bytedeco</groupId> <artifactId>javacv</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>flycapture-platform</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>libdc1394-platform</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>libfreenect-platform</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>libfreenect2-platform</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>librealsense-platform</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>videoinput-platform</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>opencv-platform</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>tesseract-platform</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>leptonica-platform</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>flandmark-platform</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>artoolkitplus-platform</artifactId> </exclusion> </exclusions> </dependency>
2. Obtain video, audio or image entity meta information
FFmpegUtil entity
@Slf4j @Service public class FFmpegUtil { private static final String IMAGE_SUFFIX = "png"; /** * Get the video duration in seconds * @param file video source * @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; } /** * Get video frame pictures * @param file video source * @param number which frame * @param dir file storage root directory * @param args file storage root directory * @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 < length) { frame = ff.grabFrame(); //Intercept which frame of picture if ((i > number) & amp; & amp; (frame.image != null)) { //Get the path to generate the image picPath = getImagePath(args); //Execute the screenshot and put it into the specified location doExecuteFrame(frame, dir + File.separator + picPath); break; } i + + ; } ff.stop(); } catch (FrameGrabber.Exception e) { e.printStackTrace(); } return picPath; } /** * Capture thumbnails * @param frame * @param targerFilePath image storage path */ public static void doExecuteFrame(Frame frame, String targetFilePath) { //Intercepted pictures if (null == frame || null == frame.image) { return; } Java2DFrameConverter converter = new Java2DFrameConverter(); BufferedImage srcImage = converter.getBufferedImage(frame); int srcImageWidth = srcImage.getWidth(); int srcImageHeight = srcImage.getHeight(); // Scale the frame image proportionally (thumbnail) 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(); } } /** * Generate the relative path of the image * @param args Pass in the name of the generated image. If it is empty, use UUID to name it. * @return for example upload/images.png */ public static String getImagePath(String args) { if (StringUtils.isNotEmpty(args)) { return args + "." + IMAGE_SUFFIX; } return getUUID() + "." + IMAGE_SUFFIX; } /** * Generate unique uuid * @return uuid */ public static String getUUID(){ return UUID.randomUUID().toString().replace("-",""); } /** * Duration format conversion * @param duration 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 < 10) { formatTime + = "0"; } formatTime + = second; } return formatTime; } /** * Get image size Kb * @param urlPath * @return */ public static String getImageSize(String urlPath){ // get data byte[] imageFromURL = getImageFromURL(urlPath); // Convert String byte2kb = bytes2kb(imageFromURL.length); return byte2kb; } /** * Get image information based on image address * * @param urlPath network image address * @return */ public static byte[] getImageFromURL(String urlPath) { // byte array byte[] data = null; // input stream InputStream is = null; // Http connection object HttpURLConnection conn = null; try { // Url object URL url = new URL(urlPath); //Open connection conn = (HttpURLConnection) url.openConnection(); // Open for reading and writing is setDoOutput // conn.setDoOutput(true); conn.setDoInput(true); //Set request method conn.setRequestMethod("GET"); //Set the timeout conn.setConnectTimeout(6000); //Get the accessed data stream is = conn.getInputStream(); // Verify whether the access status is 200 normal if (conn.getResponseCode() == 200) { data = readInputStream(is); } else { data = null; } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (is != null) { // close the stream is.close(); } } catch (IOException e) { e.printStackTrace(); } // close connection conn.disconnect(); } return data; } /** * Convert stream to bytes * * @param is * @return */ public static byte[] readInputStream(InputStream is) { /** * Capture the data in the memory buffer and convert it into a byte array * ByteArrayOutputStream class creates a buffer of byte type array internally in the program when creating its instance, and then uses instances of ByteArrayOutputStream and ByteArrayInputStream to write or read byte type data into the array. * In network transmission, we often need to transmit many variables. We can use ByteArrayOutputStream to collect all variables together and then send the data out at once. */ ByteArrayOutputStream baos = new ByteArrayOutputStream(); //Create byte array 1024 = 1M byte[] buffer = new byte[1024]; // Prevent infinite loop int length = -1; try { // Loop to write data to byte array while ((length = is.read(buffer)) != -1) { baos.write(buffer, 0, length); } // Forced refresh and clean-up work are mainly to allow the data flow to be completely transmitted in the transmission project of the pipeline to prevent data loss. baos.flush(); } catch (IOException e) { e.printStackTrace(); } // Convert byte stream to byte array byte[] data = baos.toByteArray(); try { // Close the reading stream is.close(); // Close the write stream baos.close(); } catch (IOException e) { e.printStackTrace(); } return data; } /** * Get the number of bytes of the local image * * @param imgPath * @return */ public static String pathSize(String imgPath) { File file = new File(imgPath); FileInputStream fis; int fileLen = 0; try { fis = new FileInputStream(file); fileLen = fis.available(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return bytes2kb(fileLen); } /** * Convert the number of bytes obtained to KB, MB mode * * @param bytes * @return */ public static String bytes2kb(long bytes) { BigDecimal filesize = new BigDecimal(bytes); // BigDecimal megabyte = new BigDecimal(1024 * 1024); // float returnValue = filesize.divide(megabyte, 2, BigDecimal.ROUND_UP).floatValue(); // if (returnValue > 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 array byte[] data = null; String format = null; // input stream InputStream is = null; // Http connection object HttpURLConnection conn = null; ImageInputStream imageInputStream = null; try { // Url object URL url = new URL(imagePath); //Open connection conn = (HttpURLConnection) url.openConnection(); // Open for reading and writing is setDoOutput // conn.setDoOutput(true); conn.setDoInput(true); //Set request method conn.setRequestMethod("GET"); //Set the timeout conn.setConnectTimeout(6000); //Get the accessed data stream is = conn.getInputStream(); // Verify whether the access status is 200 normal 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) { // close the stream is.close(); } if(imageInputStream != null){ imageInputStream.close(); } } catch (IOException e) { e.printStackTrace(); } // close connection conn.disconnect(); } return format; } /** * Convert inputStream to file * @param is * @param file The file directory to be output */ 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(); } } /** * Get duration */ 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; } /** * Get video details * @param file * @return */ public static VideoInfoVO getVideoInfo(String file) { VideoInfoVO videoInfoVO = new VideoInfoVO(); FFmpegFrameGrabber grabber = null; try { grabber = FFmpegFrameGrabber.createDefault(file); // Start FFmpeg grabber.start(); //Read video frame number videoInfoVO.setLengthInFrames(grabber.getLengthInVideoFrames()); //Read video frame rate videoInfoVO.setFrameRate(grabber.getVideoFrameRate()); //Read video seconds videoInfoVO.setDuration(grabber.getLengthInTime() / 1000000.00); //Read video width videoInfoVO.setWidth(grabber.getImageWidth()); //Read video height 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) { // The code here is very important. If it is not there, FFmpeg may not be able to be closed. grabber.stop(); grabber.release(); } } catch (FFmpegFrameGrabber.Exception e) { log.error("getVideoInfo grabber.release failed Failed to obtain file information: {}", e.getMessage()); } } } }
VideoInfoVO entity
@Getter @Setter public class VideoInfoVO { /** *Total number of frames **/ private int lengthInFrames; /** * Frame rate **/ private double frameRate; /** * duration **/ private double duration; /** * Video encoding */ private String videoCode; /** * Audio encoding */ private String audioCode; private int width; private int height; private int audioChannel; private String md5; /** * Audio sample rate */ private Integer sampleRate; private Double fileSize; public String toJson() { try { ObjectMapper objectMapper = new ObjectMapper(); return objectMapper.writeValueAsString(this); } catch (Exception e) { return ""; } } }
InputStream to FileInputStream
/** * inputStream to FileInputStream * @param inputStream * @return * @throwsIOException */ 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); }
Get file size
/** * Get file size * @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; }
Capture video frame cover
/** * Intercept the video to obtain the picture of the specified frame * * @param video source video file * @param picPath screenshot storage path */ public String getVideoPic(InputStream video, String picPath) { FFmpegFrameGrabber ff = new FFmpegFrameGrabber(video); try { ff.start(); // Capture the middle frame picture (specifically depends on the actual situation) int i = 0; int length = ff.getLengthInFrames(); // int middleFrame = length / 2; int middleFrame = 5; Frame frame = null; while (i < length) { frame = ff.grabFrame(); if ((i > middleFrame) & amp; & amp; (frame.image != null)) { break; } i + + ; } //Intercepted frame picture Java2DFrameConverter converter = new Java2DFrameConverter(); BufferedImage srcImage = converter.getBufferedImage(frame); int srcImageWidth = srcImage.getWidth(); int srcImageHeight = srcImage.getHeight(); // Scale the screenshot proportionally (thumbnail) 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; } }