Live
Article12 min read

DIY Deepfake Magic: Create Stunning Face Swaps from Home for Just $0.24/Hour!

DIY Deepfake Magic: Create Stunning Face Swaps from Home for Just $0.24/Hour!

Hey there, AI adventurers! Welcome back to Best Free AI Porn, where we geek out on the coolest, most accessible ways to play with cutting-edge tech. If you've ever dreamed of swapping faces in images like a digital wizard—without dropping a fortune or needing a supercomputer—this tutorial is your golden ticket. We're talking deepfakes made easy, right from your couch, using free tools and a sneaky cloud setup that's stealthy and budget-friendly. No fancy hardware required; just your browser and a bit of curiosity.

Today, we'll walk through creating deepfakes with ComfyUI and the ReActor node. It's a node-based powerhouse for Stable Diffusion, perfect for generating images from prompts and then seamlessly swapping faces. We'll use RunPod for cloud power at a whisper-quiet $0.24 per hour on an RTX 2000 Ada GPU. Think of it as renting a beastly machine that does all the heavy lifting while you sip coffee. We'll keep things stealthy—no traces on your local setup, everything ephemeral and secure.

By the end, you'll have a workflow to generate custom scenes and swap in any face you like. Remember, play responsibly: this is for fun, art, and creativity. Let's get that deepfake glow-up started!

How to make deepfakes illustration

Step 1: Sign Up for RunPod – Your Cloud Playground Awaits

First things first: you need a RunPod account. It's free to sign up, and you'll need to add some credits to get rolling. Head over to runpod.io and click "Sign Up." Fill in your details—email, password, the usual. Once you're in the dashboard, top up your account with at least $10 (that's enough for about 35-40 hours on our cheap pod, plus storage). Pro tip: Use a referral if you spot one for bonus credits!

From the docs at RunPod's get-started guide, the minimum credit keeps things simple. No credit card drama if you watch your usage—set auto-termination later to avoid surprises. Once funded, you're dashboard-ready. Friendly reminder: RunPod's secure, but always use strong passwords for that stealth vibe.

Step 2: Deploy Your Minimal Pod – Cheap, Fast, and Furious

Now, let's spin up a pod. In the RunPod dashboard, go to the "Pods" section and hit "Deploy." Search for the template: runpod/pytorch:2.8.0-py3.11-cuda12.8.1-cudnn-devel-ubuntu22.04. This bad boy is optimized for PyTorch with CUDA 12.8.1, perfect for our AI antics.

Key Configs (Highlight: These are crucial for keeping costs low!):

  • GPU: Select RTX 2000 Ada – it's $0.24/hour, with 16GB VRAM. Plenty for SDXL and ReActor without breaking the bank. (Confirmed pricing from RunPod's GPU dashboard and Reddit discussions.)
  • Storage: Opt for a 100GB Network Volume (~$7/month persistent). It saves your models and outputs across sessions—super stealthy for long-term play without re-downloading everything.
  • Other Settings: 20GB RAM, 1 vCPU. Enable auto-termination after 10-30 minutes of inactivity to save credits.
  • Hit "Deploy" and wait 1-2 minutes for the pod to go green (Running status).

Your pod ID will pop up—note it down; we'll use it for connections. If you're new, check RunPod's ComfyUI tutorial for visuals. Boom—your home deepfake lab is live!

Step 3: Connect via Jupyter Lab – Your Control Center

With the pod running, click "Connect" in the dashboard. Under HTTP Services, grab the Jupyter Lab link: https://[podId]-8888.proxy.runpod.net/lab. (Replace [podId] with your actual ID, like jsqxxxxxxt3q5.) This opens a web-based IDE—think VS Code in the cloud.

If it asks for a token, it's in the pod logs or generated on connect. From RunPod docs, just paste it in. Once loaded, you'll see the file browser at /workspace. Friendly heads-up: Bookmark this URL; it's your gateway.

Pro Tip: If Jupyter feels clunky, some pods offer VS Code Server, but Jupyter's perfect for our terminal needs. No local installs—total stealth!

Step 4: Fire Up the Terminal – Time to Install the Magic

In Jupyter Lab, go to "File" > "New" > "Terminal" (or right-click in the file browser and select "New Terminal"). You're now in a Linux shell at /workspace. This is where the fun ramps up!

Highlight: The One-Liner Install – Copy-Paste This Beast!
Paste and run this exact command. It clones ComfyUI, sets up the environment, installs ReActor, and downloads essentials like SDXL models. It takes 5-15 minutes (downloads are the bottleneck). Watch the magic unfold!

cd /workspace && git clone https://github.com/comfyanonymous/ComfyUI.git && cd ComfyUI && apt update && apt install -y build-essential && python -m venv venv && source venv/bin/activate && pip install --upgrade pip && pip install torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cu128 && pip install -r requirements.txt && cd custom_nodes && git clone https://github.com/Gourieff/comfyui-reactor-node.git && cd comfyui-reactor-node && pip install insightface==0.7.3 && python install.py && mkdir -p ../../models/insightface/models/antelopev2 && wget -O ../../models/insightface/models/antelopev2/inswapper_128.onnx https://huggingface.co/ezioruan/inswapper_128.onnx/resolve/main/inswapper_128.onnx && cd ../../models/facerestore_models && wget -O codeformer-v0.1.0.pth https://github.com/sczhou/CodeFormer/releases/download/v0.1.0/codeformer.pth && cd ../checkpoints && wget -O sd_xl_base_1.0.safetensors https://huggingface.co/stabilityai/stable-diffusion-xl-base-1.0/resolve/main/sd_xl_base_1.0.safetensors && cd ../vae && wget -O sdxl_vae.safetensors https://huggingface.co/stabilityai/sdxl-vae/resolve/main/sdxl_vae.safetensors && cd /workspace/ComfyUI

What This Does (Breakdown for the Curious):

  • Navigates to /workspace and clones ComfyUI from GitHub.
  • Updates system and installs build tools for compiling deps.
  • Creates a virtual env (venv) to keep things tidy.
  • Installs PyTorch (CUDA 12.8 compatible), ComfyUI requirements, ReActor node, and Insightface for face detection.
  • Downloads: Inswapper model (~246MB) for swapping, CodeFormer (~540MB) for face restoration, SDXL base (~6.9GB) for image gen, and VAE (~335MB) for decoding.
  • Ends back in ComfyUI dir.

If it hiccups (e.g., network glitch), re-run sections. Source: Aggregated from ComfyUI GitHub, ReActor repo, and RunPod tutorials.

Step 5: Uncensor ReActor – Unlock the Full Potential (Stealth Mode)

ReActor has a built-in NSFW filter to play nice, but for unrestricted creativity, we'll tweak it. This is a simple edit—ethical use only, folks!

In Jupyter's file browser, navigate to: /workspace/ComfyUI/custom_nodes/comfyui-reactor-node/scripts/reactor_sfw.py.

Right-click the file > "Open With" > "Editor" (or use terminal: nano reactor_sfw.py).

Find the function def nsfw_image(...) (around line 10-20). At the very beginning of it, add: return False. Save the file.

Why? This bypasses the detector, letting ReActor work on any content. From Reddit guide and YouTube fix, it's a quick hack. Restart ComfyUI after (next step) for changes to stick. Stealthy and reversible—just comment out the line later.

Step 6: Launch ComfyUI – Your Node Wonderland

Back in the terminal (ensure you're in /workspace/ComfyUI and venv activated: source venv/bin/activate), start the server:

python main.py --listen 0.0.0.0 --port 3000

This binds to all interfaces on port 3000. If port 3000 is busy, kill it: fuser -k 3000/tcp and retry.

Now, in the RunPod dashboard, click "Connect" on your pod > HTTP Service for port 3000: https://[podId]-3000.proxy.runpod.net/. (Some templates use 8188; adjust if needed.) You'll see the ComfyUI interface—a canvas for nodes!

From RunPod's Flux guide, this proxies securely. If it doesn't load, restart via terminal or pod menu.

Restart Tip: In ComfyUI, use the menu (top-right) for refresh, or terminal kill/restart for full reboot.

Step 7: Load the Workflow – Paste and Play

ComfyUI uses JSON workflows. Copy this complete minimal ReActor deepfake workflow (text-to-image gen + face swap). In the UI, click "Load" (or drag-drop a .json file if you save it).

Here's the full JSON—save it as deepfake_workflow.json locally if you like, then upload via Jupyter to /workspace/ComfyUI and load:

{
  "id": "minimal-reactor-workflow",
  "revision": 0,
  "last_node_id": 10,
  "last_link_id": 14,
  "nodes": [
    {
      "id": 1,
      "type": "CheckpointLoaderSimple",
      "pos": [100, 100],
      "size": [270, 98],
      "flags": {},
      "order": 0,
      "mode": 0,
      "inputs": [],
      "outputs": [
        {
          "name": "MODEL",
          "type": "MODEL",
          "links": [1]
        },
        {
          "name": "CLIP",
          "type": "CLIP",
          "links": [2, 3]
        },
        {
          "name": "VAE",
          "type": "VAE",
          "links": [4]
        }
      ],
      "properties": {
        "cnr_id": "comfy-core",
        "ver": "0.3.41",
        "Node name for S&R": "CheckpointLoaderSimple"
      },
      "widgets_values": ["sd_xl_base_1.0.safetensors"]
    },
    {
      "id": 2,
      "type": "CLIPTextEncode",
      "pos": [400, 100],
      "size": [400, 200],
      "flags": {},
      "order": 1,
      "mode": 0,
      "inputs": [
        {
          "name": "clip",
          "type": "CLIP",
          "link": 2
        }
      ],
      "outputs": [
        {
          "name": "CONDITIONING",
          "type": "CONDITIONING",
          "links": [5]
        }
      ],
      "properties": {
        "cnr_id": "comfy-core",
        "ver": "0.3.41",
        "Node name for S&R": "CLIPTextEncode"
      },
      "widgets_values": ["a beautiful landscape, mountains, river, sunset"]
    },
    {
      "id": 3,
      "type": "CLIPTextEncode",
      "pos": [400, 350],
      "size": [400, 200],
      "flags": {},
      "order": 2,
      "mode": 0,
      "inputs": [
        {
          "name": "clip",
          "type": "CLIP",
          "link": 3
        }
      ],
      "outputs": [
        {
          "name": "CONDITIONING",
          "type": "CONDITIONING",
          "links": [6]
        }
      ],
      "properties": {
        "cnr_id": "comfy-core",
        "ver": "0.3.41",
        "Node name for S&R": "CLIPTextEncode"
      },
      "widgets_values": ["blurry, low quality, artifacts"]
    },
    {
      "id": 4,
      "type": "EmptyLatentImage",
      "pos": [100, 250],
      "size": [270, 106],
      "flags": {},
      "order": 3,
      "mode": 0,
      "inputs": [],
      "outputs": [
        {
          "name": "LATENT",
          "type": "LATENT",
          "links": [7]
        }
      ],
      "properties": {
        "cnr_id": "comfy-core",
        "ver": "0.3.41",
        "Node name for S&R": "EmptyLatentImage"
      },
      "widgets_values": [1024, 1024, 1]
    },
    {
      "id": 5,
      "type": "KSampler",
      "pos": [850, 100],
      "size": [270, 262],
      "flags": {},
      "order": 4,
      "mode": 0,
      "inputs": [
        {
          "name": "model",
          "type": "MODEL",
          "link": 1
        },
        {
          "name": "positive",
          "type": "CONDITIONING",
          "link": 5
        },
        {
          "name": "negative",
          "type": "CONDITIONING",
          "link": 6
        },
        {
          "name": "latent_image",
          "type": "LATENT",
          "link": 7
        }
      ],
      "outputs": [
        {
          "name": "LATENT",
          "type": "LATENT",
          "links": [8]
        }
      ],
      "properties": {
        "cnr_id": "comfy-core",
        "ver": "0.3.41",
        "Node name for S&R": "KSampler"
      },
      "widgets_values": [156680208522230, "randomize", 20, 1, "euler", "normal", 1]
    },
    {
      "id": 6,
      "type": "VAEDecode",
      "pos": [1150, 100],
      "size": [147, 46],
      "flags": {},
      "order": 5,
      "mode": 0,
      "inputs": [
        {
          "name": "samples",
          "type": "LATENT",
          "link": 8
        },
        {
          "name": "vae",
          "type": "VAE",
          "link": 4
        }
      ],
      "outputs": [
        {
          "name": "IMAGE",
          "type": "IMAGE",
          "links": [9]
        }
      ],
      "properties": {
        "cnr_id": "comfy-core",
        "ver": "0.3.41",
        "Node name for S&R": "VAEDecode"
      },
      "widgets_values": []
    },
    {
      "id": 7,
      "type": "LoadImage",
      "pos": [100, 400],
      "size": [340, 314],
      "flags": {},
      "order": 6,
      "mode": 0,
      "inputs": [],
      "outputs": [
        {
          "name": "IMAGE",
          "type": "IMAGE",
          "links": [10]
        },
        {
          "name": "MASK",
          "type": "MASK",
          "links": null
        }
      ],
      "properties": {
        "cnr_id": "comfy-core",
        "ver": "0.3.41",
        "Node name for S&R": "LoadImage"
      },
      "widgets_values": ["source_face_image.png", "image"]
    },
    {
      "id": 8,
      "type": "ReActorFaceSwap",
      "pos": [1350, 100],
      "size": [285, 358],
      "flags": {},
      "order": 7,
      "mode": 0,
      "inputs": [
        {
          "name": "input_image",
          "type": "IMAGE",
          "link": 9
        },
        {
          "name": "source_image",
          "type": "IMAGE",
          "link": 10
        },
        {
          "name": "face_model",
          "type": "FACE_MODEL",
          "link": null
        },
        {
          "name": "face_boost",
          "type": "FACE_BOOST",
          "link": null
        }
      ],
      "outputs": [
        {
          "name": "SWAPPED_IMAGE",
          "type": "IMAGE",
          "links": [11]
        },
        {
          "name": "FACE_MODEL",
          "type": "FACE_MODEL",
          "links": null
        },
        {
          "name": "ORIGINAL_IMAGE",
          "type": "IMAGE",
          "links": null
        }
      ],
      "properties": {
        "cnr_id": "comfyui-reactor",
        "ver": "48a3ad27f99f775dcf63e61276e0110d256597ef",
        "Node name for S&R": "ReActorFaceSwap"
      },
      "widgets_values": [true, "inswapper_128.onnx", "retinaface_resnet50", "codeformer-v0.1.0.pth", 1, 1, "no", "no", "0", "0", 1]
    },
    {
      "id": 9,
      "type": "SaveImage",
      "pos": [1650, 100],
      "size": [308, 270],
      "flags": {},
      "order": 8,
      "mode": 0,
      "inputs": [
        {
          "name": "images",
          "type": "IMAGE",
          "link": 11
        }
      ],
      "outputs": [],
      "properties": {
        "cnr_id": "comfy-core",
        "ver": "0.3.41",
        "Node name for S&R": "SaveImage"
      },
      "widgets_values": ["ComfyUI"]
    }
  ],
  "links": [
    [1, 1, 0, 5, 0, "MODEL"],
    [2, 1, 1, 2, 0, "CLIP"],
    [3, 1, 1, 3, 0, "CLIP"],
    [4, 1, 2, 6, 1, "VAE"],
    [5, 2, 0, 5, 1, "CONDITIONING"],
    [6, 3, 0, 5, 2, "CONDITIONING"],
    [7, 4, 0, 5, 3, "LATENT"],
    [8, 5, 0, 6, 0, "LATENT"],
    [9, 6, 0, 8, 0, "IMAGE"],
    [10, 7, 0, 8, 1, "IMAGE"],
    [11, 8, 0, 9, 0, "IMAGE"]
  ],
  "groups": [],
  "config": {},
  "extra": {},
  "version": 0.4
}

This workflow generates an image from a prompt (using SDXL), then swaps in a source face via ReActor. Sourced from ComfyUI examples and ReActor docs.

Step 8: Choose Your Input Image – The Face Swap Star

Upload your source face image to /workspace/ComfyUI/input/ via Jupyter (drag-drop in file browser). Clear, front-facing photos work best—think high-res, neutral expression.

In the workflow, double-click the "LoadImage" node (ID 7). Set filename to your image (e.g., "myface.png") and resource to "image." Hit save. For the target, it'll auto-gen from the prompt, but you can swap nodes for img2img if needed.

From ReActor GitHub, input_image is the base (generated scene), source_image is your face to swap in.

Step 9: Craft Your Prompt – Let the Creativity Flow

Double-click the positive "CLIPTextEncode" node (ID 2) and edit the prompt. Example: "a seductive pose in a bedroom, soft lighting, detailed skin." Keep negatives (ID 3) like "ugly, deformed, extra limbs" for quality.

SDXL shines with descriptive prompts—add styles like "photorealistic, 8k." From Hugging Face SDXL page, it's text-to-image gold. Tweak for your vision, then save nodes.

Step 10: Run the Workflow – Watch the Deepfake Unfold

Hit the "Queue Prompt" button (top-right in ComfyUI). It processes: sampling (~20 steps, 10-20s), decoding (quick), ReActor swap (2-5s). Output saves to /workspace/ComfyUI/output/—download via Jupyter.

First run? ~30s total on RTX 2000 Ada. Playful tweak: Randomize seed in KSampler for variety!

Troubleshooting: Common Hiccups and Fixes

  • Pod Won't Start: Check credits; redeploy if stuck. See RunPod docs.
  • Download Fails: Wget timeouts? Add --tries=3 --continue to commands. Network volumes help persistence (Reddit tip).
  • ReActor Errors: Insightface import fail? Re-run pip install insightface==0.7.3. For CUDA mismatches, verify template (PyTorch guide).
  • Black/Blurry Output: NSFW filter? Double-check edit. Low quality? Bump steps to 30 or refine prompt.
  • VRAM Crash: Lower res in EmptyLatentImage to 512x512. RTX 2000 handles 1024x1024 fine, though.
  • ComfyUI Not Loading: Kill port (fuser -k 3000/tcp), restart python command. From GitHub issues.

If stuck, search r/comfyui on Reddit—community's super helpful.

Advanced Tips: Level Up Your Deepfakes

Want video? Add AnimateDiff nodes (git clone in custom_nodes). For better swaps, enable ReActor's masking: Add ReActorMaskHelper node, connect as per GitHub. Blend faces? Use Load Face Model for .safetensors saves.

Stealth mode: Terminate pods after use; outputs download to your device. Costs? $0.24/hr + storage—under $1 for a session!

FAQs: Your Burning Questions Answered

Q: Is this legal/ethical?
A: Deepfakes are tools—use for consensual fun or art. Avoid harm; check laws (e.g., no non-consensual porn). ReActor warns "use on your own responsibility" (GitHub).

Q: Can I run this locally?
A: Sure, if you have a GPU (RTX 30-series+). But RunPod's cheaper for testing—no heat or power bills!

Q: More models?
A: Download via terminal, e.g., wget LoRAs to /models/loras. See SDXL guide.

Q: Costs add up?
A: $10 gets 40+ hours. Persistent volume: $7/month. Monitor in dashboard.

Q: Video deepfakes?
A: Chain with Mov2Mov (tutorial). Frame-by-frame magic!

There you have it, friends—a full DIY deepfake setup that's playful, powerful, and purse-friendly. Experiment, create, and share your wins in the comments. What's your first swap? Drop it below—we're all ears (and eyes)! Stay creative, stay safe. 🚀