Files
video-gen/DEPLOYMENT.md
T
2026-07-11 09:17:07 +08:00

22 KiB
Raw Blame History

VideoGen 部署文档

项目结构

video_item/
├── video-gen-api/          # 后端 (Python FastAPI + SQLAlchemy + Alembic)
├── video-gen-app/          # 前台/用户端 (React 19 + Vite 8 + Ant Design 6)
├── video-gen-admin/        # 后台管理端 (React 19 + Vite 8 + Ant Design 6)
└── DEPLOYMENT.md           # 本文档

三个前端/后端的关系: video-gen-app (用户前台) 和 video-gen-admin (管理后台) 都连接同一个 video-gen-api 后端。


一、环境要求

组件 版本要求 说明
Python >= 3.10 推荐 3.12
Node.js >= 18 推荐 20+
PostgreSQL >= 14 推荐 16必须
Redis >= 6 推荐用于: 限流/验证码/Celery/任务状态
FFmpeg 任意 用于视频封面截帧,留空时从 PATH 自动查找
ca-certificates 任意 必须,HTTPS 请求需要(新服务器/容器常缺)
alipay-sdk-python >=3.7.1160 可选,支付宝支付
wechatpayv3 >=2.0.2 可选,微信支付
volcengine-python-sdk >=1.1.0 可选,视频生成/短信

二、后端部署 (video-gen-api)

1. 安装依赖

# ⚠️ 新服务器/容器必须先装 CA 证书,否则 HTTPS(支付宝/火山等)全部失败
# CentOS/RHEL
sudo yum install -y ca-certificates
# Ubuntu/Debian
sudo apt-get install -y ca-certificates

cd video-gen-api

# 创建虚拟环境
python -m venv .venv
# Windows
.venv\Scripts\activate
# Linux/Mac
source .venv/bin/activate

# 安装基础依赖
pip install -e .

# 安装 PostgreSQL 驱动(生产环境必须)
pip install -e ".[pg]"

# 如需 Redis 支持(限流、验证码、Celery)
pip install -e ".[pg,redis]"

# 如需 Celery 异步任务(ChatAPI 生成流水线)
pip install -e ".[pg,redis,celery]"

# 如需支付宝
pip install -e ".[pg,redis,celery,alipay]"

# 如需微信支付
pip install -e ".[pg,redis,celery,alipay,wxpay]"

# 如需火山引擎 SDK(短信等)
pip install -e ".[pg,redis,celery,alipay,wxpay,volc]"

2. 配置环境变量

复制 .env.example.env,修改关键配置:

cp .env.example .env
# ── 基础配置 ──
APP_NAME=VideoGen API
APP_VERSION=1.0.0
DEBUG=false
SECRET_KEY=改成一个随机的长字符串(JWT 签名密钥)

# ── 数据库(必须) ──
DATABASE_URL=postgresql+asyncpg://用户名:密码@localhost:5432/videogen

# ── Redis(可选,留空则禁用限流/验证码/Celery) ──
REDIS_URL=redis://localhost:6379/0

# ── JWT ──
JWT_ALGORITHM=HS256
JWT_EXPIRE_MINUTES=1440          # 普通登录 24h
JWT_EXPIRE_REMEMBER_MINUTES=10080 # 记住登录 7天

# ── 视频生成(火山引擎 Ark) ──
SEEDANCE_API_KEY=你的API Key
SEEDANCE_API_BASE=https://ark.cn-beijing.volces.com/api/v3
SEEDANCE_CALLBACK_URL=https://你的域名/api/generation-records/callback

# ── LLM 提示词优化 ──
LLM_API_BASE=https://api.openai.com/v1
LLM_API_KEY=
LLM_MODEL=gpt-4o
LLM_MOCK=true                    # true=使用 mock 响应,不调用真实 LLM

# ── 前后端通信加密(32字节 base64,留空则禁用) ──
ENCRYPTION_KEY=你的32字节base64密钥

# ── 存储路径(本地存储) ──
STORAGE_TYPE=local
STORAGE_LOCAL_PATH=./storage/generate/videos
STORAGE_IMAGE_LOCAL_PATH=./storage/generate/images
STORAGE_VIDEO_COVER_LOCAL_PATH=./storage/generate/covers
UPLOAD_LOCAL_PATH=./storage/uploads

# ── 跨域(生产环境务必限制域名,默认 ["*"] 允许所有) ──
CORS_ORIGINS=["https://你的前台域名.com", "https://你的后台域名.com"]

# ── 回调基础地址 ──
BASE_URL=https://你的域名

# ── 验证码 ──
CAPTCHA_ENABLED=true

# ── 短信(火山引擎 SDKSMS_MOCK=false 时生效) ──
SMS_MOCK=true
VOLC_SMS_ACCESS_KEY_ID=
VOLC_SMS_SECRET_ACCESS_KEY=
VOLC_SMS_ACCOUNT=消息组ID
VOLC_SMS_TEMPLATE_ID=模板ID
VOLC_SMS_SIGN=短信签名

# ── 支付(PAYMENT_MOCK=false 时生效) ──
PAYMENT_MOCK=true
WECHAT_MCH_ID=
WECHAT_API_KEY=
ALIPAY_APP_ID=
ALIPAY_PRIVATE_KEY=
ALIPAY_PUBLIC_KEY=
ALIPAY_NOTIFY_URL=

# ── Celery(可选,留空则禁用 ChatAPI 异步流水线) ──
CELERY_BROKER_URL=redis://localhost:6379/5
CELERY_RESULT_BACKEND=redis://localhost:6379/6

# ── FFmpeg(留空自动从 PATH 查找) ──
FFMPEG_BIN=/usr/bin/ffmpeg

关于 ENCRYPTION_KEY 的生成: 需要 32 字节(256 位)的 base64 编码字符串。生成方式:openssl rand -base64 32。前后端必须使用完全相同的密钥。

3. 初始化数据库

# 创建 PostgreSQL 数据库
psql -U postgres -c "CREATE DATABASE videogen OWNER videogen;"

# 启动后端(首次启动自动建表)
python -m uvicorn app.main:app --host 0.0.0.0 --port 8000

首次启动时会自动创建所有数据表41 个 model)。

⚠️ 关于种子数据: 代码中包含 _seed_data() 函数(创建管理员/演示用户、系统配置、引擎配置等),但当前在 main.py 中被注释掉了# await _seed_data())。因此首次启动不会自动创建管理员账号。

**如果你需要种子数据,**有以下选择:

  1. main.py 中取消注释 # await _seed_data() 后重启
  2. 手动通过 API 或数据库脚本创建管理员账号
  3. 自行编写独立的种子脚本调用 _seed_data()

4. 数据库迁移 (Alembic)

项目使用 Alembic 管理数据库结构变更。

cd video-gen-api

# 修改 model 后,自动生成迁移文件
python -m alembic revision --autogenerate -m "描述改动内容"

# 执行迁移
python -m alembic upgrade head

# 查看当前版本
python -m alembic current

# 查看迁移历史
python -m alembic history

# 回滚一步
python -m alembic downgrade -1

部署流程: 拉取代码后先执行 alembic upgrade head,再重启后端服务。

5. 生产运行

# 直接运行(推荐 4 workers
python -m uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 4

systemd 服务文件 /etc/systemd/system/videogen-api.service

[Unit]
Description=VideoGen API
After=network.target postgresql.service

[Service]
Type=simple
User=www-data
WorkingDirectory=/opt/video-gen-api
Environment=PATH=/opt/video-gen-api/.venv/bin
ExecStart=/opt/video-gen-api/.venv/bin/python -m uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 4
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable videogen-api
sudo systemctl start videogen-api

6. Celery Worker(可选)

ChatAPI 异步生成流水线需要 Celery Worker,依赖 Redis 作为 Broker。

Celery 使用 6 个队列,按功能分离:

队列 用途
gen_chatapi_create ChatAPI 生成任务创建(含爆款开头/拆镜复刻的提词步骤)
gen_provider_poll 轮询火山引擎生成状态
gen_result_download 下载生成的视频/图片结果
gen_recovery 容灾恢复任务(统一队列,避免占用业务 worker)
gen_private_portrait 真人素材认证与同步
default 默认队列(用户 OAuth、清理任务等)
# 启动 Worker(消费所有队列)
celery -A app.tasks.celery_app worker -l info -Q gen_chatapi_create,gen_provider_poll,gen_result_download,gen_recovery,gen_private_portrait,default

systemd 服务文件 /etc/systemd/system/videogen-worker.service

[Unit]
Description=VideoGen Celery Worker
After=network.target redis.service

[Service]
Type=simple
User=www-data
WorkingDirectory=/opt/video-gen-api
Environment=PATH=/opt/video-gen-api/.venv/bin
ExecStart=/opt/video-gen-api/.venv/bin/celery -A app.tasks.celery_app worker -l info -Q gen_chatapi_create,gen_provider_poll,gen_result_download,gen_recovery,gen_private_portrait,default
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

7. Docker 部署(可选)

项目提供 Dockerfiledocker-compose.yml

⚠️ 注意: 默认 Dockerfile 只安装基础依赖(pip install .),生产使用需改为 ".[pg,redis,celery]"

cd video-gen-api

# 使用前需修改 Dockerfile 第 6 行为:
# RUN pip install --no-cache-dir ".[pg,redis,celery]"

docker compose up -d

启动的服务:

服务 端口 说明
api 8000 FastAPI 应用(--reload 开发模式)
worker - Celery Worker(消费所有队列)
postgres 5432 PostgreSQL 16
redis 6379 Redis 7

8. Nginx 反向代理

server {
    listen 80;
    server_name api.yourdomain.com;

    # 上传文件大小限制(视频上传需要较大值)
    client_max_body_size 100M;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_read_timeout 300s;
    }

    # 静态文件 (上传的视频/图片)
    location /uploads/ {
        alias /opt/video-gen-api/storage/uploads/;
        expires 7d;
    }
}

三、前台部署 (video-gen-app)

用户前台,面向最终用户。

1. 安装依赖 & 构建

cd video-gen-app

npm install

# 配置 API 地址(创建 .env.production
echo "VITE_API_BASE=https://api.yourdomain.com" > .env.production

# 如需前后端加密通信(与后端 ENCRYPTION_KEY 相同)
echo "VITE_ENCRYPTION_KEY=密钥" >> .env.production

# 构建
npm run build

构建产物在 dist/ 目录。

2. 前端环境变量

变量 说明 默认值
VITE_API_BASE 后端 API 地址 http://localhost:8000
VITE_USE_MOCK 是否使用 mock 数据(无需后端) false
VITE_ENCRYPTION_KEY 前后端通信加密密钥(需与后端一致) 空(不加密)

3. Nginx 配置

server {
    listen 80;
    server_name yourdomain.com;
    root /opt/video-gen-app/dist;
    index index.html;

    # SPA 路由:所有页面请求回退到 index.html
    location / {
        try_files $uri $uri/ /index.html;
    }

    # 静态资源缓存(带 hash 的文件名可长期缓存)
    location /assets/ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
}

四、后台管理部署 (video-gen-admin)

管理员后台,面向运营/管理人员。

1. 安装依赖 & 构建

cd video-gen-admin

npm install

# 配置 API 地址
echo "VITE_API_BASE=https://api.yourdomain.com" > .env.production

# 如需前后端加密通信
echo "VITE_ENCRYPTION_KEY=密钥" >> .env.production

# 构建
npm run build

2. 后台环境变量

变量 说明 默认值
VITE_API_BASE 后端 API 地址 http://localhost:8000
VITE_USE_MOCK 是否使用 mock 数据 false
VITE_ENCRYPTION_KEY 前后端通信加密密钥 空(不加密)

3. Nginx 配置

server {
    listen 80;
    server_name admin.yourdomain.com;
    root /opt/video-gen-admin/dist;
    index index.html;

    location / {
        try_files $uri $uri/ /index.html;
    }

    location /assets/ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
}

五、完整 Nginx 配置示例 (单机部署)

# 后端 API
server {
    listen 80;
    server_name api.yourdomain.com;
    client_max_body_size 100M;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_read_timeout 300s;
    }

    location /uploads/ {
        alias /opt/video-gen-api/storage/uploads/;
        expires 7d;
    }
}

# 前台
server {
    listen 80;
    server_name yourdomain.com;
    root /opt/video-gen-app/dist;
    index index.html;

    location / {
        try_files $uri $uri/ /index.html;
    }

    location /assets/ {
        expires 1y;
    }
}

# 后台管理
server {
    listen 80;
    server_name admin.yourdomain.com;
    root /opt/video-gen-admin/dist;
    index index.html;

    location / {
        try_files $uri $uri/ /index.html;
    }

    location /assets/ {
        expires 1y;
    }
}

六、SSL 配置 (推荐)

使用 Certbot 获取免费证书:

sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d yourdomain.com -d admin.yourdomain.com -d api.yourdomain.com

七、默认账号

⚠️ 默认账号仅在种子数据被执行后存在(见第三节第 3 点说明)。

角色 用户名 手机号 密码 积分
管理员 admin 13800000000 123456 10000
演示用户 demo 13888888888 123456 2680

首次部署后务必修改默认密码。


八、架构说明

后端启动时的后台任务

后端启动时(lifespan)会自动启动以下进程内后台任务:

任务 说明
task_queue (video_queue) 内置 asyncio 任务队列,轮询视频/图片生成状态
upload_queue 上传任务队列
material_consumption_queue 素材消耗队列
token_refresh_scheduler 每 5 分钟检查并刷新即将过期的 token
poll_pre_test_results 每分钟轮询前测结果
schedule_daily_sync 每天 9 点自动同步素材消耗
_order_expiry_loop 每分钟同步待支付订单状态 + 自动过期订单

加上 Celery Worker(可选,处理 ChatAPI 异步流水线)。

中间件栈(从外到内,即请求到达的顺序)

  1. RequestLoggingMiddleware — 请求/响应日志记录
  2. AntiCrawlerMiddleware — 反爬虫(拦截空 UA 和常见 bot)
  3. RateLimitMiddleware — 滑动窗口限流(Redis 支撑)
  4. RequestEncryptMiddleware — AES-256-GCM 请求/响应加密
  5. CORSMiddleware — 跨域(expose X-Encrypted 响应头)

前后端通信加密

机制: AES-256-GCM 对称加密,前后端共享同一个 ENCRYPTION_KEY。使用 Web Crypto API(前端)和 cryptography 库(后端)。

生效条件: 同时满足以下两个条件才启用加密:

  • 后端 .envENCRYPTION_KEY 非空
  • 前端 .envVITE_ENCRYPTION_KEY 非空
  • 运行在安全上下文(HTTPS 或 localhost

加密范围:

请求类型 请求体 响应体
GET(无 body 不加密(无内容) 加密
POST/PUT/DELETE(有 body 加密 加密

工作流:

  1. 前端发送 POST 请求时,将 JSON 请求体加密为 { data: "<密文>" },并加 X-Encrypted: true 请求头
  2. 后端中间件检测到 X-Encrypted: true 时解密请求体,处理完后加密响应体
  3. 支付回调接口(/payments/alipay/callback, /payments/wechat/callback)白名单跳过加密

GET 请求注意: GET 没有请求体,但响应仍会被加密。前端会自动检测并解密。

文件日志加密(独立机制)

与通信加密不同,文件日志存储使用另一套独立的 AES-CBC-256 加密:

日志类型 目录 加密方式
请求/响应日志 log/RequestResponse/{日期}.log AES-CBC-256,密钥硬编码
AI 模型日志 log/AiModel/{日期}.log AES-CBC-256,密钥硬编码

日志加密密钥与 ENCRYPTION_KEY 无关,是代码中硬编码的值。解密工具:/internal/decrypt-data 页面。

内部管理端点

端点 用途
/internal/ 后端入口导航页
/internal/health 健康检查 ({"status": "ok"})
/internal/status 服务状态监控页 (Celery/Redis 连接状态)
/internal/decrypt-data 日志数据解密工具(AES-CBC
/internal/api-docs Swagger API 文档
/internal/api-redoc ReDoc API 文档
/uploads/ 用户上传的静态文件(挂载为静态目录)
/api/decrypt 解密接口(POST,供解密工具调用)

前端 Mock 模式

前端支持 Mock 数据模式,无需后端即可开发:

  • 设置 VITE_USE_MOCK=true 时,所有 API 调用返回本地假数据
  • 适用场景:纯前端开发、演示、无后端环境
  • 注意:mock 模式下仍会调用部分真实 API(如站点信息、验证码)

存储路径

路径 用途
storage/generate/videos/ 生成的视频文件
storage/generate/images/ 生成的图片文件
storage/generate/covers/ 视频封面缩略图
storage/uploads/ 用户上传的原始文件

外部服务依赖

服务 用途 是否必须
火山引擎 Ark 视频生成(Seedance 2.0)、图片生成(Seedream 5.0)、LLM
火山引擎短信 短信验证码 否(可 mock
微信支付 / 支付宝 充值支付 否(可 mock,未完整实现)
FFmpeg 视频封面截帧 否(留空自动查找)

九、目录结构 (部署后)

/opt/
├── video-gen-api/                      # 后端
│   ├── .env                            # 环境变量
│   ├── .venv/                          # Python 虚拟环境
│   ├── app/                            # 应用代码
│   │   ├── api/                        # API 路由
│   │   │   ├── v1/                     # v1 版本接口(前端用户端 + 部分管理接口)
│   │   │   └── admin/                  # 管理端接口
│   │   ├── middleware/                 # 中间件
│   │   ├── models/                     # 数据模型 (41 个)
│   │   ├── services/                   # 业务服务
│   │   ├── tasks/                      # Celery 任务
│   │   ├── enums/                      # 枚举定义
│   │   └── utils/                      # 工具函数
│   ├── alembic/                        # 数据库迁移文件
│   ├── storage/
│   │   ├── generate/
│   │   │   ├── videos/                 # 生成的视频
│   │   │   ├── images/                 # 生成的图片
│   │   │   └── covers/                 # 视频封面
│   │   └── uploads/                    # 用户上传
│   └── log/
│       ├── AiModel/                    # AI 模型请求日志(加密)
│       └── RequestResponse/            # 请求响应日志(加密)
├── video-gen-app/dist/                 # 前台构建产物
└── video-gen-admin/dist/               # 后台构建产物

十、常用运维命令

# 查看后端日志
sudo journalctl -u videogen-api -f

# 重启后端
sudo systemctl restart videogen-api

# 重启 Celery Worker
sudo systemctl restart videogen-worker

# 重新构建前端
cd /opt/video-gen-app && npm run build
cd /opt/video-gen-admin && npm run build

# 数据库备份
pg_dump -U videogen videogen > backup_$(date +%Y%m%d).sql

# 数据库恢复
psql -U videogen videogen < backup_20260512.sql

# 执行数据库迁移
cd /opt/video-gen-api && python -m alembic upgrade head

# 生成迁移文件
cd /opt/video-gen-api && python -m alembic revision --autogenerate -m "描述"

# 查看 Celery 活动任务
celery -A app.tasks.celery_app inspect active

十一、环境变量完整参考

后端 (video-gen-api/.env)

变量 必填 默认值 说明
SECRET_KEY change-me JWT 签名密钥
DATABASE_URL sqlite PostgreSQL 连接串
REDIS_URL Redis 连接串,留空禁用限流/验证码
JWT_EXPIRE_MINUTES 1440 Token 有效期(分钟)
JWT_EXPIRE_REMEMBER_MINUTES 10080 记住登录 Token 有效期
SEEDANCE_API_KEY 火山引擎 API Key
SEEDANCE_API_BASE 火山地址 API 基础 URL
SEEDANCE_CALLBACK_URL 生成结果回调 URL
LLM_API_BASE OpenAI LLM API 地址
LLM_API_KEY LLM API Key
LLM_MODEL gpt-4o LLM 模型名称
LLM_MOCK true 是否 mock LLM 响应
ENCRYPTION_KEY 占位符 前后端通信加密密钥
SMS_MOCK true 是否 mock 短信
PAYMENT_MOCK false 是否 mock 支付
CORS_ORIGINS ["*"] 允许的跨域来源
BASE_URL 测试地址 站点基础 URL,用于回调拼接
STORAGE_TYPE local 存储类型
UPLOAD_LOCAL_PATH ./storage/uploads 上传文件存储路径
FFMPEG_BIN FFmpeg 路径(留空自动查找)
CAPTCHA_ENABLED true 是否启用验证码
CELERY_BROKER_URL Celery Broker(留空禁用 Celery
CELERY_RESULT_BACKEND Celery 结果后端
RATE_LIMIT_ENABLED true 是否启用限流

前台 (video-gen-app/.env.production)

变量 必填 默认值 说明
VITE_API_BASE localhost:8000 后端 API 地址
VITE_USE_MOCK false 是否使用 mock 数据
VITE_ENCRYPTION_KEY 通信加密密钥(与后端一致)

后台管理 (video-gen-admin/.env.production)

同前台。


十二、故障排查

现象 可能原因 解决方案
前端登录后 401 Token 过期或 SECRET_KEY 不一致 检查后端 SECRET_KEY 是否变更
上传文件失败 413 Nginx 上传大小限制 增大 client_max_body_size
加密请求报错"解密失败" 前后端密钥不一致 确保 VITE_ENCRYPTION_KEY = 后端 ENCRYPTION_KEY
非 HTTPS 环境加密无效 Web Crypto API 需要安全上下文 本地开发用 localhost,生产用 HTTPS
Celery 任务不执行 Redis 未启动或地址错误 检查 CELERY_BROKER_URL 和 Redis
限流不生效 Redis 未配置 检查 REDIS_URL
短信发送失败 火山配置缺失或 SMS_MOCK=true 填入 VOLC_SMS_* 变量并设 SMS_MOCK=false
视频封面无法生成 FFmpeg 未安装 安装 FFmpeg 或设置 FFMPEG_BIN
HTTPS 请求支付宝/火山失败 缺少 CA 证书 安装 ca-certificates
数据库迁移失败 Model 定义与迁移不一致 重新生成迁移文件后执行