adbrasi commited on
Commit
17ec742
·
verified ·
1 Parent(s): 84ddefc

Upload wanForProduction2.sh

Browse files
Files changed (1) hide show
  1. wanForProduction2.sh +555 -0
wanForProduction2.sh ADDED
@@ -0,0 +1,555 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ # setup_comfyui_wan22.sh
3
+ # Script baseado no CODE1 com modelos/nodes do CODE2 e melhorias de robustez
4
+
5
+ set -euo pipefail
6
+
7
+ # Cores para output
8
+ RED='\033[0;31m'
9
+ GREEN='\033[0;32m'
10
+ YELLOW='\033[1;33m'
11
+ BLUE='\033[0;34m'
12
+ NC='\033[0m'
13
+
14
+ log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
15
+ 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="${COMFY_DIR:-/root/comfy/ComfyUI}"
21
+ MODELS_DIR="$COMFY_DIR/models"
22
+ COMFY_HOST="${COMFY_HOST:-0.0.0.0}"
23
+ COMFY_PORT="${COMFY_PORT:-8818}"
24
+ CIVITAI_TOKEN="${CIVITAI_TOKEN:-}"
25
+ HF_TOKEN="${HF_TOKEN:-}"
26
+ VENV_DIR="${VENV_DIR:-/root/comfy/.venv}"
27
+
28
+ # Suprimir avisos do pip quando executado como root
29
+ export PIP_ROOT_USER_ACTION=ignore
30
+
31
+ # Performance
32
+ export MAX_JOBS="${MAX_JOBS:-32}"
33
+ export HF_HUB_ENABLE_HF_TRANSFER=1
34
+ export HF_TRANSFER_CONCURRENCY="${HF_TRANSFER_CONCURRENCY:-16}"
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
+
39
+ PYTHON_BIN=""
40
+
41
+ # Lista de downloads (formato: URL|TIPO|NOME_OPCIONAL)
42
+ DOWNLOAD_FILES=(
43
+ "https://huggingface.co/Kijai/WanVideo_comfy_fp8_scaled/resolve/main/I2V/Wan2_2-I2V-A14B-LOW_fp8_e4m3fn_scaled_KJ.safetensors|diffusion_models|"
44
+ "https://huggingface.co/Kijai/WanVideo_comfy_fp8_scaled/resolve/main/I2V/Wan2_2-I2V-A14B-HIGH_fp8_e4m3fn_scaled_KJ.safetensors|diffusion_models|"
45
+ "https://huggingface.co/jrewingwannabe/Wan2.2-Lightning_I2V-A14B-4steps-lora/resolve/main/Wan2.2-Lightning_I2V-A14B-4steps-lora_HIGH_fp16.safetensors|loras|"
46
+ "https://huggingface.co/jrewingwannabe/Wan2.2-Lightning_I2V-A14B-4steps-lora/resolve/main/Wan2.2-Lightning_I2V-A14B-4steps-lora_LOW_fp16.safetensors|loras|"
47
+ "https://huggingface.co/Kijai/WanVideo_comfy/resolve/main/LoRAs/AniSora/Wan2_2_I2V_AniSora_3_2_HIGH_rank_64_fp16.safetensors|loras|"
48
+ "https://huggingface.co/Kijai/WanVideo_comfy/resolve/main/Wan2_1_VAE_bf16.safetensors|vae|"
49
+ "https://huggingface.co/Kijai/WanVideo_comfy/resolve/main/open-clip-xlm-roberta-large-vit-huge-14_visual_fp16.safetensors|clip_vision|"
50
+ "https://huggingface.co/Comfy-Org/Wan_2.1_ComfyUI_repackaged/resolve/main/split_files/text_encoders/umt5_xxl_fp8_e4m3fn_scaled.safetensors|text_encoders|"
51
+ "https://huggingface.co/ABDALLALSWAITI/Upscalers/resolve/main/general/Swin2SR_ClassicalSR_X2_64.pth|upscale_models|"
52
+ "https://huggingface.co/adbrasi/download_models/resolve/main/22-nsfw-HIGH-e6.safetensors|loras|"
53
+ "https://huggingface.co/adbrasi/download_models/resolve/main/NSFW-22-H-e8.safetensors|loras|"
54
+ "https://huggingface.co/adbrasi/download_models/resolve/main/NSFW-22-L-e8.safetensors|loras|"
55
+ "https://huggingface.co/adbrasi/download_models/resolve/main/smoothLoopv2_000002450_high_noise.safetensors|loras|"
56
+ "https://huggingface.co/adbrasi/download_models/resolve/main/smoothLoopv2_000002450_low_noise.safetensors|loras|"
57
+ "https://huggingface.co/adbrasi/download_models/resolve/main/ultimate_sex_000006500_high_noise.safetensors|loras|"
58
+ "https://huggingface.co/adbrasi/download_models/resolve/main/ultimate_sex_000006500_low_noise.safetensors|loras|"
59
+ )
60
+
61
+ # Custom nodes (do CODE2)
62
+ CUSTOM_NODES=(
63
+ "https://github.com/kijai/ComfyUI-Florence2"
64
+ "https://github.com/adbrasi/groqrouter"
65
+ "https://github.com/kijai/ComfyUI-WanVideoWrapper"
66
+ "https://github.com/Fannovel16/ComfyUI-Frame-Interpolation"
67
+ "https://github.com/kijai/ComfyUI-GIMM-VFI"
68
+ "https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite"
69
+ "https://github.com/kijai/ComfyUI-KJNodes"
70
+ "https://github.com/Artificial-Sweetener/comfyui-WhiteRabbit"
71
+ "https://github.com/shiimizu/ComfyUI_smZNodes"
72
+ "https://github.com/CoreyCorza/ComfyUI-CRZnodes"
73
+ "https://github.com/pythongosssss/ComfyUI-Custom-Scripts"
74
+ "https://github.com/pythongosssss/ComfyUI-WD14-Tagger"
75
+ "https://github.com/WASasquatch/was-node-suite-comfyui"
76
+ "https://github.com/justUmen/Bjornulf_custom_nodes"
77
+ "https://github.com/mingsky-ai/ComfyUI-MingNodes"
78
+ "https://github.com/adbrasi/upavidito"
79
+ "https://github.com/wallish77/wlsh_nodes"
80
+ "https://github.com/raindrop313/ComfyUI-WanVideoStartEndFrames"
81
+ "https://github.com/MushroomFleet/DJZ-Nodes"
82
+ "https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes"
83
+ "https://github.com/MoonGoblinDev/Civicomfy"
84
+ )
85
+
86
+ download_hf() {
87
+ local hf_path="$1"
88
+ local target_dir="$2"
89
+ local filename="$3"
90
+ local revision="${4:-}"
91
+
92
+ if [[ -z "$filename" ]]; then
93
+ filename="$(basename "${hf_path%%\?*}")"
94
+ fi
95
+
96
+ mkdir -p "$target_dir"
97
+ if [[ -f "$target_dir/$filename" ]]; then
98
+ local existing_size
99
+ existing_size=$(stat -c%s "$target_dir/$filename" 2>/dev/null || echo 0)
100
+ if [[ "$existing_size" -gt 1048576 ]]; then
101
+ log_success "Já existe: $filename"
102
+ return 0
103
+ fi
104
+ fi
105
+
106
+ local owner="${hf_path%%/*}"
107
+ local remainder="${hf_path#*/}"
108
+ if [[ "$owner" == "$hf_path" ]]; then
109
+ log_error "Caminho HuggingFace inválido: $hf_path"
110
+ return 1
111
+ fi
112
+
113
+ local repo_segment="${remainder%%/*}"
114
+ if [[ "$repo_segment" == "$remainder" ]]; then
115
+ log_error "Arquivo não especificado no caminho: $hf_path"
116
+ return 1
117
+ fi
118
+
119
+ remainder="${remainder#*/}"
120
+ if [[ -z "$remainder" ]]; then
121
+ log_error "Arquivo não especificado no caminho: $hf_path"
122
+ return 1
123
+ fi
124
+
125
+ if [[ "$repo_segment" == *@* ]]; then
126
+ if [[ -z "$revision" ]]; then
127
+ revision="${repo_segment#*@}"
128
+ fi
129
+ repo_segment="${repo_segment%@*}"
130
+ fi
131
+
132
+ local repo_id="$owner/$repo_segment"
133
+ local file_path="$remainder"
134
+ local attempt success temp_dir
135
+ for attempt in 1 2 3; do
136
+ temp_dir="$(mktemp -d)"
137
+ success=false
138
+
139
+ log_info "[HF] Tentativa $attempt/3: ${repo_id}/${file_path}${revision:+ @}${revision:+$revision}"
140
+
141
+ if command -v hf >/dev/null 2>&1; then
142
+ local hf_cmd=(hf download "$repo_id" "$file_path")
143
+ if [[ -n "$revision" ]]; then
144
+ hf_cmd+=(--revision "$revision")
145
+ fi
146
+ hf_cmd+=(--local-dir "$temp_dir" --quiet)
147
+ if [[ -n "$HF_TOKEN" ]]; then
148
+ hf_cmd+=(--token "$HF_TOKEN")
149
+ fi
150
+ if HF_HUB_ENABLE_HF_TRANSFER=1 "${hf_cmd[@]}"; then
151
+ success=true
152
+ fi
153
+ fi
154
+
155
+ if [[ "$success" == false ]]; then
156
+ local fallback_revision="${revision:-main}"
157
+ local direct_url="https://huggingface.co/${repo_id}/resolve/${fallback_revision}/${file_path}"
158
+ log_warn "[HF] Tentativa $attempt usando fallback HTTP"
159
+ if command -v aria2c >/dev/null 2>&1; then
160
+ local aria_cmd=(aria2c -c -s 16 -x 16 -k 1M --console-log-level=warn --summary-interval=10 --dir "$temp_dir" --out "$filename")
161
+ if [[ -n "$HF_TOKEN" ]]; then
162
+ aria_cmd+=(--header="Authorization: Bearer $HF_TOKEN")
163
+ fi
164
+ aria_cmd+=("$direct_url")
165
+ if "${aria_cmd[@]}"; then
166
+ success=true
167
+ fi
168
+ fi
169
+ if [[ "$success" == false ]] && command -v curl >/dev/null 2>&1; then
170
+ local curl_cmd=(curl -L -# -o "$temp_dir/$filename")
171
+ if [[ -n "$HF_TOKEN" ]]; then
172
+ curl_cmd+=(-H "Authorization: Bearer $HF_TOKEN")
173
+ fi
174
+ curl_cmd+=("$direct_url")
175
+ if "${curl_cmd[@]}"; then
176
+ success=true
177
+ fi
178
+ fi
179
+ if [[ "$success" == false ]] && command -v wget >/dev/null 2>&1; then
180
+ local wget_cmd=(wget -q --show-progress -c -O "$temp_dir/$filename")
181
+ if [[ -n "$HF_TOKEN" ]]; then
182
+ wget_cmd+=(--header="Authorization: Bearer $HF_TOKEN")
183
+ fi
184
+ wget_cmd+=("$direct_url")
185
+ if "${wget_cmd[@]}"; then
186
+ success=true
187
+ fi
188
+ fi
189
+ fi
190
+
191
+ if [[ "$success" == true ]]; then
192
+ local downloaded
193
+ downloaded="$(find "$temp_dir" -type f -name "$filename" -print -quit)"
194
+ if [[ -z "$downloaded" ]]; then
195
+ downloaded="$(find "$temp_dir" -type f -print -quit)"
196
+ fi
197
+ if [[ -n "$downloaded" ]]; then
198
+ mv "$downloaded" "$target_dir/$filename"
199
+ rm -rf "$temp_dir"
200
+ if [[ -s "$target_dir/$filename" ]]; then
201
+ log_success "Download concluído: $filename"
202
+ return 0
203
+ fi
204
+ log_warn "Arquivo vazio após download: $filename"
205
+ rm -f "$target_dir/$filename"
206
+ fi
207
+ fi
208
+
209
+ rm -rf "$temp_dir"
210
+ log_warn "Tentativa $attempt falhou para $filename"
211
+ sleep $((2 * attempt))
212
+ done
213
+
214
+ log_error "Falha ao baixar: $filename"
215
+ return 1
216
+ }
217
+
218
+
219
+ download_file() {
220
+ local url="$1"
221
+ local target_dir="$2"
222
+ local filename="$3"
223
+
224
+ if [[ "$url" == *"civitai.com/api/download"* ]] && [[ "$url" != *"token="* ]] && [[ -n "$CIVITAI_TOKEN" ]]; then
225
+ if [[ "$url" == *"?"* ]]; then
226
+ url="${url}&token=${CIVITAI_TOKEN}"
227
+ else
228
+ url="${url}?token=${CIVITAI_TOKEN}"
229
+ fi
230
+ fi
231
+ mkdir -p "$target_dir"
232
+
233
+ local final_name="$filename"
234
+ if [[ -z "$final_name" ]]; then
235
+ final_name="$(basename "${url%%\?*}")"
236
+ fi
237
+
238
+ if [[ -f "$target_dir/$final_name" ]]; then
239
+ local existing_size
240
+ existing_size=$(stat -c%s "$target_dir/$final_name" 2>/dev/null || echo 0)
241
+ if [[ "$existing_size" -gt 524288 ]]; then
242
+ log_success "Já existe: $final_name"
243
+ return 0
244
+ fi
245
+ fi
246
+
247
+ local attempt success
248
+ for attempt in 1 2 3; do
249
+ success=false
250
+ log_info "[DL] Tentativa $attempt/3: ${final_name}"
251
+ if command -v aria2c >/dev/null 2>&1; then
252
+ if aria2c -c -s 16 -x 16 -k 1M --console-log-level=warn --summary-interval=10 --dir "$target_dir" --out "$final_name" "$url"; then
253
+ success=true
254
+ fi
255
+ fi
256
+ if [[ "$success" == false ]] && command -v wget >/dev/null 2>&1; then
257
+ if wget -q --show-progress -c -O "$target_dir/$final_name" "$url"; then
258
+ success=true
259
+ fi
260
+ fi
261
+ if [[ "$success" == false ]] && command -v curl >/dev/null 2>&1; then
262
+ if curl -L -# -C - -o "$target_dir/$final_name" "$url"; then
263
+ success=true
264
+ fi
265
+ fi
266
+ if [[ "$success" == true ]]; then
267
+ if [[ -s "$target_dir/$final_name" ]]; then
268
+ log_success "Download concluído: $final_name"
269
+ return 0
270
+ fi
271
+ log_warn "Arquivo vazio após download: $final_name"
272
+ rm -f "$target_dir/$final_name"
273
+ fi
274
+ log_warn "Tentativa $attempt falhou para $final_name"
275
+ sleep $((2 * attempt))
276
+ done
277
+
278
+ log_error "Falha ao baixar: $final_name"
279
+ return 1
280
+ }
281
+
282
+ download_mega() {
283
+ local url="$1"
284
+ local target_dir="$2"
285
+
286
+ url="${url#mega://}"
287
+ mkdir -p "$target_dir"
288
+
289
+ if ! command -v megadl >/dev/null 2>&1; then
290
+ log_warn "megadl não encontrado; tente instalar megatools manualmente"
291
+ return 1
292
+ fi
293
+
294
+ local attempt
295
+ for attempt in 1 2 3; do
296
+ log_info "[MEGA] Tentativa $attempt/3"
297
+ local temp_dir
298
+ temp_dir="$(mktemp -d)"
299
+ if megadl --limit-speed 0 --path "$temp_dir" "$url"; then
300
+ local moved=0
301
+ while IFS= read -r -d '' file; do
302
+ if [[ ! -f "$file" ]]; then
303
+ continue
304
+ fi
305
+ local base
306
+ base="$(basename "$file")"
307
+ if [[ -f "$target_dir/$base" ]]; then
308
+ log_success "Já existe: $base"
309
+ else
310
+ if mv "$file" "$target_dir/$base"; then
311
+ log_success "Download Mega.nz concluído: $base"
312
+ else
313
+ log_warn "Falha ao mover $base para destino final"
314
+ continue
315
+ fi
316
+ fi
317
+ moved=1
318
+ done < <(find "$temp_dir" -type f -print0)
319
+
320
+ rm -rf "$temp_dir"
321
+ if (( moved )); then
322
+ return 0
323
+ fi
324
+ log_warn "[MEGA] Nenhum arquivo detectado após download"
325
+ sleep $((2 * attempt))
326
+ else
327
+ log_warn "Tentativa $attempt falhou para Mega.nz"
328
+ rm -rf "$temp_dir"
329
+ sleep $((2 * attempt))
330
+ fi
331
+ done
332
+
333
+ log_error "Falha ao baixar de Mega.nz: $url"
334
+ return 1
335
+ }
336
+
337
+
338
+
339
+ process_downloads() {
340
+ local failed=0
341
+ for entry in "${DOWNLOAD_FILES[@]}"; do
342
+ IFS='|' read -r raw_url type filename <<< "$entry"
343
+ local target_dir="$MODELS_DIR/$type"
344
+ mkdir -p "$target_dir"
345
+
346
+ if [[ "$raw_url" == mega://* ]]; then
347
+ if ! download_mega "$raw_url" "$target_dir"; then
348
+ ((failed++))
349
+ fi
350
+ elif [[ "$raw_url" == hf://* ]]; then
351
+ local hf_path="${raw_url#hf://}"
352
+ if ! download_hf "$hf_path" "$target_dir" "$filename"; then
353
+ ((failed++))
354
+ fi
355
+ elif [[ "$raw_url" == https://huggingface.co/* ]]; then
356
+ local sanitized_url="${raw_url%%\?*}"
357
+ local hf_relative="${sanitized_url#https://huggingface.co/}"
358
+ IFS='/' read -ra hf_parts <<< "$hf_relative"
359
+ if (( ${#hf_parts[@]} >= 4 )) && [[ "${hf_parts[2]}" == "resolve" || "${hf_parts[2]}" == "blob" || "${hf_parts[2]}" == "raw" ]]; then
360
+ local hf_owner="${hf_parts[0]}"
361
+ local hf_repo="${hf_parts[1]}"
362
+ local hf_revision="${hf_parts[3]}"
363
+ local start_index=4
364
+ local hf_file_path=""
365
+ for ((i=start_index; i<${#hf_parts[@]}; i++)); do
366
+ if [[ -n "$hf_file_path" ]]; then
367
+ hf_file_path+='/'
368
+ fi
369
+ hf_file_path+="${hf_parts[i]}"
370
+ done
371
+ if [[ -n "$hf_file_path" ]]; then
372
+ local hf_path_combined="${hf_owner}/${hf_repo}/${hf_file_path}"
373
+ if ! download_hf "$hf_path_combined" "$target_dir" "$filename" "$hf_revision"; then
374
+ ((failed++))
375
+ fi
376
+ else
377
+ if ! download_file "$raw_url" "$target_dir" "$filename"; then
378
+ ((failed++))
379
+ fi
380
+ fi
381
+ else
382
+ if ! download_file "$raw_url" "$target_dir" "$filename"; then
383
+ ((failed++))
384
+ fi
385
+ fi
386
+ else
387
+ if ! download_file "$raw_url" "$target_dir" "$filename"; then
388
+ ((failed++))
389
+ fi
390
+ fi
391
+ done
392
+
393
+ if (( failed > 0 )); then
394
+ return 1
395
+ fi
396
+ return 0
397
+ }
398
+
399
+ clone_repo() {
400
+ local url="$1"
401
+ local dest="$2"
402
+
403
+ local name
404
+ name="$(basename "$dest")"
405
+
406
+ if [[ -d "$dest/.git" ]]; then
407
+ if ! git -C "$dest" pull --ff-only --no-rebase >/dev/null 2>&1; then
408
+ log_warn "Falha ao atualizar $name"
409
+ else
410
+ log_success "Atualizado: $name"
411
+ fi
412
+ else
413
+ if ! git clone --depth 1 "$url" "$dest" >/dev/null 2>&1; then
414
+ log_warn "Falha ao clonar $name"
415
+ return
416
+ fi
417
+ log_success "Clonado: $name"
418
+ fi
419
+
420
+ if [[ -f "$dest/requirements.txt" ]]; then
421
+ if [[ -n "$PYTHON_BIN" ]]; then
422
+ if ! "$PYTHON_BIN" -m pip install -q -r "$dest/requirements.txt" >/dev/null 2>&1; then
423
+ log_warn "Falha ao instalar requirements de $name"
424
+ else
425
+ log_info "Dependências instaladas para $name"
426
+ fi
427
+ else
428
+ log_warn "PYTHON_BIN não definido; pulei requirements de $name"
429
+ fi
430
+ fi
431
+ }
432
+
433
+ # ========== INSTALAÇÃO ==========
434
+ log_info "========================================="
435
+ log_info " ComfyUI + Wan 2.2 Setup"
436
+ log_info "========================================="
437
+
438
+ # 1. Dependências
439
+ log_info "[1/7] Instalando dependências do sistema..."
440
+ if command -v apt-get >/dev/null 2>&1; then
441
+ apt-get update -qq || log_warn "apt-get update falhou; seguindo assim mesmo"
442
+ apt-get install -y -qq python3-venv aria2 megatools git wget curl || log_warn "apt-get install retornou erro"
443
+ else
444
+ log_warn "apt-get indisponível; certifique-se de que python3-venv, aria2, megatools, git, wget e curl estão instalados"
445
+ fi
446
+ log_success "Dependências do sistema tratadas"
447
+
448
+ # 2. Preparar ambiente virtual
449
+ log_info "[2/7] Preparando ambiente virtual..."
450
+ if [[ ! -d "$VENV_DIR/bin" ]]; then
451
+ python3 -m venv "$VENV_DIR"
452
+ log_success "Ambiente virtual criado em $VENV_DIR"
453
+ else
454
+ log_info "Ambiente virtual já existe em $VENV_DIR"
455
+ fi
456
+ . "$VENV_DIR/bin/activate"
457
+ PYTHON_BIN="$VENV_DIR/bin/python"
458
+
459
+ "$PYTHON_BIN" -m pip install -U pip wheel setuptools -q || log_warn "Falha na atualização do pip"
460
+ "$PYTHON_BIN" -m pip install -U "huggingface_hub[cli,hf_transfer]" comfy-cli -q || log_warn "Falha instalando huggingface_hub/comfy-cli"
461
+ log_success "Ambiente virtual pronto e comfy-cli instalado"
462
+
463
+ # 3. Instalar ComfyUI
464
+ log_info "[3/7] Instalando ComfyUI..."
465
+ if [[ -f "$COMFY_DIR/main.py" ]]; then
466
+ log_warn "ComfyUI já presente"
467
+ else
468
+ comfy --skip-prompt install --fast-deps --nvidia || log_error "Instalação do ComfyUI falhou"
469
+ fi
470
+
471
+ REQ_FILE="$COMFY_DIR/requirements.txt"
472
+ if [[ -f "$REQ_FILE" ]]; then
473
+ log_info "Verificando dependências do ComfyUI em: $REQ_FILE"
474
+ if [[ -n "$PYTHON_BIN" ]]; then
475
+ if "$PYTHON_BIN" -m pip install -q -r "$REQ_FILE"; then
476
+ log_success "Requirements do ComfyUI instalados/validados"
477
+ else
478
+ log_warn "Falha ao instalar requirements do ComfyUI; verifique o log acima e reexecute se necessário"
479
+ fi
480
+ else
481
+ log_warn "PYTHON_BIN não definido; pulei requirements do ComfyUI"
482
+ fi
483
+ else
484
+ log_warn "requirements.txt do ComfyUI não encontrado em $REQ_FILE"
485
+ fi
486
+
487
+ log_success "ComfyUI pronto"
488
+
489
+ # 4. Instalar PyTorch (CUDA 12.8)
490
+ log_info "[4/7] Instalando PyTorch CUDA 12.8..."
491
+ "$PYTHON_BIN" -m pip install --force --upgrade torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu128 || log_error "Falha ao instalar PyTorch"
492
+ log_success "PyTorch configurado"
493
+
494
+ # 5. Instalar SageAttention (condicional)
495
+ log_info "[5/7] Instalando SageAttention..."
496
+ if "$PYTHON_BIN" - <<'PY' >/dev/null 2>&1
497
+ import torch, sys
498
+ sys.exit(0 if torch.cuda.is_available() else 1)
499
+ PY
500
+ then
501
+ if "$PYTHON_BIN" -m pip install "https://huggingface.co/adbrasi/comfywheel/resolve/main/sageattention-2.2.0-cp312-cp312-linux_x86_64.whl" -q; then
502
+ if "$PYTHON_BIN" - <<'PY' >/dev/null 2>&1
503
+ import sageattention
504
+ PY
505
+ then
506
+ log_success "SageAttention instalado"
507
+ else
508
+ log_warn "SageAttention instalado, mas não pôde ser importado"
509
+ fi
510
+ else
511
+ log_warn "Falha ao instalar SageAttention"
512
+ fi
513
+ else
514
+ log_warn "CUDA indisponível; pulando SageAttention"
515
+ fi
516
+
517
+ # 6. Downloads de modelos
518
+ log_info "[6/7] Baixando modelos..."
519
+ mkdir -p "$MODELS_DIR"
520
+ if process_downloads; then
521
+ log_success "Downloads concluídos (ou já presentes)"
522
+ else
523
+ log_warn "Alguns downloads falharam; reexecute o script para tentar novamente"
524
+ fi
525
+
526
+ # 7. Custom nodes
527
+ log_info "[7/7] Instalando custom nodes..."
528
+ CN_DIR="$COMFY_DIR/custom_nodes"
529
+ mkdir -p "$CN_DIR"
530
+ node_total=${#CUSTOM_NODES[@]}
531
+ node_index=0
532
+ set +e
533
+ for repo in "${CUSTOM_NODES[@]}"; do
534
+ ((node_index++))
535
+ log_info "[$node_index/$node_total] $(basename "$repo")"
536
+ clone_repo "$repo" "$CN_DIR/$(basename "$repo")"
537
+ done
538
+ set -e
539
+ log_success "Custom nodes processados"
540
+
541
+
542
+ SAGE_FLAG=""
543
+ if "$PYTHON_BIN" - <<'PY' >/dev/null 2>&1
544
+ import sageattention
545
+ PY
546
+ then
547
+ SAGE_FLAG="--use-sage-attention"
548
+ fi
549
+
550
+ log_info "========================================="
551
+ log_info "Iniciando ComfyUI em http://${COMFY_HOST}:${COMFY_PORT}"
552
+ log_info "========================================="
553
+
554
+ cd "$COMFY_DIR"
555
+ exec comfy launch -- ${SAGE_FLAG:+$SAGE_FLAG} --listen "$COMFY_HOST" --port "$COMFY_PORT"