Instructions to use KoshiMazaki/akuspace-ltx25 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- LTX.io
How to use KoshiMazaki/akuspace-ltx25 with LTX.io:
# Install the LTX-2 pipelines git clone https://github.com/Lightricks/LTX-2.git cd LTX-2 uv sync --frozen
# Download the weights from this repo, plus the Gemma text encoder hf download KoshiMazaki/akuspace-ltx25 --local-dir models/akuspace-ltx25 hf download google/gemma-3-12b-it-qat-q4_0-unquantized --local-dir models/gemma-3-12b
# Text/image-to-video with the LoRA on the HQ two-stage base pipeline uv run python -m ltx_pipelines.ti2vid_two_stages_hq \ --checkpoint-path path/to/checkpoint.safetensors \ --distilled-lora path/to/distilled_lora.safetensors 0.8 \ --spatial-upsampler-path path/to/spatial_upsampler.safetensors \ --gemma-root models/gemma-3-12b \ --lora models/akuspace-ltx25/<weights>.safetensors 1.0 \ --prompt "your prompt here" \ --output-path output.mp4 # For image-to-video, add: --image path/to/image.jpg 0 0.8 - Reverb
How to use KoshiMazaki/akuspace-ltx25 with Reverb:
# No code snippets available yet for this library. # To use this model, check the repository files and the library's documentation. # Want to help? PRs adding snippets are welcome at: # https://github.com/huggingface/huggingface.js
- Notebooks
- Google Colab
- Kaggle
| """Pre-flight checks for the acoustic-space dataset. Run before every training run. | |
| Every check here exists because something slipped past a weaker one: | |
| grid a source missing from one space silently shrinks that space's | |
| coverage; the manifest still builds and training still runs | |
| duration a failed rsync left a file TRUNCATED, not missing. Presence | |
| checks passed. Only a duration sweep caught it, and preprocessing | |
| silently skipped the item (71 of 72) while reporting exit 0 | |
| integrity the same failure again, 2026-08-10, in the place this script did | |
| not look: an interrupted write left a TARGET holding 0.54s of | |
| audio under a header still declaring 6.000s. Byte-for-byte it was | |
| 9% present. Every header-based reader called it healthy; only the | |
| VAE refused it, months of "mysterious VAE skip" later. Bytes are | |
| the only honest witness, and the BUILT dataset needs checking, | |
| not just the slices -- the corruption was written by the copy step | |
| format mixed sample rate / channel count reaches the VAE as garbage | |
| level if one source is much louder than the rest, the model can learn | |
| loudness as a cue for space instead of learning the space | |
| depth how far each render sits from its dry source. Catches a space | |
| that was rendered near-dry by mistake -- the failure mode that | |
| would teach contradictory things under one caption | |
| Exit code is non-zero if anything fails, so it can gate a pipeline. | |
| python verify_dataset.py <sliced_dir> [--expect-seconds 6.0] [--manifest path] | |
| [--dataset-dir <.../audio>] | |
| Pass --dataset-dir to also byte-check the built references/ and targets/. Do it | |
| on every run: the slices can be perfect while the copy of them is not. | |
| """ | |
| import argparse | |
| import subprocess | |
| import sys | |
| import wave | |
| from pathlib import Path | |
| import numpy as np | |
| # Spaces that add an environmental bed rather than pure reverb. Level variation | |
| # across sources is DELIBERATE here (it stops the model memorising one exact | |
| # ambient recording), so depth outliers are not flagged as errors. | |
| AMBIENCE_SPACES = {"outdoor_day_birds", "outdoor_night"} | |
| def probe_duration(p: Path) -> float: | |
| r = subprocess.run( | |
| ["ffprobe", "-v", "error", "-show_entries", "format=duration", | |
| "-of", "default=nw=1:nk=1", str(p)], | |
| capture_output=True, text=True, | |
| ) | |
| try: | |
| return float(r.stdout.strip()) | |
| except ValueError: | |
| return -1.0 | |
| def probe_format(p: Path) -> tuple: | |
| r = subprocess.run( | |
| ["ffprobe", "-v", "error", "-select_streams", "a", | |
| "-show_entries", "stream=sample_rate,channels", "-of", "csv=p=0", str(p)], | |
| capture_output=True, text=True, | |
| ) | |
| parts = r.stdout.strip().split(",") | |
| try: | |
| return int(parts[0]), int(parts[1]) | |
| except (IndexError, ValueError): | |
| return (0, 0) | |
| def probe_integrity(p: Path) -> tuple: | |
| """Compare the frame count a WAV declares against the audio data really there. | |
| A truncated WAV keeps its original header, so anything reading length from | |
| metadata -- wave.getnframes(), soundfile.info(), most "duration" fields -- | |
| reports the ORIGINAL length for a file that is mostly gone. ffprobe's | |
| format=duration is the exception, deriving duration from real size. | |
| Returns (ok, real_bytes, expected_bytes, real_seconds). | |
| """ | |
| try: | |
| with wave.open(str(p), "rb") as w: | |
| n, ch, sw, sr = w.getnframes(), w.getnchannels(), w.getsampwidth(), w.getframerate() | |
| real = len(w.readframes(n)) | |
| except Exception: | |
| return False, 0, 0, 0.0 | |
| expected = n * ch * sw | |
| bps = ch * sw * sr | |
| # tolerate a padding byte, not a missing chunk | |
| return real >= expected - 4, real, expected, (real / bps if bps else 0.0) | |
| def load_mono(p: Path, sr: int = 24000) -> np.ndarray: | |
| tmp = Path(f"/tmp/_vd_{p.parent.name[:12]}_{p.stem[:16]}.wav") | |
| subprocess.run( | |
| ["ffmpeg", "-y", "-v", "error", "-i", str(p), "-ac", "1", "-ar", str(sr), str(tmp)], | |
| capture_output=True, | |
| ) | |
| try: | |
| with wave.open(str(tmp)) as w: | |
| return np.frombuffer(w.readframes(w.getnframes()), dtype=np.int16).astype(float) / 32768.0 | |
| except Exception: | |
| return np.array([]) | |
| def main() -> int: | |
| ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) | |
| ap.add_argument("sliced_dir") | |
| ap.add_argument("--expect-seconds", type=float, default=6.0) | |
| ap.add_argument("--tolerance", type=float, default=0.05) | |
| ap.add_argument("--manifest", default=None) | |
| ap.add_argument("--dataset-dir", default=None, | |
| help="built dataset audio/ dir; byte-checks references/ and targets/ too") | |
| ap.add_argument("--allow-longer", action="store_true", | |
| help="permit renders longer than expected (cathedral tails); still flags SHORT files") | |
| args = ap.parse_args() | |
| D = Path(args.sliced_dir) | |
| if not (D / "dry").is_dir(): | |
| print(f"no dry/ directory under {D}") | |
| return 2 | |
| spaces = sorted(d.name for d in D.iterdir() if d.is_dir() and d.name != "dry") | |
| sources = sorted(p.stem for p in (D / "dry").glob("*.wav")) | |
| fails = [] | |
| print(f"sources: {len(sources)} spaces: {len(spaces)}") | |
| print() | |
| # --- 1. grid completeness ------------------------------------------------- | |
| missing = [(s, sp) for s in sources for sp in spaces if not (D / sp / f"{s}.wav").exists()] | |
| print(f"[grid] {'FAIL' if missing else 'ok '} {len(sources)*len(spaces)} expected, {len(missing)} missing") | |
| for s, sp in missing[:10]: | |
| print(f" missing: {sp}/{s}.wav") | |
| if missing: | |
| fails.append("grid") | |
| # --- 2. duration ---------------------------------------------------------- | |
| bad_dur = [] | |
| for p in sorted(D.rglob("*.wav")): | |
| d = probe_duration(p) | |
| short = d < args.expect_seconds - args.tolerance | |
| long_ = d > args.expect_seconds + args.tolerance | |
| if short or (long_ and not args.allow_longer): | |
| bad_dur.append((p.relative_to(D), d)) | |
| print(f"[duration] {'FAIL' if bad_dur else 'ok '} expecting {args.expect_seconds}s" | |
| f"{' (longer allowed)' if args.allow_longer else ''}, {len(bad_dur)} wrong") | |
| for rel, d in bad_dur[:10]: | |
| print(f" {rel} {d:.2f}s") | |
| if bad_dur: | |
| fails.append("duration") | |
| # --- 3. byte-level integrity ---------------------------------------------- | |
| # The duration check above would catch truncation, but only where it is | |
| # pointed, and it was only ever pointed at the slices. The one corruption | |
| # this project has had was written into the BUILT dataset by the copy step, | |
| # which nothing verified at all. | |
| roots = [("sliced", D)] | |
| if args.dataset_dir: | |
| ds = Path(args.dataset_dir) | |
| for sub in ("references", "targets"): | |
| if (ds / sub).is_dir(): | |
| roots.append((sub, ds / sub)) | |
| else: | |
| print(f"[integrity] warning: no {sub}/ under {ds}") | |
| truncated, n_checked = [], 0 | |
| for label, root in roots: | |
| for p in sorted(root.rglob("*.wav")): | |
| n_checked += 1 | |
| ok, real, expected, secs = probe_integrity(p) | |
| if not ok: | |
| truncated.append((label, p.name, real, expected, secs)) | |
| print(f"[integrity] {'FAIL' if truncated else 'ok '} {n_checked} files byte-checked" | |
| f"{'' if args.dataset_dir else ' (slices only -- pass --dataset-dir)'}" | |
| f", {len(truncated)} truncated") | |
| for label, name, real, expected, secs in truncated[:10]: | |
| pct = 100.0 * real / expected if expected else 0.0 | |
| print(f" {label}/{name}") | |
| print(f" {real:,} of {expected:,} bytes ({pct:.1f}%) = {secs:.2f}s of real audio") | |
| if truncated: | |
| fails.append("integrity") | |
| # --- 4. format ------------------------------------------------------------ | |
| fmts = {} | |
| for p in sorted(D.rglob("*.wav")): | |
| fmts.setdefault(probe_format(p), []).append(p.relative_to(D)) | |
| print(f"[format] {'FAIL' if len(fmts) > 1 else 'ok '} {len(fmts)} distinct (sample_rate, channels)") | |
| for f, ps in fmts.items(): | |
| print(f" {f}: {len(ps)} files" + (f" e.g. {ps[0]}" if len(fmts) > 1 else "")) | |
| if len(fmts) > 1: | |
| fails.append("format") | |
| # --- 5. dry source levels ------------------------------------------------- | |
| levels = {} | |
| for s in sources: | |
| x = load_mono(D / "dry" / f"{s}.wav") | |
| if x.size: | |
| levels[s] = 20 * np.log10(np.sqrt((x ** 2).mean()) + 1e-12) | |
| if levels: | |
| lo, hi = min(levels.values()), max(levels.values()) | |
| spread = hi - lo | |
| # a wide spread is fine when it is transient material (claps): check peaks too | |
| print(f"[level] ok dry RMS spread {spread:.1f} dB " | |
| f"({min(levels, key=levels.get)} {lo:.1f} .. {max(levels, key=levels.get)} {hi:.1f})") | |
| if spread > 15: | |
| print(" note: >15 dB spread. Fine for sparse transients (claps sit low on RMS,") | |
| print(" high on peak); worth checking if it is a genuinely quiet recording.") | |
| # --- 6. processing depth -------------------------------------------------- | |
| print("[depth] rel_diff = RMS(wet-dry)/RMS(dry) per space, across sources") | |
| for sp in spaces: | |
| vals = [] | |
| for s in sources: | |
| wp, dp = D / sp / f"{s}.wav", D / "dry" / f"{s}.wav" | |
| if not wp.exists(): | |
| continue | |
| w, d = load_mono(wp), load_mono(dp) | |
| if not w.size or not d.size: | |
| continue | |
| n = min(len(w), len(d)) | |
| vals.append(float(np.sqrt(((w[:n] - d[:n]) ** 2).mean()) / (np.sqrt((d[:n] ** 2).mean()) + 1e-12))) | |
| if not vals: | |
| continue | |
| med, lo, hi = float(np.median(vals)), min(vals), max(vals) | |
| note = "" | |
| if sp in AMBIENCE_SPACES: | |
| note = " (ambience bed - level variation is deliberate)" | |
| elif lo < 0.25 * med: | |
| note = " <- OUTLIER: some source rendered near-dry" | |
| fails.append(f"depth:{sp}") | |
| print(f" {sp:24} median {med:.3f} range {lo:.3f}-{hi:.3f}{note}") | |
| # --- 7. manifest ---------------------------------------------------------- | |
| # Two manifest shapes reach this script: the PAIRS grid (id / reference_audio | |
| # / audio / split) and the SLICES report (output / source_id / environment). | |
| # Reading pair columns off a slices.csv raised KeyError and exited 1 *after* | |
| # every check had already passed -- a green run reported as a failure. | |
| if args.manifest: | |
| import csv | |
| rows = list(csv.DictReader(open(args.manifest))) | |
| base = Path(args.manifest).parent | |
| cols = set(rows[0]) if rows else set() | |
| print() | |
| if {"reference_audio", "audio"} <= cols: | |
| path_cols, id_col = ("reference_audio", "audio"), "id" | |
| elif "output" in cols: | |
| path_cols, id_col = ("output",), "output" | |
| else: | |
| path_cols, id_col = (), "" | |
| print(f"[manifest] skip {len(rows)} rows, unrecognised columns: {sorted(cols)}") | |
| if path_cols: | |
| broken = [r.get(id_col, "?") for r in rows for k in path_cols | |
| if not (base / r[k]).resolve().exists()] | |
| n_train = sum(1 for r in rows if r.get("split") == "train") | |
| print(f"[manifest] {'FAIL' if broken else 'ok '} {len(rows)} rows, {n_train} train, " | |
| f"{len(broken)} broken paths, {n_train // max(len(spaces),1)} train sources/space") | |
| for b in broken[:6]: | |
| print(f" broken: {b}") | |
| if broken: | |
| fails.append("manifest") | |
| print() | |
| if fails: | |
| print(f"FAILED: {', '.join(sorted(set(fails)))}") | |
| return 1 | |
| print("all checks passed - safe to preprocess") | |
| return 0 | |
| if __name__ == "__main__": | |
| sys.exit(main()) | |