x2XcarleX2x commited on
Commit
bb9b5d4
·
verified ·
1 Parent(s): 040fb57

Upload 3 files

Browse files
Files changed (3) hide show
  1. app_wan.py +171 -0
  2. config.yaml +26 -9
  3. start.sh +1 -1
app_wan.py ADDED
@@ -0,0 +1,171 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # demo_aduc_wan.py
2
+ import gradio as gr
3
+ import torch
4
+ import logging
5
+ from PIL import Image
6
+ from typing import List, Dict, Any
7
+
8
+ # --- Importa os Pilares da nossa Arquitetatura ADUC ---
9
+ from aduc_framework.managers.vae_wan_manager import vae_wan_manager_singleton as VaeWan
10
+ from aduc_framework.managers.wan_manager import wan_manager_singleton as Wan
11
+ from aduc_framework.types import LatentConditioningItem
12
+ from aduc_framework.tools.video_encode_tool import video_encode_tool_singleton as VideoTool
13
+
14
+ # --- Configuração do Logging ---
15
+ logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - [%(name)s] - %(message)s')
16
+ logger = logging.getLogger("ADUC_WAN_DEMO")
17
+
18
+ # --- Lógica Principal da Geração (Adaptada para Gradio) ---
19
+
20
+ def generate_aduc_video(
21
+ image1: Image.Image, strength1: float, frame_idx1: int,
22
+ image2: Image.Image, strength2: float, frame_idx2: int,
23
+ image3: Image.Image, strength3: float, frame_idx3: int,
24
+ motion_prompt: str,
25
+ progress=gr.Progress(track_tqdm=True)
26
+ ):
27
+ """
28
+ Função principal que orquestra a geração de vídeo e é chamada pela interface Gradio.
29
+ """
30
+ try:
31
+ # --- 1. Validação e Montagem do Plano de Produção ---
32
+ progress(0, desc="[Diretor] Validando o plano de produção...")
33
+
34
+ production_plan = []
35
+ if image1: production_plan.append({"image": image1, "frame_index": int(frame_idx1), "strength": strength1})
36
+ if image2: production_plan.append({"image": image2, "frame_index": int(frame_idx2), "strength": strength2})
37
+ if image3: production_plan.append({"image": image3, "frame_index": int(frame_idx3), "strength": strength3})
38
+
39
+ if not production_plan:
40
+ raise gr.Error("Por favor, forneça pelo menos uma imagem para iniciar a geração.")
41
+
42
+ resolution = (480, 832) # Resolução padrão para o teste
43
+
44
+ # --- 2. Pré-Produção: Conversão para Latentes ---
45
+ progress(0.1, desc="[VaeWan] Convertendo imagens para o espaço latente...")
46
+ pil_images = [item["image"] for item in production_plan]
47
+ latent_tensors = VaeWan.encode_batch(pil_images, target_resolution=resolution)
48
+
49
+ # --- 3. Estruturação: Montando as Condições ADUC ---
50
+ progress(0.2, desc="[Diretor] Montando ordens de serviço (LatentConditioningItems)...")
51
+ conditioning_items = [
52
+ LatentConditioningItem(
53
+ latent_tensor=latent_tensors[i],
54
+ media_frame_number=item["frame_index"],
55
+ conditioning_strength=item["strength"]
56
+ ) for i, item in enumerate(production_plan)
57
+ ]
58
+
59
+ # --- 4. Produção: Geração pelo WanManager ---
60
+ progress(0.3, desc="[WanManager] Luz, Câmera, Ação! Gerando fragmento latente (pode levar um momento)...")
61
+ job_params = {
62
+ "conditioning_items_data": conditioning_items,
63
+ "motion_prompt": motion_prompt,
64
+ "height": resolution[0],
65
+ "width": resolution[1],
66
+ "video_total_frames": 81,
67
+ "num_inference_steps": 8,
68
+ }
69
+ video_latents, _ = Wan.generate_latent_fragment(**job_params)
70
+
71
+ # --- 5. Pós-Produção: Decodificação ---
72
+ progress(0.8, desc="[VaeWan] Decodificando o resultado final para pixels...")
73
+ video_pixels = VaeWan.decode(video_latents)
74
+
75
+ # --- 6. Salvamento ---
76
+ progress(0.9, desc="[VideoTool] Salvando o arquivo de vídeo final...")
77
+ output_path = "demo_aduc_wan_output.mp4"
78
+ VideoTool.save_video_from_tensor(video_pixels, path=output_path, fps=16)
79
+
80
+ progress(1.0, desc="Produção Concluída!")
81
+ return output_path
82
+
83
+ except Exception as e:
84
+ logger.error("Ocorreu um erro durante a geração do vídeo.", exc_info=True)
85
+ # Lança um erro que será exibido na interface do Gradio
86
+ raise gr.Error(f"Falha na geração: {e}")
87
+
88
+
89
+ # --- Construção da Interface Gráfica (UI) ---
90
+
91
+ with gr.Blocks(theme=gr.themes.Soft(), title="ADUC-SDR Wan Demo") as demo:
92
+ gr.Markdown(
93
+ """
94
+ # 🎬 Demo ADUC-SDR com WanManager (Lightning)
95
+ ### Bem-vindo, Mestre Deformes!
96
+ Esta interface permite controlar o especialista `WanManager` usando a metodologia ADUC.
97
+ Faça o upload de até 3 keyframes, defina suas posições e forças no vídeo e escreva um prompt para guiar a animação.
98
+ """
99
+ )
100
+
101
+ with gr.Row():
102
+ with gr.Column(scale=1):
103
+ gr.Markdown("### Keyframe 1 (Inicial)")
104
+ img1 = gr.Image(type="pil", label="Imagem de Início")
105
+ strength1 = gr.Slider(minimum=0.0, maximum=1.0, value=1.0, label="Força (Strength)", info="1.0 = o vídeo começa EXATAMENTE nesta imagem.")
106
+ frame_idx1 = gr.Number(value=0, label="Índice do Frame", info="Em que ponto do vídeo este frame aparece (0 é o início).", precision=0)
107
+
108
+ with gr.Column(scale=1):
109
+ gr.Markdown("### Keyframe 2 (Intermediário)")
110
+ img2 = gr.Image(type="pil", label="Imagem do Meio")
111
+ strength2 = gr.Slider(minimum=0.0, maximum=1.0, value=0.6, label="Força (Strength)", info="< 1.0 = o vídeo é INFLUENCIADO por esta imagem.")
112
+ frame_idx2 = gr.Number(value=40, label="Índice do Frame", info="O padrão é o meio do vídeo (frame 40 de 81).", precision=0)
113
+
114
+ with gr.Column(scale=1):
115
+ gr.Markdown("### Keyframe 3 (Final)")
116
+ img3 = gr.Image(type="pil", label="Imagem Final")
117
+ strength3 = gr.Slider(minimum=0.0, maximum=1.0, value=1.0, label="Força (Strength)", info="1.0 = o vídeo termina EXATAMENTE nesta imagem.")
118
+ frame_idx3 = gr.Number(value=80, label="Índice do Frame", info="O padrão é o último frame do vídeo.", precision=0)
119
+
120
+ with gr.Row():
121
+ motion_prompt_input = gr.Textbox(
122
+ label="📝 Prompt de Movimento",
123
+ placeholder="Ex: a beautiful cinematic shot of a majestic landscape changing seasons",
124
+ lines=2,
125
+ scale=3
126
+ )
127
+ generate_btn = gr.Button("🎬 Gerar Vídeo", variant="primary", scale=1)
128
+
129
+ with gr.Row():
130
+ output_video = gr.Video(label="Resultado da Produção", interactive=False)
131
+
132
+ # Conecta o botão à função de geração
133
+ generate_btn.click(
134
+ fn=generate_aduc_video,
135
+ inputs=[
136
+ img1, strength1, frame_idx1,
137
+ img2, strength2, frame_idx2,
138
+ img3, strength3, frame_idx3,
139
+ motion_prompt_input
140
+ ],
141
+ outputs=[output_video]
142
+ )
143
+
144
+ gr.Examples(
145
+ examples=[
146
+ ["examples/frame_1.png", 1.0, 0, "examples/frame_2.png", 0.7, 40, "examples/frame_3.png", 1.0, 80, "A slow zoom out revealing a vast alien desert at sunset"],
147
+ ],
148
+ inputs=[img1, strength1, frame_idx1, img2, strength2, frame_idx2, img3, strength3, frame_idx3, motion_prompt_input],
149
+ outputs=[output_video],
150
+ fn=generate_aduc_video,
151
+ cache_examples=False, # Desativa o cache para sempre rodar a geração
152
+ )
153
+
154
+ if __name__ == "__main__":
155
+ # Cria a pasta e as imagens de exemplo se não existirem
156
+ if not os.path.exists("examples"):
157
+ os.makedirs("examples")
158
+ try:
159
+ Image.new('RGB', (832, 480), color = (73, 109, 137)).save("examples/frame_1.png")
160
+ Image.new('RGB', (832, 480), color = (173, 109, 237)).save("examples/frame_2.png")
161
+ Image.new('RGB', (832, 480), color = (255, 255, 0)).save("examples/frame_3.png")
162
+ except:
163
+ pass # Evita que o app quebre se não tiver permissão de escrita
164
+
165
+ os.makedirs(WORKSPACE_DIR, exist_ok=True)
166
+ logger.info("Aplicação Gradio pronta. Lançando interface...")
167
+ demo.launch(
168
+ debug=True
169
+ server_name="0.0.0.0",
170
+ server_port=int(os.getenv("PORT", "7860")),
171
+ )
config.yaml CHANGED
@@ -40,15 +40,32 @@ specialists:
40
  # Alterado para usar o modelo 0.9.8-dev.
41
  config_file: "ltxv-13b-0.9.8-distilled.yaml"
42
  enable_prompt_enhancement: false
43
-
44
-
45
- lora:
46
- - model_id: "Lightricks/LTX-Video-ICLoRA-pose-13b-0.9.7"
47
- weight: 0.5
48
- - model_id: "Lightricks/LTX-Video-ICLoRA-depth-13b-0.9.7"
49
- weight: 0.3
50
- - model_id: "Lightricks/LTX-Video-ICLoRA-detailer-13b-0.9.8"
51
- weight: 0.6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
 
53
 
54
  mmaudio:
 
40
  # Alterado para usar o modelo 0.9.8-dev.
41
  config_file: "ltxv-13b-0.9.8-distilled.yaml"
42
  enable_prompt_enhancement: false
43
+ lora:
44
+ # Exemplo de como adicionar LoRAs para estilização.
45
+ - model_id: "Lightricks/LTX-Video-ICLoRA-pose-13b-0.9.7"
46
+ weight: 0.5
47
+ - model_id: "Lightricks/LTX-Video-ICLoRA-depth-13b-0.9.7"
48
+ weight: 0.3
49
+ - model_id: "Lightricks/LTX-Video-ICLoRA-detailer-13b-0.9.8"
50
+ weight: 0.6
51
+
52
+ vae_wan: # O VAE dedicado e treinado especificamente para o Wan2.2.
53
+ gpus_required: 1 # Aloca 1 GPU para manter o VAE do Wan "quente".
54
+ model_id: "Wan-AI/Wan2.2-I2V-A14B-Diffusers"
55
+
56
+ wan:
57
+ gpus_required: 1 # Aloca 1 GPU para o worker do WanManager.
58
+ model_id: "Wan-AI/Wan2.2-I2V-A14B-Diffusers"
59
+ optimized_model_id: "cbensimon/Wan2.2-I2V-A14B-bf16-Diffusers"
60
+ lora_repo: "Kijai/WanVideo_comfy"
61
+ lora_filename: "Lightx2v/lightx2v_I2V_14B_480p_cfg_step_distill_rank128_bf16.safetensors"
62
+ # Parâmetros padrão para o modo Lightning (8 passos).
63
+ default_height: 480
64
+ default_width: 832
65
+ default_frames: 81
66
+ guidance_scale: 1.0
67
+ guidance_scale_2: 1.0
68
+ inference_steps: 8
69
 
70
 
71
  mmaudio:
start.sh CHANGED
@@ -61,4 +61,4 @@ echo "✅ Modelos prontos."
61
  # --- Etapa 3: Iniciar a Aplicação Principal ---
62
  echo "🎬 Iniciando a aplicação ($1)..."
63
  echo "🚀 Iniciando app.py..."
64
- python3 /app/app.py --listen --port ${PORT:-7860}
 
61
  # --- Etapa 3: Iniciar a Aplicação Principal ---
62
  echo "🎬 Iniciando a aplicação ($1)..."
63
  echo "🚀 Iniciando app.py..."
64
+ python3 /app/app_wan.py --listen --port ${PORT:-7860}