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

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

1. 调整Workflow

我们要部署以下workflow
在这里插入图片描述
做两个修改

  • 输入改为从Load Image(Base64) 读入图片,当然使用上面的从路径中读图也是可以的
  • 输出改为SaveImageWebsocket节点,通过websocket返回图片,当然使用SaveImage给定路径也是可以的
    ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/d2e2f42f33df4567a63750900590cb75.png

2. 导出API调用json文件

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 <403>, please check your proxy")
                logger.error("get <403>, 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"}} <class 'str'>
            # {"type": "progress", "data": {"value": 50, "max": 50, "prompt_id": "cfd0c1cb-04ae-490d-8ed2-6b16bf103da9", "node": "3"}} <class 'str'>
            # {"type": "executing", "data": {"node": "8", "display_node": "8", "prompt_id": "cfd0c1cb-04ae-490d-8ed2-6b16bf103da9"}} <class 'str'>
            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"}} <class 'str'>
{"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}} <class 'str'>
{"type": "executed", "data": {"node": "58", "display_node": "58", "output": {"images": [{"filename": "ComfyUI_00022_.png", "subfolder": "", "type": "output"}]}, "prompt_id": "eb77c8c4-40d5-4dc0-a6a9-234c25cb4722"}} <class 'str'>
{"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"}} <class 'str'>
{"type": "executing", "data": {"node": "52", "display_node": "52", "prompt_id": "eb77c8c4-40d5-4dc0-a6a9-234c25cb4722"}} <class 'str'>
{"type": "progress", "data": {"value": 1, "max": 20, "prompt_id": "eb77c8c4-40d5-4dc0-a6a9-234c25cb4722", "node": "52"}} <class 'str'>
{"type": "progress", "data": {"value": 2, "max": 20, "prompt_id": "eb77c8c4-40d5-4dc0-a6a9-234c25cb4722", "node": "52"}} <class 'str'>
{"type": "progress", "data": {"value": 3, "max": 20, "prompt_id": "eb77c8c4-40d5-4dc0-a6a9-234c25cb4722", "node": "52"}} <class 'str'>
......
{"type": "progress", "data": {"value": 19, "max": 20, "prompt_id": "eb77c8c4-40d5-4dc0-a6a9-234c25cb4722", "node": "52"}} <class 'str'>
{"type": "progress", "data": {"value": 20, "max": 20, "prompt_id": "eb77c8c4-40d5-4dc0-a6a9-234c25cb4722", "node": "52"}} <class 'str'>
{"type": "executing", "data": {"node": "8", "display_node": "8", "prompt_id": "eb77c8c4-40d5-4dc0-a6a9-234c25cb4722"}} <class 'str'>
{"type": "executing", "data": {"node": "50", "display_node": "50", "prompt_id": "eb77c8c4-40d5-4dc0-a6a9-234c25cb4722"}} <class 'str'>
{"type": "progress", "data": {"value": 0, "max": 1, "prompt_id": "eb77c8c4-40d5-4dc0-a6a9-234c25cb4722", "node": "50"}} <class 'str'>

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"}} <class 'str'>
        # {"type": "progress", "data": {"value": 50, "max": 50, "prompt_id": "cfd0c1cb-04ae-490d-8ed2-6b16bf103da9", "node": "3"}} <class 'str'>
        # {"type": "executing", "data": {"node": "8", "display_node": "8", "prompt_id": "cfd0c1cb-04ae-490d-8ed2-6b16bf103da9"}} <class 'str'>  
        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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/977910.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【多模态大模型】端侧语音大模型minicpm-o:手机上的 GPT-4o 级多模态大模型

MiniCPM-o ,它是一款 开源、轻量级 的多模态大语言模型,目标是在手机等资源受限的环境中实现 GPT-4o 级别的多模态能力! 1. MiniCPM-o:小身材,大能量! MiniCPM-o 的名字已经暗示了它的核心特点:Mini (小巧) 和 CPM (中文预训练模型),最后的 “o” 则代表 Omnimodal …

【C++】深入理解List:双向链表的应用

凭时间赢来的东西&#xff0c;时间肯定会为之作证。 前言 这是我自己学习C的第七篇博客总结。后期我会继续把C学习笔记开源至博客上。 上一期笔记是关于C的vector类知识&#xff0c;没看的同学可以过去看看&#xff1a;【C】探索Vector&#xff1a;灵活的数据存储解决方案-CS…

Spring Cloud源码 - Eureka源码原理分析

Eureka源码原理分析 文章目录 Eureka源码原理分析一&#xff1a;启动过程源码1&#xff1a;初始化环境2&#xff1a;初始化上下文2.1&#xff1a;加载erueka-server配置文件2.2&#xff1a;构造实例信息管理器2.3&#xff1a;初始化erueka-client2.4&#xff1a;处理注册相关的…

2.23操作列表

操作列表 一&#xff1a;遍历整个列表 – for循环 names[xixi, gofy, haha] for name in names:print(f"{name} is very very good good")print(f"{name}&#xff0c;欢迎回家\n")xixi is very very good good xixi&#xff0c;欢迎回家gofy is very ver…

Solidity study

Solidity 开发环境 Solidity编辑器&#xff1a;Solidity编辑器是一种专门用于编写和编辑Solidity代码的编辑器。常用的Solidity编辑器包括Visual Studio Code、Atom和Sublime Text。以太坊开发环境&#xff1a;以太坊开发环境&#xff08;Ethereum Development Environment&am…

Git版本控制系统---本地操作(万字详解!)

目录 git基本配置 认识工作区、暂存区、版本库 添加文件--情况一&#xff1a; 添加文件-情况二: 修改文件: 版本回退&#xff1a; git基本配置 1.初始化本地仓库&#xff0c;注意&#xff1a;一定要在一个目录下进行&#xff0c;一般都是新建一个文件夹&#xff0c;在文件…

IDEA配置JSP环境

首先下载IDEA2021.3&#xff0c;因为最新版本不能简单配置web开发环境。然后新建一个java开发项目&#xff1a; 然后右键创建的项目&#xff0c;添加web框架&#xff1a; 选择web appliciation 在web inf文件夹下创建classes和lib文件夹&#xff1a; 点击file &#xff0c;选择…

前端兼容处理接口返回的文件流或json数据

参考文档&#xff1a;JavaScript | MDN 参考链接&#xff1a;Blob格式转json格式&#xff0c;拿到后端返回的json数据_blob转json-CSDN博客 参考链接&#xff1a;https://juejin.cn/post/7117939029567340557 场景&#xff1a;导入上传文件&#xff0c;导入成功&#xff0c;…

短剧源码部署搭建小程序搭建IAA+IAP混合解锁模式

在当今数字化内容消费迅速增长的时代&#xff0c;短剧作为一种新兴的内容形式&#xff0c;凭借其短小精悍、节奏紧凑的特点&#xff0c;迅速吸引了大量用户。作为一名软件体验测试人员&#xff0c;我有幸体验了一款集创新与实用为一体的短剧小程序。这款小程序不仅在前端用户体…

网络原理---HTTP/HTTPS

通过之前的网络编程&#xff0c;我们已经初步了解UDP和TCP的基本实现方法&#xff0c;接下来我们对其进一步的学习。 在网络编程中&#xff1a; 1.读和写数据通过Socket&#xff0c;通过Socket内置的InputStream和OutputStream(读写的基本单位都是字节&#xff09;。2.当在编…

【Python修仙编程】(二) Python3灵源初探(2)

第一部分&#xff1a;林羽的修仙之旅——字符串与布尔类型的修炼 林羽站在练气期一阶的起点&#xff0c;望着手中的《Python无极心法》秘籍&#xff0c;心中充满了期待。师傅玄天真人在一旁微笑着说道&#xff1a;“林羽&#xff0c;今天我们要修炼的是‘字符串’和‘布尔类型…

【HTML— 快速入门】HTML 基础

准备工作 vscode下载 百度网盘 Subline Text 下载 Sublime Text下载 百度网盘 vscode 下载 Sublime Text 是一款轻量好用的文本编辑器&#xff0c;我们在写前端代码时&#xff0c;使用 Sublime Text 打开比使用记事本打开&#xff0c;得到的代码体验更好&#xff0c;比 vscode…

pipeline 使用git parameter插件实现动态选择分支构造

效果&#xff0c;&#xff0c;点击build with Parameters 就会出现右边的当前仓库的所有的分支&#xff0c;默认最多显示5个&#xff0c;可以修改配置&#xff0c;修改显示的最大分支数量。如果分支太多&#xff0c;可以通过右边的过滤框输入过滤。 安装git params插件 搜索g…

国产OS上完整编译Qt5.15、搭建基本开发环境需要的库

近期有师弟问我国产OS安装Qt5.15编译老是不完整&#xff0c;不是没声音&#xff0c;就是没视频&#xff0c;或者没有xcb。通过QEMU模拟Arm64&#xff0c;闲来20几天摸索&#xff0c;完整编译了Qt5.15&#xff0c;并编译成功了我的SDR玩具taskBus。 1.主要结论&#xff1a; 该O…

数据库 安装initializing database不通过

出现一下情况时&#xff1a; 处理方法&#xff1a; 将自己的电脑名称 中文改成英文 即可通过

【视频2 - 4】初识操作系统,Linux,虚拟机

&#x1f4dd;前言说明&#xff1a; ●本专栏主要记录本人的基础算法学习以及LeetCode刷题记录&#xff0c;主要跟随B站博主灵茶山的视频进行学习&#xff0c;专栏中的每一篇文章对应B站博主灵茶山的一个视频 ●题目主要为B站视频内涉及的题目以及B站视频中提到的“课后作业”。…

AI绘画软件Stable Diffusion详解教程(2):Windows系统本地化部署操作方法(专业版)

一、事前准备 1、一台配置不错的电脑&#xff0c;英伟达显卡&#xff0c;20系列起步&#xff0c;建议显存6G起步&#xff0c;安装win10或以上版本&#xff0c;我的显卡是40系列&#xff0c;16G显存&#xff0c;所以跑大部分的模型都比较快&#xff1b; 2、科学上网&#xff0…

将Ubuntu操作系统的安装源设置为阿里云

在使用Ubuntu操作系统时,默认的软件源通常是国外的仓库,这可能会导致软件安装和更新速度较慢。为了提高下载速度和稳定性,我们可以将Ubuntu的安装源设置为阿里云镜像源。以下是详细步骤: 一、准备工作 在开始之前,请确保您的Ubuntu系统可以正常上网,并且您拥有管理员权…

IP-------GRE和MGRE

4.GRE和MGRE 1.应用场景 现实场景 居家工作&#xff0c;公司工作&#xff0c;分公司工作----------需要传输交换数据--------NAT---在该场景中需要两次NAT&#xff08;不安全&#xff09; 为了安全有两种手段-----1.物理专线---成本高 2.VPN--虚拟专用网---隧道技术--封装技…

Visual Studio Code 跨平台安装与配置指南(附官方下载链接)

一、软件定位与核心功能 Visual Studio Code&#xff08;简称VS Code&#xff09;是微软开发的开源跨平台代码编辑器&#xff0c;支持超过50种编程语言的智能补全、调试和版本控制功能。2025版本新增AI辅助编程模块&#xff0c;可自动生成单元测试代码和API文档注释。 二、下载…