---
title: oobleck
---

<div class="python-reference">
<a id="fastvideo.models.vaes.oobleck-classes"></a>
<a id="fastvideo.models.vaes.oobleck-functions"></a>
<a id="fastvideo.models.vaes.oobleck.OobleckVAE-functions"></a>
<a id="fastvideo.models.vaes.oobleck"></a>
<p>Stable Audio Open 1.0 "Oobleck" VAE.</p>
<p>5-stage Conv1d autoencoder with Snake activations + diagonal-Gaussian
bottleneck. Loads <code>stabilityai/stable-audio-open-1.0/vae/</code> weights
directly via <code>OobleckVAE.from_pretrained(...)</code>.</p>
<pre><code>vae = OobleckVAE.from_pretrained("stabilityai/stable-audio-open-1.0", subfolder="vae")
waveform = vae.decode(latent)            # (B, audio_channels, samples)
latent   = vae.encode(waveform).sample()  # or .mode()
</code></pre>
<h2 id="fastvideo.models.vaes.oobleck.init_logger"><code>fastvideo.models.vaes.oobleck.init_logger</code></h2>
<pre class="doc-signature"><code>init_logger(name: str) -&gt; _FastvideoLogger</code></pre>
<p>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.</p>
<h2 id="fastvideo.models.vaes.oobleck.Snake1d"><code>fastvideo.models.vaes.oobleck.Snake1d</code></h2>
<pre class="doc-signature"><code>Snake1d(hidden_dim: int, logscale: bool = True)</code></pre>
<p>A 1D Snake activation with learnable per-channel alpha/beta.</p>

<details><summary>Source</summary><pre><code>class Snake1d(nn.Module):
    &quot;&quot;&quot;A 1D Snake activation with learnable per-channel alpha/beta.&quot;&quot;&quot;

    def __init__(self, hidden_dim: int, logscale: bool = 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, x: torch.Tensor) -&gt; torch.Tensor:
        shape = x.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)
        x = x.reshape(shape&#91;0&#93;, shape&#91;1&#93;, -1)
        x = x + (beta + 1e-9).reciprocal() * torch.sin(alpha * x).pow(2)
        return x.reshape(shape)</code></pre></details>
<h3 id="fastvideo.models.vaes.oobleck.Snake1d.forward"><code>fastvideo.models.vaes.oobleck.Snake1d.forward</code></h3>
<pre class="doc-signature"><code>forward(x: torch.Tensor) -&gt; torch.Tensor</code></pre>

<details><summary>Source</summary><pre><code>def forward(self, x: torch.Tensor) -&gt; torch.Tensor:
    shape = x.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)
    x = x.reshape(shape&#91;0&#93;, shape&#91;1&#93;, -1)
    x = x + (beta + 1e-9).reciprocal() * torch.sin(alpha * x).pow(2)
    return x.reshape(shape)</code></pre></details>
<h2 id="fastvideo.models.vaes.oobleck.OobleckResidualUnit"><code>fastvideo.models.vaes.oobleck.OobleckResidualUnit</code></h2>
<pre class="doc-signature"><code>OobleckResidualUnit(dimension: int = 16, dilation: int = 1)</code></pre>


<details><summary>Source</summary><pre><code>class OobleckResidualUnit(nn.Module):

    def __init__(self, dimension: int = 16, dilation: int = 1):
        super().__init__()
        pad = ((7 - 1) * dilation) // 2
        self.snake1 = Snake1d(dimension)
        self.conv1 = weight_norm(nn.Conv1d(
            dimension,
            dimension,
            kernel_size=7,
            dilation=dilation,
            padding=pad,
        ))
        self.snake2 = Snake1d(dimension)
        self.conv2 = weight_norm(nn.Conv1d(dimension, dimension, kernel_size=1))

    def forward(self, x: torch.Tensor) -&gt; torch.Tensor:
        out = self.conv1(self.snake1(x))
        out = self.conv2(self.snake2(out))
        pad = (x.shape&#91;-1&#93; - out.shape&#91;-1&#93;) // 2
        if pad &gt; 0:
            x = x&#91;..., pad:-pad&#93;
        return x + out</code></pre></details>
<h3 id="fastvideo.models.vaes.oobleck.OobleckResidualUnit.forward"><code>fastvideo.models.vaes.oobleck.OobleckResidualUnit.forward</code></h3>
<pre class="doc-signature"><code>forward(x: torch.Tensor) -&gt; torch.Tensor</code></pre>

<details><summary>Source</summary><pre><code>def forward(self, x: torch.Tensor) -&gt; torch.Tensor:
    out = self.conv1(self.snake1(x))
    out = self.conv2(self.snake2(out))
    pad = (x.shape&#91;-1&#93; - out.shape&#91;-1&#93;) // 2
    if pad &gt; 0:
        x = x&#91;..., pad:-pad&#93;
    return x + out</code></pre></details>
<h2 id="fastvideo.models.vaes.oobleck.OobleckEncoderBlock"><code>fastvideo.models.vaes.oobleck.OobleckEncoderBlock</code></h2>
<pre class="doc-signature"><code>OobleckEncoderBlock(input_dim: int, output_dim: int, stride: int = 1)</code></pre>


<details><summary>Source</summary><pre><code>class OobleckEncoderBlock(nn.Module):

    def __init__(self, input_dim: int, output_dim: int, stride: int = 1):
        super().__init__()
        self.res_unit1 = OobleckResidualUnit(input_dim, dilation=1)
        self.res_unit2 = OobleckResidualUnit(input_dim, dilation=3)
        self.res_unit3 = OobleckResidualUnit(input_dim, dilation=9)
        self.snake1 = Snake1d(input_dim)
        self.conv1 = weight_norm(
            nn.Conv1d(
                input_dim,
                output_dim,
                kernel_size=2 * stride,
                stride=stride,
                padding=math.ceil(stride / 2),
            ))

    def forward(self, x: torch.Tensor) -&gt; torch.Tensor:
        x = self.res_unit1(x)
        x = self.res_unit2(x)
        x = self.snake1(self.res_unit3(x))
        return self.conv1(x)</code></pre></details>
<h3 id="fastvideo.models.vaes.oobleck.OobleckEncoderBlock.forward"><code>fastvideo.models.vaes.oobleck.OobleckEncoderBlock.forward</code></h3>
<pre class="doc-signature"><code>forward(x: torch.Tensor) -&gt; torch.Tensor</code></pre>

<details><summary>Source</summary><pre><code>def forward(self, x: torch.Tensor) -&gt; torch.Tensor:
    x = self.res_unit1(x)
    x = self.res_unit2(x)
    x = self.snake1(self.res_unit3(x))
    return self.conv1(x)</code></pre></details>
<h2 id="fastvideo.models.vaes.oobleck.OobleckDecoderBlock"><code>fastvideo.models.vaes.oobleck.OobleckDecoderBlock</code></h2>
<pre class="doc-signature"><code>OobleckDecoderBlock(input_dim: int, output_dim: int, stride: int = 1)</code></pre>


<details><summary>Source</summary><pre><code>class OobleckDecoderBlock(nn.Module):

    def __init__(self, input_dim: int, output_dim: int, stride: int = 1):
        super().__init__()
        self.snake1 = Snake1d(input_dim)
        self.conv_t1 = weight_norm(
            nn.ConvTranspose1d(
                input_dim,
                output_dim,
                kernel_size=2 * stride,
                stride=stride,
                padding=math.ceil(stride / 2),
            ))
        self.res_unit1 = OobleckResidualUnit(output_dim, dilation=1)
        self.res_unit2 = OobleckResidualUnit(output_dim, dilation=3)
        self.res_unit3 = OobleckResidualUnit(output_dim, dilation=9)

    def forward(self, x: torch.Tensor) -&gt; torch.Tensor:
        x = self.snake1(x)
        x = self.conv_t1(x)
        x = self.res_unit1(x)
        x = self.res_unit2(x)
        return self.res_unit3(x)</code></pre></details>
<h3 id="fastvideo.models.vaes.oobleck.OobleckDecoderBlock.forward"><code>fastvideo.models.vaes.oobleck.OobleckDecoderBlock.forward</code></h3>
<pre class="doc-signature"><code>forward(x: torch.Tensor) -&gt; torch.Tensor</code></pre>

<details><summary>Source</summary><pre><code>def forward(self, x: torch.Tensor) -&gt; torch.Tensor:
    x = self.snake1(x)
    x = self.conv_t1(x)
    x = self.res_unit1(x)
    x = self.res_unit2(x)
    return self.res_unit3(x)</code></pre></details>
<h2 id="fastvideo.models.vaes.oobleck.OobleckDiagonalGaussianDistribution"><code>fastvideo.models.vaes.oobleck.OobleckDiagonalGaussianDistribution</code></h2>
<pre class="doc-signature"><code>OobleckDiagonalGaussianDistribution(parameters: torch.Tensor, deterministic: bool = False)</code></pre>
<p>Diagonal-Gaussian VAE posterior with <code>softplus(scale) + 1e-4</code> std.</p>

<details><summary>Source</summary><pre><code>class OobleckDiagonalGaussianDistribution:
    &quot;&quot;&quot;Diagonal-Gaussian VAE posterior with `softplus(scale) + 1e-4` std.&quot;&quot;&quot;

    def __init__(self, parameters: torch.Tensor, deterministic: bool = False):
        self.parameters = parameters
        self.mean, self.scale = parameters.chunk(2, dim=1)
        self.std = nn.functional.softplus(self.scale) + 1e-4
        self.var = self.std * self.std
        self.logvar = torch.log(self.var)
        self.deterministic = deterministic

    def sample(self, generator: torch.Generator | None = None) -&gt; torch.Tensor:
        noise = torch.randn(
            self.mean.shape,
            generator=generator,
            device=self.parameters.device,
            dtype=self.parameters.dtype,
        )
        return self.mean + self.std * noise

    def mode(self) -&gt; torch.Tensor:
        return self.mean</code></pre></details>
<h3 id="fastvideo.models.vaes.oobleck.OobleckDiagonalGaussianDistribution.sample"><code>fastvideo.models.vaes.oobleck.OobleckDiagonalGaussianDistribution.sample</code></h3>
<pre class="doc-signature"><code>sample(generator: torch.Generator | None = None) -&gt; torch.Tensor</code></pre>

<details><summary>Source</summary><pre><code>def sample(self, generator: torch.Generator | None = None) -&gt; torch.Tensor:
    noise = torch.randn(
        self.mean.shape,
        generator=generator,
        device=self.parameters.device,
        dtype=self.parameters.dtype,
    )
    return self.mean + self.std * noise</code></pre></details>
<h3 id="fastvideo.models.vaes.oobleck.OobleckDiagonalGaussianDistribution.mode"><code>fastvideo.models.vaes.oobleck.OobleckDiagonalGaussianDistribution.mode</code></h3>
<pre class="doc-signature"><code>mode() -&gt; torch.Tensor</code></pre>

<details><summary>Source</summary><pre><code>def mode(self) -&gt; torch.Tensor:
    return self.mean</code></pre></details>
<h2 id="fastvideo.models.vaes.oobleck.OobleckDecoderOutput"><code>fastvideo.models.vaes.oobleck.OobleckDecoderOutput</code></h2>
<pre class="doc-signature"><code>OobleckDecoderOutput(sample: torch.Tensor)</code></pre>


<details><summary>Source</summary><pre><code>@dataclass
class OobleckDecoderOutput:
    sample: torch.Tensor</code></pre></details>
<h2 id="fastvideo.models.vaes.oobleck.OobleckEncoder"><code>fastvideo.models.vaes.oobleck.OobleckEncoder</code></h2>
<pre class="doc-signature"><code>OobleckEncoder(encoder_hidden_size: int, audio_channels: int, downsampling_ratios: list&#91;int&#93;, channel_multiples: list&#91;int&#93;)</code></pre>


<details><summary>Source</summary><pre><code>class OobleckEncoder(nn.Module):

    def __init__(
        self,
        encoder_hidden_size: int,
        audio_channels: int,
        downsampling_ratios: list&#91;int&#93;,
        channel_multiples: list&#91;int&#93;,
    ):
        super().__init__()
        strides = downsampling_ratios
        channel_multiples = &#91;1&#93; + list(channel_multiples)
        self.conv1 = weight_norm(nn.Conv1d(
            audio_channels,
            encoder_hidden_size,
            kernel_size=7,
            padding=3,
        ))
        self.block = nn.ModuleList(&#91;
            OobleckEncoderBlock(
                input_dim=encoder_hidden_size * channel_multiples&#91;i&#93;,
                output_dim=encoder_hidden_size * channel_multiples&#91;i + 1&#93;,
                stride=s,
            ) for i, s in enumerate(strides)
        &#93;)
        d_model = encoder_hidden_size * channel_multiples&#91;-1&#93;
        self.snake1 = Snake1d(d_model)
        self.conv2 = weight_norm(nn.Conv1d(
            d_model,
            encoder_hidden_size,
            kernel_size=3,
            padding=1,
        ))

    def forward(self, x: torch.Tensor) -&gt; torch.Tensor:
        x = self.conv1(x)
        for m in self.block:
            x = m(x)
        x = self.snake1(x)
        return self.conv2(x)</code></pre></details>
<h3 id="fastvideo.models.vaes.oobleck.OobleckEncoder.forward"><code>fastvideo.models.vaes.oobleck.OobleckEncoder.forward</code></h3>
<pre class="doc-signature"><code>forward(x: torch.Tensor) -&gt; torch.Tensor</code></pre>

<details><summary>Source</summary><pre><code>def forward(self, x: torch.Tensor) -&gt; torch.Tensor:
    x = self.conv1(x)
    for m in self.block:
        x = m(x)
    x = self.snake1(x)
    return self.conv2(x)</code></pre></details>
<h2 id="fastvideo.models.vaes.oobleck.OobleckDecoder"><code>fastvideo.models.vaes.oobleck.OobleckDecoder</code></h2>
<pre class="doc-signature"><code>OobleckDecoder(channels: int, input_channels: int, audio_channels: int, upsampling_ratios: list&#91;int&#93;, channel_multiples: list&#91;int&#93;)</code></pre>


<details><summary>Source</summary><pre><code>class OobleckDecoder(nn.Module):

    def __init__(
        self,
        channels: int,
        input_channels: int,
        audio_channels: int,
        upsampling_ratios: list&#91;int&#93;,
        channel_multiples: list&#91;int&#93;,
    ):
        super().__init__()
        strides = upsampling_ratios
        channel_multiples = &#91;1&#93; + list(channel_multiples)
        self.conv1 = weight_norm(nn.Conv1d(
            input_channels,
            channels * channel_multiples&#91;-1&#93;,
            kernel_size=7,
            padding=3,
        ))
        self.block = nn.ModuleList(&#91;
            OobleckDecoderBlock(
                input_dim=channels * channel_multiples&#91;len(strides) - i&#93;,
                output_dim=channels * channel_multiples&#91;len(strides) - i - 1&#93;,
                stride=s,
            ) for i, s in enumerate(strides)
        &#93;)
        self.snake1 = Snake1d(channels)
        self.conv2 = weight_norm(nn.Conv1d(
            channels,
            audio_channels,
            kernel_size=7,
            padding=3,
            bias=False,
        ))

    def forward(self, x: torch.Tensor) -&gt; torch.Tensor:
        x = self.conv1(x)
        for layer in self.block:
            x = layer(x)
        x = self.snake1(x)
        return self.conv2(x)</code></pre></details>
<h3 id="fastvideo.models.vaes.oobleck.OobleckDecoder.forward"><code>fastvideo.models.vaes.oobleck.OobleckDecoder.forward</code></h3>
<pre class="doc-signature"><code>forward(x: torch.Tensor) -&gt; torch.Tensor</code></pre>

<details><summary>Source</summary><pre><code>def forward(self, x: torch.Tensor) -&gt; torch.Tensor:
    x = self.conv1(x)
    for layer in self.block:
        x = layer(x)
    x = self.snake1(x)
    return self.conv2(x)</code></pre></details>
<h2 id="fastvideo.models.vaes.oobleck.OobleckVAE"><code>fastvideo.models.vaes.oobleck.OobleckVAE</code></h2>
<pre class="doc-signature"><code>OobleckVAE(config = None, *, encoder_hidden_size: int = 128, downsampling_ratios: list&#91;int&#93; | None = None, channel_multiples: list&#91;int&#93; | None = None, decoder_channels: int = 128, decoder_input_channels: int = 64, audio_channels: int = 2, sampling_rate: int = 44100)</code></pre>
<p>Stable Audio Open 1.0 VAE.</p>
<p>Constructed either from an <code>OobleckVAEConfig</code> (the standard
<code>VAELoader</code> path) or from explicit kwargs (back-compat for tests
and <code>from_pretrained</code> callers).</p>

<details><summary>Source</summary><pre><code>class OobleckVAE(nn.Module):
    &quot;&quot;&quot;Stable Audio Open 1.0 VAE.

    Constructed either from an `OobleckVAEConfig` (the standard
    `VAELoader` path) or from explicit kwargs (back-compat for tests
    and `from_pretrained` callers).
    &quot;&quot;&quot;

    def __init__(
        self,
        config=None,  # type: OobleckVAEConfig | None
        *,
        encoder_hidden_size: int = 128,
        downsampling_ratios: list&#91;int&#93; | None = None,
        channel_multiples: list&#91;int&#93; | None = None,
        decoder_channels: int = 128,
        decoder_input_channels: int = 64,
        audio_channels: int = 2,
        sampling_rate: int = 44100,
    ):
        super().__init__()
        if config is not None:
            arch = config.arch_config
            encoder_hidden_size = arch.encoder_hidden_size
            downsampling_ratios = list(arch.downsampling_ratios)
            channel_multiples = list(arch.channel_multiples)
            decoder_channels = arch.decoder_channels
            decoder_input_channels = arch.decoder_input_channels
            audio_channels = arch.audio_channels
            sampling_rate = arch.sampling_rate
        if downsampling_ratios is None:
            downsampling_ratios = &#91;2, 4, 4, 8, 8&#93;
        if channel_multiples is None:
            channel_multiples = &#91;1, 2, 4, 8, 16&#93;
        self.encoder_hidden_size = encoder_hidden_size
        self.downsampling_ratios = downsampling_ratios
        self.decoder_channels = decoder_channels
        self.upsampling_ratios = list(reversed(downsampling_ratios))
        self.hop_length = int(np.prod(downsampling_ratios))
        self.sampling_rate = sampling_rate
        self.audio_channels = audio_channels
        self.decoder_input_channels = decoder_input_channels

        self.encoder = OobleckEncoder(
            encoder_hidden_size=encoder_hidden_size,
            audio_channels=audio_channels,
            downsampling_ratios=downsampling_ratios,
            channel_multiples=channel_multiples,
        )
        self.decoder = OobleckDecoder(
            channels=decoder_channels,
            input_channels=decoder_input_channels,
            audio_channels=audio_channels,
            upsampling_ratios=self.upsampling_ratios,
            channel_multiples=channel_multiples,
        )

    def encode(
        self,
        x: torch.Tensor,
    ) -&gt; OobleckDiagonalGaussianDistribution:
        return OobleckDiagonalGaussianDistribution(self.encoder(x))

    def decode(self, z: torch.Tensor) -&gt; OobleckDecoderOutput:
        return OobleckDecoderOutput(sample=self.decoder(z))

    def forward(
        self,
        sample: torch.Tensor,
        sample_posterior: bool = False,
    ) -&gt; OobleckDecoderOutput:
        posterior = self.encode(sample)
        z = posterior.sample() if sample_posterior else posterior.mode()
        return self.decode(z)

    # -------------------------------------------------------------------
    # Loader
    # -------------------------------------------------------------------
    @classmethod
    def from_pretrained(
        cls,
        model_path: str,
        *,
        subfolder: str | None = None,
        torch_dtype: torch.dtype | None = None,
    ) -&gt; &quot;OobleckVAE&quot;:
        &quot;&quot;&quot;Instantiate and load weights from a Stable Audio VAE dir.

        `model_path` may be:
          * a HF repo id (e.g. `stabilityai/stable-audio-open-1.0`),
          * a local directory containing `config.json` + safetensors,
          * a local directory whose `subfolder=&quot;vae&quot;` holds those files.

        For gated repos, the HF token is read by `resolve_hf_token`.
        &quot;&quot;&quot;
        import inspect
        from safetensors.torch import load_file

        from fastvideo.utils import resolve_hf_token

        # Resolve to a local directory.
        if os.path.isdir(model_path):
            root = model_path
        else:
            from huggingface_hub import snapshot_download
            allow = &#91;&quot;vae/*&quot;&#93; if subfolder else &#91;&quot;*&quot;&#93;
            root = snapshot_download(
                repo_id=model_path,
                token=resolve_hf_token(),
                allow_patterns=allow,
            )
        if subfolder:
            root = os.path.join(root, subfolder)
        if not os.path.isdir(root):
            raise FileNotFoundError(f&quot;Not a directory: &#123;root&#125;&quot;)

        cfg_path = os.path.join(root, &quot;config.json&quot;)
        if not os.path.isfile(cfg_path):
            raise FileNotFoundError(f&quot;Expected config.json at &#123;cfg_path&#125;. If using a HF repo, &quot;
                                    f&quot;pass subfolder=&#x27;vae&#x27;.&quot;)
        with open(cfg_path) as f:
            cfg = json.load(f)
        cfg_fields = &#123;k: v for k, v in cfg.items() if not k.startswith(&quot;_&quot;)&#125;
        # Diffusers configs commonly carry extra fields (`scaling_factor`,
        # `_diffusers_version`, ...) the bare `OobleckVAE` ctor doesn&#x27;t accept.
        init_params = inspect.signature(cls.__init__).parameters
        cfg_fields = &#123;k: v for k, v in cfg_fields.items() if k in init_params&#125;

        model = cls(**cfg_fields)

        weights_path = os.path.join(root, &quot;diffusion_pytorch_model.safetensors&quot;)
        if not os.path.isfile(weights_path):
            # Allow `model.safetensors` as a fallback.
            alt = os.path.join(root, &quot;model.safetensors&quot;)
            if os.path.isfile(alt):
                weights_path = alt
            else:
                raise FileNotFoundError(f&quot;No safetensors weights under &#123;root&#125;. Expected &quot;
                                        f&quot;diffusion_pytorch_model.safetensors.&quot;)
        state = load_file(weights_path)
        missing, unexpected = model.load_state_dict(state, strict=False)
        if missing:
            raise RuntimeError(f&quot;OobleckVAE missing &#123;len(missing)&#125; keys from &#123;weights_path&#125;: &quot;
                               f&quot;&#123;missing&#91;:5&#93;&#125;&quot;)
        if unexpected:
            # Non-critical: some checkpoints embed the VAE inside a larger
            # container (e.g. `pretransform.model.*`). Log the count so
            # genuine loader regressions don&#x27;t go unnoticed.
            logger.debug(
                &quot;OobleckVAE: ignored %d unexpected keys from %s &quot;
                &quot;(first 3: %s)&quot;,
                len(unexpected),
                weights_path,
                unexpected&#91;:3&#93;,
            )

        if torch_dtype is not None:
            model = model.to(dtype=torch_dtype)
        model.eval()
        return model</code></pre></details>
<h3 id="fastvideo.models.vaes.oobleck.OobleckVAE.encode"><code>fastvideo.models.vaes.oobleck.OobleckVAE.encode</code></h3>
<pre class="doc-signature"><code>encode(x: torch.Tensor) -&gt; OobleckDiagonalGaussianDistribution</code></pre>

<details><summary>Source</summary><pre><code>def encode(
    self,
    x: torch.Tensor,
) -&gt; OobleckDiagonalGaussianDistribution:
    return OobleckDiagonalGaussianDistribution(self.encoder(x))</code></pre></details>
<h3 id="fastvideo.models.vaes.oobleck.OobleckVAE.decode"><code>fastvideo.models.vaes.oobleck.OobleckVAE.decode</code></h3>
<pre class="doc-signature"><code>decode(z: torch.Tensor) -&gt; OobleckDecoderOutput</code></pre>

<details><summary>Source</summary><pre><code>def decode(self, z: torch.Tensor) -&gt; OobleckDecoderOutput:
    return OobleckDecoderOutput(sample=self.decoder(z))</code></pre></details>
<h3 id="fastvideo.models.vaes.oobleck.OobleckVAE.forward"><code>fastvideo.models.vaes.oobleck.OobleckVAE.forward</code></h3>
<pre class="doc-signature"><code>forward(sample: torch.Tensor, sample_posterior: bool = False) -&gt; OobleckDecoderOutput</code></pre>

<details><summary>Source</summary><pre><code>def forward(
    self,
    sample: torch.Tensor,
    sample_posterior: bool = False,
) -&gt; OobleckDecoderOutput:
    posterior = self.encode(sample)
    z = posterior.sample() if sample_posterior else posterior.mode()
    return self.decode(z)</code></pre></details>
<h3 id="fastvideo.models.vaes.oobleck.OobleckVAE.from_pretrained"><code>fastvideo.models.vaes.oobleck.OobleckVAE.from_pretrained</code></h3>
<pre class="doc-signature"><code>from_pretrained(model_path: str, *, subfolder: str | None = None, torch_dtype: torch.dtype | None = None) -&gt; &#x27;OobleckVAE&#x27;</code></pre>
<p>Instantiate and load weights from a Stable Audio VAE dir.</p>
<p><code>model_path</code> may be:
  * a HF repo id (e.g. <code>stabilityai/stable-audio-open-1.0</code>),
  * a local directory containing <code>config.json</code> + safetensors,
  * a local directory whose <code>subfolder="vae"</code> holds those files.</p>
<p>For gated repos, the HF token is read by <code>resolve_hf_token</code>.</p>
<details><summary>Source</summary><pre><code>@classmethod
def from_pretrained(
    cls,
    model_path: str,
    *,
    subfolder: str | None = None,
    torch_dtype: torch.dtype | None = None,
) -&gt; &quot;OobleckVAE&quot;:
    &quot;&quot;&quot;Instantiate and load weights from a Stable Audio VAE dir.

    `model_path` may be:
      * a HF repo id (e.g. `stabilityai/stable-audio-open-1.0`),
      * a local directory containing `config.json` + safetensors,
      * a local directory whose `subfolder=&quot;vae&quot;` holds those files.

    For gated repos, the HF token is read by `resolve_hf_token`.
    &quot;&quot;&quot;
    import inspect
    from safetensors.torch import load_file

    from fastvideo.utils import resolve_hf_token

    # Resolve to a local directory.
    if os.path.isdir(model_path):
        root = model_path
    else:
        from huggingface_hub import snapshot_download
        allow = &#91;&quot;vae/*&quot;&#93; if subfolder else &#91;&quot;*&quot;&#93;
        root = snapshot_download(
            repo_id=model_path,
            token=resolve_hf_token(),
            allow_patterns=allow,
        )
    if subfolder:
        root = os.path.join(root, subfolder)
    if not os.path.isdir(root):
        raise FileNotFoundError(f&quot;Not a directory: &#123;root&#125;&quot;)

    cfg_path = os.path.join(root, &quot;config.json&quot;)
    if not os.path.isfile(cfg_path):
        raise FileNotFoundError(f&quot;Expected config.json at &#123;cfg_path&#125;. If using a HF repo, &quot;
                                f&quot;pass subfolder=&#x27;vae&#x27;.&quot;)
    with open(cfg_path) as f:
        cfg = json.load(f)
    cfg_fields = &#123;k: v for k, v in cfg.items() if not k.startswith(&quot;_&quot;)&#125;
    # Diffusers configs commonly carry extra fields (`scaling_factor`,
    # `_diffusers_version`, ...) the bare `OobleckVAE` ctor doesn&#x27;t accept.
    init_params = inspect.signature(cls.__init__).parameters
    cfg_fields = &#123;k: v for k, v in cfg_fields.items() if k in init_params&#125;

    model = cls(**cfg_fields)

    weights_path = os.path.join(root, &quot;diffusion_pytorch_model.safetensors&quot;)
    if not os.path.isfile(weights_path):
        # Allow `model.safetensors` as a fallback.
        alt = os.path.join(root, &quot;model.safetensors&quot;)
        if os.path.isfile(alt):
            weights_path = alt
        else:
            raise FileNotFoundError(f&quot;No safetensors weights under &#123;root&#125;. Expected &quot;
                                    f&quot;diffusion_pytorch_model.safetensors.&quot;)
    state = load_file(weights_path)
    missing, unexpected = model.load_state_dict(state, strict=False)
    if missing:
        raise RuntimeError(f&quot;OobleckVAE missing &#123;len(missing)&#125; keys from &#123;weights_path&#125;: &quot;
                           f&quot;&#123;missing&#91;:5&#93;&#125;&quot;)
    if unexpected:
        # Non-critical: some checkpoints embed the VAE inside a larger
        # container (e.g. `pretransform.model.*`). Log the count so
        # genuine loader regressions don&#x27;t go unnoticed.
        logger.debug(
            &quot;OobleckVAE: ignored %d unexpected keys from %s &quot;
            &quot;(first 3: %s)&quot;,
            len(unexpected),
            weights_path,
            unexpected&#91;:3&#93;,
        )

    if torch_dtype is not None:
        model = model.to(dtype=torch_dtype)
    model.eval()
    return model</code></pre></details>
</div>
