API接口支持模板自定义参数
This commit is contained in:
@@ -18,7 +18,7 @@ from fastapi import APIRouter, HTTPException
|
|||||||
from loguru import logger
|
from loguru import logger
|
||||||
|
|
||||||
from api.dependencies import PixelleVideoDep
|
from api.dependencies import PixelleVideoDep
|
||||||
from api.schemas.frame import FrameRenderRequest, FrameRenderResponse
|
from api.schemas.frame import FrameRenderRequest, FrameRenderResponse, TemplateParamsResponse
|
||||||
from pixelle_video.services.frame_html import HTMLFrameGenerator
|
from pixelle_video.services.frame_html import HTMLFrameGenerator
|
||||||
from pixelle_video.utils.template_util import parse_template_size, resolve_template_path
|
from pixelle_video.utils.template_util import parse_template_size, resolve_template_path
|
||||||
|
|
||||||
@@ -82,3 +82,80 @@ async def render_frame(
|
|||||||
logger.error(f"Frame render error: {e}")
|
logger.error(f"Frame render error: {e}")
|
||||||
raise HTTPException(status_code=500, detail=str(e))
|
raise HTTPException(status_code=500, detail=str(e))
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/template/params", response_model=TemplateParamsResponse)
|
||||||
|
async def get_template_params(
|
||||||
|
template: str
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Get custom parameters for a template
|
||||||
|
|
||||||
|
Returns the custom parameters defined in the template HTML file.
|
||||||
|
These parameters can be passed via `template_params` in video generation requests.
|
||||||
|
|
||||||
|
Template parameters are defined using syntax: `{{param_name:type=default}}`
|
||||||
|
|
||||||
|
Supported types:
|
||||||
|
- `text`: String input
|
||||||
|
- `number`: Numeric input
|
||||||
|
- `color`: Color picker (hex format)
|
||||||
|
- `bool`: Boolean checkbox
|
||||||
|
|
||||||
|
Example template syntax:
|
||||||
|
```html
|
||||||
|
<div style="color: {{accent_color:color=#ff0000}}">
|
||||||
|
{{custom_text:text=Hello World}}
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
Args:
|
||||||
|
template: Template path (e.g., '1080x1920/image_default.html')
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Template parameters with their types, defaults, and labels
|
||||||
|
|
||||||
|
Example response:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"template": "1080x1920/image_default.html",
|
||||||
|
"media_width": 1080,
|
||||||
|
"media_height": 1440,
|
||||||
|
"params": {
|
||||||
|
"accent_color": {
|
||||||
|
"type": "color",
|
||||||
|
"default": "#ff0000",
|
||||||
|
"label": "accent_color"
|
||||||
|
},
|
||||||
|
"background": {
|
||||||
|
"type": "text",
|
||||||
|
"default": "https://example.com/bg.jpg",
|
||||||
|
"label": "background"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
logger.info(f"Get template params: {template}")
|
||||||
|
|
||||||
|
# Resolve template path
|
||||||
|
template_path = resolve_template_path(template)
|
||||||
|
|
||||||
|
# Create generator and parse parameters
|
||||||
|
generator = HTMLFrameGenerator(template_path)
|
||||||
|
params = generator.parse_template_parameters()
|
||||||
|
media_width, media_height = generator.get_media_size()
|
||||||
|
|
||||||
|
return TemplateParamsResponse(
|
||||||
|
template=template,
|
||||||
|
media_width=media_width,
|
||||||
|
media_height=media_height,
|
||||||
|
params=params
|
||||||
|
)
|
||||||
|
|
||||||
|
except FileNotFoundError:
|
||||||
|
raise HTTPException(status_code=404, detail=f"Template not found: {template}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Get template params error: {e}")
|
||||||
|
raise HTTPException(status_code=500, detail=str(e))
|
||||||
|
|
||||||
|
|||||||
@@ -151,6 +151,10 @@ async def generate_video_sync(
|
|||||||
logger.warning("voice_id parameter is deprecated, please use tts_workflow instead")
|
logger.warning("voice_id parameter is deprecated, please use tts_workflow instead")
|
||||||
video_params["voice_id"] = request_body.voice_id
|
video_params["voice_id"] = request_body.voice_id
|
||||||
|
|
||||||
|
# Add custom template parameters if specified
|
||||||
|
if request_body.template_params:
|
||||||
|
video_params["template_params"] = request_body.template_params
|
||||||
|
|
||||||
# Call video generator service
|
# Call video generator service
|
||||||
result = await pixelle_video.generate_video(**video_params)
|
result = await pixelle_video.generate_video(**video_params)
|
||||||
|
|
||||||
@@ -252,6 +256,10 @@ async def generate_video_async(
|
|||||||
logger.warning("voice_id parameter is deprecated, please use tts_workflow instead")
|
logger.warning("voice_id parameter is deprecated, please use tts_workflow instead")
|
||||||
video_params["voice_id"] = request_body.voice_id
|
video_params["voice_id"] = request_body.voice_id
|
||||||
|
|
||||||
|
# Add custom template parameters if specified
|
||||||
|
if request_body.template_params:
|
||||||
|
video_params["template_params"] = request_body.template_params
|
||||||
|
|
||||||
result = await pixelle_video.generate_video(**video_params)
|
result = await pixelle_video.generate_video(**video_params)
|
||||||
|
|
||||||
# Get file size
|
# Get file size
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
Frame/Template rendering API schemas
|
Frame/Template rendering API schemas
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Optional
|
from typing import Optional, Dict, Any, List
|
||||||
from pydantic import BaseModel, Field
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
|
|
||||||
@@ -47,3 +47,23 @@ class FrameRenderResponse(BaseModel):
|
|||||||
width: int = Field(..., description="Frame width in pixels")
|
width: int = Field(..., description="Frame width in pixels")
|
||||||
height: int = Field(..., description="Frame height in pixels")
|
height: int = Field(..., description="Frame height in pixels")
|
||||||
|
|
||||||
|
|
||||||
|
class TemplateParamConfig(BaseModel):
|
||||||
|
"""Single template parameter configuration"""
|
||||||
|
type: str = Field(..., description="Parameter type: 'text', 'number', 'color', 'bool'")
|
||||||
|
default: Any = Field(..., description="Default value")
|
||||||
|
label: str = Field(..., description="Display label for the parameter")
|
||||||
|
|
||||||
|
|
||||||
|
class TemplateParamsResponse(BaseModel):
|
||||||
|
"""Template parameters response"""
|
||||||
|
success: bool = True
|
||||||
|
message: str = "Success"
|
||||||
|
template: str = Field(..., description="Template path")
|
||||||
|
media_width: int = Field(..., description="Media width from template meta tags")
|
||||||
|
media_height: int = Field(..., description="Media height from template meta tags")
|
||||||
|
params: Dict[str, TemplateParamConfig] = Field(
|
||||||
|
default_factory=dict,
|
||||||
|
description="Custom parameters defined in template. Key is parameter name, value is config."
|
||||||
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
Video generation API schemas
|
Video generation API schemas
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Optional, Literal
|
from typing import Optional, Literal, Dict, Any
|
||||||
from pydantic import BaseModel, Field
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
|
|
||||||
@@ -69,6 +69,13 @@ class VideoGenerateRequest(BaseModel):
|
|||||||
description="HTML template path with size (e.g., '1080x1920/default.html'). Video size is auto-determined from template."
|
description="HTML template path with size (e.g., '1080x1920/default.html'). Video size is auto-determined from template."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# === Template Custom Parameters ===
|
||||||
|
template_params: Optional[Dict[str, Any]] = Field(
|
||||||
|
None,
|
||||||
|
description="Custom template parameters (e.g., {'accent_color': '#ff0000', 'background': 'url'}). "
|
||||||
|
"Available parameters depend on the template. Use GET /api/templates/{template_path}/params to discover them."
|
||||||
|
)
|
||||||
|
|
||||||
# === Image Style ===
|
# === Image Style ===
|
||||||
prompt_prefix: Optional[str] = Field(None, description="Image style prefix")
|
prompt_prefix: Optional[str] = Field(None, description="Image style prefix")
|
||||||
|
|
||||||
@@ -82,7 +89,11 @@ class VideoGenerateRequest(BaseModel):
|
|||||||
"text": "Atomic Habits teaches us that small changes compound over time to produce remarkable results.",
|
"text": "Atomic Habits teaches us that small changes compound over time to produce remarkable results.",
|
||||||
"mode": "generate",
|
"mode": "generate",
|
||||||
"n_scenes": 5,
|
"n_scenes": 5,
|
||||||
"voice_id": "[Chinese] zh-CN Yunjian",
|
"frame_template": "1080x1920/image_default.html",
|
||||||
|
"template_params": {
|
||||||
|
"accent_color": "#3498db",
|
||||||
|
"background": "https://example.com/custom-bg.jpg"
|
||||||
|
},
|
||||||
"title": "The Power of Atomic Habits"
|
"title": "The Power of Atomic Habits"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user