from diffusers_helper.hf_login import login # Hugging Face ログイン import os import threading import time import requests from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry import json # Hugging Face ダウンロード用キャッシュディレクトリを設定 os.environ['HF_HOME'] = os.path.abspath( os.path.realpath( os.path.join(os.path.dirname(__file__), './hf_download') ) ) import gradio as gr import torch import traceback import einops import safetensors.torch as sf import numpy as np import math # 環境に応じた GPU 利用設定 IN_HF_SPACE = os.environ.get('SPACE_ID') is not None GPU_AVAILABLE = False GPU_INITIALIZED = False last_update_time = time.time() # Spaces 環境の場合、spaces モジュールをインポートして GPU 状態をチェック if IN_HF_SPACE: try: import spaces GPU_AVAILABLE = torch.cuda.is_available() if GPU_AVAILABLE: device_name = torch.cuda.get_device_name(0) total_mem = torch.cuda.get_device_properties(0).total_memory / 1e9 print(f"GPU 利用可能: {device_name}, メモリ: {total_mem:.2f} GB") # 簡易テスト t = torch.zeros(1, device='cuda') + 1 del t else: print("警告: CUDA は利用可能だが GPU が見つかりません") except ImportError: print("spaces モジュールがインポートできませんでした") GPU_AVAILABLE = torch.cuda.is_available() else: GPU_AVAILABLE = torch.cuda.is_available() # 出力用フォルダを作成 outputs_folder = './outputs/' os.makedirs(outputs_folder, exist_ok=True) # モデル管理用グローバル変数 models = {} cpu_fallback_mode = not GPU_AVAILABLE # モデルをロードする関数 def load_models(): """ モデルをロードし、グローバル変数に保存します。 初回のみ実行され、以降はスキップされます。 """ global models, cpu_fallback_mode, GPU_INITIALIZED if GPU_INITIALIZED: print("モデルは既にロード済みです") return models print("モデルのロードを開始します...") try: # デバイスとデータ型設定 device = 'cuda' if GPU_AVAILABLE and not cpu_fallback_mode else 'cpu' dtype = torch.float16 if GPU_AVAILABLE else torch.float32 transformer_dtype = torch.bfloat16 if GPU_AVAILABLE else torch.float32 # モデルを順次ロード from transformers import LlamaModel, CLIPTextModel, LlamaTokenizerFast, CLIPTokenizer from diffusers import AutoencoderKLHunyuanVideo from diffusers_helper.models.hunyuan_video_packed import HunyuanVideoTransformer3DModelPacked from diffusers_helper.hunyuan import encode_prompt_conds, vae_decode, vae_encode, vae_decode_fake from diffusers_helper.utils import save_bcthw_as_mp4, crop_or_pad_yield_mask, soft_append_bcthw, resize_and_center_crop, generate_timestamp from diffusers_helper.pipelines.k_diffusion_hunyuan import sample_hunyuan from diffusers_helper.clip_vision import hf_clip_vision_encode from diffusers_helper.memory import get_cuda_free_memory_gb, move_model_to_device_with_memory_preservation, unload_complete_models, load_model_as_complete, DynamicSwapInstaller from diffusers_helper.thread_utils import AsyncStream, async_run # テキストエンコーダー text_encoder = LlamaModel.from_pretrained( "hunyuanvideo-community/HunyuanVideo", subfolder='text_encoder', torch_dtype=dtype ).to('cpu') text_encoder_2 = CLIPTextModel.from_pretrained( "hunyuanvideo-community/HunyuanVideo", subfolder='text_encoder_2', torch_dtype=dtype ).to('cpu') tokenizer = LlamaTokenizerFast.from_pretrained( "hunyuanvideo-community/HunyuanVideo", subfolder='tokenizer' ) tokenizer_2 = CLIPTokenizer.from_pretrained( "hunyuanvideo-community/HunyuanVideo", subfolder='tokenizer_2' ) # VAE vae = AutoencoderKLHunyuanVideo.from_pretrained( "hunyuanvideo-community/HunyuanVideo", subfolder='vae', torch_dtype=dtype ).to('cpu') # 画像エンコーダー from transformers import SiglipImageProcessor, SiglipVisionModel feature_extractor = SiglipImageProcessor.from_pretrained("lllyasviel/flux_redux_bfl", subfolder='feature_extractor') image_encoder = SiglipVisionModel.from_pretrained("lllyasviel/flux_redux_bfl", subfolder='image_encoder', torch_dtype=dtype).to('cpu') # トランスフォーマーモデル transformer = HunyuanVideoTransformer3DModelPacked.from_pretrained( 'from diffusers_helper.hf_login import login # Hugging Face ログイン import os import threading import time import requests from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry import json # Hugging Face ダウンロード用キャッシュディレクトリを設定 os.environ['HF_HOME'] = os.path.abspath( os.path.realpath( os.path.join(os.path.dirname(__file__), './hf_download') ) ) import gradio as gr import torch import traceback import einops import safetensors.torch as sf import numpy as np import math # 環境に応じた GPU 利用設定 IN_HF_SPACE = os.environ.get('SPACE_ID') is not None GPU_AVAILABLE = False GPU_INITIALIZED = False last_update_time = time.time() # Spaces 環境の場合、spaces モジュールをインポートして GPU 状態をチェック if IN_HF_SPACE: try: import spaces GPU_AVAILABLE = torch.cuda.is_available() if GPU_AVAILABLE: device_name = torch.cuda.get_device_name(0) total_mem = torch.cuda.get_device_properties(0).total_memory / 1e9 print(f"GPU 利用可能: {device_name}, メモリ: {total_mem:.2f} GB") # 簡易テスト t = torch.zeros(1, device='cuda') + 1 del t else: print("警告: CUDA は利用可能だが GPU が見つかりません") except ImportError: print("spaces モジュールがインポートできませんでした") GPU_AVAILABLE = torch.cuda.is_available() else: GPU_AVAILABLE = torch.cuda.is_available() # 出力用フォルダを作成 outputs_folder = './outputs/' os.makedirs(outputs_folder, exist_ok=True) # モデル管理用グローバル変数 models = {} cpu_fallback_mode = not GPU_AVAILABLE # モデルをロードする関数 def load_models(): """ モデルをロードし、グローバル変数に保存します。 初回のみ実行され、以降はスキップされます。 """ global models, cpu_fallback_mode, GPU_INITIALIZED if GPU_INITIALIZED: print("モデルは既にロード済みです") return models print("モデルのロードを開始します...") try: # デバイスとデータ型設定 device = 'cuda' if GPU_AVAILABLE and not cpu_fallback_mode else 'cpu' dtype = torch.float16 if GPU_AVAILABLE else torch.float32 transformer_dtype = torch.bfloat16 if GPU_AVAILABLE else torch.float32 # モデルを順次ロード from transformers import LlamaModel, CLIPTextModel, LlamaTokenizerFast, CLIPTokenizer from diffusers import AutoencoderKLHunyuanVideo from diffusers_helper.models.hunyuan_video_packed import HunyuanVideoTransformer3DModelPacked from diffusers_helper.hunyuan import encode_prompt_conds, vae_decode, vae_encode, vae_decode_fake from diffusers_helper.utils import save_bcthw_as_mp4, crop_or_pad_yield_mask, soft_append_bcthw, resize_and_center_crop, generate_timestamp from diffusers_helper.pipelines.k_diffusion_hunyuan import sample_hunyuan from diffusers_helper.clip_vision import hf_clip_vision_encode from diffusers_helper.memory import get_cuda_free_memory_gb, move_model_to_device_with_memory_preservation, unload_complete_models, load_model_as_complete, DynamicSwapInstaller from diffusers_helper.thread_utils import AsyncStream, async_run # テキストエンコーダー text_encoder = LlamaModel.from_pretrained( "hunyuanvideo-community/HunyuanVideo", subfolder='text_encoder', torch_dtype=dtype ).to('cpu') text_encoder_2 = CLIPTextModel.from_pretrained( "hunyuanvideo-community/HunyuanVideo", subfolder='text_encoder_2', torch_dtype=dtype ).to('cpu') tokenizer = LlamaTokenizerFast.from_pretrained( "hunyuanvideo-community/HunyuanVideo", subfolder='tokenizer' ) tokenizer_2 = CLIPTokenizer.from_pretrained( "hunyuanvideo-community/HunyuanVideo", subfolder='tokenizer_2' ) # VAE vae = AutoencoderKLHunyuanVideo.from_pretrained( "hunyuanvideo-community/HunyuanVideo", subfolder='vae', torch_dtype=dtype ).to('cpu') # 画像エンコーダー from transformers import SiglipImageProcessor, SiglipVisionModel feature_extractor = SiglipImageProcessor.from_pretrained("lllyasviel/flux_redux_bfl", subfolder='feature_extractor') image_encoder = SiglipVisionModel.from_pretrained("lllyasviel/flux_redux_bfl", subfolder='image_encoder', torch_dtype=dtype).to('cpu') # トランスフォーマーモデル transformer = HunyuanVideoTransformer3DModelPacked.from_pretrained( 'tori29umai/FramePackI2V_HY_rotate_landscape', torch_dtype=transformer_dtype ).to('cpu') # 評価モードに設定 vae.eval(); text_encoder.eval(); text_encoder_2.eval(); image_encoder.eval(); transformer.eval() # メモリ最適化 vae.enable_slicing(); vae.enable_tiling() transformer.high_quality_fp32_output_for_inference = True # デバイス移行 if GPU_AVAILABLE and not cpu_fallback_mode: try: DynamicSwapInstaller.install_model(transformer, device=device) DynamicSwapInstaller.install_model(text_encoder, device=device) except Exception: # GPU への移行に失敗した場合は CPU モードにフォールバック cpu_fallback_mode = True # グローバル変数に保存 models = { 'text_encoder': text_encoder, 'text_encoder_2': text_encoder_2, 'tokenizer': tokenizer, 'tokenizer_2': tokenizer_2, 'vae': vae, 'feature_extractor': feature_extractor, 'image_encoder': image_encoder, 'transformer': transformer } GPU_INITIALIZED = True print(f"モデルロード完了。モード: {'GPU' if not cpu_fallback_mode else 'CPU'}") return models except Exception as e: # エラー発生時の処理 print(f"モデルロード中にエラー発生: {e}") traceback.print_exc() # ログをファイルに出力 try: with open(os.path.join(outputs_folder, "error_log.txt"), "w") as f: f.write(traceback.format_exc()) except: pass cpu_fallback_mode = True return {} def get_models(): """ モデルを返す。未ロードならロードを実行。 """ global models if not models: models = load_models() return models # 非同期ストリーム stream = None @torch.no_grad() def worker(input_image, prompt, n_prompt, seed, total_second_length, latent_window_size, steps, cfg, gs, rs, gpu_memory_preservation, use_teacache): """ 実際の動画生成処理を行うワーカー関数。 入力画像とプロンプトから逐次進捗を返却。 """ global last_update_time, stream last_update_time = time.time() total_second_length = min(total_second_length, 5.0) # モデル取得 models_data = get_models() if not models_data: stream.output_queue.push(('error', 'モデルロード失敗')) stream.output_queue.push(('end', None)) return text_encoder = models_data['text_encoder'] text_encoder_2 = models_data['text_encoder_2'] tokenizer = models_data['tokenizer'] tokenizer_2 = models_data['tokenizer_2'] vae = models_data['vae'] feature_extractor = models_data['feature_extractor'] image_encoder = models_data['image_encoder'] transformer = models_data['transformer'] # デバイス決定 device = 'cuda' if GPU_AVAILABLE and not cpu_fallback_mode else 'cpu' if cpu_fallback_mode: latent_window_size = min(latent_window_size, 5) steps = min(steps, 15) total_second_length = min(total_second_length, 2.0) # フレーム数計算 total_latent_sections = max(int(round((total_second_length * 30) / (latent_window_size * 4))), 1) job_id = str(int(time.time() * 1000)) history_latents = None history_pixels = None total_generated_latent_frames = 0 # 進捗開始 stream.output_queue.push(('progress', (None, '', '