Spaces:
Running on Zero
Running on Zero
| from __future__ import annotations | |
| import configparser | |
| from dataclasses import dataclass | |
| import os | |
| from pathlib import Path | |
| ROOT = Path(__file__).resolve().parent.parent | |
| def _bool(value: str) -> bool: | |
| return value.strip().lower() in {"1", "true", "yes", "on"} | |
| class SpaceConfig: | |
| width: int | |
| height: int | |
| seconds: float | |
| fps: int | |
| steps: int | |
| split_step: int | |
| cfg: float | |
| shift: float | |
| sampler: str | |
| scheduler: str | |
| start_strength: float | |
| end_strength: float | |
| end_mask_strength: float | |
| use_rife: bool | |
| rife_frames: int | |
| use_crossfade: bool | |
| text_encoder_quantization: str | |
| global_resident_models: bool | |
| vae_tiling: bool | |
| gpu_size: str | |
| gpu_duration: int | |
| concurrency_limit: int | |
| def frame_count(self) -> int: | |
| requested = max(int(round(self.seconds * self.fps)), 1) | |
| return requested + ((4 - ((requested - 1) % 4)) % 4) | |
| def load_space_config(path: Path | None = None) -> SpaceConfig: | |
| parser = configparser.ConfigParser() | |
| config_path = path or ROOT / "config.ini" | |
| if not parser.read(config_path): | |
| raise FileNotFoundError(f"Configuration not found: {config_path}") | |
| section = parser["SPACE"] | |
| gpu_size = os.environ.get("ZERO_GPU_SIZE", section.get("zero_gpu_size", "large")).strip().lower() | |
| if gpu_size not in {"large", "xlarge"}: | |
| raise ValueError("ZERO_GPU_SIZE must be 'large' or 'xlarge'.") | |
| width, height = section.getint("width"), section.getint("height") | |
| if width % 16 or height % 16: | |
| raise ValueError("width and height must be divisible by 16.") | |
| steps, split = section.getint("steps"), section.getint("split_step") | |
| if not 0 < split < steps: | |
| raise ValueError("split_step must be between 1 and steps-1.") | |
| text_encoder_quantization = section.get("text_encoder_quantization", "int8_weight_only").strip().lower() | |
| if text_encoder_quantization not in {"int8_weight_only", "bf16"}: | |
| raise ValueError("text_encoder_quantization must be 'int8_weight_only' or 'bf16'.") | |
| return SpaceConfig( | |
| width=width, | |
| height=height, | |
| seconds=section.getfloat("seconds"), | |
| fps=section.getint("fps"), | |
| steps=steps, | |
| split_step=split, | |
| cfg=section.getfloat("cfgscale"), | |
| shift=section.getfloat("model_sampling_shift"), | |
| sampler=section.get("sampler_name", "euler"), | |
| scheduler=section.get("scheduler", "normal"), | |
| start_strength=section.getfloat("start_latent_strength"), | |
| end_strength=section.getfloat("end_latent_strength"), | |
| end_mask_strength=section.getfloat("end_temporal_mask_strength"), | |
| use_rife=_bool(section.get("apply_rife_seam", "true")), | |
| rife_frames=section.getint("rife_seam_frames"), | |
| use_crossfade=_bool(section.get("apply_crossfade", "true")), | |
| text_encoder_quantization=text_encoder_quantization, | |
| global_resident_models=_bool(section.get("global_resident_models", "false")), | |
| vae_tiling=_bool(section.get("vae_tiling", "false")), | |
| gpu_size=gpu_size, | |
| gpu_duration=int(os.environ.get("ZERO_GPU_DURATION", section.get("zero_gpu_duration", "300"))), | |
| concurrency_limit=section.getint("concurrency_limit", 1), | |
| ) | |