支持fastapi服务

This commit is contained in:
puke
2025-10-28 01:33:36 +08:00
committed by puke
parent c387137446
commit c200761b97
28 changed files with 1854 additions and 4 deletions

48
api/schemas/__init__.py Normal file
View File

@@ -0,0 +1,48 @@
"""
API Schemas (Pydantic models)
"""
from api.schemas.base import BaseResponse, ErrorResponse
from api.schemas.llm import LLMChatRequest, LLMChatResponse
from api.schemas.tts import TTSSynthesizeRequest, TTSSynthesizeResponse
from api.schemas.image import ImageGenerateRequest, ImageGenerateResponse
from api.schemas.content import (
NarrationGenerateRequest,
NarrationGenerateResponse,
ImagePromptGenerateRequest,
ImagePromptGenerateResponse,
TitleGenerateRequest,
TitleGenerateResponse,
)
from api.schemas.video import (
VideoGenerateRequest,
VideoGenerateResponse,
VideoGenerateAsyncResponse,
)
__all__ = [
# Base
"BaseResponse",
"ErrorResponse",
# LLM
"LLMChatRequest",
"LLMChatResponse",
# TTS
"TTSSynthesizeRequest",
"TTSSynthesizeResponse",
# Image
"ImageGenerateRequest",
"ImageGenerateResponse",
# Content
"NarrationGenerateRequest",
"NarrationGenerateResponse",
"ImagePromptGenerateRequest",
"ImagePromptGenerateResponse",
"TitleGenerateRequest",
"TitleGenerateResponse",
# Video
"VideoGenerateRequest",
"VideoGenerateResponse",
"VideoGenerateAsyncResponse",
]

21
api/schemas/base.py Normal file
View File

@@ -0,0 +1,21 @@
"""
Base schemas
"""
from typing import Any, Optional
from pydantic import BaseModel
class BaseResponse(BaseModel):
"""Base API response"""
success: bool = True
message: str = "Success"
data: Optional[Any] = None
class ErrorResponse(BaseModel):
"""Error response"""
success: bool = False
message: str
error: Optional[str] = None

91
api/schemas/content.py Normal file
View File

@@ -0,0 +1,91 @@
"""
Content generation API schemas
"""
from typing import List, Optional
from pydantic import BaseModel, Field
# ============================================================================
# Narration Generation
# ============================================================================
class NarrationGenerateRequest(BaseModel):
"""Narration generation request"""
text: str = Field(..., description="Source text to generate narrations from")
n_scenes: int = Field(5, ge=1, le=20, description="Number of scenes")
min_words: int = Field(5, ge=1, le=100, description="Minimum words per narration")
max_words: int = Field(20, ge=1, le=200, description="Maximum words per narration")
class Config:
json_schema_extra = {
"example": {
"text": "Atomic Habits is about making small changes that lead to remarkable results.",
"n_scenes": 5,
"min_words": 5,
"max_words": 20
}
}
class NarrationGenerateResponse(BaseModel):
"""Narration generation response"""
success: bool = True
message: str = "Success"
narrations: List[str] = Field(..., description="Generated narrations")
# ============================================================================
# Image Prompt Generation
# ============================================================================
class ImagePromptGenerateRequest(BaseModel):
"""Image prompt generation request"""
narrations: List[str] = Field(..., description="List of narrations")
min_words: int = Field(30, ge=10, le=100, description="Minimum words per prompt")
max_words: int = Field(60, ge=10, le=200, description="Maximum words per prompt")
class Config:
json_schema_extra = {
"example": {
"narrations": [
"Small habits compound over time",
"Focus on systems, not goals"
],
"min_words": 30,
"max_words": 60
}
}
class ImagePromptGenerateResponse(BaseModel):
"""Image prompt generation response"""
success: bool = True
message: str = "Success"
image_prompts: List[str] = Field(..., description="Generated image prompts")
# ============================================================================
# Title Generation
# ============================================================================
class TitleGenerateRequest(BaseModel):
"""Title generation request"""
text: str = Field(..., description="Source text")
style: Optional[str] = Field(None, description="Title style (e.g., 'engaging', 'formal')")
class Config:
json_schema_extra = {
"example": {
"text": "Atomic Habits is about making small changes that lead to remarkable results.",
"style": "engaging"
}
}
class TitleGenerateResponse(BaseModel):
"""Title generation response"""
success: bool = True
message: str = "Success"
title: str = Field(..., description="Generated title")

31
api/schemas/image.py Normal file
View File

@@ -0,0 +1,31 @@
"""
Image generation API schemas
"""
from typing import Optional
from pydantic import BaseModel, Field
class ImageGenerateRequest(BaseModel):
"""Image generation request"""
prompt: str = Field(..., description="Image generation prompt")
width: int = Field(1024, ge=512, le=2048, description="Image width")
height: int = Field(1024, ge=512, le=2048, description="Image height")
workflow: Optional[str] = Field(None, description="Custom workflow filename")
class Config:
json_schema_extra = {
"example": {
"prompt": "A serene mountain landscape at sunset, photorealistic style",
"width": 1024,
"height": 1024
}
}
class ImageGenerateResponse(BaseModel):
"""Image generation response"""
success: bool = True
message: str = "Success"
image_path: str = Field(..., description="Path to generated image")

31
api/schemas/llm.py Normal file
View File

@@ -0,0 +1,31 @@
"""
LLM API schemas
"""
from typing import Optional
from pydantic import BaseModel, Field
class LLMChatRequest(BaseModel):
"""LLM chat request"""
prompt: str = Field(..., description="User prompt")
temperature: float = Field(0.7, ge=0.0, le=2.0, description="Temperature (0.0-2.0)")
max_tokens: int = Field(2000, ge=1, le=32000, description="Maximum tokens")
class Config:
json_schema_extra = {
"example": {
"prompt": "Explain the concept of atomic habits in 3 sentences",
"temperature": 0.7,
"max_tokens": 2000
}
}
class LLMChatResponse(BaseModel):
"""LLM chat response"""
success: bool = True
message: str = "Success"
content: str = Field(..., description="Generated response")
tokens_used: Optional[int] = Field(None, description="Tokens used (if available)")

28
api/schemas/tts.py Normal file
View File

@@ -0,0 +1,28 @@
"""
TTS API schemas
"""
from pydantic import BaseModel, Field
class TTSSynthesizeRequest(BaseModel):
"""TTS synthesis request"""
text: str = Field(..., description="Text to synthesize")
voice_id: str = Field("zh-CN-YunjianNeural", description="Voice ID")
class Config:
json_schema_extra = {
"example": {
"text": "Hello, welcome to ReelForge!",
"voice_id": "zh-CN-YunjianNeural"
}
}
class TTSSynthesizeResponse(BaseModel):
"""TTS synthesis response"""
success: bool = True
message: str = "Success"
audio_path: str = Field(..., description="Path to generated audio file")
duration: float = Field(..., description="Audio duration in seconds")

80
api/schemas/video.py Normal file
View File

@@ -0,0 +1,80 @@
"""
Video generation API schemas
"""
from typing import Optional, Literal
from pydantic import BaseModel, Field
class VideoGenerateRequest(BaseModel):
"""Video generation request"""
# === Input ===
text: str = Field(..., description="Source text for video generation")
# === Processing Mode ===
mode: Literal["generate", "fixed"] = Field(
"generate",
description="Processing mode: 'generate' (AI generates narrations) or 'fixed' (use text as-is)"
)
# === Optional Title ===
title: Optional[str] = Field(None, description="Video title (auto-generated if not provided)")
# === Basic Config ===
n_scenes: int = Field(5, ge=1, le=20, description="Number of scenes (generate mode only)")
voice_id: str = Field("zh-CN-YunjianNeural", description="TTS voice ID")
# === LLM Parameters ===
min_narration_words: int = Field(5, ge=1, le=100, description="Min narration words")
max_narration_words: int = Field(20, ge=1, le=200, description="Max narration words")
min_image_prompt_words: int = Field(30, ge=10, le=100, description="Min image prompt words")
max_image_prompt_words: int = Field(60, ge=10, le=200, description="Max image prompt words")
# === Image Parameters ===
image_width: int = Field(1024, ge=512, le=2048, description="Image width")
image_height: int = Field(1024, ge=512, le=2048, description="Image height")
image_workflow: Optional[str] = Field(None, description="Custom image workflow")
# === Video Parameters ===
video_width: int = Field(1080, ge=512, le=3840, description="Video width")
video_height: int = Field(1920, ge=512, le=3840, description="Video height")
video_fps: int = Field(30, ge=15, le=60, description="Video FPS")
# === Frame Template ===
frame_template: Optional[str] = Field(None, description="HTML template name (e.g., 'default.html')")
# === Image Style ===
prompt_prefix: Optional[str] = Field(None, description="Image style prefix")
# === BGM ===
bgm_path: Optional[str] = Field(None, description="Background music path")
bgm_volume: float = Field(0.3, ge=0.0, le=1.0, description="BGM volume (0.0-1.0)")
class Config:
json_schema_extra = {
"example": {
"text": "Atomic Habits teaches us that small changes compound over time to produce remarkable results.",
"mode": "generate",
"n_scenes": 5,
"voice_id": "zh-CN-YunjianNeural",
"title": "The Power of Atomic Habits"
}
}
class VideoGenerateResponse(BaseModel):
"""Video generation response (synchronous)"""
success: bool = True
message: str = "Success"
video_url: str = Field(..., description="URL to access generated video")
duration: float = Field(..., description="Video duration in seconds")
file_size: int = Field(..., description="File size in bytes")
class VideoGenerateAsyncResponse(BaseModel):
"""Video generation async response"""
success: bool = True
message: str = "Task created successfully"
task_id: str = Field(..., description="Task ID for tracking progress")