Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
424c9a9423 | ||
|
|
8f60c81ef3 | ||
|
|
dd648d1ae5 | ||
|
|
02e839e272 | ||
|
|
ec8c56707b | ||
|
|
1e8d317ee8 | ||
|
|
e81df111a7 | ||
|
|
90e55ffe14 | ||
|
|
4e73b1d3fc | ||
|
|
c2292850bb |
@@ -1,15 +1,25 @@
|
||||
##
|
||||
v0.2.7 🚀🚗🚚🏃
|
||||
v0.3.0 🚀🚗🚚🏃
|
||||
|
||||
- [Add getting camera video stream](./workflow/7-camera-workflow.json)
|
||||
- Add a slider to the floating window, which can be used as input for denoise
|
||||
- Add random seed control method to the floating window
|
||||
- OSupport for calling multiple GPTs
|
||||
- Added support for setting proxies: HTTP_PROXY, HTTPS_PROXY, http_proxy, https_proxy ✅
|
||||
|
||||
- Added a new Speech feature node, enabling the use of a voice assistant: SpeechRecognition & SpeechSynthesis 🎙️
|
||||
|
||||
- Added TextImage node, allowing conversion of text into image format 📷
|
||||
|
||||
- Added SvgImage node, enabling layout parsing and poster generation in conjunction with the Layer class node 🖼️
|
||||
|
||||
- Added an experimental 3DImage node for loading 3D models 🌟
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
### SpeechRecognition & SpeechSynthesis
|
||||

|
||||
|
||||
[Voice + Real-time Face Swap Workflow](./workflow/语音+实时换脸workflow.json)
|
||||
|
||||
### ScreenShareNode & FloatingVideoNode
|
||||
> Now comfyui supports capturing screen pixel streams from any software and can be used for LCM-Lora integration. Let's get started with implementation and design! 💻🌐
|
||||
|
||||
|
||||
+7
-1
@@ -293,8 +293,10 @@ from .nodes.Vae import VAELoader,VAEDecode
|
||||
from .nodes.ScreenShareNode import ScreenShareNode,FloatingVideo
|
||||
from .nodes.Clipseg import CLIPSeg,CombineMasks
|
||||
from .nodes.ChatGPT import ChatGPTNode,ShowTextForGPT,CharacterInText
|
||||
from .nodes.Audio import SpeechRecognition,SpeechSynthesis
|
||||
from .nodes.Utils import ColorInput,FontInput
|
||||
|
||||
|
||||
# 要导出的所有节点及其名称的字典
|
||||
# 注意:名称应全局唯一
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
@@ -324,6 +326,8 @@ NODE_CLASS_MAPPINGS = {
|
||||
"ChatGPTOpenAI":ChatGPTNode,
|
||||
"ShowTextForGPT":ShowTextForGPT,
|
||||
"CharacterInText":CharacterInText,
|
||||
"SpeechRecognition":SpeechRecognition,
|
||||
"SpeechSynthesis":SpeechSynthesis,
|
||||
"Color":ColorInput,
|
||||
"Font":FontInput
|
||||
}
|
||||
@@ -338,7 +342,9 @@ NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"FloatingVideo":"FloatingVideo ♾️Mixlab",
|
||||
"ChatGPTOpenAI":"ChatGPT ♾️Mixlab",
|
||||
"ShowTextForGPT":"ShowTextForGPT ♾️Mixlab",
|
||||
"MergeLayers":"MergeLayers ♾️Mixlab"
|
||||
"MergeLayers":"MergeLayers ♾️Mixlab",
|
||||
"SpeechSynthesis":"SpeechSynthesis ♾️Mixlab",
|
||||
"SpeechRecognition":"SpeechRecognition ♾️Mixlab"
|
||||
}
|
||||
|
||||
# web ui的节点功能
|
||||
|
||||
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 73 KiB |
@@ -0,0 +1,46 @@
|
||||
|
||||
|
||||
|
||||
|
||||
class SpeechRecognition:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {"required": {
|
||||
"upload":("AUDIOINPUTMIX",), },
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
RETURN_NAMES = ("prompt",)
|
||||
|
||||
FUNCTION = "run"
|
||||
|
||||
CATEGORY = "♾️Mixlab/audio"
|
||||
|
||||
INPUT_IS_LIST = False
|
||||
OUTPUT_IS_LIST = (False,)
|
||||
|
||||
def run(self,upload):
|
||||
return (upload,)
|
||||
|
||||
|
||||
class SpeechSynthesis:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"text": ("STRING", {"forceInput": True}),
|
||||
}
|
||||
}
|
||||
|
||||
INPUT_IS_LIST = True
|
||||
RETURN_TYPES = ("STRING",)
|
||||
FUNCTION = "run"
|
||||
OUTPUT_NODE = True
|
||||
OUTPUT_IS_LIST = (True,)
|
||||
|
||||
CATEGORY = "♾️Mixlab/audio"
|
||||
|
||||
def run(self, text):
|
||||
# print(session_history)
|
||||
return {"ui": {"text": text}, "result": (text,)}
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ def chat(client, model_name,messages ):
|
||||
except (urllib.error.HTTPError, openai.OpenAIError) as ex:
|
||||
if try_count >= 3:
|
||||
raise ex
|
||||
time.sleep(5)
|
||||
time.sleep(3)
|
||||
continue
|
||||
|
||||
finish_reason = response.choices[0].finish_reason
|
||||
|
||||
+7
-4
@@ -1,3 +1,6 @@
|
||||
#### Thanks:
|
||||
# [ComfyUI-CLIPSeg](https://github.com/biegert/ComfyUI-CLIPSeg/tree/main)
|
||||
|
||||
from transformers import CLIPSegProcessor, CLIPSegForImageSegmentation
|
||||
|
||||
from PIL import Image
|
||||
@@ -252,7 +255,7 @@ class CombineMasks:
|
||||
|
||||
# A dictionary that contains all nodes you want to export with their names
|
||||
# NOTE: names should be globally unique
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"CLIPSeg": CLIPSeg,
|
||||
"CombineSegMasks": CombineMasks,
|
||||
}
|
||||
# NODE_CLASS_MAPPINGS = {
|
||||
# "CLIPSeg": CLIPSeg,
|
||||
# "CombineSegMasks": CombineMasks,
|
||||
# }
|
||||
|
||||
+9
-6
@@ -1,7 +1,7 @@
|
||||
import os
|
||||
|
||||
# FONT_PATH= os.path.abspath(os.path.join(os.path.dirname(__file__),'../assets/王汉宗颜楷体繁.ttf'))
|
||||
import matplotlib.font_manager as fm
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -16,11 +16,14 @@ def get_font_files(directory):
|
||||
font_files[font_name] = os.path.abspath(font_path)
|
||||
|
||||
try:
|
||||
font_paths = fm.findSystemFonts()
|
||||
for path in font_paths:
|
||||
font_prop = fm.FontProperties(fname=path)
|
||||
font_name = font_prop.get_name()
|
||||
font_files[font_name] = path
|
||||
import sys
|
||||
if sys.platform != "darwin":
|
||||
import matplotlib.font_manager as fm
|
||||
font_paths = fm.findSystemFonts()
|
||||
for path in font_paths:
|
||||
font_prop = fm.FontProperties(fname=path)
|
||||
font_name = font_prop.get_name()
|
||||
font_files[font_name] = path
|
||||
except ValueError:
|
||||
print("findSystemFonts error")
|
||||
|
||||
|
||||
@@ -0,0 +1,311 @@
|
||||
import { app } from '../../../scripts/app.js'
|
||||
// import { api } from '../../../scripts/api.js'
|
||||
import { ComfyWidgets } from '../../../scripts/widgets.js'
|
||||
import { $el } from '../../../scripts/ui.js'
|
||||
|
||||
function get_position_style (ctx, widget_width, y, node_height) {
|
||||
const MARGIN = 4 // the margin around the html element
|
||||
|
||||
/* Create a transform that deals with all the scrolling and zooming */
|
||||
const elRect = ctx.canvas.getBoundingClientRect()
|
||||
const transform = new DOMMatrix()
|
||||
.scaleSelf(
|
||||
elRect.width / ctx.canvas.width,
|
||||
elRect.height / ctx.canvas.height
|
||||
)
|
||||
.multiplySelf(ctx.getTransform())
|
||||
.translateSelf(MARGIN, MARGIN + y)
|
||||
|
||||
return {
|
||||
transformOrigin: '0 0',
|
||||
transform: transform,
|
||||
left: `0`,
|
||||
top: `0`,
|
||||
cursor: 'pointer',
|
||||
position: 'absolute',
|
||||
maxWidth: `${widget_width - MARGIN * 2}px`,
|
||||
// maxHeight: `${node_height - MARGIN * 2}px`, // we're assuming we have the whole height of the node
|
||||
width: `${widget_width - MARGIN * 2}px`,
|
||||
// height: `${node_height * 0.3 - MARGIN * 2}px`,
|
||||
// background: '#EEEEEE',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
// alignItems: 'center',
|
||||
justifyContent: 'space-around'
|
||||
}
|
||||
}
|
||||
|
||||
const getLocalData = key => {
|
||||
let data = {}
|
||||
try {
|
||||
data = JSON.parse(localStorage.getItem(key)) || {}
|
||||
} catch (error) {
|
||||
return {}
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
function speakText (text) {
|
||||
const speechMsg = new SpeechSynthesisUtterance()
|
||||
speechMsg.text = text
|
||||
|
||||
// 语音合成结束时触发的事件
|
||||
speechMsg.onend = function (event) {
|
||||
console.log('语音播放结束')
|
||||
window._mixlab_speech_synthesis_onend = true
|
||||
}
|
||||
|
||||
// 语音合成错误时触发的事件
|
||||
speechMsg.onerror = function (event) {
|
||||
console.error('语音播放错误:', event.error)
|
||||
}
|
||||
|
||||
// 使用浏览器默认语音合成器进行语音播放
|
||||
speechSynthesis.speak(speechMsg)
|
||||
}
|
||||
|
||||
// 调用方法,将文字转换为语音播放
|
||||
// speakText('Hello, how are you?');
|
||||
// #MixCopilot
|
||||
|
||||
const start = (element, id, startBtn) => {
|
||||
|
||||
startBtn.className='loading_mixlab'
|
||||
|
||||
window.recognition = new webkitSpeechRecognition()
|
||||
|
||||
window.recognition.continuous = true
|
||||
window.recognition.interimResults = true
|
||||
window.recognition.lang = navigator.language
|
||||
|
||||
let timeoutId, intervalId
|
||||
|
||||
window.recognition.onstart = () => {
|
||||
console.log('开始语音输入', window._mixlab_speech_synthesis_onend)
|
||||
window._mixlab_speech_synthesis_onend = false
|
||||
}
|
||||
|
||||
window.recognition.onresult = function (event) {
|
||||
const result = event.results[event.results.length - 1][0].transcript
|
||||
console.log('识别结果:', result)
|
||||
element.value = result
|
||||
|
||||
let data = getLocalData('_mixlab_speech_recognition')
|
||||
data[id] = result.trim()
|
||||
localStorage.setItem('_mixlab_speech_recognition', JSON.stringify(data))
|
||||
|
||||
if (timeoutId) clearTimeout(timeoutId)
|
||||
|
||||
if (!window.recognition) return
|
||||
|
||||
timeoutId = setTimeout(function () {
|
||||
console.log('结果传递::', result)
|
||||
app.queuePrompt(0, 1)
|
||||
window.recognition?.stop()
|
||||
window.recognition = null;
|
||||
startBtn.className=''
|
||||
startBtn.innerText = 'START'
|
||||
|
||||
timeoutId = null
|
||||
|
||||
intervalId = setInterval(() => {
|
||||
if (
|
||||
app.ui.lastQueueSize === 0 &&
|
||||
!window.recognition &&
|
||||
window._mixlab_speech_synthesis_onend
|
||||
) {
|
||||
start(element, id, startBtn)
|
||||
startBtn.innerText = 'STOP'
|
||||
if (intervalId) {
|
||||
clearInterval(intervalId)
|
||||
}
|
||||
}
|
||||
}, 2200)
|
||||
}, 2000)
|
||||
}
|
||||
|
||||
window.recognition.onend = function () {
|
||||
console.log('语音输入结束')
|
||||
}
|
||||
|
||||
window.recognition.onspeechend = function () {
|
||||
console.log('onspeechend')
|
||||
}
|
||||
|
||||
window.recognition.onerror = function (event) {
|
||||
console.log('Error occurred in recognition: ' + event.error)
|
||||
}
|
||||
|
||||
window.recognition.start()
|
||||
}
|
||||
|
||||
app.registerExtension({
|
||||
name: 'Mixlab.audio.SpeechRecognition',
|
||||
async getCustomWidgets (app) {
|
||||
return {
|
||||
AUDIOINPUTMIX (node, inputName, inputData, app) {
|
||||
// console.log('##node', node)
|
||||
const widget = {
|
||||
type: inputData[0], // the type, CHEESE
|
||||
name: inputName, // the name, slice
|
||||
size: [128, 32], // a default size
|
||||
draw (ctx, node, width, y) {},
|
||||
computeSize (...args) {
|
||||
return [128, 32] // a method to compute the current size of the widget
|
||||
},
|
||||
async serializeValue (nodeId, widgetIndex) {
|
||||
let data = getLocalData('_mixlab_speech_recognition')
|
||||
return data[node.id] || 'Hello Mixlab'
|
||||
}
|
||||
}
|
||||
// widget.something = something; // maybe adds stuff to it
|
||||
node.addCustomWidget(widget) // adds it to the node
|
||||
return widget // and returns it.
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
async beforeRegisterNodeDef (nodeType, nodeData, app) {
|
||||
if (nodeType.comfyClass == 'SpeechRecognition') {
|
||||
const orig_nodeCreated = nodeType.prototype.onNodeCreated
|
||||
nodeType.prototype.onNodeCreated = function () {
|
||||
orig_nodeCreated?.apply(this, arguments)
|
||||
|
||||
const widget = {
|
||||
type: 'div',
|
||||
name: 'chatgptdiv',
|
||||
draw (ctx, node, widget_width, y, widget_height) {
|
||||
Object.assign(
|
||||
this.div.style,
|
||||
get_position_style(ctx, widget_width, 44, node.size[1])
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
widget.div = $el('div', {})
|
||||
|
||||
document.body.appendChild(widget.div)
|
||||
|
||||
const inputDiv = (key, placeholder) => {
|
||||
let div = document.createElement('div')
|
||||
const startBtn = document.createElement('button')
|
||||
const textArea = document.createElement('textarea')
|
||||
|
||||
textArea.className = `${'comfy-multiline-input'} ${placeholder}`
|
||||
|
||||
textArea.style = `margin-top: 14px;
|
||||
height: 44px;`
|
||||
|
||||
div.style = `flex-direction: column;
|
||||
display: flex;
|
||||
margin: 0px 8px 6px;`
|
||||
|
||||
startBtn.style = `
|
||||
outline: none;
|
||||
border: none;
|
||||
padding: 4px; `
|
||||
|
||||
startBtn.innerText = 'START'
|
||||
|
||||
div.appendChild(startBtn)
|
||||
div.appendChild(textArea)
|
||||
|
||||
startBtn.addEventListener('click', () => {
|
||||
if (window.recognition) {
|
||||
window.recognition.stop()
|
||||
window.recognition = null
|
||||
startBtn.innerText = 'START'
|
||||
startBtn.className=''
|
||||
} else {
|
||||
start(textArea, this.id, startBtn)
|
||||
startBtn.innerText = 'STOP'
|
||||
}
|
||||
})
|
||||
|
||||
return div
|
||||
}
|
||||
|
||||
let inputAudio = inputDiv('_mixlab_speech_recognition', 'audio')
|
||||
widget.div.appendChild(inputAudio)
|
||||
|
||||
this.addCustomWidget(widget)
|
||||
|
||||
const onRemoved = this.onRemoved
|
||||
this.onRemoved = () => {
|
||||
inputAudio.remove()
|
||||
widget.div.remove()
|
||||
return onRemoved?.()
|
||||
}
|
||||
|
||||
this.serialize_widgets = true //需要保存参数
|
||||
}
|
||||
}
|
||||
},
|
||||
async loadedGraphNode (node, app) {
|
||||
if (node.type === 'SpeechRecognition') {
|
||||
let data = getLocalData('_mixlab_speech_recognition')
|
||||
// console.log('_mixlab_speech_recognition', node.widgets)
|
||||
let div = node.widgets.filter(f => f.type === 'div')[0]
|
||||
if (div && data[node.id]) {
|
||||
div.div.querySelector('textarea').value = data[node.id]
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
app.registerExtension({
|
||||
name: 'Mixlab.audio.SpeechSynthesis',
|
||||
async beforeRegisterNodeDef (nodeType, nodeData, app) {
|
||||
if (nodeData.name === 'SpeechSynthesis') {
|
||||
function populate (text) {
|
||||
// console.log('SpeechSynthesis',this.widgets)
|
||||
|
||||
if (this.widgets) {
|
||||
const pos = this.widgets.findIndex(w => w.name === 'text')
|
||||
if (pos !== -1) {
|
||||
for (let i = pos; i < this.widgets.length; i++) {
|
||||
this.widgets[i].onRemove?.()
|
||||
}
|
||||
this.widgets.length = pos
|
||||
}
|
||||
}
|
||||
|
||||
for (let list of text) {
|
||||
const w = ComfyWidgets['STRING'](
|
||||
this,
|
||||
'text',
|
||||
['STRING', { multiline: true }],
|
||||
app
|
||||
).widget
|
||||
w.inputEl.readOnly = true
|
||||
w.inputEl.style.opacity = 0.6
|
||||
w.value = list
|
||||
}
|
||||
|
||||
speakText(text.join('\n'))
|
||||
|
||||
// console.log('ShowTextForGPT',this.widgets.length)
|
||||
requestAnimationFrame(() => {
|
||||
const sz = this.computeSize()
|
||||
if (sz[0] < this.size[0]) {
|
||||
sz[0] = this.size[0]
|
||||
}
|
||||
if (sz[1] < this.size[1]) {
|
||||
sz[1] = this.size[1]
|
||||
}
|
||||
this.onResize?.(sz)
|
||||
app.graph.setDirtyCanvas(true, false)
|
||||
})
|
||||
}
|
||||
|
||||
// When the node is executed we will be sent the input text, display this in the widget
|
||||
const onExecuted = nodeType.prototype.onExecuted
|
||||
nodeType.prototype.onExecuted = function (message) {
|
||||
onExecuted?.apply(this, arguments)
|
||||
populate.call(this, message.text)
|
||||
}
|
||||
|
||||
this.serialize_widgets = true //需要保存参数
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -3,7 +3,7 @@ import { app } from '../../../scripts/app.js'
|
||||
const repoOwner = 'shadowcz007' // 替换为仓库的所有者
|
||||
const repoName = 'comfyui-mixlab-nodes' // 替换为仓库的名称
|
||||
|
||||
const version = 'v0.2.7'
|
||||
const version = 'v0.3.1'
|
||||
|
||||
fetch(`https://api.github.com/repos/${repoOwner}/${repoName}/releases/latest`)
|
||||
.then(response => response.json())
|
||||
|
||||
@@ -192,7 +192,7 @@ app.registerExtension({
|
||||
|
||||
let id = node.id
|
||||
|
||||
console.log('ChatGPTOpenAI serialize_widgets', this)
|
||||
// console.log('ChatGPTOpenAI serialize_widgets', this)
|
||||
|
||||
widget.div.querySelector('.Key').value = apiKey[id] || 'by Mixlab'
|
||||
widget.div.querySelector('.URL').value =
|
||||
@@ -216,12 +216,27 @@ app.registerExtension({
|
||||
this.widgets.length = pos;
|
||||
}
|
||||
}
|
||||
// console.log('ShowTextForGPT',this.widgets.length)
|
||||
for (const list of text) {
|
||||
// console.log('ShowTextForGPT',text)
|
||||
for (let list of text) {
|
||||
const w = ComfyWidgets["STRING"](this, "text", ["STRING", { multiline: true }], app).widget;
|
||||
w.inputEl.readOnly = true;
|
||||
w.inputEl.style.opacity = 0.6;
|
||||
w.value = list;
|
||||
|
||||
try {
|
||||
let data=JSON.parse(list);
|
||||
data=Array.from(data,d=>{
|
||||
return {
|
||||
...d,
|
||||
content:decodeURIComponent(d.content)
|
||||
}
|
||||
})
|
||||
list=JSON.stringify(data,null,2)
|
||||
} catch (error) {
|
||||
// console.log(error)
|
||||
}
|
||||
|
||||
w.value =list;
|
||||
|
||||
}
|
||||
// console.log('ShowTextForGPT',this.widgets.length)
|
||||
requestAnimationFrame(() => {
|
||||
|
||||
@@ -1,19 +1,61 @@
|
||||
import { app } from '../../../scripts/app.js'
|
||||
|
||||
function injectCSS(css) {
|
||||
// 检查页面中是否已经存在具有相同内容的style标签
|
||||
const existingStyle = document.querySelector('style');
|
||||
if (existingStyle && existingStyle.textContent === css) {
|
||||
return; // 如果已经存在相同的样式,则不进行注入
|
||||
}
|
||||
|
||||
// 创建一个新的style标签,并将CSS内容注入其中
|
||||
const style = document.createElement('style');
|
||||
style.textContent = css;
|
||||
|
||||
// 将style标签插入到页面的head元素中
|
||||
const head = document.querySelector('head');
|
||||
head.appendChild(style);
|
||||
}
|
||||
|
||||
injectCSS(`::-webkit-scrollbar {
|
||||
width: 2px;
|
||||
}
|
||||
|
||||
@keyframes loading_mixlab {
|
||||
0% {
|
||||
background-color: green;
|
||||
}
|
||||
|
||||
50% {
|
||||
background-color: lightgreen;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-color: green;
|
||||
}
|
||||
}
|
||||
|
||||
.loading_mixlab {
|
||||
background-color: green;
|
||||
animation-name: loading_mixlab;
|
||||
animation-duration: 2s;
|
||||
animation-iteration-count: infinite;
|
||||
}`);
|
||||
|
||||
|
||||
async function getCustomnodeMappings (mode = 'url') {
|
||||
// mode = "local";
|
||||
let api_host = `${window.location.hostname}:${window.location.port}`
|
||||
let api_base = ''
|
||||
let url = `${window.location.protocol}//${api_host}${api_base}`
|
||||
|
||||
const response = await fetch(`${url}/customnode/getmappings?mode=${mode}`)
|
||||
const data = await response.json()
|
||||
|
||||
let nodes = {}
|
||||
try {
|
||||
const response = await fetch(`${url}/customnode/getmappings?mode=${mode}`)
|
||||
const data = await response.json()
|
||||
for (let url in data) {
|
||||
let n = data[url]
|
||||
for (let node of n[0]) {
|
||||
// if(node=='CLIPSeg')console.log('#CLIPSeg',n)
|
||||
nodes[node] = { url, title: n[1].title_aux }
|
||||
}
|
||||
}
|
||||
@@ -59,9 +101,10 @@ app.showMissingNodesError = async function (
|
||||
missingNodeTypes,
|
||||
hasAddedNodes = true
|
||||
) {
|
||||
|
||||
const nodesMap = await getCustomnodeMappings()
|
||||
console.log('#nodesMap', nodesMap)
|
||||
// console.log('###MIXLAB', missingNodeTypes, hasAddedNodes)
|
||||
console.log('###MIXLAB', missingNodeTypes, hasAddedNodes)
|
||||
this.ui.dialog.show(
|
||||
`When loading the graph, the following node types were not found: <ul>${missingNodeGithub(
|
||||
missingNodeTypes,
|
||||
|
||||
+23
-2
@@ -1,3 +1,24 @@
|
||||
::-webkit-scrollbar {
|
||||
width: 2px;
|
||||
}
|
||||
width: 2px;
|
||||
}
|
||||
|
||||
@keyframes loading_mixlab {
|
||||
0% {
|
||||
background-color: green;
|
||||
}
|
||||
|
||||
50% {
|
||||
background-color: lightgreen;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-color: green;
|
||||
}
|
||||
}
|
||||
|
||||
.loading_mixlab {
|
||||
background-color: green;
|
||||
animation-name: loading_mixlab;
|
||||
animation-duration: 2s;
|
||||
animation-iteration-count: infinite;
|
||||
}
|
||||
@@ -0,0 +1,862 @@
|
||||
{
|
||||
"last_node_id": 28,
|
||||
"last_link_id": 64,
|
||||
"nodes": [
|
||||
{
|
||||
"id": 7,
|
||||
"type": "CLIPTextEncode",
|
||||
"pos": [
|
||||
515,
|
||||
130
|
||||
],
|
||||
"size": {
|
||||
"0": 400,
|
||||
"1": 200
|
||||
},
|
||||
"flags": {},
|
||||
"order": 3,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "clip",
|
||||
"type": "CLIP",
|
||||
"link": 33
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "CONDITIONING",
|
||||
"type": "CONDITIONING",
|
||||
"links": [
|
||||
29
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "CLIPTextEncode"
|
||||
},
|
||||
"widgets_values": [
|
||||
""
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"type": "LoraLoader",
|
||||
"pos": [
|
||||
515,
|
||||
460
|
||||
],
|
||||
"size": {
|
||||
"0": 315,
|
||||
"1": 126
|
||||
},
|
||||
"flags": {},
|
||||
"order": 4,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "model",
|
||||
"type": "MODEL",
|
||||
"link": 31
|
||||
},
|
||||
{
|
||||
"name": "clip",
|
||||
"type": "CLIP",
|
||||
"link": 45
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "MODEL",
|
||||
"type": "MODEL",
|
||||
"links": [
|
||||
44
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
},
|
||||
{
|
||||
"name": "CLIP",
|
||||
"type": "CLIP",
|
||||
"links": null,
|
||||
"shape": 3
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LoraLoader"
|
||||
},
|
||||
"widgets_values": [
|
||||
"lcm-lora-sdv1-5.safetensors",
|
||||
1,
|
||||
1
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"type": "VAEDecode",
|
||||
"pos": [
|
||||
1430,
|
||||
130
|
||||
],
|
||||
"size": {
|
||||
"0": 210,
|
||||
"1": 46
|
||||
},
|
||||
"flags": {},
|
||||
"order": 11,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "samples",
|
||||
"type": "LATENT",
|
||||
"link": 35
|
||||
},
|
||||
{
|
||||
"name": "vae",
|
||||
"type": "VAE",
|
||||
"link": 34
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "IMAGE",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
41
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "VAEDecode"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 23,
|
||||
"type": "VAEEncode",
|
||||
"pos": [
|
||||
515,
|
||||
1092
|
||||
],
|
||||
"size": {
|
||||
"0": 210,
|
||||
"1": 46
|
||||
},
|
||||
"flags": {},
|
||||
"order": 6,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "pixels",
|
||||
"type": "IMAGE",
|
||||
"link": 57
|
||||
},
|
||||
{
|
||||
"name": "vae",
|
||||
"type": "VAE",
|
||||
"link": 58
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "LATENT",
|
||||
"type": "LATENT",
|
||||
"links": [
|
||||
54
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "VAEEncode"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"type": "CheckpointLoaderSimple",
|
||||
"pos": [
|
||||
100,
|
||||
130
|
||||
],
|
||||
"size": {
|
||||
"0": 315,
|
||||
"1": 98
|
||||
},
|
||||
"flags": {},
|
||||
"order": 0,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "MODEL",
|
||||
"type": "MODEL",
|
||||
"links": [
|
||||
31
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
},
|
||||
{
|
||||
"name": "CLIP",
|
||||
"type": "CLIP",
|
||||
"links": [
|
||||
32,
|
||||
33,
|
||||
45
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 1
|
||||
},
|
||||
{
|
||||
"name": "VAE",
|
||||
"type": "VAE",
|
||||
"links": [
|
||||
34,
|
||||
58
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 2
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "CheckpointLoaderSimple"
|
||||
},
|
||||
"widgets_values": [
|
||||
"deliberate_v2.safetensors"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"type": "CLIPTextEncode",
|
||||
"pos": [
|
||||
515,
|
||||
1268
|
||||
],
|
||||
"size": {
|
||||
"0": 400,
|
||||
"1": 200
|
||||
},
|
||||
"flags": {},
|
||||
"order": 8,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "clip",
|
||||
"type": "CLIP",
|
||||
"link": 32
|
||||
},
|
||||
{
|
||||
"name": "text",
|
||||
"type": "STRING",
|
||||
"link": 62,
|
||||
"widget": {
|
||||
"name": "text"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "CONDITIONING",
|
||||
"type": "CONDITIONING",
|
||||
"links": [
|
||||
51
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "CLIPTextEncode"
|
||||
},
|
||||
"widgets_values": [
|
||||
""
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 20,
|
||||
"type": "FloatingVideo",
|
||||
"pos": [
|
||||
1274,
|
||||
536
|
||||
],
|
||||
"size": [
|
||||
315,
|
||||
58
|
||||
],
|
||||
"flags": {},
|
||||
"order": 12,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "images",
|
||||
"type": "IMAGE",
|
||||
"link": 41
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "FloatingVideo"
|
||||
},
|
||||
"widgets_values": [
|
||||
null
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"type": "KSampler",
|
||||
"pos": [
|
||||
1004,
|
||||
130
|
||||
],
|
||||
"size": [
|
||||
315,
|
||||
262
|
||||
],
|
||||
"flags": {},
|
||||
"order": 10,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "model",
|
||||
"type": "MODEL",
|
||||
"link": 44
|
||||
},
|
||||
{
|
||||
"name": "positive",
|
||||
"type": "CONDITIONING",
|
||||
"link": 51
|
||||
},
|
||||
{
|
||||
"name": "negative",
|
||||
"type": "CONDITIONING",
|
||||
"link": 29
|
||||
},
|
||||
{
|
||||
"name": "latent_image",
|
||||
"type": "LATENT",
|
||||
"link": 54
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "LATENT",
|
||||
"type": "LATENT",
|
||||
"links": [
|
||||
35
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "KSampler"
|
||||
},
|
||||
"widgets_values": [
|
||||
758428944049342,
|
||||
"fixed",
|
||||
4,
|
||||
1.6,
|
||||
"lcm",
|
||||
"karras",
|
||||
0.61
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 24,
|
||||
"type": "ScreenShare",
|
||||
"pos": [
|
||||
62,
|
||||
543
|
||||
],
|
||||
"size": {
|
||||
"0": 315,
|
||||
"1": 194
|
||||
},
|
||||
"flags": {},
|
||||
"order": 1,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "IMAGE",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
55,
|
||||
57
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
},
|
||||
{
|
||||
"name": "PROMPT",
|
||||
"type": "STRING",
|
||||
"links": [],
|
||||
"shape": 3,
|
||||
"slot_index": 1
|
||||
},
|
||||
{
|
||||
"name": "FLOAT",
|
||||
"type": "FLOAT",
|
||||
"links": [],
|
||||
"shape": 3,
|
||||
"slot_index": 2
|
||||
},
|
||||
{
|
||||
"name": "INT",
|
||||
"type": "INT",
|
||||
"links": null,
|
||||
"shape": 3
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "ScreenShare"
|
||||
},
|
||||
"widgets_values": [
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "PreviewImage",
|
||||
"pos": [
|
||||
-416,
|
||||
516
|
||||
],
|
||||
"size": {
|
||||
"0": 210,
|
||||
"1": 246
|
||||
},
|
||||
"flags": {},
|
||||
"order": 5,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "images",
|
||||
"type": "IMAGE",
|
||||
"link": 55
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "PreviewImage"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 26,
|
||||
"type": "ChatGPTOpenAI",
|
||||
"pos": [
|
||||
5,
|
||||
1325
|
||||
],
|
||||
"size": [
|
||||
400,
|
||||
357.99993896484375
|
||||
],
|
||||
"flags": {},
|
||||
"order": 7,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "prompt",
|
||||
"type": "STRING",
|
||||
"link": 61,
|
||||
"widget": {
|
||||
"name": "prompt"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "text",
|
||||
"type": "STRING",
|
||||
"links": [
|
||||
62,
|
||||
63
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
},
|
||||
{
|
||||
"name": "messages",
|
||||
"type": "STRING",
|
||||
"links": null,
|
||||
"shape": 3
|
||||
},
|
||||
{
|
||||
"name": "session_history",
|
||||
"type": "STRING",
|
||||
"links": null,
|
||||
"shape": 3
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "ChatGPTOpenAI"
|
||||
},
|
||||
"widgets_values": [
|
||||
null,
|
||||
null,
|
||||
"",
|
||||
"你需要根据用户的输入,转化为英文单词的短句子组合,输出英文",
|
||||
"gpt-35-turbo",
|
||||
1249,
|
||||
"randomize",
|
||||
1,
|
||||
null
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 28,
|
||||
"type": "SpeechSynthesis",
|
||||
"pos": [
|
||||
542,
|
||||
1570
|
||||
],
|
||||
"size": [
|
||||
315,
|
||||
76
|
||||
],
|
||||
"flags": {},
|
||||
"order": 9,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "text",
|
||||
"type": "STRING",
|
||||
"link": 63,
|
||||
"widget": {
|
||||
"name": "text"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "STRING",
|
||||
"type": "STRING",
|
||||
"links": null,
|
||||
"shape": 6
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "SpeechSynthesis"
|
||||
},
|
||||
"widgets_values": [
|
||||
"A very handsome elderly gentleman."
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 25,
|
||||
"type": "SpeechRecognition",
|
||||
"pos": [
|
||||
-5,
|
||||
1101
|
||||
],
|
||||
"size": [
|
||||
392.5606180664065,
|
||||
166.64923671875022
|
||||
],
|
||||
"flags": {},
|
||||
"order": 2,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "prompt",
|
||||
"type": "STRING",
|
||||
"links": [
|
||||
61
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "SpeechRecognition"
|
||||
},
|
||||
"widgets_values": [
|
||||
null,
|
||||
null
|
||||
]
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
[
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
3,
|
||||
6,
|
||||
0,
|
||||
5,
|
||||
0,
|
||||
"MODEL"
|
||||
],
|
||||
[
|
||||
5,
|
||||
8,
|
||||
0,
|
||||
5,
|
||||
2,
|
||||
"CONDITIONING"
|
||||
],
|
||||
[
|
||||
6,
|
||||
9,
|
||||
0,
|
||||
5,
|
||||
3,
|
||||
"LATENT"
|
||||
],
|
||||
[
|
||||
7,
|
||||
10,
|
||||
0,
|
||||
6,
|
||||
0,
|
||||
"MODEL"
|
||||
],
|
||||
[
|
||||
8,
|
||||
10,
|
||||
1,
|
||||
6,
|
||||
1,
|
||||
"CLIP"
|
||||
],
|
||||
[
|
||||
9,
|
||||
5,
|
||||
0,
|
||||
11,
|
||||
0,
|
||||
"LATENT"
|
||||
],
|
||||
[
|
||||
10,
|
||||
10,
|
||||
2,
|
||||
11,
|
||||
1,
|
||||
"VAE"
|
||||
],
|
||||
[
|
||||
11,
|
||||
6,
|
||||
1,
|
||||
7,
|
||||
0,
|
||||
"CLIP"
|
||||
],
|
||||
[
|
||||
12,
|
||||
6,
|
||||
1,
|
||||
8,
|
||||
0,
|
||||
"CLIP"
|
||||
],
|
||||
[
|
||||
14,
|
||||
11,
|
||||
0,
|
||||
3,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
17,
|
||||
1,
|
||||
2,
|
||||
7,
|
||||
1,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
18,
|
||||
7,
|
||||
0,
|
||||
15,
|
||||
0,
|
||||
"CONDITIONING"
|
||||
],
|
||||
[
|
||||
19,
|
||||
15,
|
||||
0,
|
||||
5,
|
||||
1,
|
||||
"CONDITIONING"
|
||||
],
|
||||
[
|
||||
20,
|
||||
16,
|
||||
0,
|
||||
15,
|
||||
1,
|
||||
"CONTROL_NET"
|
||||
],
|
||||
[
|
||||
24,
|
||||
1,
|
||||
0,
|
||||
18,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
25,
|
||||
18,
|
||||
0,
|
||||
15,
|
||||
2,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
29,
|
||||
7,
|
||||
0,
|
||||
5,
|
||||
2,
|
||||
"CONDITIONING"
|
||||
],
|
||||
[
|
||||
31,
|
||||
10,
|
||||
0,
|
||||
6,
|
||||
0,
|
||||
"MODEL"
|
||||
],
|
||||
[
|
||||
32,
|
||||
10,
|
||||
1,
|
||||
8,
|
||||
0,
|
||||
"CLIP"
|
||||
],
|
||||
[
|
||||
33,
|
||||
10,
|
||||
1,
|
||||
7,
|
||||
0,
|
||||
"CLIP"
|
||||
],
|
||||
[
|
||||
34,
|
||||
10,
|
||||
2,
|
||||
11,
|
||||
1,
|
||||
"VAE"
|
||||
],
|
||||
[
|
||||
35,
|
||||
5,
|
||||
0,
|
||||
11,
|
||||
0,
|
||||
"LATENT"
|
||||
],
|
||||
[
|
||||
41,
|
||||
11,
|
||||
0,
|
||||
20,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
44,
|
||||
6,
|
||||
0,
|
||||
5,
|
||||
0,
|
||||
"MODEL"
|
||||
],
|
||||
[
|
||||
45,
|
||||
10,
|
||||
1,
|
||||
6,
|
||||
1,
|
||||
"CLIP"
|
||||
],
|
||||
[
|
||||
51,
|
||||
8,
|
||||
0,
|
||||
5,
|
||||
1,
|
||||
"CONDITIONING"
|
||||
],
|
||||
[
|
||||
54,
|
||||
23,
|
||||
0,
|
||||
5,
|
||||
3,
|
||||
"LATENT"
|
||||
],
|
||||
[
|
||||
55,
|
||||
24,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
57,
|
||||
24,
|
||||
0,
|
||||
23,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
58,
|
||||
10,
|
||||
2,
|
||||
23,
|
||||
1,
|
||||
"VAE"
|
||||
],
|
||||
[
|
||||
61,
|
||||
25,
|
||||
0,
|
||||
26,
|
||||
0,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
62,
|
||||
26,
|
||||
0,
|
||||
8,
|
||||
1,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
63,
|
||||
26,
|
||||
0,
|
||||
28,
|
||||
0,
|
||||
"STRING"
|
||||
]
|
||||
],
|
||||
"groups": [],
|
||||
"config": {},
|
||||
"extra": {},
|
||||
"version": 0.4
|
||||
}
|
||||
Reference in New Issue
Block a user