User option to enable/disable out-of-focus live previews#4936
Conversation
This reverts commit 6b56801.
|
I'll fix problems tomorrow |
Nice! I had Claude take a look, I hope this is of use to you.
|
|
using websockets for preview is not inherently a bad idea, but premise how current polling works is inherently wrong. i'm open to adding websocket push method, but this pr changes too much of existing infrastructure for it to be a viable thing. now, having said that, if there are bugs in existing polling based live preview, lets find and fix those. |
I'll change the PR later today |
|
this is not "live preview fixes", this is a completly new method for live preview and it's has its own pros AND cons. before even considering, I have to ask why - what exactly is the problem with current live preview and how does this solve it. cant just say "I had problems and now this works". |
Whenever I'm generating, there is a delay with polling rate implemention, sometimes the steps get stuck or it doesn't update the live preview until it approaches 90% of the first pass which most of the time is too late for it to cancel it when I'm not happy with the preview result and then it already starts with hires fix or detailer and takes longer for me to cancel. You also said polling implementation pauses when not focused on the tab, well I have multiple monitors and most of the time I'm doing something else while I wait for the gen and then the preview doesn't show where the image or video is at, which would be pretty handy for me to have. Whenever I try a other UI like reforged, forge neo, comfy and etc... they always show the progress since the first step of the gen and does it each step or each 2 steps, while the SD.NEXT implementation is inconsistent on my end. When I tested the WebSocket implementation it worked like the other UIs, instant and not affecting generation time like I used to get, I sent 2 video's to you on discord, so that you can see what I mean. |
|
that's why i asked for description of the issue. now lets separate the stories:
as a result, your approach gives more deterministic preview timings, but has far bigger impact on actual generation time. thus i said "it has pros and cons" now, regarding showing preview while not-in-focus, that can be solved with a user option regardless of if its push or poll. ideally, we should be using torch streams instead of relying on python runners, but i've been reluctant to do so due to streams compatibility issues with different gpu architectures. going back on polling - its cheap and commonly used. even if you set polling to 10ms, it should not have noticeable impact. its far from original statement that it runs decode on every poll. |
Alright, Now I get it, I'll go look for adding that user option to enable/disable not-in-focus previews |
|
i'm ok with adding this option to setting, but dist/* files should not be part of the pr - i will run a rebuild on my end, otherwise we have too much churn. |
Undid changes to dist files |
|
lgtm, i'll merge soon, cant today/tomorrow as i'm out |

Description
I've been triggered a lot lately by the late and buggy way live previews show up, sometimes not even at all, also it made my gens laggy, sometimes gens would get stuck, so I made it step based, changeable in settings too in case you want the live preview to generate every 2, 3 or 4 and etc... I did the same to the progress tracking and added a fallback in case the per step based progress tracking fails.
Technical details
The live preview system previously relied on frontend HTTP polling every 500ms, the backend would decode latents and JPEG-encode on every poll, regardless of whether the sampling step had changed. This caused unnecessary GPU work (same latent decoded 10-40x per step), increased latency and made previews feel sluggish or sometimes fail to appear (what I said above).
This PR replaces the polling architecture with a step-driven push model:
Preview images are now generated at sampling step boundaries (configurable via Show live preview every N steps) and pushed immediately via WebSocket (/ws/preview), no more waiting for the next poll cycle or redundant re-decoding.
Progress tracking is also step-based, pushed on every callback step through the same WebSocket channel. HTTP polling is retained as a low-frequency fallback (2s default) for timeout/completion detection if the WebSocket connection drops.
A step-level latch in do_set_current_image() prevents re-decoding the same latent on subsequent polls, eliminating the primary source of wasted GPU time.
The base64 image data URI is now cached in assign_current_image() rather than re-encoded on every HTTP request.
Testing
As for testing, I've tested it a lot with different settings and with things like detailer for example, also the performance is great, something I instantly noticed during gens.
Personal note
As always feel free to comment, I learn from people like you :)
Image