adbrasi commited on
Commit
82e01b7
·
verified ·
1 Parent(s): 590c961

Update wanForProduction.sh

Browse files
Files changed (1) hide show
  1. wanForProduction.sh +406 -211
wanForProduction.sh CHANGED
@@ -1,10 +1,12 @@
1
  #!/usr/bin/env bash
2
  # setup_comfyui_combined.sh
3
- # Script combinado para instalação do ComfyUI com Wan 2.2
4
 
5
  set -euo pipefail
6
 
7
- # Cores
 
 
8
  RED='\033[0;31m'
9
  GREEN='\033[0;32m'
10
  YELLOW='\033[1;33m'
@@ -16,25 +18,31 @@ log_success() { echo -e "${GREEN}[✓]${NC} $1"; }
16
  log_warn() { echo -e "${YELLOW}[!]${NC} $1"; }
17
  log_error() { echo -e "${RED}[✗]${NC} $1"; }
18
 
 
 
 
19
  # Configuração
20
- COMFY_DIR="/root/comfy/ComfyUI"
 
21
  MODELS_DIR="$COMFY_DIR/models"
22
- COMFY_HOST="0.0.0.0"
23
- COMFY_PORT="8818"
24
- CIVITAI_TOKEN="4fcb2834969399006a736ee402b061e5"
25
-
26
- # Performance
27
- export MAX_JOBS=32
28
- export NVCC_APPEND_FLAGS="--threads 8"
 
29
  export UV_SYSTEM_PYTHON=1
30
  export PYTORCH_CUDA_ALLOC_CONF="expandable_segments:True"
31
  export HF_HUB_ENABLE_HF_TRANSFER=1
32
- export HF_TRANSFER_CONCURRENCY=16
33
- export EXT_PARALLEL=4
34
 
35
- # Lista de downloads - Formato: "URL|TIPO|NOME_OPCIONAL"
36
- DOWNLOAD_FILES=(
37
- # Wan 2.2 models
 
38
  "hf://Kijai/WanVideo_comfy/Wan22-Lightning/Wan2.2-Lightning_T2V-v1.1-A14B-4steps-lora_HIGH_fp16.safetensors|loras|Wan2.2-Lightning_T2V-v1.1-A14B-4steps-lora_HIGH_fp16.safetensors"
39
  "hf://Kijai/WanVideo_comfy/Wan22-Lightning/Wan2.2-Lightning_T2V-v1.1-A14B-4steps-lora_LOW_fp16.safetensors|loras|Wan2.2-Lightning_T2V-v1.1-A14B-4steps-lora_LOW_fp16.safetensors"
40
  "hf://Kijai/WanVideo_comfy_fp8_scaled/I2V/Wan2_2-I2V-A14B-HIGH_fp8_e5m2_scaled_KJ.safetensors|diffusion_models|Wan2_2-I2V-A14B-HIGH_fp8_e5m2_scaled_KJ.safetensors"
@@ -43,22 +51,15 @@ DOWNLOAD_FILES=(
43
  "hf://Kijai/WanVideo_comfy/Wan22-Lightning/Wan2.2-Lightning_I2V-A14B-4steps-lora_LOW_fp16.safetensors|loras|Wan2.2-Lightning_I2V-A14B-4steps-lora_LOW_fp16.safetensors"
44
  "hf://Kijai/WanVideo_comfy/Wan2_1_VAE_fp32.safetensors|vae|Wan2_1_VAE_fp32.safetensors"
45
  "hf://Kijai/WanVideo_comfy/umt5-xxl-enc-bf16.safetensors|text_encoders|umt5-xxl-enc-bf16.safetensors"
46
-
47
- # Wan 2.1 models
48
  "hf://Kijai/WanVideo_comfy/Lightx2v/lightx2v_I2V_14B_480p_cfg_step_distill_rank256_bf16.safetensors|loras|lightx2v_I2V_14B_480p_cfg_step_distill_rank256_bf16.safetensors"
49
  "hf://Comfy-Org/Wan_2.2_ComfyUI_Repackaged/split_files/vae/wan_2.1_vae.safetensors|vae|wan_2.1_vae.safetensors"
50
  "hf://Comfy-Org/Wan_2.2_ComfyUI_Repackaged/split_files/text_encoders/umt5_xxl_fp16.safetensors|text_encoders|umt5_xxl_fp16.safetensors"
51
-
52
- # Wan 2.1 clip vision
53
  "hf://Kijai/WanVideo_comfy/open-clip-xlm-roberta-large-vit-huge-14_visual_fp32.safetensors|clip_vision|open-clip-xlm-roberta-large-vit-huge-14_visual_fp32.safetensors"
54
  "hf://Comfy-Org/Wan_2.1_ComfyUI_repackaged/split_files/clip_vision/clip_vision_h.safetensors|clip_vision|clip_vision_h.safetensors"
55
-
56
- # Upscaler extra
57
  "https://huggingface.co/ABDALLALSWAITI/Upscalers/resolve/main/anime/2x-AnimeSharpV2_MoSR_Soft.pth|upscale_models|2x-AnimeSharpV2_MoSR_Soft.pth"
58
  )
59
 
60
- # Mega downloads
61
- MEGA_LORAS=(
62
  "https://mega.nz/file/QFxREJpZ#0dge8TyRgb52lMFKdsk-Ac-rwcoG49hvBHvaqNsZkuk"
63
  "https://mega.nz/file/lIhQETjT#nKlQ01Euw6fUxo8P5bfwlQrxAkWEedXQQOqHv5u4yrM"
64
  "https://mega.nz/file/UIAESACY#Qlei1Pj5Nwno3Sz-wsTekvD-YgCkN1A5QbFKoRHXG9E"
@@ -72,13 +73,14 @@ MEGA_LORAS=(
72
  "https://mega.nz/file/hZhhhCQS#4je0Im2g1kEvTCuPotjVWkA-g6XICkqMb-mKxMt6R3Y"
73
  )
74
 
75
- MEGA_UPSCALE=(
76
  "https://mega.nz/file/qdQwAJSC#rPY2Hg4x-_RbHiHUBFW-YU8xZUqPpq5Gpl1uPFiJvW4"
77
  "https://mega.nz/file/KIh2marA#CehVNXxQhGfp1bqUL0K1YPWNqrCUoLPCZGq2W6XqmWo"
78
  )
79
 
80
- # Custom nodes do CODE2
81
- CUSTOM_NODES=(
 
82
  "https://github.com/kijai/ComfyUI-Florence2"
83
  "https://github.com/adbrasi/groqrouter"
84
  "https://github.com/kijai/ComfyUI-WanVideoWrapper"
@@ -105,259 +107,452 @@ CUSTOM_NODES=(
105
  "https://github.com/grmchn/ComfyUI-ProportionChanger"
106
  )
107
 
108
- # Download HuggingFace
109
- download_hf() {
110
- local url="$1"
111
- local target_dir="$2"
112
- local filename="$3"
113
-
114
- # Extrair repo e file_path da URL hf://
115
- url="${url#hf://}"
116
- local repo="$(echo "$url" | cut -d'/' -f1-2)"
117
- local file_path="$(echo "$url" | cut -d'/' -f3-)"
118
-
119
- if [ -n "$filename" ] && [ -f "$target_dir/$filename" ]; then
120
- log_success "Já existe: $filename"
121
- return 0
122
- fi
123
-
124
- log_info "Baixando HF: $filename"
125
-
126
- local temp_dir
127
- temp_dir="$(mktemp -d)"
128
-
129
- if command -v hf >/dev/null 2>&1; then
130
- HF_HUB_ENABLE_HF_TRANSFER=1 hf download "$repo" "$file_path" \
131
- --local-dir "$temp_dir" --local-dir-use-symlinks False 2>/dev/null || {
132
- rm -rf "$temp_dir"
133
- log_error "Falha ao baixar: $filename"
134
- return 1
135
- }
136
- elif command -v huggingface-cli >/dev/null 2>&1; then
137
- HF_HUB_ENABLE_HF_TRANSFER=1 huggingface-cli download "$repo" "$file_path" \
138
- --local-dir "$temp_dir" --local-dir-use-symlinks False 2>/dev/null || {
139
- rm -rf "$temp_dir"
140
- log_error "Falha ao baixar: $filename"
141
- return 1
142
- }
143
  else
144
- wget -q --show-progress -c -O "$target_dir/$filename" "https://huggingface.co/$url"
145
- rm -rf "$temp_dir"
146
- return $?
147
  fi
148
-
149
- # Mover arquivo baixado para destino
150
- local downloaded_file
151
- downloaded_file="$(find "$temp_dir" -type f \( -name "*.safetensors" -o -name "*.pth" -o -name "*.pt" -o -name "*.bin" \) | head -1)"
152
- if [ -n "$downloaded_file" ]; then
153
- mv "$downloaded_file" "$target_dir/$filename"
154
- rm -rf "$temp_dir"
155
- log_success "Download concluído: $filename"
156
- return 0
157
  else
158
- rm -rf "$temp_dir"
159
- log_error "Arquivo não encontrado após download: $filename"
160
- return 1
161
  fi
162
  }
163
 
164
- # Download Mega
165
- download_mega() {
 
 
 
 
166
  local url="$1"
167
- local target_dir="$2"
168
-
169
- log_info "Baixando do Mega..."
170
-
171
- cd "$target_dir"
172
- if megadl "$url" 2>/dev/null; then
173
- log_success "Mega download OK"
174
  else
175
- log_warn "Mega download falhou"
176
  fi
177
- cd - >/dev/null
178
  }
179
 
180
- # Download normal
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181
  download_file() {
182
  local url="$1"
183
  local target_dir="$2"
184
  local filename="$3"
185
-
186
- # Adicionar token Civitai se necessário
187
- if [[ "$url" == *"civitai.com"* ]] && [[ "$url" != *"token="* ]]; then
188
- url="${url}&token=${CIVITAI_TOKEN}"
 
 
 
189
  fi
190
-
191
- if [ -n "$filename" ] && [ -f "$target_dir/$filename" ]; then
192
- log_success " existe: $filename"
193
  return 0
194
  fi
195
-
196
- log_info "Baixando: ${filename:-arquivo}"
197
-
198
- # Tentar com aria2c primeiro
199
- if command -v aria2c >/dev/null 2>&1; then
200
- if [ -n "$filename" ]; then
201
- aria2c -c -x 16 -s 16 -k 1M --console-log-level=warn --dir="$target_dir" --out="$filename" "$url" || \
202
- wget -q --show-progress -c -O "$target_dir/$filename" "$url" || \
203
- log_error "Download falhou: $filename"
204
- else
205
- aria2c -c -x 16 -s 16 -k 1M --console-log-level=warn --dir="$target_dir" "$url" || \
206
- (cd "$target_dir" && wget -q --show-progress -c "$url") || \
207
- log_error "Download falhou: $url"
208
  fi
209
- elif [ -n "$filename" ]; then
210
- wget -q --show-progress -c -O "$target_dir/$filename" "$url" || \
211
- log_error "Download falhou: $filename"
212
- else
213
- (cd "$target_dir" && wget -q --show-progress -c "$url") || \
214
- log_error "Download falhou: $url"
215
  fi
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
216
  }
217
 
218
- # Processar downloads
219
  process_downloads() {
 
220
  for entry in "${DOWNLOAD_FILES[@]}"; do
221
- IFS='|' read -r url type filename <<< "$entry"
222
-
223
- # Criar diretório
 
 
224
  local target_dir="$MODELS_DIR/$type"
225
  mkdir -p "$target_dir"
226
-
227
- # Baixar arquivo
228
- if [[ "$url" == hf://* ]]; then
229
- download_hf "$url" "$target_dir" "$filename"
230
- else
231
- download_file "$url" "$target_dir" "$filename"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
232
  fi
233
  done
 
 
234
  }
235
 
236
- # Clone git repo
237
- clone_repo() {
238
  local url="$1"
239
  local dest="$2"
240
-
241
- if [ -d "$dest/.git" ]; then
242
- git -C "$dest" pull --ff-only 2>/dev/null || true
 
 
 
 
 
 
 
243
  else
244
- git clone --depth 1 "$url" "$dest" 2>/dev/null || true
 
 
 
 
245
  fi
246
-
247
- # Instalar requirements se existir
248
- if [ -f "$dest/requirements.txt" ]; then
249
- pip install -q -r "$dest/requirements.txt" 2>/dev/null || true
 
250
  fi
251
  }
252
 
253
- # ========== INSTALAÇÃO ==========
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
254
 
 
 
 
255
  log_info "========================================="
256
- log_info " ComfyUI + Wan 2.2 Setup"
257
  log_info "========================================="
258
 
259
- # 1. Instalar dependências
260
- log_info "[1/7] Instalando dependências..."
261
-
262
- apt-get update -qq
263
- apt-get install -y -qq aria2 megatools git wget curl 2>/dev/null
264
-
265
- pip install --upgrade pip wheel setuptools -q
266
- pip install --upgrade "huggingface_hub[cli,hf_transfer]>=0.26.0" comfy-cli -q
267
-
268
- log_success "Dependências instaladas"
269
-
270
- # 2. Instalar ComfyUI
271
- log_info "[2/7] Instalando ComfyUI..."
272
 
273
- if [ -f "$COMFY_DIR/main.py" ]; then
274
- log_warn "ComfyUI existe"
 
 
 
 
 
 
 
 
275
  else
276
- comfy --skip-prompt install --fast-deps --nvidia
277
  fi
278
 
279
- log_success "ComfyUI instalado"
280
-
281
- # 3. Instalar PyTorch com CUDA 12.8
282
- log_info "[3/7] Instalando PyTorch com CUDA 12.8..."
283
- pip install --upgrade torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu128
284
  log_success "PyTorch com CUDA 12.8 instalado"
285
 
286
- # 4. Instalar SageAttention
287
- log_info "[4/7] Instalando SageAttention..."
288
- if python3 -c "import torch; print(torch.cuda.is_available())" 2>/dev/null | grep -q True; then
289
- pip install "https://huggingface.co/adbrasi/comfywheel/resolve/main/sageattention-2.2.0-cp311-cp311-linux_x86_64.whl" -q || log_warn "Falha ao instalar SageAttention"
290
- python3 -c "import sageattention" >/dev/null 2>&1 || log_warn "SageAttention não pôde ser importado"
291
- log_success "SageAttention instalado"
292
  else
293
- log_warn "CUDA não detectado, pulando SageAttention"
 
 
 
 
294
  fi
 
295
 
296
- # 5. Baixar modelos
297
- log_info "[5/7] Baixando modelos..."
298
 
299
- # Criar diretórios
300
  mkdir -p "$MODELS_DIR"/{diffusion_models,loras,vae,vae_approx,text_encoders,clip_vision,controlnet,upscale_models,checkpoints}
 
 
 
 
 
301
 
302
- # Processar downloads principais
303
- process_downloads
304
-
305
- # Baixar Mega LoRAs
306
- LORA_DIR="$MODELS_DIR/loras"
307
- for mega_url in "${MEGA_LORAS[@]}"; do
308
- download_mega "$mega_url" "$LORA_DIR"
309
- done
310
-
311
- # Baixar Mega Upscale
312
- UPSCALE_DIR="$MODELS_DIR/upscale_models"
313
- for mega_url in "${MEGA_UPSCALE[@]}"; do
314
- download_mega "$mega_url" "$UPSCALE_DIR"
315
- done
316
-
317
- log_success "Downloads processados"
318
 
319
- # 6. Instalar custom nodes
320
- log_info "[6/7] Instalando custom nodes..."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
321
 
 
322
  CN_DIR="$COMFY_DIR/custom_nodes"
323
  mkdir -p "$CN_DIR"
324
-
325
  total_nodes=${#CUSTOM_NODES[@]}
326
  current_node=0
327
-
328
  for repo in "${CUSTOM_NODES[@]}"; do
329
  ((current_node++))
330
- node_name=$(basename "$repo")
331
- log_info "[$current_node/$total_nodes] Instalando: $node_name"
332
- clone_repo "$repo" "$CN_DIR/$node_name"
333
  done
334
-
335
  log_success "Custom nodes instalados"
336
 
337
- # 7. Verificação final
338
- log_info "[7/7] Verificando instalação..."
339
-
340
- echo ""
341
- log_info "Modelos disponíveis:"
342
- for dir in diffusion_models loras vae vae_approx text_encoders clip_vision controlnet upscale_models checkpoints; do
343
- if [ -d "$MODELS_DIR/$dir" ]; then
344
- local count
345
- count=$(find "$MODELS_DIR/$dir" -type f \( -name "*.safetensors" -o -name "*.pth" -o -name "*.pt" -o -name "*.bin" \) 2>/dev/null | wc -l)
346
- if [ "$count" -gt 0 ]; then
347
- log_success " $dir: $count arquivo(s)"
 
 
 
 
 
348
  fi
349
- fi
350
- done
 
351
 
352
- # Verificar e iniciar com SageAttention se disponível
353
- log_info "========================================="
354
- log_success "Instalação concluída!"
355
- log_info "Iniciando ComfyUI..."
356
- log_info "URL: http://localhost:$COMFY_PORT"
357
  log_info "========================================="
 
 
 
 
 
 
358
 
359
  SAGE_FLAG=""
360
- python3 -c "import sageattention" >/dev/null 2>&1 && SAGE_FLAG="--use-sage-attention" || true
 
 
 
 
361
 
362
  cd "$COMFY_DIR"
363
- exec comfy launch -- ${SAGE_FLAG:+$SAGE_FLAG} --listen "$COMFY_HOST" --port "$COMFY_PORT"
 
 
1
  #!/usr/bin/env bash
2
  # setup_comfyui_combined.sh
3
+ # Script baseado no CODE1 com melhorias e modelos/nodes do CODE2
4
 
5
  set -euo pipefail
6
 
7
+ # -----------------------------
8
+ # Cores para output
9
+ # -----------------------------
10
  RED='\033[0;31m'
11
  GREEN='\033[0;32m'
12
  YELLOW='\033[1;33m'
 
18
  log_warn() { echo -e "${YELLOW}[!]${NC} $1"; }
19
  log_error() { echo -e "${RED}[✗]${NC} $1"; }
20
 
21
+ command_exists() { command -v "$1" >/dev/null 2>&1; }
22
+
23
+ # -----------------------------
24
  # Configuração
25
+ # -----------------------------
26
+ COMFY_DIR="${COMFY_DIR:-/root/comfy/ComfyUI}"
27
  MODELS_DIR="$COMFY_DIR/models"
28
+ COMFY_HOST="${COMFY_HOST:-0.0.0.0}"
29
+ COMFY_PORT="${COMFY_PORT:-8818}"
30
+ CIVITAI_TOKEN="${CIVITAI_TOKEN:-4fcb2834969399006a736ee402b061e5}"
31
+ HF_TOKEN="${HF_TOKEN:-}"
32
+
33
+ # Configurações de performance
34
+ export MAX_JOBS=${MAX_JOBS:-32}
35
+ export NVCC_APPEND_FLAGS="${NVCC_APPEND_FLAGS:---threads 8}"
36
  export UV_SYSTEM_PYTHON=1
37
  export PYTORCH_CUDA_ALLOC_CONF="expandable_segments:True"
38
  export HF_HUB_ENABLE_HF_TRANSFER=1
39
+ export HF_TRANSFER_CONCURRENCY=${HF_TRANSFER_CONCURRENCY:-16}
40
+ export EXT_PARALLEL=${EXT_PARALLEL:-4}
41
 
42
+ # -----------------------------
43
+ # Listas de downloads (modelos do CODE2)
44
+ # -----------------------------
45
+ readonly DOWNLOAD_FILES=(
46
  "hf://Kijai/WanVideo_comfy/Wan22-Lightning/Wan2.2-Lightning_T2V-v1.1-A14B-4steps-lora_HIGH_fp16.safetensors|loras|Wan2.2-Lightning_T2V-v1.1-A14B-4steps-lora_HIGH_fp16.safetensors"
47
  "hf://Kijai/WanVideo_comfy/Wan22-Lightning/Wan2.2-Lightning_T2V-v1.1-A14B-4steps-lora_LOW_fp16.safetensors|loras|Wan2.2-Lightning_T2V-v1.1-A14B-4steps-lora_LOW_fp16.safetensors"
48
  "hf://Kijai/WanVideo_comfy_fp8_scaled/I2V/Wan2_2-I2V-A14B-HIGH_fp8_e5m2_scaled_KJ.safetensors|diffusion_models|Wan2_2-I2V-A14B-HIGH_fp8_e5m2_scaled_KJ.safetensors"
 
51
  "hf://Kijai/WanVideo_comfy/Wan22-Lightning/Wan2.2-Lightning_I2V-A14B-4steps-lora_LOW_fp16.safetensors|loras|Wan2.2-Lightning_I2V-A14B-4steps-lora_LOW_fp16.safetensors"
52
  "hf://Kijai/WanVideo_comfy/Wan2_1_VAE_fp32.safetensors|vae|Wan2_1_VAE_fp32.safetensors"
53
  "hf://Kijai/WanVideo_comfy/umt5-xxl-enc-bf16.safetensors|text_encoders|umt5-xxl-enc-bf16.safetensors"
 
 
54
  "hf://Kijai/WanVideo_comfy/Lightx2v/lightx2v_I2V_14B_480p_cfg_step_distill_rank256_bf16.safetensors|loras|lightx2v_I2V_14B_480p_cfg_step_distill_rank256_bf16.safetensors"
55
  "hf://Comfy-Org/Wan_2.2_ComfyUI_Repackaged/split_files/vae/wan_2.1_vae.safetensors|vae|wan_2.1_vae.safetensors"
56
  "hf://Comfy-Org/Wan_2.2_ComfyUI_Repackaged/split_files/text_encoders/umt5_xxl_fp16.safetensors|text_encoders|umt5_xxl_fp16.safetensors"
 
 
57
  "hf://Kijai/WanVideo_comfy/open-clip-xlm-roberta-large-vit-huge-14_visual_fp32.safetensors|clip_vision|open-clip-xlm-roberta-large-vit-huge-14_visual_fp32.safetensors"
58
  "hf://Comfy-Org/Wan_2.1_ComfyUI_repackaged/split_files/clip_vision/clip_vision_h.safetensors|clip_vision|clip_vision_h.safetensors"
 
 
59
  "https://huggingface.co/ABDALLALSWAITI/Upscalers/resolve/main/anime/2x-AnimeSharpV2_MoSR_Soft.pth|upscale_models|2x-AnimeSharpV2_MoSR_Soft.pth"
60
  )
61
 
62
+ readonly MEGA_LORAS=(
 
63
  "https://mega.nz/file/QFxREJpZ#0dge8TyRgb52lMFKdsk-Ac-rwcoG49hvBHvaqNsZkuk"
64
  "https://mega.nz/file/lIhQETjT#nKlQ01Euw6fUxo8P5bfwlQrxAkWEedXQQOqHv5u4yrM"
65
  "https://mega.nz/file/UIAESACY#Qlei1Pj5Nwno3Sz-wsTekvD-YgCkN1A5QbFKoRHXG9E"
 
73
  "https://mega.nz/file/hZhhhCQS#4je0Im2g1kEvTCuPotjVWkA-g6XICkqMb-mKxMt6R3Y"
74
  )
75
 
76
+ readonly MEGA_UPSCALE=(
77
  "https://mega.nz/file/qdQwAJSC#rPY2Hg4x-_RbHiHUBFW-YU8xZUqPpq5Gpl1uPFiJvW4"
78
  "https://mega.nz/file/KIh2marA#CehVNXxQhGfp1bqUL0K1YPWNqrCUoLPCZGq2W6XqmWo"
79
  )
80
 
81
+ readonly RIFE_MODELS=()
82
+
83
+ readonly CUSTOM_NODES=(
84
  "https://github.com/kijai/ComfyUI-Florence2"
85
  "https://github.com/adbrasi/groqrouter"
86
  "https://github.com/kijai/ComfyUI-WanVideoWrapper"
 
107
  "https://github.com/grmchn/ComfyUI-ProportionChanger"
108
  )
109
 
110
+ # -----------------------------
111
+ # Funções auxiliares
112
+ # -----------------------------
113
+ apt_update_safe() {
114
+ if command_exists apt-get; then
115
+ export DEBIAN_FRONTEND=noninteractive
116
+ apt-get update -y || log_warn "apt-get update falhou; seguindo mesmo assim."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
117
  else
118
+ log_warn "apt-get não disponível; pulando update."
 
 
119
  fi
120
+ }
121
+
122
+ apt_install_safe() {
123
+ if command_exists apt-get; then
124
+ export DEBIAN_FRONTEND=noninteractive
125
+ apt-get install -y "$@" || log_warn "Falha ao instalar pacote(s): $*"
 
 
 
126
  else
127
+ log_warn "apt-get não disponível; não foi possível instalar: $*"
 
 
128
  fi
129
  }
130
 
131
+ stat_bytes() {
132
+ local path="$1"
133
+ stat -c%s "$path" 2>/dev/null || echo 0
134
+ }
135
+
136
+ add_civitai_token() {
137
  local url="$1"
138
+ if [[ "$url" == *"civitai.com/api/download"* ]] && [[ "$url" != *"token="* ]] && [[ -n "$CIVITAI_TOKEN" ]]; then
139
+ if [[ "$url" == *"?"* ]]; then
140
+ printf '%s&token=%s' "$url" "$CIVITAI_TOKEN"
141
+ else
142
+ printf '%s?token=%s' "$url" "$CIVITAI_TOKEN"
143
+ fi
 
144
  else
145
+ printf '%s' "$url"
146
  fi
 
147
  }
148
 
149
+ download_hf() {
150
+ local repo="$1"
151
+ local file_path="$2"
152
+ local target_dir="$3"
153
+ local filename="$4"
154
+
155
+ if [[ -z "$filename" ]]; then
156
+ filename="$(basename "$file_path")"
157
+ fi
158
+
159
+ local target_file="$target_dir/$filename"
160
+ if [[ -f "$target_file" ]] && (( $(stat_bytes "$target_file") > 1000000 )); then
161
+ log_success "Arquivo já existe: $filename"
162
+ return 0
163
+ fi
164
+
165
+ log_info "Baixando de HF: $filename"
166
+ local temp_dir
167
+ temp_dir="$(mktemp -d)"
168
+ local success=false
169
+
170
+ if command_exists hf; then
171
+ if HF_HUB_ENABLE_HF_TRANSFER=1 hf download "$repo" "$file_path" --local-dir "$temp_dir" --local-dir-use-symlinks False; then
172
+ success=true
173
+ else
174
+ log_warn "hf download falhou; tentando fallback."
175
+ fi
176
+ fi
177
+
178
+ if [[ "$success" == false ]] && command_exists huggingface-cli; then
179
+ if HF_HUB_ENABLE_HF_TRANSFER=1 huggingface-cli download "$repo" "$file_path" --local-dir "$temp_dir" --local-dir-use-symlinks False; then
180
+ success=true
181
+ else
182
+ log_warn "huggingface-cli falhou; tentando download direto."
183
+ fi
184
+ fi
185
+
186
+ if [[ "$success" == false ]]; then
187
+ local direct_url="https://huggingface.co/${repo}/resolve/main/${file_path}"
188
+ local header=""
189
+ if [[ -n "$HF_TOKEN" ]]; then
190
+ header="Authorization: Bearer ${HF_TOKEN}"
191
+ fi
192
+ if command_exists aria2c; then
193
+ local aria_cmd=(aria2c -c -s 16 -x 16 -k 1M --console-log-level=warn --summary-interval=10)
194
+ if [[ -n "$header" ]]; then
195
+ aria_cmd+=(--header="$header")
196
+ fi
197
+ aria_cmd+=(--dir="$temp_dir" --out="$filename" "$direct_url")
198
+ if "${aria_cmd[@]}"; then
199
+ success=true
200
+ else
201
+ log_warn "aria2c direto falhou; tentando curl/wget."
202
+ fi
203
+ fi
204
+ if [[ "$success" == false ]] && command_exists curl; then
205
+ local curl_cmd=(curl -L -# -o "$temp_dir/$filename")
206
+ if [[ -n "$header" ]]; then
207
+ curl_cmd+=(-H "$header")
208
+ fi
209
+ curl_cmd+=("$direct_url")
210
+ if "${curl_cmd[@]}"; then
211
+ success=true
212
+ fi
213
+ fi
214
+ if [[ "$success" == false ]] && command_exists wget; then
215
+ local wget_cmd=(wget -q --show-progress -c -O "$temp_dir/$filename")
216
+ if [[ -n "$header" ]]; then
217
+ wget_cmd+=(--header="$header")
218
+ fi
219
+ wget_cmd+=("$direct_url")
220
+ if "${wget_cmd[@]}"; then
221
+ success=true
222
+ fi
223
+ fi
224
+ fi
225
+
226
+ if [[ "$success" == true ]]; then
227
+ local downloaded_file
228
+ downloaded_file="$(find "$temp_dir" -maxdepth 1 -type f | head -n 1)"
229
+ if [[ -n "$downloaded_file" ]]; then
230
+ mkdir -p "$target_dir"
231
+ mv "$downloaded_file" "$target_file"
232
+ rm -rf "$temp_dir"
233
+ log_success "Download concluído: $filename"
234
+ return 0
235
+ fi
236
+ fi
237
+
238
+ rm -rf "$temp_dir"
239
+ log_error "Falha ao baixar: $filename"
240
+ return 1
241
+ }
242
+
243
  download_file() {
244
  local url="$1"
245
  local target_dir="$2"
246
  local filename="$3"
247
+
248
+ url="$(add_civitai_token "$url")"
249
+ mkdir -p "$target_dir"
250
+
251
+ local final_name="$filename"
252
+ if [[ -z "$final_name" ]]; then
253
+ final_name="$(basename "${url%%\?*}")"
254
  fi
255
+
256
+ if [[ -f "$target_dir/$final_name" ]] && (( $(stat_bytes "$target_dir/$final_name") > 500000 )); then
257
+ log_success "Arquivo existe: $final_name"
258
  return 0
259
  fi
260
+
261
+ log_info "Baixando: $final_name"
262
+
263
+ if command_exists aria2c; then
264
+ local aria_opts=(-c -s 16 -x 16 -k 1M --console-log-level=warn --summary-interval=10)
265
+ if aria2c "${aria_opts[@]}" --dir="$target_dir" --out="$final_name" "$url"; then
266
+ return 0
 
 
 
 
 
 
267
  fi
268
+ log_warn "aria2c falhou; tentando wget/curl."
 
 
 
 
 
269
  fi
270
+
271
+ if command_exists wget; then
272
+ if wget -q --show-progress -c -O "$target_dir/$final_name" "$url"; then
273
+ return 0
274
+ fi
275
+ log_warn "wget falhou; tentando curl."
276
+ fi
277
+
278
+ if command_exists curl; then
279
+ if curl -L -# -C - -o "$target_dir/$final_name" "$url"; then
280
+ return 0
281
+ fi
282
+ fi
283
+
284
+ log_error "Falha ao baixar: $url"
285
+ return 1
286
+ }
287
+
288
+ download_mega() {
289
+ local url="$1"
290
+ local target_dir="$2"
291
+
292
+ url="${url#mega://}"
293
+ mkdir -p "$target_dir"
294
+
295
+ if ! command_exists megadl; then
296
+ log_warn "megadl não encontrado; tentando instalar megatools."
297
+ apt_update_safe
298
+ apt_install_safe megatools
299
+ fi
300
+
301
+ if command_exists megadl; then
302
+ log_info "Baixando de Mega.nz: $url"
303
+ if (cd "$target_dir" && megadl "$url"); then
304
+ log_success "Download Mega.nz concluído"
305
+ return 0
306
+ fi
307
+ fi
308
+
309
+ log_error "Falha ao baixar de Mega.nz: $url"
310
+ return 1
311
  }
312
 
 
313
  process_downloads() {
314
+ local failed=0
315
  for entry in "${DOWNLOAD_FILES[@]}"; do
316
+ IFS='|' read -r raw_url type filename <<< "$entry"
317
+ raw_url="$(echo "$raw_url" | xargs)"
318
+ type="$(echo "$type" | xargs)"
319
+ filename="$(echo "$filename" | xargs)"
320
+
321
  local target_dir="$MODELS_DIR/$type"
322
  mkdir -p "$target_dir"
323
+
324
+ local attempt success=false
325
+ local label="$filename"
326
+ if [[ -z "$label" ]]; then
327
+ label="$(basename "${raw_url%%\?*}")"
328
+ fi
329
+ if [[ -z "$label" || "$label" == "." ]]; then
330
+ label="$raw_url"
331
+ fi
332
+ for attempt in 1 2 3; do
333
+ if [[ "$raw_url" == mega://* ]]; then
334
+ if download_mega "$raw_url" "$target_dir"; then
335
+ success=true
336
+ fi
337
+ elif [[ "$raw_url" == hf://* ]]; then
338
+ local trimmed="${raw_url#hf://}"
339
+ local repo="$(echo "$trimmed" | cut -d'/' -f1-2)"
340
+ local file_path="$(echo "$trimmed" | cut -d'/' -f3-)"
341
+ if download_hf "$repo" "$file_path" "$target_dir" "$filename"; then
342
+ success=true
343
+ fi
344
+ else
345
+ if download_file "$raw_url" "$target_dir" "$filename"; then
346
+ success=true
347
+ fi
348
+ fi
349
+
350
+ if [[ "$success" == true ]]; then
351
+ break
352
+ fi
353
+
354
+ log_warn "Tentativa $attempt falhou para $label; aguardando antes de tentar novamente."
355
+ sleep $((2 * attempt))
356
+ done
357
+
358
+ if [[ "$success" == false ]]; then
359
+ log_error "Falhou após múltiplas tentativas: $label"
360
+ ((failed++))
361
  fi
362
  done
363
+
364
+ return $failed
365
  }
366
 
367
+ clone_or_update() {
 
368
  local url="$1"
369
  local dest="$2"
370
+ local node_name
371
+ node_name="$(basename "$dest")"
372
+
373
+ mkdir -p "$(dirname "$dest")"
374
+
375
+ if [[ -d "$dest/.git" ]]; then
376
+ log_info "Atualizando $node_name..."
377
+ if ! timeout 120 git -C "$dest" pull --ff-only --rebase=false; then
378
+ log_warn "Timeout/erro ao atualizar $node_name"
379
+ fi
380
  else
381
+ log_info "Clonando $node_name..."
382
+ if ! timeout 120 git clone --recursive --depth 1 "$url" "$dest"; then
383
+ log_warn "Falha ao clonar $node_name"
384
+ return
385
+ fi
386
  fi
387
+
388
+ if [[ -f "$dest/requirements.txt" ]]; then
389
+ if ! timeout 180 python3 -m pip install --no-warn-script-location -q -r "$dest/requirements.txt"; then
390
+ log_warn "Falha ao instalar requirements para $node_name"
391
+ fi
392
  fi
393
  }
394
 
395
+ install_sageattention() {
396
+ log_info "[5/9] Instalando SageAttention..."
397
+ if python3 - <<'PY' 2>/dev/null | grep -q True; then
398
+ import torch
399
+ print(torch.cuda.is_available())
400
+ PY
401
+ if python3 -m pip install "https://huggingface.co/adbrasi/comfywheel/resolve/main/sageattention-2.2.0-cp311-cp311-linux_x86_64.whl" -q; then
402
+ if python3 - <<'PY' >/dev/null 2>&1; then
403
+ import sageattention
404
+ PY
405
+ log_success "SageAttention instalado"
406
+ else
407
+ log_warn "SageAttention instalado mas não pôde ser importado"
408
+ fi
409
+ else
410
+ log_warn "Falha ao instalar SageAttention"
411
+ fi
412
+ else
413
+ log_warn "CUDA não detectado; pulando SageAttention"
414
+ fi
415
+ }
416
 
417
+ # -----------------------------
418
+ # Instalação principal
419
+ # -----------------------------
420
  log_info "========================================="
421
+ log_info " ComfyUI + Wan 2.2 Setup (Merged)"
422
  log_info "========================================="
423
 
424
+ log_info "[1/9] Preparando dependências do sistema..."
425
+ if ! command_exists aria2c || ! command_exists megadl; then
426
+ apt_update_safe
427
+ command_exists aria2c || apt_install_safe aria2
428
+ command_exists megadl || apt_install_safe megatools
429
+ fi
430
+ for cmd in python3 git wget curl; do
431
+ if ! command_exists "$cmd"; then
432
+ log_error "Dependência faltando: $cmd"
433
+ exit 1
434
+ fi
435
+ done
436
+ log_success "Dependências de sistema OK"
437
 
438
+ log_info "[2/9] Atualizando pip e ferramentas Python..."
439
+ python3 -m pip install --upgrade pip wheel setuptools -q
440
+ python3 -m pip install --upgrade "huggingface_hub[cli,hf_transfer]>=0.26.0" comfy-cli -q
441
+ if [[ -n "$HF_TOKEN" ]] && command_exists huggingface-cli; then
442
+ huggingface-cli login --token "$HF_TOKEN" --add-to-git-credential || log_warn "Falha ao autenticar no HuggingFace"
443
+ fi
444
+ if command_exists hf; then
445
+ log_success "Ferramenta 'hf' disponível"
446
+ elif command_exists huggingface-cli; then
447
+ log_warn "Usando 'huggingface-cli' para downloads"
448
  else
449
+ log_warn "Sem CLI oficial do HuggingFace; tentaremos fallback HTTP"
450
  fi
451
 
452
+ log_info "[3/9] Instalando PyTorch CUDA 12.8..."
453
+ python3 -m pip install --upgrade torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu128
 
 
 
454
  log_success "PyTorch com CUDA 12.8 instalado"
455
 
456
+ log_info "[4/9] Instalando ComfyUI..."
457
+ if [[ -f "$COMFY_DIR/main.py" ]]; then
458
+ log_warn "ComfyUI existe; pulando instalação base"
 
 
 
459
  else
460
+ comfy --skip-prompt install --fast-deps --nvidia
461
+ if [[ ! -f "$COMFY_DIR/main.py" ]]; then
462
+ log_error "ComfyUI não foi instalado corretamente"
463
+ exit 1
464
+ fi
465
  fi
466
+ log_success "ComfyUI disponível em $COMFY_DIR"
467
 
468
+ install_sageattention
 
469
 
470
+ log_info "[6/9] Baixando modelos principais..."
471
  mkdir -p "$MODELS_DIR"/{diffusion_models,loras,vae,vae_approx,text_encoders,clip_vision,controlnet,upscale_models,checkpoints}
472
+ if process_downloads; then
473
+ log_success "Modelos baixados (ou já presentes)"
474
+ else
475
+ log_warn "Alguns modelos falharam. Consulte logs acima e tente novamente."
476
+ fi
477
 
478
+ log_info "[7/9] Baixando modelos RIFE (opcional)..."
479
+ if (( ${#RIFE_MODELS[@]} )); then
480
+ RIFE_DIR="$MODELS_DIR/tensorrt/rife"
481
+ mkdir -p "$RIFE_DIR"
482
+ for url in "${RIFE_MODELS[@]}"; do
483
+ fname="$(basename "${url%%\?*}")"
484
+ download_file "$url" "$RIFE_DIR" "$fname" || log_warn "Falha ao baixar RIFE: $fname"
485
+ done
486
+ log_success "Modelos RIFE processados"
487
+ else
488
+ log_warn "Lista RIFE vazia — pulando"
489
+ fi
 
 
 
 
490
 
491
+ log_info "[8/9] Baixando arquivos do Mega.nz..."
492
+ if (( ${#MEGA_LORAS[@]} )); then
493
+ LORA_DIR="$MODELS_DIR/loras"
494
+ mkdir -p "$LORA_DIR"
495
+ for url in "${MEGA_LORAS[@]}"; do
496
+ download_mega "$url" "$LORA_DIR" || log_warn "Mega.nz falhou: $url"
497
+ done
498
+ fi
499
+ if (( ${#MEGA_UPSCALE[@]} )); then
500
+ UPSCALE_DIR="$MODELS_DIR/upscale_models"
501
+ mkdir -p "$UPSCALE_DIR"
502
+ for url in "${MEGA_UPSCALE[@]}"; do
503
+ download_mega "$url" "$UPSCALE_DIR" || log_warn "Mega.nz falhou: $url"
504
+ done
505
+ fi
506
+ log_success "Downloads Mega.nz concluídos (quando disponíveis)"
507
 
508
+ log_info "[9/9] Instalando custom nodes..."
509
  CN_DIR="$COMFY_DIR/custom_nodes"
510
  mkdir -p "$CN_DIR"
 
511
  total_nodes=${#CUSTOM_NODES[@]}
512
  current_node=0
 
513
  for repo in "${CUSTOM_NODES[@]}"; do
514
  ((current_node++))
515
+ log_info "[$current_node/$total_nodes] Processando $(basename "$repo")"
516
+ clone_or_update "$repo" "$CN_DIR/$(basename "$repo")"
 
517
  done
 
518
  log_success "Custom nodes instalados"
519
 
520
+ check_critical_files() {
521
+ local files=(
522
+ "$COMFY_DIR/main.py"
523
+ "$MODELS_DIR/vae/wan_2.1_vae.safetensors"
524
+ "$MODELS_DIR/vae/Wan2_1_VAE_fp32.safetensors"
525
+ "$MODELS_DIR/text_encoders/umt5_xxl_fp16.safetensors"
526
+ "$MODELS_DIR/text_encoders/umt5-xxl-enc-bf16.safetensors"
527
+ "$MODELS_DIR/clip_vision/clip_vision_h.safetensors"
528
+ )
529
+ local missing=0
530
+ for file in "${files[@]}"; do
531
+ if [[ -f "$file" ]]; then
532
+ log_success "✓ $(basename "$file")"
533
+ else
534
+ log_warn "✗ $(basename "$file") não encontrado"
535
+ ((missing++))
536
  fi
537
+ done
538
+ return $missing
539
+ }
540
 
 
 
 
 
 
541
  log_info "========================================="
542
+ if check_critical_files; then
543
+ log_success "Instalação concluída com sucesso!"
544
+ else
545
+ log_warn "Alguns arquivos essenciais não foram encontrados. Veja avisos acima."
546
+ fi
547
+ log_info "Preparando para iniciar ComfyUI..."
548
 
549
  SAGE_FLAG=""
550
+ if python3 - <<'PY' >/dev/null 2>&1; then
551
+ import sageattention
552
+ PY
553
+ SAGE_FLAG="--use-sage-attention"
554
+ fi
555
 
556
  cd "$COMFY_DIR"
557
+ log_info "Iniciando ComfyUI em http://$COMFY_HOST:$COMFY_PORT"
558
+ exec comfy launch -- ${SAGE_FLAG:+$SAGE_FLAG} --listen "$COMFY_HOST" --port "$COMFY_PORT"