SpringBoot 使用 FFmpeg 实现视频压缩

FFmpeg 是一个强大的开源音视频处理工具,可以用于视频转码、压缩、剪辑等操作。在 SpringBoot 项目中集成 FFmpeg,可以实现视频上传后自动压缩的功能,减少存储空间和带宽消耗。本文将详细介绍如何在 SpringBoot 中使用 FFmpeg 进行视频压缩。

图片[1]_SpringBoot 使用 FFmpeg 实现视频压缩_知途无界

1. 准备工作

1.1 安装 FFmpeg

FFmpeg 需要在服务器上安装,才能被 SpringBoot 调用。不同操作系统的安装方式:

Linux (Ubuntu/Debian)

sudo apt update
sudo apt install ffmpeg

验证安装:

ffmpeg -version

Windows

  1. 下载 FFmpeg Windows 版本:FFmpeg 官网
  2. 解压后,将 bin 目录添加到系统环境变量 PATH 中。
  3. 在命令行运行 ffmpeg -version 检查是否安装成功。

MacOS

brew install ffmpeg

1.2 SpringBoot 项目依赖

pom.xml 中添加必要的依赖(如果需要调用外部 API 或存储文件):

<dependencies>
    <!-- Spring Boot Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- 文件上传支持 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>

    <!-- 可选:用于存储压缩后的视频(如 AWS S3、MinIO) -->
    <!-- <dependency>
        <groupId>io.minio</groupId>
        <artifactId>minio</artifactId>
        <version>8.5.6</version>
    </dependency> -->
</dependencies>

2. 实现视频压缩功能

2.1 视频上传接口

首先,创建一个文件上传接口,接收用户上传的视频:

import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;

@RestController
@RequestMapping("/api/video")
public class VideoController {

    @PostMapping("/upload")
    public String uploadVideo(@RequestParam("file") MultipartFile file) {
        if (file.isEmpty()) {
            return "上传失败,请选择文件";
        }

        // 保存原始视频到服务器临时目录
        String originalFilePath = "/tmp/original_" + file.getOriginalFilename();
        try {
            file.transferTo(new File(originalFilePath));
        } catch (IOException e) {
            e.printStackTrace();
            return "文件保存失败";
        }

        // 调用 FFmpeg 进行压缩
        String compressedFilePath = compressVideo(originalFilePath);

        // 返回压缩后的视频路径(可以存储到数据库或返回给前端)
        return "压缩成功!压缩后路径:" + compressedFilePath;
    }

    /**
     * 使用 FFmpeg 压缩视频
     * @param inputPath 原始视频路径
     * @return 压缩后的视频路径
     */
    private String compressVideo(String inputPath) {
        // 定义压缩后的视频路径
        String outputPath = inputPath.replace(".mp4", "_compressed.mp4");

        // FFmpeg 压缩命令(调整参数以控制压缩质量)
        String ffmpegCommand = String.format(
            "ffmpeg -i %s -c:v libx264 -crf 28 -preset fast -c:a aac -b:a 128k %s",
            inputPath, outputPath
        );

        // 执行 FFmpeg 命令
        try {
            Process process = Runtime.getRuntime().exec(ffmpegCommand);
            process.waitFor(); // 等待命令执行完成
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("FFmpeg 压缩失败");
        }

        return outputPath;
    }
}

2.2 关键参数说明

  • -c:v libx264:使用 H.264 编码器(兼容性好)。
  • -crf 28:恒定质量因子(值越大,压缩率越高,画质越低,范围 0-51,推荐 18-28)。
  • -preset fast:编码速度与压缩率的平衡(可选 ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow)。
  • -c:a aac:音频编码器(AAC 格式)。
  • -b:a 128k:音频比特率(128kbps)。

2.3 测试视频压缩

  1. 启动 SpringBoot 项目。
  2. 使用 Postman 或前端页面上传视频:
  • URL: http://localhost:8080/api/video/upload
  • Method: POST
  • 参数: 选择 form-datakey 设为 file,上传视频文件。
  1. 返回压缩后的视频路径,可以下载或存储到数据库。

3. 优化与扩展

3.1 异步压缩(避免阻塞请求)

如果视频较大,压缩可能耗时较长,可以使用 异步任务(如 @Async 或消息队列):

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Service
public class VideoCompressionService {

    @Async
    public void compressVideoAsync(String inputPath) {
        String outputPath = inputPath.replace(".mp4", "_compressed.mp4");
        String ffmpegCommand = String.format(
            "ffmpeg -i %s -c:v libx264 -crf 28 -preset fast -c:a aac -b:a 128k %s",
            inputPath, outputPath
        );
        try {
            Runtime.getRuntime().exec(ffmpegCommand).waitFor();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

然后在 Controller 中调用:

@Autowired
private VideoCompressionService compressionService;

@PostMapping("/upload")
public String uploadVideo(@RequestParam("file") MultipartFile file) {
    // ... 保存文件后
    compressionService.compressVideoAsync(originalFilePath);
    return "上传成功,正在压缩...";
}

3.2 存储压缩后的视频

可以将压缩后的视频存储到:

  • 本地磁盘(如 /var/videos/compressed/
  • 云存储(如 AWS S3、阿里云 OSS、MinIO)
  • 数据库 BLOB(不推荐,仅适用于小文件)

示例(存储到 MinIO):

import io.minio.MinioClient;
import io.minio.PutObjectArgs;

public void uploadToMinIO(String filePath, String bucketName) {
    try {
        MinioClient minioClient = MinioClient.builder()
            .endpoint("https://minio.example.com")
            .credentials("accessKey", "secretKey")
            .build();

        minioClient.putObject(
            PutObjectArgs.builder()
                .bucket(bucketName)
                .object("compressed_" + System.currentTimeMillis() + ".mp4")
                .stream(new FileInputStream(filePath), -1, 10485760) // 10MB 分块
                .build()
        );
    } catch (Exception e) {
        e.printStackTrace();
    }
}

3.3 返回压缩后的视频 URL

如果存储到云服务,可以返回下载链接:

return "压缩成功!下载链接:" + "https://minio.example.com/compressed_video.mp4";

4. 常见问题

4.1 FFmpeg 执行失败

  • 检查 FFmpeg 是否安装ffmpeg -version
  • 检查命令是否正确:在服务器终端手动运行 FFmpeg 命令测试。
  • 检查文件路径:确保 inputPathoutputPath 正确。

4.2 视频压缩后画质太差

  • 调整 -crf 参数(值越小,画质越好,文件越大)。
  • 调整 -preset 参数(slow 压缩率更高,但速度慢)。

4.3 大文件上传超时

  • 调整 SpringBoot 的 spring.servlet.multipart.max-file-sizemax-request-size
  spring.servlet.multipart.max-file-size=100MB
  spring.servlet.multipart.max-request-size=100MB
  • 使用分片上传或断点续传(如阿里云 OSS 的分片上传 API)。

5. 总结

本文介绍了如何在 SpringBoot 中集成 FFmpeg 实现视频压缩:

  1. 安装 FFmpeg(服务器必备)。
  2. 创建上传接口,接收用户视频。
  3. 调用 FFmpeg 压缩,调整参数控制画质和文件大小。
  4. 优化方案:异步压缩、云存储、返回下载链接。
  5. 常见问题排查

适用于视频网站、在线教育、监控系统等需要视频压缩的场景。🚀

© 版权声明
THE END
喜欢就点个赞,支持一下吧!
点赞5 分享
评论 抢沙发
头像
欢迎您留下评论!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容