ltdrdata / ComfyUI-Impact-Pack

Custom nodes pack for ComfyUI This custom node helps to conveniently enhance images through Detector, Detailer, Upscaler, Pipe, and more.
GNU General Public License v3.0
1.73k stars 162 forks source link

ImpactControlBridge not working in API mode #486

Open gdanny opened 6 months ago

gdanny commented 6 months ago

I exported a workflow API json file and sent it to the server after setting all necessary parameters.

However in this particular workflow the ImpactControlBridge doesn't seem to work when using it within an API-json-file.

Here is the stack trace:

`ERROR:root:!!! Exception during processing !!! ERROR:root:Traceback (most recent call last): File "P:\KI\ComfyUI\ComfyUI\execution.py", line 152, in recursive_execute output_data, output_ui = get_output_data(obj, input_data_all) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "P:\KI\ComfyUI\ComfyUI\execution.py", line 82, in get_output_data return_values = map_node_over_list(obj, input_data_all, obj.FUNCTION, allow_interrupt=True) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "P:\KI\ComfyUI\ComfyUI\execution.py", line 75, in map_node_over_list results.append(getattr(obj, func)(**slice_dict(input_data_all, i))) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "P:\KI\ComfyUI\ComfyUI\custom_nodes\ComfyUI-Impact-Pack\modules\impact\logics.py", line 648, in doit nodes, links = workflow_to_map(extra_pnginfo['workflow'])


TypeError: 'NoneType' object is not subscriptable`

It seems as if either extra_pnginfo is missing in the exported JSON-file or (more plausible) that it is a bug, since the parameter for extra_pnginfo is defaulting to None if omitted and the doit-method accesses it as an object directly on the first line:

    def doit(self, value, mode, behavior=True, unique_id=None, prompt=None, extra_pnginfo=None):
        global error_skip_flag

        nodes, links = workflow_to_map(extra_pnginfo['workflow'])

        active_nodes = []
        mute_nodes = []
        bypass_nodes = []

        for link in nodes[unique_id]['outputs'][0]['links']:
            node_id = str(links[link][2])

            next_nodes = []
            impact.utils.collect_non_reroute_nodes(nodes, links, next_nodes, node_id)

            for next_node_id in next_nodes:
                node_mode = nodes[next_node_id]['mode']

                if node_mode == 0:
                    active_nodes.append(next_node_id)
                elif node_mode == 2:
                    mute_nodes.append(next_node_id)
                elif node_mode == 4:
                    bypass_nodes.append(next_node_id)

        if mode:
            # active
            should_be_active_nodes = mute_nodes + bypass_nodes
            if len(should_be_active_nodes) > 0:
                PromptServer.instance.send_sync("impact-bridge-continue", {"node_id": unique_id, 'actives': list(should_be_active_nodes)})
                error_skip_flag = True
                raise Exception("IMPACT-PACK-SIGNAL: STOP CONTROL BRIDGE\nIf you see this message, your ComfyUI-Manager is outdated. Please update it.")

        elif behavior:
            # mute
            should_be_mute_nodes = active_nodes + bypass_nodes
            if len(should_be_mute_nodes) > 0:
                PromptServer.instance.send_sync("impact-bridge-continue", {"node_id": unique_id, 'mutes': list(should_be_mute_nodes)})
                error_skip_flag = True
                raise Exception("IMPACT-PACK-SIGNAL: STOP CONTROL BRIDGE\nIf you see this message, your ComfyUI-Manager is outdated. Please update it.")

        else:
            # bypass
            should_be_bypass_nodes = active_nodes + mute_nodes
            if len(should_be_bypass_nodes) > 0:
                PromptServer.instance.send_sync("impact-bridge-continue", {"node_id": unique_id, 'bypasses': list(should_be_bypass_nodes)})
                error_skip_flag = True
                raise Exception("IMPACT-PACK-SIGNAL: STOP CONTROL BRIDGE\nIf you see this message, your ComfyUI-Manager is outdated. Please update it.")

        return (value, )

Without checking if extra_pnginfo might be None.
ltdrdata commented 6 months ago

ImpactControlBridge cannot be used in API mode because it depends on the front. After the following PR is merged, it will be reworked. https://github.com/comfyanonymous/ComfyUI/pull/2666

gdanny commented 6 months ago

Thanks for your swift reply. Maybe I can manage without ImpactControlBridge. My workflow is supposed to upscale a picture using IP-Adapter FaceID if it contains a person. However ApplyFaceID fails and stops the workflow if there is no face in the picture. So I used a BBOX-Detector for the faces and ImpactControlBridge to bypass the ApplyFaceID-node if there are no proper faces.

Can you think of another way of doing it, so that I can use API mode?

ltdrdata commented 6 months ago

As of now, there is no easy way in API mode. A separate channel is needed to receive state information besides the image, and the workflow at the place where the API is sent should be dynamically altered according to that state.

mijuku233 commented 6 months ago

Thanks for your swift reply. Maybe I can manage without ImpactControlBridge. My workflow is supposed to upscale a picture using IP-Adapter FaceID if it contains a person. However ApplyFaceID fails and stops the workflow if there is no face in the picture. So I used a BBOX-Detector for the faces and ImpactControlBridge to bypass the ApplyFaceID-node if there are no proper faces.

Can you think of another way of doing it, so that I can use API mode?

Try using ImpactConditionalBranchSelMode. branch

When cond=true, faceid is applied. When cond=false, faceid is not applied.

gdanny commented 6 months ago

Thank you very much. This hint has helped. Although I used the conditional-branch-sel-node in another way than proposed. In your example the Apply-IP-Adapter-Node gets executed anyway and therefore runs into an error when getting passed an image without face. So I check for faces with a BBOX-detector and Segs-Isnt-Empty-Node and switch the input image for Face-ID to a dummy image if there's no face in the original picture.

mijuku233 commented 6 months ago

Thank you very much. This hint has helped. Although I used the conditional-branch-sel-node in another way than proposed. In your example the Apply-IP-Adapter-Node gets executed anyway and therefore runs into an error when getting passed an image without face. So I check for faces with a BBOX-detector and Segs-Isnt-Empty-Node and switch the input image for Face-ID to a dummy image if there's no face in the original picture.

After select on prompt is turned on, the unselected branch will not be executed, just like it has been mute. So in this example, when cond=false, ipadapter will not be executed at all.

gdanny commented 6 months ago

Okay, but on prompt the workflow doesn't know yet, whether the picture contains a face or not. I see, your example would have worked, but in my case, I want the cond-Value to be set at runtime (as an input).