adbrasi commited on
Commit
4d5acf3
·
verified ·
1 Parent(s): a662fec

Upload nsfw_videoGen.sh

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