Download helpers.py from Opera8/LTX-2-3: direct link, hf CLI and curl.
- Browser
- Download file 2.23 kB
-
https://huggingface.co/spaces/Opera8/LTX-2-3/resolve/main/helpers.py
- Command line
-
hf download hf://spaces/Opera8/LTX-2-3/helpers.py
-
curl -L -o helpers.py https://huggingface.co/spaces/Opera8/LTX-2-3/resolve/main/helpers.py
2.23 kB
| """Pure helper functions (no torch / gradio imports, so they are easy to test).""" | |
| from __future__ import annotations | |
| DEFAULT_FRAME_RATE = 24.0 | |
| # Resolution presets: (width, height). All values are multiples of 64, which the | |
| # two-stage pipeline (half-res stage 1 -> x2 upscale -> stage 2) requires. | |
| RESOLUTIONS = { | |
| "high": {"16:9": (1536, 1024), "9:16": (1024, 1536), "1:1": (1024, 1024)}, | |
| "low": {"16:9": (768, 512), "9:16": (512, 768), "1:1": (768, 768)}, | |
| } | |
| RESOLUTION_MULTIPLE = 64 | |
| MIN_SIDE = 256 | |
| MAX_SIDE = 2048 | |
| def snap_dimension(value, multiple: int = RESOLUTION_MULTIPLE, lo: int = MIN_SIDE, hi: int = MAX_SIDE) -> int: | |
| """Round ``value`` to the nearest multiple of ``multiple`` inside [lo, hi]. | |
| The UI exposes free-form Width/Height boxes; an arbitrary value such as 1000 | |
| would crash the pipeline, so we always snap before generating. | |
| """ | |
| try: | |
| v = float(value) | |
| except (TypeError, ValueError): | |
| v = float(lo) | |
| snapped = int(round(v / multiple)) * multiple | |
| return max(lo, min(hi, snapped)) | |
| def compute_num_frames(duration: float, frame_rate: float = DEFAULT_FRAME_RATE) -> int: | |
| """Number of frames for ``duration`` seconds, in the 8k+1 form LTX expects.""" | |
| frames = int(float(duration) * frame_rate) + 1 | |
| return ((frames - 1 + 7) // 8) * 8 + 1 | |
| def detect_aspect_ratio(image) -> str: | |
| """Closest of '16:9', '9:16', '1:1' for a PIL image / numpy array (default 16:9).""" | |
| if image is None: | |
| return "16:9" | |
| size = getattr(image, "size", None) | |
| if isinstance(size, tuple) and len(size) == 2: # PIL.Image -> (w, h) | |
| w, h = size | |
| elif hasattr(image, "shape"): # numpy array -> (h, w, ...); its .size is an int | |
| h, w = image.shape[:2] | |
| else: | |
| return "16:9" | |
| if not w or not h: | |
| return "16:9" | |
| ratio = w / h | |
| candidates = {"16:9": 16 / 9, "9:16": 9 / 16, "1:1": 1.0} | |
| return min(candidates, key=lambda k: abs(ratio - candidates[k])) | |
| def pick_resolution(image, high_res: bool) -> tuple[int, int]: | |
| """(width, height) preset matching the image's aspect ratio and the quality tier.""" | |
| tier = "high" if high_res else "low" | |
| return RESOLUTIONS[tier][detect_aspect_ratio(image)] | |