File size: 7,297 Bytes
9d02e09
 
9a6b3d7
 
9d02e09
 
 
9a6b3d7
 
 
9d02e09
9a6b3d7
9d02e09
9a6b3d7
9d02e09
 
4957d04
9d02e09
 
9a6b3d7
 
 
 
9d02e09
 
 
 
 
 
4957d04
9a6b3d7
9d02e09
 
 
9a6b3d7
9d02e09
9a6b3d7
 
9d02e09
 
9a6b3d7
 
 
 
 
 
 
 
 
 
9d02e09
 
 
 
 
 
 
 
 
 
 
9a6b3d7
9d02e09
 
9a6b3d7
 
9d02e09
 
 
9a6b3d7
 
9d02e09
 
9a6b3d7
9d02e09
 
 
 
 
 
9a6b3d7
9d02e09
 
 
 
 
 
 
9a6b3d7
 
 
 
 
 
9d02e09
9a6b3d7
 
 
 
 
 
 
 
 
9d02e09
 
9a6b3d7
9d02e09
9a6b3d7
 
9d02e09
 
9a6b3d7
 
9d02e09
 
 
9a6b3d7
9d02e09
 
9a6b3d7
9d02e09
9a6b3d7
 
9d02e09
9a6b3d7
 
9d02e09
 
9a6b3d7
9d02e09
 
 
 
9a6b3d7
9d02e09
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9a6b3d7
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
# FILE: api/ltx_aduc_orchestrator.py
# DESCRIPTION: The main workflow orchestrator for the ADUC-SDR LTX suite.
# In this simplified architecture, it coordinates a single unified client (LtxAducPipeline)
# to execute the complete video generation pipeline from prompt to MP4.

import logging
import time
import yaml
import os
import sys 
from PIL import Image
from typing import Optional, Dict, Union

# O Orquestrador importa o CLIENTE UNIFICADO que ele vai coordenar.
from api.ltx.ltx_aduc_pipeline import ltx_aduc_pipeline

# O Orquestrador importa as FERRAMENTAS de que precisa para as tarefas finais.
from tools.video_encode_tool import video_encode_tool_singleton

# Importa o Path para carregar a configuração.
from pathlib import Path
LTX_VIDEO_REPO_DIR = Path("/data/LTX-Video")

# ==============================================================================
# --- A CLASSE ORQUESTRADORA (Cérebro do Workflow) ---
# ==============================================================================

class LtxAducOrchestrator:
    """
    Orquestra o fluxo de trabalho completo de geração de vídeo,
    coordenando o cliente unificado LTX. É o ponto de entrada principal para a UI.
    """
    def __init__(self):
        """
        Inicializa o orquestrador, carregando a configuração base uma única vez.
        """
        self.output_dir = "/app/output"
        self.base_config = self._load_base_config()
        logging.info("✅ LTX ADUC Orchestrator initialized and ready.")

    def _load_base_config(self) -> Dict:
        """Carrega a configuração base do arquivo YAML, que contém os parâmetros padrão."""
        try:
            config_path = LTX_VIDEO_REPO_DIR / "configs" / "ltxv-13b-0.9.8-distilled-fp8.yaml"
            with open(config_path, "r") as file:
                return yaml.safe_load(file)
        except Exception as e:
            logging.error(f"Failed to load base config file. Orchestrator may not function correctly. Error: {e}")
            return {}

    def __call__(
        self,
        prompt: str,
        initial_image: Optional[Image.Image] = None,
        height: int = 432,
        width: int = 768,
        duration_in_seconds: float = 4.0,
        ltx_configs: Optional[Dict] = None,
        output_filename_base: str = "ltx_aduc_video"
    ) -> Optional[str]:
        """
        Ponto de entrada principal do Orquestrador. Executa o pipeline completo de geração de vídeo.

        Args:
            prompt (str): O prompt de texto completo, onde cada nova linha é uma cena.
            initial_image (Optional[Image.Image]): Imagem PIL para condicionar a primeira cena.
            height (int): Altura do vídeo final.
            width (int): Largura do vídeo final.
            duration_in_seconds (float): Duração total desejada do vídeo.
            ltx_configs (Optional[Dict]): Configurações avançadas da UI para sobrescrever os padrões.
            output_filename_base (str): Nome base para o arquivo de vídeo de saída.

        Returns:
            Optional[str]: O caminho para o arquivo .mp4 gerado, ou None em caso de falha.
        """
        t0 = time.time()
        logging.info(f"Orchestrator starting new job for prompt: '{prompt.splitlines()[0]}...'")

        try:
            # =================================================================
            # --- ETAPA 1: PREPARAÇÃO DOS INPUTS E CONFIGURAÇÕES ---
            # =================================================================
            prompt_list = [line.strip() for line in prompt.splitlines() if line.strip()]
            if not prompt_list:
                raise ValueError("O prompt está vazio ou não contém linhas válidas.")

            initial_conditioning_items = []
            if initial_image:
                logging.info("Orchestrator delegating: create conditioning item.")
                conditioning_params = [(0, 1.0)] # (frame_number, strength)
                initial_conditioning_items = ltx_aduc_pipeline.encode_to_conditioning_items(
                    media_list=[initial_image],
                    params=conditioning_params,
                    resolution=(height, width)
                )

            common_ltx_args = self.base_config.get("first_pass", {}).copy()
            common_ltx_args.update({
                'negative_prompt': "blurry, low quality, bad anatomy, deformed",
                'height': height,
                'width': width
            })
            if ltx_configs:
                common_ltx_args.update(ltx_configs)

            # =================================================================
            # --- ETAPA 2: DELEGAR GERAÇÃO DO VÍDEO LATENTE ---
            # =================================================================
            logging.info("Orchestrator delegating: generate latent video.")
            final_latents, used_seed = ltx_aduc_pipeline.generate_latents(
                prompt_list=prompt_list,
                duration_in_seconds=duration_in_seconds,
                common_ltx_args=common_ltx_args,
                initial_conditioning_items=initial_conditioning_items
            )
            if final_latents is None:
                raise RuntimeError("LTX client failed to generate a latent tensor.")
            logging.info(f"Orchestrator received latent tensor with shape: {final_latents.shape}")

            # =================================================================
            # --- ETAPA 3: DELEGAR DECODIFICAÇÃO PARA PIXELS ---
            # =================================================================
            logging.info("Orchestrator delegating: decode latent to pixels.")
            pixel_tensor = ltx_aduc_pipeline.decode_to_pixels(final_latents)
            if pixel_tensor is None:
                raise RuntimeError("LTX client failed to decode the latent tensor.")
            logging.info(f"Orchestrator received pixel tensor with shape: {pixel_tensor.shape}")

            # =================================================================
            # --- ETAPA 4: TAREFA FINAL - CODIFICAR PARA MP4 ---
            # =================================================================
            video_filename = f"{output_filename_base}_{int(time.time())}_{used_seed}.mp4"
            output_path = f"{self.output_dir}/{video_filename}"
            
            logging.info(f"Orchestrator executing final task: saving tensor to MP4 at {output_path}")
            video_encode_tool_singleton.save_video_from_tensor(
                pixel_5d=pixel_tensor,
                path=output_path,
                fps=24
            )

            total_time = time.time() - t0
            logging.info(f"🚀🚀🚀 Orchestrator job complete! Video saved to {output_path}. Total time: {total_time:.2f}s")
            
            return output_path

        except Exception:
            logging.error("ORCHESTRATOR FAILED! A critical error occurred during the workflow.", exc_info=True)
            return None

# ==============================================================================
# --- INSTÂNCIA SINGLETON DO ORQUESTRADOR ---
# ==============================================================================
ltx_aduc_orchestrator = LtxAducOrchestrator()