implement preview image, video and audio in combo list
Add option in settings show preview content in combo list Change path to save pose image to input update readme extras_nodes and pyprojects version.
This commit is contained in:
@@ -20,4 +20,8 @@
|
||||
|
||||
- Speech & Recognition speech
|
||||
|
||||
- Preview image, video and sound select list combo
|
||||
|
||||

|
||||
|
||||
**Note** (Speech & Recognition speech): If your browser Firefox: go to `about:config`, find `media.webspeech.recognition.enable`, `media.webspeech.recognition.force_enable` set values to `true`
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 820 KiB |
@@ -39,6 +39,11 @@ const SpeechAndRecognationSpeechLS = localStorage.getItem(
|
||||
);
|
||||
// end - Recognation & speech
|
||||
|
||||
// Preview image, video and audio select list combo
|
||||
const PreviewImageVideoComboLS = localStorage.getItem(
|
||||
`Comfy.Settings.${idExt}.PreviewImageVideoCombo`
|
||||
);
|
||||
|
||||
// Settings set values from LS or default
|
||||
let PreviewImageSize = PreviewImageSizeLS
|
||||
? JSON.parse(PreviewImageSizeLS)
|
||||
@@ -52,14 +57,212 @@ let PreviewImageSize = PreviewImageSizeLS
|
||||
// Speech & Recognition widget settings
|
||||
SpeechAndRecognationSpeech = SpeechAndRecognationSpeechLS
|
||||
? JSON.parse(SpeechAndRecognationSpeechLS)
|
||||
: true,
|
||||
// Preview image, video and audio select list combo
|
||||
PreviewImageVideoCombo = PreviewImageVideoComboLS
|
||||
? JSON.parse(PreviewImageVideoComboLS)
|
||||
: true;
|
||||
|
||||
// Preview image, video and audio content loading function
|
||||
const SUPPORTS_FORMAT = {
|
||||
image: ["jpg", "jpeg", "bmp", "png", "gif", "tiff", "avif"],
|
||||
video: ["mp4", "webm"],
|
||||
audio: ["ogg", "wav", "mp3"],
|
||||
};
|
||||
|
||||
const loadingContent = (src) => {
|
||||
return new Promise((res, rej) => {
|
||||
let ext = src.slice(src.lastIndexOf(".") + 1).toLowerCase();
|
||||
ext = /\w+/.exec(ext)[0];
|
||||
|
||||
if (SUPPORTS_FORMAT.image.includes(ext)) {
|
||||
const img = new Image();
|
||||
img.crossOrigin = "";
|
||||
img.onload = (e) => res({ raw: img, type: "image", src });
|
||||
img.onerror = (err) => rej(err);
|
||||
img.src = src;
|
||||
} else if (SUPPORTS_FORMAT.video.includes(ext)) {
|
||||
const video = document.querySelector(".preview_vid");
|
||||
video.onerror = (err) => rej(err);
|
||||
|
||||
video.addEventListener("canplay", (e) => {
|
||||
res({ raw: video, type: "video", src });
|
||||
});
|
||||
video.src = src;
|
||||
} else if (SUPPORTS_FORMAT.audio.includes(ext)) {
|
||||
const audio = document.querySelector(".preview_audio");
|
||||
audio.onerror = (err) => rej(err);
|
||||
|
||||
audio.addEventListener("canplaythrough", (e) => {
|
||||
res({ raw: audio, type: "audio", src });
|
||||
});
|
||||
audio.src = src;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function drawVid(raw, canvas, ctx, type) {
|
||||
ctx.drawImage(raw, 0, 0, canvas.width, canvas.height);
|
||||
|
||||
canvas.requanim = requestAnimationFrame(
|
||||
drawVid.bind(this, raw, canvas, ctx, type)
|
||||
);
|
||||
}
|
||||
//
|
||||
|
||||
// Register Extension
|
||||
app.registerExtension({
|
||||
name: idExt,
|
||||
|
||||
init() {
|
||||
addStylesheet("css/extrasnode/extras_node_styles.css", import.meta.url);
|
||||
|
||||
// Preview image, video and audio select list combo
|
||||
const addItem = LiteGraph.ContextMenu.prototype.addItem;
|
||||
LiteGraph.ContextMenu.prototype.addItem = function () {
|
||||
const element = addItem?.apply(this, arguments);
|
||||
|
||||
if (!PreviewImageVideoCombo) return;
|
||||
|
||||
const [name, value, options] = arguments;
|
||||
if (value instanceof Object) return;
|
||||
|
||||
if (!this.root?.preview_content_combo) {
|
||||
const preview_content_combo = $el(
|
||||
"div.preview_content_combo",
|
||||
{
|
||||
style: {
|
||||
position: "absolute",
|
||||
maxWidth: "160px",
|
||||
right: "calc(-1% - 160px)",
|
||||
},
|
||||
parent: this.root,
|
||||
},
|
||||
[
|
||||
$el("canvas.preview_img", {
|
||||
style: { width: "100%" },
|
||||
}),
|
||||
$el("video.preview_vid", {
|
||||
style: { opacity: 0, width: 0, height: 0 },
|
||||
crossOrigin: "anonymous",
|
||||
autoplay: false,
|
||||
muted: false,
|
||||
preload: "auto",
|
||||
}),
|
||||
$el("audio.preview_audio", {
|
||||
style: { opacity: 0, position: "absolute", left: 0 },
|
||||
crossOrigin: "anonymous",
|
||||
autoplay: false,
|
||||
muted: false,
|
||||
preload: "auto",
|
||||
controls: true,
|
||||
}),
|
||||
]
|
||||
);
|
||||
|
||||
this.root.preview_content_combo = preview_content_combo;
|
||||
}
|
||||
|
||||
LiteGraph.pointerListenerAdd(element, "enter", (e) => {
|
||||
if (element?.dataset?.value) {
|
||||
const body_rect = document.body.getBoundingClientRect();
|
||||
const root_rect = this.root.getBoundingClientRect();
|
||||
const { x, y } = element.getBoundingClientRect();
|
||||
|
||||
const scale = app.graph.extra.ds.scale;
|
||||
|
||||
const canvas = this.root.preview_content_combo.children[0];
|
||||
const ctx = canvas.getContext("2d");
|
||||
|
||||
loadingContent(
|
||||
api.apiURL(
|
||||
`/view?filename=${encodeURIComponent(
|
||||
element.dataset.value
|
||||
)}&type=input`
|
||||
)
|
||||
).then(({ raw, type, src }) => {
|
||||
this.root.preview_content_combo.style.maxWidth =
|
||||
type === "audio" ? "300px" : "160px";
|
||||
|
||||
const previewWidth = parseInt(
|
||||
this.root.preview_content_combo.style.maxWidth
|
||||
);
|
||||
|
||||
if (scale >= 1) {
|
||||
this.root.preview_content_combo.style.top = `${
|
||||
(y - root_rect.top) / scale
|
||||
}px`;
|
||||
} else {
|
||||
this.root.preview_content_combo.style.top = `${
|
||||
y - root_rect.top
|
||||
}px`;
|
||||
}
|
||||
|
||||
if (
|
||||
body_rect.width &&
|
||||
root_rect.right + previewWidth > body_rect.width
|
||||
) {
|
||||
this.root.preview_content_combo.style.left = `${
|
||||
-previewWidth - 10
|
||||
}px`;
|
||||
this.root.preview_content_combo.style.right = "auto";
|
||||
} else {
|
||||
this.root.preview_content_combo.style.left = "auto";
|
||||
this.root.preview_content_combo.style.right = `calc(-1% - ${this.root.preview_content_combo.style.maxWidth})`;
|
||||
}
|
||||
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
const video = document.querySelector(".preview_vid");
|
||||
const audio = document.querySelector(".preview_audio");
|
||||
|
||||
if (type === "image") {
|
||||
canvas.width = raw.naturalWidth;
|
||||
canvas.height = raw.naturalHeight;
|
||||
if (!video.paused) {
|
||||
video.pause();
|
||||
video.currentTime = 0;
|
||||
}
|
||||
cancelAnimationFrame(canvas.requanim);
|
||||
} else if (type === "video") {
|
||||
canvas.width = raw.videoWidth;
|
||||
canvas.height = raw.videoHeight;
|
||||
video.play();
|
||||
} else if (type === "audio") {
|
||||
Object.assign(audio.style, {
|
||||
opacity: 1,
|
||||
});
|
||||
audio.play();
|
||||
}
|
||||
|
||||
if (type === "video" || type === "image") {
|
||||
Object.assign(audio.style, {
|
||||
opacity: 0,
|
||||
});
|
||||
!audio.paused && audio.pause();
|
||||
ctx.drawImage(raw, 0, 0, canvas.width, canvas.height);
|
||||
}
|
||||
|
||||
if (type === "video")
|
||||
canvas.requanim = requestAnimationFrame(
|
||||
drawVid.bind(this, raw, canvas, ctx, type)
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
LiteGraph.pointerListenerAdd(element, "leave", (e) => {
|
||||
if (element?.dataset?.value) {
|
||||
const canvas = this.root.preview_content_combo.children[0];
|
||||
const video = document.querySelector(".preview_vid");
|
||||
if (!video.paused) {
|
||||
video.pause();
|
||||
video.currentTime = 0;
|
||||
}
|
||||
cancelAnimationFrame(canvas.requanim);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// PreviewImage settings ui
|
||||
app.ui.settings.addSetting({
|
||||
id: `${idExt}.PreviewImage`,
|
||||
@@ -242,6 +445,17 @@ app.registerExtension({
|
||||
]);
|
||||
},
|
||||
});
|
||||
|
||||
// Preview image, video and audio settings ui
|
||||
app.ui.settings.addSetting({
|
||||
id: `${idExt}.PreviewImageVideoCombo`,
|
||||
name: "🔸 Preview images and videos in the list",
|
||||
defaultValue: true,
|
||||
type: "boolean",
|
||||
onChange(value) {
|
||||
PreviewImageVideoCombo = value;
|
||||
},
|
||||
});
|
||||
},
|
||||
async beforeRegisterNodeDef(nodeType, nodeData, app) {
|
||||
// --- Preview Text Node
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Title: Set Poses in ComflyUI from ControlNet
|
||||
* Author: AlekPet
|
||||
* Description: I rewrote the main.js file as a class, from fkunn1326's openpose-editor (https://github.com/fkunn1326/openpose-editor/blob/master/javascript/main.js)
|
||||
* Version: 2024.07.21
|
||||
* Version: 2024.10.13
|
||||
* Github: https://github.com/AlekPet/ComfyUI_Custom_Nodes_AlekPet
|
||||
*/
|
||||
|
||||
@@ -492,7 +492,7 @@ class OpenPose {
|
||||
let formData = new FormData();
|
||||
formData.append("image", blob, fileName);
|
||||
formData.append("overwrite", "true");
|
||||
formData.append("type", "temp");
|
||||
formData.append("type", "input");
|
||||
uploadFile(formData);
|
||||
}, "image/png");
|
||||
// - end
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
[project]
|
||||
name = "comfyui_custom_nodes_alekpet"
|
||||
description = "Nodes: PoseNode, PainterNode, TranslateTextNode, TranslateCLIPTextEncodeNode, DeepTranslatorTextNode, DeepTranslatorCLIPTextEncodeNode, ArgosTranslateTextNode, ArgosTranslateCLIPTextEncodeNode, PreviewTextNode, HexToHueNode, ColorsCorrectNode, IDENode."
|
||||
version = "1.0.29.1"
|
||||
version = "1.0.29.3"
|
||||
license = { file = "LICENSE" }
|
||||
|
||||
[project.urls]
|
||||
|
||||
Reference in New Issue
Block a user