Audio-to-Audio
PyTorch
ONNX
Safetensors
TensorRT
English
fast_oobleck_decoder
ace-step
audio
vae
knowledge-distillation
music-generation
streaming
dreamvae
custom_code
Instructions to use daydreamlive/DreamVAE with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- TensorRT
How to use daydreamlive/DreamVAE with TensorRT:
# 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
File size: 11,103 Bytes
53e74f7 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 | #!/usr/bin/env python3
"""Export FastOobleckDecoder checkpoint to ONNX and build a TRT engine.
The student decoder has the exact same I/O contract as the teacher
(latents [B, 64, T] -> audio [B, 2, samples]), so we reuse the existing
VAE TRT build pipeline. The resulting engine is a drop-in replacement.
Usage:
uv run python research_program/vae_distillation/export_trt.py \
--ckpt research_program/vae_distillation/checkpoints/student_step620000.pt
# FP32 engine (if FP16 has Snake1d issues):
uv run python research_program/vae_distillation/export_trt.py \
--ckpt research_program/vae_distillation/checkpoints/student_step620000.pt \
--no-fp16
# Custom output directory:
uv run python research_program/vae_distillation/export_trt.py \
--ckpt ... --output-dir trt_engines
"""
import argparse
import logging
import math
import sys
from pathlib import Path
import torch
import torch.nn as nn
from torch.nn.utils import weight_norm
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
logger = logging.getLogger(__name__)
# =========================================================================
# Student model definition (must match training script exactly)
# =========================================================================
class Snake1d(nn.Module):
def __init__(self, hidden_dim, logscale=True):
super().__init__()
self.alpha = nn.Parameter(torch.zeros(1, hidden_dim, 1))
self.beta = nn.Parameter(torch.zeros(1, hidden_dim, 1))
self.alpha.requires_grad = True
self.beta.requires_grad = True
self.logscale = logscale
def forward(self, hidden_states):
shape = hidden_states.shape
alpha = self.alpha if not self.logscale else torch.exp(self.alpha)
beta = self.beta if not self.logscale else torch.exp(self.beta)
hidden_states = hidden_states.reshape(shape[0], shape[1], -1)
hidden_states = hidden_states + (beta + 1e-9).reciprocal() * torch.sin(alpha * hidden_states).pow(2)
hidden_states = hidden_states.reshape(shape)
return hidden_states
class FastResidualUnit(nn.Module):
def __init__(self, dim: int, dilation: int = 1):
super().__init__()
pad = ((7 - 1) * dilation) // 2
self.snake1 = Snake1d(dim)
self.conv1 = weight_norm(nn.Conv1d(dim, dim, kernel_size=7, dilation=dilation, padding=pad))
self.snake2 = Snake1d(dim)
self.conv2 = weight_norm(nn.Conv1d(dim, dim, kernel_size=1))
def forward(self, x):
h = self.conv1(self.snake1(x))
h = self.conv2(self.snake2(h))
pad = (x.shape[-1] - h.shape[-1]) // 2
if pad > 0:
x = x[..., pad:-pad]
return x + h
class FastDecoderBlock(nn.Module):
def __init__(self, in_dim: int, out_dim: int, stride: int = 1):
super().__init__()
self.snake1 = Snake1d(in_dim)
self.conv_t = weight_norm(nn.ConvTranspose1d(
in_dim, out_dim, kernel_size=2 * stride, stride=stride,
padding=math.ceil(stride / 2),
))
self.res1 = FastResidualUnit(out_dim, dilation=1)
self.res2 = FastResidualUnit(out_dim, dilation=3)
def forward(self, x):
x = self.snake1(x)
x = self.conv_t(x)
x = self.res1(x)
x = self.res2(x)
return x
class FastOobleckDecoder(nn.Module):
def __init__(self, channels=128, input_channels=64, audio_channels=2,
upsampling_ratios=None, channel_multiples=None):
super().__init__()
if upsampling_ratios is None:
upsampling_ratios = [10, 6, 4, 4, 2]
if channel_multiples is None:
channel_multiples = [1, 2, 4, 8, 8]
cm = [1] + channel_multiples
self.conv1 = weight_norm(nn.Conv1d(input_channels, channels * cm[-1], kernel_size=7, padding=3))
blocks = []
for i, stride in enumerate(upsampling_ratios):
in_dim = channels * cm[len(upsampling_ratios) - i]
out_dim = channels * cm[len(upsampling_ratios) - i - 1]
blocks.append(FastDecoderBlock(in_dim, out_dim, stride=stride))
self.blocks = nn.ModuleList(blocks)
self.final_snake = Snake1d(channels)
self.conv2 = weight_norm(nn.Conv1d(channels, audio_channels, kernel_size=7, padding=3, bias=False))
def forward(self, latents: torch.Tensor) -> torch.Tensor:
x = self.conv1(latents)
for block in self.blocks:
x = block(x)
x = self.final_snake(x)
x = self.conv2(x)
return x
# =========================================================================
# Export
# =========================================================================
def export_onnx(student: nn.Module, onnx_path: Path, device: str = "cuda"):
"""Export student decoder to ONNX with dynamic latent length."""
onnx_path.parent.mkdir(parents=True, exist_ok=True)
# Trace with 30s worth of latent frames (750 = 30s * 25 fps)
example = torch.randn(1, 64, 750, device=device, dtype=torch.float32)
logger.info("Tracing student decoder for ONNX export...")
with torch.no_grad():
torch.onnx.export(
student,
(example,),
str(onnx_path),
input_names=["latents"],
output_names=["audio"],
dynamic_axes={
"latents": {0: "batch", 2: "latent_frames"},
"audio": {0: "batch", 2: "samples"},
},
opset_version=18,
do_constant_folding=True,
dynamo=False,
)
logger.info("ONNX saved to %s (%.1f MB)", onnx_path, onnx_path.stat().st_size / (1 << 20))
return onnx_path
def build_engine(onnx_path: Path, engine_path: Path, fp16: bool = True):
"""Build TRT engine using the same config as the teacher VAE decoder."""
# Import the existing build infrastructure
sys.path.insert(0, str(Path(__file__).resolve().parents[2]))
from acestep.engine.trt.vae_export import VAETRTBuildConfig, build_vae_decode_engine
config = VAETRTBuildConfig(fp16=fp16)
return build_vae_decode_engine(str(onnx_path), str(engine_path), config=config)
def verify_engine(engine_path: Path, device: str = "cuda"):
"""Quick sanity check: run a dummy input through the engine."""
from polygraphy.backend.common import bytes_from_path
from polygraphy.backend.trt import engine_from_bytes
from polygraphy import cuda as pg_cuda
engine = engine_from_bytes(bytes_from_path(str(engine_path)))
ctx = engine.create_execution_context()
stream = pg_cuda.Stream()
# 10s of audio = 250 latent frames
T = 250
latents = torch.randn(1, 64, T, device=device, dtype=torch.float32).contiguous()
ctx.set_input_shape("latents", (1, 64, T))
ctx.set_tensor_address("latents", latents.data_ptr())
out_shape = tuple(ctx.get_tensor_shape("audio"))
audio_buf = torch.empty(out_shape, dtype=torch.float32, device=device)
ctx.set_tensor_address("audio", audio_buf.data_ptr())
ok = ctx.execute_async_v3(stream.ptr)
stream.synchronize()
expected_samples = T * 1920 # hop length
assert ok, "TRT execution failed"
assert out_shape == (1, 2, expected_samples), f"Shape mismatch: {out_shape} vs (1, 2, {expected_samples})"
assert not torch.isnan(audio_buf).any(), "NaN in output"
assert audio_buf.abs().max() > 1e-6, "Output is all zeros"
logger.info("Engine verification passed: input [1, 64, %d] -> output %s, range [%.4f, %.4f]",
T, list(out_shape), audio_buf.min().item(), audio_buf.max().item())
# Quick speed check
import time
torch.cuda.synchronize()
times = []
for _ in range(20):
torch.cuda.synchronize()
t0 = time.time()
ctx.execute_async_v3(stream.ptr)
stream.synchronize()
times.append(time.time() - t0)
avg_ms = sum(times) / len(times) * 1000
logger.info("TRT speed (10s audio, 20 trials): %.1f ms avg", avg_ms)
def main():
parser = argparse.ArgumentParser(description="Export FastOobleckDecoder to ONNX + TRT")
parser.add_argument("--ckpt", type=str, required=True, help="Path to student checkpoint .pt")
parser.add_argument("--output-dir", type=str, default=None,
help="Output directory (default: trt_engines/ in project root)")
parser.add_argument("--no-fp16", action="store_true", help="Build FP32 engine instead of FP16")
parser.add_argument("--skip-engine", action="store_true", help="Only export ONNX, skip TRT build")
parser.add_argument("--skip-verify", action="store_true", help="Skip engine verification")
parser.add_argument("--device", type=str, default="cuda")
args = parser.parse_args()
ckpt_path = Path(args.ckpt)
step = "unknown"
# Determine output paths
project_root = Path(__file__).resolve().parents[2]
if args.output_dir:
out_dir = Path(args.output_dir)
else:
out_dir = project_root / "trt_engines"
# Load student
logger.info("Loading checkpoint: %s", ckpt_path)
ckpt = torch.load(ckpt_path, map_location=args.device, weights_only=False)
config = ckpt.get("config", {})
student = FastOobleckDecoder(
channels=config.get("channels", 128),
input_channels=config.get("input_channels", 64),
audio_channels=config.get("audio_channels", 2),
upsampling_ratios=config.get("upsampling_ratios", [10, 6, 4, 4, 2]),
channel_multiples=config.get("channel_multiples", [1, 2, 4, 8, 8]),
).to(args.device).eval()
student.load_state_dict(ckpt["student_state_dict"])
step = ckpt.get("step", "unknown")
params_m = sum(p.numel() for p in student.parameters()) / 1e6
logger.info("Student loaded: step %s, %.1fM params", step, params_m)
# ONNX export
onnx_dir = out_dir / "_onnx" / "dreamvae_decode"
onnx_path = onnx_dir / "dreamvae_decode.onnx"
export_onnx(student, onnx_path, device=args.device)
if args.skip_engine:
logger.info("Skipping TRT engine build (--skip-engine)")
return
# TRT engine build
fp16 = not args.no_fp16
prec = "fp16" if fp16 else "fp32"
engine_name = f"dreamvae_decode_{prec}_240s"
engine_dir = out_dir / engine_name
engine_path = engine_dir / f"{engine_name}.engine"
logger.info("Building TRT engine (%s)...", prec)
build_engine(onnx_path, engine_path, fp16=fp16)
if not args.skip_verify:
logger.info("Verifying engine...")
verify_engine(engine_path, device=args.device)
logger.info("Done. Engine: %s", engine_path)
logger.info("To use as drop-in replacement, pass this engine path where vae_decode engine is expected.")
if __name__ == "__main__":
main()
|