From d6b2f02ccec58e8d2b688a18557dc842779f4d5e Mon Sep 17 00:00:00 2001 From: puke <1129090915@qq.com> Date: Tue, 6 Jan 2026 11:11:11 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E6=96=B0=E5=A2=9Erunninghub=E7=9A=8448G?= =?UTF-8?q?=E6=98=BE=E5=AD=98=E6=9C=BA=E5=99=A8=E8=B0=83=E7=94=A8=E6=94=AF?= =?UTF-8?q?=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pixelle_video/config/manager.py | 7 +++- pixelle_video/config/schema.py | 1 + pixelle_video/service.py | 4 ++ pixelle_video/services/comfy_base_service.py | 12 ++++++ pyproject.toml | 2 +- uv.lock | 8 ++-- web/components/settings.py | 43 +++++++++++++++----- web/i18n/locales/en_US.json | 4 ++ web/i18n/locales/zh_CN.json | 4 ++ 9 files changed, 69 insertions(+), 16 deletions(-) diff --git a/pixelle_video/config/manager.py b/pixelle_video/config/manager.py index 9dfb4be..63ee43d 100644 --- a/pixelle_video/config/manager.py +++ b/pixelle_video/config/manager.py @@ -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}) diff --git a/pixelle_video/config/schema.py b/pixelle_video/config/schema.py index 1929082..9558366 100644 --- a/pixelle_video/config/schema.py +++ b/pixelle_video/config/schema.py @@ -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") diff --git a/pixelle_video/service.py b/pixelle_video/service.py index 453cc51..90b8762 100644 --- a/pixelle_video/service.py +++ b/pixelle_video/service.py @@ -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 diff --git a/pixelle_video/services/comfy_base_service.py b/pixelle_video/services/comfy_base_service.py index 576f65e..6fd0d1a 100644 --- a/pixelle_video/services/comfy_base_service.py +++ b/pixelle_video/services/comfy_base_service.py @@ -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 diff --git a/pyproject.toml b/pyproject.toml index 0826c7b..b2a8c79 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -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", ] diff --git a/uv.lock b/uv.lock index f769dbf..26d437f 100644 --- a/uv.lock +++ b/uv.lock @@ -432,7 +432,7 @@ wheels = [ [[package]] name = "comfykit" -version = "0.1.11" +version = "0.1.12" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiofiles" }, @@ -442,9 +442,9 @@ dependencies = [ { name = "pydantic" }, { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/2c/c2/55612d8ee85f0f003113b36795ee40c2ce5ea4f3806baa6b056fb88e696a/comfykit-0.1.11.tar.gz", hash = "sha256:1dc96c15da81a1c69a5f42af2f0f156f9574e534ac925476d1e469b02f2736b0", size = 50179 } +sdist = { url = "https://files.pythonhosted.org/packages/1b/d3/6213304fae8823441567b00a5e62ea2f9ae229c86e62ad5996df18851511/comfykit-0.1.12.tar.gz", hash = "sha256:129aedbb1966e78f406ab96cc713e5ade089182156a1cafd3c4c79cac4fcd3c9", size = 50671 } wheels = [ - { url = "https://files.pythonhosted.org/packages/c0/e5/9fdd7da9a944fa8ad32f1e7623604d5bbc0a37f8a6d9beda23e51e3e3698/comfykit-0.1.11-py3-none-any.whl", hash = "sha256:d23cf636adc360976f4724cfc5a0f3ef23dd77735c852a1f83f061256a7b9a2e", size = 53286 }, + { url = "https://files.pythonhosted.org/packages/d9/e6/c008888d1386cb75ba2fde68b07f45821500e262536039aead9689d335c3/comfykit-0.1.12-py3-none-any.whl", hash = "sha256:30ec8c8368b5b8224a26bb21cdf2240b5aff9938146a76229c079427f7c12421", size = 53697 }, ] [[package]] @@ -1697,7 +1697,7 @@ dev = [ requires-dist = [ { name = "beautifulsoup4", specifier = ">=4.14.2" }, { name = "certifi", specifier = ">=2025.10.5" }, - { name = "comfykit", specifier = ">=0.1.11" }, + { name = "comfykit", specifier = ">=0.1.12" }, { name = "edge-tts", specifier = "==7.2.1" }, { name = "fastapi", specifier = ">=0.115.0" }, { name = "fastmcp", specifier = ">=2.0.0" }, diff --git a/web/components/settings.py b/web/components/settings.py index 1a29617..8293e2c 100644 --- a/web/components/settings.py +++ b/web/components/settings.py @@ -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 diff --git a/web/i18n/locales/en_US.json b/web/i18n/locales/en_US.json index 91fb10b..9d3c786 100644 --- a/web/i18n/locales/en_US.json +++ b/web/i18n/locales/en_US.json @@ -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", diff --git a/web/i18n/locales/zh_CN.json b/web/i18n/locales/zh_CN.json index 3b46835..fe12bb7 100644 --- a/web/i18n/locales/zh_CN.json +++ b/web/i18n/locales/zh_CN.json @@ -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 合成", From d6a24171a88ce24b0596d3aad0144a515dbcc88d Mon Sep 17 00:00:00 2001 From: puke <1129090915@qq.com> Date: Tue, 6 Jan 2026 11:19:52 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 25 ++++++++++--------------- README_EN.md | 25 ++++++++++--------------- 2 files changed, 20 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 5416353..10f14d3 100644 --- a/README.md +++ b/README.md @@ -31,22 +31,17 @@ https://github.com/user-attachments/assets/a42e7457-fcc8-40da-83fc-784c45a8b95d ![Web UI界面](resources/webui.png) -## 📋 更新日志 +## 📋 最近更新 -### 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 服务调用支持并行处理,新增历史记录页面,支持批量创建视频任务 ## ✨ 功能亮点 diff --git a/README_EN.md b/README_EN.md index d4dd9a7..4a37e52 100644 --- a/README_EN.md +++ b/README_EN.md @@ -30,22 +30,17 @@ Just input a **topic**, and Pixelle-Video will automatically: ![Web UI Interface](resources/webui_en.png) -## 📋 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 From e1e5aaf130ecd328433d21f7a9c1b814198a788c Mon Sep 17 00:00:00 2001 From: puke <1129090915@qq.com> Date: Tue, 6 Jan 2026 11:49:18 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E4=BC=98=E5=8C=96web=E9=A1=B5=E9=9D=A2FAQ?= =?UTF-8?q?=E7=9A=84=E5=B1=95=E7=A4=BA=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/components/faq.py | 58 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 51 insertions(+), 7 deletions(-) diff --git a/web/components/faq.py b/web/components/faq.py index 22a1f5f..a890e2f 100644 --- a/web/components/faq.py +++ b/web/components/faq.py @@ -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(