From dcadab885677e68b69831b588932afafdb6e92a6 Mon Sep 17 00:00:00 2001
From: liurunyu <lry9898@163.com>
Date: 星期一, 13 一月 2025 14:52:17 +0800
Subject: [PATCH] 增加视频文件生成缩略图功能

---
 pipIrr-platform/pom.xml                                                                            |   22 ++++
 pipIrr-platform/pipIrr-web/pipIrr-web-file/src/main/java/com/dy/pipIrrWebFile/util/ZipImg.java     |   18 +++
 pipIrr-platform/pipIrr-web/pipIrr-web-file/src/main/java/com/dy/pipIrrWebFile/util/VideoUtils.java |  172 ++++++++++++++++++++++++++++++++++
 pipIrr-platform/pipIrr-web/pipIrr-web-file/src/main/java/com/dy/pipIrrWebFile/files/FileCtrl.java  |   57 ++++++++++
 pipIrr-platform/pipIrr-web/pom.xml                                                                 |   17 +++
 5 files changed, 283 insertions(+), 3 deletions(-)

diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-file/src/main/java/com/dy/pipIrrWebFile/files/FileCtrl.java b/pipIrr-platform/pipIrr-web/pipIrr-web-file/src/main/java/com/dy/pipIrrWebFile/files/FileCtrl.java
index f8e6734..62f19d8 100644
--- a/pipIrr-platform/pipIrr-web/pipIrr-web-file/src/main/java/com/dy/pipIrrWebFile/files/FileCtrl.java
+++ b/pipIrr-platform/pipIrr-web/pipIrr-web-file/src/main/java/com/dy/pipIrrWebFile/files/FileCtrl.java
@@ -9,8 +9,9 @@
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.multipart.MultipartFile;
 
-import java.io.File;
-import java.io.InputStream;
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.*;
 
 /**
  * web鏂囦欢涓婁紶, 鍐呴儴璋冪敤锛屽嵆鐢卞叾浠栧瓙妯″潡璋冪敤锛�
@@ -24,6 +25,9 @@
 
     @Value("${dy.photoZipWidth}")
     private String photoZipWidthStr ;
+
+    private static final String VideoZipPicFileType = "jpg";
+    private static final Integer VideoZipPicFromFrame = 5 ;
 
     /**
      * web鍒嗗竷寮忔枃浠剁郴缁熶繚瀛樼収鐗囨枃浠�
@@ -65,7 +69,7 @@
                         String zipFilePath1 = filePath.substring(0, index) ;
                         String zipFilePath2 = filePath.substring(index) ;
                         String zipFilePath = zipFilePath1 + "_" + zipFilePath2 ;
-                        InputStream zipFileInput = null ;
+                        InputStream zipFileInput ;
                         if(zipFilePath2.equalsIgnoreCase(".png")){
                             zipFileInput = ZipImg.zipToPng(fPic, photoZipWidth, photoZipWidth) ;
                         }else{
@@ -152,6 +156,26 @@
                     String filePath = absolutePath + fileRelativePath ;
                     if(!fUtil.saveFile(filePath, input)){
                         fileRelativePath = null ;
+                    }else {
+                        //瀛樺偍鎴愬姛, 鐢熸垚缂╃暐鍥�
+                        BufferedImage bufImg = new VideoUtils(VideoZipPicFileType, VideoZipPicFromFrame).fetchFrame(file) ;
+                        int index = filePath.lastIndexOf(".") ;
+                        String basePath = filePath.substring(0, index) ;
+                        Integer photoZipWidth = 400 ;
+                        if(photoZipWidthStr != null && NumUtil.isPlusIntNumber(photoZipWidthStr)){
+                            photoZipWidth = Integer.parseInt(photoZipWidthStr) ;
+                        }
+                        String zipFilePath = basePath + "_." + VideoZipPicFileType ;
+                        InputStream zipFileInput = ZipImg.zipToJpg(bufImg, photoZipWidth, photoZipWidth) ;
+                        if(zipFileInput.available() > 0){
+                            new FileUtil().saveFile(zipFilePath, zipFileInput) ;
+                        }else{
+                            //濡傛灉鍘嬬缉鏂囦欢涓嶅瓨鍦ㄦ垨鐢熸垚澶辫触锛屽垯澶嶅埗婧愭枃浠�
+                            ByteArrayOutputStream os = new ByteArrayOutputStream();
+                            ImageIO.write(bufImg, VideoZipPicFileType, os);
+                            InputStream in = new ByteArrayInputStream(os.toByteArray());
+                            new FileUtil().saveFile(zipFilePath, in) ;
+                        }
                     }
                 }
             }
@@ -199,4 +223,31 @@
         return fileRelativePath ;
     }
 
+
+    public static void main(String[] args) throws Exception{
+        String photoZipWidthStr = "400" ;
+        String VideoZipPicFileType = "jpg";
+        //瀛樺偍鎴愬姛, 鐢熸垚缂╃暐鍥�
+        String filePath = "D:\\mp4\\test.mp4" ;
+        BufferedImage bufImg = new VideoUtils("jpg", 0).fetchFrame(filePath) ;
+        int index = filePath.lastIndexOf(".") ;
+        String basePath = filePath.substring(0, index) ;
+        Integer photoZipWidth = 400 ;
+        if(photoZipWidthStr != null && NumUtil.isPlusIntNumber(photoZipWidthStr)){
+            photoZipWidth = Integer.parseInt(photoZipWidthStr) ;
+        }
+        String zipFilePath = basePath + "_." + VideoZipPicFileType ;
+        InputStream zipFileInput = null ;
+        zipFileInput = ZipImg.zipToJpg(bufImg, photoZipWidth, photoZipWidth) ;
+        if(zipFileInput.available() > 0){
+            new FileUtil().saveFile(zipFilePath, zipFileInput) ;
+        }else{
+            //濡傛灉鍘嬬缉鏂囦欢涓嶅瓨鍦ㄦ垨鐢熸垚澶辫触锛屽垯澶嶅埗婧愭枃浠�
+            ByteArrayOutputStream os = new ByteArrayOutputStream();
+            ImageIO.write(bufImg, VideoZipPicFileType, os);
+            InputStream in = new ByteArrayInputStream(os.toByteArray());
+            new FileUtil().saveFile(zipFilePath, in) ;
+        }
+    }
+
 }
diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-file/src/main/java/com/dy/pipIrrWebFile/util/VideoUtils.java b/pipIrr-platform/pipIrr-web/pipIrr-web-file/src/main/java/com/dy/pipIrrWebFile/util/VideoUtils.java
new file mode 100644
index 0000000..1258861
--- /dev/null
+++ b/pipIrr-platform/pipIrr-web/pipIrr-web-file/src/main/java/com/dy/pipIrrWebFile/util/VideoUtils.java
@@ -0,0 +1,172 @@
+package com.dy.pipIrrWebFile.util;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.io.FileUtils;
+import org.jcodec.api.FrameGrab;
+import org.jcodec.common.model.Picture;
+import org.jcodec.scale.AWTUtil;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.*;
+
+/**
+ * @Author: liurunyu
+ * @Date: 2025/1/13 11:22
+ * @Description
+ */
+
+/**
+ * 瑙嗛鎿嶄綔宸ュ叿绫�
+ */
+@Slf4j
+public class VideoUtils {
+
+    /*** 鍥剧墖鏍煎紡*/
+    private static final String FILE_EXT = "jpg";
+
+    /*** 甯ф暟*/
+    private static final int THUMB_FRAME = 5;
+
+    /*** 鍥剧墖鏍煎紡*/
+    private String fileExt ;
+
+    /*** 甯ф暟*/
+    private Integer thumbFrame ;
+
+    public VideoUtils(){
+        this.fileExt = FILE_EXT;
+        this.thumbFrame = THUMB_FRAME;
+    }
+
+
+    public VideoUtils(String fileExt, int thumbFrame){
+        this.fileExt = fileExt;
+        this.thumbFrame = thumbFrame;
+        if(this.fileExt == null || this.fileExt.trim().equals("")){
+            this.fileExt = FILE_EXT;
+        }
+        if(this.thumbFrame == null || this.thumbFrame.intValue() <= 0){
+            this.thumbFrame = THUMB_FRAME;
+        }
+    }
+
+    /**
+     * 鑾峰彇鎸囧畾瑙嗛鐨勫抚骞朵繚瀛樹负鍥剧墖鑷虫寚瀹氱洰褰�
+     * @param videoFilePath 婧愯棰戞枃浠惰矾寰�
+     * @param frameFilePath 鎴彇甯х殑鍥剧墖瀛樻斁璺緞
+     */
+    public void fetchFrame(String videoFilePath, String frameFilePath) throws Exception {
+        File videoFile = new File(videoFilePath);
+        File frameFile = new File(frameFilePath);
+        getThumbnail(videoFile, frameFile);
+    }
+
+
+    /**
+     * 鑾峰彇鎸囧畾瑙嗛鐨勫抚骞朵繚瀛樹负鍥剧墖鑷虫寚瀹氱洰褰�
+     * @param videoFilePath 婧愯棰戞枃浠惰矾寰�
+     */
+    public BufferedImage fetchFrame(String videoFilePath) throws Exception {
+        File videoFile = new File(videoFilePath);
+        return getThumbnail(videoFile);
+    }
+
+    /**
+     * 鑾峰彇鎸囧畾瑙嗛鐨勫抚骞朵繚瀛樹负鍥剧墖鑷虫寚瀹氱洰褰�
+     *
+     * @param videoFile  婧愯棰戞枃浠�
+     * @param targetFile 鎴彇甯х殑鍥剧墖
+     */
+    public void fetchFrame(MultipartFile videoFile, File targetFile) throws Exception {
+        File file = new File(videoFile.getName());
+        FileUtils.copyInputStreamToFile(videoFile.getInputStream(), file);
+        getThumbnail(file, targetFile);
+    }
+
+    /**
+     * 鑾峰彇鎸囧畾瑙嗛鐨勫抚骞朵繚瀛樹负鍥剧墖鑷虫寚瀹氱洰褰�
+     *
+     * @param videoFile  婧愯棰戞枃浠�
+     */
+    public BufferedImage fetchFrame(MultipartFile videoFile) throws Exception {
+        File file = new File(videoFile.getName());
+        FileUtils.copyInputStreamToFile(videoFile.getInputStream(), file);
+        return getThumbnail(file);
+    }
+
+    /**
+     * 鑾峰彇鎸囧畾瑙嗛鐨勫抚骞朵繚瀛樹负鍥剧墖鑷虫寚瀹氱洰褰�
+     *
+     * @param videoFile 婧愯棰戞枃浠�
+
+    public File fetchFrame2(MultipartFile videoFile) {
+        String originalFilename = videoFile.getOriginalFilename();
+        File file = new File(originalFilename);
+        File targetFile = null;
+        try {
+            FileUtils.copyInputStreamToFile(videoFile.getInputStream(), file);
+
+            int i = originalFilename.lastIndexOf(".");
+            String imageName;
+
+            if (i > 0) {
+                imageName = originalFilename.substring(0, i);
+            } else {
+                imageName = UUID.randomUUID().toString().replace("-", "");
+            }
+            imageName = imageName + ".jpg";
+            targetFile = new File(imageName);
+            getThumbnail(file, targetFile);
+        } catch (Exception e) {
+            log.error("鑾峰彇瑙嗛鎸囧畾甯у紓甯革細", e);
+        } finally {
+            if (file.exists()) {
+                file.delete();
+            }
+        }
+        log.debug("瑙嗛鏂囦欢 - 甯ф埅鍙� - 澶勭悊缁撴潫");
+        return targetFile;
+    }
+    */
+
+    /**
+     * 鑾峰彇绗竴甯х缉鐣ュ浘
+     *
+     * @param videoFile  瑙嗛璺緞
+     * @param targetFile 缂╃暐鍥剧洰鏍囪矾寰�
+     */
+    public void getThumbnail(File videoFile, File targetFile) throws Exception {
+        // 鏍规嵁鎵╁睍鍚嶅垱寤轰竴涓柊鏂囦欢璺緞
+        Picture picture = FrameGrab.getFrameFromFile(videoFile, thumbFrame);
+        BufferedImage bufferedImage = AWTUtil.toBufferedImage(picture);
+        ImageIO.write(bufferedImage, fileExt, targetFile);
+    }
+
+
+    /**
+     * 鑾峰彇绗竴甯х缉鐣ュ浘
+     *
+     * @param videoFile  瑙嗛璺緞
+     */
+    public BufferedImage getThumbnail(File videoFile) throws Exception {
+        // 鏍规嵁鎵╁睍鍚嶅垱寤轰竴涓柊鏂囦欢璺緞
+        Picture picture = FrameGrab.getFrameFromFile(videoFile, thumbFrame);
+        BufferedImage bufferedImage = AWTUtil.toBufferedImage(picture);
+        return bufferedImage;
+    }
+
+
+    public static void main(String[] args) {
+        VideoUtils util = new VideoUtils();
+        try {
+            long startTime = System.currentTimeMillis();
+            util.getThumbnail(new File("D:\\mp4\\test.mp4"), new File("D:\\mp4\\test.jpg"));
+            System.out.println("鎴彇鍥剧墖鑰楁椂锛�" + (System.currentTimeMillis() - startTime));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+}
diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-file/src/main/java/com/dy/pipIrrWebFile/util/ZipImg.java b/pipIrr-platform/pipIrr-web/pipIrr-web-file/src/main/java/com/dy/pipIrrWebFile/util/ZipImg.java
index 180ca61..fecc46f 100644
--- a/pipIrr-platform/pipIrr-web/pipIrr-web-file/src/main/java/com/dy/pipIrrWebFile/util/ZipImg.java
+++ b/pipIrr-platform/pipIrr-web/pipIrr-web-file/src/main/java/com/dy/pipIrrWebFile/util/ZipImg.java
@@ -18,8 +18,16 @@
         return zip(file, "jpg", xSize, ySize) ;
     }
 
+    public static InputStream zipToJpg(BufferedImage buf, int xSize, int ySize) throws Exception{
+        return zip(buf, "jpg", xSize, ySize) ;
+    }
+
     public static InputStream zipToPng(File file, int xSize, int ySize) throws Exception{
         return zip(file, "png", xSize, ySize) ;
+    }
+
+    public static InputStream zipToPng(BufferedImage buf, int xSize, int ySize) throws Exception{
+        return zip(buf, "png", xSize, ySize) ;
     }
 
     public static void zipToFile(File file, File toFile, int xSize, int ySize) throws Exception{
@@ -36,6 +44,16 @@
         os = null ;
         return in ;
     }
+
+    private static InputStream zip(BufferedImage buf, String type, int xSize, int ySize) throws Exception{
+        BufferedImage bi = Thumbnails.of(buf).size(xSize, ySize).outputQuality(1f).asBufferedImage();
+        ByteArrayOutputStream os = new ByteArrayOutputStream();
+        ImageIO.write(bi, type, os);
+        InputStream in = new ByteArrayInputStream(os.toByteArray());
+        bi = null ;
+        os = null ;
+        return in ;
+    }
     
     public static void main(String[] args){
     	File f = new File("D:/test.jpg") ;
diff --git a/pipIrr-platform/pipIrr-web/pom.xml b/pipIrr-platform/pipIrr-web/pom.xml
index 9f2da8a..4998d97 100644
--- a/pipIrr-platform/pipIrr-web/pom.xml
+++ b/pipIrr-platform/pipIrr-web/pom.xml
@@ -226,6 +226,23 @@
             </exclusions>
         </dependency>
 
+        <!-- java瑙嗛澶勭悊 -->
+        <dependency>
+            <groupId>org.jcodec</groupId>
+            <artifactId>jcodec</artifactId>
+            <version>0.2.5</version>
+        </dependency>
+        <dependency>
+            <groupId>org.jcodec</groupId>
+            <artifactId>jcodec-javase</artifactId>
+            <version>0.2.5</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <version>2.18.0</version>
+        </dependency>
+
         <!-- 娴嬭瘯 -->
         <dependency>
             <groupId>org.springframework.boot</groupId>
diff --git a/pipIrr-platform/pom.xml b/pipIrr-platform/pom.xml
index a7955fc..97dc779 100644
--- a/pipIrr-platform/pom.xml
+++ b/pipIrr-platform/pom.xml
@@ -303,6 +303,28 @@
                 <scope>import</scope>
             </dependency>
 
+            <!-- java瑙嗛澶勭悊 -->
+            <dependency>
+                <groupId>org.jcodec</groupId>
+                <artifactId>jcodec</artifactId>
+                <version>0.2.5</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.jcodec</groupId>
+                <artifactId>jcodec-javase</artifactId>
+                <version>0.2.5</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+            <dependency>
+                <groupId>commons-io</groupId>
+                <artifactId>commons-io</artifactId>
+                <version>2.18.0</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
             <!-- 娴嬭瘯 -->
             <dependency>
                 <groupId>org.springframework.boot</groupId>

--
Gitblit v1.8.0