废话不多说,直接上代码,复制粘贴即可使用

maven依赖

		<!-- 阿里云OSS对象存储 -->
        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-sdk-oss</artifactId>
            <version>3.10.2</version>
        </dependency>

        <!--获取视频时长、分辨率、帧率、码率-->
        <dependency>
            <groupId>ws.schild</groupId>
            <artifactId>jave-all-deps</artifactId>
            <version>2.6.0</version>
        </dependency>

application-dev.yaml

aliyun:
  oss:
    # 阿里云OSS服务接入点
    endpoint: oss**************.com
    # 阿里云账号Access Key Id
    accessKeyId: L****************PU4j
    # 阿里云账号Access Key Secret
    accessKeySecret: 0*******************qr
    # OSS存储空间
    bucketName: d*******t

OssService.java

private Logger log = LoggerFactory.getLogger(OssService.class);

    @Value("${aliyun.oss.endpoint}")
    private String endpoint;

    @Value("${aliyun.oss.accessKeyId}")
    private String accessKeyId;

    @Value("${aliyun.oss.accessKeySecret}")
    private String accessKeySecret;

    @Value("${aliyun.oss.bucketName}")
    private String bucketName;

    public Map<String, String> uploadVideo(MultipartFile file) throws Exception {
        log.info("上传视频开始" + System.currentTimeMillis());
        try {
            // 获取文件名和扩展名
            String OriginalFilename = file.getOriginalFilename();
            String fileExt = OriginalFilename.substring(OriginalFilename.lastIndexOf(".") + 1).toLowerCase();
            // 原始文件保存到临时目录
            String tempPath = RuoYiConfig.getUploadPath();
            String upload = FileUploadUtils.upload(tempPath, file);
            String originalFilePath = tempPath + upload.replaceAll("/profile/upload", "");
            Map<String,String> videoMap = this.getVideoInfo(originalFilePath);

            //是否压缩视频
            // TODO 分辨率-宽大于等于1920,分辨率-高大于等于1080,则压缩视频;
            int isCompressed = this.isCompressed(videoMap);
            if(isCompressed == 0){
                Map<String, String> videoToOSSMap = this.uploadVideoToOSS(file, originalFilePath, videoMap);
                //删除本地文件
                File file1 = new File(originalFilePath);
                if (file1.exists()) {
                    file1.delete();
                }
                return videoToOSSMap;
            }
            else {
                //视频压缩
                log.info("开始压缩视频:"+System.currentTimeMillis());
                Map<String, String> compressMap = this.toCompressFile(originalFilePath,fileExt,isCompressed);
                log.info("压缩视频结束:"+System.currentTimeMillis());
                String compressedCode = compressMap.get("compressedCode");
                String compressedFilePath = compressMap.get("compressedFilePath");
                File compressedFile = new File(compressedFilePath);
                Map<String, String> videoToOSSMap = new HashMap<>();
                if ("0".equals(compressedCode) && compressedFile.exists()) {
                   videoToOSSMap = this.uploadVideoToOSS(file, compressedFilePath, videoMap);
                }
                //删除上传的视频以及压缩后的视频
                File file1 = new File(originalFilePath);
                file1.delete();
                compressedFile.delete();
                log.info("上传视频结束:"+System.currentTimeMillis());
                return videoToOSSMap;
            }
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    /*
     * 压缩视频
     * @param originalFilePath  待转换的文件
     * @param fileExt  文件扩展名
     * @param type  压缩类型
     */
    private Map<String, String> toCompressFile(String originalFilePath,String fileExt,int type) throws Exception {
        File originalFile = new File(originalFilePath);
        // 设置压缩后的视频文件路径
        String compressedFilePath = originalFilePath.substring(0, originalFilePath.lastIndexOf(".")) + "_压缩后" + "." + fileExt;
        File compressedFile = new File(compressedFilePath);
        while (true) {
            boolean exists = originalFile.exists();
            log.info("等待文件生成:" + exists);
            if (originalFile.exists()) {
                break;
            }
        }
        // 调用ffmpeg命令行进行压缩
        ProcessBuilder processBuilder = null;
        if(type == 1){
            processBuilder = new ProcessBuilder(
                    "ffmpeg",
                    "-i", originalFile.getAbsolutePath(),
//                "-vcodec", "libx264",
//                "-crf", "18",         // 提高CRF值,降低画质来减少CPU使用
                "-preset", "ultrafast",                     // 更快的编码速度,减少CPU负载
//                "-maxrate", "2000k",                        // 降低最大比特率
//                "-bufsize", "4000k",                        // 减小缓冲区大小
//                "-acodec", "aac",                           // 音频编码
//                "-b:a", "128k",                             // 降低音频比特率
//                "-r", "15",                                 // 降低帧率
//                "-b:v", "600k",                             // 降低视频比特率
                    "-s", "1280x720",                            // 降低分辨率
//                "-movflags", "+faststart",                  // 提前索引以支持快速播放
                    "-threads", "2",                            // 使用双线程,视系统资源增加
                    compressedFile.getAbsolutePath()            // 输出文件路径
            );
        }
        else if(type == 2){
            processBuilder = new ProcessBuilder(
                    "ffmpeg",
                    "-i", originalFile.getAbsolutePath(),
//                "-vcodec", "libx264",
//                "-crf", "18",         // 提高CRF值,降低画质来减少CPU使用
                "-preset", "ultrafast",                     // 更快的编码速度,减少CPU负载
//                "-maxrate", "2000k",                        // 降低最大比特率
//                "-bufsize", "4000k",                        // 减小缓冲区大小
//                "-acodec", "aac",                           // 音频编码
//                "-b:a", "128k",                             // 降低音频比特率
                    "-r", "20",                                 // 降低帧率
//                "-b:v", "600k",                             // 降低视频比特率
//                "-s", "1280x720",                            // 降低分辨率
//                "-movflags", "+faststart",                  // 提前索引以支持快速播放
                    "-threads", "2",                            // 使用双线程,视系统资源增加
                    compressedFile.getAbsolutePath()            // 输出文件路径
            );
        }else {
            processBuilder = new ProcessBuilder();
        }
        processBuilder.inheritIO();
        Process process = processBuilder.start();
        int i = process.waitFor();
        log.info("压缩视频完成,状态码:" + i);
        Map<String, String> map = new HashMap<>();
        map.put("compressedCode", i + "");
        map.put("compressedFilePath", compressedFile.getAbsolutePath());
        return map;
    }

    /**
     * 获取视频信息
     */
    private  Map<String, String> getVideoInfo(String videoUrl) {
        Map<String, String> map = new HashMap<>();
        // 视频时长
        long time = 0;
        // 码率
        int bitRate = 0;
        // 帧率
        float frameRate = 0;
        // 分辨率-高
        int height = 0;
        // 分辨率-宽
        int width = 0;
        // 视频解码器名称
        String decoder = "";
        try {
            MultimediaObject media = new MultimediaObject(new File(videoUrl));
            MultimediaInfo info = media.getInfo();
            // 时长,毫秒级
            long duration = info.getDuration();
            // 毫秒级时长转化为秒
            BigDecimal bigDecimal1 = new BigDecimal(duration);
            BigDecimal bigDecimal2 = new BigDecimal(1000);
            // 四舍五入,只保留整数
            time = bigDecimal1.divide(bigDecimal2, 0, RoundingMode.HALF_UP).longValue();
            // 获取媒体视频对象
            VideoInfo video = info.getVideo();
            // 码率
            bitRate = video.getBitRate();
            // 帧率
            frameRate = video.getFrameRate();
            // 分辨率-高
            height = video.getSize().getHeight();
            // 分辨率-宽
            width = video.getSize().getWidth();
            // 视频解码器名称
            decoder = video.getDecoder();
        } catch (Exception e) {
            e.getMessage();
        }
        map.put("time", time + "");
        map.put("bitRate", bitRate + "");
        map.put("frameRate", frameRate + "");
        map.put("height", height + "");
        map.put("width", width + "");
        map.put("decoder", decoder);
        return map;
    }

    /**
     * 判断是否压缩视频
     * 0:不压缩
     * 1:分辨率压缩
     * 2:帧率压缩
     *
     */
    private int isCompressed(Map<String, String> videoMap){
        //视频码率
        int bitRate = Convert.toInt(videoMap.get("bitRate"));
        //视频帧率
        float frameRate = Convert.toFloat(videoMap.get("frameRate"));
        //分辨率-高
        int height = Convert.toInt(videoMap.get("height"));
        // 分辨率-宽
        int width = Convert.toInt(videoMap.get("width"));
        //判断视频分辨率是否超过限制
        if (height > 720 && width > 1280){
            return 1;
        }
        // 判断视频帧率是否超过限制
        if (frameRate > 30){
            return 2;
        }
        return 0;
    }

    /**
     * 上传视频到阿里云
     */
    private Map<String, String> uploadVideoToOSS(MultipartFile file, String filePath, Map<String,String> videoMap) throws Exception {
        Map<String, String> map = new HashMap<>();
        String endPoint = this.endpoint;
        String accessKeyId = this.accessKeyId;
        String accessKeySecret = this.accessKeySecret;
        String bucketName = this.bucketName;

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endPoint, accessKeyId, accessKeySecret);
        //上传文件流
        InputStream inputStream = new FileInputStream(new File(filePath));
        String originalFilename = file.getOriginalFilename();
        String uuid = java.util.UUID.randomUUID().toString().replaceAll("-", "");
        String fileName = uuid + "_" + originalFilename;
        //按照当前日期,创建文件夹,上传到创建的文件夹下。规则: 年/月/日
        String timeUrl = new DateTime().toString("yyyy/MM/dd");
        fileName = timeUrl + "/" + fileName;
        // 文件上传。
        ossClient.putObject(bucketName, fileName, inputStream);
        // 关闭OSSClient。
        ossClient.shutdown();
        //上传之后文件路径
        String url = "https://" + bucketName + "." + endPoint + "/" + fileName;
        map.put("url", url);
        map.put("originalFilename", originalFilename);
        map.put("fileName", fileName);
        map.put("time", videoMap.get("time"));
        return map;
    }

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐