当前位置: 首页 > article >正文

使用 Python 构建并调用 ComfyUI 图像生成 API:完整实战指南

快速打造你自己的本地 AI 图像生成服务,支持 Web 前端一键调用!


📌 前言

在 AIGC 快速发展的今天,ComfyUI 作为一款模块化、节点式的图像生成界面,备受开发者青睐。但默认情况下,ComfyUI 主要通过界面交互操作,缺少标准化 API 接口。

本文将手把手教你如何:

  • Python 脚本调用 ComfyUI 本地服务生成图像;

  • 使用 FastAPI 封装 API 接口

  • 搭建一个简单的 前端网页输入提示词 → 实时获取生成图像 的完整闭环系统。

适合希望将本地 ComfyUI 服务嵌入前后端系统或自动化流程的开发者。


🧱 环境准备

  • 安装并运行 ComfyUI 本地服务

  • Python >= 3.10

  • 安装依赖:

pip install fastapi uvicorn websockets

🧠 后端模块分层

我们将后端分为两层:

  1. comfyuiservice.py:负责构造图像生成的 Prompt、连接 WebSocket、拉取图片等底层逻辑。

import websocket
import uuid
import json
import urllib.request
import urllib.parse
save_image_websocket = 'SaveImage'
server_address = "127.0.0.1:8188"
client_id = str(uuid.uuid4())def get_prompt_with_workflow(input, batch_size=3):prompt_text = r'''{"5": {"inputs": {"width": 1024,"height": 576,"batch_size": BATCH_SIZE_PLACEHOLDER},"class_type": "EmptyLatentImage","_meta": {"title": "空Latent"}},"6": {"inputs": {"text": "","clip": ["11",0]},"class_type": "CLIPTextEncode","_meta": {"title": "CLIP文本编码器"}},"8": {"inputs": {"samples": ["13",0],"vae": ["10",0]},"class_type": "VAEDecode","_meta": {"title": "VAE解码"}},"9": {"inputs": {"filename_prefix": "Liblib","images": ["8",0]},"class_type": "SaveImage","_meta": {"title": "保存图像"}},"10": {"inputs": {"vae_name": "taef1"},"class_type": "VAELoader","_meta": {"title": "VAE加载器"}},"11": {"inputs": {"clip_name1": "flux_text_encoders\\t5xxl_fp8_e4m3fn.safetensors","clip_name2": "flux_text_encoders\\clip_l.safetensors","type": "flux"},"class_type": "DualCLIPLoader","_meta": {"title": "双CLIP加载器"}},"12": {"inputs": {"unet_name": "F.1基础算法模型-哩布在线可运行_F.1-dev-fp8.safetensors","weight_dtype": "fp8_e4m3fn"},"class_type": "UNETLoader","_meta": {"title": "UNET加载器"}},"13": {"inputs": {"noise": ["25",0],"guider": ["22",0],"sampler": ["16",0],"sigmas": ["17",0],"latent_image": ["5",0]},"class_type": "SamplerCustomAdvanced","_meta": {"title": "自定义采样器(高级)"}},"16": {"inputs": {"sampler_name": "euler"},"class_type": "KSamplerSelect","_meta": {"title": "K采样器选择"}},"17": {"inputs": {"scheduler": "simple","steps": 20,"denoise": 1,"model": ["12",0]},"class_type": "BasicScheduler","_meta": {"title": "基础调度器"}},"22": {"inputs": {"model": ["12",0],"conditioning": ["6",0]},"class_type": "BasicGuider","_meta": {"title": "基础引导"}},"25": {"inputs": {"noise_seed": 334879893459679},"class_type": "RandomNoise","_meta": {"title": "随机噪波"}}}'''prompt_text = prompt_text.replace("BATCH_SIZE_PLACEHOLDER", str(batch_size))prompt_json = json.loads(prompt_text)prompt_json["6"]["inputs"]["text"] = inputreturn prompt_jsondef queue_prompt(prompt):p = {"prompt": prompt, "client_id": client_id}data = json.dumps(p).encode('utf-8')req = urllib.request.Request(f"http://{server_address}/prompt", data=data)return json.loads(urllib.request.urlopen(req).read())def get_image(filename, subfolder, folder_type):data = {"filename": filename, "subfolder": subfolder, "type": folder_type}url_values = urllib.parse.urlencode(data)with urllib.request.urlopen(f"http://{server_address}/view?{url_values}") as response:return response.read()def get_images(ws, prompt, batch_size):prompt_id = queue_prompt(prompt)['prompt_id']print(f"📩 prompt_id: {prompt_id}")images_data = []while True:out = ws.recv()if isinstance(out, str):try:message = json.loads(out)except json.JSONDecodeError:continuemsg_type = message.get('type')if msg_type == 'executed':data = message['data']current_prompt_id = data.get('prompt_id')node = data.get('node')print(f"🔄 执行中 - prompt_id: {current_prompt_id}, 节点: {node}")if current_prompt_id == prompt_id and node == "9":images = data.get('output', {}).get('images', [])if images and len(images) == batch_size:print(f"🖼️ 收到节点9的所有图像信息,共{len(images)}张")for img_info in images:filename = img_info['filename']subfolder = img_info.get('subfolder', '')folder_type = img_info.get('type', 'output')print(f"🖼️ 获取文件:{filename}, 子文件夹:{subfolder}, 类型:{folder_type}")image_bytes = get_image(filename, subfolder, folder_type)images_data.append((filename, image_bytes))breakelse:passreturn images_datadef fetch_images_from_comfy(input, batch_size=3):ws = websocket.WebSocket()ws.connect(f"ws://{server_address}/ws?clientId={client_id}")images = get_images(ws, get_prompt_with_workflow(input, batch_size), batch_size)ws.close()return imagesif __name__ == '__main__':# 生成3张图,保存为output_0.png, output_1.png, output_2.pngbatch = 3results = fetch_images_from_comfy("a gril", batch_size=batch)if results:for idx, (filename, img_bytes) in enumerate(results):out_name = f"output_{idx}.png"with open(out_name, "wb") as f:f.write(img_bytes)print(f"✅ 图像保存成功:{out_name}")else:print("❌ 没有生成图像")
  1. main.py:用 FastAPI 提供标准接口,供前端或其他服务调用。

from fastapi import FastAPI, Query  # 导入FastAPI主框架和用于接收查询参数的Query
from fastapi.responses import StreamingResponse  # 用于返回流式响应(如图片流)
from fastapi.middleware.cors import CORSMiddleware  # 导入跨域资源共享中间件
import io  # 导入io模块,用于处理内存中的二进制流
import comfyuiservice  # 导入自定义的comfyui服务模块(负责图像生成)app = FastAPI()  # 创建FastAPI应用实例# 添加跨域中间件,允许所有来源访问API,适合开发和测试阶段
app.add_middleware(CORSMiddleware,allow_origins=["*"],  # 允许所有来源allow_credentials=True,  # 允许携带凭证allow_methods=["*"],  # 允许所有HTTP方法(GET、POST等)allow_headers=["*"],  # 允许所有请求头
)# 定义一个GET接口,路径为 /get-image,接收一个名为input的查询字符串参数
@app.get("/get-image")
async def get_image(input: str = Query(None)):# 调用comfyuiservice模块的fetch_image_from_comfy函数,传入输入文本,生成图像二进制数据images = comfyuiservice.fetch_images_from_comfy(input)# 将二进制图像数据放入BytesIO流中,方便返回给客户端image_stream = io.BytesIO(images[0][1]) # 只获取一张图片# 以流式响应返回图片,声明媒体类型为PNG格式return StreamingResponse(image_stream, media_type="image/png")# 定义一个简单的GET接口,路径为 /hello,用于测试服务是否正常
@app.get("/hello")
def read_hello():return {"message": "Hello World!"}  # 返回一个JSON字典,表示接口工作正常

🧩 comfyuiservice.py 详解

这是核心逻辑所在,通过 Python 控制 ComfyUI 本地服务进行图像生成。

✅ 核心功能包括:

  • 构建 ComfyUI Workflow Prompt

  • 使用 WebSocket 监听图像生成完成信号

  • 通过 HTTP 接口拉取图像二进制流

📌 使用示例:

results = fetch_images_from_comfy("a gril", batch_size=1)

返回的图像是二进制格式,可直接保存为 .png 文件或通过接口流式返回。


🌐 main.py:FastAPI 封装接口

通过 FastAPI,我们将图像生成功能开放为 HTTP API,方便前端或自动化调用。

🔧 核心接口

GET /get-image?input=你的提示词

返回内容:生成的图像(image/png)

✅ 支持跨域(CORS)

通过添加 CORSMiddleware,支持前端跨域请求,方便调试和部署。


💻 前端页面:一键生成图像

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Display Image</title>
</head>
<body><h1>Display Image from Comfy UI Server</h1><!-- Input field to get user input --><input type="text" id="user-input" placeholder="Enter text for image" /><button onclick="fetchImage()">Load Image</button><!-- Container for displaying the image --><div id="image-container"></div><script>function fetchImage() {// Get the value from the input fieldconst inputValue = document.getElementById('user-input').value;// Fetch the image with the input as a query parameterfetch(`http://127.0.0.1:8000/get-image?input=${encodeURIComponent(inputValue)}`).then(response => {if (!response.ok) throw new Error('Image not found');return response.blob();}).then(blob => {// Create an image element and set its source to the fetched blobconst img = document.createElement('img');img.src = URL.createObjectURL(blob);img.alt = "Image from server";// Clear any existing image and display the new onedocument.getElementById('image-container').innerHTML = '';document.getElementById('image-container').appendChild(img);}).catch(error => console.error('Error:', error));}</script>
</body>
</html>

前端请求 http://localhost:8000/get-image?input=xxx,后台返回图像 blob 后动态展示。


📦 项目结构建议

comfyui-api/
├── main.py                 # FastAPI 启动文件
├── comfyuiservice.py       # 图像生成逻辑
├── index.html          # 前端页面

🚀 启动服务

uvicorn main:app --reload

访问 http://127.0.0.1:8000/hello 查看是否运行成功。


🧪 效果演示

在浏览器中打开 HTML 页面,输入提示词如 【a cat】,点击生成,几秒内即可看到生成图像显示在页面上。


✅ 总结

通过本文教程,我们完成了:

  • 构建 Python 图像生成模块对接本地 ComfyUI;

  • 使用 FastAPI 提供 HTTP API;

  • 简单前端调用生成图像,完成 AIGC 接口开发。

🧾 结语

通过本文,你已经学会了如何使用 Python 和 FastAPI 调用本地 ComfyUI 接口,实现前端一键生成图像的完整流程。

这个方案适合:

  • AIGC 产品原型开发

  • 本地 AI 模型部署与集成

  • 前后端协作式图像生成系统搭建

如果你觉得这篇教程对你有帮助,欢迎点赞、收藏和转发分享给更多开发者
💬 如果你在部署过程中遇到任何问题,或有更好的优化建议,欢迎在评论区留言交流

你的每一个反馈,都是我持续更新的动力!✨

🔖 引用与参考资料

  • ComfyUI 官方仓库https://github.com/comfyanonymous/ComfyUI

  • FastAPIFastAPI framework, high performance, easy to learn, fast to code, ready for productionhttps://fastapi.tiangolo.com/

  • WebSocket 文档 - MDNhttps://developer.mozilla.org/zh-CN/docs/Web/API/WebSocket

  • GitHub - dci05049/ComfyUiWebserverContribute to dci05049/ComfyUiWebserver development by creating an account on GitHub.https://github.com/dci05049/ComfyUiWebserver

相关文章:

使用 Python 构建并调用 ComfyUI 图像生成 API:完整实战指南

快速打造你自己的本地 AI 图像生成服务&#xff0c;支持 Web 前端一键调用&#xff01; &#x1f4cc; 前言 在 AIGC 快速发展的今天&#xff0c;ComfyUI 作为一款模块化、节点式的图像生成界面&#xff0c;备受开发者青睐。但默认情况下&#xff0c;ComfyUI 主要通过界面交互…...

嵌入式学习笔记-freeRTOS taskENTER_CRITICAL(_FROM_ISR)跟taskEXIT_CRITICAL(_FROM_ISR)函数解析

一 函数taskENTER_CRITICAL&#xff0c;taskEXIT_CRITICAL 函数taskENTER_CRITICAL最终实现如下&#xff1a; 第①处按照系统设定的configMAX_SYSCALL_INTERRUPT_PRIORITY值对中断进行屏蔽 第②处调用一次自增一次 第③处检查中断状态寄存器位&#xff0c;如果有任何中断位置…...

Unity基础-数学向量

Unity基础-数学向量 二、向量相关用法 概述 向量在Unity游戏开发中扮演着重要角色&#xff0c;用于表示位置、方向、速度等。Unity提供了Vector2、Vector3等结构体来处理向量运算。 1. 向量基础操作 1.1 向量创建和访问 // 创建向量 Vector3 position new Vector3(1, 2,…...

【华为云Astro-服务编排】服务编排中图元的使用与配置

目录 子服务编排图元 子服务编排图元的作用 如何使用子服务编排图元 脚本图元 脚本图元的作用 如何使用脚本图元 记录创建图元 记录创建图元的作用 如何使用记录创建图元 记录删除图元 记录删除图元的作用 如何使用记录删除图元 记录查询图元 记录查询图元的作用…...

1panel面板中部署SpringBoot和Vue前后端分离系统 【图文教程】

1panel面板中部署SpringBoot和Vue前后端分离系统 一&#xff0c;1panel面板部署二&#xff0c;安装OpenResty三&#xff0c;安装MySQL&#xff0c;Redis等Spring boot 运行依赖环境四&#xff0c;SpringBoot 应用配置及打包部署配置打包部署 五 &#xff0c;前端VUE应用配置打包…...

C++.OpenGL (7/64)摄像机(Camera)

摄像机(Camera) 摄像机系统核心组件 #mermaid-svg-lmysTXAyyzKytiOC {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-lmysTXAyyzKytiOC .error-icon{fill:#552222;}#mermaid-svg-lmysTXAyyzKytiOC .error-text{fi…...

使用xdocreport导出word

之前java总用freemaker进行导出&#xff0c;但是改xml实在是太繁琐了&#xff0c;这次找了另一个工具进行体验. 一、简单导出 pom引入 <dependency><groupId>fr.opensagres.xdocreport</groupId><artifactId>fr.opensagres.xdocreport.core</arti…...

青少年编程与数学 01-011 系统软件简介 05 macOS操作系统

青少年编程与数学 01-011 系统软件简介 05 macOS操作系统 一、历史发展&#xff08;一&#xff09;经典 Mac OS&#xff08;1984-2001&#xff09;&#xff08;二&#xff09;Mac OS X&#xff08;2001-2016&#xff09;&#xff08;三&#xff09;macOS&#xff08;2016-至今&…...

Python打卡训练营学习记录Day43

作业&#xff1a; kaggle找到一个图像数据集&#xff0c;用cnn网络进行训练并且用grad-cam做可视化 进阶&#xff1a;并拆分成多个文件 从谷歌图片中拍摄的 10 种不同类别的动物图片 数据预处理 import os from torchvision import datasets, transforms from torch.utils…...

【Android基础回顾】二:handler消息机制

Android 的 Handler 机制 是 Android 应用中实现线程间通信、任务调度、消息分发的核心机制之一&#xff0c;它基于 消息队列&#xff08;MessageQueue&#xff09; 消息循环&#xff08;Looper&#xff09; 消息处理器&#xff08;Handler&#xff09; 组成。 1 handler的使用…...

每日Prompt:每天上班的状态

提示词 一个穿着清朝官服的僵尸脸上贴着符纸&#xff0c;在电脑面前办公&#xff0c;房间阴暗&#xff0c;电脑桌面很乱&#xff0c;烟灰缸里面满是烟头...

.net ORM框架dapper批量插入

.NET ORM 框架 Dapper 批量插入全解析 在 .NET 开发中&#xff0c;与数据库交互是常见需求。Dapper 作为轻量级的 ORM&#xff08;对象关系映射&#xff09;库&#xff0c;在简化数据库交互方面表现出色。今天我们就来深入探讨 Dapper 实现批量插入的几种方法。 为什么需要批…...

C++11 右值引用:从入门到精通

文章目录 一、引言二、左值和右值&#xff08;一&#xff09;概念&#xff08;二&#xff09;区别和判断方法 三、左值引用和右值引用&#xff08;一&#xff09;左值引用&#xff08;二&#xff09;右值引用 四、移动语义&#xff08;一&#xff09;概念和必要性&#xff08;二…...

.net 使用MQTT订阅消息

在nuGet下载M2Mqtt V4.3.0版本。&#xff08;支持.net framework&#xff09; 订阅主题 public void LoadMQQCData() {string enpoint "xxx.xxx.x.x";//ip地址int port 1883;//端口string user "usrname";//用户名string pwd "pwd";//密码…...

Python实现快速排序的三种经典写法及算法解析

今天想熟悉一下python的基础写法&#xff0c;那就从最经典的快速排序来开始吧&#xff1a; 1、经典分治写法&#xff08;原地排序&#xff09; 时间复杂度&#xff1a;平均O(nlogn)&#xff0c;最坏O(n) 空间复杂度&#xff1a;O(logn)递归栈空间 特点&#xff1a;通过左右指针…...

【递归、搜索与回溯】综合练习(四)

&#x1f4dd;前言说明&#xff1a; 本专栏主要记录本人递归&#xff0c;搜索与回溯算法的学习以及LeetCode刷题记录&#xff0c;按专题划分每题主要记录&#xff1a;&#xff08;1&#xff09;本人解法 本人屎山代码&#xff1b;&#xff08;2&#xff09;优质解法 优质代码…...

强化学习入门:Gym实现CartPole随机智能体

前言 最近想开一个关于强化学习专栏&#xff0c;因为DeepSeek-R1很火&#xff0c;但本人对于LLM连门都没入。因此&#xff0c;只是记录一些类似的读书笔记&#xff0c;内容不深&#xff0c;大多数只是一些概念的东西&#xff0c;数学公式也不会太多&#xff0c;还望读者多多指教…...

STM32:CAN总线精髓:特性、电路、帧格式与波形分析详解

声明&#xff1a;此博客是我的学习笔记&#xff0c;所看课程是江协科技的CAN总线课程&#xff0c;知识点都大同小异&#xff0c;我仅进行总结并加上了我自己的理解&#xff0c;所引案例也都是课程中的案例&#xff0c;希望对你的理解有所帮助&#xff01; 知识点1【CAN总线的概…...

贝叶斯深度学习!华科大《Nat. Commun.》发表BNN重大突破!

华科大提出基于贝叶斯深度学习的超分辨率成像&#xff0c;成功被Nat. Commun.收录。可以说&#xff0c;这是贝叶斯神经网络BNN近期最值得关注的成果之一了。另外还有AAAI 2025上的Bella新框架&#xff0c;计算成本降低了99.7%&#xff0c;也非常值得研读。 显然鉴于BNN“不确定…...

【大模型LLM学习】Flash-Attention的学习记录

【大模型LLM学习】Flash-Attention的学习记录 0. 前言1. flash-attention原理简述2. 从softmax到online softmax2.1 safe-softmax2.2 3-pass safe softmax2.3 Online softmax2.4 Flash-attention2.5 Flash-attention tiling 0. 前言 Flash Attention可以节约模型训练和推理时间…...

三、元器件的选型

前言&#xff1a;我们确立了题目的功能后&#xff0c;就可以开始元器件的选型&#xff0c;元器件的选型关乎到我们后面代码编写的一个难易。 一、主控的选择 主控的选择很大程度上决定我们后续使用的代码编译器&#xff0c;比如ESP32使用的是VScode&#xff0c;或者Arduino&a…...

精益数据分析(95/126):Socialight的定价转型启示——B2B商业模式的价格策略与利润优化

精益数据分析&#xff08;95/126&#xff09;&#xff1a;Socialight的定价转型启示——B2B商业模式的价格策略与利润优化 在创业过程中&#xff0c;从B2C转向B2B不仅是商业模式的转变&#xff0c;更是定价策略与成本结构的全面重构。今天&#xff0c;我们将通过Socialight的实…...

stm32_DMA

DMA 1. 概念与基本原理 DMA&#xff0c;全称Direct Memory Access&#xff0c;即直接存储器访问。它是微控制器&#xff08;MCU&#xff09;、嵌入式处理器中的一个独立硬件模块&#xff0c;用于在无需CPU干预的情况下&#xff0c;在不同内存区域&#xff08;包括外设寄存器和…...

物联网数据归档之数据存储方案选择分析

在上一篇文章中《物联网数据归档方案选择分析》中凯哥分析了归档设计的两种方案,并对两种方案进行了对比。这篇文章咱们就来分析分析,归档后数据应该存储在哪里?及存储方案对比。 这里就选择常用的mysql及taos数据库来存储归档后的数据吧。 你在处理设备归档表存储方案时对…...

【自动驾驶避障开发】如何让障碍物在 RViz 中‘显形’?呈现感知数据转 Polygon 全流程

【自动驾驶避障开发】如何让障碍物在 RViz 中"显形"?呈现感知数据转 Polygon 全流程 自动驾驶系统中的障碍物可视化是开发调试过程中至关重要的一环。本文将详细介绍如何将自动驾驶感知模块检测到的障碍物数据转换为RViz可显示的Polygon(多边形)形式,实现障碍物…...

【C语言】C语言经典小游戏:贪吃蛇(上)

文章目录 一、游戏背景及其功能二、Win32 API介绍1、Win32 API2、控制台程序3、定位坐标&#xff08;COORD&#xff09;4、获得句柄&#xff08;GetStdHandle&#xff09;5、获得光标属性&#xff08;GetConsoleCursorInfo&#xff09;1&#xff09;描述光标属性&#xff08;CO…...

usbutils工具的使用帮助

作为嵌入式系统开发中的常用工具&#xff0c;usbutils 是一套用于管理和调试USB设备的Linux命令行工具集。以下是其核心功能和使用方法的详细说明&#xff1a; 1. 工具组成 核心命令&#xff1a; lsusb&#xff1a;列出所有连接的USB设备及详细信息&#xff08;默认安装&#…...

vue2中使用jspdf插件实现页面自定义块pdf下载

pdf下载 实现pdf下载的环境安装jspdf插件在项目中使用 实现pdf下载的环境 项目需求案例背景&#xff0c;点击【pdf下载】按钮&#xff0c;弹出pdf下载弹窗&#xff0c;显示需要下载四个模块的下载进度&#xff0c;下载完成后&#xff0c;关闭弹窗即可&#xff01; 项目使用的是…...

如何防止服务器被用于僵尸网络(Botnet)攻击 ?

防止服务器被用于僵尸网络&#xff08;Botnet&#xff09;攻击是关键的网络安全措施之一。僵尸网络是黑客利用大量被感染的计算机、服务器或物联网设备来发起攻击的网络。以下是关于如何防止服务器被用于僵尸网络攻击的技术文章&#xff1a; 防止服务器被用于僵尸网络&#xff…...

基于cornerstone3D的dicom影像浏览器 第二十九章 自定义菜单组件

文章目录 前言一、程序结构1. 菜单数据结构2. XMenu.vue3. XSubMenu.vue4. XSubMenuSlot.vue5. XMenuItem.vue 二、调用流程总结 前言 菜单用于组织程序功能&#xff0c;为用户提供导航。是用户与程序交互非常重要的接口。 开源组件库像Element Plus和Ant Design中都提供了功能…...