VideoMind 是一个基于 Spring Boot 3 + React 的 AI 视频内容分析与问答平台。项目围绕“上传视频 -> 后端异步分析 -> 生成视频文案 -> 构建 RAG 索引 -> 基于视频内容问答”这条主链路展开,重点展示大文件分片上传、Redis 状态管理、Redisson 分布式锁、RocketMQ 异步任务、FFmpeg 音频抽取、阿里云 DashScope ASR、DeepSeek 内容分析、Embedding 与 pgvector 向量检索等工程能力。
该页面展示视频队列、当前视频、问答对话、RAG 构建状态、完整文案、摘要和风险等级。用户选择一个已分析视频后,可以点击“构建 RAG”,再围绕视频内容提问;后端会基于文案片段和向量索引返回答案与引用片段。
该页面展示选中视频的完整转写文案,以及“选择视频、上传视频、提交分析、后端分析、视频文案”五个阶段的真实耗时。它对应前端工作台中的流程可视化,便于观察一次视频处理从上传到文案生成的完整路径。
该页面展示上传视频、开始分析和当前阶段三个核心面板。前端只负责选择本地视频和触发操作,ASR、AI、OSS、Redis、RocketMQ 等后端密钥与流程均由后端配置和服务端代码管理。
该截图展示 RAG 构建触发 AI rate limit 的失败状态。后端在视频分析、Embedding 构建、视频问答前都会先经过用户维度的 Redis 令牌桶限流;超出额度时直接返回错误,避免进入队列或继续消耗模型 Token。
| 层级 | 技术 | 作用 |
|---|---|---|
| 后端 | Java 17、Spring Boot 3、Spring Security | REST API、鉴权、业务编排 |
| ORM | MyBatis-Plus、MySQL 8 | 用户、视频、上传任务、分析任务、RAG 文档元数据、AI 调用日志 |
| 缓存与锁 | Redis、Redisson | 上传状态、响应缓存、AI 限流、分布式锁 |
| 消息队列 | RocketMQ | 分析任务异步发布与消费 |
| 对象存储 | 阿里云 OSS / 本地存储 | 视频文件、临时音频 URL |
| 音视频处理 | FFmpeg、FFprobe | 视频时长探测、音频抽取 |
| ASR | 阿里云 DashScope ASR / 本地实现 | 音频转写、时间戳片段 |
| AI | DeepSeek OpenAI-compatible API / 本地实现 | 结构化视频分析、问答答案生成 |
| Embedding | DashScope Embedding / Local Hash Embedding | 文案片段向量化 |
| 向量库 | PostgreSQL + pgvector | RAG 语义检索 |
| 前端 | React 19、Vite、TypeScript、lucide-react、spark-md5 | 工作台 UI、分片上传、MD5 计算、RAG 问答交互 |
videomind/
├── src/main/java/com/videomind/
│ ├── VideoMindApplication.java # 程序入口
│ ├── api/ # HTTP 接口层
│ │ └── dto/ # 请求
│ ├── common/ # 统一响应、异常、分页
│ ├── config/ # Redis、OSS、AI、ASR、MQ、pgvector 配置
│ ├── domain/ # 数据模型与数据库访问
│ │ ├── entity/ # 用户、视频、任务、分析结果、RAG 文档
│ │ ├── mapper/ # MyBatis-Plus Mapper
│ │ └── model/ # 上传状态、分析状态枚举
│ ├── security/ # JWT 鉴权与当前用户
│ └── service/ # 核心业务层
│ ├── ai/ # DeepSeek 分析
│ ├── asr/ # 阿里云 DashScope ASR,本地转写
│ ├── cache/ # Redis
│ ├── embedding/ # DashScope
│ ├── publisher/ # RocketMQ
│ ├── rate/ # Redis Lua
│ ├── upload/ # 分片上传、OSS、本地存储、Redisson 锁
│ ├── vector/ # pgvector
│ └── video/ # FFmpeg 音频抽取
├── src/main/resources/
│ └── application.yml # 后端配置文件
├── src/test/ # 后端测试
├── docker/ # MySQL、PostgreSQL、RocketMQ 初始化配置
├── docs/ # 项目说明与 README 图片
├── videomind-web/
│ ├── src/
│ │ ├── App.tsx # 前端主页面
│ │ ├── lib/videomindApi.ts # 前端 API SDK、MD5 分片上传
│ │ ├── styles.css # 页面样式
│ │ └── test/ # 前端测试配置
│ ├── package.json # 前端依赖与脚本
│ └── vite.config.ts # Vite 配置
├── docker-compose.yml # MySQL、Redis、pgvector、RocketMQ 编排
├── pom.xml # 后端 Maven 配置
└── README.md # 项目说明
flowchart LR
Browser["浏览器 / React 工作台"]
API["Spring Boot REST API"]
Auth["JWT / Spring Security"]
MySQL["MySQL\n业务数据"]
Redis["Redis\n上传状态 / 缓存 / 限流"]
Redisson["Redisson Lock\nlock:upload:merge:{fileMd5}"]
OSS["阿里云 OSS / 本地文件"]
MQ["RocketMQ\nvideo-analysis-request"]
Processor["AnalysisTaskProcessor"]
FFmpeg["FFmpeg / FFprobe"]
ASR["阿里云 DashScope ASR"]
DeepSeek["DeepSeek Chat API"]
Embedding["Embedding Client\nDashScope / Local"]
PgVector["PostgreSQL + pgvector"]
Browser -->|"登录 / 上传 / 查询 / 问答"| API
API --> Auth
API --> MySQL
API --> Redis
API --> Redisson
API --> OSS
API -->|"发布 taskId"| MQ
MQ -->|"消费 taskId"| Processor
Processor --> FFmpeg
FFmpeg -->|"抽取 audio.wav"| ASR
ASR -->|"transcript + timestamps"| Processor
Processor --> DeepSeek
Processor -->|"分析结果 / RAG 文档元数据"| MySQL
Processor -->|"预热分析缓存"| Redis
API -->|"构建 RAG"| Embedding
Embedding --> PgVector
API -->|"视频问答:向量召回"| PgVector
API -->|"问答生成"| DeepSeek
API -->|"问答缓存"| Redis
前端计算视频 MD5 并分片上传;后端用 Redis 记录分片状态,合并时用 Redisson 按 MD5 加锁,避免同一个视频被重复合并。合并完成后,视频写入 OSS 或本地存储,并在 MySQL 保存视频记录。
用户提交分析后,后端创建分析任务并通过 RocketMQ 异步处理。消费者调用 FFmpeg 抽取音频,再调用 ASR 得到视频文案,最后交给 DeepSeek 生成摘要、关键词、标签、风险等级等结构化结果。
分析完成后,系统把视频文案切成可检索片段,并保存到 rag_document。构建 RAG 时,后端为片段生成 Embedding,写入 pgvector,后续问答就可以按语义召回相关片段。
用户提问时,系统先查 Redis 问答缓存;未命中则向量化问题,到 pgvector 召回相关文案片段,再让 DeepSeek 基于片段生成回答。回答会带引用内容,方便追溯到视频原文。
Redis 负责上传状态、分析缓存、问答缓存和 AI 限流。分析结果缓存到 video:analysis:{videoId},问答缓存到 video:qa:{videoId}:{questionHash};AI 调用使用用户维度令牌桶,超限直接返回 429。
为什么选: 视频分片合并和同 MD5 去重可能被并发触发,普通本地锁在多实例部署下不可靠,所以使用 Redisson 分布式锁。
lock:upload:merge:{fileMd5}
效果: 同一个视频只会被一个请求合并,避免重复写文件、重复上传 OSS、重复创建数据库记录。lock.lock() 还会触发 WatchDog 自动续期,适合较长耗时的合并过程。
为什么选: 视频文案通常很长,直接塞给模型成本高、效果不稳定,所以拆成 TRANSCRIPT_CHUNK 做检索。优先按 ASR 时间戳切分;没有时间戳时按 800 字符切块并保留 160 字符 overlap。
效果: 问答时只召回相关片段,减少 Token 消耗,也能把回答定位到视频时间点;pgvector 无结果时还能回退到本地相关性排序。
为什么选: FFmpeg、ASR、AI 分析都属于耗时任务,不适合阻塞 HTTP 请求。
效果: 上传和提交分析接口可以快速返回,后端通过任务状态跟踪处理进度,也方便做失败重试和后续扩展。
为什么选: DeepSeek 提供 OpenAI 兼容接口,接入成本低;DashScope ASR 和 Embedding 能覆盖语音转写和向量化能力。
效果: 视频可以自动生成文案、摘要和问答上下文;本地实现用于测试演示,真实环境再切换外部模型服务。
cd D:\video-web-ai\videomind
docker compose up -d mysql redis postgres-vector rocketmq-namesrv rocketmq-broker rocketmq-dashboard依赖服务默认端口:
| 服务 | 端口 |
|---|---|
| MySQL | 3306 |
| Redis | 6379 |
| PostgreSQL + pgvector | 5432 |
| RocketMQ NameServer | 9876 |
| RocketMQ Broker | 10909、10911、10912 |
| RocketMQ Dashboard | 8088 |
cd D:\video-web-ai\videomind
mvn spring-boot:run后端默认运行在 http://localhost:8080。
cd D:\video-web-ai\videomind\videomind-web
npm install
npm run dev前端默认运行在 Vite 输出的本地地址,通常是 http://127.0.0.1:5173。
请使用环境变量或本地安全配置注入真实密钥,不要把密钥提交到仓库。
| 变量 | 说明 |
|---|---|
VIDEOMIND_JWT_SECRET |
JWT 签名密钥 |
SPRING_DATASOURCE_URL / SPRING_DATASOURCE_USERNAME / SPRING_DATASOURCE_PASSWORD |
MySQL 连接 |
SPRING_DATA_REDIS_HOST / SPRING_DATA_REDIS_PORT / SPRING_DATA_REDIS_PASSWORD |
Redis 连接 |
ROCKETMQ_NAME_SERVER |
RocketMQ NameServer |
VIDEOMIND_ANALYSIS_PUBLISHER_MODE |
分析发布器模式,常用值为 local 或 rocketmq |
VIDEOMIND_OSS_MODE |
对象存储模式,常用值为 local 或 aliyun |
ALIYUN_OSS_ENDPOINT / ALIYUN_OSS_BUCKET / ALIYUN_OSS_ACCESS_KEY_ID / ALIYUN_OSS_ACCESS_KEY_SECRET |
阿里云 OSS 配置 |
ALIYUN_DASHSCOPE_API_KEY |
阿里云 DashScope ASR / Embedding Key |
DEEPSEEK_API_KEY / DEEPSEEK_BASE_URL / DEEPSEEK_CHAT_MODEL |
DeepSeek 模型配置 |
VIDEOMIND_EMBEDDING_PROVIDER |
Embedding Provider,常用值为 local 或 dashscope |
VECTOR_DATASOURCE_URL / VECTOR_DATASOURCE_USERNAME / VECTOR_DATASOURCE_PASSWORD |
pgvector 数据库连接 |
cd D:\video-web-ai\videomind
mvn testcd D:\video-web-ai\videomind\videomind-web
npm test
npm run build


