|
|
import os |
|
|
from typing import List, Tuple |
|
|
|
|
|
PWD = os.path.dirname(__file__) |
|
|
|
|
|
import subprocess |
|
|
|
|
|
subprocess.run("pip install flash-attn --no-build-isolation", env={"FLASH_ATTENTION_SKIP_CUDA_BUILD": "TRUE"}, shell=True) |
|
|
|
|
|
try: |
|
|
import os |
|
|
|
|
|
from huggingface_hub import login |
|
|
|
|
|
|
|
|
hf_token = os.environ["HF_TOKEN"] |
|
|
if hf_token: |
|
|
login(token=hf_token) |
|
|
print("✅ Authenticated with Hugging Face") |
|
|
else: |
|
|
print("No HF_TOKEN found, trying without authentication...") |
|
|
except Exception as e: |
|
|
print(f"Authentication failed: {e}") |
|
|
|
|
|
|
|
|
from download_checkpoints import main as download_checkpoints |
|
|
|
|
|
os.makedirs("./checkpoints", exist_ok=True) |
|
|
download_checkpoints(hf_token="", output_dir="./checkpoints", model="7b_av") |
|
|
|
|
|
os.environ["TOKENIZERS_PARALLELISM"] = "false" |
|
|
|
|
|
import copy |
|
|
import json |
|
|
import random |
|
|
from io import BytesIO |
|
|
|
|
|
import gradio as gr |
|
|
import torch |
|
|
from cosmos_transfer1.checkpoints import ( |
|
|
BASE_7B_CHECKPOINT_AV_SAMPLE_PATH, |
|
|
BASE_7B_CHECKPOINT_PATH, |
|
|
EDGE2WORLD_CONTROLNET_DISTILLED_CHECKPOINT_PATH, |
|
|
) |
|
|
from cosmos_transfer1.diffusion.inference.inference_utils import ( |
|
|
validate_controlnet_specs, |
|
|
) |
|
|
from cosmos_transfer1.diffusion.inference.preprocessors import Preprocessors |
|
|
from cosmos_transfer1.diffusion.inference.world_generation_pipeline import ( |
|
|
DiffusionControl2WorldGenerationPipeline, |
|
|
DistilledControl2WorldGenerationPipeline, |
|
|
) |
|
|
from cosmos_transfer1.utils import log, misc |
|
|
from cosmos_transfer1.utils.io import read_prompts_from_file, save_video |
|
|
|
|
|
from helper import parse_arguments |
|
|
|
|
|
torch.enable_grad(False) |
|
|
torch.serialization.add_safe_globals([BytesIO]) |
|
|
|
|
|
|
|
|
def inference(cfg, control_inputs) -> Tuple[List[str], List[str]]: |
|
|
video_paths = [] |
|
|
prompt_paths = [] |
|
|
|
|
|
control_inputs = validate_controlnet_specs(cfg, control_inputs) |
|
|
misc.set_random_seed(cfg.seed) |
|
|
|
|
|
device_rank = 0 |
|
|
process_group = None |
|
|
if cfg.num_gpus > 1: |
|
|
from cosmos_transfer1.utils import distributed |
|
|
from megatron.core import parallel_state |
|
|
|
|
|
distributed.init() |
|
|
parallel_state.initialize_model_parallel(context_parallel_size=cfg.num_gpus) |
|
|
process_group = parallel_state.get_context_parallel_group() |
|
|
|
|
|
device_rank = distributed.get_rank(process_group) |
|
|
|
|
|
preprocessors = Preprocessors() |
|
|
|
|
|
if cfg.use_distilled: |
|
|
assert not cfg.is_av_sample |
|
|
checkpoint = EDGE2WORLD_CONTROLNET_DISTILLED_CHECKPOINT_PATH |
|
|
pipeline = DistilledControl2WorldGenerationPipeline( |
|
|
checkpoint_dir=cfg.checkpoint_dir, |
|
|
checkpoint_name=checkpoint, |
|
|
offload_network=cfg.offload_diffusion_transformer, |
|
|
offload_text_encoder_model=cfg.offload_text_encoder_model, |
|
|
offload_guardrail_models=cfg.offload_guardrail_models, |
|
|
guidance=cfg.guidance, |
|
|
num_steps=cfg.num_steps, |
|
|
fps=cfg.fps, |
|
|
seed=cfg.seed, |
|
|
num_input_frames=cfg.num_input_frames, |
|
|
control_inputs=control_inputs, |
|
|
sigma_max=cfg.sigma_max, |
|
|
blur_strength=cfg.blur_strength, |
|
|
canny_threshold=cfg.canny_threshold, |
|
|
upsample_prompt=cfg.upsample_prompt, |
|
|
offload_prompt_upsampler=cfg.offload_prompt_upsampler, |
|
|
process_group=process_group, |
|
|
) |
|
|
else: |
|
|
checkpoint = BASE_7B_CHECKPOINT_AV_SAMPLE_PATH if cfg.is_av_sample else BASE_7B_CHECKPOINT_PATH |
|
|
|
|
|
|
|
|
pipeline = DiffusionControl2WorldGenerationPipeline( |
|
|
checkpoint_dir=cfg.checkpoint_dir, |
|
|
checkpoint_name=checkpoint, |
|
|
offload_network=cfg.offload_diffusion_transformer, |
|
|
offload_text_encoder_model=cfg.offload_text_encoder_model, |
|
|
offload_guardrail_models=cfg.offload_guardrail_models, |
|
|
guidance=cfg.guidance, |
|
|
num_steps=cfg.num_steps, |
|
|
fps=cfg.fps, |
|
|
seed=cfg.seed, |
|
|
num_input_frames=cfg.num_input_frames, |
|
|
control_inputs=control_inputs, |
|
|
sigma_max=cfg.sigma_max, |
|
|
blur_strength=cfg.blur_strength, |
|
|
canny_threshold=cfg.canny_threshold, |
|
|
upsample_prompt=cfg.upsample_prompt, |
|
|
offload_prompt_upsampler=cfg.offload_prompt_upsampler, |
|
|
process_group=process_group, |
|
|
) |
|
|
|
|
|
if cfg.batch_input_path: |
|
|
log.info(f"Reading batch inputs from path: {cfg.batch_input_path}") |
|
|
prompts = read_prompts_from_file(cfg.batch_input_path) |
|
|
else: |
|
|
|
|
|
prompts = [{"prompt": cfg.prompt, "visual_input": cfg.input_video_path}] |
|
|
|
|
|
batch_size = cfg.batch_size if hasattr(cfg, "batch_size") else 1 |
|
|
if any("upscale" in control_input for control_input in control_inputs) and batch_size > 1: |
|
|
batch_size = 1 |
|
|
log.info("Setting batch_size=1 as upscale does not support batch generation") |
|
|
os.makedirs(cfg.video_save_folder, exist_ok=True) |
|
|
for batch_start in range(0, len(prompts), batch_size): |
|
|
|
|
|
batch_prompts = prompts[batch_start : batch_start + batch_size] |
|
|
actual_batch_size = len(batch_prompts) |
|
|
|
|
|
batch_prompt_texts = [p.get("prompt", None) for p in batch_prompts] |
|
|
batch_video_paths = [p.get("visual_input", None) for p in batch_prompts] |
|
|
|
|
|
batch_control_inputs = [] |
|
|
for i, input_dict in enumerate(batch_prompts): |
|
|
current_prompt = input_dict.get("prompt", None) |
|
|
current_video_path = input_dict.get("visual_input", None) |
|
|
|
|
|
if cfg.batch_input_path: |
|
|
video_save_subfolder = os.path.join(cfg.video_save_folder, f"video_{batch_start+i}") |
|
|
os.makedirs(video_save_subfolder, exist_ok=True) |
|
|
else: |
|
|
video_save_subfolder = cfg.video_save_folder |
|
|
|
|
|
current_control_inputs = copy.deepcopy(control_inputs) |
|
|
if "control_overrides" in input_dict: |
|
|
for hint_key, override in input_dict["control_overrides"].items(): |
|
|
if hint_key in current_control_inputs: |
|
|
current_control_inputs[hint_key].update(override) |
|
|
else: |
|
|
log.warning(f"Ignoring unknown control key in override: {hint_key}") |
|
|
|
|
|
|
|
|
log.info("running preprocessor") |
|
|
preprocessors( |
|
|
current_video_path, |
|
|
current_prompt, |
|
|
current_control_inputs, |
|
|
video_save_subfolder, |
|
|
cfg.regional_prompts if hasattr(cfg, "regional_prompts") else None, |
|
|
) |
|
|
batch_control_inputs.append(current_control_inputs) |
|
|
|
|
|
regional_prompts = [] |
|
|
region_definitions = [] |
|
|
if hasattr(cfg, "regional_prompts") and cfg.regional_prompts: |
|
|
log.info(f"regional_prompts: {cfg.regional_prompts}") |
|
|
for regional_prompt in cfg.regional_prompts: |
|
|
regional_prompts.append(regional_prompt["prompt"]) |
|
|
if "region_definitions_path" in regional_prompt: |
|
|
log.info(f"region_definitions_path: {regional_prompt['region_definitions_path']}") |
|
|
region_definition_path = regional_prompt["region_definitions_path"] |
|
|
if isinstance(region_definition_path, str) and region_definition_path.endswith(".json"): |
|
|
with open(region_definition_path, "r") as f: |
|
|
region_definitions_json = json.load(f) |
|
|
region_definitions.extend(region_definitions_json) |
|
|
else: |
|
|
region_definitions.append(region_definition_path) |
|
|
|
|
|
if hasattr(pipeline, "regional_prompts"): |
|
|
pipeline.regional_prompts = regional_prompts |
|
|
if hasattr(pipeline, "region_definitions"): |
|
|
pipeline.region_definitions = region_definitions |
|
|
|
|
|
|
|
|
batch_outputs = pipeline.generate( |
|
|
prompt=batch_prompt_texts, |
|
|
video_path=batch_video_paths, |
|
|
negative_prompt=cfg.negative_prompt, |
|
|
control_inputs=batch_control_inputs, |
|
|
save_folder=video_save_subfolder, |
|
|
batch_size=actual_batch_size, |
|
|
) |
|
|
if batch_outputs is None: |
|
|
log.critical("Guardrail blocked generation for entire batch.") |
|
|
continue |
|
|
|
|
|
videos, final_prompts = batch_outputs |
|
|
for i, (video, prompt) in enumerate(zip(videos, final_prompts)): |
|
|
if cfg.batch_input_path: |
|
|
video_save_subfolder = os.path.join(cfg.video_save_folder, f"video_{batch_start+i}") |
|
|
video_save_path = os.path.join(video_save_subfolder, "output.mp4") |
|
|
prompt_save_path = os.path.join(video_save_subfolder, "prompt.txt") |
|
|
else: |
|
|
video_save_path = os.path.join(cfg.video_save_folder, f"{cfg.video_save_name}.mp4") |
|
|
prompt_save_path = os.path.join(cfg.video_save_folder, f"{cfg.video_save_name}.txt") |
|
|
|
|
|
if device_rank == 0: |
|
|
os.makedirs(os.path.dirname(video_save_path), exist_ok=True) |
|
|
save_video( |
|
|
video=video, |
|
|
fps=cfg.fps, |
|
|
H=video.shape[1], |
|
|
W=video.shape[2], |
|
|
video_save_quality=5, |
|
|
video_save_path=video_save_path, |
|
|
) |
|
|
video_paths.append(video_save_path) |
|
|
|
|
|
|
|
|
with open(prompt_save_path, "wb") as f: |
|
|
f.write(prompt.encode("utf-8")) |
|
|
|
|
|
prompt_paths.append(prompt_save_path) |
|
|
|
|
|
log.info(f"Saved video to {video_save_path}") |
|
|
log.info(f"Saved prompt to {prompt_save_path}") |
|
|
|
|
|
|
|
|
if cfg.num_gpus > 1: |
|
|
parallel_state.destroy_model_parallel() |
|
|
import torch.distributed as dist |
|
|
|
|
|
dist.destroy_process_group() |
|
|
|
|
|
return video_paths, prompt_paths |
|
|
|
|
|
|
|
|
def generate_video( |
|
|
hdmap_video_input, |
|
|
lidar_video_input, |
|
|
prompt, |
|
|
negative_prompt="The video captures a series of frames showing ugly scenes, static with no motion, motion blur, over-saturation, shaky footage, low resolution, grainy texture, pixelated images, poorly lit areas, underexposed and overexposed scenes, poor color balance, washed out colors, choppy sequences, jerky movements, low frame rate, artifacting, color banding, unnatural transitions, outdated special effects, fake elements, unconvincing visuals, poorly edited content, jump cuts, visual noise, and flickering. Overall, the video is of poor quality.", |
|
|
seed=42, |
|
|
randomize_seed=False, |
|
|
progress=gr.Progress(track_tqdm=True), |
|
|
): |
|
|
if randomize_seed: |
|
|
actual_seed = random.randint(0, 1000000) |
|
|
else: |
|
|
actual_seed = seed |
|
|
|
|
|
args, control_inputs = parse_arguments( |
|
|
controlnet_specs_in={ |
|
|
"hdmap": {"control_weight": 0.3, "input_control": hdmap_video_input}, |
|
|
"lidar": {"control_weight": 0.7, "input_control": lidar_video_input}, |
|
|
}, |
|
|
checkpoint_dir="./cosmos-transfer1/checkpoints", |
|
|
prompt=prompt, |
|
|
negative_prompt=negative_prompt, |
|
|
sigma_max=80, |
|
|
offload_text_encoder_model=True, |
|
|
is_av_sample=True, |
|
|
num_gpus=1, |
|
|
seed=seed, |
|
|
) |
|
|
videos, prompts = inference(args, control_inputs) |
|
|
|
|
|
video = videos[0] |
|
|
return video, video, actual_seed |
|
|
|
|
|
|
|
|
|
|
|
with gr.Blocks() as demo: |
|
|
gr.Markdown( |
|
|
""" |
|
|
# Cosmos-Transfer1-7B-Sample-AV |
|
|
""" |
|
|
) |
|
|
with gr.Row(): |
|
|
with gr.Column(): |
|
|
hdmap_input = gr.Video(label="Input HD Map Video", format="mp4") |
|
|
lidar_input = gr.Video(label="Input LiDAR Video", format="mp4") |
|
|
|
|
|
prompt_input = gr.Textbox( |
|
|
label="Prompt", |
|
|
lines=5, |
|
|
value="A close-up shot captures a vibrant yellow scrubber vigorously working on a grimy plate, its bristles moving in circular motions to lift stubborn grease and food residue. The dish, once covered in remnants of a hearty meal, gradually reveals its original glossy surface. Suds form and bubble around the scrubber, creating a satisfying visual of cleanliness in progress. The sound of scrubbing fills the air, accompanied by the gentle clinking of the dish against the sink. As the scrubber continues its task, the dish transforms, gleaming under the bright kitchen lights, symbolizing the triumph of cleanliness over mess.", |
|
|
placeholder="Enter your descriptive prompt here...", |
|
|
) |
|
|
|
|
|
negative_prompt_input = gr.Textbox( |
|
|
label="Negative Prompt", |
|
|
lines=3, |
|
|
value="The video captures a series of frames showing ugly scenes, static with no motion, motion blur, over-saturation, shaky footage, low resolution, grainy texture, pixelated images, poorly lit areas, underexposed and overexposed scenes, poor color balance, washed out colors, choppy sequences, jerky movements, low frame rate, artifacting, color banding, unnatural transitions, outdated special effects, fake elements, unconvincing visuals, poorly edited content, jump cuts, visual noise, and flickering. Overall, the video is of poor quality.", |
|
|
placeholder="Enter what you DON'T want to see in the image...", |
|
|
) |
|
|
|
|
|
with gr.Row(): |
|
|
randomize_seed_checkbox = gr.Checkbox(label="Randomize Seed", value=True) |
|
|
seed_input = gr.Slider(minimum=0, maximum=1000000, value=1, step=1, label="Seed") |
|
|
|
|
|
generate_button = gr.Button("Generate Image") |
|
|
|
|
|
with gr.Column(): |
|
|
output_video = gr.Video(label="Generated Video", format="mp4") |
|
|
output_file = gr.File(label="Download Video") |
|
|
|
|
|
generate_button.click( |
|
|
fn=generate_video, |
|
|
inputs=[hdmap_input, lidar_input, prompt_input, negative_prompt_input, seed_input, randomize_seed_checkbox], |
|
|
outputs=[output_video, output_file, seed_input], |
|
|
) |
|
|
|
|
|
if __name__ == "__main__": |
|
|
demo.launch() |
|
|
|