diff --git a/.idea/php.xml b/.idea/php.xml
new file mode 100644
index 0000000..f324872
--- /dev/null
+++ b/.idea/php.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..e529b61
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 3c8e2a8..631eea4 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -4,7 +4,13 @@
-
+
+
+
+
+
+
+
@@ -17,27 +23,27 @@
-
+ {
+ "associatedIndex": 3
+}
- {
+ "keyToString": {
+ "RunOnceActivity.ShowReadmeOnStart": "true",
+ "git-widget-placeholder": "main",
+ "last_opened_file_path": "/Users/jerrychukwudi/projects/ComfyUI_UploadToWebhookHTTP",
+ "node.js.detected.package.eslint": "true",
+ "node.js.detected.package.tslint": "true",
+ "node.js.selected.package.eslint": "(autodetect)",
+ "node.js.selected.package.tslint": "(autodetect)",
+ "nodejs_package_manager_path": "npm",
+ "vue.rearranger.settings.migration": "true"
}
-}]]>
+}
@@ -54,7 +60,8 @@
1744020525893
-
+
+
diff --git a/README.md b/README.md
index 7a6c82c..ab30af1 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,105 @@
-# ComfyUI_UploadToWebhookHTTP
\ No newline at end of file
+# ComfyUI_UploadToWebHook
+## @jerrywap
+
+
+
+A custom node for [ComfyUI](https://github.com/comfyanonymous/ComfyUI) that allows you to **send generated image(s) or video clips** directly to an HTTP webhook along with optional metadata such as `prompt_id` and `other_data`.
+
+---
+
+## โจ Features
+
+- ๐ Upload a single image or video (from image sequence) to a webhook URL
+- ๐ฆ Includes `prompt_id` and additional `other_data` as form data
+- ๐ง Accepts image tensor input from ComfyUI image nodes
+- ๐๏ธ Optional save toggle to control file persistence (save or temp)
+- ๐ Textarea input for passing additional JSON data
+
+---
+
+## ๐ง Installation
+
+1. Clone or download this repo into your `ComfyUI/custom_nodes` directory:
+
+```
+cd /workspace/ComfyUI/custom_nodes
+git clone https://github.com/yourusername/ComfyUI_UploadToWebHook.git
+```
+
+2. Install dependencies:
+
+```
+cd ComfyUI_UploadToWebHook
+bash install.sh
+```
+
+3. Restart ComfyUI (or use the **Reload Custom Nodes** button if available).
+
+---
+
+## ๐งฉ How to Use
+
+In ComfyUI:
+
+1. Drag your image output (e.g., from `VAE Decode`) to the **Send To Http Webhook** node.
+2. Configure:
+ - `webhook_url`: The URL that will receive your image or video.
+ - `frame_rate`: Only used when sending multiple images as a video.
+ - `save_image`: Toggle to control whether to store file permanently.
+ - `prompt_id`: (optional) Identifier of your prompt or run.
+ - `other_data`: (optional) JSON key-value data sent as extra POST fields.
+
+---
+
+## ๐ผ๏ธ UI Example
+
+
+
+---
+
+## ๐งช Webhook Example
+
+You can test with a free service like [https://webhook.site](https://webhook.site).
+
+- The uploaded image/video appears as `file`.
+- Additional fields (`prompt_id`, `other_data`) are sent as part of the POST form data.
+
+---
+
+## ๐ค Output Payload
+
+Sample multipart form sent to webhook:
+
+```
+POST /your/webhook HTTP/1.1
+Content-Type: multipart/form-data
+
+file: image.png / video.mp4
+prompt_id: acde070d-8c4c-4f0d-9d8a-162843
+other_data: {"hello": "world"}
+```
+
+---
+
+## ๐ Folder Structure
+
+```
+ComfyUI_UploadToWebHook/
+โโโ __init__.py
+โโโ requirements.txt
+โโโ install.sh
+```
+
+---
+
+## ๐งโ๐ป Contributing
+
+Pull requests and feature ideas are welcome!
+Feel free to fork and create a PR.
+
+---
+
+## ๐ License
+
+This project is licensed under the MIT License.
+See [LICENSE](./LICENSE) for details.
diff --git a/__init__.py b/__init__.py
new file mode 100644
index 0000000..8d91d91
--- /dev/null
+++ b/__init__.py
@@ -0,0 +1,106 @@
+import os
+import json
+import numpy as np
+import requests
+from PIL import Image
+
+import folder_paths
+from moviepy.video.io.ImageSequenceClip import ImageSequenceClip
+
+class UploadToWebHookHTTP:
+ @classmethod
+ def INPUT_TYPES(cls):
+ return {
+ "required": {
+ "images": ("IMAGE",),
+ "webhook_url": ("STRING", {"default": "https://example.com/path_to_webhook"}),
+ "frame_rate": ("INT", {"default": 12, "min": 1, "max": 60, "step": 1}),
+ "save_image": ("BOOLEAN", {"default": True}),
+ "prompt_id": ("STRING", {"default": ""}),
+ "other_data": (
+ "STRING",
+ {
+ "default": "{\n \"key1\": \"value1\",\n \"key2\": \"value2\"\n}",
+ "multiline": True
+ }
+ )
+ },
+ }
+
+ RETURN_TYPES = ("STRING",)
+ OUTPUT_NODE = True
+ CATEGORY = "JerrywapWebhookHTTP"
+ FUNCTION = "generate_and_upload_video"
+
+ def generate_and_upload_video(
+ self,
+ images,
+ webhook_url: str,
+ frame_rate: int,
+ save_image=True,
+ prompt_id: str = "",
+ other_data: str = "{}"
+ ):
+ output_dir = folder_paths.get_output_directory() if save_image else folder_paths.get_temp_directory()
+
+ (
+ full_output_folder,
+ filename,
+ counter,
+ subfolder,
+ _,
+ ) = folder_paths.get_save_image_path("final", output_dir)
+
+ # Prepare payload
+ try:
+ parsed_data = json.loads(other_data)
+ except json.JSONDecodeError:
+ parsed_data = {}
+
+ if prompt_id:
+ parsed_data["prompt_id"] = prompt_id
+
+ if len(images) == 1:
+ single_file_path = os.path.join(full_output_folder, f"{filename}_.png")
+ single_image = 255.0 * images[0].cpu().numpy()
+ single_image_pil = Image.fromarray(single_image.astype(np.uint8))
+ single_image_pil.save(single_file_path)
+
+ with open(single_file_path, "rb") as file:
+ response = requests.post(
+ webhook_url,
+ files={"file": ("image.png", file, "image/png")},
+ data=parsed_data
+ )
+
+ else:
+ frames = [255.0 * image.cpu().numpy() for image in images]
+ clip = ImageSequenceClip(frames, fps=frame_rate)
+ file_path = os.path.join(full_output_folder, f"{filename}_{counter:05}_.mp4")
+ clip.write_videofile(file_path, codec="libx264", fps=frame_rate)
+
+ with open(file_path, "rb") as file_data:
+ response = requests.post(
+ webhook_url,
+ files={"file": ("video.mp4", file_data, "video/mp4")},
+ data=parsed_data
+ )
+
+ # Response output
+ if response.status_code == 200 or response.status_code == 201 or response.status_code == 204:
+ print("โ
Successfully uploaded to Webhook.")
+ print(f"Response Code: {response.status_code}")
+ print(f"Response Text: {response.text}")
+ else:
+ print(f"โ Failed to upload. Status code: {response.status_code} - {response.text}")
+
+ return ("Uploading Completed",)
+
+
+NODE_CLASS_MAPPINGS = {
+ "UploadToWebHookHTTP": UploadToWebHookHTTP,
+}
+
+NODE_DISPLAY_NAME_MAPPINGS = {
+ "UploadToWebHookHTTP": "Send To Http Webhook",
+}
diff --git a/install.sh b/install.sh
new file mode 100644
index 0000000..9053fa6
--- /dev/null
+++ b/install.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+echo "๐ง Installing dependencies for ComfyUI_UploadToWebHook..."
+
+# Exit immediately if a command exits with a non-zero status
+set -e
+
+# Activate venv if in ComfyUI RunPod or similar
+if [ -d "../../venv" ]; then
+ echo "๐ฆ Activating virtual environment..."
+ source ../../venv/bin/activate
+fi
+
+# Install requirements
+pip install -r requirements.txt
+
+echo "โ
Installation complete!"
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..dfd0d52
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,4 @@
+numpy
+requests
+Pillow
+moviepy
diff --git a/screenshot.png b/screenshot.png
new file mode 100644
index 0000000..058fba8
Binary files /dev/null and b/screenshot.png differ
diff --git a/screenshot2.png b/screenshot2.png
new file mode 100644
index 0000000..67eea89
Binary files /dev/null and b/screenshot2.png differ