File size: 10,534 Bytes
db47818
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
# app_refactored_with_postprod.py

import gradio as gr
import os
import sys
from pathlib import Path
import traceback

# --- Import dos Serviços de Backend ---

# Serviço LTX para geração de vídeo base e refinamento de textura
try:
    from api.ltx_server_refactored import video_generation_service
except ImportError:
    print("ERRO FATAL: Não foi possível importar 'video_generation_service' de 'api.ltx_server_refactored'.")
    print("Verifique se o arquivo existe e se o ambiente está configurado corretamente.")
    sys.exit(1)


# Serviço SeedVR para upscaling de alta qualidade
try:
    from api.seedvr_server import SeedVRServer
except ImportError:
    print("AVISO: Não foi possível importar SeedVRServer. A aba de upscaling SeedVR será desativada.")
    SeedVRServer = None # Define como None para tratamento gracioso de erro

# Inicializa o servidor SeedVR uma vez, se disponível
if SeedVRServer:
    print("Inicializando o servidor de inferência SeedVR...")
    seedvr_inference_server = SeedVRServer()
else:
    seedvr_inference_server = None

# --- ESTADO DA SESSÃO ---
# Mantém os caminhos dos arquivos entre os cliques dos botões
def create_initial_state():
    return {
        "low_res_video": None,
        "low_res_latents": None,
        "refined_video": None,
        "refined_latents": None,
        "used_seed": None
    }

# --- FUNÇÕES WRAPPER PARA A UI ---

def run_generate_low(prompt, neg_prompt, start_img, height, width, duration, cfg, seed, randomize_seed, progress=gr.Progress(track_tqdm=True)):
    """
    Executa a primeira etapa: geração de um vídeo base em baixa resolução.
    """
    print("UI: Chamando generate_low")
    
    try:
        # 1. Preparar conditioning_items (se uma imagem de início for fornecida)
        conditioning_items = []
        if start_img:
            # A função `prepare_condition_items` precisa de uma estimativa do número de frames
            num_frames_estimate = int(duration * 24)
            items_list = [[start_img, 0, 1.0]] # Imagem de início, no frame 0, com peso 1.0
            conditioning_items = video_generation_service.prepare_condition_items(items_list, height, width, num_frames_estimate)

        # Determina a seed a ser usada
        used_seed = None if randomize_seed else seed
        
        # 2. Chamar a função de geração de baixa resolução do backend
        video_path, tensor_path, final_seed = video_generation_service.generate_low(
            prompt=prompt, negative_prompt=neg_prompt,
            height=height, width=width, duration=duration,
            guidance_scale=cfg, seed=used_seed,
            conditioning_items=conditioning_items
        )
        
        # 3. Atualizar o estado da aplicação com os caminhos dos arquivos resultantes
        new_state = {
            "low_res_video": video_path,
            "low_res_latents": tensor_path,
            "refined_video": None, # Limpa resultados de execuções anteriores
            "refined_latents": None,
            "used_seed": final_seed
        }
        
        # 4. Retorna os resultados para a UI
        #    - O caminho do vídeo para o componente de vídeo
        #    - O novo estado para o componente gr.State
        #    - Um update para tornar o grupo de pós-produção visível
        return video_path, new_state, gr.update(visible=True)
        
    except Exception as e:
        error_message = f"❌ Ocorreu um erro na Geração Base:\n{e}"
        print(f"{error_message}\nDetalhes: {traceback.format_exc()}")
        raise gr.Error(error_message)


def run_seedvr_upscaling(state, seed, resolution, batch_size, fps, progress=gr.Progress(track_tqdm=True)):
    """
    Função de callback que executa o processo de upscaling com SeedVR.
    """
    if not state or not state.get("low_res_video"):
        raise gr.Error("Erro: Gere um vídeo base primeiro na Etapa 1.")
    if not seedvr_inference_server:
        raise gr.Error("Erro: O servidor SeedVR não está disponível. Verifique a instalação e os logs.")
        
    video_path = state["low_res_video"]
    
    progress(0, desc="Iniciando SeedVR Upscaling...")
    print(f"▶️  Iniciando processo de upscaling SeedVR para o vídeo: {video_path}")
    
    try:
        # Wrapper para a barra de progresso do Gradio
        def progress_wrapper(p, desc=""):
            progress(p, desc=desc)
            print(f"⌛ Progresso SeedVR: {p*100:.1f}% - {desc}")

        # Chama o método de inferência do servidor SeedVR
        output_filepath = seedvr_inference_server.run_inference(
            file_path=video_path,
            seed=seed,
            resolution=resolution,
            batch_size=batch_size,
            fps=fps,
            progress=progress_wrapper
        )
        
        final_message = f"✅ Processo SeedVR concluído!\nVídeo salvo em: {output_filepath}"
        print(final_message)
        # Retorna o vídeo e a mensagem de sucesso para a UI
        return gr.update(value=output_filepath, interactive=True), gr.update(value=final_message, interactive=False)

    except Exception as e:
        error_message = f"❌ Ocorreu um erro grave durante o upscaling com SeedVR:\n{e}"
        print(f"{error_message}\nDetalhes: {traceback.format_exc()}")
        # Retorna None para o vídeo e a mensagem de erro para o status box
        return None, gr.update(value=error_message, interactive=False)


# --- DEFINIÇÃO DA INTERFACE GRADIO ---
with gr.Blocks(css="#col-container { margin: 0 auto; max-width: 900px; }", theme=gr.themes.Monochrome()) as demo:
    gr.Markdown("# LTX Video - Geração e Pós-Produção por Etapas")
    
    # Componente invisível para armazenar o estado da aplicação (caminhos de arquivos, etc.)
    app_state = gr.State(value=create_initial_state())

    # --- ETAPA 1: Geração Base ---
    with gr.Row():
        with gr.Column(scale=1):
            gr.Markdown("### Etapa 1: Configurações de Geração")
            prompt_input = gr.Textbox(label="Prompt", value="A majestic dragon flying over a medieval castle", lines=3)
            neg_prompt_input = gr.Textbox(label="Negative Prompt", value="worst quality, blurry, low quality, jittery", lines=2)
            start_image = gr.Image(label="Imagem de Início (Opcional)", type="filepath", sources=["upload", "clipboard"])
            
            with gr.Accordion("Parâmetros Avançados", open=False):
                height_input = gr.Slider(label="Height", value=512, step=32, minimum=256, maximum=1024)
                width_input = gr.Slider(label="Width", value=704, step=32, minimum=256, maximum=1024)
                duration_input = gr.Slider(label="Duração (s)", value=4, step=1, minimum=1, maximum=10)
                cfg_input = gr.Slider(label="Guidance Scale (CFG)", value=3.0, step=0.1, minimum=1.0, maximum=10.0)
                seed_input = gr.Number(label="Seed", value=42, precision=0)
                randomize_seed = gr.Checkbox(label="Randomize Seed", value=True)

            generate_low_btn = gr.Button("1. Gerar Vídeo Base (Low-Res)", variant="primary")
        
        with gr.Column(scale=1):
            gr.Markdown("### Vídeo Base Gerado")
            low_res_video_output = gr.Video(label="O resultado da Etapa 1 aparecerá aqui", interactive=False)

    # --- ETAPA 2: Pós-Produção (no rodapé, em abas) ---
    with gr.Group(visible=False) as post_prod_group:
        gr.Markdown("<hr style='margin-top: 20px; margin-bottom: 20px;'>")
        gr.Markdown("## Etapa 2: Pós-Produção")
        gr.Markdown("Use o vídeo gerado acima como entrada para as ferramentas abaixo.")

        with gr.Tabs():
            with gr.TabItem("🚀 Upscaler Textura (LTX)"):
                gr.Markdown("*(Funcionalidade a ser implementada no futuro)*")
                # Aqui iriam os componentes para o refinamento LTX
                # refine_ltx_btn = gr.Button("Aplicar Refinamento de Textura LTX")
                # refined_ltx_video_output = gr.Video(label="Vídeo com Textura Refinada")

            with gr.TabItem("✨ Upscaler SeedVR"):
                with gr.Row():
                    with gr.Column(scale=1):
                        gr.Markdown("### Parâmetros do SeedVR")
                        seedvr_seed = gr.Slider(minimum=0, maximum=999999, value=42, step=1, label="Seed")
                        seedvr_resolution = gr.Slider(minimum=720, maximum=1440, value=1072, step=8, label="Resolução Vertical (Altura)")
                        seedvr_batch_size = gr.Slider(minimum=1, maximum=16, value=4, step=1, label="Batch Size por GPU")
                        seedvr_fps_output = gr.Number(label="FPS de Saída (0 = original)", value=0)
                        run_seedvr_button = gr.Button("Iniciar Upscaling SeedVR", variant="primary", interactive=(seedvr_inference_server is not None))
                        if not seedvr_inference_server:
                             gr.Markdown("<p style='color: red;'>Serviço SeedVR não disponível.</p>")

                    with gr.Column(scale=1):
                        gr.Markdown("### Resultado do Upscaling")
                        seedvr_video_output = gr.Video(label="Vídeo com Upscale SeedVR", interactive=False)
                        seedvr_status_box = gr.Textbox(label="Status do Processamento", value="Aguardando...", lines=3, interactive=False)

            with gr.TabItem("🔊 Áudio (MM-Audio)"):
                gr.Markdown("*(Funcionalidade futura para adicionar som aos vídeos)*")
                # Componentes para a geração de áudio viriam aqui

    # --- LÓGICA DE EVENTOS DA UI ---

    # Conecta o botão da Etapa 1 à sua função de backend
    generate_low_btn.click(
        fn=run_generate_low,
        inputs=[prompt_input, neg_prompt_input, start_image, height_input, width_input, duration_input, cfg_input, seed_input, randomize_seed],
        outputs=[low_res_video_output, app_state, post_prod_group]
    )

    # Conecta o botão da Aba SeedVR à sua função de backend
    run_seedvr_button.click(
        fn=run_seedvr_upscaling,
        inputs=[
            app_state,
            seedvr_seed,
            seedvr_resolution,
            seedvr_batch_size,
            seedvr_fps_output
        ],
        outputs=[
            seedvr_video_output,
            seedvr_status_box
        ]
    )


if __name__ == "__main__":
    # Inicia a aplicação Gradio
    demo.queue().launch(
        server_name="0.0.0.0",
        debug=True,
        show_error=True
    )