Skip to content

Allow saving generated ControlNet previews#1364

Merged
mcmonkey4eva merged 8 commits into
mcmonkeyprojects:masterfrom
jtreminio:controlnet-save
May 23, 2026
Merged

Allow saving generated ControlNet previews#1364
mcmonkey4eva merged 8 commits into
mcmonkeyprojects:masterfrom
jtreminio:controlnet-save

Conversation

@jtreminio

Copy link
Copy Markdown
Contributor
CleanShot.2026-05-02.at.13.05.55.mp4

@jtreminio jtreminio marked this pull request as ready for review May 2, 2026 18:07
Comment thread src/Text2Image/T2IEngine.cs Outdated
}
if (user_input.Get(T2IParamTypes.ControlNetPreviewOnly, false))
{
string controlNetInputFolder = $"inputs/_comfy{backend.Data.ID}/";

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wh... what's going on here? This seems very out of place

Comment thread src/wwwroot/js/genpage/gentab/params.js Outdated
return `inputs/_comfy${parsedId}`;
}
}
return 'inputs';

@mcmonkey4eva mcmonkey4eva May 2, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of this function except this one line is silly. Probably something like inputs/controlnet/ is the folder to use - edit oh that's literally what you're doing anyway, you just split it across places lol

Comment thread src/wwwroot/js/genpage/gentab/params.js Outdated
}
genericRequest('AddImageToHistory', data, res => {
if (inputBrowserHelper.inputImageBrowser) {
inputBrowserHelper.inputImageBrowser.lightRefresh();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is redundant, I'm guessing you copied from the code in the input browser itself, but that's a special case

@jtreminio

Copy link
Copy Markdown
Contributor Author

Per discord conversation, should save directly to inputs/controlnet and not inputs/_comfyN/controlnet. The existing design is clear now, and this PR is much smaller.

@jtreminio

Copy link
Copy Markdown
Contributor Author

With the recent refactor, now getting an error. Setting this back to draft while I hunt down the issue:

21:49:35.490 [Error] Error in websocket handler: System.AggregateException: One or more errors occurred. (Invalid value for parameter ControlNet Image Input)
 ---> System.Exception: Invalid value for parameter ControlNet Image Input
 ---> System.IO.DirectoryNotFoundException: Could not find a part of the path '/workspace/Output/local/inputs/controlnet/controlnet-preview-2026-05-09_21-49-10-336.mp4'.
   at Interop.ThrowExceptionForIoErrno(ErrorInfo errorInfo, String path, Boolean isDirError)
   at Microsoft.Win32.SafeHandles.SafeFileHandle.Open(String fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize, UnixFileMode openPermissions, Int64& fileLength, UnixFileMode& filePermissions, Boolean failForSymlink, Boolean& wasSymlink, Func`4 createOpenException)
   at System.IO.File.ReadAllBytes(String path)
   at SwarmUI.Text2Image.T2IParamTypes.FilePathToDataString(Session session, String filePath, String errorContext) in /workspace/src/Text2Image/T2IParamTypes.cs:line 1143
   at SwarmUI.Text2Image.T2IParamTypes.ValidateParam(T2IParamType type, String val, Session session) in /workspace/src/Text2Image/T2IParamTypes.cs:line 1075
   at SwarmUI.Text2Image.T2IParamTypes.ApplyParameter(String paramTypeName, String value, T2IParamInput data, Int32 sectionId) in /workspace/src/Text2Image/T2IParamTypes.cs:line 1168
   --- End of inner exception stack trace ---
   at SwarmUI.Text2Image.T2IParamTypes.ApplyParameter(String paramTypeName, String value, T2IParamInput data, Int32 sectionId) in /workspace/src/Text2Image/T2IParamTypes.cs:line 1177
   at SwarmUI.WebAPI.T2IAPI.RequestToParams(Session session, JObject rawInput, Boolean applyPresets) in /workspace/src/WebAPI/T2IAPI.cs:line 213
   at SwarmUI.WebAPI.T2IAPI.GenT2I_Internal(Session session, ValueTuple`4 input, Action`1 output, Boolean isWS) in /workspace/src/WebAPI/T2IAPI.cs:line 268
   --- End of inner exception stack trace ---

@jtreminio jtreminio marked this pull request as draft May 10, 2026 02:54
Comment thread src/Text2Image/T2IParamTypes.cs Outdated
public static string FilePathToDataString(Session session, string filePath, string errorContext)
{
string root = WebServer.GetUserOutputRoot(session.User);
string root = Utilities.CombinePathWithAbsolute(Environment.CurrentDirectory, session.User.OutputDirectory);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Selecting from the "Select" modal would try to pull from the wrong location when generating workflow.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

very out of bounds for this PR, but valid fix for if you have AppendUserNameToOutputPath disabled

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually yeah no, i committed this fix separately

g.CurrentMedia.SaveOutput(g.CurrentVae, g.CurrentAudioVae, id: "9");
if (imageNodeActual.AttachedAudio is not null)
{
g.Workflow["9"]["inputs"]["fps"] = NodePath((string)imageNodeActual.AttachedAudio.Path[0], 2);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use uploaded video's FPS when saving preview, otherwise audio would often desync.

@mcmonkey4eva mcmonkey4eva May 11, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think most AttachedAudio sources have a video FPS source?? 0.o

Note that part of the point of the 'proper wg node' thing is to reduce weird path hacks like this

@jtreminio jtreminio marked this pull request as ready for review May 10, 2026 21:38
Comment thread src/wwwroot/js/genpage/gentab/params.js Outdated
if (controlnetGroup) {
let firstGroup = controlnetGroup.querySelector('.input-group');
let buttonDiv = createDiv(`controlnet_button_preview`, null, `<button class="basic-button" onclick="controlnetShowPreview()">Preview</button>`);
let buttonDiv = createDiv(`controlnet_button_preview`, null, `<button class="basic-button" onclick="controlnetShowPreview()">Preview</button> <button class="basic-button" onclick="controlnetSavePreviewToServer()">Save to Server</button>`);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This probably needs a disabled or a display:none? otherwise it's a very odd button with odd behavior.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea was to have it both generate the preview and save to server in one go, if the user had not clicked "Preview" beforehand.

I'll change to only appear once a preview image/video is available.

@jtreminio jtreminio requested a review from mcmonkey4eva May 18, 2026 17:27
@mcmonkey4eva mcmonkey4eva merged commit 6bd2ad3 into mcmonkeyprojects:master May 23, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants