From 072fff9b055a2b9e281961f28fe7fde572336c8a Mon Sep 17 00:00:00 2001
From: zqy <2522236926@qq.com>
Date: 星期五, 02 一月 2026 17:35:11 +0800
Subject: [PATCH] 修改bug

---
 ruoyi-admin/pom.xml                                                         |    6 
 ruoyi-common/src/main/java/com/ruoyi/common/config/ElasticSearchConfig.java |    1 
 zhang-content/src/main/java/com/ruoyi/service/impl/VideoProcessService.java |  398 +++++++++++++++++++++++++++++++++++++++++++-------------
 zhang-content/pom.xml                                                       |    5 
 4 files changed, 314 insertions(+), 96 deletions(-)

diff --git a/ruoyi-admin/pom.xml b/ruoyi-admin/pom.xml
index 3c2856d..6cadb66 100644
--- a/ruoyi-admin/pom.xml
+++ b/ruoyi-admin/pom.xml
@@ -135,6 +135,12 @@
             <version>2.4.6</version>
             <scope>runtime</scope>
         </dependency>
+
+        <dependency>
+            <groupId>org.bytedeco</groupId>
+            <artifactId>javacv-platform</artifactId>
+            <version>1.5.8</version>
+        </dependency>
     </dependencies>
 
     <build>
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/config/ElasticSearchConfig.java b/ruoyi-common/src/main/java/com/ruoyi/common/config/ElasticSearchConfig.java
index 26f2dfe..828d2d7 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/config/ElasticSearchConfig.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/config/ElasticSearchConfig.java
@@ -37,7 +37,6 @@
                         8087,
 
 
-
                     "http"
 
                 )
diff --git a/zhang-content/pom.xml b/zhang-content/pom.xml
index 938b663..396abeb 100644
--- a/zhang-content/pom.xml
+++ b/zhang-content/pom.xml
@@ -127,6 +127,11 @@
             <scope>runtime</scope>
         </dependency>
 
+        <dependency>
+            <groupId>org.bytedeco</groupId>
+            <artifactId>javacv-platform</artifactId>
+            <version>1.5.8</version>
+        </dependency>
 
     </dependencies>
 
diff --git a/zhang-content/src/main/java/com/ruoyi/service/impl/VideoProcessService.java b/zhang-content/src/main/java/com/ruoyi/service/impl/VideoProcessService.java
index 1b60a01..7dc98db 100644
--- a/zhang-content/src/main/java/com/ruoyi/service/impl/VideoProcessService.java
+++ b/zhang-content/src/main/java/com/ruoyi/service/impl/VideoProcessService.java
@@ -24,6 +24,13 @@
 import java.util.List;
 import java.util.concurrent.TimeUnit;
 
+import org.bytedeco.javacv.FFmpegFrameGrabber;
+import org.bytedeco.javacv.Java2DFrameConverter;
+import org.bytedeco.javacv.Frame;
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+
+
 @Service
 @Slf4j
 public class VideoProcessService {
@@ -248,23 +255,12 @@
 
 
 
-
-
-
-
-
-
-
     /**
-     * 澶勭悊瑙嗛鏂囦欢锛氱敓鎴怋ase64缂栫爜鐨勫皝闈�
+     * 澶勭悊瑙嗛鏂囦欢锛氱敓鎴怋ase64缂栫爜鐨勫皝闈� (浣跨敤JavaCV)
      */
     public Map<String, Object> processVideo(File file, int width, int height,
-                                            float quality, String format,boolean deleteY) {
+                                            float quality, String format, boolean deleteY) {
         Map<String, Object> result = new HashMap<>();
-        File tempVideoFile = file;
-
-
-        System.out.println();
 
         try {
             // 1. 楠岃瘉瑙嗛鏍煎紡
@@ -274,21 +270,12 @@
                 return result;
             }
 
-            // 2. 淇濆瓨鍘熷鏂囦欢鍒颁复鏃剁洰褰�
-//            String originalFilename = file.getName();
-//            tempVideoFile = File.createTempFile("video_", ".temp");
-
-            // 3. 鑾峰彇瑙嗛淇℃伅
-//            MultimediaInfo info = getVideoInfo(tempVideoFile);
-//            double durationSeconds = info.getDuration() / 1000.0;
-//            String videoResolution = info.getVideo().getSize().getWidth() + "x" + info.getVideo().getSize().getHeight();
-
-            // 4. 鐢熸垚Base64鏍煎紡鐨勫皝闈�
-            String base64Thumbnail = generateBase64ThumbnailFromFile(
-                tempVideoFile,
+            // 2. 浣跨敤鏂扮殑JavaCV鏂规硶鐢熸垚Base64灏侀潰
+            String base64Thumbnail = generateBase64ThumbnailWithJavaCV(
+                file,
                 width > 0 ? width : thumbnailWidth,
                 height > 0 ? height : thumbnailHeight,
-                (int) quality,
+                quality, // 娉ㄦ剰锛氳繖閲屼紶鍏loat绫诲瀷鐨剄uality
                 format != null ? format : thumbnailFormat
             );
 
@@ -298,25 +285,15 @@
                 return result;
             }
 
-            // 5. 鑾峰彇缂╃暐鍥惧ぇ灏�
+            // 3. 鑾峰彇缂╃暐鍥惧ぇ灏� (鏂规硶淇濇寔涓嶅彉锛屼緷璧朆ase64)
             String thumbnailSize = extractImageSizeFromBase64(base64Thumbnail);
-            String[] sizeParts = thumbnailSize.split("x");
-            int thumbWidth = sizeParts.length > 0 ? Integer.parseInt(sizeParts[0]) : 0;
-            int thumbHeight = sizeParts.length > 1 ? Integer.parseInt(sizeParts[1]) : 0;
 
-            // 6. 杩斿洖缁撴灉
+            // 4. 杩斿洖缁撴灉
             result.put("success", true);
             result.put("type", "video");
             result.put("format", format != null ? format : thumbnailFormat);
-//            result.put("originalFilename", originalFilename);
-//            result.put("originalWidth", info.getVideo().getSize().getWidth());
-//            result.put("originalHeight", info.getVideo().getSize().getHeight());
-//            result.put("originalResolution", videoResolution);
-//            result.put("duration", durationSeconds);
-//            result.put("videoFormat", info.getFormat());
-//            result.put("compressedWidth", thumbWidth);
-//            result.put("compressedHeight", thumbHeight);
             result.put("base64", base64Thumbnail);
+            result.put("thumbnailSize", thumbnailSize); // 鍙�夛紝杩斿洖灏哄淇℃伅
             result.put("message", "瑙嗛灏侀潰鐢熸垚鎴愬姛");
 
         } catch (Exception e) {
@@ -325,24 +302,29 @@
             result.put("message", "灏侀潰鐢熸垚澶辫触: " + e.getMessage());
         } finally {
             // 娓呯悊涓存椂鏂囦欢
-            if (tempVideoFile != null && tempVideoFile.exists() && deleteY) {
+            if (deleteY && file != null && file.exists()) {
                 try {
-                    tempVideoFile.delete();
+                    file.delete();
                 } catch (Exception e) {
                     log.warn("鍒犻櫎涓存椂瑙嗛鏂囦欢鏃跺嚭閿�", e);
                 }
             }
         }
-
         return result;
     }
+
+
     /**
-     * 鐢熸垚Base64鏍煎紡鐨勫皝闈紙鍙嚜瀹氫箟鍙傛暟锛�
+     * 銆愭牳蹇冦�戜娇鐢↗avaCV鐢熸垚Base64鏍煎紡鐨勫皝闈�
      */
-    private String generateBase64ThumbnailFromFile(File videoFile, int width, int height,
-                                                   int quality, String format) {
-        File tempThumbnailFile = null;
-        Process process = null;
+    /**
+     * 銆愭牳蹇冦�戜娇鐢↗avaCV鐢熸垚Base64鏍煎紡鐨勫皝闈�
+     */
+    private String generateBase64ThumbnailWithJavaCV(File videoFile, int targetWidth,
+                                                     int targetHeight, float quality,
+                                                     String format) {
+        FFmpegFrameGrabber grabber = null;
+        Java2DFrameConverter converter = null;
 
         try {
             if (!videoFile.exists()) {
@@ -350,82 +332,308 @@
                 return null;
             }
 
-            // 1. 鍒涘缓涓存椂鏂囦欢鐢ㄤ簬淇濆瓨缂╃暐鍥�
-            String ext = format != null ? format : thumbnailFormat;
-            tempThumbnailFile = File.createTempFile("thumb_", "." + ext);
-            tempThumbnailFile.deleteOnExit();
+            // 1. 鍒濆鍖栨姄鍙栧櫒
+            grabber = new FFmpegFrameGrabber(videoFile);
+            grabber.start();
 
-            // 2. 鑾峰彇瑙嗛鏃堕暱锛岃绠楁埅鍥炬椂闂寸偣
-            MultimediaInfo info = getVideoInfo(videoFile);
-            double durationSeconds = info.getDuration() / 1000.0;
+            // 鑾峰彇瑙嗛鏃堕暱
+            long durationMicroseconds = grabber.getLengthInTime();
+            double durationSeconds = durationMicroseconds / 1_000_000.0;
             double screenshotTime = calculateScreenshotTime(durationSeconds);
 
-            // 3. 鏋勫缓FFmpeg鍛戒护
-            String ffmpegCmd = String.format(
-                "ffmpeg -y -i \"%s\" -ss %.2f -vframes 1 -q:v %d -s %dx%d -f image2 \"%s\"",
-                videoFile.getAbsolutePath(),
-                screenshotTime,
-                quality,
-                width,
-                height,
-                tempThumbnailFile.getAbsolutePath()
-            );
+            log.info("瑙嗛淇℃伅 - 鏂囦欢鍚�: {}, 鏃堕暱: {}s, 鎴浘鏃堕棿: {}s, 鍘熷灏哄: {}x{}",
+                videoFile.getName(), durationSeconds, screenshotTime,
+                grabber.getImageWidth(), grabber.getImageHeight());
 
-            // 4. 鎵цFFmpeg鍛戒护
-            ProcessBuilder processBuilder = new ProcessBuilder();
-            String[] command = isWindows() ?
-                new String[]{"cmd.exe", "/c", ffmpegCmd} :
-                new String[]{"bash", "-c", ffmpegCmd};
+            // 2. 璺宠浆鍒版寚瀹氭椂闂寸偣
+            grabber.setTimestamp((long) (screenshotTime * 1_000_000));
 
-            processBuilder.command(command);
-            processBuilder.redirectErrorStream(true);
-            process = processBuilder.start();
+            // 3. 鎶撳彇甯�
+            Frame frame = null;
+            BufferedImage bufferedImage = null;
+            converter = new Java2DFrameConverter();
 
-            // 5. 绛夊緟鍛戒护瀹屾垚
-            boolean finished = process.waitFor(30, TimeUnit.SECONDS);
-            if (!finished) {
-                process.destroyForcibly();
+            // 灏濊瘯鎶撳彇澶氬抚
+            for (int i = 0; i < 10; i++) {
+                frame = grabber.grabImage();
+                if (frame != null && frame.image != null) {
+                    bufferedImage = converter.convert(frame);
+                    if (bufferedImage != null) {
+                        log.info("鎴愬姛鎶撳彇绗瑊}甯э紝鍥剧墖灏哄: {}x{}",
+                            i, bufferedImage.getWidth(), bufferedImage.getHeight());
+                        break;
+                    }
+                }
+            }
+
+            if (bufferedImage == null) {
+                log.error("鏃犳硶浠庤棰戜腑鎶撳彇鏈夋晥鍥惧儚甯�");
                 return null;
             }
 
-            int exitCode = process.waitFor();
-            if (exitCode != 0 || !tempThumbnailFile.exists() || tempThumbnailFile.length() == 0) {
+            // 4. 璋冩暣鍥剧墖灏哄
+            int originalWidth = bufferedImage.getWidth();
+            int originalHeight = bufferedImage.getHeight();
+
+            if (targetWidth > 0 || targetHeight > 0) {
+                bufferedImage = resizeImage(bufferedImage, targetWidth, targetHeight, true);
+                log.info("璋冩暣灏哄: {}x{} -> {}x{}",
+                    originalWidth, originalHeight,
+                    bufferedImage.getWidth(), bufferedImage.getHeight());
+            }
+
+            // 5. 鍘嬬缉骞惰浆鎹负Base64
+            byte[] compressedBytes;
+            String actualFormat = (format != null && !format.isEmpty()) ? format : "jpg";
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+            try {
+                if ("jpg".equalsIgnoreCase(actualFormat) || "jpeg".equalsIgnoreCase(actualFormat)) {
+                    compressAsJpeg(bufferedImage, baos, quality);
+                } else if ("png".equalsIgnoreCase(actualFormat)) {
+                    compressAsPng(bufferedImage, baos, (int)(quality * 9));
+                } else {
+                    if (!ImageIO.write(bufferedImage, actualFormat, baos)) {
+                        // 濡傛灉涓嶆敮鎸佽鏍煎紡锛屽洖閫�鍒癹pg
+                        log.warn("涓嶆敮鎸佹牸寮�: {}锛屽洖閫�鍒癹pg", actualFormat);
+                        actualFormat = "jpg";
+                        baos.reset();
+                        compressAsJpeg(bufferedImage, baos, quality);
+                    }
+                }
+
+                compressedBytes = baos.toByteArray();
+
+                if (compressedBytes == null || compressedBytes.length == 0) {
+                    log.error("鍘嬬缉鍚庣殑鍥剧墖鏁版嵁涓虹┖");
+                    return null;
+                }
+
+                log.info("鍥剧墖鍘嬬缉鎴愬姛锛屽ぇ灏�: {} bytes", compressedBytes.length);
+
+            } catch (Exception e) {
+                log.error("鍥剧墖鍘嬬缉澶辫触: {}", e.getMessage());
+                // 灏濊瘯浣跨敤榛樿鏂瑰紡
+                baos.reset();
+                if (ImageIO.write(bufferedImage, actualFormat, baos)) {
+                    compressedBytes = baos.toByteArray();
+                } else {
+                    return null;
+                }
+            }
+
+            // 6. 鏋勫缓Data URL
+            String base64 = Base64.getEncoder().encodeToString(compressedBytes);
+            if (base64 == null || base64.isEmpty()) {
+                log.error("Base64缂栫爜澶辫触");
                 return null;
             }
 
-            // 6. 璇诲彇鍥剧墖鏂囦欢骞惰浆鎹负Base64
-            byte[] fileContent = Files.readAllBytes(tempThumbnailFile.toPath());
+            String mimeType = getMimeType(actualFormat);
+            String dataUrl = "data:" + mimeType + ";base64," + base64;
 
-            if (!isValidImage(fileContent)) {
-                return null;
-            }
+            log.info("鐢熸垚Base64 Data URL鎴愬姛锛岄暱搴�: {}, 鏍煎紡: {}",
+                dataUrl.length(), actualFormat);
 
-            // 7. 杞崲涓築ase64
-            String base64 = Base64.getEncoder().encodeToString(fileContent);
-            String mimeType = getMimeType(ext);
-
-            return "data:" + mimeType + ";base64," + base64;
+            return dataUrl;
 
         } catch (Exception e) {
-            log.error("鐢熸垚Base64灏侀潰澶辫触", e);
+            log.error("浣跨敤JavaCV鐢熸垚灏侀潰澶辫触: {}", e.getMessage(), e);
             return null;
         } finally {
-            // 娓呯悊璧勬簮
-            if (process != null && process.isAlive()) {
-                process.destroy();
+            // 7. 閲婃斁璧勬簮
+            if (converter != null) {
+                try {
+                    converter.close();
+                } catch (Exception e) {
+                    log.warn("鍏抽棴Java2DFrameConverter鏃跺嚭閿�", e);
+                }
             }
 
-            if (tempThumbnailFile != null && tempThumbnailFile.exists()) {
+            if (grabber != null) {
                 try {
-                    tempThumbnailFile.delete();
+                    grabber.stop();
+                    grabber.release();
                 } catch (Exception e) {
-                    // ignore
+                    log.warn("閲婃斁FFmpegFrameGrabber璧勬簮鏃跺嚭閿�", e);
                 }
             }
         }
     }
 
 
+
+//    /**
+//     * 澶勭悊瑙嗛鏂囦欢锛氱敓鎴怋ase64缂栫爜鐨勫皝闈�
+//     */
+//    public Map<String, Object> processVideo(File file, int width, int height,
+//                                            float quality, String format,boolean deleteY) {
+//        Map<String, Object> result = new HashMap<>();
+//        File tempVideoFile = file;
+//
+//
+//        System.out.println();
+//
+//        try {
+//            // 1. 楠岃瘉瑙嗛鏍煎紡
+//            if (!isVideoFile(file)) {
+//                result.put("success", false);
+//                result.put("message", "涓嶆敮鎸佺殑瑙嗛鏍煎紡");
+//                return result;
+//            }
+//
+//            // 2. 淇濆瓨鍘熷鏂囦欢鍒颁复鏃剁洰褰�
+////            String originalFilename = file.getName();
+////            tempVideoFile = File.createTempFile("video_", ".temp");
+//
+//            // 3. 鑾峰彇瑙嗛淇℃伅
+////            MultimediaInfo info = getVideoInfo(tempVideoFile);
+////            double durationSeconds = info.getDuration() / 1000.0;
+////            String videoResolution = info.getVideo().getSize().getWidth() + "x" + info.getVideo().getSize().getHeight();
+//
+//            // 4. 鐢熸垚Base64鏍煎紡鐨勫皝闈�
+//            String base64Thumbnail = generateBase64ThumbnailFromFile(
+//                tempVideoFile,
+//                width > 0 ? width : thumbnailWidth,
+//                height > 0 ? height : thumbnailHeight,
+//                (int) quality,
+//                format != null ? format : thumbnailFormat
+//            );
+//
+//            if (base64Thumbnail == null || base64Thumbnail.isEmpty()) {
+//                result.put("success", false);
+//                result.put("message", "灏侀潰鐢熸垚澶辫触");
+//                return result;
+//            }
+//
+//            // 5. 鑾峰彇缂╃暐鍥惧ぇ灏�
+//            String thumbnailSize = extractImageSizeFromBase64(base64Thumbnail);
+//            String[] sizeParts = thumbnailSize.split("x");
+//            int thumbWidth = sizeParts.length > 0 ? Integer.parseInt(sizeParts[0]) : 0;
+//            int thumbHeight = sizeParts.length > 1 ? Integer.parseInt(sizeParts[1]) : 0;
+//
+//            // 6. 杩斿洖缁撴灉
+//            result.put("success", true);
+//            result.put("type", "video");
+//            result.put("format", format != null ? format : thumbnailFormat);
+////            result.put("originalFilename", originalFilename);
+////            result.put("originalWidth", info.getVideo().getSize().getWidth());
+////            result.put("originalHeight", info.getVideo().getSize().getHeight());
+////            result.put("originalResolution", videoResolution);
+////            result.put("duration", durationSeconds);
+////            result.put("videoFormat", info.getFormat());
+////            result.put("compressedWidth", thumbWidth);
+////            result.put("compressedHeight", thumbHeight);
+//            result.put("base64", base64Thumbnail);
+//            result.put("message", "瑙嗛灏侀潰鐢熸垚鎴愬姛");
+//
+//        } catch (Exception e) {
+//            log.error("瑙嗛灏侀潰鐢熸垚澶辫触", e);
+//            result.put("success", false);
+//            result.put("message", "灏侀潰鐢熸垚澶辫触: " + e.getMessage());
+//        } finally {
+//            // 娓呯悊涓存椂鏂囦欢
+//            if (tempVideoFile != null && tempVideoFile.exists() && deleteY) {
+//                try {
+//                    tempVideoFile.delete();
+//                } catch (Exception e) {
+//                    log.warn("鍒犻櫎涓存椂瑙嗛鏂囦欢鏃跺嚭閿�", e);
+//                }
+//            }
+//        }
+//
+//        return result;
+//    }
+//    /**
+//     * 鐢熸垚Base64鏍煎紡鐨勫皝闈紙鍙嚜瀹氫箟鍙傛暟锛�
+//     */
+//    private String generateBase64ThumbnailFromFile(File videoFile, int width, int height,
+//                                                   int quality, String format) {
+//        File tempThumbnailFile = null;
+//        Process process = null;
+//
+//        try {
+//            if (!videoFile.exists()) {
+//                log.error("瑙嗛鏂囦欢涓嶅瓨鍦�: {}", videoFile.getAbsolutePath());
+//                return null;
+//            }
+//
+//            // 1. 鍒涘缓涓存椂鏂囦欢鐢ㄤ簬淇濆瓨缂╃暐鍥�
+//            String ext = format != null ? format : thumbnailFormat;
+//            tempThumbnailFile = File.createTempFile("thumb_", "." + ext);
+//            tempThumbnailFile.deleteOnExit();
+//
+//            // 2. 鑾峰彇瑙嗛鏃堕暱锛岃绠楁埅鍥炬椂闂寸偣
+//            MultimediaInfo info = getVideoInfo(videoFile);
+//            double durationSeconds = info.getDuration() / 1000.0;
+//            double screenshotTime = calculateScreenshotTime(durationSeconds);
+//
+//            // 3. 鏋勫缓FFmpeg鍛戒护
+//            String ffmpegCmd = String.format(
+//                "ffmpeg -y -i \"%s\" -ss %.2f -vframes 1 -q:v %d -s %dx%d -f image2 \"%s\"",
+//                videoFile.getAbsolutePath(),
+//                screenshotTime,
+//                quality,
+//                width,
+//                height,
+//                tempThumbnailFile.getAbsolutePath()
+//            );
+//
+//            // 4. 鎵цFFmpeg鍛戒护
+//            ProcessBuilder processBuilder = new ProcessBuilder();
+//            String[] command = isWindows() ?
+//                new String[]{"cmd.exe", "/c", ffmpegCmd} :
+//                new String[]{"bash", "-c", ffmpegCmd};
+//
+//            processBuilder.command(command);
+//            processBuilder.redirectErrorStream(true);
+//            process = processBuilder.start();
+//
+//            // 5. 绛夊緟鍛戒护瀹屾垚
+//            boolean finished = process.waitFor(30, TimeUnit.SECONDS);
+//            if (!finished) {
+//                process.destroyForcibly();
+//                return null;
+//            }
+//
+//            int exitCode = process.waitFor();
+//            if (exitCode != 0 || !tempThumbnailFile.exists() || tempThumbnailFile.length() == 0) {
+//                return null;
+//            }
+//
+//            // 6. 璇诲彇鍥剧墖鏂囦欢骞惰浆鎹负Base64
+//            byte[] fileContent = Files.readAllBytes(tempThumbnailFile.toPath());
+//
+//            if (!isValidImage(fileContent)) {
+//                return null;
+//            }
+//
+//            // 7. 杞崲涓築ase64
+//            String base64 = Base64.getEncoder().encodeToString(fileContent);
+//            String mimeType = getMimeType(ext);
+//
+//            return "data:" + mimeType + ";base64," + base64;
+//
+//        } catch (Exception e) {
+//            log.error("鐢熸垚Base64灏侀潰澶辫触", e);
+//            return null;
+//        } finally {
+//            // 娓呯悊璧勬簮
+//            if (process != null && process.isAlive()) {
+//                process.destroy();
+//            }
+//
+//            if (tempThumbnailFile != null && tempThumbnailFile.exists()) {
+//                try {
+//                    tempThumbnailFile.delete();
+//                } catch (Exception e) {
+//                    // ignore
+//                }
+//            }
+//        }
+//    }
+
+
     /**
      * 鐢熸垚Base64鏍煎紡鐨勫皝闈紙涓嶅瓨鍌ㄦ枃浠讹級
      */

--
Gitblit v1.9.1