chore: Merge upstream/main with RunningHub 48G support and FAQ improvements
This commit is contained in:
25
README.md
25
README.md
@@ -31,22 +31,17 @@ https://github.com/user-attachments/assets/a42e7457-fcc8-40da-83fc-784c45a8b95d
|
||||

|
||||
|
||||
|
||||
## 📋 更新日志
|
||||
## 📋 最近更新
|
||||
|
||||
### 2025-12-04
|
||||
|
||||
- 🎨 **新增「自定义素材」功能** - 支持用户上传自己的照片和视频:
|
||||
- 📸 **智能图片分析**: AI 自动识别图片内容,生成精准描述
|
||||
- 🎥 **视频理解能力**: 支持视频素材分析,理解视频中的场景和内容
|
||||
- ✍️ **智能脚本生成**: 基于素材内容和用户意图,自动生成视频文案和旁白
|
||||
- 🎬 **一键成片**: 将你的照片/视频素材,快速制作成带文案和配音的完整视频
|
||||
- 💡 降低创作门槛,让没有素材的用户也能轻松制作专业视频
|
||||
|
||||
### 2025-11-18
|
||||
|
||||
- 优化 RunningHub 服务调用,支持并行处理,大幅提升生成速度
|
||||
- 新增历史记录页面,可查看和管理所有生成过的视频
|
||||
- 支持一次性创建多个视频任务,提高批量创作效率
|
||||
- ✅ **2026-01-06**: 新增 RunningHub 48G 显存机器调用支持
|
||||
- ✅ **2025-12-28**: 支持 RunningHub 并发限制可配置,优化 LLM 返回结构化数据的逻辑
|
||||
- ✅ **2025-12-17**: 支持 ComfyUI API Key 配置,支持 Nano Banana 模型调用,API 接口支持模板自定义参数
|
||||
- ✅ **2025-12-10**: 侧边栏内置 FAQ,锁定 edge-tts 版本修复 TTS 服务不稳定问题
|
||||
- ✅ **2025-12-08**: 支持固定脚本多种分割方式(段落/行/句子),优化模板选择交互逻辑支持直接预览选择
|
||||
- ✅ **2025-12-06**: 修复视频生成 API 返回 URL 路径处理,支持跨平台兼容
|
||||
- ✅ **2025-12-05**: 新增 Windows 整合包下载,优化图片与视频反推工作流
|
||||
- ✅ **2025-12-04**: 新增「自定义素材」功能,支持用户上传自己的照片和视频,AI 智能分析生成脚本
|
||||
- ✅ **2025-11-18**: 优化 RunningHub 服务调用支持并行处理,新增历史记录页面,支持批量创建视频任务
|
||||
|
||||
|
||||
## ✨ 功能亮点
|
||||
|
||||
25
README_EN.md
25
README_EN.md
@@ -30,22 +30,17 @@ Just input a **topic**, and Pixelle-Video will automatically:
|
||||

|
||||
|
||||
|
||||
## 📋 Changelog
|
||||
## 📋 Recent Updates
|
||||
|
||||
### 2025-12-04
|
||||
|
||||
- 🎨 **New "Custom Media" Feature** - Support uploading your own photos and videos:
|
||||
- 📸 **Smart Image Analysis**: AI automatically recognizes image content and generates accurate descriptions
|
||||
- 🎥 **Video Understanding**: Supports video asset analysis to understand scenes and content
|
||||
- ✍️ **Intelligent Script Generation**: Auto-generates video scripts and narration based on asset content and user intent
|
||||
- 🎬 **One-Click Production**: Transform your photos/videos into complete videos with scripts and voiceover
|
||||
- 💡 Lower the creative barrier for users without existing media assets
|
||||
|
||||
### 2025-11-18
|
||||
|
||||
- Optimized RunningHub service calls with parallel processing for significantly faster speed
|
||||
- Added history page to view and manage all generated videos
|
||||
- Support creating multiple video tasks at once for efficient batch production
|
||||
- ✅ **2026-01-06**: Added RunningHub 48G VRAM machine support
|
||||
- ✅ **2025-12-28**: Configurable RunningHub concurrency limit, improved LLM structured data response handling
|
||||
- ✅ **2025-12-17**: Added ComfyUI API Key configuration, Nano Banana model support, API template custom parameters
|
||||
- ✅ **2025-12-10**: Built-in FAQ in sidebar, fixed edge-tts version to resolve TTS service instability
|
||||
- ✅ **2025-12-08**: Support multiple script split modes (paragraph/line/sentence), improved template selection with direct preview
|
||||
- ✅ **2025-12-06**: Fixed video generation API URL path handling with cross-platform compatibility
|
||||
- ✅ **2025-12-05**: Added Windows all-in-one package download, optimized image and video analysis workflows
|
||||
- ✅ **2025-12-04**: New "Custom Media" feature - upload your photos/videos with AI-powered analysis and script generation
|
||||
- ✅ **2025-11-18**: Parallel processing for RunningHub, added history page, batch video task creation support
|
||||
|
||||
|
||||
## ✨ Key Features
|
||||
|
||||
@@ -131,6 +131,7 @@ class ConfigManager:
|
||||
"comfyui_api_key": self.config.comfyui.comfyui_api_key,
|
||||
"runninghub_api_key": self.config.comfyui.runninghub_api_key,
|
||||
"runninghub_concurrent_limit": self.config.comfyui.runninghub_concurrent_limit,
|
||||
"runninghub_instance_type": self.config.comfyui.runninghub_instance_type,
|
||||
"tts": {
|
||||
"default_workflow": self.config.comfyui.tts.default_workflow,
|
||||
},
|
||||
@@ -149,7 +150,8 @@ class ConfigManager:
|
||||
comfyui_url: Optional[str] = None,
|
||||
comfyui_api_key: Optional[str] = None,
|
||||
runninghub_api_key: Optional[str] = None,
|
||||
runninghub_concurrent_limit: Optional[int] = None
|
||||
runninghub_concurrent_limit: Optional[int] = None,
|
||||
runninghub_instance_type: Optional[str] = None
|
||||
):
|
||||
"""Set ComfyUI global configuration"""
|
||||
updates = {}
|
||||
@@ -161,6 +163,9 @@ class ConfigManager:
|
||||
updates["runninghub_api_key"] = runninghub_api_key
|
||||
if runninghub_concurrent_limit is not None:
|
||||
updates["runninghub_concurrent_limit"] = runninghub_concurrent_limit
|
||||
if runninghub_instance_type is not None:
|
||||
# Empty string means disable (treat as None for storage)
|
||||
updates["runninghub_instance_type"] = runninghub_instance_type if runninghub_instance_type else None
|
||||
|
||||
if updates:
|
||||
self.update({"comfyui": updates})
|
||||
|
||||
@@ -74,6 +74,7 @@ class ComfyUIConfig(BaseModel):
|
||||
comfyui_api_key: Optional[str] = Field(default=None, description="ComfyUI API Key (optional)")
|
||||
runninghub_api_key: Optional[str] = Field(default=None, description="RunningHub API Key (optional)")
|
||||
runninghub_concurrent_limit: int = Field(default=1, ge=1, le=10, description="RunningHub concurrent execution limit (1-10)")
|
||||
runninghub_instance_type: Optional[str] = Field(default=None, description="RunningHub instance type (optional, set to 'plus' for 48GB VRAM)")
|
||||
tts: TTSSubConfig = Field(default_factory=TTSSubConfig, description="TTS-specific configuration")
|
||||
image: ImageSubConfig = Field(default_factory=ImageSubConfig, description="Image-specific configuration")
|
||||
video: VideoSubConfig = Field(default_factory=VideoSubConfig, description="Video-specific configuration")
|
||||
|
||||
@@ -120,6 +120,10 @@ class PixelleVideoCore:
|
||||
kit_config["api_key"] = comfyui_config["comfyui_api_key"]
|
||||
if comfyui_config.get("runninghub_api_key"):
|
||||
kit_config["runninghub_api_key"] = comfyui_config["runninghub_api_key"]
|
||||
# Only pass instance_type if it has a non-empty value
|
||||
instance_type = comfyui_config.get("runninghub_instance_type")
|
||||
if instance_type and instance_type.strip():
|
||||
kit_config["runninghub_instance_type"] = instance_type
|
||||
|
||||
return kit_config
|
||||
|
||||
|
||||
@@ -231,6 +231,7 @@ class ComfyBaseService:
|
||||
self,
|
||||
comfyui_url: Optional[str] = None,
|
||||
runninghub_api_key: Optional[str] = None,
|
||||
runninghub_instance_type: Optional[str] = None,
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
Prepare ComfyKit configuration
|
||||
@@ -238,6 +239,7 @@ class ComfyBaseService:
|
||||
Args:
|
||||
comfyui_url: ComfyUI URL (optional, overrides config)
|
||||
runninghub_api_key: RunningHub API key (optional, overrides config)
|
||||
runninghub_instance_type: RunningHub instance type (optional, overrides config)
|
||||
|
||||
Returns:
|
||||
ComfyKit configuration dict
|
||||
@@ -262,6 +264,16 @@ class ComfyBaseService:
|
||||
if final_rh_key:
|
||||
kit_config["runninghub_api_key"] = final_rh_key
|
||||
|
||||
# RunningHub instance type (priority: param > global config > env)
|
||||
# Only pass if non-empty value
|
||||
final_instance_type = (
|
||||
runninghub_instance_type
|
||||
or self.global_config.get("runninghub_instance_type")
|
||||
or os.getenv("RUNNINGHUB_INSTANCE_TYPE")
|
||||
)
|
||||
if final_instance_type and final_instance_type.strip():
|
||||
kit_config["runninghub_instance_type"] = final_instance_type
|
||||
|
||||
logger.debug(f"ComfyKit config: {kit_config}")
|
||||
return kit_config
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ dependencies = [
|
||||
"fastapi>=0.115.0",
|
||||
"uvicorn[standard]>=0.32.0",
|
||||
"python-multipart>=0.0.12",
|
||||
"comfykit>=0.1.11",
|
||||
"comfykit>=0.1.12",
|
||||
"beautifulsoup4>=4.14.2",
|
||||
]
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
FAQ component for displaying frequently asked questions
|
||||
"""
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
@@ -57,6 +58,50 @@ def load_faq_content(language: str) -> Optional[str]:
|
||||
return None
|
||||
|
||||
|
||||
def parse_faq_sections(content: str) -> list[tuple[str, str]]:
|
||||
"""
|
||||
Parse FAQ content into sections by ### headings
|
||||
|
||||
Args:
|
||||
content: Raw markdown content
|
||||
|
||||
Returns:
|
||||
List of (question, answer) tuples
|
||||
"""
|
||||
# Remove the first main heading (starts with #, not ###)
|
||||
lines = content.split('\n')
|
||||
if lines and lines[0].startswith('#') and not lines[0].startswith('##'):
|
||||
content = '\n'.join(lines[1:])
|
||||
|
||||
# Split by ### headings (top-level questions)
|
||||
# Pattern matches ### at start of line followed by question text
|
||||
pattern = r'^###\s+(.+?)$'
|
||||
|
||||
sections = []
|
||||
current_question = None
|
||||
current_answer_lines = []
|
||||
|
||||
for line in content.split('\n'):
|
||||
match = re.match(pattern, line)
|
||||
if match:
|
||||
# Save previous section if exists
|
||||
if current_question is not None:
|
||||
answer = '\n'.join(current_answer_lines).strip()
|
||||
sections.append((current_question, answer))
|
||||
# Start new section
|
||||
current_question = match.group(1).strip()
|
||||
current_answer_lines = []
|
||||
else:
|
||||
current_answer_lines.append(line)
|
||||
|
||||
# Save last section
|
||||
if current_question is not None:
|
||||
answer = '\n'.join(current_answer_lines).strip()
|
||||
sections.append((current_question, answer))
|
||||
|
||||
return sections
|
||||
|
||||
|
||||
def render_faq_sidebar():
|
||||
"""
|
||||
Render FAQ in the sidebar
|
||||
@@ -77,14 +122,13 @@ def render_faq_sidebar():
|
||||
if faq_content:
|
||||
# Display FAQ in an expander, expanded by default
|
||||
with st.expander(tr('faq.expand_to_view', fallback='FAQ'), expanded=True):
|
||||
# Remove the first heading from FAQ content since we already show it above
|
||||
lines = faq_content.split('\n')
|
||||
# Skip the first line if it's a heading
|
||||
if lines and lines[0].startswith('#'):
|
||||
faq_content = '\n'.join(lines[1:])
|
||||
# Parse FAQ into sections
|
||||
sections = parse_faq_sections(faq_content)
|
||||
|
||||
# Display FAQ content
|
||||
st.markdown(faq_content, unsafe_allow_html=True)
|
||||
# Display each question in its own collapsible expander
|
||||
for question, answer in sections:
|
||||
with st.expander(question, expanded=False):
|
||||
st.markdown(answer, unsafe_allow_html=True)
|
||||
|
||||
# Add a link to GitHub issues for more help
|
||||
st.markdown(
|
||||
|
||||
@@ -180,15 +180,35 @@ def render_advanced_settings():
|
||||
f"(https://www.runninghub{'.cn' if get_language() == 'zh_CN' else '.ai'}/?inviteCode=bozpdlbj)"
|
||||
)
|
||||
|
||||
# RunningHub concurrent limit
|
||||
runninghub_concurrent_limit = st.number_input(
|
||||
tr("settings.comfyui.runninghub_concurrent_limit"),
|
||||
min_value=1,
|
||||
max_value=10,
|
||||
value=comfyui_config.get("runninghub_concurrent_limit", 1),
|
||||
help=tr("settings.comfyui.runninghub_concurrent_limit_help"),
|
||||
key="runninghub_concurrent_limit_input"
|
||||
)
|
||||
# RunningHub concurrent limit and instance type (in one row)
|
||||
limit_col, instance_col = st.columns(2)
|
||||
with limit_col:
|
||||
runninghub_concurrent_limit = st.number_input(
|
||||
tr("settings.comfyui.runninghub_concurrent_limit"),
|
||||
min_value=1,
|
||||
max_value=10,
|
||||
value=comfyui_config.get("runninghub_concurrent_limit", 1),
|
||||
help=tr("settings.comfyui.runninghub_concurrent_limit_help"),
|
||||
key="runninghub_concurrent_limit_input"
|
||||
)
|
||||
with instance_col:
|
||||
# Check if instance type is "plus" (48G VRAM enabled)
|
||||
current_instance_type = comfyui_config.get("runninghub_instance_type") or ""
|
||||
is_plus_enabled = current_instance_type == "plus"
|
||||
# Instance type options with i18n
|
||||
instance_options = [
|
||||
tr("settings.comfyui.runninghub_instance_24g"),
|
||||
tr("settings.comfyui.runninghub_instance_48g"),
|
||||
]
|
||||
runninghub_instance_type_display = st.selectbox(
|
||||
tr("settings.comfyui.runninghub_instance_type"),
|
||||
options=instance_options,
|
||||
index=1 if is_plus_enabled else 0,
|
||||
help=tr("settings.comfyui.runninghub_instance_type_help"),
|
||||
key="runninghub_instance_type_input"
|
||||
)
|
||||
# Convert display value back to actual value
|
||||
runninghub_48g_enabled = runninghub_instance_type_display == tr("settings.comfyui.runninghub_instance_48g")
|
||||
|
||||
# ====================================================================
|
||||
# Action Buttons (full width at bottom)
|
||||
@@ -206,11 +226,14 @@ def render_advanced_settings():
|
||||
config_manager.set_llm_config(llm_api_key, llm_base_url, llm_model)
|
||||
|
||||
# Save ComfyUI configuration (optional fields, always save what's provided)
|
||||
# Convert checkbox to instance type: True -> "plus", False -> ""
|
||||
instance_type = "plus" if runninghub_48g_enabled else ""
|
||||
config_manager.set_comfyui_config(
|
||||
comfyui_url=comfyui_url if comfyui_url else None,
|
||||
comfyui_api_key=comfyui_api_key if comfyui_api_key else None,
|
||||
runninghub_api_key=runninghub_api_key if runninghub_api_key else None,
|
||||
runninghub_concurrent_limit=int(runninghub_concurrent_limit)
|
||||
runninghub_concurrent_limit=int(runninghub_concurrent_limit),
|
||||
runninghub_instance_type=instance_type
|
||||
)
|
||||
|
||||
# Only save to file if LLM config is valid
|
||||
|
||||
@@ -197,6 +197,10 @@
|
||||
"settings.comfyui.runninghub_get_api_key": "Get RunningHub API Key",
|
||||
"settings.comfyui.runninghub_concurrent_limit": "Concurrent Limit",
|
||||
"settings.comfyui.runninghub_concurrent_limit_help": "RunningHub concurrent execution limit (1-10), default is 1 for regular members, adjust based on your membership level",
|
||||
"settings.comfyui.runninghub_instance_type": "Machine Spec",
|
||||
"settings.comfyui.runninghub_instance_type_help": "Select RunningHub machine spec, 48G VRAM is suitable for large models or high-resolution generation (requires membership support)",
|
||||
"settings.comfyui.runninghub_instance_24g": "24G VRAM",
|
||||
"settings.comfyui.runninghub_instance_48g": "48G VRAM",
|
||||
"tts.inference_mode": "Synthesis Mode",
|
||||
"tts.mode.local": "Local Synthesis",
|
||||
"tts.mode.comfyui": "ComfyUI Synthesis",
|
||||
|
||||
@@ -197,6 +197,10 @@
|
||||
"settings.comfyui.runninghub_get_api_key": "点此获取 RunningHub API Key",
|
||||
"settings.comfyui.runninghub_concurrent_limit": "并发限制",
|
||||
"settings.comfyui.runninghub_concurrent_limit_help": "RunningHub 并发执行数量(1-10),普通会员默认为1,请根据您的会员等级调整",
|
||||
"settings.comfyui.runninghub_instance_type": "机器规格",
|
||||
"settings.comfyui.runninghub_instance_type_help": "选择 RunningHub 机器规格,48G 显存适用于大模型或高分辨率生成(需要会员支持)",
|
||||
"settings.comfyui.runninghub_instance_24g": "24G 显存",
|
||||
"settings.comfyui.runninghub_instance_48g": "48G 显存",
|
||||
"tts.inference_mode": "合成方式",
|
||||
"tts.mode.local": "本地合成",
|
||||
"tts.mode.comfyui": "ComfyUI 合成",
|
||||
|
||||
Reference in New Issue
Block a user