563 lines
27 KiB
Python
563 lines
27 KiB
Python
# SPDX-License-Identifier: Apache-2.0
|
|
# Adapted from vllm: https://github.com/vllm-project/vllm/blob/v0.7.3/vllm/envs.py
|
|
"""Registry of the environment variables that FastVideo reads.
|
|
|
|
Every FastVideo-owned environment variable is declared here once, as a typed
|
|
field with a default, a category, and a description. Code reads a variable
|
|
with ``envs.NAME.get()`` inside a function, writes it with ``envs.NAME.set()``,
|
|
and tests change it temporarily with ``envs.NAME.override()``. Each field type
|
|
has one parsing rule, and a value that the rule rejects raises ``EnvVarError``.
|
|
|
|
The policy for environment variables is in ``docs/contributing/env_vars.md``,
|
|
and ``fastvideo/tests/contract/test_env_policy.py`` enforces it.
|
|
"""
|
|
|
|
import logging
|
|
import os
|
|
from collections.abc import Callable, Iterator
|
|
from contextlib import contextmanager
|
|
from typing import Generic, TypeVar
|
|
|
|
T = TypeVar("T")
|
|
# String fields accept a string default or None (unset).
|
|
S = TypeVar("S", str, str | None)
|
|
|
|
POLICY_DOC = "docs/contributing/env_vars.md"
|
|
|
|
# Allowed values of EnvField.category.
|
|
CATEGORIES = ("path", "distributed", "logging", "attention", "performance", "output", "profiling", "debug", "sampling",
|
|
"eval", "test")
|
|
|
|
_TRUE_VALUES = frozenset({"1", "true", "yes", "on"})
|
|
_FALSE_VALUES = frozenset({"0", "false", "no", "off", ""})
|
|
|
|
# fastvideo.logger imports this module, so warnings go through the standard
|
|
# logging module; the "fastvideo" logger configuration still applies.
|
|
_logger = logging.getLogger(__name__)
|
|
_warned_messages: set[str] = set()
|
|
|
|
|
|
def _warn_once(message: str) -> None:
|
|
if message not in _warned_messages:
|
|
_warned_messages.add(message)
|
|
_logger.warning(message)
|
|
|
|
|
|
class EnvVarError(ValueError):
|
|
"""An environment variable holds a value that its registered type rejects."""
|
|
|
|
|
|
class EnvField(Generic[T]):
|
|
"""One registered environment variable: its type, default, category, and description.
|
|
|
|
``default`` is either the value itself or a zero-argument function that
|
|
computes it on each read while the variable is unset. ``deprecated_names``
|
|
lists earlier names of a renamed variable; they are read, with a warning,
|
|
only when the variable itself is unset.
|
|
"""
|
|
|
|
type_name = ""
|
|
|
|
def __init__(self, default: T | Callable[[], T], *, category: str, doc: str,
|
|
deprecated_names: tuple[str, ...] = ()) -> None:
|
|
self.name = "" # Set by _register_fields() from the module attribute name.
|
|
self.default = default
|
|
self.category = category
|
|
self.doc = doc
|
|
self.deprecated_names = deprecated_names
|
|
|
|
def parse(self, raw: str) -> T:
|
|
raise NotImplementedError
|
|
|
|
def format(self, value: T) -> str:
|
|
return str(value)
|
|
|
|
def _read_raw(self) -> tuple[str, str] | None:
|
|
"""Return (name, raw value) from the variable or its first set deprecated name."""
|
|
raw = os.environ.get(self.name)
|
|
if raw is not None:
|
|
return self.name, raw
|
|
for old_name in self.deprecated_names:
|
|
raw = os.environ.get(old_name)
|
|
if raw is not None:
|
|
_warn_once(f"{old_name} is deprecated and will be removed in the next minor release; "
|
|
f"set {self.name} instead.")
|
|
return old_name, raw
|
|
return None
|
|
|
|
def get(self) -> T:
|
|
"""Return the parsed value, or the default when the variable is unset."""
|
|
found = self._read_raw()
|
|
if found is None:
|
|
return self.default() if callable(self.default) else self.default
|
|
name, raw = found
|
|
try:
|
|
return self.parse(raw)
|
|
except ValueError as exc:
|
|
raise EnvVarError(f"Invalid value {raw!r} for {name}: {exc}. See {POLICY_DOC}.") from None
|
|
|
|
def is_set(self) -> bool:
|
|
return any(name in os.environ for name in (self.name, *self.deprecated_names))
|
|
|
|
def set(self, value: T) -> None:
|
|
os.environ[self.name] = self.format(value)
|
|
|
|
def clear(self) -> None:
|
|
for name in (self.name, *self.deprecated_names):
|
|
os.environ.pop(name, None)
|
|
|
|
@contextmanager
|
|
def override(self, value: T | None) -> Iterator[None]:
|
|
"""Set the variable, or unset it when ``value`` is None, and restore the previous values on exit."""
|
|
previous = {name: os.environ.get(name) for name in (self.name, *self.deprecated_names)}
|
|
self.clear()
|
|
if value is not None:
|
|
self.set(value)
|
|
try:
|
|
yield
|
|
finally:
|
|
for name, old_value in previous.items():
|
|
if old_value is None:
|
|
os.environ.pop(name, None)
|
|
else:
|
|
os.environ[name] = old_value
|
|
|
|
def __bool__(self) -> bool:
|
|
raise TypeError(f"Use envs.{self.name}.get() to read {self.name}.")
|
|
|
|
|
|
class EnvBool(EnvField[bool]):
|
|
"""True for 1, true, yes, on; false for 0, false, no, off, and the empty string; case-insensitive."""
|
|
|
|
type_name = "bool"
|
|
|
|
def parse(self, raw: str) -> bool:
|
|
value = raw.strip().lower()
|
|
if value in _TRUE_VALUES:
|
|
return True
|
|
if value in _FALSE_VALUES:
|
|
return False
|
|
raise ValueError("expected 1, true, yes, on, 0, false, no, off, or an empty string")
|
|
|
|
def format(self, value: bool) -> str:
|
|
return "1" if value else "0"
|
|
|
|
|
|
class EnvInt(EnvField[int]):
|
|
type_name = "int"
|
|
|
|
def parse(self, raw: str) -> int:
|
|
return int(raw)
|
|
|
|
|
|
class EnvFloat(EnvField[float]):
|
|
type_name = "float"
|
|
|
|
def parse(self, raw: str) -> float:
|
|
return float(raw)
|
|
|
|
|
|
class EnvStr(EnvField[S]):
|
|
type_name = "str"
|
|
|
|
def parse(self, raw: str) -> S:
|
|
return raw
|
|
|
|
|
|
class EnvPath(EnvField[S]):
|
|
"""A filesystem path; a leading ``~`` is expanded."""
|
|
|
|
type_name = "path"
|
|
|
|
def parse(self, raw: str) -> S:
|
|
return os.path.expanduser(raw)
|
|
|
|
|
|
class EnvChoice(EnvField[str]):
|
|
"""One of ``choices``; the value is stripped and lower-cased before the check."""
|
|
|
|
def __init__(self, default: str, *, choices: tuple[str, ...], category: str, doc: str) -> None:
|
|
super().__init__(default, category=category, doc=doc)
|
|
self.choices = choices
|
|
self.type_name = "one of " + ", ".join(choices)
|
|
|
|
def parse(self, raw: str) -> str:
|
|
value = raw.strip().lower()
|
|
if value not in self.choices:
|
|
raise ValueError(f"expected one of {', '.join(self.choices)}")
|
|
return value
|
|
|
|
|
|
def get_default_cache_root() -> str:
|
|
return os.getenv(
|
|
"XDG_CACHE_HOME",
|
|
os.path.join(os.path.expanduser("~"), ".cache"),
|
|
)
|
|
|
|
|
|
def get_default_config_root() -> str:
|
|
return os.getenv(
|
|
"XDG_CONFIG_HOME",
|
|
os.path.join(os.path.expanduser("~"), ".config"),
|
|
)
|
|
|
|
|
|
# Variables that other tools read (CUDA, NCCL, PyTorch, launchers) are written
|
|
# only through these helpers. The contract test checks each name against its
|
|
# write allowlist.
|
|
|
|
|
|
def set_external(name: str, value: str) -> None:
|
|
"""Set an environment variable that another tool reads."""
|
|
os.environ[name] = value
|
|
|
|
|
|
def setdefault_external(name: str, value: str) -> None:
|
|
"""Set an environment variable that another tool reads, unless it is already set."""
|
|
os.environ.setdefault(name, value)
|
|
|
|
|
|
def unset_external(name: str) -> None:
|
|
"""Remove an environment variable that another tool reads."""
|
|
os.environ.pop(name, None)
|
|
|
|
|
|
# ================== Paths ==================
|
|
|
|
FASTVIDEO_CONFIG_ROOT = EnvPath(
|
|
lambda: os.path.expanduser(os.path.join(get_default_config_root(), "fastvideo")),
|
|
category="path",
|
|
doc="Root directory for FastVideo configuration files, at runtime and at installation. "
|
|
"Defaults to ~/.config/fastvideo, or $XDG_CONFIG_HOME/fastvideo when XDG_CONFIG_HOME is set.")
|
|
FASTVIDEO_CACHE_ROOT = EnvPath(
|
|
lambda: os.path.expanduser(os.path.join(get_default_cache_root(), "fastvideo")),
|
|
category="path",
|
|
doc="Root directory for FastVideo cache files. "
|
|
"Defaults to ~/.cache/fastvideo, or $XDG_CACHE_HOME/fastvideo when XDG_CACHE_HOME is set.")
|
|
FASTVIDEO_REASON1_WEIGHTS_PATH = EnvStr(None,
|
|
category="path",
|
|
doc="Local path or Hugging Face id of Reason1 weights to load instead of the "
|
|
"checkpoint's own.")
|
|
|
|
# ================== Distributed ==================
|
|
|
|
FASTVIDEO_HOST_IP = EnvStr(
|
|
"",
|
|
category="distributed",
|
|
doc="IP address of this node when the node has several network interfaces. Set it on each node for multi-node "
|
|
"inference.")
|
|
FASTVIDEO_LOOPBACK_IP = EnvStr("",
|
|
category="distributed",
|
|
doc="Loopback IP address to use instead of the detected one.")
|
|
FASTVIDEO_RAY_PER_WORKER_GPUS = EnvFloat(
|
|
1.0,
|
|
category="distributed",
|
|
doc="GPUs per Ray worker. A fraction lets Ray schedule several actors on one GPU, so other actors can share "
|
|
"the GPUs with FastVideo.")
|
|
FASTVIDEO_NCCL_SO_PATH = EnvStr(
|
|
None,
|
|
category="distributed",
|
|
doc="Path to the NCCL library file. Needed because the nccl>=2.19 that PyTorch ships has a bug "
|
|
"(https://github.com/NVIDIA/nccl/issues/1234).")
|
|
FASTVIDEO_HCCL_SO_PATH = EnvStr(None,
|
|
category="distributed",
|
|
doc="Path to the HCCL library file on Ascend NPUs.",
|
|
deprecated_names=("HCCL_SO_PATH", ))
|
|
FASTVIDEO_WORKER_MULTIPROC_METHOD = EnvChoice("spawn",
|
|
choices=("spawn", "fork", "forkserver"),
|
|
category="distributed",
|
|
doc="Multiprocessing start method for worker processes.")
|
|
FASTVIDEO_ULYSSES_A2A = EnvChoice(
|
|
"off",
|
|
choices=("off", "auto"),
|
|
category="distributed",
|
|
doc="Sequence-parallel all-to-all backend. off uses the NCCL path in DistributedAutograd.AllToAll4D. auto uses "
|
|
"the fused NVLink kernel when the group is a load-store accessible mesh of 2, 4, 6, or 8 ranks in eager "
|
|
"execution, and the NCCL path otherwise.")
|
|
|
|
# ================== Logging ==================
|
|
|
|
FASTVIDEO_CONFIGURE_LOGGING = EnvBool(
|
|
True,
|
|
category="logging",
|
|
doc="Configure logging at import. When true, FastVideo uses its default logging configuration or the file in "
|
|
"FASTVIDEO_LOGGING_CONFIG_PATH.")
|
|
FASTVIDEO_LOGGING_CONFIG_PATH = EnvStr(None, category="logging", doc="Path to a JSON logging configuration file.")
|
|
FASTVIDEO_LOGGING_LEVEL = EnvStr("INFO", category="logging", doc="Default logging level.")
|
|
FASTVIDEO_LOGGING_PREFIX = EnvStr("", category="logging", doc="Prefix prepended to every log message.")
|
|
FASTVIDEO_STAGE_LOGGING = EnvBool(False, category="logging", doc="Log the time that each pipeline stage takes.")
|
|
|
|
# ================== Attention ==================
|
|
|
|
FASTVIDEO_ATTENTION_BACKEND = EnvStr(
|
|
None,
|
|
category="attention",
|
|
doc="Attention backend, as an AttentionBackendEnum name such as TORCH_SDPA, FLASH_ATTN, VIDEO_SPARSE_ATTN, "
|
|
"SAGE_ATTN, or SAGE_ATTN_THREE. FastVideoArgs uses it when FastVideoArgs.attention_backend is unset.")
|
|
# FA4 is opt-in and never auto-selected just because it is installed. Below
|
|
# sm90, grad-enabled and GQA calls are routed to FA2 (FA4's backward asserts
|
|
# sm90+ and its pack_gqa fails to JIT there).
|
|
FASTVIDEO_FA4 = EnvBool(False,
|
|
category="attention",
|
|
doc="The FLASH_ATTN backend uses FlashAttention-4 (flash_attn.cute) instead of FA3 or FA2.")
|
|
FASTVIDEO_MINIMAX_H3_FA4_PACKED_VARLEN = EnvBool(
|
|
False,
|
|
category="attention",
|
|
doc="MiniMax-H3 dense DiT self-attention uses the FlashAttention-4 packed-varlen entry point. This changes the "
|
|
"floating-point reduction order, so it is an inference-only opt-in.")
|
|
FASTVIDEO_VSA_SM100A = EnvBool(
|
|
False,
|
|
category="attention",
|
|
doc="VIDEO_SPARSE_ATTN_H3 sends no-grad tile-64 forwards to the data-center Blackwell (sm_100a) kernel. "
|
|
"fastvideo-kernel reads the same variable with the same rule.")
|
|
FASTVIDEO_NVFP4_FA4 = EnvBool(
|
|
False,
|
|
category="attention",
|
|
doc="FlashAttention-4 quantizes Q and K to NVFP4. An explicit nvfp4_fa4 attention implementation argument "
|
|
"takes precedence.")
|
|
FASTVIDEO_DISABLE_ATTENTION_COMPILE = EnvBool(
|
|
True,
|
|
category="attention",
|
|
doc="Keep attention forward out of torch.compile graphs (torch.compiler.disable). Set it to 0 to let attention "
|
|
"constructed under that setting be traced. Setting it explicitly to true also blocks regional compile.")
|
|
FASTVIDEO_MLX_WINDOW = EnvInt(0,
|
|
category="attention",
|
|
doc="MLX FastWan windowed attention size in tokens. 0 uses full attention.")
|
|
FASTVIDEO_MLX_WINDOW_SINK = EnvInt(0,
|
|
category="attention",
|
|
doc="Number of sink tokens that MLX windowed attention always attends to.")
|
|
|
|
# ================== Performance ==================
|
|
|
|
# Non-fullgraph-traceable attention backends such as VSA degrade to eager with
|
|
# one warning; see _regional_compile_unsupported_reason in
|
|
# fastvideo/models/loader/fsdp_load.py.
|
|
FASTVIDEO_INFERENCE_TORCH_COMPILE = EnvBool(
|
|
False,
|
|
category="performance",
|
|
doc="Compile each DiT transformer block with fullgraph torch.compile at inference. Same as "
|
|
"FastVideoArgs.inference_torch_compile=True.")
|
|
FASTVIDEO_VAE_PARALLEL_DECODE = EnvBool(
|
|
False,
|
|
category="performance",
|
|
doc="MiniMax-H3 VAE decode splits its temporal chunks across the sequence-parallel ranks instead of running "
|
|
"serially on the output rank. Same as FastVideoArgs.vae_parallel_decode=True.")
|
|
FASTVIDEO_VAE_PARALLEL_ENCODE = EnvBool(
|
|
False,
|
|
category="performance",
|
|
doc="MiniMax-H3 reference-video VAE encode splits its temporal chunks across the sequence-parallel ranks. "
|
|
"Same as FastVideoArgs.vae_parallel_encode=True.")
|
|
FASTVIDEO_VAE_PARALLEL_DECODE_STRATEGY = EnvStr(
|
|
None,
|
|
category="performance",
|
|
doc="Collective that moves chunks in parallel VAE decode: gather (used when unset) or all_gather.")
|
|
# Adapted from the NVlabs/Sana Sol-Engine implementation.
|
|
FASTVIDEO_MINIMAX_H3_FUSIONS = EnvStr(
|
|
"",
|
|
category="performance",
|
|
doc="MiniMax-H3 inference-only Triton fusions: all, 1, or a comma-separated subset of "
|
|
"modulate,qknorm_rope,swiglu. Empty, 0, or none keeps the eager implementation.")
|
|
FASTVIDEO_FSDP2_AUTOWRAP = EnvBool(False,
|
|
category="performance",
|
|
doc="FSDP2 shards modules by parameter count instead of the model's shard "
|
|
"conditions. Not supported by self-forcing distillation.")
|
|
FASTVIDEO_FSDP2_MIN_PARAMS = EnvInt(10000000,
|
|
category="performance",
|
|
doc="Minimum parameter count of a module that FASTVIDEO_FSDP2_AUTOWRAP shards.")
|
|
FASTVIDEO_MLX_COMPILE = EnvBool(False, category="performance", doc="Compile the MLX DiT forward with mx.compile.")
|
|
FASTVIDEO_MLX_FAST_NORM = EnvBool(False, category="performance", doc="Use MLX fast normalization kernels.")
|
|
FASTVIDEO_MLX_DQ_GEMM = EnvStr(
|
|
"1",
|
|
category="performance",
|
|
doc="MLX dequantized GEMM for affine-quantized weights: 0 turns it off, 1 uses the measured minimum row count, "
|
|
"and an integer sets the minimum row count.")
|
|
FASTVIDEO_LTX2_VAE_CHANNELS_LAST_3D = EnvBool(True,
|
|
category="performance",
|
|
doc="LTX-2 VAE uses the channels_last_3d memory format.")
|
|
FASTVIDEO_LTX2_DISABLE_AUDIO_AUTOCAST = EnvBool(True,
|
|
category="performance",
|
|
doc="LTX-2 audio decoding runs without CUDA autocast.",
|
|
deprecated_names=("LTX2_DISABLE_AUDIO_AUTOCAST", ))
|
|
FASTVIDEO_FLUX2_DISABLE_BF16_REDUCED_PRECISION_REDUCTION = EnvBool(
|
|
False,
|
|
category="performance",
|
|
doc="Flux denoising disables reduced-precision reductions in bf16 matmuls, which tightens accumulation for "
|
|
"the 4-step Klein model.")
|
|
|
|
# ================== Output encoding ==================
|
|
|
|
FASTVIDEO_FFMPEG_BIN = EnvStr("ffmpeg", category="output", doc="ffmpeg executable used to save video with audio.")
|
|
FASTVIDEO_VIDEO_CODEC = EnvStr("libx264", category="output", doc="ffmpeg video codec for saved videos.")
|
|
FASTVIDEO_NVENC_PRESET = EnvStr("p1", category="output", doc="NVENC preset when the codec is an *_nvenc codec.")
|
|
FASTVIDEO_NVENC_TUNE = EnvStr("ull", category="output", doc="NVENC tune option.")
|
|
FASTVIDEO_NVENC_RC = EnvStr("constqp", category="output", doc="NVENC rate-control mode.")
|
|
FASTVIDEO_NVENC_QP = EnvStr("28", category="output", doc="NVENC quantization parameter.")
|
|
FASTVIDEO_NVENC_BF = EnvStr("0", category="output", doc="NVENC number of B-frames.")
|
|
FASTVIDEO_X264_PRESET = EnvStr("ultrafast", category="output", doc="x264 preset for non-NVENC codecs.")
|
|
FASTVIDEO_OUTPUT_PIX_FMT = EnvStr("yuv420p", category="output", doc="ffmpeg pixel format for saved videos.")
|
|
|
|
# ================== Profiling ==================
|
|
|
|
FASTVIDEO_NVTX_PROFILE = EnvBool(False,
|
|
category="profiling",
|
|
doc="Emit NVTX ranges for external profilers such as Nsight Systems.")
|
|
FASTVIDEO_TORCH_PROFILER_DIR = EnvPath(
|
|
None,
|
|
category="profiling",
|
|
doc="Enables the torch profiler and sets the directory for its traces. Must be an absolute path.")
|
|
FASTVIDEO_TORCH_PROFILER_RECORD_SHAPES = EnvBool(False, category="profiling", doc="Torch profiler records shapes.")
|
|
FASTVIDEO_TORCH_PROFILER_WITH_PROFILE_MEMORY = EnvBool(False,
|
|
category="profiling",
|
|
doc="Torch profiler profiles memory.")
|
|
FASTVIDEO_TORCH_PROFILER_WITH_STACK = EnvBool(
|
|
False, category="profiling", doc="Torch profiler captures stacks. Costs about 1.5x runtime and 1.4x trace size.")
|
|
FASTVIDEO_TORCH_PROFILER_WITH_FLOPS = EnvBool(False, category="profiling", doc="Torch profiler profiles FLOPs.")
|
|
FASTVIDEO_TORCH_PROFILE_REGIONS = EnvStr(
|
|
"",
|
|
category="profiling",
|
|
doc="Comma-separated profiler regions to record. The torch profiler requires at least one region.")
|
|
|
|
# ================== Debug ==================
|
|
|
|
FASTVIDEO_TRACE_ACTIVATIONS = EnvBool(False, category="debug", doc="Enable activation trace hooks.")
|
|
FASTVIDEO_TRACE_LAYERS = EnvStr("", category="debug", doc="Regex filter for traced module names. Empty means all.")
|
|
FASTVIDEO_TRACE_STATS = EnvStr("abs_mean,sum",
|
|
category="debug",
|
|
doc="Comma-separated activation statistics dumped for each output tensor.")
|
|
FASTVIDEO_TRACE_OUTPUT = EnvStr("/tmp/fv_trace_<pid>.jsonl",
|
|
category="debug",
|
|
doc="JSONL path for activation traces. The literal <pid> is replaced at runtime.")
|
|
FASTVIDEO_TRACE_STEPS = EnvStr("", category="debug", doc="Comma-separated denoising step indices. Empty means all.")
|
|
FASTVIDEO_H3_VSA_PROBE = EnvStr(
|
|
None,
|
|
category="debug",
|
|
doc="Output directory for the VSA-H3 attention-mass probe, which writes one .pt file per step, layer, and rank. "
|
|
"Keeps the model out of regional compile.")
|
|
FASTVIDEO_LTX2_GEMMA_LOG = EnvStr("",
|
|
category="debug",
|
|
doc="Log file for LTX-2 Gemma text-encoder hidden states, used by parity tests.",
|
|
deprecated_names=("LTX2_FASTVIDEO_GEMMA_LOG", ))
|
|
FASTVIDEO_COSMOS25_LOG_KNOBS = EnvBool(False,
|
|
category="debug",
|
|
doc="Log the Cosmos 2.5 latent-preparation conditioning inputs.")
|
|
|
|
# ================== Sampling ==================
|
|
|
|
# CFG gating fraction for stale-uncond reuse (Adaptive Guidance / LinearAG
|
|
# variant — Castillo et al. 2023, arXiv:2312.12487). Float in [0, 1].
|
|
# Interpretation: for step index `i < len(timesteps) * X`, run both
|
|
# cond and uncond forwards and refresh delta_cached = cond - uncond.
|
|
# Once `i >= len(timesteps) * X`, skip the uncond forward and reuse
|
|
# the cached delta: noise_pred = cond + (guidance_scale - 1) * delta.
|
|
#
|
|
# Edge cases:
|
|
# 1.0 (default) : disables gating; identical to baseline two-pass CFG.
|
|
# 0.5 : run uncond for the first half of steps, reuse delta
|
|
# for the second half (~25% inference time saved on
|
|
# bandwidth-bound SP setups).
|
|
# 0.0 : step 0 still computes uncond fresh (cache is empty
|
|
# at start) — all subsequent steps reuse the step-0
|
|
# delta. This is the most aggressive setting; does
|
|
# NOT mean "no uncond forward ever."
|
|
#
|
|
# Caveats:
|
|
# - Algorithmically approximate; not bit-exact vs baseline CFG.
|
|
# Validate per-pipeline with SSIM / VBench before lowering below 1.0.
|
|
# - Interaction with `guidance_rescale > 0` is unvalidated; the
|
|
# denoising stage logs a warning when both are active.
|
|
# - Wan2.2 high/low-noise expert switch invalidates the cache.
|
|
FASTVIDEO_CFG_GATE_STEP = EnvFloat(
|
|
1.0,
|
|
category="sampling",
|
|
doc="CFG gating fraction in [0, 1]. Steps before len(timesteps) * X run the conditional and unconditional "
|
|
"forwards; later steps reuse the cached difference. 1.0 disables gating.")
|
|
FASTVIDEO_LTX2_USE_DISTILLED_SIGMAS = EnvBool(
|
|
True,
|
|
category="sampling",
|
|
doc="LTX-2 uses the distilled sigma schedule when FastVideoArgs.ltx2_use_distilled_sigmas is also true.",
|
|
deprecated_names=("LTX2_USE_DISTILLED_SIGMAS", ))
|
|
|
|
# ================== Evaluation ==================
|
|
|
|
FASTVIDEO_EVAL_CACHE = EnvPath(lambda: os.path.join(FASTVIDEO_CACHE_ROOT.get(), "eval"),
|
|
category="eval",
|
|
doc="Cache directory for evaluation models and datasets. Defaults to "
|
|
"$FASTVIDEO_CACHE_ROOT/eval.")
|
|
FASTVIDEO_PHYSICS_IQ_BUCKET_URL = EnvStr("https://storage.googleapis.com/physics-iq-benchmark",
|
|
category="eval",
|
|
doc="Base URL of the Physics-IQ benchmark bucket.")
|
|
FASTVIDEO_VBENCH_FULL_INFO_JSON = EnvStr(None,
|
|
category="eval",
|
|
doc="Path to VBench_full_info.json, used instead of the vendored copy.",
|
|
deprecated_names=("VBENCH_FULL_INFO_JSON", ))
|
|
FASTVIDEO_FVD_REF_FEATURES = EnvStr(None, category="eval", doc="Cached reference-feature file for the FVD metric.")
|
|
FASTVIDEO_FAD_REF_FEATURES = EnvStr(None,
|
|
category="eval",
|
|
doc="Cached reference-feature file for the audio Frechet distance metric.")
|
|
|
|
# ================== Tests ==================
|
|
|
|
FASTVIDEO_TEST_LTX2_OVERFIT_DATA_DIR = EnvStr("data/cats",
|
|
category="test",
|
|
doc="Raw data directory for preprocess_ltx2_overfit.py.",
|
|
deprecated_names=("LTX2_OVERFIT_DATA_DIR", ))
|
|
FASTVIDEO_TEST_LTX2_OVERFIT_CAPTION_JSON = EnvStr("videos2caption_1_sample.json",
|
|
category="test",
|
|
doc="Caption file, relative to the raw data directory.",
|
|
deprecated_names=("LTX2_OVERFIT_CAPTION_JSON", ))
|
|
FASTVIDEO_TEST_LTX2_OVERFIT_VIDEO_SUBDIR = EnvStr("video",
|
|
category="test",
|
|
doc="Video subdirectory, relative to the raw data directory.",
|
|
deprecated_names=("LTX2_OVERFIT_VIDEO_SUBDIR", ))
|
|
FASTVIDEO_TEST_LTX2_OVERFIT_OUTPUT_DIR = EnvStr("data/ltx2_overfit_preprocessed",
|
|
category="test",
|
|
doc="Output directory for preprocess_ltx2_overfit.py.",
|
|
deprecated_names=("LTX2_OVERFIT_OUTPUT_DIR", ))
|
|
FASTVIDEO_TEST_LTX2_OVERFIT_MODEL = EnvStr("FastVideo/LTX2-Distilled-Diffusers",
|
|
category="test",
|
|
doc="Model repository whose encoders preprocess_ltx2_overfit.py uses.",
|
|
deprecated_names=("LTX2_OVERFIT_MODEL", ))
|
|
FASTVIDEO_TEST_LTX2_OVERFIT_NUM_COPIES = EnvInt(4,
|
|
category="test",
|
|
doc="Number of copies of the overfit sample in the parquet file.",
|
|
deprecated_names=("LTX2_OVERFIT_NUM_COPIES", ))
|
|
FASTVIDEO_TEST_KANDINSKY5_OVERFIT_DATA_DIR = EnvStr("data/kandinsky5_overfit",
|
|
category="test",
|
|
doc="Raw data directory for preprocess_kandinsky5_overfit.py.",
|
|
deprecated_names=("KANDINSKY5_OVERFIT_DATA_DIR", ))
|
|
FASTVIDEO_TEST_KANDINSKY5_OVERFIT_OUTPUT_DIR = EnvStr("data/kandinsky5_overfit_preprocessed",
|
|
category="test",
|
|
doc="Output directory for preprocess_kandinsky5_overfit.py.",
|
|
deprecated_names=("KANDINSKY5_OVERFIT_OUTPUT_DIR", ))
|
|
|
|
# Variables that FastVideo no longer reads. Setting one logs a warning; delete
|
|
# the entries in the next minor release.
|
|
DEPRECATED_VARIABLES = {
|
|
"FASTVIDEO_TARGET_DEVICE": "no code reads it",
|
|
"FASTVIDEO_USE_PRECOMPILED": "no code reads it",
|
|
"FASTVIDEO_RINGBUFFER_WARNING_INTERVAL": "no code reads it",
|
|
"FASTVIDEO_ENGINE_ITERATION_TIMEOUT_S": "no code reads it",
|
|
"FASTVIDEO_SERVER_DEV_MODE": "no code reads it",
|
|
"FASTVIDEO_TEST_DYNAMO_FULLGRAPH_CAPTURE": "no code reads it",
|
|
"FASTVIDEO_TRACE_FUNCTION": "no code reads it",
|
|
}
|
|
|
|
|
|
def warn_deprecated_variables() -> None:
|
|
"""Log a warning for each variable in DEPRECATED_VARIABLES that is set."""
|
|
for name, reason in DEPRECATED_VARIABLES.items():
|
|
if name in os.environ:
|
|
_warn_once(f"{name} is deprecated and has no effect ({reason}); it will be removed in the next minor "
|
|
"release.")
|
|
|
|
|
|
def _register_fields() -> dict[str, EnvField]:
|
|
"""Name each module-level EnvField after its attribute and return the fields by name."""
|
|
fields = {name: value for name, value in globals().items() if isinstance(value, EnvField)}
|
|
for name, field in fields.items():
|
|
field.name = name
|
|
return fields
|
|
|
|
|
|
environment_variables: dict[str, EnvField] = _register_fields()
|