使用 Spring Boot + Redis 队列实现视频文件上传及 Ffmpeg 转码

使用 Spring Boot + Redis 队列实现视频文件上传及 Ffmpeg 转码

原创 编程疏影 路条编程 2024年07月19日 08:01 河北

图片

使用 Spring Boot + Redis 队列实现视频文件上传及 Ffmpeg 转码

在当今的互联网应用中,视频处理是一个常见且重要的需求。本方案旨在实现视频文件的上传,并利用 Redis 队列和 Ffmpeg 工具将上传的视频转码为 MP4 格式,以满足不同平台和设备的播放需求。

技术选型

  1. Spring Boot:作为构建现代化 Web 应用的首选框架,Spring Boot 提供了自动配置、起步依赖管理和嵌入式服务器等特性,大大简化了项目的搭建和开发过程。其强大的依赖管理和注解驱动的开发模式,能够快速构建高效、可扩展的后端服务。

    • 自动配置:减少了繁琐的配置文件编写,能够根据项目所引入的依赖自动完成常见的配置,例如数据库连接、缓存配置等。

    • 起步依赖:通过引入特定的起步依赖,能够方便地集成各种常用的技术栈,如数据库、消息队列、安全框架等,避免了手动管理大量的依赖版本问题。

    • 嵌入式服务器:内置了 Tomcat、Jetty 等服务器,使得开发和部署更加便捷,无需额外配置和部署独立的服务器。

  2. Redis:一款高性能的键值对存储数据库,常用于缓存、消息队列等场景。

    • 作为消息队列:Redis 的列表(List)数据结构非常适合实现简单的消息队列。其快速的入队和出队操作,能够高效地处理任务的调度和分发。

    • 高性能读写:Redis 基于内存存储,具有极快的读写速度,能够满足高并发场景下对数据的快速访问需求。

    • 数据结构丰富:除了列表,还支持字符串、哈希、集合、有序集合等多种数据结构,可根据不同的业务需求灵活选择。

  3. Ffmpeg:强大的多媒体处理工具,支持多种音频、视频格式的转换和处理。

    • 广泛的格式支持:能够处理几乎所有常见的视频和音频格式,包括但不限于 MP4、AVI、MOV、FLV 等。

    • 丰富的编码选项:提供了多种视频编码(如 H.264、H.265)和音频编码(如 AAC、MP3)的选择,以满足不同的质量和性能要求。

    • 命令行操作:通过命令行参数,可以灵活地定制视频处理的流程,如裁剪、缩放、帧率调整等。

项目搭建

创建 Spring Boot 项目,添加相关依赖。以下是 pom.xml 中的关键依赖:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>video-processing</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>video-processing</name>
    <description>Demo project for video processing with Spring Boot, Redis and Ffmpeg</description>

    <properties>
        <java.version>11</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.4</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

配置 Redis 连接信息和视频保存目录。在 application.yml 中添加如下配置:

spring:
  redis:
    host: localhost
    port: 6379
    password: your_password  # 如果有密码
  video:
    upload-directory: /your/custom/upload/directory

安装 Ffmpeg 工具,确保在系统环境变量中配置好 Ffmpeg 的路径,以便在 Java 代码中能够调用其命令进行视频转码操作。

添加 Redis 配置类:

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;

@Configuration
public class RedisConfig {

    @Value("${spring.redis.host}")
    private String host;

    @Value("${spring.redis.port}")
    private int port;

    @Value("${spring.redis.password}")
    private String password;

    @Bean
    public JedisConnectionFactory jedisConnectionFactory() {
        RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration(host, port);
        configuration.setPassword(password);
        JedisClientConfiguration jedisClientConfiguration = JedisClientConfiguration.builder()
           .connectTimeout(Duration.ofMillis(5000))
           .readTimeout(Duration.ofMillis(5000))
           .build();
        return new JedisConnectionFactory(configuration, jedisClientConfiguration);
    }

    @Bean
    public RedisTemplate<String, String> redisTemplate() {
        RedisTemplate<String, String> template = new RedisTemplate<>();
        template.setConnectionFactory(jedisConnectionFactory());
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new StringRedisSerializer());
        return template;
    }
}

前端视频上传页面(upload.html):

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>视频上传</title>
</head>
<body>
    <h2>上传视频</h2>
    <form action="/video/upload" method="post" enctype="multipart/form-data">
        <input type="file" name="file" />
        <input type="submit" value="上传" />
    </form>
</body>
</html>

** 视频上传接口**

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;

@Controller
@RequestMapping("/video")
public class VideoUploadController {

    @Value("${spring.video.upload-directory}")
    private String uploadDirectory;

    @PostMapping("/upload")
    public String uploadVideo(@RequestParam("file") MultipartFile file) {
        // 保存上传的视频文件到指定目录
        String filePath = uploadDirectory + File.separator + file.getOriginalFilename();
        try {
            file.transferTo(new File(filePath));
            // 将视频文件路径加入 Redis 队列
            redisTemplate.opsForList().rightPush("videoQueue", filePath);
            return "视频上传成功,即将转码";
        } catch (IOException e) {
            e.printStackTrace();
            return "视频上传失败";
        }
    }
}

Redis 队列处理

@Service
public class VideoProcessingService {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Scheduled(fixedDelay = 5000) // 每 5 秒检查队列
    public void processVideoQueue() {
        String filePath = redisTemplate.opsForList().leftPop("videoQueue");
        if (filePath!= null) {
            // 调用 Ffmpeg 进行转码
            convertVideoToMp4(filePath);
        }
    }

    private void convertVideoToMp4(String filePath) {
        // Ffmpeg 转码命令
        String command = "ffmpeg -i " + filePath + " -c:v libx264 -c:a aac " + filePath + ".mp4";
        try {
            Runtime runtime = Runtime.getRuntime();
            runtime.exec(command);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

总结

本方案通过 Spring Boot 构建了简洁高效的视频上传接口,利用 Redis 队列实现了任务的异步处理,结合 Ffmpeg 完成了视频的转码工作。整个流程具有良好的可扩展性和稳定性,能够满足实际业务中对视频处理的需求。但在实际应用中,还需要考虑错误处理、任务监控、资源优化等方面的问题,以确保系统的健壮性和性能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值