liurunyu
2025-01-13 dcadab885677e68b69831b588932afafdb6e92a6
增加视频文件生成缩略图功能
4个文件已修改
1个文件已添加
286 ■■■■■ 已修改文件
pipIrr-platform/pipIrr-web/pipIrr-web-file/src/main/java/com/dy/pipIrrWebFile/files/FileCtrl.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-file/src/main/java/com/dy/pipIrrWebFile/util/VideoUtils.java 172 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-file/src/main/java/com/dy/pipIrrWebFile/util/ZipImg.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pom.xml 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pom.xml 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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) ;
        }
    }
}
pipIrr-platform/pipIrr-web/pipIrr-web-file/src/main/java/com/dy/pipIrrWebFile/util/VideoUtils.java
New file
@@ -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();
        }
    }
}
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") ;
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>
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>