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
scripts/dataset: add build_eurorack_dry.py
Browse files
scripts/dataset/build_eurorack_dry.py
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Build one combined dry file to run through the Eurorack in a single pass.
|
| 2 |
+
|
| 3 |
+
WHY ONE FILE: processing every source in one continuous pass guarantees the patch
|
| 4 |
+
settings are identical across all of them. Doing it per-source is exactly what
|
| 5 |
+
broke the outdoor spaces — six sources ended up 0.11-0.33x the ambience level of
|
| 6 |
+
the others because the treatment drifted between renders.
|
| 7 |
+
|
| 8 |
+
GAPS BETWEEN SOURCES: a granular delay has a long, unpredictable tail. Without a
|
| 9 |
+
gap, source N's tail bleeds into source N+1's opening and every slice after the
|
| 10 |
+
first is contaminated. GAP_S of silence lets each tail decay before the next
|
| 11 |
+
source starts. The tail is still ringing at the 6 s mark, which is what the
|
| 12 |
+
dataset wants — clips are hard-cut with no fade, because a tail still sounding at
|
| 13 |
+
the boundary teaches the model that reverb continues past the window.
|
| 14 |
+
|
| 15 |
+
LEVELS: every source is normalised to the same ACTIVE loudness first, so the
|
| 16 |
+
patch sees consistent input. Active rather than peak because claps are sparse —
|
| 17 |
+
they read 12.7 dB quiet on RMS while sounding no quieter.
|
| 18 |
+
|
| 19 |
+
SOURCES: the 10 clean existing sources plus the 4 new recordings. The four
|
| 20 |
+
ElevenLabs sources are excluded — their Prohibited Use Policy bars training on
|
| 21 |
+
output, so they are being replaced by these recordings.
|
| 22 |
+
|
| 23 |
+
Writes the combined wav plus a manifest giving each source's exact offset, so the
|
| 24 |
+
processed return can be sliced back precisely.
|
| 25 |
+
"""
|
| 26 |
+
import csv
|
| 27 |
+
import subprocess
|
| 28 |
+
import wave
|
| 29 |
+
import os
|
| 30 |
+
from pathlib import Path
|
| 31 |
+
|
| 32 |
+
import numpy as np
|
| 33 |
+
|
| 34 |
+
SLICED = Path(os.environ.get("AKUSPACE_DATASET", "../../../../AUDIO-LTX-LORA/Dataset")) / "Sliced" / "dry"
|
| 35 |
+
NEW = Path(os.environ.get("AKUSPACE_DATASET", "../../../../AUDIO-LTX-LORA/Dataset")) / "male-female" / "female-male-dry.wav"
|
| 36 |
+
OUT = Path(os.environ.get("AKUSPACE_DATASET", "../../../../AUDIO-LTX-LORA/Dataset")) / "eurorack-input"
|
| 37 |
+
SR, SLOT_S, GAP_S = 48000, 6.0, 6.0
|
| 38 |
+
TARGET_ACTIVE_DB = -16.0
|
| 39 |
+
|
| 40 |
+
# ElevenLabs sources, excluded — being replaced by the new recordings
|
| 41 |
+
DROP = {"femaleTTS_1", "femaleTTS_2", "voice_scot_01", "voice_scot_02"}
|
| 42 |
+
# the new 24 s file is 4 x 6 s: female, female, male, male (iPhone)
|
| 43 |
+
NEW_SLICES = ["female_new_01", "female_new_02", "male_new_01", "male_new_02"]
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
def load(p, ch=2):
|
| 47 |
+
r = subprocess.run(["ffmpeg", "-v", "error", "-i", str(p), "-ac", str(ch),
|
| 48 |
+
"-ar", str(SR), "-f", "f32le", "-"], capture_output=True)
|
| 49 |
+
return np.frombuffer(r.stdout, dtype="<f4").astype(np.float64).reshape(-1, ch)
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
def save(x, p):
|
| 53 |
+
p.parent.mkdir(parents=True, exist_ok=True)
|
| 54 |
+
y = np.clip(x, -1.0, 1.0)
|
| 55 |
+
i = (y * 8388607.0).astype(np.int32)
|
| 56 |
+
b = np.stack([i & 0xFF, (i >> 8) & 0xFF, (i >> 16) & 0xFF], axis=-1).astype(np.uint8)
|
| 57 |
+
with wave.open(str(p), "wb") as w:
|
| 58 |
+
w.setnchannels(x.shape[1]); w.setsampwidth(3); w.setframerate(SR)
|
| 59 |
+
w.writeframes(b.tobytes())
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
def active_db(x):
|
| 63 |
+
m = x.mean(axis=1)
|
| 64 |
+
fr = SR // 20
|
| 65 |
+
n = len(m) // fr
|
| 66 |
+
if n < 5:
|
| 67 |
+
return 20 * np.log10(np.sqrt((m ** 2).mean()) + 1e-12)
|
| 68 |
+
f = np.sqrt((m[:n * fr].reshape(n, fr) ** 2).mean(axis=1))
|
| 69 |
+
a = f[f > f.max() * 0.1]
|
| 70 |
+
return 20 * np.log10(a.mean() + 1e-12) if a.size else -99.0
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
slot, gap = int(SLOT_S * SR), int(GAP_S * SR)
|
| 74 |
+
items = []
|
| 75 |
+
|
| 76 |
+
for p in sorted(SLICED.glob("*.wav")):
|
| 77 |
+
if p.stem in DROP:
|
| 78 |
+
continue
|
| 79 |
+
items.append((p.stem, load(p)[:slot]))
|
| 80 |
+
|
| 81 |
+
if NEW.exists():
|
| 82 |
+
n = load(NEW)
|
| 83 |
+
for i, name in enumerate(NEW_SLICES):
|
| 84 |
+
seg = n[i * slot:(i + 1) * slot]
|
| 85 |
+
if len(seg) >= slot // 2:
|
| 86 |
+
items.append((name, seg))
|
| 87 |
+
else:
|
| 88 |
+
print(f"!! missing {NEW}")
|
| 89 |
+
|
| 90 |
+
print(f"{'source':<20} {'active in':>10} {'gain':>7} {'offset':>9}")
|
| 91 |
+
print("-" * 52)
|
| 92 |
+
buf, rows, pos = [], [], 0.0
|
| 93 |
+
for name, x in items:
|
| 94 |
+
a = active_db(x)
|
| 95 |
+
g = 10 ** ((TARGET_ACTIVE_DB - a) / 20)
|
| 96 |
+
y = x * g
|
| 97 |
+
if len(y) < slot:
|
| 98 |
+
y = np.vstack([y, np.zeros((slot - len(y), y.shape[1]))])
|
| 99 |
+
buf.append(y)
|
| 100 |
+
buf.append(np.zeros((gap, y.shape[1])))
|
| 101 |
+
rows.append({"source": name, "start_s": f"{pos:.3f}",
|
| 102 |
+
"end_s": f"{pos + SLOT_S:.3f}", "gain_db": f"{20*np.log10(g):+.2f}"})
|
| 103 |
+
print(f"{name:<20} {a:>9.1f} {20*np.log10(g):>+6.1f} {pos:>8.1f}s")
|
| 104 |
+
pos += SLOT_S + GAP_S
|
| 105 |
+
|
| 106 |
+
combined = np.vstack(buf)
|
| 107 |
+
peak = 20 * np.log10(np.abs(combined).max() + 1e-12)
|
| 108 |
+
if peak > -3.0: # uniform trim, changes no ratio
|
| 109 |
+
combined *= 10 ** ((-3.0 - peak) / 20)
|
| 110 |
+
print(f"\n trimmed {-3.0 - peak:+.1f} dB for headroom")
|
| 111 |
+
|
| 112 |
+
save(combined, OUT / "eurorack_input_dry.wav")
|
| 113 |
+
with open(OUT / "eurorack_input_manifest.csv", "w", newline="") as fh:
|
| 114 |
+
w = csv.DictWriter(fh, fieldnames=list(rows[0].keys()))
|
| 115 |
+
w.writeheader(); w.writerows(rows)
|
| 116 |
+
|
| 117 |
+
print(f"\n{len(items)} sources, {SLOT_S:g}s each + {GAP_S:g}s gap")
|
| 118 |
+
print(f" total {len(combined)/SR:.1f}s peak {20*np.log10(np.abs(combined).max()+1e-12):+.1f} dBFS")
|
| 119 |
+
print(f" -> {OUT}/eurorack_input_dry.wav")
|
| 120 |
+
print(f" -> {OUT}/eurorack_input_manifest.csv (offsets for slicing the return)")
|
| 121 |
+
print("\nRun this whole file through the patch in ONE pass. Do not touch the")
|
| 122 |
+
print("controls between sources — the modulation varying is fine and even")
|
| 123 |
+
print("desirable, but the SEND LEVEL must stay constant or you reproduce the")
|
| 124 |
+
print("outdoor bug, where one caption meant different amounts on different sources.")
|