Files
2026-06-22 09:18:45 +08:00

218 lines
9.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Commands
```bash
# 下载依赖
go mod download
# 编译
go build -o media main.go
# 运行(开发)
go run main.go
# 格式化代码
go fmt ./...
# 代码检查
go vet ./...
# Docker 构建(多阶段构建,包含 FFmpeg 和 whisper 运行时)
docker build -t media .
# Docker 运行
docker run -p 3010:3010 media
```
## Architecture
这是一个多媒体处理微服务项目,基于 GoFrame 框架开发,提供视频处理、音频提取、语音识别、字幕叠加等功能。
### 目录结构
```
main.go # 应用入口,注册所有 Controller 路由
config.yml # 配置文件
consts/ # 常量定义
controller/ # HTTP 控制器层(路由入口)
- audio/ # 音频提取接口
- video/ # 视频相关接口(拼接、剪切、分析、合并、字幕、转码、场景分割)
- common/ # 公共工具(文件上传保存)
service/ # 业务逻辑层
- video/ # 视频服务(拼接、剪切、分析、合并混音、字幕叠加、转码、场景分割)
- audio/ # 音频提取服务
- asr/ # 语音识别服务
- scene/ # 场景检测服务
- image/ # 图片处理服务
- setup/ # 初始化服务(自动检查/安装依赖)
dao/ # 数据访问层
model/ # 数据模型
- dto/ # 传输对象(请求/响应)
- entity/ # 数据库实体
resource/ # 静态资源(日志、临时文件)
sql/ # 数据库建表 SQL
scripts/ # 外部脚本(scene_detect.py
```
### 核心功能
| 功能 | 说明 | 依赖 |
|------|------|------|
| 视频拼接 | 支持多视频拼接,提供 fast(无损 concat demuxer)和 reencode(重编码归一化)两种模式,可上传结果到 MinIO,支持同步和异步任务 | FFmpeg |
| 视频分镜剪切 | 根据分镜时间片段列表剪切视频并重新拼接输出,支持同步和异步任务 | FFmpeg |
| 视频拼接+混音 | 拼接多段视频后混入音频(支持多段),以视频时长为准自动补静音或截断,异步任务 | FFmpeg |
| 字幕叠加 | 使用 HyperFrames 将字幕/图片/动画元素渲染叠加到视频上,自动检测分辨率、拼接多视频、消音、降噪,异步任务 | FFmpeg + HyperFrames (npm) |
| 场景分割 | 使用 PySceneDetect 自动检测视频场景切分点,按场景分割为独立片段并上传,异步任务 | FFmpeg + Python3 + PySceneDetect |
| 视频转码 | 将视频转码为 H.264 + AAC + MP4 + faststartMOOV前置),同步接口 | FFmpeg |
| 音频提取 | 从视频文件中提取音频,支持 mp3/aac/wav/ogg/flac 多种格式 | FFmpeg |
| 语音识别 | 异步语音转文字任务,基于 OpenAI Whisper | FFmpeg + Whisper |
| 视频分析 | 调用外部 Marlin-2B VLM 服务对视频进行理解分析,生成场景描述和事件切分,支持 mock 模式,异步串行处理 | FFmpeg + 外部 VLM 服务 |
### 启动初始化
- `setup` 包在 `init()` 阶段自动执行,启动时自动检查并安装缺失依赖
- 检查项:FFmpeg、Python3、PySceneDetectscenedetect)、HyperFramesnpm 全局包)
- 每个依赖都按平台自动安装(macOS: brew, Linux: apt/apk/yum, Windows: winget/choco/scoop
- Docker 容器环境自动检测,跳过 sudo
### API 端点
**视频拼接:**
- `POST /video/concat` - 视频拼接(URL 输入,同步)
- `POST /video/concat/async` - 视频拼接(URL 输入,异步)
- `POST /video/concat/upload` - 视频拼接(文件上传,同步)
- `POST /video/concat/upload/async` - 视频拼接(文件上传,异步)
- `GET /video/concat/task/{taskId}` - 查询异步拼接任务结果
**视频分镜剪切:**
- `POST /video/cut` - 视频分镜剪切(URL 输入,同步)
- `POST /video/cut/async` - 视频分镜剪切(URL 输入,异步)
- `GET /video/cut/task/{taskId}` - 查询异步剪切任务结果
**视频拼接+混音:**
- `POST /video/merge/async` - 创建拼接混音异步任务
- `GET /video/merge/task/{taskId}` - 查询任务结果
**字幕叠加:**
- `POST /video/caption` - 创建字幕叠加异步任务
- `GET /video/caption/{taskId}` - 查询任务结果
**场景分割:**
- `POST /video/scene-split` - 创建场景分割异步任务
- `GET /video/scene-split/task/{taskId}` - 查询任务结果
**视频转码:**
- `POST /video/transcode` - 上传视频并转码为 H.264+AAC+MP4(同步)
**视频分析:**
- `POST /video/analysis` - 创建视频分析异步任务
- `GET /video/analysis/task/{taskId}` - 查询分析任务结果
**语音识别:**
- `POST /audio/transcribe` - 创建语音转文字异步任务
- `GET /audio/task/{taskId}` - 获取转写任务详情
- `GET /audio/task/{taskId}/progress` - 获取任务进度
- `GET /audio/tasks` - 获取任务列表
### 依赖外部服务
- PostgreSQL - 数据存储
- Redis - 缓存
- Consul - 服务发现
- Jaeger - 链路追踪
- OSS/MinIO - 文件存储(通过内部 oss 微服务 `oss/file/uploadFile` 接口上传)
- FFmpeg + ffprobe - 多媒体处理
- Whisper - 语音识别
- HyperFrames (npm) - HTML/GSAP 视频渲染引擎,用于字幕叠加
- PySceneDetect - Python 场景检测库
- Marlin-2B VLM 服务 - 视频理解大模型(分析功能使用)
### 内部依赖
项目依赖内部私有公共包 `gitea.redpowerfuture.com/red-future/common`,包含 HTTP 路由注册(`http.RouteRegister`)、用户信息解析(`beans.User`)、Consul、Jaeger 等基础设施封装。Docker 构建过程中已配置访问凭证。
### Docker 镜像
多阶段构建镜像包含:
- 编译后的二进制
- FFmpeg 运行时
- Python 3 + openai-whisperPython 版本,用于语音识别)
- 非 root 用户 `appuser` 运行
- 暴露端口 `3010`
### 架构设计
**分层架构:**
- `controller` - HTTP 入口,参数解析,调用 Service,返回响应
- `service` - 业务逻辑实现,每个功能领域一个子包
- `dao` - 数据访问层,数据库 CRUD 操作
- `model` - 数据模型,`dto` 存放请求/响应传输对象,`entity` 存放数据库实体
**设计模式:**
- 使用 GoFrame 框架的依赖注入模式
- 所有 Service 和 Controller 都使用**单例模式**`var Xxx = new(xxxStruct)`
- 路由注册在 `main.go` 中通过 `http.RouteRegister` 集中管理
- 临时文件处理完需要**及时清理**(使用 `defer os.Remove()``defer os.RemoveAll()`
**异步任务处理:**
- 长时任务(拼接、剪切、合并混音、字幕叠加、场景分割、语音识别、视频分析)都支持**异步执行**
- 同步模式直接等待结果返回,异步模式创建任务后立即返回任务 ID
- 异步任务状态持久化到数据库,可通过任务 ID 查询进度和结果
- 支持回调 URL,任务完成后 POST 回调通知调用方,携带 `X-User-Info` 头透传用户信息
- 任务执行使用 goroutine 异步处理,通过 recover 捕获 panic 并更新为失败状态
- 视频拼接+混音使用信号量控制并发(通过 `merge.concurrency` 配置)
**用户身份:**
- 所有接口优先从请求头 `Authorization` / `X-User-Info` 解析用户信息
- 解析失败使用默认 `admin` / tenantId=1 用于开发和调试
- 异步任务通过 `context.WithValue` 将用户信息传递给 goroutine
**Service 层共享工具函数(`service/video` 包内):**
- `getUserFromCtx(ctx)` - 从 context 提取用户信息
- `downloadFile(ctx, url, dir)` - 下载远程文件到本地
- `uploadToMinIO(ctx, localPath)` - 通过 OSS 微服务上传文件到 MinIO
- `lookupFFmpegPath()` - 查找 FFmpeg 可执行文件路径(优先配置路径,回退系统 PATH)
- `getVideoResolution(ctx, path)` - 用 ffprobe 获取视频分辨率
- `getVideoRealDuration(ctx, path)` - 用 ffprobe 获取视频时长(float64秒)
- `getVideoDurationStr(ctx, path)` - 获取视频时长可读字符串(m:ss格式)
- `cleanupFiles(paths)` - 批量清理临时文件
### 配置
主要配置在 `config.yml`:
**Server:**
- `server.address` - 监听地址(默认 `:3010`
- `server.clientMaxBodySize` - 上传文件大小限制(默认 `200MB`
**限流:**
- `rate.limit` - 每秒请求限制(默认 200
- `rate.burst` - 突发请求允许量(默认 300
**FFmpeg:**
- `ffmpeg.path` - FFmpeg 可执行文件路径,留空则从 PATH 自动查找
- `ffmpeg.temp_dir` - 临时文件目录(存放上传的视频和处理输出)
**视频分析:**
- `analysis.video_dir` - 视频永久存储目录(按 taskId 子目录组织)
- `analysis.caption_url` - Caption 接口地址
- `analysis.caption_timeout` - 单次调用超时(默认 `30m`
- `analysis.max_new_tokens` - 传递给 Caption 接口的参数
- `analysis.mock_caption` - 是否启用 mock 模式(true: 返回模拟数据,false: 真实调用)
**视频拼接+混音:**
- `merge.concurrency` - 并发数控制(默认 1,串行处理)
**HyperFrames 字幕叠加:**
- `hyperframes.render_timeout` - 渲染超时时间(分钟,默认 30)
- `hyperframes.headless` - 是否启用 headless 模式(默认 true
**外部服务:**
- `database` - PostgreSQL 数据库配置
- `redis` - Redis 配置
- `consul` - Consul 服务发现配置
- `jaeger` - Jaeger 链路追踪配置
- `filePrefix` - OSS/MinIO 文件访问地址前缀