Skip to content
FastVideo
Esc
↑↓navigate↵open⌘Jpreview
On this page

minimax_h3_audio_vae

MiniMax-H3 audio VAE (DAC encoder + BigVGAN decoder) for Apple Silicon MLX.

Faithful port of fastvideo/models/vaes/minimax_h3_audio.py:

  • Encoder: plain-Snake residual units (dilations 1/3/9), strided down-sampling blocks, then the attention projection block — causal multi-head attention over the latent stream with q/v biases and a forced zero k bias, head averaging, average pooling into latent_channels streams, output projection, and a GeGLU MLP.
  • Decoder: 1x1 projection back to the trunk width, BigVGAN with weight-normalized ConvTranspose1d upsampling, AMP residual blocks with SnakeBeta behind alias-free Kaiser-window up/down sampling, final SnakeBeta
  • conv, and the [-1, 1] clamp.
  • Kaiser-window low-pass filters exactly as released; released filter buffers are used when present so numerics do not depend on window construction.

Waveforms are float32 in [-1, 1] at 32 kHz. Stereo latents (2, 32, N) decode independently while preserving channel order and duration. Production code never imports PyTorch; torch parity references live only in tests.

fastvideo.mlx_runtime.minimax_h3_audio_vae.init_logger

init_logger(name: str) -> _FastvideoLogger

The main purpose of this function is to ensure that loggers are retrieved in such a way that we can be sure the root fastvideo logger has already been configured.

fastvideo.mlx_runtime.minimax_h3_audio_vae.MiniMaxH3AudioVAEConfigView

MiniMaxH3AudioVAEConfigView(encoder_dim: int = 64, encoder_rates: tuple[int, ...] = (2, 4, 4, 5, 5), latent_dim: int = 2048, latent_channels: int = 32, num_attention_heads: int = 8, decoder_dim: int = 1024, decoder_rates: tuple[int, ...] = (5, 5, 2, 2, 2, 2, 2), decoder_kernel_sizes: tuple[int, ...] = (9, 9, 4, 4, 4, 4, 4), resblock_kernel_sizes: tuple[int, ...] = (3, 7, 11), resblock_dilation_sizes: tuple[tuple[int, ...], ...] = ((1, 3, 5), (1, 3, 5), (1, 3, 5)), sampling_rate: int = 32000, latents_mean: tuple[float, ...] | None = None, latents_std: tuple[float, ...] | None = None)

Architecture constants (defaults mirror the released audio_vae/config.json).

Source
@dataclass(frozen=True)
class MiniMaxH3AudioVAEConfigView:
    """Architecture constants (defaults mirror the released audio_vae/config.json)."""
encoder_dim: int = 64
encoder_rates: tuple[int, ...] = (2, 4, 4, 5, 5)
latent_dim: int = 2048
latent_channels: int = 32
num_attention_heads: int = 8
decoder_dim: int = 1024
decoder_rates: tuple[int, ...] = (5, 5, 2, 2, 2, 2, 2)
decoder_kernel_sizes: tuple[int, ...] = (9, 9, 4, 4, 4, 4, 4)
resblock_kernel_sizes: tuple[int, ...] = (3, 7, 11)
resblock_dilation_sizes: tuple[tuple[int, ...], ...] = ((1, 3, 5), (1, 3, 5), (1, 3, 5))
sampling_rate: int = 32000
latents_mean: tuple[float, ...] | None = None
latents_std: tuple[float, ...] | None = None

@classmethod
def from_vae_dir(cls, vae_dir: str | Path) -> MiniMaxH3AudioVAEConfigView:
    config = json.loads((Path(vae_dir) / "config.json").read_text())
    return cls(
        encoder_dim=int(config["encoder_dim"]),
        encoder_rates=tuple(int(v) for v in config["encoder_rates"]),
        latent_dim=int(config["latent_dim"]),
        latent_channels=int(config["latent_channels"]),
        num_attention_heads=int(config["num_attention_heads"]),
        decoder_dim=int(config["decoder_dim"]),
        decoder_rates=tuple(int(v) for v in config["decoder_rates"]),
        decoder_kernel_sizes=tuple(int(v) for v in config["decoder_kernel_sizes"]),
        resblock_kernel_sizes=tuple(int(v) for v in config["resblock_kernel_sizes"]),
        resblock_dilation_sizes=tuple(tuple(int(d) for d in group) for group in config["resblock_dilation_sizes"]),
        sampling_rate=int(config["sampling_rate"]),
        latents_mean=tuple(float(v) for v in config["latents_mean"]) if "latents_mean" in config else None,
        latents_std=tuple(float(v) for v in config["latents_std"]) if "latents_std" in config else None,
    )

@property
def hop_length(self) -> int:
    return math.prod(self.encoder_rates)</code></pre></details>

fastvideo.mlx_runtime.minimax_h3_audio_vae.MiniMaxH3AudioVAEConfigView.from_vae_dir

from_vae_dir(vae_dir: str | Path) -> MiniMaxH3AudioVAEConfigView
Source
@classmethod
def from_vae_dir(cls, vae_dir: str | Path) -> MiniMaxH3AudioVAEConfigView:
    config = json.loads((Path(vae_dir) / "config.json").read_text())
    return cls(
        encoder_dim=int(config["encoder_dim"]),
        encoder_rates=tuple(int(v) for v in config["encoder_rates"]),
        latent_dim=int(config["latent_dim"]),
        latent_channels=int(config["latent_channels"]),
        num_attention_heads=int(config["num_attention_heads"]),
        decoder_dim=int(config["decoder_dim"]),
        decoder_rates=tuple(int(v) for v in config["decoder_rates"]),
        decoder_kernel_sizes=tuple(int(v) for v in config["decoder_kernel_sizes"]),
        resblock_kernel_sizes=tuple(int(v) for v in config["resblock_kernel_sizes"]),
        resblock_dilation_sizes=tuple(tuple(int(d) for d in group) for group in config["resblock_dilation_sizes"]),
        sampling_rate=int(config["sampling_rate"]),
        latents_mean=tuple(float(v) for v in config["latents_mean"]) if "latents_mean" in config else None,
        latents_std=tuple(float(v) for v in config["latents_std"]) if "latents_std" in config else None,
    )

fastvideo.mlx_runtime.minimax_h3_audio_vae.kaiser_sinc_filter1d

kaiser_sinc_filter1d(cutoff: float, half_width: float, kernel_size: int) -> np.ndarray

NumPy replica of the released Kaiser-windowed sinc low-pass.

Source
def kaiser_sinc_filter1d(cutoff: float, half_width: float, kernel_size: int) -> np.ndarray:
    """NumPy replica of the released Kaiser-windowed sinc low-pass."""
    half_size = kernel_size // 2
    attenuation = 2.285 * (half_size - 1) * math.pi * (4 * half_width) + 7.95
    if attenuation > 50.0:
        beta = 0.1102 * (attenuation - 8.7)
    elif attenuation >= 21.0:
        beta = 0.5842 * (attenuation - 21)**0.4 + 0.07886 * (attenuation - 21.0)
    else:
        beta = 0.0
    window = np.kaiser(kernel_size, beta).astype(np.float32)  # periodic=False semantics
    if kernel_size % 2 == 0:
        time = np.arange(-half_size, half_size, dtype=np.float32) + 0.5
    else:
        time = np.arange(kernel_size, dtype=np.float32) - half_size
    filter_ = 2 * cutoff * window * np.sinc(2 * cutoff * time)
    filter_ /= filter_.sum()
    return filter_.astype(np.float32)

fastvideo.mlx_runtime.minimax_h3_audio_vae.MLXMiniMaxH3AudioVAE

MLXMiniMaxH3AudioVAE(weights: dict[str, Any], config: MiniMaxH3AudioVAEConfigView, *, include_encoder: bool = True)

DAC-style posterior encoder plus BigVGAN waveform decoder.

Source
class MLXMiniMaxH3AudioVAE:
    """DAC-style posterior encoder plus BigVGAN waveform decoder."""
def __init__(self, weights: dict&#91;str, Any&#93;, config: MiniMaxH3AudioVAEConfigView, *, include_encoder: bool = True):
    self.weights = weights
    self.config = config
    self.has_encoder = include_encoder
    self.latent_channels = config.latent_channels
    mean = config.latents_mean if config.latents_mean is not None else &#91;0.0&#93; * config.latent_channels
    std = config.latents_std if config.latents_std is not None else &#91;1.0&#93; * config.latent_channels
    self._latents_mean = np.asarray(mean, dtype=np.float32).reshape(1, -1, 1)
    self._latents_std = np.asarray(std, dtype=np.float32).reshape(1, -1, 1)

# -- normalization --------------------------------------------------

def normalize_latents(self, latents):
    return (latents - mx.array(self._latents_mean)) / mx.array(self._latents_std)

def denormalize_latents(self, latents):
    return latents * mx.array(self._latents_std) + mx.array(self._latents_mean)

def _filter(self, key: str) -&gt; mx.array:
    &quot;&quot;&quot;Released filter buffer flattened to (K,) (they ship as (1, 1, K)).&quot;&quot;&quot;
    try:
        return mx.reshape(self.weights&#91;key&#93;, (-1, ))
    except KeyError as exc:
        raise KeyError(f&quot;H3 audio VAE is missing released filter buffer &#x27;&#123;key&#125;&#x27;&quot;) from exc

# -- encoder ----------------------------------------------------------

def encode(self, waveform):
    &quot;&quot;&quot;Mono waveform (1, 1, S) -&gt; posterior mean/logvar each (1, C, N).&quot;&quot;&quot;
    if not self.has_encoder:
        raise RuntimeError(&quot;This MLX H3 audio VAE was loaded without encoder weights.&quot;)
    cfg = self.config
    w = self.weights
    samples = waveform.shape&#91;-1&#93;
    right_pad = math.ceil(samples / cfg.hop_length) * cfg.hop_length - samples
    if right_pad &gt; 0:
        waveform = mx.pad(waveform, ((0, 0), (0, 0), (0, right_pad)))

    x = _conv1d(waveform,
                _wn_weight(w&#91;&quot;encoder.block.0.weight_v&quot;&#93;, w&#91;&quot;encoder.block.0.weight_g&quot;&#93;),
                w&#91;&quot;encoder.block.0.bias&quot;&#93;,
                padding=3)
    dim = cfg.encoder_dim
    for index, stride in enumerate(cfg.encoder_rates, start=1):
        prefix = f&quot;encoder.block.&#123;index&#125;&quot;
        dim *= 2
        # Three residual units with dilations 1, 3, 9 at dim//2 channels.
        for unit, dilation in enumerate((1, 3, 9)):
            p = f&quot;&#123;prefix&#125;.block.&#123;unit&#125;&quot;
            residual = _snake(x, w&#91;f&quot;&#123;p&#125;.block.0.alpha&quot;&#93;)
            residual = _conv1d(residual,
                               _wn_weight(w&#91;f&quot;&#123;p&#125;.block.1.weight_v&quot;&#93;, w&#91;f&quot;&#123;p&#125;.block.1.weight_g&quot;&#93;),
                               w&#91;f&quot;&#123;p&#125;.block.1.bias&quot;&#93;,
                               padding=((7 - 1) * dilation) // 2,
                               dilation=dilation)
            residual = _snake(residual, w&#91;f&quot;&#123;p&#125;.block.2.alpha&quot;&#93;)
            residual = _conv1d(residual, _wn_weight(w&#91;f&quot;&#123;p&#125;.block.3.weight_v&quot;&#93;, w&#91;f&quot;&#123;p&#125;.block.3.weight_g&quot;&#93;),
                               w&#91;f&quot;&#123;p&#125;.block.3.bias&quot;&#93;)
            pad = (x.shape&#91;-1&#93; - residual.shape&#91;-1&#93;) // 2
            if pad &gt; 0:
                x = x&#91;..., pad:-pad&#93;
            x = x + residual
        x = _snake(x, w&#91;f&quot;&#123;prefix&#125;.block.3.alpha&quot;&#93;)
        x = _conv1d(x,
                    _wn_weight(w&#91;f&quot;&#123;prefix&#125;.block.4.weight_v&quot;&#93;, w&#91;f&quot;&#123;prefix&#125;.block.4.weight_g&quot;&#93;),
                    w&#91;f&quot;&#123;prefix&#125;.block.4.bias&quot;&#93;,
                    stride=stride,
                    padding=math.ceil(stride / 2))
    snake_index = len(cfg.encoder_rates) + 1
    conv_index = len(cfg.encoder_rates) + 2
    x = _snake(x, w&#91;f&quot;encoder.block.&#123;snake_index&#125;.alpha&quot;&#93;)
    hidden = _conv1d(x,
                     _wn_weight(w&#91;f&quot;encoder.block.&#123;conv_index&#125;.weight_v&quot;&#93;,
                                w&#91;f&quot;encoder.block.&#123;conv_index&#125;.weight_g&quot;&#93;),
                     w&#91;f&quot;encoder.block.&#123;conv_index&#125;.bias&quot;&#93;,
                     padding=1)

    projected = _ct(self._attention_projection(_ct(hidden, 0, 2, 1)), 0, 2, 1)
    mean = _conv1d(projected, w&#91;&quot;mean_proj.weight&quot;&#93;, w&#91;&quot;mean_proj.bias&quot;&#93;)
    logvar = _conv1d(projected, w&#91;&quot;logs_proj.weight&quot;&#93;, w&#91;&quot;logs_proj.bias&quot;&#93;)
    return mean, logvar

def _attention_projection(self, hidden):
    &quot;&quot;&quot;MiniMaxH3AudioAttnProjection over (B, S, latent_dim).&quot;&quot;&quot;
    cfg = self.config
    w = self.weights
    num_heads = cfg.num_attention_heads
    head_dim = hidden.shape&#91;-1&#93; // num_heads
    batch, seq_len, _ = hidden.shape

    normed = _layer_norm(hidden, w&#91;&quot;pre_block.norm1.weight&quot;&#93;, w&#91;&quot;pre_block.norm1.bias&quot;&#93;)
    bias = mx.concatenate(&#91;w&#91;&quot;pre_block.attn.q_bias&quot;&#93;, w&#91;&quot;pre_block.attn.zero_k_bias&quot;&#93;, w&#91;&quot;pre_block.attn.v_bias&quot;&#93;&#93;)
    qkv = _linear(normed, w&#91;&quot;pre_block.attn.qkv.weight&quot;&#93;, bias)
    qkv = qkv.reshape(batch, seq_len, 3, num_heads, head_dim)
    query = _ct(qkv&#91;:, :, 0&#93;, 0, 2, 1, 3)  # (B, H, S, Dh)
    key = _ct(qkv&#91;:, :, 1&#93;, 0, 2, 1, 3)
    value = _ct(qkv&#91;:, :, 2&#93;, 0, 2, 1, 3)

    scores = (query @ _ct(key, 0, 1, 3, 2)) * head_dim**-0.5
    causal_mask = mx.triu(mx.ones((seq_len, seq_len), dtype=mx.bool_), k=1)
    scores = mx.where(causal_mask&#91;None, None&#93;, mx.array(-np.inf, dtype=scores.dtype), scores)
    attn_weights = mx.softmax(scores, axis=-1)
    attended = attn_weights @ value  # (B, H, S, Dh)
    attended = _ct(attended, 0, 2, 1, 3).mean(axis=2)  # head mean -&gt; (B, S, Dh)

    out_dim = cfg.latent_channels
    pool_factor = attended.shape&#91;-1&#93; // out_dim
    if attended.shape&#91;-1&#93; % out_dim != 0:
        raise ValueError(&quot;Attention head dimension must pool evenly into latent channels.&quot;)
    pooled = attended.reshape(batch, seq_len, out_dim, pool_factor).mean(axis=-1)
    attn_out = _linear(pooled, w&#91;&quot;pre_block.attn.proj.weight&quot;&#93;, w&#91;&quot;pre_block.attn.proj.bias&quot;&#93;)

    projected = _linear(_layer_norm(hidden, w&#91;&quot;pre_block.norm3.weight&quot;&#93;, w&#91;&quot;pre_block.norm3.bias&quot;&#93;),
                        w&#91;&quot;pre_block.proj.weight&quot;&#93;, w&#91;&quot;pre_block.proj.bias&quot;&#93;) + attn_out
    mlp_in = _layer_norm(projected, w&#91;&quot;pre_block.norm2.weight&quot;&#93;, w&#91;&quot;pre_block.norm2.bias&quot;&#93;)
    # GeGluMlp carries its own inner LayerNorm before w0/w1.
    mlp_normed = _layer_norm(mlp_in, w&#91;&quot;pre_block.mlp.norm.weight&quot;&#93;, w&#91;&quot;pre_block.mlp.norm.bias&quot;&#93;)
    gate = _gelu_tanh(_linear(mlp_normed, w&#91;&quot;pre_block.mlp.w0.weight&quot;&#93;, w&#91;&quot;pre_block.mlp.w0.bias&quot;&#93;))
    value_mlp = _linear(mlp_normed, w&#91;&quot;pre_block.mlp.w1.weight&quot;&#93;, w&#91;&quot;pre_block.mlp.w1.bias&quot;&#93;)
    mlp_out = _linear(gate * value_mlp, w&#91;&quot;pre_block.mlp.w2.weight&quot;&#93;, w&#91;&quot;pre_block.mlp.w2.bias&quot;&#93;)
    return projected + mlp_out

# -- decoder ----------------------------------------------------------

def decode(self, latents):
    &quot;&quot;&quot;Latents (B, 32, N) -&gt; waveforms (B, 1, S) clamped to &#91;-1, 1&#93;.&quot;&quot;&quot;
    cfg = self.config
    w = self.weights
    hidden = _conv1d(latents, w&#91;&quot;dec_in_proj.weight&quot;&#93;, w&#91;&quot;dec_in_proj.bias&quot;&#93;)
    hidden = _conv1d(hidden,
                     _wn_weight(w&#91;&quot;decoder.conv_pre.weight_v&quot;&#93;, w&#91;&quot;decoder.conv_pre.weight_g&quot;&#93;),
                     w&#91;&quot;decoder.conv_pre.bias&quot;&#93;,
                     padding=3)
    num_resblocks = len(cfg.resblock_kernel_sizes)
    for index, (rate, kernel) in enumerate(zip(cfg.decoder_rates, cfg.decoder_kernel_sizes, strict=False)):
        weight = _wn_weight(w&#91;f&quot;decoder.ups.&#123;index&#125;.0.weight_v&quot;&#93;, w&#91;f&quot;decoder.ups.&#123;index&#125;.0.weight_g&quot;&#93;)
        hidden = _conv_transpose1d(hidden,
                                   weight,
                                   w&#91;f&quot;decoder.ups.&#123;index&#125;.0.bias&quot;&#93;,
                                   stride=rate,
                                   padding=(kernel - rate) // 2)
        residual_sum = None
        for j in range(num_resblocks):
            out = self._amp_block(hidden, f&quot;decoder.resblocks.&#123;index * num_resblocks + j&#125;&quot;,
                                  cfg.resblock_kernel_sizes&#91;j&#93;, cfg.resblock_dilation_sizes&#91;j&#93;)
            residual_sum = out if residual_sum is None else residual_sum + out
        if residual_sum is None:
            raise RuntimeError(&quot;H3 audio VAE decoder has no residual blocks.&quot;)
        hidden = residual_sum / num_resblocks
    alpha = w&#91;&quot;decoder.activation_post.act.alpha&quot;&#93;
    beta = w&#91;&quot;decoder.activation_post.act.beta&quot;&#93;
    up_filter = self._filter(&quot;decoder.activation_post.upsample.filter&quot;)
    down_filter = self._filter(&quot;decoder.activation_post.downsample.lowpass.filter&quot;)
    hidden = _activation1d(hidden, alpha, beta, up_filter, down_filter)
    hidden = _conv1d(hidden,
                     _wn_weight(w&#91;&quot;decoder.conv_post.weight_v&quot;&#93;, w&#91;&quot;decoder.conv_post.weight_g&quot;&#93;),
                     w.get(&quot;decoder.conv_post.bias&quot;),
                     padding=3)
    return mx.clip(hidden, -1.0, 1.0)

def _amp_block(self, x, prefix: str, kernel_size: int, dilations: tuple&#91;int, ...&#93;):
    &quot;&quot;&quot;MiniMaxH3AudioAMPBlock: per dilation, act -&gt; conv1 -&gt; act -&gt; conv2 + skip.&quot;&quot;&quot;
    w = self.weights
    for j, dilation in enumerate(dilations):
        pad1 = (kernel_size * dilation - dilation) // 2
        pad2 = (kernel_size - 1) // 2
        up1 = self._filter(f&quot;&#123;prefix&#125;.activations.&#123;2 * j&#125;.upsample.filter&quot;)
        down1 = self._filter(f&quot;&#123;prefix&#125;.activations.&#123;2 * j&#125;.downsample.lowpass.filter&quot;)
        residual = _activation1d(x, w&#91;f&quot;&#123;prefix&#125;.activations.&#123;2 * j&#125;.act.alpha&quot;&#93;,
                                 w&#91;f&quot;&#123;prefix&#125;.activations.&#123;2 * j&#125;.act.beta&quot;&#93;, up1, down1)
        residual = _conv1d(residual,
                           _wn_weight(w&#91;f&quot;&#123;prefix&#125;.convs1.&#123;j&#125;.weight_v&quot;&#93;, w&#91;f&quot;&#123;prefix&#125;.convs1.&#123;j&#125;.weight_g&quot;&#93;),
                           w&#91;f&quot;&#123;prefix&#125;.convs1.&#123;j&#125;.bias&quot;&#93;,
                           padding=pad1,
                           dilation=dilation)
        up2 = self._filter(f&quot;&#123;prefix&#125;.activations.&#123;2 * j + 1&#125;.upsample.filter&quot;)
        down2 = self._filter(f&quot;&#123;prefix&#125;.activations.&#123;2 * j + 1&#125;.downsample.lowpass.filter&quot;)
        residual = _activation1d(residual, w&#91;f&quot;&#123;prefix&#125;.activations.&#123;2 * j + 1&#125;.act.alpha&quot;&#93;,
                                 w&#91;f&quot;&#123;prefix&#125;.activations.&#123;2 * j + 1&#125;.act.beta&quot;&#93;, up2, down2)
        residual = _conv1d(residual,
                           _wn_weight(w&#91;f&quot;&#123;prefix&#125;.convs2.&#123;j&#125;.weight_v&quot;&#93;, w&#91;f&quot;&#123;prefix&#125;.convs2.&#123;j&#125;.weight_g&quot;&#93;),
                           w&#91;f&quot;&#123;prefix&#125;.convs2.&#123;j&#125;.bias&quot;&#93;,
                           padding=pad2)
        x = residual + x
    return x</code></pre></details>

fastvideo.mlx_runtime.minimax_h3_audio_vae.MLXMiniMaxH3AudioVAE.normalize_latents

normalize_latents(latents)
Source
def normalize_latents(self, latents):
    return (latents - mx.array(self._latents_mean)) / mx.array(self._latents_std)

fastvideo.mlx_runtime.minimax_h3_audio_vae.MLXMiniMaxH3AudioVAE.denormalize_latents

denormalize_latents(latents)
Source
def denormalize_latents(self, latents):
    return latents * mx.array(self._latents_std) + mx.array(self._latents_mean)

fastvideo.mlx_runtime.minimax_h3_audio_vae.MLXMiniMaxH3AudioVAE.encode

encode(waveform)

Mono waveform (1, 1, S) -> posterior mean/logvar each (1, C, N).

Source
def encode(self, waveform):
    """Mono waveform (1, 1, S) -> posterior mean/logvar each (1, C, N)."""
    if not self.has_encoder:
        raise RuntimeError("This MLX H3 audio VAE was loaded without encoder weights.")
    cfg = self.config
    w = self.weights
    samples = waveform.shape[-1]
    right_pad = math.ceil(samples / cfg.hop_length) * cfg.hop_length - samples
    if right_pad > 0:
        waveform = mx.pad(waveform, ((0, 0), (0, 0), (0, right_pad)))
x = _conv1d(waveform,
            _wn_weight(w&#91;&quot;encoder.block.0.weight_v&quot;&#93;, w&#91;&quot;encoder.block.0.weight_g&quot;&#93;),
            w&#91;&quot;encoder.block.0.bias&quot;&#93;,
            padding=3)
dim = cfg.encoder_dim
for index, stride in enumerate(cfg.encoder_rates, start=1):
    prefix = f&quot;encoder.block.&#123;index&#125;&quot;
    dim *= 2
    # Three residual units with dilations 1, 3, 9 at dim//2 channels.
    for unit, dilation in enumerate((1, 3, 9)):
        p = f&quot;&#123;prefix&#125;.block.&#123;unit&#125;&quot;
        residual = _snake(x, w&#91;f&quot;&#123;p&#125;.block.0.alpha&quot;&#93;)
        residual = _conv1d(residual,
                           _wn_weight(w&#91;f&quot;&#123;p&#125;.block.1.weight_v&quot;&#93;, w&#91;f&quot;&#123;p&#125;.block.1.weight_g&quot;&#93;),
                           w&#91;f&quot;&#123;p&#125;.block.1.bias&quot;&#93;,
                           padding=((7 - 1) * dilation) // 2,
                           dilation=dilation)
        residual = _snake(residual, w&#91;f&quot;&#123;p&#125;.block.2.alpha&quot;&#93;)
        residual = _conv1d(residual, _wn_weight(w&#91;f&quot;&#123;p&#125;.block.3.weight_v&quot;&#93;, w&#91;f&quot;&#123;p&#125;.block.3.weight_g&quot;&#93;),
                           w&#91;f&quot;&#123;p&#125;.block.3.bias&quot;&#93;)
        pad = (x.shape&#91;-1&#93; - residual.shape&#91;-1&#93;) // 2
        if pad &gt; 0:
            x = x&#91;..., pad:-pad&#93;
        x = x + residual
    x = _snake(x, w&#91;f&quot;&#123;prefix&#125;.block.3.alpha&quot;&#93;)
    x = _conv1d(x,
                _wn_weight(w&#91;f&quot;&#123;prefix&#125;.block.4.weight_v&quot;&#93;, w&#91;f&quot;&#123;prefix&#125;.block.4.weight_g&quot;&#93;),
                w&#91;f&quot;&#123;prefix&#125;.block.4.bias&quot;&#93;,
                stride=stride,
                padding=math.ceil(stride / 2))
snake_index = len(cfg.encoder_rates) + 1
conv_index = len(cfg.encoder_rates) + 2
x = _snake(x, w&#91;f&quot;encoder.block.&#123;snake_index&#125;.alpha&quot;&#93;)
hidden = _conv1d(x,
                 _wn_weight(w&#91;f&quot;encoder.block.&#123;conv_index&#125;.weight_v&quot;&#93;,
                            w&#91;f&quot;encoder.block.&#123;conv_index&#125;.weight_g&quot;&#93;),
                 w&#91;f&quot;encoder.block.&#123;conv_index&#125;.bias&quot;&#93;,
                 padding=1)

projected = _ct(self._attention_projection(_ct(hidden, 0, 2, 1)), 0, 2, 1)
mean = _conv1d(projected, w&#91;&quot;mean_proj.weight&quot;&#93;, w&#91;&quot;mean_proj.bias&quot;&#93;)
logvar = _conv1d(projected, w&#91;&quot;logs_proj.weight&quot;&#93;, w&#91;&quot;logs_proj.bias&quot;&#93;)
return mean, logvar</code></pre></details>

fastvideo.mlx_runtime.minimax_h3_audio_vae.MLXMiniMaxH3AudioVAE.decode

decode(latents)

Latents (B, 32, N) -> waveforms (B, 1, S) clamped to [-1, 1].

Source
def decode(self, latents):
    """Latents (B, 32, N) -> waveforms (B, 1, S) clamped to [-1, 1]."""
    cfg = self.config
    w = self.weights
    hidden = _conv1d(latents, w["dec_in_proj.weight"], w["dec_in_proj.bias"])
    hidden = _conv1d(hidden,
                     _wn_weight(w["decoder.conv_pre.weight_v"], w["decoder.conv_pre.weight_g"]),
                     w["decoder.conv_pre.bias"],
                     padding=3)
    num_resblocks = len(cfg.resblock_kernel_sizes)
    for index, (rate, kernel) in enumerate(zip(cfg.decoder_rates, cfg.decoder_kernel_sizes, strict=False)):
        weight = _wn_weight(w[f"decoder.ups.{index}.0.weight_v"], w[f"decoder.ups.{index}.0.weight_g"])
        hidden = _conv_transpose1d(hidden,
                                   weight,
                                   w[f"decoder.ups.{index}.0.bias"],
                                   stride=rate,
                                   padding=(kernel - rate) // 2)
        residual_sum = None
        for j in range(num_resblocks):
            out = self._amp_block(hidden, f"decoder.resblocks.{index * num_resblocks + j}",
                                  cfg.resblock_kernel_sizes[j], cfg.resblock_dilation_sizes[j])
            residual_sum = out if residual_sum is None else residual_sum + out
        if residual_sum is None:
            raise RuntimeError("H3 audio VAE decoder has no residual blocks.")
        hidden = residual_sum / num_resblocks
    alpha = w["decoder.activation_post.act.alpha"]
    beta = w["decoder.activation_post.act.beta"]
    up_filter = self._filter("decoder.activation_post.upsample.filter")
    down_filter = self._filter("decoder.activation_post.downsample.lowpass.filter")
    hidden = _activation1d(hidden, alpha, beta, up_filter, down_filter)
    hidden = _conv1d(hidden,
                     _wn_weight(w["decoder.conv_post.weight_v"], w["decoder.conv_post.weight_g"]),
                     w.get("decoder.conv_post.bias"),
                     padding=3)
    return mx.clip(hidden, -1.0, 1.0)

fastvideo.mlx_runtime.minimax_h3_audio_vae.mlx_h3_audio_vae_from_file

mlx_h3_audio_vae_from_file(weights_path: str | Path, *, include_encoder: bool = True, config: MiniMaxH3AudioVAEConfigView | None = None, component_dir: str | Path | None = None) -> MLXMiniMaxH3AudioVAE

Load the released audio VAE from its single safetensors file.

The released checkpoint is ~605 MB fp32; it is read whole (bounded) and kept at release precision.

Source
def mlx_h3_audio_vae_from_file(weights_path: str | Path,
                               *,
                               include_encoder: bool = True,
                               config: MiniMaxH3AudioVAEConfigView | None = None,
                               component_dir: str | Path | None = None) -> MLXMiniMaxH3AudioVAE:
    """Load the released audio VAE from its single safetensors file.
The released checkpoint is ~605 MB fp32; it is read whole (bounded) and
kept at release precision.
&quot;&quot;&quot;
weights_path = Path(weights_path)
if config is None:
    if component_dir is None:
        component_dir = weights_path.parent
    config = MiniMaxH3AudioVAEConfigView.from_vae_dir(component_dir)
arrays = mx.load(str(weights_path))
wanted_prefixes: tuple&#91;str, ...&#93; = (&quot;dec_in_proj.&quot;, &quot;decoder.&quot;, &quot;mean_proj.&quot;, &quot;logs_proj.&quot;)
if include_encoder:
    wanted_prefixes += (&quot;encoder.&quot;, &quot;pre_block.&quot;)
weights: dict&#91;str, Any&#93; = &#123;&#125;
for key in arrays:
    if key.startswith(wanted_prefixes):
        weights&#91;key&#93; = arrays&#91;key&#93;
del arrays
gc.collect()
mx.clear_cache()
required = &#91;&quot;dec_in_proj.weight&quot;, &quot;decoder.conv_pre.weight_v&quot;, &quot;decoder.conv_post.weight_v&quot;&#93;
if include_encoder:
    required.extend(
        (&quot;mean_proj.weight&quot;, &quot;logs_proj.weight&quot;, &quot;pre_block.attn.qkv.weight&quot;, &quot;encoder.block.0.weight_v&quot;))
missing = &#91;key for key in required if key not in weights&#93;
if missing:
    raise KeyError(f&quot;H3 audio VAE is missing required tensors: &#123;missing&#125;&quot;)
return MLXMiniMaxH3AudioVAE(weights, config, include_encoder=include_encoder)</code></pre></details>

fastvideo.mlx_runtime.minimax_h3_audio_vae.mlx_h3_audio_vae_from_dir

mlx_h3_audio_vae_from_dir(component_dir: str | Path, *, include_encoder: bool = True, storage_dtype: str = 'fp32') -> MLXMiniMaxH3AudioVAE

Load from the released component directory (audio_vae/).

Source
def mlx_h3_audio_vae_from_dir(component_dir: str | Path,
                              *,
                              include_encoder: bool = True,
                              storage_dtype: str = "fp32") -> MLXMiniMaxH3AudioVAE:
    """Load from the released component directory (audio_vae/)."""
    if storage_dtype != "fp32":
        raise ValueError(f"H3 audio VAE numerics require storage_dtype='fp32', got {storage_dtype!r}.")
component_dir = Path(component_dir)
single = component_dir / &quot;diffusion_pytorch_model.safetensors&quot;
if not single.exists():
    raise FileNotFoundError(f&quot;No audio VAE safetensors under &#123;component_dir&#125;&quot;)
return mlx_h3_audio_vae_from_file(single, include_encoder=include_encoder, component_dir=component_dir)</code></pre></details>

Was this page helpful?