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_v5_outdoor.py
Browse files
scripts/dataset/build_v5_outdoor.py
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Add the two outdoor places to v5-rooms — de-ghosted, beds exactly as rendered.
|
| 2 |
+
|
| 3 |
+
These are PLACES, not spaces — an ambience bed rather than a reverb. The bed is
|
| 4 |
+
never scaled in either direction: boosting a bed amplifies the field recording's
|
| 5 |
+
own noise floor (tried; sounded unnatural), and pulling everything down to the
|
| 6 |
+
quietest loses the space. Two levels only, cut downward from the render: "high"
|
| 7 |
+
is the bed as rendered, "low" 8 dB under it.
|
| 8 |
+
|
| 9 |
+
THE DE-GHOST: the old render batches carry the dry at 0.74x (day) / 0.67x
|
| 10 |
+
(night) for the eight old non-clap sources — a flat level offset from
|
| 11 |
+
render-batch drift, while claps and the four new voices sit at 1.00. Building
|
| 12 |
+
R = w - d straight from those renders buries a negative ghost of the dry inside
|
| 13 |
+
R, which dominated every naive ambience measurement (the ghost alone reads
|
| 14 |
+
-9.5 dB in night, which is why the old sources "measured" -9.4) and taught two
|
| 15 |
+
transforms under one caption: "duck the voice ~3 dB + bed" on eight sources,
|
| 16 |
+
"keep the voice + bed" on six. So the dry is projected out of each render and
|
| 17 |
+
every pair is rebuilt on a unity dry: bed = w - fit*d, wet = d + bed. True bed
|
| 18 |
+
levels are consistent across sources (day -11..-24, night -19..-28); the
|
| 19 |
+
"17 dB spread" and "claps 10 dB low" stories were artifacts of the ghost.
|
| 20 |
+
|
| 21 |
+
Chosen in the 08-13 A/B (Dataset/v5-outdoor-compare/): both versions sound
|
| 22 |
+
near-identical by ear, so the de-ghosted one wins on consistency — all 28
|
| 23 |
+
outdoor pairs teach the same transform, matching every room and SFX pair.
|
| 24 |
+
"""
|
| 25 |
+
import subprocess
|
| 26 |
+
import wave
|
| 27 |
+
import os
|
| 28 |
+
from pathlib import Path
|
| 29 |
+
|
| 30 |
+
import numpy as np
|
| 31 |
+
|
| 32 |
+
SR, SLOT = 48000, 6 * 48000
|
| 33 |
+
BASE = Path(os.environ.get("AKUSPACE_DATASET", "../../../../AUDIO-LTX-LORA/Dataset"))
|
| 34 |
+
SLICED, MF, OUT = BASE / "Sliced", BASE / "male-female", BASE / "v5-rooms"
|
| 35 |
+
DROP = {"femaleTTS_1", "femaleTTS_2", "voice_scot_01", "voice_scot_02"}
|
| 36 |
+
MF_SRC = ["female_new_01", "female_new_02", "male_new_01", "male_new_02"]
|
| 37 |
+
CEILING_DB = -3.0
|
| 38 |
+
LOW_OFFSET_DB = -8.0 # "low" sits this far under "high"
|
| 39 |
+
|
| 40 |
+
SPACES = {
|
| 41 |
+
"outdoor_day_birds": ("outdoor_day_birds", "female-male-outside.wav"),
|
| 42 |
+
"outdoor_night": ("outdoor_night", "female-male-outside-night.wav"),
|
| 43 |
+
}
|
| 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 db(x):
|
| 63 |
+
return 20 * np.log10(np.sqrt((x ** 2).mean()) + 1e-12)
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
base, batch = {}, {}
|
| 67 |
+
dmf = load(MF / "female-male-dry.wav")
|
| 68 |
+
for space, (folder, mffile) in SPACES.items():
|
| 69 |
+
for p in sorted((SLICED / "dry").glob("*.wav")):
|
| 70 |
+
src = p.stem
|
| 71 |
+
if src in DROP:
|
| 72 |
+
continue
|
| 73 |
+
wp = SLICED / folder / f"{src}.wav"
|
| 74 |
+
if not wp.exists():
|
| 75 |
+
continue
|
| 76 |
+
d, w = load(p)[:SLOT], load(wp)
|
| 77 |
+
n = min(len(d), len(w), SLOT)
|
| 78 |
+
base[(src, space)] = (d[:n], w[:n] - d[:n])
|
| 79 |
+
batch[(src, space)] = "existing"
|
| 80 |
+
mp = MF / mffile
|
| 81 |
+
if mp.exists():
|
| 82 |
+
w = load(mp)
|
| 83 |
+
for i, src in enumerate(MF_SRC):
|
| 84 |
+
a, b = i * SLOT, (i + 1) * SLOT
|
| 85 |
+
d, ws = dmf[a:b], w[a:b]
|
| 86 |
+
n = min(len(d), len(ws))
|
| 87 |
+
base[(src, space)] = (d[:n], ws[:n] - d[:n])
|
| 88 |
+
batch[(src, space)] = "new"
|
| 89 |
+
|
| 90 |
+
print(f"{'source':<16} {'space':<20} {'batch':<10} {'fit':>6} {'naive':>8} {'bed':>8}")
|
| 91 |
+
print("-" * 76)
|
| 92 |
+
out = {}
|
| 93 |
+
for space in SPACES:
|
| 94 |
+
for (src, sp), (d, R) in sorted(base.items()):
|
| 95 |
+
if sp != space:
|
| 96 |
+
continue
|
| 97 |
+
naive = db(R.mean(axis=1)) - db(d.mean(axis=1))
|
| 98 |
+
# project the dry out of the render; fit = 1 + c, with c the ghost
|
| 99 |
+
# coefficient (about -0.33 on the night old sources, ~0 on claps and
|
| 100 |
+
# the new voices). The residual is the true bed, kept as rendered —
|
| 101 |
+
# the bed itself is never scaled up or down.
|
| 102 |
+
c = float(np.dot(R.ravel(), d.ravel()) / (np.dot(d.ravel(), d.ravel()) + 1e-12))
|
| 103 |
+
bed = R - c * d
|
| 104 |
+
out[(src, space, "high")] = (d, bed)
|
| 105 |
+
out[(src, space, "low")] = (d, bed * 10 ** (LOW_OFFSET_DB / 20))
|
| 106 |
+
print(f"{src:<16} {space:<20} {batch[(src, sp)]:<10} {1 + c:>6.3f} "
|
| 107 |
+
f"{naive:>+7.1f} {db(bed.mean(axis=1)) - db(d.mean(axis=1)):>+7.1f}")
|
| 108 |
+
print(f"{'':<16} {space:<20} beds as rendered on a unity dry; low = high {LOW_OFFSET_DB:+g} dB\n")
|
| 109 |
+
|
| 110 |
+
peak = max(20 * np.log10(np.abs(d + R).max() + 1e-12) for d, R in out.values())
|
| 111 |
+
trim = min(0.0, CEILING_DB - peak)
|
| 112 |
+
print(f"loudest {peak:+.1f} dBFS -> uniform trim {trim:+.1f} dB")
|
| 113 |
+
for (src, space, lv), (d, R) in out.items():
|
| 114 |
+
g = 10 ** (trim / 20)
|
| 115 |
+
save((d + R) * g, OUT / space / lv / f"{src}.wav")
|
| 116 |
+
save(d * g, OUT / space / "dry" / f"{src}.wav")
|
| 117 |
+
|
| 118 |
+
import shutil
|
| 119 |
+
for space in SPACES: # drop the old single-level folder
|
| 120 |
+
old = OUT / space / "bed"
|
| 121 |
+
if old.exists():
|
| 122 |
+
shutil.rmtree(old)
|
| 123 |
+
|
| 124 |
+
print(f"\n{len(out)} pairs -> {OUT} ({len(SPACES)} places x 2 levels)")
|