Support multi-path ComfyUI installs

This commit is contained in:
Dominik Bargiel
2025-12-03 11:33:20 +01:00
parent 16cdd994a3
commit dfbad19ff8
3 changed files with 95 additions and 7 deletions
+10
View File
@@ -49,6 +49,16 @@ Copy `plugins/ComfyUI/` to your Deadline Repository's `custom/plugins/` director
### Model Paths (Optional)
For render farms with shared storage, copy `example_extra_model_paths.yaml` to your ComfyUI installation as `extra_model_paths.yaml` and update paths.
### Multiple ComfyUI Install Paths
In Deadline Monitor → Repository Options → ComfyUI plugin configuration, the `ComfyUI Installation Paths` field now accepts multiple entries. Add one path per line (drive letters, UNC shares, etc.). Workers will walk the list from top to bottom, apply Deadline path mapping, expand environment variables, and pick the first path that contains both `ComfyUI/main.py` and `python_embeded/python.exe`. This mirrors the multi-path behavior used by Deadline's Houdini plugin.
Example:
```
C:\ComfyUI_windows_portable
D:\Apps\ComfyUI
\\NAS01\software\ComfyUI
```
## How It Works
1. Captures current ComfyUI workflow
+3 -3
View File
@@ -17,12 +17,12 @@ Default=True
Description=Not configurable
[ComfyUIPath]
Type=filename
Label=ComfyUI Installation Path
Type=multilinemultifilename
Label=ComfyUI Installation Paths
Category=Configuration
Index=0
Default=C:\\ComfyUI_windows_portable
Description=Path to your ComfyUI portable installation directory. The plugin will automatically find main.py and the embedded Python executable.
Description=One path per line (local drive letters, UNC paths, etc). Workers try each entry in order and pick the first install that contains ComfyUI\\main.py and python_embeded\\python.exe.
[DefaultOutputDirectory]
Type=filename
+82 -4
View File
@@ -119,6 +119,8 @@ class ComfyUI(DeadlinePlugin):
self.progress_value = 0
self.thread_running = True
self.custom_output_dir_specified = False
self.comfyui_install_path = None
self.comfyui_path_candidates = []
# Batch processing variables
self.chunk_size = 1
@@ -130,6 +132,73 @@ class ComfyUI(DeadlinePlugin):
self.completed_prompts = set()
self.current_tracking_index = 0
def _resolve_comfyui_install_path(self) -> str:
"""Resolve the ComfyUI installation path from multi-entry configuration."""
if self.comfyui_install_path:
return self.comfyui_install_path
config_entry = self.GetConfigEntryWithDefault("ComfyUIPath", "").strip()
if not config_entry:
error_msg = "ComfyUIPath configuration is empty. Please specify at least one installation path."
self.LogWarning(error_msg)
self.FailRender(error_msg)
return ""
raw_candidates = []
for line in config_entry.splitlines():
stripped_line = line.strip()
if not stripped_line:
continue
parts = [segment.strip().strip('\"').strip("'") for segment in stripped_line.split(";")]
raw_candidates.extend([part for part in parts if part])
if not raw_candidates:
error_msg = "ComfyUIPath configuration did not yield any usable paths."
self.LogWarning(error_msg)
self.FailRender(error_msg)
return ""
resolved_candidates = []
for candidate in raw_candidates:
try:
mapped = RepositoryUtils.CheckPathMapping(candidate)
except Exception as e:
self.LogWarning(f"Path mapping failed for '{candidate}': {e}")
mapped = candidate
expanded = os.path.expandvars(os.path.expanduser(mapped))
normalized = os.path.normpath(expanded)
resolved_candidates.append(normalized)
self.comfyui_path_candidates = resolved_candidates
self.LogInfo(f"Resolving ComfyUI installation path from {len(resolved_candidates)} candidate(s).")
for candidate in resolved_candidates:
if not candidate:
continue
python_exe = os.path.join(candidate, "python_embeded", "python.exe")
comfy_main = os.path.join(candidate, "ComfyUI", "main.py")
path_exists = os.path.exists(python_exe) and os.path.exists(comfy_main)
if path_exists:
self.comfyui_install_path = candidate
self.LogInfo(f"Using ComfyUI installation at: {candidate}")
return self.comfyui_install_path
missing_items = []
if not os.path.exists(python_exe):
missing_items.append("python_embeded/python.exe")
if not os.path.exists(comfy_main):
missing_items.append("ComfyUI/main.py")
missing_desc = ", ".join(missing_items) if missing_items else "required files"
self.LogWarning(f"Skipping ComfyUI path '{candidate}' (missing {missing_desc}).")
error_msg = "Unable to locate a valid ComfyUI installation from ComfyUIPath entries. "
error_msg += f"Tried: {', '.join(resolved_candidates)}"
self.LogWarning(error_msg)
self.FailRender(error_msg)
return ""
def Cleanup(self):
"""Clean up plugin resources"""
self.thread_running = False
@@ -251,7 +320,9 @@ class ComfyUI(DeadlinePlugin):
self.LogInfo(f"Using configured default output directory: {self.comfyui_output_dir}")
else:
# Fall back to ComfyUI's standard output directory
comfyui_path = self.GetConfigEntry("ComfyUIPath")
comfyui_path = self._resolve_comfyui_install_path()
if not comfyui_path:
raise ComfyUIError("ComfyUI installation path could not be resolved for output directory setup.")
self.comfyui_output_dir = os.path.join(comfyui_path, "ComfyUI", "output")
self.custom_output_dir_specified = False
self.LogInfo(f"Using ComfyUI's default output directory: {self.comfyui_output_dir}")
@@ -352,6 +423,9 @@ class ComfyUI(DeadlinePlugin):
try:
self._setup_batch_processing()
comfyui_path = self._resolve_comfyui_install_path()
if not comfyui_path:
raise ComfyUIError("ComfyUI installation path could not be resolved.")
self._setup_output_directory()
self._setup_temp_directory()
self._calculate_comfyui_port()
@@ -431,7 +505,9 @@ class ComfyUI(DeadlinePlugin):
def RenderExecutable(self):
"""Get the Python executable for ComfyUI"""
comfyui_path = self.GetConfigEntry("ComfyUIPath")
comfyui_path = self._resolve_comfyui_install_path()
if not comfyui_path:
return ""
python_exe = os.path.join(comfyui_path, "python_embeded", "python.exe")
if os.path.exists(python_exe):
@@ -440,14 +516,16 @@ class ComfyUI(DeadlinePlugin):
self._set_deadline_environment_variables()
return python_exe
else:
error_msg = f"ComfyUI embedded Python not found at: {python_exe}. Please check your ComfyUIPath configuration."
error_msg = f"ComfyUI embedded Python not found at: {python_exe}. Please check your ComfyUIPath entries."
self.LogWarning(error_msg)
self.FailRender(error_msg)
return ""
def RenderArgument(self):
"""Build command line arguments for ComfyUI"""
comfyui_path = self.GetConfigEntry("ComfyUIPath")
comfyui_path = self._resolve_comfyui_install_path()
if not comfyui_path:
return ""
comfyui_main_py = os.path.join(comfyui_path, "ComfyUI", "main.py")
# Validate that main.py exists