Remote Text Encode Qwen Image 2.1 ⚡
Text, Sixteen Reference Images, and a Latent — Encoded on Your Mac Instead
- vae
- image_1
- image_2
- image_3
- image_4
- image_5
- image_6
- image_7
- image_8
- image_9
- image_10
- image_11
- image_12
- image_13
- image_14
- image_15
- image_16
- positive
- negative
- latent
What you're actually getting
Qwen-Image's conditioning stack is a vision-language model, not a text encoder in the CLIP sense - the family has always encoded the reference image twice, once into the VLM for semantic understanding and once into the VAE for appearance. For Qwen-Image 2.1 that VLM is an 8B-class Qwen3-VL, and 8B-class encoders are exactly the thing that doesn't fit next to a diffusion transformer on an 8GB card.
Remote Text Encode Qwen Image 2.1 ⚡ moves that whole side of the graph to a Mac on your LAN. It's not a text encoder with a network cable - it's the multimodal version: you hand it a positive prompt, a negative, and up to sixteen reference images, and it returns both conditionings plus the empty latent canvas the sampler needs. Three things out of one node. The pack's own pitch is that the conditioning stage stops competing with the DiT for VRAM, and for Qwen-Image 2.1 that's a real argument.
The mechanism, briefly
Each reference image gets resized so its area is roughly resolution × resolution, rounded to multiples of 32, aspect preserved; resolution = 0 keeps each image at its own size. Alpha is composited over white (rgb * a + (1 - a)) before it leaves your machine. Prompts and images go to the Mac as a safetensors payload - pure numbers plus JSON metadata, no pickle, nothing executable.
The Mac then does what native ComfyUI does: wraps your prompt in the Qwen chat template with <image1>… slots, runs the backbone, drops the system turn before the second <|im_start|>, and slices the hidden states. If you passed a vae, it also drops the vision tokens and reports their positions back as image slots; the node attaches those, plus any attention mask, to the conditioning. Everything comes back bf16.
Two details that will surprise you if nobody says them:
The latent output is a canvas of zeros. Shape [1, 64, H//16, W//16], sized from your first reference image (or from resolution, falling back to 1024 when there's no image and resolution is 0). It is not an encoded picture - it's the blank frame you sample into. It's 64-channel, i.e. Wan-VAE space, which is why the vae input expects a WanVAE.
Only the first frame of each input batch is used. Every image_N is read as image[:1]. Sixteen slots does not mean sixteen images from one batch node - you wire sixteen separate images, or slice a batch upstream.
The fields that matter
model_name is a single-entry dropdown, Qwen-Image-2.1-Text-Encoder-Heretic, and it must match the folder name under MODELS_DIR on the Mac. prompt and negative_prompt are both multiline and both required widgets - leave the negative empty rather than hunting for a way to skip it. resolution is the one beginners trip on, because it sets both the reference resize target and the output canvas size.
Optional: vae (a WanVAE - wire it when you want appearance-faithful references rather than vision-token references), and image_1 through image_16.
Outputs: positive and negative into your guider/sampler, latent into whatever sampler takes a LATENT. The conditionings carry image_slots, attention_mask and reference_latents as needed - you don't have to wire those.
Installing it
Same pack, so the same first two steps - ComfyUI Manager and search "ComfyUI-MacOffload-TE", or:
cd ComfyUI/custom_nodes
git clone https://github.com/j0eyhu/ComfyUI-MacOffload-TE
Then create macoffload_config.json in the pack folder (copy macoffload_config.example.json) pointing at your Mac:
{ "server_url": "http://192.168.1.42:8288" }
The Mac is the heavy half: server/ needs a venv, pip install -r requirements.txt (pinned torch/transformers stack), a .env with MODELS_DIR and BRIDGE_PORT=8288, the pottokao/Qwen-Image-2.1-Text-Encoder-Heretic folder inside that directory, then python server.py. Restart ComfyUI afterwards and the node appears under ⚡ MacOffload/Conditioning.
Where people get burned
"Malformed safetensors response - missing positive/negative embeddings." The server loaded the wrong encoder class for that folder. Its type detection sniffs config.json and falls back on folder names containing "image" or "heretic", so keep the model folder named as published and re-check the Mac's terminal output.
Connection failures. The error message is unusually helpful and it's worth reading: check the server process, check the IP, check the macOS firewall. curl http://<mac-ip>:8288/health from the PC settles it in five seconds.
Timeouts on the first encode. Model load happens inside the first request and the client gives it 300 seconds. Cold-start with a 512px throwaway render first.
WanVAE, not SD VAE. A 16-channel VAE won't produce the 64-channel reference latents this stack expects. Keep a Wan 2.1 VAE around regardless - it's the known swap for the over-smoothing complaint on 2026 models.
Squeezing both nodes onto one Mac. If you also run the Flux Klein encoder, MAX_MODELS=1 means every model switch evicts and reloads. Set MAX_MODELS=2.
Is it worth it
Be clear-eyed: young pack, no community footprint I could find, targeting a model new enough that the written coverage hasn't caught up. The upside is real though - the whole multimodal encode, sixteen images included, costs zero local VRAM, and you get conditioning plus canvas from one node instead of a six-node reference pipeline. If you have a Mac with headroom and a card that chokes on an 8B VLM, it's currently about the only way to run Qwen-Image 2.1 conditioning without quantizing your way into mush.
Inputs (21)
| Name | Type | Default | Description |
|---|---|---|---|
| model_name | COMBO | Qwen-Image-2.1-Text-Encoder-Heretic | Model folder name on remote Mac server. Click 'Fetch Models' to query models from server. |
| prompt | STRING | Positive prompt describing the desired image generation. | |
| negative_prompt | STRING | Negative prompt describing unwanted attributes. | |
| resolution | INT | 10240–4096 | Reference images are resized to about resolution x resolution pixels, at multiples of 32, preserving aspect ratio. 0 keeps each reference at its own size. |
| vaeopt | VAE | Optional WanVAE model used to encode reference images into reference latents. | |
| image_1opt | IMAGE | Optional reference image #1 for multimodal image-to-image conditioning. | |
| image_2opt | IMAGE | Optional reference image #2 for multimodal image-to-image conditioning. | |
| image_3opt | IMAGE | Optional reference image #3 for multimodal image-to-image conditioning. | |
| image_4opt | IMAGE | Optional reference image #4 for multimodal image-to-image conditioning. | |
| image_5opt | IMAGE | Optional reference image #5 for multimodal image-to-image conditioning. | |
| image_6opt | IMAGE | Optional reference image #6 for multimodal image-to-image conditioning. | |
| image_7opt | IMAGE | Optional reference image #7 for multimodal image-to-image conditioning. | |
| image_8opt | IMAGE | Optional reference image #8 for multimodal image-to-image conditioning. | |
| image_9opt | IMAGE | Optional reference image #9 for multimodal image-to-image conditioning. | |
| image_10opt | IMAGE | Optional reference image #10 for multimodal image-to-image conditioning. | |
| image_11opt | IMAGE | Optional reference image #11 for multimodal image-to-image conditioning. | |
| image_12opt | IMAGE | Optional reference image #12 for multimodal image-to-image conditioning. | |
| image_13opt | IMAGE | Optional reference image #13 for multimodal image-to-image conditioning. | |
| image_14opt | IMAGE | Optional reference image #14 for multimodal image-to-image conditioning. | |
| image_15opt | IMAGE | Optional reference image #15 for multimodal image-to-image conditioning. | |
| image_16opt | IMAGE | Optional reference image #16 for multimodal image-to-image conditioning. |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| positive | CONDITIONING | — |
| negative | CONDITIONING | — |
| latent | LATENT | — |