D3voz/openjutsu

★ 229⑂ 41

One-click character swap for videos: an open-source, local Higgsfield Genjutsu alternative built on ComfyUI and MiniMax H3.

About D3voz/openjutsu

D3voz/openjutsu is an open-source project on GitHub, mainly written in TypeScript. One-click character swap for videos: an open-source, local Higgsfield Genjutsu alternative built on ComfyUI and MiniMax H3. It currently holds 229 stars and 41 forks with 38 open issues, and was last pushed on 2026-10-28 (repository created 2026-10-26).

Project Overview

Git Homed tracks it on the Today's Trending board, currently at rank #31 with 0 new stars today.

GitHub Repository Details

Repository D3voz/openjutsu · default branch main · size 69484 KB · watchers 4 · source: GitHub REST API and repository README

README

Openjutsu

An open-source, Genjutsu-style character and object swap for video. Drop a video and a character photo, press Generate, and the main person in the video is replaced by your character. Or change their hair or clothes, remove something, or put them somewhere else. The camera, cuts, motion and soundtrack stay. Everything runs on open weights on your own GPU: MiniMax H3 for the video, SAM 3.1 to track people, and Qwen3-VL 8B to describe the pictures and shots.

The app is a small Next.js front end over a ComfyUI workflow. It uses @comfyorg/sdk, following Comfy's comfy-reshoot reference app.

https://github.com/user-attachments/assets/2d8d763a-1764-49a6-9116-d6d1be661ff6

| Advanced: several people, pick who becomes who | Object swap: paint where it goes | | --- | --- | | Two people swapped, each from their own photo | Sunglasses painted onto a person's eyes | | From picture: a new look and place from one picture | Post-processing: fix faces | | A video frame and a picture combined into a posed picture, then a video | A small face redrawn at close-up size |

First visit: visual describer

The welcome page lets you choose the vision-language model that describes pictures and video frames and writes prompts. Qwen3-VL 8B INT8 remains the default; Qwen3-VL 4B FP8 and Gemma 4 E2B INT8 are smaller alternatives. Install a compatible single-file model including its vision weights in ComfyUI/models/text_encoders, then press Refresh models. Other installed models can be selected if they support image/video input and text generation through ComfyUI's CLIPLoader and Generate Text nodes. Text-only models and files requiring a different loader are unsuitable.

Choose according to available VRAM and leave room for image/video context and working memory; file size is not a VRAM requirement, and H3 generation has separate memory needs. Your selection is saved in this browser and used for swaps, prompt descriptions and Find people. Reopen Welcome & models to change it, or use Visual describer under Model components. Alternative describers may change prompt quality and person matching. Set up later opens the editor; generation still checks the required files. The separate H3 text encoder remains unchanged.

Modes

Requirements

Custom nodes

Install these into ComfyUI/custom_nodes (ComfyUI Manager finds the first three by name):

| Pack | Used for | | --- | --- | | SolarRenderer | From picture: SolarRenderer LoRA loading, conditioning and four-step sampling | | ComfyUI-MiniMaxH3-Context-Loop 0.7.3+ | clip loop, checkpoints, final assembly | | ComfyUI-Fantastic-MiniMaxH3-PromptBuilder | masked video-edit latent | | ComfyUI-KJNodes | Grow Mask With Blur; From picture: VRAM cleanup | | comfyui_controlnet_aux | From picture: Metric3D normal maps | | ComfyUI-VideoHelperSuite | video loading | | comfyui-h3-oneclick-swap | swap and object plans, people and role masks, grey mannequins, track labelling, cut finder, shot list, face-fix chunks | | ComfyUI-H3-FaceRefine | Fix faces: face tracking and cropping, SAM face masks, pasting back | | ComfyUI-Impact-Pack | Fix faces: SAM loader | | comfyui-image-detail-contrast | Fix colours: Image Detail Contrast | | Orion4D_FXMax | Fix colours: DCTL Tone Mapper and its presets | | comfyui-websocket-reconnect-fix | every job: keeps live progress coming after the proxy reconnects to ComfyUI (adds no nodes) |

Restart ComfyUI after installing them.

Before uploading a job, Openjutsu checks the selected workflow against ComfyUI's node and model lists. Missing packs appear with installation links; missing model files appear with their destination folders. Disabled steps are excluded from the check. This checks registered nodes and listed model files, not Python dependencies, model integrity or available VRAM. COMFYUI_URL must point at ComfyUI itself (normally http://127.0.0.1:8188).

Models

For From picture → SolarRenderer, download solarrenderer_4step_lora.safetensors and solarrenderer_control_lora.safetensors from Enderfga/SolarRenderer, or the corresponding rank-64 pair from mdevoz/SolarRendererRank64. Put both in ComfyUI/models/loras or a subfolder, reload the app and choose their paths in the render settings.

| Folder in ComfyUI/models | File | | --- | --- | | diffusion_models | minimax_h3_ref2va_pruned_int8_convrot.safetensors | | loras | minimax_h3_DMAD_4step_full_lora_avg_rank_39_bf16.safetensors | | text_encoders | qwen3vl_32b_minimax_h3_int4_convrot.safetensors (H3 text encoder) | | text_encoders | qwen3vl_8b_int8_convrot.safetensors (describer) | | vae | minimax_h3_video_vae_int8_convrot.safetensors, minimax_h3_audio_vae_fp32.safetensors | | checkpoints | sam3.1_multiplex_fp16.safetensors | | ultralytics/bbox, ultralytics/segm | face_yolov8m.pt, person_yolov8m-seg.pt (Bingsu/adetailer), for Fix faces | | sams | sam_vit_b_01ec64.pth, for Fix faces | | insightface/models | buffalo_l (InsightFace downloads it on first use), for Fix faces |

Run it locally

On Windows, double-click start_openjutsu.bat (ComfyUI must be running, or started while it waits). The first run installs comfy-api-proxy 0.1.6 into .venv-proxy and the node packages, and patch_proxy.py fixes the proxy's live progress (node changes and mid-job previews). Each run builds the app, then opens the proxy and the app (npm start, the production server) in two windows and the page in your browser. Close those two windows to stop Openjutsu. The manual steps:

1. Start ComfyUI on 127.0.0.1:8188. On Windows, set AIOHTTP_NOSENDFILE=1 first (PowerShell: $env:AIOHTTP_NOSENDFILE = "1"). Without it, the first partial-file request (the video player sends one when you seek) can stall ComfyUI's /view, and every later file download hangs until ComfyUI restarts. 2. Install the proxy, fix its live progress with this repo's patch_proxy.py (run it with the same Python), and start it. It serves the Comfy API v2 on 127.0.0.1:8189. Raise the upload cap for longer videos (the default is 100 MB):

   pip install comfy-api-proxy==0.1.6
   python openjutsu/patch_proxy.py
   comfy-api-proxy run --max-upload-mb 500
   

3. Install and start the app:

   git clone  openjutsu
   cd openjutsu
   cp .env.example .env.local
   npm ci
   npm run build
   npm start
   

While changing the code, npm run dev runs the development server instead.

4. Open .

.env.local sets COMFY_BASE_URL=http://127.0.0.1:8189. Leave COMFY_API_KEY empty for a local proxy. The base model and LoRA pickers read ComfyUI's model lists from COMFYUI_URL (default http://127.0.0.1:8188); without it they become text fields.

Uploads are limited to 512 MB total per request, including reference pictures. Uploads are streamed to a temporary folder, and up to three can arrive at once per app process; a fourth is asked to retry shortly. After a job ends, its uploads are removed from comfy-api-proxy, but the files stay in ComfyUI's input/ folder. Generation continues in ComfyUI independently.

A 6 s clip at 480p takes about 6–13 minutes on a 4060 Ti, most of it in H3 sampling. 736p is the default; 1080p is about 2.5× slower than 736p and needs much more memory. Custom sets an exact width × height from 256 to 2048 px a side (rounded to 32); the video is scaled and centre-cropped to that shape first. It needs the short_edge input of the H3 Swap Plan nodes in comfyui-h3-oneclick-swap.

Advanced motion transfer has a Montage tab for edited clips where different people take turns within one shot without a hard cut (whip pans, selfie handovers, travel montages). Write roles as "who - looks" ("the dancer - white polo, jeans"): the looks help match the people, and only the part before " - " reaches H3. Generate tracks everyone with SAM over the whole video, matches each appearance to the roles with Qwen (a person SAM loses and finds again is matched again, so they keep their photo; Qwen sees each appearance in its frame and close up at three moments, a few appearances at a time, and is asked again about any it skips or matches to one photo twice at the same moment) and makes the video as one chain like Standard, with overlapping clips: each clip has one H3 pass per photo on screen in it (the two with the most screen time) that masks only that photo's appearances, with a prompt about that person only. Appearances on screen for under 12 frames or at under 2% of the frame stay as they are, since H3 draws them as grey figures; the result page lists them. Find people (about 3 minutes for 18 s of video) is the optional review: it does the tracking and matching alone, lists the appearances with a photo picker each and saves the tracks, and Generate from that list masks with exactly those tracks. The saved tracks live in ComfyUI's temp folder and are checked against the video, part and size, so after a ComfyUI restart or a change, Find people again. It needs the pack's H3TrackCrops and H3TrackRoles (which now runs Qwen itself), H3MontagePeople, H3MontageTracks, H3MontagePicks, H3MontagePlan and H3MontagePass nodes.

Tips

How it works

Each clip, SAM 3.1 tracks everyone at 1008 px (its own working size), and H3 People Mask keeps the largest person. The edit mask adds 10% headroom above the head, holds each pose for 2 frames and grows by 40 px, so a differently built character has room; it does not affect the motion. The motion reference H3 follows is the source clip with that person turned into a sharp grey mannequin of their exact silhouette, so the pose, arms and fingers stay readable.

workflows/simple.api.json is one API export of that workflow with the hat fix and No lip-sync enabled. For each request, lib/simple.ts:

lib/model.ts then sets the Swap Plan's steps and the H3 Diffusion Model file, and replaces the DMAD LoRA node with the chosen LoRAs in a chain (or links the model straight through when there are none). Advanced mode does the same.

lib/comfy.ts binds the uploaded video to VHS_LoadVideo and the photo to the LoadImage node, then submits with the SDK. /api/jobs/[id]/events reads the job's raw event stream (the SDK's low-level getJobEvents) and forwards it to the page as server-sent events. Node ids are turned into node titles and clip numbers there: each clip after the first is a graph expansion of the loop, whose node ids carry a prefix per clip (64, 66.0.0.64, 66.0.0.Recurse.0.0.64 for Save Clip in clips 1–3). The final MP4 is the output of the Final Video node (MiniMaxH3ChainAssemble, node 67).

workflows/mask.api.json is the mask check: the same SAM, People Mask and grow settings over the whole video, with the mask tinted over the frames next to the mannequin, saved as an MP4.

Advanced mode labels the people before it masks them. Per clip, H3 Track Crops shows each SAM track once per shot (the person alone, and the frame with them boxed) to Qwen3-VL 8B, which names the subject or "other"; H3 Track Roles reads that answer and settles a subject named twice in one shot by colour. H3 Role Mask builds the edit mask from the labelled tracks only, and the shot-list describer sees each labelled person outlined in their subject's colour, so the prompt names the same people the masks do. lib/advanced.ts finds nodes by title, drops unused picture branches and, without the hat fix or No lip-sync, their nodes; the exports are made from workflows/build/oneclick_advanced_build.js with every optional group on.

Object swap uses the same masked edit for the tracked things; SAM 3 tracks each comma-separated thing as its own prompt. The H3 Object Swap Plan writes a MiniMax video-editing prompt ([video editing + reference generation + audio reuse]), and the shot-list describer is told not to mention the thing being changed. Change: the tracked area is regenerated, and the motion reference shows it as a grey shape that keeps its shape and movement but not its colours. Background: the grown person mask is inverted (flip_input), so the edit reaches a little into the person's edge, and the whole background turns into a grey blur that keeps the camera movement. Remove: there is no motion reference (a grey shape would come back as a grey object), and the prompt describes what fills the area without naming what was there. lib/object.ts makes these changes by node title.

Fix faces works on the face, not the frame. H3 Face Track + Crop follows the face of the person in the photo over the whole video (InsightFace picks them out whe

GitHub Stars & Activity

229Stars
41Forks
38Open issues
TypeScriptLanguage

GitHub Popularity

GitHub stars229
Forks41
Open issues38
Primary languageTypeScript
LicenseMIT
Stars gained today0
Created2026-10-26
Last pushed2026-10-28

Trending History

Daily boardrank #31 · ▲ 0 stars

Related GitHub Projects

1

andyhuo520 / digital-human-koubo

TypeScript★ 1,400⑂ 323
→
2

kargulstudio / calender-app-design

TypeScript★ 795⑂ 96
→
3

yaojingang / GEOInflow

TypeScript★ 707⑂ 227
→
4

blakeandersonw / ai-app-playbook

TypeScript★ 571⑂ 77
→
5
→
6

shipwords-dev / shipwords

TypeScript★ 237⑂ 152
→
7

rudderlabs / devbox

TypeScript★ 160⑂ 9
→
8

athcagithub / postiz-leaked

TypeScript★ 157⑂ 384
→

More Trending Repositories