Extensions/ComfyUI-BruxosDoVFX-ProxyPose
ComfyUI Extension

ComfyUI-BruxosDoVFX-ProxyPose

Bruxos do VFX nodes that run the official ProxyPose pipeline for 6-DoF pose tracking via video-to-video translation within ComfyUI, with automatic timer display. (Description by CC)

By NyckM·Created about a month ago·Updated about a month ago· 0
NyckM/ComfyUI-BruxosDoVFX-ProxyPose
Nodes
On cloudLocal install
Stars0
Updatedabout a month ago
Readme

ComfyUI-BruxosDoVFX-ProxyPose

<img width="949" height="687" alt="image" src="https://github.com/user-attachments/assets/ae755e42-a05e-46a7-b9ed-535862373d32" />

Nodes do Bruxos do VFX que rodam o pipeline oficial do ProxyPose — rastreio de pose 6-DoF via tradução vídeo-para-vídeo (Wan2.1-T2V-14B + LoRA) — dentro do ComfyUI, com o selo/timer Bruxos aparecendo em cada node automaticamente.

TL;DR do ProxyPose: você marca um pixel de um objeto no primeiro frame; o modelo gera um vídeo-proxy onde um cubo colorido fica grudado no objeto e gira junto com ele; o tracking extrai a trajetória de pose 6-DoF (rotação + translação) frame a frame.


https://github.com/user-attachments/assets/0eb0fc20-2464-4564-8ec4-2056f27e2a0f

Por que é um wrapper e não um port nativo do Wan

O ProxyPose não usa o condicionamento padrão do Wan I2V. Ele reescreve o forward do DiT (concatenação por token, modulação de timestep por token, RoPE modificado) e roda um loop DDIM próprio com ruído parcial no primeiro frame. Esse comportamento vive no forward patcheado — não apenas nos pesos da LoRA. Por isso, aplicar só a LoRA no Wan nativo do ComfyUI não reproduz o resultado. O caminho pragmático, e o que estes nodes fazem, é reaproveitar o pipeline diffsynth do próprio repositório.

Um port 100% nativo (reimplementando aquele forward + um sampler custom contra o WanModel do ComfyUI) é possível, mas é bem mais trabalho e fica pra uma segunda fase.


Instalação

1. Clonar e instalar o ProxyPose (em qualquer pasta):

git clone https://github.com/ruihangzhang97/proxypose
cd proxypose
pip install -e .                # puxa diffsynth, decord, etc.

2. Instalar o PyTorch3D — depende da sua versão de CUDA/torch. Siga o README do ProxyPose. Instale no mesmo Python que o ComfyUI usa (venv/embedded), senão o import inference falha.

3. Instalar estes nodes:

cd ComfyUI/custom_nodes
git clone https://github.com/<seu-usuario>/ComfyUI-BruxosDoVFX-ProxyPose

Reinicie o ComfyUI. Na primeira execução o pipeline baixa sozinho ~30 GB (Wan2.1-T2V-14B base) + ~600 MB (LoRA) do HuggingFace.


Os nodes

Todos ficam na categoria Bruxos do VFX/ProxyPose.

ProxyPose Model Loader (Bruxos)

Carrega o Wan2.1 + LoRA via diffsynth.

| Campo | Tipo | O que é | |---|---|---| | repo_path | STRING | auto (padrão) usa o deps/proxypose empacotado. Ou informe o caminho do proxypose clonado | | gen_config | STRING | YAML de geração (relativo ao repo_path ou absoluto) | | device | combo | cuda / cpu | | precision | combo | fp8_e4m3 (padrão), fp8_e5m2 ou bf16. fp8 guarda os pesos do DiT em fp8 e computa em bf16 — corta ~metade da VRAM do DiT, com leve perda de qualidade e sem ganho de velocidade | | vram_limit_gb | FLOAT | Teto de VRAM pro offload por camada (0 = sem teto; ex.: 20 numa placa de 24 GB) | | lora_alpha | FLOAT | Intensidade da LoRA (padrão 1.0) | | offload_text_encoder | BOOLEAN | Mantém o T5 na CPU (usado 1× e descartado). Recomendado ligado |

Saídas: pipe (PROXYPOSE_PIPE), gen_config (PROXYPOSE_GENCFG).

VRAM: os 30 GB não ficam todos na GPU — o T5 (~11 GB) é usado uma vez pra codificar o prompt fixo e descartado. O que domina é o DiT de 14B (bf16 ≈ 28 GB de pesos). Em fp8_e4m3 isso cai pra ~14 GB, e o vram_limit_gb faz o offload por camada pro resto. O fp8 reduz a VRAM em uso, não o tamanho do download.

ProxyPose Point Prompt (Bruxos)

Define o pixel de consulta no primeiro frame, em resolução cheia.

| Campo | Tipo | O que é | |---|---|---| | u | INT | Coluna (x) do pixel alvo | | v | INT | Linha (y) do pixel alvo | | points_json | STRING | Opcional: *.points.json do proxypose-annotate (sobrescreve u/v) |

Saída: prompt (PROXYPOSE_PROMPT).

ProxyPose Sampler (Bruxos)

Pipeline completo: crop quadrado no ponto → render do cubo proxy → geração Wan → tracking PnP.

| Campo | Tipo | O que é | |---|---|---| | pipe | entrada | Do Model Loader | | gen_config | entrada | Do Model Loader | | images | IMAGE | Vídeo de entrada (batch de frames) — não pré-cortar | | prompt | entrada | Do Point Prompt | | repo_path | STRING | Mesmo caminho do repo | | track_config | STRING | YAML de tracking | | num_frames | INT | 49 casa com a janela temporal do Wan | | seed | INT | Semente | | device | combo | cuda / cpu | | depth_anything_npz | STRING | Opcional: *.da3.npz pra estimar a focal (vazio = FOV fixo 45°) |

Saídas: visualization (IMAGE, painel de 5 colunas: entrada / proxy / tracking / overlay / prompt) e poses_json (STRING com rvec/tvec por frame).


As ligações

┌──────────────────────────┐
│ ProxyPose Model Loader    │── pipe ───────────┐
│ (Bruxos)                  │── gen_config ──┐  │
└──────────────────────────┘                │  │
                                             ▼  ▼
┌──────────────────┐   images   ┌───────────────────────────┐  visualization  ┌──────────────────┐
│ Load Video       │───────────►│ ProxyPose Sampler (Bruxos) │────────────────►│ Save Video       │
│ (Bruxos)         │            │                            │                 │ (Bruxos)         │
└──────────────────┘            └───────────────────────────┘                 └──────────────────┘
                                             ▲              │
┌──────────────────────────┐   prompt        │              └── poses_json ──► (opcional: salvar/inspecionar)
│ ProxyPose Point Prompt    │─────────────────┘
│ (Bruxos)                  │
└──────────────────────────┘

Resumo das conexões:

  • Model Loader → Sampler: pipe e gen_config.
  • Point Prompt → Sampler: prompt.
  • Load Video → Sampler: images (saída images, slot 0, do Load Video).
  • Sampler → Save Video: visualizationimages.
  • poses_json é opcional; ligue num node que mostre/salve texto, ou deixe solto.

O repo_path precisa estar preenchido igual no Model Loader e no Sampler.


Workflow de exemplo

Em workflows/proxypose_bruxos_basico.json. Arraste pra dentro do ComfyUI. Depois:

  1. No Load Video, escolha/faça upload do seu clipe (ou use o baseball_swing.mp4 do repo ProxyPose).
  2. No Model Loader e no Sampler, aponte repo_path pro seu proxypose clonado.
  3. No Point Prompt, ajuste u/v pro pixel do objeto que você quer rastrear (no primeiro frame, resolução cheia).
  4. Rode. O timer Bruxos mostra o tempo de cada etapa (a geração Wan é a mais pesada).

O timer Bruxos

web/bruxos_node_timer.js carimba todo node automaticamente: roxo com ▶ correndo ao vivo enquanto processa, verde com o tempo final ao terminar, e um resumo ordenado (mais lento primeiro) no console. Liga/desliga na engrenagem de configurações (Bruxos: mostrar timer em cada node).

  • Node 1 (render clássico): selo no canto inferior direito do node.
  • Node 2.0: o tempo vai no título (⏱ 4.3s), correndo ao vivo.

Se você juntar estes nodes ao pacote ComfyUI-Bruxos-do-VFX (que já tem este mesmo JS), apague o web/bruxos_node_timer.js daqui — carregar a extensão duas vezes desenha o selo em dobro.


⚠️ Instalação segura — os 8 pilares intocáveis (Bruxos)

Estes nodes importam o diffsynth dentro do Python do ComfyUI. Ou seja, instalar o ProxyPose mexe no mesmo ambiente onde vivem sage, DVD, FaceFusion etc. Antes de qualquer pip install, 8 nomes são intocáveis:

torch (2.8.0+cu128) · CUDA 12.8 (vem dentro do torch) · torchvision · torchaudio · numpy (1.26.4) · scipy (1.13.1) · sageattention (2.2.0+cu128torch2.8.0) · onnxruntime-gpu (1.22.x, build CUDA 12).

O pyproject.toml do ProxyPose pede numpy, scipy, torchvision sem pin e ainda gradio (que os nodes nunca usam). Um pip install -e . cru pode puxar scipy novo → numpy 2.x → cascata. Por isso nunca rode o install cru.

Windows (ComfyUI-Easy-Install / portable) — o jeito fácil

duplo-clique em instalar-proxypose.bat (na raiz deste node). Ele:

  1. acha o python_embeded do ComfyUI sozinho;
  2. gera a trava dos pilares a partir do teu ambiente atual;
  3. clona o ProxyPose em deps\proxypose (aqui dentro do node);
  4. instala o pacote com --no-deps (pula o gradio) e as libs sob a trava;
  5. tenta o pytorch3d (ver aviso abaixo);
  6. confere os pilares no fim e te mostra o repo_path pra colar nos nodes.

Se qualquer passo tentar mexer num pilar, o .bat para sem forçar nada. No fim ele imprime o caminho pra colar em repo_path (nos dois nodes), algo como C:/Users/voce/.../ComfyUI-BruxosDoVFX-ProxyPose/deps/proxypose.

pytorch3d no Windows: não tem wheel oficial e compilar falha com MSVC novo + CUDA 12.9 (erro conhecido no código pulsar, vector_types.h: expected a ">"). O .bat resolve isso instalando uma wheel pré-compilada do índice MiroPsota (pytorch3d==0.7.9+pt2.8.0cu128, ou 0.7.8). Se precisar manual: python_embeded\python.exe -m pip install --extra-index-url https://miropsota.github.io/torch_packages_builder -c constraints-bruxos.txt pytorch3d==0.7.9+pt2.8.0cu128 (confira a versão exata em https://miropsota.github.io/torch_packages_builder/pytorch3d/).

Linux / manual

Use o kit em tools/:

# no MESMO Python/venv do ComfyUI:
python tools/check_pilares.py                 # snapshot ANTES
bash tools/instalar-proxypose-seguro.sh ~/proxypose
python tools/check_pilares.py --conferir      # tem que dar "OK — nenhum pilar se mexeu"

O script gera uma trava (constraints-bruxos.txt) a partir do teu ambiente atual, faz dry-run antes de cada passo e aborta se algum comando tentar mexer num pilar. Ele instala o proxypose com --no-deps (pula o gradio), as deps reais sob a trava, e o pytorch3d com --no-build-isolation (compila contra o teu torch 2.8, sem puxar outro).

O warning You need cu130 é armadilha — ignore pra sempre. O CUDA que importa é o que o torch cu128 traz.

Se o diffsynth exigir numpy 2.x → modo ISOLADO (subprocess)

Se o passo de dry-run acusar conflito contra a trava (diffsynth pedindo numpy≥2), então instalar in-process é incompatível com o numpy 1.26.4. Nesse caso não force: rode o ProxyPose num venv separado e faça os nodes chamarem o CLI dele por subprocess, passando os frames por uma pasta temporária. Assim o ambiente do ComfyUI fica intocado (não importa diffsynth nenhum). É a versão à prova de bala — peça a refatoração pra esse modo (é uma troca no proxypose_nodes.py, sem tocar no resto).


Notas / limitações

  • fp8 (VRAM): o padrão fp8_e4m3 guarda os pesos do DiT em fp8 e computa em bf16. Reduz a VRAM em uso (~metade do DiT), com leve perda de qualidade e sem ganhar velocidade. Só vale em cuda (fp8 na CPU cai pra bf16 automaticamente). Se a saída vier ruim/NaN com fp8 + LoRA, teste precision=bf16 com vram_limit_gb > 0 (offload por camada, sem perda de qualidade, só mais lento). O combo fp8 + forward patcheado do ProxyPose é o ponto que vale testar primeiro na sua máquina.
  • Geração fixa em 512×512; o Sampler recorta um quadrado ao redor do ponto e reescala. Alimente o vídeo em resolução cheia, sem pré-cortar.
  • num_frames=49 casa com a janela do Wan; mudanças grandes podem piorar a qualidade.
  • poses_json traz vetores rotação/translação do OpenCV por frame; converta pra matriz 4×4 com cv2.Rodrigues se precisar (ver convert_tracking_results no repo ProxyPose).
  • A saída visualization é o painel de 5 colunas do CLI. Se quiser só o vídeo-proxy ou só o overlay como saídas separadas, dá pra adicionar isso no Sampler — abra uma issue.

Créditos

  • ProxyPose — Ruihang Zhang, Felix Taubner, Pooja Ravi, Kiriakos N. Kutulakos, David B. Lindell (University of Toronto / Vector Institute). Paper · Repo
  • Nodes ComfyUI + selo/timer — Bruxos do VFX.

Licença

MIT (ver LICENSE). O ProxyPose e o Wan2.1 têm licenças próprias — respeite os termos de cada um.