video-flow-b/docs/video-edit-api-specification.md
2025-10-27 15:48:42 +08:00

626 lines
15 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.

# 🎬 Video Edit API 完整规范文档
## 📋 概述
本文档为video-flow-b视频编辑功能的后端API提供完整的实现规范包括RESTful API设计、数据结构定义、认证机制、数据库设计等为后端开发团队提供详细的实现指南。
## 🏗️ 系统架构
### 技术栈建议
- **后端框架**: FastAPI (Python) / Express.js (Node.js) / Spring Boot (Java)
- **数据库**: PostgreSQL (主数据库) + Redis (缓存)
- **认证**: JWT Token
- **文件存储**: AWS S3 / 阿里云OSS
- **消息队列**: Redis / RabbitMQ (用于异步处理)
### 服务架构
```
Frontend (React)
↓ HTTP/HTTPS
API Gateway
Video Edit Service
Database (PostgreSQL) + Cache (Redis)
```
## 🗄️ 数据库设计
### 1. 编辑点表 (edit_points)
```sql
CREATE TABLE edit_points (
id VARCHAR(50) PRIMARY KEY,
video_id VARCHAR(100) NOT NULL,
project_id VARCHAR(100) NOT NULL,
user_id INTEGER NOT NULL,
position_x FLOAT NOT NULL CHECK (position_x >= 0 AND position_x <= 100),
position_y FLOAT NOT NULL CHECK (position_y >= 0 AND position_y <= 100),
timestamp FLOAT NOT NULL CHECK (timestamp >= 0),
description TEXT DEFAULT '',
status VARCHAR(20) DEFAULT 'pending' CHECK (status IN ('pending', 'edited', 'processing', 'completed', 'failed')),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
-- 索引
INDEX idx_edit_points_video_project (video_id, project_id),
INDEX idx_edit_points_user (user_id),
INDEX idx_edit_points_status (status),
INDEX idx_edit_points_created (created_at DESC),
-- 外键约束
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
);
```
### 2. 编辑历史表 (edit_point_history)
```sql
CREATE TABLE edit_point_history (
id SERIAL PRIMARY KEY,
edit_point_id VARCHAR(50) NOT NULL,
action VARCHAR(20) NOT NULL CHECK (action IN ('created', 'updated', 'deleted', 'submitted')),
old_data JSONB,
new_data JSONB,
user_id INTEGER NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
-- 索引
INDEX idx_history_edit_point (edit_point_id),
INDEX idx_history_user (user_id),
INDEX idx_history_created (created_at DESC),
-- 外键约束
FOREIGN KEY (edit_point_id) REFERENCES edit_points(id) ON DELETE CASCADE,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
```
### 3. 编辑任务队列表 (edit_tasks)
```sql
CREATE TABLE edit_tasks (
id SERIAL PRIMARY KEY,
edit_point_id VARCHAR(50) NOT NULL,
task_type VARCHAR(20) NOT NULL DEFAULT 'edit_request',
priority INTEGER DEFAULT 0,
status VARCHAR(20) DEFAULT 'pending' CHECK (status IN ('pending', 'processing', 'completed', 'failed')),
payload JSONB NOT NULL,
result JSONB,
error_message TEXT,
retry_count INTEGER DEFAULT 0,
max_retries INTEGER DEFAULT 3,
scheduled_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
started_at TIMESTAMP,
completed_at TIMESTAMP,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
-- 索引
INDEX idx_tasks_status (status),
INDEX idx_tasks_scheduled (scheduled_at),
INDEX idx_tasks_edit_point (edit_point_id),
-- 外键约束
FOREIGN KEY (edit_point_id) REFERENCES edit_points(id) ON DELETE CASCADE
);
```
## 🔌 API 端点规范
### 基础配置
- **Base URL**: `https://api.smartvideo.py.qikongjian.com/v1`
- **Content-Type**: `application/json`
- **认证方式**: Bearer Token (JWT)
### 1. 获取编辑点列表
```http
GET /video-edit/edit-points
```
**查询参数:**
```typescript
interface GetEditPointsQuery {
video_id: string; // 必需视频ID
project_id: string; // 必需项目ID
offset?: number; // 可选偏移量默认0
limit?: number; // 可选限制数量默认50最大100
status?: EditPointStatus; // 可选:状态筛选
sort?: 'created_at' | 'updated_at' | 'timestamp'; // 可选:排序字段
order?: 'asc' | 'desc'; // 可选排序方向默认desc
}
```
**响应格式:**
```typescript
interface GetEditPointsResponse {
code: number; // 状态码0表示成功
successful: boolean; // 是否成功
message: string; // 响应消息
data: {
edit_points: EditPoint[];
total_count: number;
has_more: boolean;
pagination: {
offset: number;
limit: number;
total: number;
};
};
}
```
**示例请求:**
```bash
curl -X GET "https://api.smartvideo.py.qikongjian.com/v1/video-edit/edit-points?video_id=video123&project_id=proj456&limit=20" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json"
```
### 2. 创建编辑点
```http
POST /video-edit/edit-points
```
**请求体:**
```typescript
interface CreateEditPointRequest {
video_id: string; // 必需视频ID
project_id: string; // 必需项目ID
position_x: number; // 必需X坐标百分比 (0-100)
position_y: number; // 必需Y坐标百分比 (0-100)
timestamp: number; // 必需:时间戳(秒)
description?: string; // 可选:编辑描述
status?: EditPointStatus; // 可选初始状态默认pending
}
```
**响应格式:**
```typescript
interface CreateEditPointResponse {
code: number;
successful: boolean;
message: string;
data: EditPoint;
}
```
**示例请求:**
```bash
curl -X POST "https://api.smartvideo.py.qikongjian.com/v1/video-edit/edit-points" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"video_id": "video123",
"project_id": "proj456",
"position_x": 50.5,
"position_y": 30.2,
"timestamp": 15.5,
"description": "需要在这里添加特效"
}'
```
### 3. 更新编辑点
```http
PUT /video-edit/edit-points/{edit_point_id}
```
**路径参数:**
- `edit_point_id`: 编辑点ID
**请求体:**
```typescript
interface UpdateEditPointRequest {
description?: string; // 可选:编辑描述
status?: EditPointStatus; // 可选:状态
position_x?: number; // 可选X坐标百分比
position_y?: number; // 可选Y坐标百分比
}
```
**响应格式:**
```typescript
interface UpdateEditPointResponse {
code: number;
successful: boolean;
message: string;
data: EditPoint;
}
```
### 4. 删除编辑点
```http
DELETE /video-edit/edit-points/{edit_point_id}
```
**路径参数:**
- `edit_point_id`: 编辑点ID
**响应格式:**
```typescript
interface DeleteEditPointResponse {
code: number;
successful: boolean;
message: string;
data: null;
}
```
### 5. 批量删除编辑点
```http
POST /video-edit/edit-points/batch-delete
```
**请求体:**
```typescript
interface BatchDeleteRequest {
edit_point_ids: string[]; // 必需要删除的编辑点ID列表
}
```
### 6. 提交编辑请求
```http
POST /video-edit/edit-points/{edit_point_id}/submit
```
**路径参数:**
- `edit_point_id`: 编辑点ID
**响应格式:**
```typescript
interface SubmitEditResponse {
code: number;
successful: boolean;
message: string;
data: {
task_id: string; // 任务ID用于跟踪处理状态
estimated_duration: number; // 预估处理时间(秒)
};
}
```
### 7. 获取编辑统计
```http
GET /video-edit/stats
```
**查询参数:**
```typescript
interface GetStatsQuery {
project_id?: string; // 可选项目ID筛选
video_id?: string; // 可选视频ID筛选
date_from?: string; // 可选:开始日期 (ISO 8601)
date_to?: string; // 可选:结束日期 (ISO 8601)
}
```
**响应格式:**
```typescript
interface GetStatsResponse {
code: number;
successful: boolean;
message: string;
data: {
total_edit_points: number;
status_breakdown: {
pending: number;
edited: number;
processing: number;
completed: number;
failed: number;
};
daily_stats: Array<{
date: string;
count: number;
}>;
};
}
```
## 🔐 认证和权限控制
### JWT Token 结构
```typescript
interface JWTPayload {
user_id: number;
username: string;
email: string;
role: 'admin' | 'user' | 'viewer';
permissions: string[];
exp: number; // 过期时间戳
iat: number; // 签发时间戳
}
```
### 权限级别
- **admin**: 所有操作权限
- **user**: 可以创建、编辑、删除自己的编辑点
- **viewer**: 只能查看编辑点
### 权限检查中间件
```python
# FastAPI 示例
from fastapi import Depends, HTTPException, status
from fastapi.security import HTTPBearer
security = HTTPBearer()
async def verify_token(token: str = Depends(security)):
try:
payload = jwt.decode(token.credentials, SECRET_KEY, algorithms=["HS256"])
return payload
except jwt.ExpiredSignatureError:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Token has expired"
)
except jwt.JWTError:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid token"
)
async def check_edit_permission(
edit_point_id: str,
current_user: dict = Depends(verify_token)
):
# 检查用户是否有权限编辑该编辑点
edit_point = await get_edit_point(edit_point_id)
if not edit_point:
raise HTTPException(status_code=404, detail="Edit point not found")
if current_user["role"] != "admin" and edit_point.user_id != current_user["user_id"]:
raise HTTPException(status_code=403, detail="Permission denied")
return edit_point
```
## 📊 数据类型定义
### TypeScript 接口定义
```typescript
// 编辑点状态枚举
enum EditPointStatus {
PENDING = 'pending',
EDITED = 'edited',
PROCESSING = 'processing',
COMPLETED = 'completed',
FAILED = 'failed'
}
// 编辑点位置
interface EditPointPosition {
x: number; // X坐标百分比 (0-100)
y: number; // Y坐标百分比 (0-100)
}
// 编辑点主数据结构
interface EditPoint {
id: string; // 编辑点唯一ID
video_id: string; // 视频ID
project_id: string; // 项目ID
user_id: number; // 用户ID
position_x: number; // X坐标百分比
position_y: number; // Y坐标百分比
timestamp: number; // 视频时间戳(秒)
description: string; // 编辑描述
status: EditPointStatus; // 状态
created_at: string; // 创建时间 (ISO 8601)
updated_at: string; // 更新时间 (ISO 8601)
}
// API 通用响应格式
interface ApiResponse<T = any> {
code: number; // 状态码0表示成功
successful: boolean; // 是否成功
message: string; // 响应消息
data: T; // 响应数据
timestamp?: string; // 响应时间戳
request_id?: string; // 请求ID用于追踪
}
// 分页信息
interface PaginationInfo {
offset: number; // 偏移量
limit: number; // 限制数量
total: number; // 总数量
has_more: boolean; // 是否有更多数据
}
// 错误详情
interface ErrorDetail {
field?: string; // 错误字段
code: string; // 错误代码
message: string; // 错误消息
}
```
## ⚠️ 错误码定义
### HTTP 状态码
- `200`: 成功
- `201`: 创建成功
- `400`: 请求参数错误
- `401`: 未认证
- `403`: 权限不足
- `404`: 资源不存在
- `409`: 资源冲突
- `422`: 数据验证失败
- `429`: 请求过于频繁
- `500`: 服务器内部错误
- `503`: 服务不可用
### 业务错误码
```typescript
enum BusinessErrorCode {
// 通用错误 (1000-1099)
INVALID_PARAMETER = 1001,
MISSING_PARAMETER = 1002,
INVALID_FORMAT = 1003,
// 认证错误 (1100-1199)
TOKEN_EXPIRED = 1101,
TOKEN_INVALID = 1102,
PERMISSION_DENIED = 1103,
// 编辑点错误 (1200-1299)
EDIT_POINT_NOT_FOUND = 1201,
EDIT_POINT_LIMIT_EXCEEDED = 1202,
INVALID_POSITION = 1203,
INVALID_TIMESTAMP = 1204,
// 视频错误 (1300-1399)
VIDEO_NOT_FOUND = 1301,
VIDEO_NOT_ACCESSIBLE = 1302,
// 项目错误 (1400-1499)
PROJECT_NOT_FOUND = 1401,
PROJECT_NOT_ACCESSIBLE = 1402,
// 系统错误 (1500-1599)
DATABASE_ERROR = 1501,
EXTERNAL_SERVICE_ERROR = 1502,
RATE_LIMIT_EXCEEDED = 1503
}
```
## 🚀 部署和运维
### 环境变量配置
```bash
# 数据库配置
DATABASE_URL=postgresql://user:password@localhost:5432/video_flow
REDIS_URL=redis://localhost:6379/0
# JWT配置
JWT_SECRET_KEY=your-super-secret-key
JWT_ALGORITHM=HS256
JWT_EXPIRE_HOURS=24
# 服务配置
API_HOST=0.0.0.0
API_PORT=8000
DEBUG=false
LOG_LEVEL=INFO
# 外部服务
S3_BUCKET=video-edit-storage
S3_ACCESS_KEY=your-access-key
S3_SECRET_KEY=your-secret-key
# 限流配置
RATE_LIMIT_REQUESTS=100
RATE_LIMIT_WINDOW=60
```
### Docker 部署
```dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
```
### 监控和日志
- **健康检查**: `GET /health`
- **指标监控**: Prometheus + Grafana
- **日志收集**: ELK Stack
- **错误追踪**: Sentry
## 📈 性能优化建议
### 数据库优化
1. **索引策略**: 为常用查询字段创建复合索引
2. **分页优化**: 使用游标分页替代偏移分页
3. **连接池**: 配置合适的数据库连接池大小
4. **读写分离**: 读操作使用只读副本
### 缓存策略
1. **Redis缓存**: 缓存热点数据和查询结果
2. **CDN**: 静态资源使用CDN加速
3. **应用缓存**: 内存中缓存频繁访问的数据
### API优化
1. **批量操作**: 支持批量创建、更新、删除
2. **字段选择**: 支持指定返回字段减少数据传输
3. **压缩**: 启用gzip压缩
4. **限流**: 实现智能限流防止滥用
## 🧪 测试策略
### 单元测试
```python
import pytest
from fastapi.testclient import TestClient
def test_create_edit_point():
response = client.post("/video-edit/edit-points", json={
"video_id": "test-video",
"project_id": "test-project",
"position_x": 50.0,
"position_y": 30.0,
"timestamp": 15.5,
"description": "Test edit point"
})
assert response.status_code == 201
assert response.json()["successful"] == True
```
### 集成测试
- API端点完整性测试
- 数据库事务测试
- 认证授权测试
- 错误处理测试
### 性能测试
- 负载测试:模拟高并发请求
- 压力测试:测试系统极限
- 稳定性测试:长时间运行测试
## 📝 开发指南
### 开发环境搭建
1. 克隆代码仓库
2. 安装依赖:`pip install -r requirements.txt`
3. 配置环境变量
4. 初始化数据库:`alembic upgrade head`
5. 启动开发服务器:`uvicorn main:app --reload`
### 代码规范
- 使用 Black 进行代码格式化
- 使用 flake8 进行代码检查
- 使用 mypy 进行类型检查
- 遵循 PEP 8 编码规范
### Git 工作流
- 使用 Git Flow 分支模型
- 提交信息遵循 Conventional Commits
- 代码审查必须通过才能合并
- 自动化 CI/CD 流程
---
## 📞 技术支持
如有任何技术问题或需要进一步的实现指导,请联系开发团队。
**文档版本**: v1.0.0
**最后更新**: 2024-09-19
**维护者**: video-flow-b 开发团队