|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import sys |
|
|
import os |
|
|
|
|
|
script_dir = os.path.dirname(os.path.abspath(__file__)) |
|
|
engineers_path = os.path.join(script_dir, "engineers") |
|
|
|
|
|
print(f"Script directory: {script_dir}") |
|
|
print(f"Engineers path: {engineers_path}") |
|
|
print(f"sys.path before import: {sys.path}") |
|
|
|
|
|
sys.path.insert(0, engineers_path) |
|
|
|
|
|
print(f"sys.path after insert: {sys.path}") |
|
|
|
|
|
try: |
|
|
from engineers.deformes4D import Deformes4DEngine |
|
|
print("Module deformes4D imported successfully!") |
|
|
except ModuleNotFoundError as e: |
|
|
print(f"Error importing deformes4D: {e}") |
|
|
sys.exit(1) |
|
|
|
|
|
try: |
|
|
from engineers.deformes3D import deformes3d_engine_singleton |
|
|
print("Module deformes3D imported successfully!") |
|
|
except ModuleNotFoundError as e: |
|
|
print(f"Error importing deformes3D: {e}") |
|
|
sys.exit(1) |
|
|
|
|
|
|
|
|
import logging |
|
|
from typing import List, Dict, Any, Generator, Tuple |
|
|
|
|
|
import gradio as gr |
|
|
from PIL import Image, ImageOps |
|
|
|
|
|
|
|
|
logger = logging.getLogger(__name__) |
|
|
|
|
|
class AducDirector: |
|
|
""" |
|
|
Represents the Scene Director, responsible for managing the production state. |
|
|
Acts as the "score" for the orchestra, keeping track of all generated artifacts |
|
|
(script, keyframes, etc.) during the creative process. |
|
|
""" |
|
|
def __init__(self, workspace_dir: str): |
|
|
self.workspace_dir = workspace_dir |
|
|
os.makedirs(self.workspace_dir, exist_ok=True) |
|
|
self.state: Dict[str, Any] = {} |
|
|
logger.info(f"The stage is set. Workspace at '{self.workspace_dir}'.") |
|
|
|
|
|
def update_state(self, key: str, value: Any) -> None: |
|
|
logger.info(f"Notating on the score: State '{key}' updated.") |
|
|
self.state[key] = value |
|
|
|
|
|
def get_state(self, key: str, default: Any = None) -> Any: |
|
|
return self.state.get(key, default) |
|
|
|
|
|
class AducOrchestrator: |
|
|
""" |
|
|
Implements the Maestro (Γ), the central orchestration layer of the ADUC architecture. |
|
|
It does not execute AI tasks directly but delegates each step of the creative |
|
|
process (scriptwriting, art direction, cinematography) to the appropriate Specialists. |
|
|
""" |
|
|
def __init__(self, workspace_dir: str): |
|
|
self.director = AducDirector(workspace_dir) |
|
|
self.editor = Deformes4DEngine(workspace_dir) |
|
|
self.painter = deformes3d_engine_singleton |
|
|
logger.info("ADUC Maestro is on the podium. Musicians (specialists) are ready.") |
|
|
|
|
|
def process_image_for_story(self, image_path: str, size: int, filename: str) -> str: |
|
|
""" |
|
|
Pre-processes a reference image, standardizing it for use by the Specialists. |
|
|
""" |
|
|
img = Image.open(image_path).convert("RGB") |
|
|
img_square = ImageOps.fit(img, (size, size), Image.Resampling.LANCZOS) |
|
|
processed_path = os.path.join(self.director.workspace_dir, filename) |
|
|
img_square.save(processed_path) |
|
|
logger.info(f"Reference image processed and saved to: {processed_path}") |
|
|
return processed_path |
|
|
|
|
|
|
|
|
|
|
|
def task_generate_storyboard(self, prompt: str, num_keyframes: int, ref_image_paths: List[str], |
|
|
progress: gr.Progress) -> Tuple[List[str], str, Any]: |
|
|
""" |
|
|
Delegates the task of creating the storyboard to the Scriptwriter (deformes2D_thinker). |
|
|
""" |
|
|
logger.info(f"Act 1, Scene 1: Script. Instructing Scriptwriter to create {num_keyframes} scenes.") |
|
|
progress(0.2, desc="Consulting AI Scriptwriter...") |
|
|
|
|
|
storyboard = deformes2d_thinker_singleton.generate_storyboard(prompt, num_keyframes, ref_image_paths) |
|
|
|
|
|
logger.info(f"Scriptwriter returned the score: {storyboard}") |
|
|
self.director.update_state("storyboard", storyboard) |
|
|
self.director.update_state("processed_ref_paths", ref_image_paths) |
|
|
return storyboard, ref_image_paths[0], gr.update(visible=True, open=True) |
|
|
|
|
|
def task_select_keyframes(self, storyboard: List[str], base_ref_paths: List[str], |
|
|
pool_ref_paths: List[str]) -> List[str]: |
|
|
""" |
|
|
Delegates to the Photographer (deformes2D_thinker) the task of selecting keyframes. |
|
|
""" |
|
|
logger.info(f"Act 1, Scene 2 (Photographer Mode): Instructing Photographer to select {len(storyboard)} keyframes.") |
|
|
selected_paths = deformes2d_thinker_singleton.select_keyframes_from_pool(storyboard, base_ref_paths, pool_ref_paths) |
|
|
logger.info(f"Photographer selected the following scenes: {[os.path.basename(p) for p in selected_paths]}") |
|
|
self.director.update_state("keyframes", selected_paths) |
|
|
return selected_paths |
|
|
|
|
|
def task_generate_keyframes(self, storyboard: List[str], initial_ref_path: str, global_prompt: str, |
|
|
keyframe_resolution: int, progress_callback_factory=None) -> List[str]: |
|
|
""" |
|
|
Delegates to the Art Director (Deformes3DEngine) the task of generating keyframes. |
|
|
""" |
|
|
logger.info("Act 1, Scene 2 (Art Director Mode): Delegating to Art Director.") |
|
|
general_ref_paths = self.director.get_state("processed_ref_paths", []) |
|
|
|
|
|
final_keyframes = self.painter.generate_keyframes_from_storyboard( |
|
|
storyboard=storyboard, |
|
|
initial_ref_path=initial_ref_path, |
|
|
global_prompt=global_prompt, |
|
|
keyframe_resolution=keyframe_resolution, |
|
|
general_ref_paths=general_ref_paths, |
|
|
progress_callback_factory=progress_callback_factory |
|
|
) |
|
|
self.director.update_state("keyframes", final_keyframes) |
|
|
logger.info("Maestro: Art Director has completed keyframe generation.") |
|
|
return final_keyframes |
|
|
|
|
|
|
|
|
|
|
|
def task_produce_original_movie(self, keyframes: List[str], global_prompt: str, seconds_per_fragment: float, |
|
|
trim_percent: int, handler_strength: float, |
|
|
destination_convergence_strength: float, |
|
|
guidance_scale: float, stg_scale: float, inference_steps: int, |
|
|
video_resolution: int, use_continuity_director: bool, |
|
|
progress: gr.Progress) -> Dict[str, Any]: |
|
|
""" |
|
|
Delegates the production of the original master video to the Deformes4DEngine. |
|
|
""" |
|
|
logger.info("Maestro: Delegating production of the original movie to Deformes4DEngine.") |
|
|
storyboard = self.director.get_state("storyboard", []) |
|
|
|
|
|
result = self.editor.generate_original_movie( |
|
|
keyframes=keyframes, |
|
|
global_prompt=global_prompt, |
|
|
storyboard=storyboard, |
|
|
seconds_per_fragment=seconds_per_fragment, |
|
|
trim_percent=trim_percent, |
|
|
handler_strength=handler_strength, |
|
|
destination_convergence_strength=destination_convergence_strength, |
|
|
video_resolution=video_resolution, |
|
|
use_continuity_director=use_continuity_director, |
|
|
guidance_scale=guidance_scale, |
|
|
stg_scale=stg_scale, |
|
|
num_inference_steps=inference_steps, |
|
|
progress=progress |
|
|
) |
|
|
|
|
|
self.director.update_state("final_video_path", result["final_path"]) |
|
|
self.director.update_state("latent_paths", result["latent_paths"]) |
|
|
logger.info("Maestro: Original movie production complete.") |
|
|
return result |
|
|
|
|
|
def task_run_latent_upscaler(self, latent_paths: List[str], chunk_size: int, progress: gr.Progress) -> Generator[Dict[str, Any], None, None]: |
|
|
""" |
|
|
Orchestrates the latent upscaling task. |
|
|
""" |
|
|
logger.info(f"Maestro: Delegating latent upscaling task for {len(latent_paths)} fragments.") |
|
|
for update in self.editor.upscale_latents_and_create_video( |
|
|
latent_paths=latent_paths, |
|
|
chunk_size=chunk_size, |
|
|
progress=progress |
|
|
): |
|
|
if "final_path" in update and update["final_path"]: |
|
|
self.director.update_state("final_video_path", update["final_path"]) |
|
|
yield update |
|
|
break |
|
|
logger.info("Maestro: Latent upscaling complete.") |
|
|
|
|
|
def task_run_hd_mastering(self, source_video_path: str, model_version: str, steps: int, prompt: str, progress: gr.Progress) -> Generator[Dict[str, Any], None, None]: |
|
|
""" |
|
|
Orchestrates the HD mastering task. |
|
|
""" |
|
|
logger.info(f"Maestro: Delegating HD mastering task using SeedVR {model_version}.") |
|
|
for update in self.editor.master_video_hd( |
|
|
source_video_path=source_video_path, |
|
|
model_version=model_version, |
|
|
steps=steps, |
|
|
prompt=prompt, |
|
|
progress=progress |
|
|
): |
|
|
if "final_path" in update and update["final_path"]: |
|
|
self.director.update_state("final_video_path", update["final_path"]) |
|
|
yield update |
|
|
break |
|
|
logger.info("Maestro: HD mastering complete.") |
|
|
|
|
|
def task_run_audio_generation(self, source_video_path: str, audio_prompt: str, progress: gr.Progress) -> Generator[Dict[str, Any], None, None]: |
|
|
""" |
|
|
Orchestrates the audio generation task. |
|
|
""" |
|
|
logger.info(f"Maestro: Delegating audio generation task.") |
|
|
for update in self.editor.generate_audio_for_final_video( |
|
|
source_video_path=source_video_path, |
|
|
audio_prompt=audio_prompt, |
|
|
progress=progress |
|
|
): |
|
|
if "final_path" in update and update["final_path"]: |
|
|
self.director.update_state("final_video_path", update["final_path"]) |
|
|
yield update |
|
|
break |
|
|
logger.info("Maestro: Audio generation complete.") |