Instructions to use bbbboiwow/cocccck with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Diffusers
How to use bbbboiwow/cocccck with Diffusers:
pip install -U diffusers transformers accelerate
import torch from diffusers import DiffusionPipeline # switch to "mps" for apple devices pipe = DiffusionPipeline.from_pretrained("bbbboiwow/cocccck", dtype=torch.bfloat16, device_map="cuda") prompt = "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k" image = pipe(prompt).images[0] - Notebooks
- Google Colab
- Kaggle
| # roop_custom_nodes.py | |
| import os | |
| import subprocess | |
| import glob | |
| from PIL import Image | |
| import numpy as np | |
| import torch | |
| import hmac | |
| import hashlib | |
| import requests | |
| # Helper: save tensor image | |
| def save_tensor_as_image(tensor, path): | |
| np_img = (tensor[0].cpu().numpy() * 255).astype(np.uint8) | |
| if np_img.shape[0] == 3: # If format is CHW | |
| np_img = np.transpose(np_img, (1, 2, 0)) # Convert to HWC for PIL | |
| img = Image.fromarray(np_img) | |
| img.save(path) | |
| # Helper: load image as tensor | |
| def load_image_as_tensor(path): | |
| img = Image.open(path).convert("RGB") | |
| np_img = np.array(img).astype(np.float32) / 255.0 | |
| return torch.from_numpy(np_img).unsqueeze(0) | |
| def get_unique_filename(path): | |
| base, ext = os.path.splitext(path) | |
| counter = 1 | |
| new_path = path | |
| while os.path.exists(new_path): | |
| new_path = f"{base}_{counter}{ext}" | |
| counter += 1 | |
| return new_path | |
| def send_webhook_image(webhook_url, webhook_secret, output_path, extra_data=None): | |
| if not webhook_url: | |
| return | |
| with open(output_path, 'rb') as f: | |
| image_data = f.read() | |
| # GitHub-style HMAC signature | |
| signature = 'sha256=' + hmac.new( | |
| webhook_secret.encode('utf-8'), | |
| image_data, | |
| hashlib.sha256 | |
| ).hexdigest() | |
| headers = { | |
| 'X-Hub-Signature-256': signature | |
| } | |
| files = { | |
| 'file': ('swapped.png', image_data, 'image/png') | |
| } | |
| data = extra_data or {} | |
| try: | |
| resp = requests.post(webhook_url, headers=headers, files=files, data=data) | |
| resp.raise_for_status() | |
| print(f"[Webhook] Sent successfully to {webhook_url}") | |
| except Exception as e: | |
| print(f"[Webhook Error] {e}") | |
| class RoopFaceSwap: | |
| def INPUT_TYPES(cls): | |
| return { | |
| "required": { | |
| "source_image": ("IMAGE",), | |
| "target_image": ("IMAGE",), | |
| "roop_dir": ("STRING", {"default": "/content/roop"}), | |
| "output_name": ("STRING", {"default": "roop_output.png"}), | |
| "many_faces": ("BOOLEAN", {"default": False}) | |
| } | |
| } | |
| RETURN_TYPES = ("IMAGE",) | |
| RETURN_NAMES = ("swapped_image",) | |
| FUNCTION = "run" | |
| CATEGORY = "Roop/Basic" | |
| def run(self, source_image, target_image, roop_dir, output_name, many_faces): | |
| temp_dir = os.path.join(roop_dir, "temp_io") | |
| os.makedirs(temp_dir, exist_ok=True) | |
| source_path = os.path.join(temp_dir, "source.png") | |
| target_path = os.path.join(temp_dir, "target.png") | |
| output_path = get_unique_filename(os.path.join(temp_dir, output_name)) | |
| save_tensor_as_image(source_image, source_path) | |
| save_tensor_as_image(target_image, target_path) | |
| cmd = [ | |
| "python", "run.py", | |
| "-s", source_path, | |
| "-t", target_path, | |
| "-o", output_path, | |
| "--execution-provider", "cuda", | |
| "--frame-processor", "face_swapper" | |
| ] | |
| if many_faces: | |
| cmd.append("--many-faces") | |
| subprocess.run(cmd, check=True, cwd=roop_dir) | |
| if not os.path.exists(output_path): | |
| print(f"[Warning] Roop did not produce output: {output_path}") | |
| blank = torch.zeros_like(target_image) | |
| return (blank,) | |
| return (load_image_as_tensor(output_path),) | |
| class RoopFaceSwapWithEnhancer: | |
| def INPUT_TYPES(cls): | |
| return { | |
| "required": { | |
| "source_image": ("IMAGE",), | |
| "target_image": ("IMAGE",), | |
| "roop_dir": ("STRING", {"default": "/content/roop"}), | |
| "output_name": ("STRING", {"default": "roop_output.png"}), | |
| "many_faces": ("BOOLEAN", {"default": False}) | |
| } | |
| } | |
| RETURN_TYPES = ("IMAGE",) | |
| RETURN_NAMES = ("swapped_image",) | |
| FUNCTION = "run" | |
| CATEGORY = "Roop/Enhanced" | |
| def run(self, source_image, target_image, roop_dir, output_name, many_faces): | |
| temp_dir = os.path.join(roop_dir, "temp_io") | |
| os.makedirs(temp_dir, exist_ok=True) | |
| source_path = os.path.join(temp_dir, "source.png") | |
| target_path = os.path.join(temp_dir, "target.png") | |
| output_path = get_unique_filename(os.path.join(temp_dir, output_name)) | |
| save_tensor_as_image(source_image, source_path) | |
| save_tensor_as_image(target_image, target_path) | |
| cmd = [ | |
| "python", "run.py", | |
| "-s", source_path, | |
| "-t", target_path, | |
| "-o", output_path, | |
| "--execution-provider", "cuda", | |
| "--frame-processor", "face_swapper", "face_enhancer" | |
| ] | |
| if many_faces: | |
| cmd.append("--many-faces") | |
| subprocess.run(cmd, check=True, cwd=roop_dir) | |
| if not os.path.exists(output_path): | |
| print(f"[Warning] Roop did not produce output: {output_path}") | |
| blank = torch.zeros_like(target_image) | |
| return (blank,) | |
| return (load_image_as_tensor(output_path),) | |
| class RoopBatchFaceSwap: | |
| def INPUT_TYPES(cls): | |
| return { | |
| "required": { | |
| "source_image": ("IMAGE",), | |
| "input_dir": ("STRING", {"default": "/input/images"}), | |
| "output_dir": ("STRING", {"default": "/output/images"}), | |
| "roop_dir": ("STRING", {"default": "/content/roop"}), | |
| "use_enhancer": ("BOOLEAN", {"default": False}), | |
| "many_faces": ("BOOLEAN", {"default": False}) | |
| } | |
| } | |
| RETURN_TYPES = () | |
| RETURN_NAMES = () | |
| FUNCTION = "run" | |
| CATEGORY = "Roop/Batch" | |
| def run(self, source_image, input_dir, output_dir, roop_dir, use_enhancer, many_faces): | |
| os.makedirs(output_dir, exist_ok=True) | |
| temp_dir = os.path.join(roop_dir, "temp_io") | |
| os.makedirs(temp_dir, exist_ok=True) | |
| source_path = os.path.join(temp_dir, "source.png") | |
| save_tensor_as_image(source_image, source_path) | |
| image_paths = glob.glob(os.path.join(input_dir, "*.jpg")) + \ | |
| glob.glob(os.path.join(input_dir, "*.png")) | |
| for img_path in image_paths: | |
| target_name = os.path.basename(img_path) | |
| target_path = os.path.join(temp_dir, "target.png") | |
| output_path = os.path.join(output_dir, f"out_{target_name}") | |
| Image.open(img_path).save(target_path) | |
| cmd = [ | |
| "python", "run.py", | |
| "-s", source_path, | |
| "-t", target_path, | |
| "-o", output_path, | |
| "--execution-provider", "cuda", | |
| "--frame-processor", "face_swapper" | |
| ] | |
| if use_enhancer: | |
| cmd[-1] += " face_enhancer" | |
| if many_faces: | |
| cmd.append("--many-faces") | |
| subprocess.run(cmd, check=True, cwd=roop_dir) | |
| if not os.path.exists(output_path): | |
| print(f"[Skipped] NSFW or error: {img_path} -> No output generated.") | |
| continue | |
| return () | |
| class RoopFaceSwapVideo: | |
| def INPUT_TYPES(cls): | |
| return { | |
| "required": { | |
| "source_image": ("IMAGE",), | |
| "target_video_path": ("STRING", {"default": "/path/to/video.mp4"}), | |
| "roop_dir": ("STRING", {"default": "/content/roop"}), | |
| "output_name": ("STRING", {"default": "swapped_video.mp4"}), | |
| "many_faces": ("BOOLEAN", {"default": False}) | |
| } | |
| } | |
| RETURN_TYPES = () | |
| RETURN_NAMES = () | |
| FUNCTION = "run" | |
| CATEGORY = "Roop/Video" | |
| def run(self, source_image, target_video_path, roop_dir, output_name, many_faces): | |
| temp_dir = os.path.join(roop_dir, "temp_io") | |
| os.makedirs(temp_dir, exist_ok=True) | |
| source_path = os.path.join(temp_dir, "source.png") | |
| output_path = get_unique_filename(os.path.join(temp_dir, output_name)) | |
| save_tensor_as_image(source_image, source_path) | |
| cmd = [ | |
| "python", "run.py", | |
| "-s", source_path, | |
| "-t", target_video_path, | |
| "-o", output_path, | |
| "--keep-fps", | |
| "--keep-frames", | |
| "--execution-provider", "cuda", | |
| "--frame-processor", "face_swapper" | |
| ] | |
| if many_faces: | |
| cmd.append("--many-faces") | |
| subprocess.run(cmd, check=True, cwd=roop_dir) | |
| if not os.path.exists(output_path): | |
| print(f"[Warning] Roop did not produce video output: {output_path}") | |
| return () | |
| class RoopSendWebhookImage: | |
| def INPUT_TYPES(cls): | |
| return { | |
| "required": { | |
| "image_tensor": ("IMAGE",), | |
| "filename": ("STRING", {"default": "output.png"}), | |
| "webhook_url": ("STRING", {"default": ""}), | |
| "webhook_secret": ("STRING", {"default": ""}), | |
| "enable_webhook": ("BOOLEAN", {"default": True}), | |
| "roop_dir": ("STRING", {"default": "/content/roop"}) | |
| } | |
| } | |
| RETURN_TYPES = () | |
| RETURN_NAMES = () | |
| FUNCTION = "run" | |
| CATEGORY = "Roop/Webhook" | |
| def run(self, image_tensor, filename, webhook_url, webhook_secret, enable_webhook, roop_dir): | |
| if not enable_webhook or not webhook_url: | |
| print("[WebhookImage] Disabled or URL not set — skipping.") | |
| return () | |
| temp_dir = os.path.join(roop_dir, "temp_io") | |
| os.makedirs(temp_dir, exist_ok=True) | |
| output_path = os.path.join(temp_dir, filename) | |
| save_tensor_as_image(image_tensor, output_path) | |
| try: | |
| with open(output_path, 'rb') as f: | |
| file_data = f.read() | |
| headers = {} | |
| if webhook_secret: | |
| signature = 'sha256=' + hmac.new( | |
| webhook_secret.encode('utf-8'), | |
| file_data, | |
| hashlib.sha256 | |
| ).hexdigest() | |
| headers['X-Hub-Signature-256'] = signature | |
| files = { | |
| 'file': (filename, file_data, 'image/png') | |
| } | |
| resp = requests.post(webhook_url, headers=headers, files=files) | |
| resp.raise_for_status() | |
| print(f"[WebhookImage] Sent image: {filename} → {webhook_url}") | |
| except Exception as e: | |
| print(f"[WebhookImage Error] {e}") | |
| return () | |
| class RoopSendWebhookFile: | |
| def INPUT_TYPES(cls): | |
| return { | |
| "required": { | |
| "file_path": ("STRING",), | |
| "filename": ("STRING", {"default": "output.mp4"}), | |
| "webhook_url": ("STRING", {"default": ""}), | |
| "webhook_secret": ("STRING", {"default": ""}), | |
| "enable_webhook": ("BOOLEAN", {"default": True}) | |
| } | |
| } | |
| RETURN_TYPES = () | |
| RETURN_NAMES = () | |
| FUNCTION = "run" | |
| CATEGORY = "Roop/Webhook" | |
| def run(self, file_path, filename, webhook_url, webhook_secret, enable_webhook): | |
| if not enable_webhook or not webhook_url: | |
| print("[WebhookFile] Disabled or URL not set — skipping.") | |
| return () | |
| if not os.path.exists(file_path): | |
| print(f"[WebhookFile] File does not exist: {file_path}") | |
| return () | |
| try: | |
| with open(file_path, 'rb') as f: | |
| file_data = f.read() | |
| headers = {} | |
| if webhook_secret: | |
| signature = 'sha256=' + hmac.new( | |
| webhook_secret.encode('utf-8'), | |
| file_data, | |
| hashlib.sha256 | |
| ).hexdigest() | |
| headers['X-Hub-Signature-256'] = signature | |
| content_type = "video/mp4" if filename.endswith(".mp4") else "application/octet-stream" | |
| files = { | |
| 'file': (filename, file_data, content_type) | |
| } | |
| resp = requests.post(webhook_url, headers=headers, files=files) | |
| resp.raise_for_status() | |
| print(f"[WebhookFile] Sent file: {filename} → {webhook_url}") | |
| except Exception as e: | |
| print(f"[WebhookFile Error] {e}") | |
| return () | |
| # Register with ComfyUI | |
| NODE_CLASS_MAPPINGS = { | |
| "RoopFaceSwap": RoopFaceSwap, | |
| "RoopFaceSwapWithEnhancer": RoopFaceSwapWithEnhancer, | |
| "RoopBatchFaceSwap": RoopBatchFaceSwap, | |
| "RoopFaceSwapVideo": RoopFaceSwapVideo, | |
| "RoopSendWebhookImage": RoopSendWebhookImage, | |
| "RoopSendWebhookFile": RoopSendWebhookFile, | |
| } | |
| NODE_DISPLAY_NAME_MAPPINGS = { | |
| "RoopFaceSwap": "Roop Face Swap (Image)", | |
| "RoopFaceSwapWithEnhancer": "Roop Face Swap + Enhancer", | |
| "RoopBatchFaceSwap": "Roop Batch Image Folder", | |
| "RoopFaceSwapVideo": "Roop Face Swap (Video)", | |
| "RoopSendWebhookImage": "Roop Webhook: Image Tensor", | |
| "RoopSendWebhookFile": "Roop Webhook: File Path", | |
| } | |