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)
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_e4m3isso cai pra ~14 GB, e ovram_limit_gbfaz 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:
pipeegen_config. - Point Prompt → Sampler:
prompt. - Load Video → Sampler:
images(saídaimages, slot 0, do Load Video). - Sampler → Save Video:
visualization→images. poses_jsoné opcional; ligue num node que mostre/salve texto, ou deixe solto.
O
repo_pathprecisa estar preenchido igual no Model Loader e no Sampler.
Workflow de exemplo
Em workflows/proxypose_bruxos_basico.json.
Arraste pra dentro do ComfyUI. Depois:
- No Load Video, escolha/faça upload do seu clipe (ou use o
baseball_swing.mp4do repo ProxyPose). - No Model Loader e no Sampler, aponte
repo_pathpro seuproxyposeclonado. - No Point Prompt, ajuste
u/vpro pixel do objeto que você quer rastrear (no primeiro frame, resolução cheia). - 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 oweb/bruxos_node_timer.jsdaqui — 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
Dê duplo-clique em instalar-proxypose.bat (na raiz deste node). Ele:
- acha o
python_embededdo ComfyUI sozinho; - gera a trava dos pilares a partir do teu ambiente atual;
- clona o ProxyPose em
deps\proxypose(aqui dentro do node); - instala o pacote com
--no-deps(pula o gradio) e as libs sob a trava; - tenta o
pytorch3d(ver aviso abaixo); - confere os pilares no fim e te mostra o
repo_pathpra 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.batresolve 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_e4m3guarda 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 emcuda(fp8 na CPU cai pra bf16 automaticamente). Se a saída vier ruim/NaN com fp8 + LoRA, testeprecision=bf16comvram_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=49casa com a janela do Wan; mudanças grandes podem piorar a qualidade.poses_jsontraz vetores rotação/translação do OpenCV por frame; converta pra matriz 4×4 comcv2.Rodriguesse precisar (verconvert_tracking_resultsno 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.