# Wan Video over Tailscale on a 16 GB NVIDIA Laptop GPU

Use this reference when setting up or driving a remote ComfyUI host for local/free video generation from Hermes/JARVIS.

## Tested host shape

- GPU: NVIDIA RTX A5000 Laptop GPU, 16 GB VRAM
- Access: ComfyUI bound to the host's Tailscale IP, e.g. `python main.py --listen "$TS_IP" --port 8188 --lowvram`
- ComfyUI: 0.22.0
- PyTorch: CUDA build, tested with 2.12.0+cu126
- Wan stack: `kijai/ComfyUI-WanVideoWrapper`
- Model set for first viable local/free path:
  - `Wan2_1-T2V-1_3B_fp8_e4m3fn.safetensors` → `models/diffusion_models/`
  - `Wan2_1_VAE_bf16.safetensors` → `models/vae/`
  - `umt5-xxl-enc-fp8_e4m3fn.safetensors` → `models/text_encoders/`

## Hugging Face CLI update

`huggingface-cli download` may now print that it is deprecated and no longer works. Use `hf download` instead:

```bash
hf download Kijai/WanVideo_comfy \
  Wan2_1-T2V-1_3B_fp8_e4m3fn.safetensors \
  --local-dir ~/ai/ComfyUI/models/diffusion_models

hf download Kijai/WanVideo_comfy \
  Wan2_1_VAE_bf16.safetensors \
  --local-dir ~/ai/ComfyUI/models/vae

hf download Kijai/WanVideo_comfy \
  umt5-xxl-enc-fp8_e4m3fn.safetensors \
  --local-dir ~/ai/ComfyUI/models/text_encoders
```

If gated/throttled, run `hf auth login` and retry.

## Stable launch pattern

For a 16 GB A5000 Laptop GPU, start ComfyUI conservatively:

```bash
cd ~/ai/ComfyUI
source .venv/bin/activate
TS_IP="$(tailscale ip -4 | head -n1)"
python main.py --listen "$TS_IP" --port 8188 --lowvram
```

Only expose the port on Tailscale. If using ufw:

```bash
sudo ufw allow in on tailscale0 to any port 8188 proto tcp
```

Health check from Hermes/another Tailscale node:

```bash
curl "http://$TS_IP:8188/system_stats"
```

## RAM/VRAM lessons

- VRAM was not the first bottleneck; system RAM was. A first attempt with ~5 GB free RAM crashed/terminated ComfyUI after the prompt was accepted.
- With ~17 GB available RAM and `--lowvram`, small Wan jobs completed successfully.
- Before first Wan run, ask the user to stop other model servers (`llama.cpp`, Ollama, vLLM, browsers/IDEs if needed) and verify:

```bash
free -h
nvidia-smi
ps aux --sort=-%mem | head -20
```

Aim for at least 12–16 GB available RAM before loading UMT5/Wan.

## API verification pattern

From Hermes, verify nodes and model visibility before trying a heavy generation:

```python
import json, urllib.request
base = "http://TAILSCALE_IP:8188"
stats = json.load(urllib.request.urlopen(base + "/system_stats", timeout=10))
info = json.load(urllib.request.urlopen(base + "/object_info", timeout=20))
for node in [
    "WanVideoModelLoader", "LoadWanVideoT5TextEncoder", "WanVideoTextEncode",
    "WanVideoSampler", "WanVideoVAELoader", "WanVideoDecode", "CreateVideo", "SaveVideo",
]:
    assert node in info, node
```

Useful loader settings discovered via `/object_info`:

- `WanVideoModelLoader`: model `Wan2_1-T2V-1_3B_fp8_e4m3fn.safetensors`, `base_precision=bf16`, `load_device=offload_device`
- `LoadWanVideoT5TextEncoder`: model `umt5-xxl-enc-fp8_e4m3fn.safetensors`, `precision=bf16`, `load_device=offload_device`
- `WanVideoTextEncode`: set `device=cpu`, `force_offload=true`, and pass `model_to_offload` for stability
- `WanVideoDecode`: enable VAE tiling for small GPU/RAM envelopes

## Smoke-test ladder

Start absurdly small to validate plumbing, then scale up.

1. Micro smoke: `128x224`, `9 frames`, `2 steps`, `8 fps`. Expect technical success, mostly artifacts.
2. Scene probe: `240x416`, `17 frames`, `4 steps`, `8 fps`. Expect abstract but plausible motion/vibe.
3. Next quality probe: `360x640`, `25 frames`, `6–8 steps`, `8 fps`.
4. If stable: `432x768`, `33 frames`, `8–12 steps`.

Do not start with 720p/10s/14B on 16 GB VRAM. Generate smaller clips, then upscale/composite/caption locally.

## Successful minimal API workflow shape

A successful API graph used these nodes:

1. `WanVideoModelLoader`
2. `LoadWanVideoT5TextEncoder`
3. `WanVideoTextEncode` with `device=cpu`
4. `WanVideoEmptyEmbeds`
5. `WanVideoSampler`
6. `WanVideoVAELoader`
7. `WanVideoDecode` with tiling
8. `CreateVideo`
9. `SaveVideo`

Polling pattern: POST `/prompt`, poll `/queue` until empty, then GET `/history/{prompt_id}` and download output with `/view?filename=...&type=output&subfolder=`.

## Quality expectation

Tiny 1.3B FP8 smoke clips are proof-of-pipeline, not production quality. They may show dark abstract motion and colored light traces rather than a crisp car. Treat them as plumbing validation; improve with resolution, frame count, steps, prompts, and possibly image-to-video seeds.