-
Notifications
You must be signed in to change notification settings - Fork 6.7k
Add LTX 2.0 Video Pipelines #12915
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+9,513
−0
Merged
Add LTX 2.0 Video Pipelines #12915
Changes from 73 commits
Commits
Show all changes
103 commits
Select commit
Hold shift + click to select a range
aa602ac
Initial LTX 2.0 transformer implementation
dg845 b3096c3
Add tests for LTX 2 transformer model
dg845 980591d
Get LTX 2 transformer tests working
dg845 e100b8f
Rename LTX 2 compile test class to have LTX2
dg845 780fb61
Remove RoPE debug print statements
dg845 5765759
Get LTX 2 transformer compile tests passing
dg845 aeecc4d
Fix LTX 2 transformer shape errors
dg845 a5f2d2d
Initial script to convert LTX 2 transformer to diffusers
dg845 d86f89d
Add more LTX 2 transformer audio arguments
dg845 57a8b9c
Allow LTX 2 transformer to be loaded from local path for conversion
dg845 a7bc052
Improve dummy inputs and add test for LTX 2 transformer consistency
dg845 bda3ff1
Fix LTX 2 transformer bugs so consistency test passes
dg845 269cf7b
Initial implementation of LTX 2.0 video VAE
dg845 baf23e2
Explicitly specify temporal and spatial VAE scale factors when conver…
dg845 5b950d6
Add initial LTX 2.0 video VAE tests
dg845 491aae0
Add initial LTX 2.0 video VAE tests (part 2)
dg845 a748975
Get diffusers implementation on par with official LTX 2.0 video VAE i…
dg845 c6a11a5
Initial LTX 2.0 vocoder implementation
dg845 8bfeb4a
Merge pull request #3 from huggingface/ltx-2-vocoder
dg845 b1cf6ff
Merge pull request #2 from huggingface/ltx-2-video-vae
dg845 6c56954
Use RMSNorm implementation closer to original for LTX 2.0 video VAE
dg845 b34ddb1
start audio decoder.
sayakpaul f4c2435
init registration.
sayakpaul e54cd6b
up
sayakpaul 907896d
simplify and clean up
sayakpaul 4904fd6
up
sayakpaul 0028955
Initial LTX 2.0 text encoder implementation
dg845 d0f9cda
Rough initial LTX 2.0 pipeline implementation
dg845 5f0f2a0
up
sayakpaul 58257eb
up
sayakpaul 059999a
up
sayakpaul 8134da6
up
sayakpaul 409d651
resolve conflicts.
sayakpaul 7bb4cf7
Merge pull request #5 from huggingface/audio-decoder
dg845 5f7e43d
Add imports for LTX 2.0 Audio VAE
dg845 d303e2a
Conversion script for LTX 2.0 Audio VAE Decoder
dg845 ae3b6e7
Merge branch 'ltx-2-transformer' into ltx-2-t2v-pipeline
dg845 54bfc5d
Add Audio VAE logic to T2V pipeline
dg845 6e6ce20
Duplicate scheduler for audio latents
dg845 cbb10b8
Support num_videos_per_prompt for prompt embeddings
dg845 595f485
LTX 2.0 scheduler and full pipeline conversion
dg845 3bf7369
Add script to test full LTX2Pipeline T2V inference
dg845 fa7d9f7
Fix pipeline return bugs
dg845 a56cf23
Add LTX 2 text encoder and vocoder to ltx2 subdirectory __init__
dg845 90edc6a
Fix more bugs in LTX2Pipeline.__call__
dg845 1484c43
Improve CPU offload support
dg845 f9b9476
Fix pipeline audio VAE decoding dtype bug
dg845 e89d9c1
Fix video shape error in full pipeline test script
dg845 b5891b1
Get LTX 2 T2V pipeline to produce reasonable outputs
dg845 0c41297
Merge pull request #4 from huggingface/ltx-2-t2v-pipeline
dg845 581f21c
Make LTX 2.0 scheduler more consistent with original code
dg845 e1f0b7e
Fix typo when applying scheduler fix in T2V inference script
dg845 280e347
Refactor Audio VAE to be simpler and remove helpers (#7)
sayakpaul 46822c4
Add support for I2V (#8)
sayakpaul 6a236a2
Merge branch 'ltx-2-transformer' into make-scheduler-consistent
dg845 bd607b9
Denormalize audio latents in I2V pipeline (analogous to T2V change) (…
dg845 d3f10fe
test i2v.
sayakpaul aae70b9
Merge pull request #10 from huggingface/make-scheduler-consistent
dg845 caae167
Move Video and Audio Text Encoder Connectors to Transformer (#12)
dg845 0be4f31
up (#19)
sayakpaul c5b52d6
address initial feedback from lightricks team (#16)
sayakpaul 2fa4f84
When using split RoPE, make sure that the output dtype is same as inp…
dg845 bff9891
Fix apply split RoPE shape error when reshaping x to 4D
dg845 cb50cac
Add export_utils file for exporting LTX 2.0 videos with audio
dg845 ce9da5d
Merge pull request #20 from huggingface/video-export-utils-file
dg845 93a417f
Tests for T2V and I2V (#6)
sayakpaul 9b8788c
resolve conflicts.
sayakpaul c039c87
up
sayakpaul 550eca3
use export util funcs.
sayakpaul ef19911
Point original checkpoint to LTX 2.0 official checkpoint
dg845 ace2ee9
Allow the I2V pipeline to accept image URLs
dg845 dd81242
make style and make quality
dg845 2fc5789
Merge branch 'main' into ltx-2-transformer
sayakpaul 57ead0b
remove function map.
sayakpaul c39f1b8
remove args.
sayakpaul bdcf23e
update docs.
sayakpaul 61e0fb4
update doc entries.
sayakpaul 8c5ab1f
disable ltx2_consistency test
sayakpaul 64b48c1
Merge branch 'main' into ltx-2-transformer
sayakpaul 5e0cf2b
Simplify LTX 2 RoPE forward by removing coords is None logic
dg845 d01a242
make style and make quality
dg845 79cf6d7
Support LTX 2.0 audio VAE encoder
dg845 cc28cf7
Merge branch 'main' into ltx-2-transformer
sayakpaul 91ee2dd
resolve conflicts
sayakpaul 5269ee5
Merge branch 'ltx-2-transformer' of github.com:huggingface/diffusers …
dg845 a17f5cb
Apply suggestions from code review
dg845 964f106
Remove print statement in audio VAE
dg845 4dfe509
up
sayakpaul 249ae1f
Merge branch 'main' into ltx-2-transformer
sayakpaul 040c118
Fix bug when calculating audio RoPE coords
dg845 44925cb
Ltx 2 latent upsample pipeline (#12922)
sayakpaul 5e50046
Fix latent upsampler filename in LTX 2 conversion script
dg845 2b85b93
Add latent upsample pipeline to LTX 2 docs
dg845 40ee3e3
Add dummy objects for LTX 2 latent upsample pipeline
dg845 99ff722
Set default FPS to official LTX 2 ckpt default of 24.0
dg845 165b945
Set default CFG scale to official LTX 2 ckpt default of 4.0
dg845 1a4ae58
Update LTX 2 pipeline example docstrings
dg845 b4d33df
make style and make quality
dg845 724afee
Remove LTX 2 test scripts
dg845 d24faa7
Fix LTX 2 upsample pipeline example docstring
dg845 353f0db
Add logic to convert and save a LTX 2 upsampling pipeline
dg845 0c9e4e2
Merge branch 'main' into ltx-2-transformer
sayakpaul f85b969
Document LTX2VideoTransformer3DModel forward pass
dg845 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,108 @@ | ||
| import argparse | ||
| import os | ||
|
|
||
| import torch | ||
|
|
||
| from diffusers import LTX2Pipeline | ||
| from diffusers.pipelines.ltx2.export_utils import encode_video | ||
|
|
||
|
|
||
| def parse_args(): | ||
| parser = argparse.ArgumentParser() | ||
|
|
||
| parser.add_argument("--model_id", type=str, default="diffusers-internal-dev/new-ltx-model") | ||
| parser.add_argument("--revision", type=str, default="main") | ||
|
|
||
| parser.add_argument( | ||
| "--prompt", | ||
| type=str, | ||
| default="A video of a dog dancing to energetic electronic dance music", | ||
| ) | ||
| parser.add_argument( | ||
| "--negative_prompt", | ||
| type=str, | ||
| default=( | ||
| "blurry, out of focus, overexposed, underexposed, low contrast, washed out colors, excessive noise, " | ||
| "grainy texture, poor lighting, flickering, motion blur, distorted proportions, unnatural skin tones, " | ||
| "deformed facial features, asymmetrical face, missing facial features, extra limbs, disfigured hands, " | ||
| "wrong hand count, artifacts around text, inconsistent perspective, camera shake, incorrect depth of " | ||
| "field, background too sharp, background clutter, distracting reflections, harsh shadows, inconsistent " | ||
| "lighting direction, color banding, cartoonish rendering, 3D CGI look, unrealistic materials, uncanny " | ||
| "valley effect, incorrect ethnicity, wrong gender, exaggerated expressions, wrong gaze direction, " | ||
| "mismatched lip sync, silent or muted audio, distorted voice, robotic voice, echo, background noise, " | ||
| "off-sync audio,incorrect dialogue, added dialogue, repetitive speech, jittery movement, awkward " | ||
| "pauses, incorrect timing, unnatural transitions, inconsistent framing, tilted camera, flat lighting, " | ||
| "inconsistent tone, cinematic oversaturation, stylized filters, or AI artifacts." | ||
| ), | ||
| ) | ||
|
|
||
| parser.add_argument("--num_inference_steps", type=int, default=40) | ||
| parser.add_argument("--height", type=int, default=512) | ||
| parser.add_argument("--width", type=int, default=768) | ||
| parser.add_argument("--num_frames", type=int, default=121) | ||
| parser.add_argument("--frame_rate", type=float, default=25.0) | ||
| parser.add_argument("--guidance_scale", type=float, default=3.0) | ||
| parser.add_argument("--seed", type=int, default=42) | ||
|
|
||
| parser.add_argument("--device", type=str, default="cuda:0") | ||
| parser.add_argument("--dtype", type=str, default="bf16") | ||
| parser.add_argument("--cpu_offload", action="store_true") | ||
|
|
||
| parser.add_argument( | ||
| "--output_dir", | ||
| type=str, | ||
| default="/home/daniel_gu/samples", | ||
| help="Output directory for generated video", | ||
| ) | ||
| parser.add_argument( | ||
| "--output_filename", | ||
| type=str, | ||
| default="ltx2_sample_video.mp4", | ||
| help="Filename of the exported generated video", | ||
| ) | ||
|
|
||
| args = parser.parse_args() | ||
| args.dtype = torch.bfloat16 if args.dtype == "bf16" else torch.float32 | ||
| return args | ||
|
|
||
|
|
||
| def main(args): | ||
| pipeline = LTX2Pipeline.from_pretrained( | ||
| args.model_id, | ||
| revision=args.revision, | ||
| torch_dtype=args.dtype, | ||
| ) | ||
| pipeline.to(device=args.device) | ||
| if args.cpu_offload: | ||
| pipeline.enable_model_cpu_offload() | ||
|
|
||
| video, audio = pipeline( | ||
| prompt=args.prompt, | ||
| negative_prompt=args.negative_prompt, | ||
| height=args.height, | ||
| width=args.width, | ||
| num_frames=args.num_frames, | ||
| frame_rate=args.frame_rate, | ||
| num_inference_steps=args.num_inference_steps, | ||
| guidance_scale=args.guidance_scale, | ||
| generator=torch.Generator(device=args.device).manual_seed(args.seed), | ||
| output_type="np", | ||
| return_dict=False, | ||
| ) | ||
|
|
||
| # Convert video to uint8 (but keep as NumPy array) | ||
| video = (video * 255).round().astype("uint8") | ||
| video = torch.from_numpy(video) | ||
|
|
||
| encode_video( | ||
| video[0], | ||
| fps=args.frame_rate, | ||
| audio=audio[0].float().cpu(), | ||
| audio_sample_rate=pipeline.vocoder.config.output_sampling_rate, # should be 24000 | ||
| output_path=os.path.join(args.output_dir, args.output_filename), | ||
| ) | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| args = parse_args() | ||
| main(args) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| import argparse | ||
| import os | ||
|
|
||
| import torch | ||
|
|
||
| from diffusers.pipelines.ltx2 import LTX2ImageToVideoPipeline | ||
| from diffusers.pipelines.ltx2.export_utils import encode_video | ||
| from diffusers.utils import load_image | ||
|
|
||
|
|
||
| def parse_args(): | ||
| parser = argparse.ArgumentParser() | ||
|
|
||
| parser.add_argument("--model_id", type=str, default="diffusers-internal-dev/new-ltx-model") | ||
| parser.add_argument("--revision", type=str, default="main") | ||
|
|
||
| parser.add_argument("--image_path", required=True, type=str) | ||
| parser.add_argument( | ||
| "--prompt", | ||
| type=str, | ||
| default="An astronaut hatches from a fragile egg on the surface of the Moon, the shell cracking and peeling apart in gentle low-gravity motion. Fine lunar dust lifts and drifts outward with each movement, floating in slow arcs before settling back onto the ground. The astronaut pushes free in a deliberate, weightless motion, small fragments of the egg tumbling and spinning through the air. In the background, the deep darkness of space subtly shifts as stars glide with the camera's movement, emphasizing vast depth and scale. The camera performs a smooth, cinematic slow push-in, with natural parallax between the foreground dust, the astronaut, and the distant starfield. Ultra-realistic detail, physically accurate low-gravity motion, cinematic lighting, and a breath-taking, movie-like shot.", | ||
| ) | ||
| parser.add_argument( | ||
| "--negative_prompt", | ||
| type=str, | ||
| default="shaky, glitchy, low quality, worst quality, deformed, distorted, disfigured, motion smear, motion artifacts, fused fingers, bad anatomy, weird hand, ugly, transition, static.", | ||
| ) | ||
|
|
||
| parser.add_argument("--num_inference_steps", type=int, default=40) | ||
| parser.add_argument("--height", type=int, default=512) | ||
| parser.add_argument("--width", type=int, default=768) | ||
| parser.add_argument("--num_frames", type=int, default=121) | ||
| parser.add_argument("--frame_rate", type=float, default=25.0) | ||
| parser.add_argument("--guidance_scale", type=float, default=3.0) | ||
| parser.add_argument("--seed", type=int, default=42) | ||
|
|
||
| parser.add_argument("--device", type=str, default="cuda:0") | ||
| parser.add_argument("--dtype", type=str, default="bf16") | ||
| parser.add_argument("--cpu_offload", action="store_true") | ||
|
|
||
| parser.add_argument( | ||
| "--output_dir", | ||
| type=str, | ||
| default="samples", | ||
| help="Output directory for generated video", | ||
| ) | ||
| parser.add_argument( | ||
| "--output_filename", | ||
| type=str, | ||
| default="ltx2_sample_video.mp4", | ||
| help="Filename of the exported generated video", | ||
| ) | ||
|
|
||
| args = parser.parse_args() | ||
| args.dtype = torch.bfloat16 if args.dtype == "bf16" else torch.float32 | ||
| return args | ||
|
|
||
|
|
||
| def main(args): | ||
| pipeline = LTX2ImageToVideoPipeline.from_pretrained( | ||
| args.model_id, | ||
| revision=args.revision, | ||
| torch_dtype=args.dtype, | ||
| ) | ||
| if args.cpu_offload: | ||
| pipeline.enable_model_cpu_offload() | ||
| else: | ||
| pipeline.to(device=args.device) | ||
|
|
||
| image = load_image(args.image_path) | ||
|
|
||
| video, audio = pipeline( | ||
| image=image, | ||
| prompt=args.prompt, | ||
| negative_prompt=args.negative_prompt, | ||
| height=args.height, | ||
| width=args.width, | ||
| num_frames=args.num_frames, | ||
| frame_rate=args.frame_rate, | ||
| num_inference_steps=args.num_inference_steps, | ||
| guidance_scale=args.guidance_scale, | ||
| generator=torch.Generator(device=args.device).manual_seed(args.seed), | ||
| output_type="np", | ||
| return_dict=False, | ||
| ) | ||
|
|
||
| # Convert video to uint8 (but keep as NumPy array) | ||
| video = (video * 255).round().astype("uint8") | ||
| video = torch.from_numpy(video) | ||
|
|
||
| encode_video( | ||
| video[0], | ||
| fps=args.frame_rate, | ||
| audio=audio[0].float().cpu(), | ||
| audio_sample_rate=pipeline.vocoder.config.output_sampling_rate, # should be 24000 | ||
| output_path=os.path.join(args.output_dir, args.output_filename), | ||
| ) | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| args = parse_args() | ||
| main(args) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,119 @@ | ||
| import argparse | ||
| from pathlib import Path | ||
|
|
||
| import torch | ||
| from huggingface_hub import hf_hub_download | ||
|
|
||
|
|
||
| def download_checkpoint( | ||
| repo_id="diffusers-internal-dev/new-ltx-model", | ||
| filename="ltx-av-step-1932500-interleaved-new-vae.safetensors", | ||
| ): | ||
| ckpt_path = hf_hub_download(repo_id=repo_id, filename=filename) | ||
| return ckpt_path | ||
|
|
||
|
|
||
| def convert_state_dict(state_dict: dict) -> dict: | ||
| converted = {} | ||
| for key, value in state_dict.items(): | ||
| if not isinstance(value, torch.Tensor): | ||
| continue | ||
| new_key = key | ||
| if new_key.startswith("decoder."): | ||
| new_key = new_key[len("decoder.") :] | ||
| converted[f"decoder.{new_key}"] = value | ||
|
|
||
| converted["latents_mean"] = converted.pop("decoder.per_channel_statistics.mean-of-means") | ||
| converted["latents_std"] = converted.pop("decoder.per_channel_statistics.std-of-means") | ||
| return converted | ||
|
|
||
|
|
||
| def load_original_decoder(device: torch.device, dtype: torch.dtype): | ||
| from ltx_core.loader.single_gpu_model_builder import SingleGPUModelBuilder as Builder | ||
| from ltx_core.model.audio_vae.model_configurator import AUDIO_VAE_DECODER_COMFY_KEYS_FILTER | ||
| from ltx_core.model.audio_vae.model_configurator import VAEDecoderConfigurator as AudioDecoderConfigurator | ||
|
|
||
| checkpoint_path = download_checkpoint() | ||
|
|
||
| # The code below comes from `ltx-pipelines/src/ltx_pipelines/txt2vid.py` | ||
| decoder = Builder( | ||
| model_path=checkpoint_path, | ||
| model_class_configurator=AudioDecoderConfigurator, | ||
| model_sd_key_ops=AUDIO_VAE_DECODER_COMFY_KEYS_FILTER, | ||
| ).build(device=device) | ||
|
|
||
| decoder.eval() | ||
| return decoder | ||
|
|
||
|
|
||
| def build_diffusers_decoder(): | ||
| from diffusers.models.autoencoders import AutoencoderKLLTX2Audio | ||
|
|
||
| with torch.device("meta"): | ||
| model = AutoencoderKLLTX2Audio() | ||
|
|
||
| model.eval() | ||
| return model | ||
|
|
||
|
|
||
| @torch.no_grad() | ||
| def main() -> None: | ||
| parser = argparse.ArgumentParser(description="Validate LTX2 audio decoder conversion.") | ||
| parser.add_argument("--device", type=str, default="cpu") | ||
| parser.add_argument("--dtype", type=str, default="bfloat16", choices=["float32", "bfloat16", "float16"]) | ||
| parser.add_argument("--batch", type=int, default=2) | ||
| parser.add_argument("--output-path", type=Path, required=True) | ||
| args = parser.parse_args() | ||
|
|
||
| device = torch.device(args.device) | ||
| dtype_map = {"float32": torch.float32, "bfloat16": torch.bfloat16, "float16": torch.float16} | ||
| dtype = dtype_map[args.dtype] | ||
|
|
||
| original_decoder = load_original_decoder(device, dtype) | ||
| diffusers_model = build_diffusers_decoder() | ||
|
|
||
| converted_state_dict = convert_state_dict(original_decoder.state_dict()) | ||
| diffusers_model.load_state_dict(converted_state_dict, assign=True, strict=False) | ||
|
|
||
| per_channel_len = original_decoder.per_channel_statistics.get_buffer("std-of-means").numel() | ||
| latent_channels = diffusers_model.decoder.latent_channels | ||
| mel_bins_for_match = per_channel_len // latent_channels if per_channel_len % latent_channels == 0 else None | ||
|
|
||
| levels = len(diffusers_model.decoder.channel_multipliers) | ||
| latent_height = diffusers_model.decoder.resolution // (2 ** (levels - 1)) | ||
| latent_width = mel_bins_for_match or latent_height | ||
|
|
||
| dummy = torch.randn( | ||
| args.batch, | ||
| diffusers_model.decoder.latent_channels, | ||
| latent_height, | ||
| latent_width, | ||
| device=device, | ||
| dtype=dtype, | ||
| generator=torch.Generator(device).manual_seed(42), | ||
| ) | ||
|
|
||
| original_out = original_decoder(dummy) | ||
|
|
||
| from diffusers.pipelines.ltx2.pipeline_ltx2 import LTX2Pipeline | ||
|
|
||
| _, a_channels, a_time, a_freq = dummy.shape | ||
| dummy = dummy.permute(0, 2, 1, 3).reshape(-1, a_time, a_channels * a_freq) | ||
| dummy = LTX2Pipeline._denormalize_audio_latents( | ||
| dummy, | ||
| diffusers_model.latents_mean, | ||
| diffusers_model.latents_std, | ||
| ) | ||
| dummy = dummy.view(-1, a_time, a_channels, a_freq).permute(0, 2, 1, 3) | ||
| diffusers_out = diffusers_model.decode(dummy).sample | ||
|
|
||
| torch.testing.assert_close(diffusers_out, original_out, rtol=1e-4, atol=1e-4) | ||
| max_diff = (diffusers_out - original_out).abs().max().item() | ||
| print(f"Conversion successful. Max diff: {max_diff:.6f}") | ||
|
|
||
| diffusers_model.to(dtype).save_pretrained(args.output_path) | ||
| print(f"Serialized model to {args.output_path}") | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| main() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's remove these files