diff --git a/CHANGELOG.md b/CHANGELOG.md index a4159fa5f..be679abcc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,8 @@ # Change Log for SD.Next -## Update for 2025-10-15 +## Update for 2025-10-16 -### Highlights for 2025-10-15 +### Highlights for 2025-10-16 It's been a month since the last release and number of changes is yet again massive with over 300 commits! Highlight are: @@ -15,8 +15,9 @@ Highlight are: - **Quantization**: new **SVD**-style quantization using SDNQ offers almost zero-loss even with **4bit** quantization and now you can also test your favorite quantization on-the-fly and then save/load model for future use +- Other: support for **Huggingface** mirrors, changes to installer to prevent unwanted `torch-cpu` operations, improved previews, etc. -### Details for 2025-10-15 +### Details for 2025-10-16 - **Models** - [WAN 2.2 14B VACE](https://huggingface.co/alibaba-pai/Wan2.2-VACE-Fun-A14B) @@ -62,6 +63,9 @@ Highlight are: enable in *settings -> pipeline modifiers -> cache-dit* - [Nunchaku Flux.1 PulID](https://nunchaku.tech/docs/nunchaku/python_api/nunchaku.pipeline.pipeline_flux_pulid.html) automatically enabled if loaded model is FLUX.1 with Nunchaku engine enabled and when PulID script is enabled + - **Huggingface mirror** in *settings -> huggingface* + if you're working from location with limited access to huggingface, you can now specify a mirror site + for example enter, `https://hf-mirror.com` - **Compute** - **ROCm** for Windows support for both official torch preview release of `torch-rocm` for windows and **TheRock** unofficial `torch-rocm` builds for windows diff --git a/modules/modelloader.py b/modules/modelloader.py index 5018d5cb9..0f8c502c3 100644 --- a/modules/modelloader.py +++ b/modules/modelloader.py @@ -27,6 +27,8 @@ def hf_login(token=None): if token is None or len(token) <= 4: log.debug('HF login: no token provided') return False + if len(shared.opts.huggingface_mirror.strip()) > 0 and os.environ.get('HF_ENDPOINT', None) is None: + os.environ['HF_ENDPOINT'] = shared.opts.huggingface_mirror.strip() if os.environ.get('HUGGING_FACE_HUB_TOKEN', None) is not None: os.environ.pop('HUGGING_FACE_HUB_TOKEN', None) os.unsetenv('HUGGING_FACE_HUB_TOKEN') diff --git a/modules/shared.py b/modules/shared.py index 3cca72294..fcaa05f1b 100644 --- a/modules/shared.py +++ b/modules/shared.py @@ -688,6 +688,7 @@ options_templates.update(options_section(('huggingface', "Huggingface"), { "diffuser_cache_config": OptionInfo(True, "Use cached model config when available"), "huggingface_token": OptionInfo('', 'HuggingFace token', gr.Textbox, {"lines": 2}), "hf_transfer_mode": OptionInfo("rust", "HuggingFace download method", gr.Radio, {"choices": ['requests', 'rust', 'xet']}), + "huggingface_mirror": OptionInfo('', 'HuggingFace mirror', gr.Textbox), "diffusers_model_load_variant": OptionInfo("default", "Preferred Model variant", gr.Radio, {"choices": ['default', 'fp32', 'fp16']}), "diffusers_vae_load_variant": OptionInfo("default", "Preferred VAE variant", gr.Radio, {"choices": ['default', 'fp32', 'fp16']}), diff --git a/modules/video_models/models_def.py b/modules/video_models/models_def.py index e1cc76f71..14f0eb8e0 100644 --- a/modules/video_models/models_def.py +++ b/modules/video_models/models_def.py @@ -153,76 +153,76 @@ models = { url='https://huggingface.co/Wan-AI/Wan2.2-TI2V-5B-Diffusers', repo='Wan-AI/Wan2.2-TI2V-5B-Diffusers', repo_cls=diffusers.WanPipeline, - te_cls=transformers.T5EncoderModel, + te_cls=transformers.UMT5EncoderModel, dit_cls=diffusers.WanTransformer3DModel), Model(name='WAN 2.2 5B I2V', url='https://huggingface.co/Wan-AI/Wan2.2-TI2V-5B-Diffusers', repo='Wan-AI/Wan2.2-TI2V-5B-Diffusers', repo_cls=diffusers.WanImageToVideoPipeline, - te_cls=transformers.T5EncoderModel, + te_cls=transformers.UMT5EncoderModel, dit_cls=diffusers.WanTransformer3DModel), Model(name='WAN 2.2 A14B T2V', url='https://huggingface.co/Wan-AI/Wan2.2-T2V-A14B-Diffusers', repo='Wan-AI/Wan2.2-T2V-A14B-Diffusers', repo_cls=diffusers.WanPipeline, - te_cls=transformers.T5EncoderModel, + te_cls=transformers.UMT5EncoderModel, dit_cls=diffusers.WanTransformer3DModel, dit_folder=("transformer", "transformer_2")), Model(name='WAN 2.2 A14B I2V', url='https://huggingface.co/Wan-AI/Wan2.2-I2V-A14B-Diffusers', repo='Wan-AI/Wan2.2-I2V-A14B-Diffusers', repo_cls=diffusers.WanImageToVideoPipeline, - te_cls=transformers.T5EncoderModel, + te_cls=transformers.UMT5EncoderModel, dit_cls=diffusers.WanTransformer3DModel, dit_folder=("transformer", "transformer_2")), Model(name='WAN 2.2 14B VACE', url='https://huggingface.co/linoyts/Wan2.2-VACE-Fun-14B-diffusers', repo='linoyts/Wan2.2-VACE-Fun-14B-diffusers', repo_cls=diffusers.WanVACEPipeline, - te_cls=transformers.T5EncoderModel, + te_cls=transformers.UMT5EncoderModel, dit_cls=diffusers.WanVACETransformer3DModel, dit_folder=("transformer", "transformer_2")), Model(name='WAN 2.1 1.3B T2V', url='https://huggingface.co/Wan-AI/Wan2.1-T2V-1.3B-Diffusers', repo='Wan-AI/Wan2.1-T2V-1.3B-Diffusers', repo_cls=diffusers.WanPipeline, - te_cls=transformers.T5EncoderModel, + te_cls=transformers.UMT5EncoderModel, dit_cls=diffusers.WanTransformer3DModel), Model(name='WAN 2.1 14B T2V', url='https://huggingface.co/Wan-AI/Wan2.1-T2V-14B-Diffusers', repo='Wan-AI/Wan2.1-T2V-14B-Diffusers', repo_cls=diffusers.WanPipeline, - te_cls=transformers.T5EncoderModel, + te_cls=transformers.UMT5EncoderModel, dit_cls=diffusers.WanTransformer3DModel), Model(name='WAN 2.1 14B I2V 480p', url='https://huggingface.co/Wan-AI/Wan2.1-I2V-14B-480P-Diffusers', repo='Wan-AI/Wan2.1-I2V-14B-480P-Diffusers', repo_cls=diffusers.WanImageToVideoPipeline, - te_cls=transformers.T5EncoderModel, + te_cls=transformers.UMT5EncoderModel, dit_cls=diffusers.WanTransformer3DModel), Model(name='WAN 2.1 14B I2V 720p', url='https://huggingface.co/Wan-AI/Wan2.1-I2V-14B-720P-Diffusers', repo='Wan-AI/Wan2.1-I2V-14B-720P-Diffusers', repo_cls=diffusers.WanImageToVideoPipeline, - te_cls=transformers.T5EncoderModel, + te_cls=transformers.UMT5EncoderModel, dit_cls=diffusers.WanTransformer3DModel), Model(name='WAN 2.1 14B FLF2V 720p', url='https://huggingface.co/Wan-AI/Wan2.1-FLF2V-14B-720P', repo='Wan-AI/Wan2.1-FLF2V-14B-720P-diffusers', repo_cls=diffusers.WanImageToVideoPipeline, - te_cls=transformers.T5EncoderModel, + te_cls=transformers.UMT5EncoderModel, dit_cls=diffusers.WanTransformer3DModel), Model(name='WAN 2.1 VACE 1.3B', url='https://huggingface.co/Wan-AI/Wan2.1-VACE-1.3B-diffusers', repo='Wan-AI/Wan2.1-VACE-1.3B-diffusers', repo_cls=diffusers.WanVACEPipeline, - te_cls=transformers.T5EncoderModel, + te_cls=transformers.UMT5EncoderModel, dit_cls=diffusers.WanVACETransformer3DModel), Model(name='WAN 2.1 VACE 14B', url='https://huggingface.co/Wan-AI/Wan2.1-VACE-14B-diffusers', repo='Wan-AI/Wan2.1-VACE-14B-diffusers', repo_cls=diffusers.WanVACEPipeline, - te_cls=transformers.T5EncoderModel, + te_cls=transformers.UMT5EncoderModel, dit_cls=diffusers.WanVACETransformer3DModel), ], 'SkyReels V2': [ diff --git a/modules/video_models/video_load.py b/modules/video_models/video_load.py index d7f47d5f2..d41e3d463 100644 --- a/modules/video_models/video_load.py +++ b/modules/video_models/video_load.py @@ -31,6 +31,10 @@ def load_model(selected: models_def.Model): selected.te = 'Disty0/t5-xxl' selected.te_folder = '' selected.te_revision = None + if selected.te_cls.__name__ == 'UMT5EncoderModel' and shared.opts.te_shared_t5: + selected.te = 'Wan-AI/Wan2.2-TI2V-5B-Diffusers' + selected.te_folder = 'text_encoder' + selected.te_revision = None if selected.te_cls.__name__ == 'LlamaModel' and shared.opts.te_shared_t5: selected.te = 'hunyuanvideo-community/HunyuanVideo' selected.te_folder = 'text_encoder' diff --git a/modules/video_models/video_save.py b/modules/video_models/video_save.py index 41095922f..24775c5a1 100644 --- a/modules/video_models/video_save.py +++ b/modules/video_models/video_save.py @@ -6,6 +6,7 @@ import numpy as np import torch import einops from modules import shared, errors ,timer, rife +from modules.video_models.video_utils import check_av def get_video_filename(frames:int, codec:str): @@ -27,11 +28,9 @@ def images_to_tensor(images): def atomic_save_video(filename, tensor:torch.Tensor, fps:float=24, codec:str='libx264', pix_fmt:str='yuv420p', options:str='', metadata:dict={}, pbar=None): - try: - import av - av.logging.set_level(av.logging.ERROR) # pylint: disable=c-extension-no-member - except Exception as e: - shared.log.error(f'Video: {e}') + av = check_av() + if av is None or av is False: + shared.log.error('Video: ffmpeg/av not available') return savejob = shared.state.begin('Save video') diff --git a/modules/video_models/video_utils.py b/modules/video_models/video_utils.py index 47faeac13..f29c43906 100644 --- a/modules/video_models/video_utils.py +++ b/modules/video_models/video_utils.py @@ -2,6 +2,7 @@ import os import sys import time from PIL import Image +from installer import install from modules import shared, sd_models, timer, errors, devices @@ -18,8 +19,10 @@ def get_url(url): def check_av(): + install('av') try: import av + av.logging.set_level(av.logging.ERROR) # pylint: disable=c-extension-no-member except Exception as e: shared.log.error(f'av package: {e}') return False