From f3e0d0d771f201d699d4a2c08e7e175b2955f313 Mon Sep 17 00:00:00 2001
From: puke <1129090915@qq.com>
Date: Wed, 17 Dec 2025 10:58:27 +0800
Subject: [PATCH] =?UTF-8?q?API=E6=8E=A5=E5=8F=A3=E6=94=AF=E6=8C=81?=
=?UTF-8?q?=E6=A8=A1=E6=9D=BF=E8=87=AA=E5=AE=9A=E4=B9=89=E5=8F=82=E6=95=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
api/routers/frame.py | 79 +++++++++++++++++++++++++++++++++++++++++++-
api/routers/video.py | 8 +++++
api/schemas/frame.py | 22 +++++++++++-
api/schemas/video.py | 15 +++++++--
4 files changed, 120 insertions(+), 4 deletions(-)
diff --git a/api/routers/frame.py b/api/routers/frame.py
index e345f87..1aff672 100644
--- a/api/routers/frame.py
+++ b/api/routers/frame.py
@@ -18,7 +18,7 @@ from fastapi import APIRouter, HTTPException
from loguru import logger
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.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}")
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
+
+ {{custom_text:text=Hello World}}
+
+ ```
+
+ 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))
+
diff --git a/api/routers/video.py b/api/routers/video.py
index 952d1b5..d033006 100644
--- a/api/routers/video.py
+++ b/api/routers/video.py
@@ -151,6 +151,10 @@ async def generate_video_sync(
logger.warning("voice_id parameter is deprecated, please use tts_workflow instead")
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
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")
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)
# Get file size
diff --git a/api/schemas/frame.py b/api/schemas/frame.py
index d4f72d6..cf0e771 100644
--- a/api/schemas/frame.py
+++ b/api/schemas/frame.py
@@ -14,7 +14,7 @@
Frame/Template rendering API schemas
"""
-from typing import Optional
+from typing import Optional, Dict, Any, List
from pydantic import BaseModel, Field
@@ -47,3 +47,23 @@ class FrameRenderResponse(BaseModel):
width: int = Field(..., description="Frame width 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."
+ )
+
diff --git a/api/schemas/video.py b/api/schemas/video.py
index 483fd16..426b654 100644
--- a/api/schemas/video.py
+++ b/api/schemas/video.py
@@ -14,7 +14,7 @@
Video generation API schemas
"""
-from typing import Optional, Literal
+from typing import Optional, Literal, Dict, Any
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."
)
+ # === 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 ===
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.",
"mode": "generate",
"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"
}
}