显示具体的模板尺寸
This commit is contained in:
@@ -4,7 +4,8 @@ Template utility functions for size parsing and template management
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List, Tuple, Optional
|
from typing import List, Tuple, Optional, Literal
|
||||||
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
|
|
||||||
def parse_template_size(template_path: str) -> Tuple[int, int]:
|
def parse_template_size(template_path: str) -> Tuple[int, int]:
|
||||||
@@ -154,6 +155,113 @@ def get_template_full_path(size: str, template_name: str) -> str:
|
|||||||
return str(template_path)
|
return str(template_path)
|
||||||
|
|
||||||
|
|
||||||
|
class TemplateDisplayInfo(BaseModel):
|
||||||
|
"""Template display information for UI layer"""
|
||||||
|
|
||||||
|
name: str = Field(..., description="Template name without extension")
|
||||||
|
size: str = Field(..., description="Size string like '1080x1920'")
|
||||||
|
width: int = Field(..., description="Width in pixels")
|
||||||
|
height: int = Field(..., description="Height in pixels")
|
||||||
|
orientation: Literal['portrait', 'landscape', 'square'] = Field(
|
||||||
|
...,
|
||||||
|
description="Video orientation"
|
||||||
|
)
|
||||||
|
is_standard: bool = Field(
|
||||||
|
...,
|
||||||
|
description="True only for standard sizes: 1080x1920, 1920x1080, 1080x1080"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TemplateInfo(BaseModel):
|
||||||
|
"""Complete template information with path and display info"""
|
||||||
|
|
||||||
|
template_path: str = Field(..., description="Full template path like '1080x1920/default.html'")
|
||||||
|
display_info: TemplateDisplayInfo = Field(..., description="Display information")
|
||||||
|
|
||||||
|
|
||||||
|
def format_template_display_info(template_name: str, size: str) -> TemplateDisplayInfo:
|
||||||
|
"""
|
||||||
|
Format template display information for UI
|
||||||
|
|
||||||
|
Returns structured data for UI layer to handle display and i18n.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
template_name: Template filename like "default.html"
|
||||||
|
size: Size string like "1080x1920"
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
TemplateDisplayInfo object with name, size, dimensions, orientation, and standard flag
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
>>> info = format_template_display_info("default.html", "1080x1920")
|
||||||
|
>>> info.name
|
||||||
|
'default'
|
||||||
|
>>> info.is_standard
|
||||||
|
True
|
||||||
|
|
||||||
|
>>> info = format_template_display_info("custom.html", "1080x1921")
|
||||||
|
>>> info.orientation
|
||||||
|
'portrait'
|
||||||
|
>>> info.is_standard
|
||||||
|
False
|
||||||
|
"""
|
||||||
|
# Keep full template name with .html extension
|
||||||
|
name = template_name
|
||||||
|
|
||||||
|
# Parse size
|
||||||
|
width, height = map(int, size.split('x'))
|
||||||
|
|
||||||
|
# Detect orientation
|
||||||
|
if height > width:
|
||||||
|
orientation = 'portrait'
|
||||||
|
elif width > height:
|
||||||
|
orientation = 'landscape'
|
||||||
|
else:
|
||||||
|
orientation = 'square'
|
||||||
|
|
||||||
|
# Check if it's a standard size (only these three)
|
||||||
|
is_standard = (width, height) in [(1080, 1920), (1920, 1080), (1080, 1080)]
|
||||||
|
|
||||||
|
return TemplateDisplayInfo(
|
||||||
|
name=name,
|
||||||
|
size=size,
|
||||||
|
width=width,
|
||||||
|
height=height,
|
||||||
|
orientation=orientation,
|
||||||
|
is_standard=is_standard
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def get_all_templates_with_info() -> List[TemplateInfo]:
|
||||||
|
"""
|
||||||
|
Get all templates with their display information
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
List of TemplateInfo objects
|
||||||
|
|
||||||
|
Example:
|
||||||
|
>>> templates = get_all_templates_with_info()
|
||||||
|
>>> for t in templates:
|
||||||
|
... print(f"{t.display_info.name} - {t.display_info.orientation}")
|
||||||
|
... print(f" Path: {t.template_path}")
|
||||||
|
... print(f" Standard: {t.display_info.is_standard}")
|
||||||
|
"""
|
||||||
|
result = []
|
||||||
|
sizes = list_available_sizes()
|
||||||
|
|
||||||
|
for size in sizes:
|
||||||
|
templates = list_templates_for_size(size)
|
||||||
|
for template in templates:
|
||||||
|
display_info = format_template_display_info(template, size)
|
||||||
|
full_path = f"{size}/{template}"
|
||||||
|
result.append(TemplateInfo(
|
||||||
|
template_path=full_path,
|
||||||
|
display_info=display_info
|
||||||
|
))
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
def resolve_template_path(template_input: Optional[str]) -> str:
|
def resolve_template_path(template_input: Optional[str]) -> str:
|
||||||
"""
|
"""
|
||||||
Resolve template input to full path with validation
|
Resolve template input to full path with validation
|
||||||
|
|||||||
69
web/app.py
69
web/app.py
@@ -667,47 +667,52 @@ def main():
|
|||||||
st.markdown(tr("template.how"))
|
st.markdown(tr("template.how"))
|
||||||
|
|
||||||
# Import template utilities
|
# Import template utilities
|
||||||
from pixelle_video.utils.template_util import list_available_sizes, list_templates_for_size
|
from pixelle_video.utils.template_util import get_all_templates_with_info
|
||||||
|
|
||||||
# Step 1: Select video size
|
# Get all templates with their info
|
||||||
VIDEO_SIZE_OPTIONS = {
|
all_templates = get_all_templates_with_info()
|
||||||
"📱 竖屏视频 (1080×1920)": "1080x1920",
|
|
||||||
"🖥 横屏视频 (1920×1080)": "1920x1080",
|
|
||||||
"⬜ 方形视频 (1080×1080)": "1080x1080",
|
|
||||||
}
|
|
||||||
|
|
||||||
# Filter available sizes (only show sizes that exist)
|
if not all_templates:
|
||||||
available_sizes = list_available_sizes()
|
st.error("No templates found. Please ensure templates are in templates/ directory with proper structure (e.g., templates/1080x1920/default.html).")
|
||||||
available_size_options = {k: v for k, v in VIDEO_SIZE_OPTIONS.items() if v in available_sizes}
|
|
||||||
|
|
||||||
if not available_size_options:
|
|
||||||
st.error("No template sizes found. Please ensure templates are in correct directory structure.")
|
|
||||||
st.stop()
|
st.stop()
|
||||||
|
|
||||||
selected_size_label = st.selectbox(
|
# Build display names with i18n
|
||||||
tr("template.video_size"),
|
ORIENTATION_I18N = {
|
||||||
list(available_size_options.keys()),
|
'portrait': tr('orientation.portrait'),
|
||||||
label_visibility="collapsed"
|
'landscape': tr('orientation.landscape'),
|
||||||
)
|
'square': tr('orientation.square')
|
||||||
selected_size = available_size_options[selected_size_label]
|
}
|
||||||
|
|
||||||
# Step 2: Select template for the chosen size
|
display_options = {}
|
||||||
template_files = list_templates_for_size(selected_size)
|
for item in all_templates:
|
||||||
|
info = item.display_info
|
||||||
|
name = info.name
|
||||||
|
orientation = ORIENTATION_I18N.get(info.orientation, info.orientation)
|
||||||
|
|
||||||
# Default to default.html if exists, otherwise first option
|
# Always show dimensions for standardization
|
||||||
default_template_index = 0
|
display_name = f"{name} - {orientation}({info.width}×{info.height})"
|
||||||
if "default.html" in template_files:
|
|
||||||
default_template_index = template_files.index("default.html")
|
|
||||||
|
|
||||||
template_name = st.selectbox(
|
display_options[display_name] = item.template_path
|
||||||
tr("template.style"),
|
|
||||||
template_files if template_files else ["default.html"],
|
# Default to "default" portrait if exists
|
||||||
index=default_template_index,
|
display_names = list(display_options.keys())
|
||||||
label_visibility="collapsed"
|
default_index = 0
|
||||||
|
for idx, name in enumerate(display_names):
|
||||||
|
if "default" in name.lower() and tr('orientation.portrait') in name:
|
||||||
|
default_index = idx
|
||||||
|
break
|
||||||
|
|
||||||
|
# Single dropdown with formatted names
|
||||||
|
selected_display_name = st.selectbox(
|
||||||
|
tr("template.select"),
|
||||||
|
display_names,
|
||||||
|
index=default_index,
|
||||||
|
label_visibility="collapsed",
|
||||||
|
help=tr("template.select_help")
|
||||||
)
|
)
|
||||||
|
|
||||||
# Combine size and template name to get full path
|
# Get full template path
|
||||||
frame_template = f"{selected_size}/{template_name}"
|
frame_template = display_options[selected_display_name]
|
||||||
|
|
||||||
# Template preview expander
|
# Template preview expander
|
||||||
with st.expander(tr("template.preview_title"), expanded=False):
|
with st.expander(tr("template.preview_title"), expanded=False):
|
||||||
|
|||||||
@@ -66,11 +66,18 @@
|
|||||||
"style.generated_prompt": "Generated prompt: {prompt}",
|
"style.generated_prompt": "Generated prompt: {prompt}",
|
||||||
|
|
||||||
"template.selector": "Template Selection",
|
"template.selector": "Template Selection",
|
||||||
|
"template.select": "Select Template",
|
||||||
|
"template.select_help": "Select template and video size",
|
||||||
"template.default": "Default",
|
"template.default": "Default",
|
||||||
"template.modern": "Modern",
|
"template.modern": "Modern",
|
||||||
"template.neon": "Neon",
|
"template.neon": "Neon",
|
||||||
"template.what": "Controls the visual layout and design style of each frame (title, text, image arrangement)",
|
"template.what": "Controls the visual layout and design style of each frame (title, text, image arrangement)",
|
||||||
"template.how": "Place .html template files in the templates/ folder for automatic detection. Supports custom CSS styles",
|
"template.how": "Place .html template files in the templates/ folder for automatic detection. Supports custom CSS styles",
|
||||||
|
"template.size_info": "Template Size",
|
||||||
|
|
||||||
|
"orientation.portrait": "Portrait",
|
||||||
|
"orientation.landscape": "Landscape",
|
||||||
|
"orientation.square": "Square",
|
||||||
"template.preview_title": "Preview Template",
|
"template.preview_title": "Preview Template",
|
||||||
"template.preview_param_title": "Title",
|
"template.preview_param_title": "Title",
|
||||||
"template.preview_param_text": "Text",
|
"template.preview_param_text": "Text",
|
||||||
|
|||||||
@@ -66,11 +66,18 @@
|
|||||||
"style.generated_prompt": "生成的提示词:{prompt}",
|
"style.generated_prompt": "生成的提示词:{prompt}",
|
||||||
|
|
||||||
"template.selector": "模板选择",
|
"template.selector": "模板选择",
|
||||||
|
"template.select": "选择模板",
|
||||||
|
"template.select_help": "选择模板和视频尺寸",
|
||||||
"template.default": "默认",
|
"template.default": "默认",
|
||||||
"template.modern": "现代",
|
"template.modern": "现代",
|
||||||
"template.neon": "霓虹",
|
"template.neon": "霓虹",
|
||||||
"template.what": "控制视频每一帧的视觉布局和设计风格(标题、文本、图片的排版样式)",
|
"template.what": "控制视频每一帧的视觉布局和设计风格(标题、文本、图片的排版样式)",
|
||||||
"template.how": "将 .html 模板文件放入 templates/ 文件夹即可自动识别。支持自定义 CSS 样式",
|
"template.how": "将 .html 模板文件放入 templates/ 文件夹即可自动识别。支持自定义 CSS 样式",
|
||||||
|
"template.size_info": "模板尺寸",
|
||||||
|
|
||||||
|
"orientation.portrait": "竖屏",
|
||||||
|
"orientation.landscape": "横屏",
|
||||||
|
"orientation.square": "方形",
|
||||||
"template.preview_title": "预览模板",
|
"template.preview_title": "预览模板",
|
||||||
"template.preview_param_title": "标题",
|
"template.preview_param_title": "标题",
|
||||||
"template.preview_param_text": "文本",
|
"template.preview_param_text": "文本",
|
||||||
|
|||||||
Reference in New Issue
Block a user