【生成模型】【ComfyUI(三)】使用WebAPI批量调用ComfyUI

06-01 1204阅读

可以参考【生成模型】【ComfyUI(一)】Flux与Flux-Fill部署与API调用中Flux-Fill部分

1. 调整Workflow

我们要部署以下workflow

【生成模型】【ComfyUI(三)】使用WebAPI批量调用ComfyUI

做两个修改

  • 输入改为从Load Image(Base64) 读入图片,当然使用上面的从路径中读图也是可以的
  • 输出改为SaveImageWebsocket节点,通过websocket返回图片,当然使用SaveImage给定路径也是可以的

    ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/d2e2f42f33df4567a63750900590cb75.png

    2. 导出API调用json文件

    【生成模型】【ComfyUI(三)】使用WebAPI批量调用ComfyUI

    3. 使用接口调用

    import requests, websocket
    import base64, io
    from PIL import Image, ImageColor
    def buffer2img(imagebuf, mode='RGB', input_type='base64'):
        if input_type == 'base64':
            buf = base64.b64decode(imagebuf)
        elif input_type == 'bytes':
            buf = imagebuf
        else:
            raise ValueError(f"input_type should in ['base64', 'bytes'], but got {input_type}")
        pil_img = Image.open(io.BytesIO(buf)).convert(mode)
        return pil_img
    def get_server_address():
        server_address = "127.0.0.1:8081"
        return server_address
    class ComfyUIRequest:
        def __init__(self, progress_bar_node_type=["KSampler"]):
            self.progress_bar_node_type = progress_bar_node_type
        def queue_prompt(self, prompt, client_id, server_address):
            """
                将任务提交给server_address上的ComfyUI,进入处理队列,同时获得返回的trace_id
            """
            p = {"prompt": prompt, "client_id": client_id}
            # data = json.dumps(p).encode('utf-8')
            # req =  urllib.request.Request("http://{}/prompt".format(server_address), data=data)
            # json.loads(urllib.request.urlopen(req).read())
            response = requests.post(f"http://{server_address}/prompt", json=p)
            if response.status_code == 200:
                return response.json()
            else:
                logger.error(f"{response}, {response.text}")
                # print(f"{response}, {response.text}")
                if response.status_code == 403:
                    # print("get , please check your proxy")
                    logger.error("get , please check your proxy")
                return None
        
        def get_images_from_web_socket(self, prompt, prompt_id, client_id, server_address):
            ws = websocket.WebSocket()
            ws.connect("ws://{}/ws?clientId={}".format(server_address, client_id))
            # progress_bar = ProgressBar(prompt, self.progress_bar_node_type)
            
            output_images = {}
            current_node = ""
            while True:
                out = ws.recv()
                # logger.debug(out, type(out))
                print(out, type(out))
                # {"type": "progress", "data": {"value": 49, "max": 50, "prompt_id": "cfd0c1cb-04ae-490d-8ed2-6b16bf103da9", "node": "3"}} 
                # {"type": "progress", "data": {"value": 50, "max": 50, "prompt_id": "cfd0c1cb-04ae-490d-8ed2-6b16bf103da9", "node": "3"}} 
                # {"type": "executing", "data": {"node": "8", "display_node": "8", "prompt_id": "cfd0c1cb-04ae-490d-8ed2-6b16bf103da9"}} 
                if isinstance(out, str):
                    message = json.loads(out)
                    if message['type'] == 'executing': 
                        data = message['data']
                        if 'prompt_id' in data and data['prompt_id'] == prompt_id:
                            if data['node'] is None:
                                break #Execution is done
                            else:
                                current_node = data['node']
                    # progress_bar.update(message)
                else:
                    if current_node in prompt and prompt[current_node]["class_type"] == "SaveImageWebsocket":
                        images_output = output_images.get(current_node, [])
                        images_output.append(out[8:])
                        output_images[current_node] = images_output
        
            return output_images
        def __call__(self, prompt, client_id, server_address):
            if client_id is None:
                client_id = str(uuid.uuid4())
            if server_address is None:
                server_address = get_server_address()
                
            req_data = self.queue_prompt(prompt, client_id, server_address)  # 发起请求
            if req_data is not None:  # 发起请求成功
                logger.info(f"req to {req_data}")
                out_images = self.get_images_from_web_socket(prompt, req_data['prompt_id'], client_id, server_address)  # 阻塞式接受返回
                return out_images
            return None
    comfyui_reqest = ComfyUIRequest()
    import json
    defalut_params = json.load(open("05_flux_fill_outpaint_fp8_3.json"))
    defalut_params["17"]["inputs"]["image"] = os.path.abspath("524169.jpg")    # input image has mul masked
    defalut_params["47"]["inputs"]["image"] = os.path.abspath("524169_mask.jpg")  # mask image
    outs = comfyui_reqest(defalut_params, client_id="12347")
    result_img = buffer2img(outs['50'][0], input_type='bytes')
    

    print(f"req to {req_data}")打印如下:

    req to {'prompt_id': '024d4de7-258b-461c-95fa-a0de3f2fefb0', 'number': 45, 'node_errors': {}}
    

    print(out, type(out))打印如下

    {"type": "status", "data": {"status": {"exec_info": {"queue_remaining": 1}}, "sid": "16745628-e6ae-46a9-99a3-fa3a5d53f586"}} 
    {"type": "execution_cached", "data": {"nodes": ["7", "23", "26", "31", "32", "34", "38", "39", "55", "56", "57", "58"], "prompt_id": "eb77c8c4-40d5-4dc0-a6a9-234c25cb4722", "timestamp": 1740473304127}} 
    {"type": "executed", "data": {"node": "58", "display_node": "58", "output": {"images": [{"filename": "ComfyUI_00022_.png", "subfolder": "", "type": "output"}]}, "prompt_id": "eb77c8c4-40d5-4dc0-a6a9-234c25cb4722"}} 
    {"type": "executed", "data": {"node": "57", "display_node": "57", "output": {"images": [{"filename": "ComfyUI_temp_ukmnl_00001_.png", "subfolder": "", "type": "temp"}]}, "prompt_id": "eb77c8c4-40d5-4dc0-a6a9-234c25cb4722"}} 
    {"type": "executing", "data": {"node": "52", "display_node": "52", "prompt_id": "eb77c8c4-40d5-4dc0-a6a9-234c25cb4722"}} 
    {"type": "progress", "data": {"value": 1, "max": 20, "prompt_id": "eb77c8c4-40d5-4dc0-a6a9-234c25cb4722", "node": "52"}} 
    {"type": "progress", "data": {"value": 2, "max": 20, "prompt_id": "eb77c8c4-40d5-4dc0-a6a9-234c25cb4722", "node": "52"}} 
    {"type": "progress", "data": {"value": 3, "max": 20, "prompt_id": "eb77c8c4-40d5-4dc0-a6a9-234c25cb4722", "node": "52"}} 
    ......
    {"type": "progress", "data": {"value": 19, "max": 20, "prompt_id": "eb77c8c4-40d5-4dc0-a6a9-234c25cb4722", "node": "52"}} 
    {"type": "progress", "data": {"value": 20, "max": 20, "prompt_id": "eb77c8c4-40d5-4dc0-a6a9-234c25cb4722", "node": "52"}} 
    {"type": "executing", "data": {"node": "8", "display_node": "8", "prompt_id": "eb77c8c4-40d5-4dc0-a6a9-234c25cb4722"}} 
    {"type": "executing", "data": {"node": "50", "display_node": "50", "prompt_id": "eb77c8c4-40d5-4dc0-a6a9-234c25cb4722"}} 
    {"type": "progress", "data": {"value": 0, "max": 1, "prompt_id": "eb77c8c4-40d5-4dc0-a6a9-234c25cb4722", "node": "50"}} 
    

    4. 增加调用进度条显示

    ComfyUI运行的时候,我们会发现界面上的运行框等信息会变化,这些都是ComfyUI在执行的每个阶段都会发送socket消息,就像上面打印的日志一样,我们可以捕获到这些日志,并增加一些实时的响应。

    比如,根据上面日志,增加一个进度条功能,然后解开ComfyUIRequest中与ProgressBar相关的两行代码的注释即可。

    from tqdm import tqdm
    class ProgressBar(object):
        def __init__(self, prompt, check_node_types=["KSampler"]):
            self.prompt = prompt
            self.progress_bars = {}
            self.check_node_types = check_node_types
        def update(self, message):
            # {"type": "progress", "data": {"value": 49, "max": 50, "prompt_id": "cfd0c1cb-04ae-490d-8ed2-6b16bf103da9", "node": "3"}} 
            # {"type": "progress", "data": {"value": 50, "max": 50, "prompt_id": "cfd0c1cb-04ae-490d-8ed2-6b16bf103da9", "node": "3"}} 
            # {"type": "executing", "data": {"node": "8", "display_node": "8", "prompt_id": "cfd0c1cb-04ae-490d-8ed2-6b16bf103da9"}}   
            try:
                if message['type'] == 'progress':  # progress
                    node = message["data"]['node']
                    if node in self.progress_bars:
                        self.progress_bars[node].update(1)
                    else:
                        if node is not None and node in self.prompt and \
                            (self.check_node_types is None or self.prompt[node]["class_type"] in self.check_node_types):
                            max_d, cur_d = message["data"]["max"], message["data"]["value"]
                            bar = self.progress_bars[node] = tqdm(total=max_d, desc=self.prompt[node]["_meta"]["title"])
                            bar.update(1)
            except KeyboardInterrupt as e:
                raise e
            except Exception as e:
                pass
    
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

相关阅读

目录[+]

取消
微信二维码
微信二维码
支付宝二维码