AI.Demo/DEPLOY.md

892 lines
24 KiB
Markdown
Raw 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.

# AI 英语学习辅助平台 — 线上部署操作流程
## 项目概述
- **项目名称**AI 英语学习辅助平台
- **技术栈**
- 前端Vue 3 + Vite + Vue RouterHistory 模式)
- 后端Express.js + FFmpeg视频合成服务
- **项目结构**
- 前端纯静态文件HTML / CSS / JS可部署到任意静态托管服务
- 后端Node.js 服务,需要 FFmpeg 环境,提供视频合成 API
---
## 一、部署前准备
### 1.1 环境要求
| 工具 | 版本要求 | 用途 |
|------|----------|------|
| Node.js | >= 18.x推荐 20.x LTS | 前端构建 & 后端服务运行 |
| npm | >= 9.x | 包管理器 |
| FFmpeg | 最新稳定版 | 后端视频合成(仅后端服务需要) |
```bash
# 检查 Node.js 和 npm 版本
node -v
npm -v
# 检查 FFmpeg 是否已安装(后端服务需要)
ffmpeg -version
```
### 1.2 安装 FFmpeg后端服务必需
#### Windows
1. 下载 FFmpeg: https://www.gyan.dev/ffmpeg/builds/
2. 解压到 `C:\ffmpeg`
3. 添加 `C:\ffmpeg\bin` 到系统环境变量 PATH
4. 验证安装:
```bash
ffmpeg -version
```
#### macOS
```bash
# 使用 Homebrew 安装
brew install ffmpeg
# 验证安装
ffmpeg -version
```
#### Linux (Ubuntu/Debian)
```bash
# 安装 FFmpeg
sudo apt update && sudo apt install ffmpeg
# 验证安装
ffmpeg -version
```
### 1.3 安装依赖
```bash
# 安装前端依赖
cd AI_Demo
npm install
# 安装后端依赖
cd server
npm install
```
---
## 二、关键配置说明
### 2.1 API 配置(必须在部署前确认)
项目所有 API 密钥集中在 `src/config/index.js`,部署前请确认以下配置项均已填写正确:
| 配置项 | 说明 |
|--------|------|
| `GRS_API_KEY` | GRS AI 接口密钥(作文批改) |
| `DOUBAO_KEY` | 豆包 API 密钥 |
| `DOUBAO_APP_ID` | 豆包语音 App ID |
| `DOUBAO_ACCESS_TOKEN` | 豆包语音访问令牌 |
| `DOUBAO_RESOURCE_ID` | 豆包 TTS 资源 ID |
| `DOUBAO_ASR_RESOURCE_ID` | 豆包 ASR 资源 ID |
| `ARK_API_KEY` | 火山引擎 Ark 大模型密钥(口语对话) |
| `ARK_MODEL` | Ark 模型名称(如 doubao-pro-4k |
### 2.2 跨域响应头要求(重要)
项目使用了 `@ffmpeg/ffmpeg`WebAssembly需要服务器返回以下响应头否则视频讲解功能将无法运行
```
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
```
> 各部署平台的配置方式见下方对应章节。
### 2.3 API 代理配置(重要)
项目在开发环境通过 Vite 代理转发以下 API 请求,**生产环境必须在服务器/网关层配置对应的反向代理**
| 前端请求路径前缀 | 代理目标 | 用途 | 备注 |
|-----------------|----------|------|------|
| `/api/video` | 后端服务(默认 http://localhost:3001 | 视频合成 | **无需跨域代理**,直接访问后端服务 |
| `/tts-api` | `https://openspeech.bytedance.com` | 豆包 TTS 语音合成 | 需要反向代理 |
| `/ark-api` | `https://ark.cn-beijing.volces.com` | 火山引擎 Ark 大模型 | 需要反向代理 |
| `/dashscope-api` | `https://dashscope.aliyuncs.com` | 阿里云百炼 | 需要反向代理 |
| `/asr-ws` | `wss://openspeech.bytedance.com` | 豆包 ASR WebSocket | 需要反向代理+注入鉴权 Header |
> **后端服务说明**`/api/video` 接口由本项目的后端服务(`server/`)提供,不需要跨域代理,但需要确保后端服务正常运行。
> **ASR WebSocket 特殊说明**`/asr-ws` 代理需要在代理层注入以下鉴权 Header浏览器原生 WebSocket 不支持自定义 Header
> - `X-Api-App-Key`
> - `X-Api-Access-Key`
> - `X-Api-Resource-Id`
> - `X-Api-Connect-Id`(每次连接随机 UUID
---
## 三、构建生产包
### 3.1 前端构建
```bash
npm run build
```
构建完成后,产物位于 `dist/` 目录,包含:
```
dist/
├── index.html
├── favicon.svg
└── assets/
├── *.js
└── *.css
```
可在本地预览构建结果:
```bash
npm run preview
```
### 3.2 后端服务准备
后端服务无需构建,直接使用源码运行即可。确保:
1. 已安装 FFmpeg见 1.2 节)
2. 已安装依赖:
```bash
cd server
npm install
```
3. 测试服务是否正常:
```bash
npm start
```
访问 http://localhost:3001/health 应返回 `{"status":"ok"}`
---
## 四、部署方案
### 方案 ANginx 部署(推荐,自有服务器)
#### 4.A.1 上传文件
`dist/` 目录内容上传到服务器,例如 `/var/www/ai-demo/`
```bash
scp -r dist/* user@your-server:/var/www/ai-demo/
```
#### 4.A.2 Nginx 配置
创建或修改 Nginx 站点配置文件(如 `/etc/nginx/sites-available/ai-demo.conf`
```nginx
server {
listen 80;
server_name your-domain.com; # 替换为你的域名或 IP
root /var/www/ai-demo;
index index.html;
# 跨域响应头FFmpeg WASM 必需)
add_header Cross-Origin-Opener-Policy "same-origin" always;
add_header Cross-Origin-Embedder-Policy "require-corp" always;
# Vue Router History 模式:所有路由回退到 index.html
location / {
try_files $uri $uri/ /index.html;
}
# 后端视频合成服务代理
location /api/video/ {
proxy_pass http://localhost:3001/api/video/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
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;
# 增大请求体大小限制(视频合成可能需要)
client_max_body_size 100m;
# 增加超时时间(视频合成耗时较长)
proxy_connect_timeout 300;
proxy_send_timeout 300;
proxy_read_timeout 300;
}
# 代理:豆包 TTS
location /tts-api/ {
proxy_pass https://openspeech.bytedance.com/;
proxy_ssl_server_name on;
proxy_set_header Host openspeech.bytedance.com;
}
# 代理:火山引擎 Ark
location /ark-api/ {
proxy_pass https://ark.cn-beijing.volces.com/;
proxy_ssl_server_name on;
proxy_set_header Host ark.cn-beijing.volces.com;
}
# 代理:阿里云百炼
location /dashscope-api/ {
proxy_pass https://dashscope.aliyuncs.com/;
proxy_ssl_server_name on;
proxy_set_header Host dashscope.aliyuncs.com;
}
# 代理:豆包 ASR WebSocket需注入鉴权 Header
location /asr-ws/ {
proxy_pass https://openspeech.bytedance.com/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host openspeech.bytedance.com;
proxy_ssl_server_name on;
# 注入豆包 ASR 鉴权 Header替换为实际值
proxy_set_header X-Api-App-Key "YOUR_DOUBAO_APP_ID";
proxy_set_header X-Api-Access-Key "YOUR_DOUBAO_ACCESS_TOKEN";
proxy_set_header X-Api-Resource-Id "volc.bigasr.sauc.duration";
}
# 静态资源缓存
location /assets/ {
expires 1y;
add_header Cache-Control "public, immutable";
add_header Cross-Origin-Opener-Policy "same-origin" always;
add_header Cross-Origin-Embedder-Policy "require-corp" always;
}
}
```
```
#### 4.A.3 启用配置并重启 Nginx
```bash
# 启用站点Ubuntu/Debian
ln -s /etc/nginx/sites-available/ai-demo.conf /etc/nginx/sites-enabled/
# 检查配置语法
nginx -t
# 重载 Nginx
systemctl reload nginx
```
#### 4.A.4 启动后端服务
后端服务需要使用进程管理器(如 PM2保持持续运行
```bash
# 安装 PM2如果未安装
npm install -g pm2
# 进入后端目录
cd /path/to/AI_Demo/server
# 启动后端服务
pm2 start index.js --name ai-demo-server
# 查看服务状态
pm2 status
# 查看日志
pm2 logs ai-demo-server
# 设置开机自启
pm2 startup
pm2 save
```
后端服务将在 `http://localhost:3001` 启动Nginx 会将 `/api/video` 请求代理到该端口。
#### 4.A.5 配置 HTTPS推荐
```bash
# 使用 Certbot 申请免费 SSL 证书
apt install certbot python3-certbot-nginx
certbot --nginx -d your-domain.com
```
---
### 方案 BNode.js + Express 部署(前后端分离)
适用于需要在 Node.js 环境中自定义响应头的场景,前后端独立部署。
#### 4.B.1 后端服务部署
后端服务已在 `server/` 目录中,需要独立运行:
```bash
# 进入后端目录
cd server
# 安装依赖
npm install
# 使用 PM2 启动服务
pm2 start index.js --name ai-demo-backend
# 设置开机自启
pm2 startup
pm2 save
```
后端服务将在 `http://localhost:3001` 启动。
#### 4.B.2 前端静态服务器
创建前端静态服务器文件 `frontend-server.js`(项目根目录):
```js
import express from 'express'
import { createProxyMiddleware } from 'http-proxy-middleware'
import { fileURLToPath } from 'url'
import path from 'path'
import crypto from 'crypto'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const app = express()
const PORT = process.env.PORT || 3000
// 全局注入 COOP/COEP 响应头FFmpeg WASM 必需)
app.use((req, res, next) => {
res.setHeader('Cross-Origin-Opener-Policy', 'same-origin')
res.setHeader('Cross-Origin-Embedder-Policy', 'require-corp')
next()
})
// 后端视频合成服务代理
app.use('/api/video', createProxyMiddleware({
target: 'http://localhost:3001',
changeOrigin: true,
timeout: 300000, // 5分钟超时
}))
// 第三方 API 代理
app.use('/tts-api', createProxyMiddleware({
target: 'https://openspeech.bytedance.com',
changeOrigin: true,
pathRewrite: { '^/tts-api': '' }
}))
app.use('/ark-api', createProxyMiddleware({
target: 'https://ark.cn-beijing.volces.com',
changeOrigin: true,
pathRewrite: { '^/ark-api': '' }
}))
app.use('/dashscope-api', createProxyMiddleware({
target: 'https://dashscope.aliyuncs.com',
changeOrigin: true,
pathRewrite: { '^/dashscope-api': '' }
}))
app.use('/asr-ws', createProxyMiddleware({
target: 'wss://openspeech.bytedance.com',
changeOrigin: true,
ws: true,
pathRewrite: { '^/asr-ws': '' },
on: {
proxyReqWs: (proxyReq) => {
proxyReq.setHeader('X-Api-App-Key', process.env.DOUBAO_APP_ID)
proxyReq.setHeader('X-Api-Access-Key', process.env.DOUBAO_ACCESS_TOKEN)
proxyReq.setHeader('X-Api-Resource-Id', 'volc.bigasr.sauc.duration')
proxyReq.setHeader('X-Api-Connect-Id', crypto.randomUUID())
}
}
}))
// 静态文件服务
app.use(express.static(path.join(__dirname, 'dist')))
// Vue Router History 模式回退
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'dist', 'index.html'))
})
app.listen(PORT, () => {
console.log(`Frontend server running at http://localhost:${PORT}`)
console.log(`Backend API: http://localhost:3001`)
})
```
#### 4.B.3 安装前端服务器依赖
```bash
# 在项目根目录安装
npm install express http-proxy-middleware
```
#### 4.B.4 启动前端服务器
```bash
# 在项目根目录启动
DOUBAO_APP_ID=xxx DOUBAO_ACCESS_TOKEN=xxx pm2 start frontend-server.js --name ai-demo-frontend
# 查看两个服务的状态
pm2 status
# 设置开机自启
pm2 save
```
现在有两个服务运行:
- **前端服务**`http://localhost:3000`(提供静态文件和代理)
- **后端服务**`http://localhost:3001`(视频合成 API
---
### 方案 CEdgeOne Pages / Vercel / Netlify纯静态托管
> **注意**:此类平台**不支持服务端代理**`/tts-api`、`/ark-api`、`/dashscope-api`、`/asr-ws` 等接口将因跨域或缺少鉴权 Header 而失败。
> 建议仅用于演示或配合独立后端服务使用。
#### 部署步骤(以 Vercel 为例)
1. 将项目推送到 GitHub
2. 在 Vercel 控制台导入仓库
3. 构建命令:`npm run build`,输出目录:`dist`
4. 创建 `vercel.json` 配置 History 模式路由回退和响应头:
```json
{
"rewrites": [{ "source": "/(.*)", "destination": "/index.html" }],
"headers": [
{
"source": "/(.*)",
"headers": [
{ "key": "Cross-Origin-Opener-Policy", "value": "same-origin" },
{ "key": "Cross-Origin-Embedder-Policy", "value": "require-corp" }
]
}
]
}
```
---
## 五、部署后验证清单
### 5.1 后端服务验证
| 验证项 | 检查方法 | 预期结果 |
|--------|----------|----------|
| 后端服务运行 | `pm2 status``ps aux \| grep node` | 显示 ai-demo-server 进程 |
| 健康检查接口 | `curl http://localhost:3001/health` | 返回 `{"status":"ok"}` |
| FFmpeg 可用 | `curl http://localhost:3001/api/video/health` | 返回 `{"status":"ok","message":"视频合成服务正常运行"}` |
| 后端日志无错误 | `pm2 logs ai-demo-server` | 无报错信息 |
### 5.2 前端服务验证
| 验证项 | 检查方法 |
|--------|----------|
| 页面正常加载 | 访问首页,确认功能卡片显示正常 |
| 路由刷新不 404 | 直接访问 `/pronunciation`、`/speaking` 等子路由 |
| COOP/COEP 响应头 | 浏览器 DevTools → Network → 查看 index.html 响应头 |
| TTS 语音合成 | 进入发音练习页,测试语音播放 |
| ASR 语音识别 | 进入口语对话页,测试麦克风录音识别 |
| 作文批改 | 进入作文批改页,提交一段英文作文 |
| 试题分析 | 进入试题分析页,上传图片或输入题目 |
| 单词拼写练习 | 进入单词拼写页,测试拼写检测功能 |
### 5.3 视频合成功能验证
| 验证项 | 检查方法 |
|--------|----------|
| 前端可访问后端 | 浏览器 Network 标签查看 `/api/video/health` 请求 |
| 视频合成接口 | 在试题分析页生成视频讲解,检查是否能正常下载 |
---
## 六、常见问题排查
### Q1视频讲解页面报错 `SharedArrayBuffer is not defined`
**原因**:服务器未返回 `Cross-Origin-Opener-Policy: same-origin``Cross-Origin-Embedder-Policy: require-corp` 响应头。
**解决**:参考第二节 2.2,在 Nginx 或 Node.js 服务器中添加对应响应头。
### Q2刷新页面出现 404
**原因**Vue Router 使用 History 模式,服务器未配置路由回退。
**解决**Nginx 添加 `try_files $uri $uri/ /index.html;`Node.js 添加通配路由返回 `index.html`
### Q3API 请求跨域报错CORS
**原因**:生产环境未配置反向代理,浏览器直接请求第三方 API 被跨域拦截。
**解决**:参考第二节 2.3,在 Nginx 或 Node.js 中配置对应代理规则。
### Q4ASR 语音识别 WebSocket 连接失败
**原因**:代理未注入豆包 ASR 鉴权 Header或 WebSocket 升级配置缺失。
**解决**:确认 Nginx 配置中包含 `proxy_set_header Upgrade $http_upgrade;` 及三个 `X-Api-*` Header。
### Q5视频合成失败或接口 504 超时
**原因**:视频合成耗时较长,默认代理超时时间不足,或后端服务未启动。
**解决**
1. 检查后端服务是否运行:`pm2 status` 或 `curl http://localhost:3001/health`
2. 检查 FFmpeg 是否安装:`ffmpeg -version`
3. 增加 Nginx 超时时间(已在配置中设置为 300 秒)
4. 查看后端日志:`pm2 logs ai-demo-server`
### Q6后端服务启动失败`FFmpeg not found`
**原因**:系统未安装 FFmpeg 或未添加到环境变量。
**解决**:参考第一节 1.2,安装 FFmpeg 并配置环境变量。
### Q7视频合成返回 `Internal server error`
**原因**:可能是 FFmpeg 处理错误、临时目录权限问题或资源下载失败。
**解决**
1. 查看后端详细日志:`pm2 logs ai-demo-server`
2. 检查 `server/temp/` 目录权限:`ls -la server/temp`
3. 测试后端健康检查:`curl http://localhost:3001/api/video/health`
### Q8构建时内存不足
**原因**:项目包含 FFmpeg WASM构建产物较大。
**解决**
```bash
# 增大 Node.js 内存限制
NODE_OPTIONS=--max-old-space-size=4096 npm run build
```
---
## 七、页面路由清单
| 路由路径 | 页面名称 | 功能说明 |
|----------|----------|----------|
| `/` | 首页 | 功能导航卡片 |
| `/pronunciation` | 发音练习 | TTS 语音合成,音标学习 |
| `/speaking` | 口语对话 | ASR 语音识别AI 对话 |
| `/essay-correction` | 作文批改 | 图片/文本作文批改 |
| `/exam-analysis` | 试题分析 | 图片题目分析解答 |
| `/spell-practice` | 单词拼写 | 单词拼写练习检测 |
| `/problem-solving` | 解题指导 | AI 解题步骤指导 |
| `/question-generator` | 题目生成 | 自动生成练习题 |
| `/question-variant` | 题目变体 | 生成相似题目变体 |
| `/audio-to-text` | 语音转文字 | 音频转文本功能 |
| `/question-explanation` | 视频讲解 | 视频合成讲解(使用后端服务)|
---
## 八、依赖版本参考
### 前端依赖package.json
| 依赖包 | 版本 |
|--------|------|
| vue | ^3.5.30 |
| vue-router | ^5.0.3 |
| vite | ^8.0.0 |
| @ffmpeg/ffmpeg | ^0.12.15 |
| @ffmpeg/util | ^0.12.2 |
| axios | ^1.13.6 |
| marked | ^17.0.5 |
| pako | ^2.1.0 |
### 后端依赖server/package.json
| 依赖包 | 版本 | 用途 |
|--------|------|------|
| express | ^4.21.0 | Web 服务器框架 |
| cors | ^2.8.5 | 跨域中间件 |
| fluent-ffmpeg | ^2.1.3 | FFmpeg Node.js 封装 |
| axios | ^1.7.0 | HTTP 客户端 |
| uuid | ^10.0.0 | UUID 生成 |
---
## 九、目录结构参考
```
AI_Demo/
├── dist/ # 前端构建产物(部署此目录)
├── server/ # 后端服务
│ ├── routes/ # 路由模块
│ │ └── video.js # 视频合成 API
│ ├── temp/ # 临时文件目录(自动创建)
│ ├── index.js # 后端服务入口
│ ├── package.json # 后端依赖配置
│ └── README.md # 后端服务文档
├── src/ # 前端源码
│ ├── config/index.js # API 密钥配置(部署前确认)
│ ├── router/index.js # 路由定义
│ ├── views/ # 页面组件
│ │ ├── HomePage.vue # 首页
│ │ ├── Pronunciation.vue # 发音练习
│ │ ├── Speaking.vue # 口语对话
│ │ ├── EssayCorrection.vue # 作文批改
│ │ ├── ExamAnalysis.vue # 试题分析
│ │ ├── SpellPractice.vue # 单词拼写
│ │ ├── ProblemSolving.vue # 解题指导
│ │ ├── QuestionGenerator.vue # 题目生成
│ │ ├── QuestionVariant.vue # 题目变体
│ │ ├── AudioToText.vue # 语音转文字
│ │ └── QuestionExplanation.vue # 视频讲解
│ ├── components/ # 公共组件
│ ├── assets/ # 静态资源
│ └── MainLayout.vue # 布局组件
├── vite.config.js # 开发代理配置(生产环境需在服务器复现)
├── package.json # 前端依赖配置
└── DEPLOY.md # 本文档
```
---
## 十、后端服务详细说明
### 10.1 服务架构
后端服务基于 Express.js 构建,主要提供视频合成功能:
- **技术栈**Express.js + Fluent-FFmpeg
- **默认端口**3001
- **主要功能**:接收图片和音频 URL合成 MP4 视频文件
### 10.2 API 接口
#### POST `/api/video/compose`
合成视频接口,将多组图片和音频合成为视频。
**请求体示例**
```json
{
"slides": [
{
"imageUrl": "https://example.com/image1.png",
"audioUrl": "https://example.com/audio1.mp3"
},
{
"imageUrl": "https://example.com/image2.png",
"audioUrl": "https://example.com/audio2.mp3"
}
],
"width": 1920,
"height": 1080
}
```
**参数说明**
- `slides`(必需):幻灯片数组,每个元素包含:
- `imageUrl`:图片 URL支持 HTTP/HTTPS URL 或 base64 data URI
- `audioUrl`:音频 URLMP3 格式)
- `width`(可选):视频宽度,默认 1920
- `height`(可选):视频高度,默认 1080
**响应**
- Content-Type: `video/mp4`
- 返回合成后的 MP4 视频文件
#### GET `/api/video/health`
健康检查接口,检查 FFmpeg 服务状态。
**响应示例**
```json
{
"status": "ok",
"message": "视频合成服务正常运行",
"formats": 300
}
```
#### GET `/health`
服务健康检查接口。
**响应示例**
```json
{
"status": "ok",
"timestamp": "2024-01-01T12:00:00.000Z"
}
```
### 10.3 环境变量配置
后端服务支持以下环境变量:
| 环境变量 | 默认值 | 说明 |
|---------|--------|------|
| `PORT` | 3001 | 服务监听端口 |
使用示例:
```bash
PORT=3002 pm2 start index.js --name ai-demo-server
```
### 10.4 临时文件管理
- 后端服务在 `server/temp/` 目录下存储临时文件
- 每个视频合成任务会创建独立的子目录(使用 UUID 命名)
- 任务完成后,临时文件会自动清理
- 如遇异常中断,可手动清理 `temp/` 目录
### 10.5 性能与资源要求
**建议配置**
- **CPU**2 核以上(视频合成需要较多 CPU 资源)
- **内存**2GB 以上
- **磁盘**10GB 以上可用空间(临时文件存储)
**并发处理**
- 单个视频合成任务处理时间:约 10-60 秒(取决于片段数量和时长)
- 建议使用队列机制处理高并发请求(当前版本为同步处理)
### 10.6 日志查看
使用 PM2 查看后端服务日志:
```bash
# 查看实时日志
pm2 logs ai-demo-server
# 查看最近 100 行日志
pm2 logs ai-demo-server --lines 100
# 清空日志
pm2 flush ai-demo-server
```
日志包含:
- 服务启动信息
- FFmpeg 命令执行日志
- 视频合成进度
- 错误信息
### 10.7 监控与告警
建议监控以下指标:
- 服务进程状态PM2 监控)
- 端口 3001 响应状态(健康检查)
- 磁盘空间(`temp/` 目录)
- CPU 和内存使用率
---
## 十一、Docker 部署(可选)
### 11.1 后端服务 Dockerfile
已提供 Dockerfile 位于 `Dockerfiles/backend.Dockerfile`(如需创建):
```dockerfile
FROM node:20-alpine
# 安装 FFmpeg
RUN apk add --no-cache ffmpeg
WORKDIR /app
# 复制依赖文件
COPY server/package*.json ./
RUN npm ci --only=production
# 复制源码
COPY server/ ./
# 创建临时目录
RUN mkdir -p temp
EXPOSE 3001
CMD ["node", "index.js"]
```
### 11.2 Docker Compose 部署
创建 `docker-compose.yml`
```yaml
version: '3.8'
services:
backend:
build:
context: .
dockerfile: Dockerfiles/backend.Dockerfile
ports:
- "3001:3001"
volumes:
- ./server/temp:/app/temp
restart: unless-stopped
environment:
- PORT=3001
frontend:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./dist:/usr/share/nginx/html
- ./nginx.conf:/etc/nginx/conf.d/default.conf
depends_on:
- backend
restart: unless-stopped
```
启动:
```bash
docker-compose up -d
```
---
## 十二、安全建议
1. **HTTPS 强制**:生产环境务必启用 HTTPS
2. **API 密钥保护**:不要将 API 密钥提交到代码仓库
3. **文件上传限制**:限制视频合成的图片和音频大小
4. **频率限制**:对 `/api/video/compose` 接口添加速率限制
5. **临时文件清理**:定期检查并清理异常终止的临时文件
6. **日志审计**:记录所有视频合成请求的来源和处理结果
---
## 十三、更新与维护
### 更新前端
```bash
git pull
npm install
npm run build
# 重新部署 dist/ 目录
```
### 更新后端
```bash
cd server
git pull
npm install
pm2 restart ai-demo-server
```
### 查看服务状态
```bash
pm2 status
pm2 logs
```
---
**文档版本**v2.0
**更新日期**2024-01-01
**更新内容**:新增后端视频合成服务部署说明