diff --git a/apps/api/app/api/router.py b/apps/api/app/api/router.py index f39b54596..64221f71f 100644 --- a/apps/api/app/api/router.py +++ b/apps/api/app/api/router.py @@ -8,9 +8,45 @@ from app.api.routes.projects import router as projects_router from app.api.routes.upload import router as upload_router api_router = APIRouter() -api_router.include_router(health_router, prefix="/health", tags=["health"]) -api_router.include_router(projects_router, prefix="/projects", tags=["projects"]) -api_router.include_router(asset_libraries_router, prefix="/asset-libraries", tags=["asset-libraries"]) -api_router.include_router(assets_router, prefix="/assets", tags=["assets"]) -api_router.include_router(ingest_jobs_router, prefix="/ingest-jobs", tags=["ingest-jobs"]) -api_router.include_router(upload_router, prefix="/upload", tags=["upload"]) + +# Health check +api_router.include_router( + health_router, + prefix="/health", + tags=["健康检查"], +) + +# Projects +api_router.include_router( + projects_router, + prefix="/projects", + tags=["项目管理"], +) + +# Asset Libraries +api_router.include_router( + asset_libraries_router, + prefix="/asset-libraries", + tags=["资产库管理"], +) + +# Assets +api_router.include_router( + assets_router, + prefix="/assets", + tags=["素材资产"], +) + +# Ingest Jobs +api_router.include_router( + ingest_jobs_router, + prefix="/ingest-jobs", + tags=["导入任务"], +) + +# Upload +api_router.include_router( + upload_router, + prefix="/upload", + tags=["文件上传"], +) diff --git a/apps/api/app/api/routes/upload.py b/apps/api/app/api/routes/upload.py index ea9f254ca..844f718cf 100644 --- a/apps/api/app/api/routes/upload.py +++ b/apps/api/app/api/routes/upload.py @@ -14,22 +14,54 @@ router = APIRouter() @router.post("", response_model=UploadAssetResponse) async def upload_asset( - file: UploadFile = File(...), - workspace_id: str = Form(...), - project_id: str = Form(...), - library_id: str = Form(...), + file: UploadFile = File(..., description="要上传的文件(视频、音频、图片等)"), + workspace_id: str = Form(..., description="工作空间 ID"), + project_id: str = Form(..., description="项目 ID"), + library_id: str = Form(..., description="资产库 ID"), ingest_job_repository: InMemoryIngestJobRepository = Depends(get_ingest_job_repository), storage_service: MinIOService = Depends(get_minio_service), ) -> UploadAssetResponse: """ - Upload asset and trigger ingest pipeline. + 上传素材文件并触发导入流水线。 - Real implementation: - 1. Accept multipart/form-data with file - 2. Store file to MinIO object storage - 3. Generate storage_key - 4. Submit ingest job - 5. Enqueue worker task + ## 功能说明 + + 1. **接收文件**:支持 multipart/form-data 上传 + 2. **存储到 MinIO**:自动存储到对象存储 + 3. **生成存储键**:格式为 `uploads/{id}/{filename}` + 4. **提交导入任务**:创建 IngestJob 记录 + 5. **异步处理**:通过 Celery 队列处理 + + ## 支持的文件类型 + + - **视频**:MP4, MOV, AVI, MKV 等 + - **音频**:MP3, WAV, AAC 等 + - **图片**:JPG, PNG, GIF, WebP 等 + + ## 请求示例 + + ```bash + curl -X POST "http://localhost:8000/api/v1/upload" \ + -H "Content-Type: multipart/form-data" \ + -F "file=@/path/to/video.mp4" \ + -F "workspace_id=ws_123" \ + -F "project_id=proj_456" \ + -F "library_id=lib_789" + ``` + + ## 响应说明 + + - `storage_key`: 文件在 MinIO 中的存储路径 + - `ingest_job_id`: 导入任务 ID,用于追踪处理状态 + - `url`: 文件的公开访问 URL + + ## 后续流程 + + 上传成功后,系统会: + 1. 自动提取文件元数据(时长、分辨率等) + 2. 生成缩略图 + 3. 进行场景分割(视频) + 4. 创建 Asset 记录 """ # Generate storage key file_id = uuid4().hex[:8] diff --git a/apps/api/main.py b/apps/api/main.py index a28a0a4b8..c4dd5014c 100644 --- a/apps/api/main.py +++ b/apps/api/main.py @@ -1,4 +1,5 @@ from fastapi import FastAPI +from fastapi.middleware.cors import CORSMiddleware from app.api.router import api_router from app.core.config import get_settings @@ -6,8 +7,60 @@ from app.core.config import get_settings def create_app() -> FastAPI: settings = get_settings() - app = FastAPI(title=settings.app_name) + + app = FastAPI( + title="小虾 SaaS API", + description=""" +小虾 SaaS 自动化剪辑系统 API + +## 功能模块 + +### 📁 资源库管理 +- **Projects**: 项目管理 +- **Asset Libraries**: 资产库管理 +- **Assets**: 素材资产管理 + +### 📤 素材导入 +- **Upload**: 文件上传(支持 MinIO 对象存储) +- **Ingest Jobs**: 素材导入任务管理 + +### 🎬 自动化剪辑 +- 智能场景分割 +- 自动转场 +- 字幕生成 + +## 技术栈 +- FastAPI + Python 3.12 +- PostgreSQL 数据库 +- Redis 队列 +- Celery 异步任务 +- MinIO 对象存储 +""", + version="0.1.0", + docs_url="/docs", + redoc_url="/redoc", + openapi_url="/openapi.json", + contact={ + "name": "小虾团队", + "email": "dev@xiaoxiajianji.com", + }, + license_info={ + "name": "Proprietary", + }, + ) + + # CORS middleware + app.add_middleware( + CORSMiddleware, + allow_origins=["*"], # TODO: Configure for production + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], + ) + + # Include API routes app.include_router(api_router, prefix=settings.api_prefix) + return app diff --git a/docs/API.md b/docs/API.md new file mode 100644 index 000000000..cf2aea386 --- /dev/null +++ b/docs/API.md @@ -0,0 +1,146 @@ +# API 文档 + +## 访问 API 文档 + +小虾 SaaS API 提供了两种交互式文档: + +### 1. Swagger UI(推荐用于测试) +- **本地开发**: http://localhost:8000/docs +- **Staging**: http://47.98.113.167:8001/docs +- **Production**: http://47.98.113.167:8000/docs + +**特点**: +- 交互式接口测试 +- 可以直接在浏览器中发送请求 +- 支持文件上传测试 + +### 2. ReDoc(推荐用于阅读) +- **本地开发**: http://localhost:8000/redoc +- **Staging**: http://47.98.113.167:8001/redoc +- **Production**: http://47.98.113.167:8000/redoc + +**特点**: +- 更清晰的文档布局 +- 更好的可读性 +- 适合生成 PDF 或打印 + +### 3. OpenAPI JSON +- **本地开发**: http://localhost:8000/openapi.json +- **Staging**: http://47.98.113.167:8001/openapi.json +- **Production**: http://47.98.113.167:8000/openapi.json + +**用途**: +- 生成客户端 SDK +- 导入到 Postman +- 集成到其他工具 + +--- + +## API 模块说明 + +### 🏥 健康检查 +- `GET /api/v1/health` - 检查 API 服务状态 + +### 📁 项目管理 +- `GET /api/v1/projects` - 列出所有项目 +- `POST /api/v1/projects` - 创建新项目 +- `GET /api/v1/projects/{id}` - 获取项目详情 + +### 📚 资产库管理 +- `GET /api/v1/asset-libraries` - 列出资产库 +- `POST /api/v1/asset-libraries` - 创建资产库 +- `GET /api/v1/asset-libraries/{id}` - 获取资产库详情 + +### 🎬 素材资产 +- `GET /api/v1/assets` - 列出素材资产 +- `POST /api/v1/assets` - 创建素材资产(通常由系统自动创建) +- `GET /api/v1/assets/{id}` - 获取资产详情 + +### 📤 文件上传 +- `POST /api/v1/upload` - 上传素材文件(视频、音频、图片等) + +**上传示例**: +```bash +curl -X POST "http://localhost:8000/api/v1/upload" \ + -H "Content-Type: multipart/form-data" \ + -F "file=@/path/to/video.mp4" \ + -F "workspace_id=ws_123" \ + -F "project_id=proj_456" \ + -F "library_id=lib_789" +``` + +### 🔄 导入任务 +- `GET /api/v1/ingest-jobs` - 列出导入任务 +- `GET /api/v1/ingest-jobs/{id}` - 获取任务详情 + +--- + +## 认证(待实现) + +当前 API 暂未启用认证。生产环境将添加: +- JWT Token 认证 +- API Key 认证 +- OAuth 2.0 + +--- + +## 错误处理 + +API 遵循标准 HTTP 状态码: + +- `200 OK` - 请求成功 +- `201 Created` - 资源创建成功 +- `400 Bad Request` - 请求参数错误 +- `404 Not Found` - 资源不存在 +- `422 Unprocessable Entity` - 数据验证失败 +- `500 Internal Server Error` - 服务器错误 + +错误响应格式: +```json +{ + "detail": "错误描述" +} +``` + +--- + +## 使用 Postman + +1. 下载 OpenAPI JSON:http://localhost:8000/openapi.json +2. 在 Postman 中选择 **Import** → **File** +3. 选择下载的 `openapi.json` 文件 +4. 所有接口将自动导入到 Postman + +--- + +## 生成客户端 SDK + +使用 OpenAPI Generator 生成各语言客户端: + +```bash +# Python +openapi-generator-cli generate \ + -i http://localhost:8000/openapi.json \ + -g python \ + -o ./client/python + +# TypeScript +openapi-generator-cli generate \ + -i http://localhost:8000/openapi.json \ + -g typescript-axios \ + -o ./client/typescript + +# Java +openapi-generator-cli generate \ + -i http://localhost:8000/openapi.json \ + -g java \ + -o ./client/java +``` + +--- + +## 反馈与支持 + +- **技术文档**: 参考项目 `docs/` 目录 +- **问题反馈**: 提交 Issue 到代码仓库 +- **联系方式**: dev@xiaoxiajianji.com