显示具体的模板尺寸

This commit is contained in:
puke
2025-11-03 11:38:11 +08:00
parent 4dbf08ca5a
commit 20e210b88d
4 changed files with 160 additions and 33 deletions

View File

@@ -4,7 +4,8 @@ Template utility functions for size parsing and template management
import os
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]:
@@ -154,6 +155,113 @@ def get_template_full_path(size: str, template_name: str) -> str:
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:
"""
Resolve template input to full path with validation

View File

@@ -667,47 +667,52 @@ def main():
st.markdown(tr("template.how"))
# 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
VIDEO_SIZE_OPTIONS = {
"📱 竖屏视频 (1080×1920)": "1080x1920",
"🖥 横屏视频 (1920×1080)": "1920x1080",
"⬜ 方形视频 (1080×1080)": "1080x1080",
}
# Get all templates with their info
all_templates = get_all_templates_with_info()
# Filter available sizes (only show sizes that exist)
available_sizes = list_available_sizes()
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.")
if not all_templates:
st.error("No templates found. Please ensure templates are in templates/ directory with proper structure (e.g., templates/1080x1920/default.html).")
st.stop()
selected_size_label = st.selectbox(
tr("template.video_size"),
list(available_size_options.keys()),
label_visibility="collapsed"
)
selected_size = available_size_options[selected_size_label]
# Build display names with i18n
ORIENTATION_I18N = {
'portrait': tr('orientation.portrait'),
'landscape': tr('orientation.landscape'),
'square': tr('orientation.square')
}
# Step 2: Select template for the chosen size
template_files = list_templates_for_size(selected_size)
display_options = {}
for item in all_templates:
info = item.display_info
name = info.name
orientation = ORIENTATION_I18N.get(info.orientation, info.orientation)
# Always show dimensions for standardization
display_name = f"{name} - {orientation}{info.width}×{info.height}"
display_options[display_name] = item.template_path
# Default to default.html if exists, otherwise first option
default_template_index = 0
if "default.html" in template_files:
default_template_index = template_files.index("default.html")
# Default to "default" portrait if exists
display_names = list(display_options.keys())
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
template_name = st.selectbox(
tr("template.style"),
template_files if template_files else ["default.html"],
index=default_template_index,
label_visibility="collapsed"
# 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
frame_template = f"{selected_size}/{template_name}"
# Get full template path
frame_template = display_options[selected_display_name]
# Template preview expander
with st.expander(tr("template.preview_title"), expanded=False):

View File

@@ -66,11 +66,18 @@
"style.generated_prompt": "Generated prompt: {prompt}",
"template.selector": "Template Selection",
"template.select": "Select Template",
"template.select_help": "Select template and video size",
"template.default": "Default",
"template.modern": "Modern",
"template.neon": "Neon",
"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.size_info": "Template Size",
"orientation.portrait": "Portrait",
"orientation.landscape": "Landscape",
"orientation.square": "Square",
"template.preview_title": "Preview Template",
"template.preview_param_title": "Title",
"template.preview_param_text": "Text",

View File

@@ -66,11 +66,18 @@
"style.generated_prompt": "生成的提示词:{prompt}",
"template.selector": "模板选择",
"template.select": "选择模板",
"template.select_help": "选择模板和视频尺寸",
"template.default": "默认",
"template.modern": "现代",
"template.neon": "霓虹",
"template.what": "控制视频每一帧的视觉布局和设计风格(标题、文本、图片的排版样式)",
"template.how": "将 .html 模板文件放入 templates/ 文件夹即可自动识别。支持自定义 CSS 样式",
"template.size_info": "模板尺寸",
"orientation.portrait": "竖屏",
"orientation.landscape": "横屏",
"orientation.square": "方形",
"template.preview_title": "预览模板",
"template.preview_param_title": "标题",
"template.preview_param_text": "文本",