#275·LTX-2

Confirm: LTX-2.5 video/audio VAE *encoders* are byte-identical to LTX-2.3 (undocumented)

Author: ofir-bar-talCreated Aug 12, 2026Updated Aug 18, 2026

Summary

While integrating LTX-2.5 into a downstream trainer, I compared the standalone VAE checkpoints shipped with Lightricks/LTX-2.5 (vae/ltx-2.5-video-vae-bf16.safetensors, vae/ltx-2.5-audio-vae-bf16.safetensors) against the VAE weights bundled inside the LTX-2.3 checkpoint (ltx-2.3-22b-dev.safetensors, keys vae.* / audio_vae.*).

Every encoder tensor and per-channel normalization stat is byte-for-byte identical between 2.3 and 2.5. The audio decoder is also identical. Only the video decoder differs (consistent with the v1.2.0 release notes' "diffusion-based video VAE decoding" addition, which appears to be a decoder architecture replacement, not a new encoder/latent space).

This is good news for anyone with 2.3-encoded latents cached for training, but I couldn't find it stated anywhere in the README, release notes, or model card, so I'd like to (a) confirm this is intentional/expected rather than a publishing artifact, and (b) suggest documenting it, since it directly answers "can I reuse latents encoded with the old VAE" for anyone upgrading.

Reproduction

python
import hashlib, torch
from safetensors import safe_open

# sha256 of the downloaded files matched the HF-recorded LFS hashes exactly:
#   vae/ltx-2.5-video-vae-bf16.safetensors: 847e14ca7f3355debca0cea4eaa24ac0fbcdf0061da054ac89ca638a869ddba3
#   vae/ltx-2.5-audio-vae-bf16.safetensors: c52733d37f6a7fb7949c3dc0fb468c6cb2169e4d836983a73babb9f0d54837a5

f23  = safe_open("ltx-2.3-22b-dev.safetensors", framework="pt")           # bundled checkpoint
f25v = safe_open("vae/ltx-2.5-video-vae-bf16.safetensors", framework="pt")
f25a = safe_open("vae/ltx-2.5-audio-vae-bf16.safetensors", framework="pt")

def compare(prefix23, prefix25, f23, f25, label):
    keys = sorted(k for k in f23.keys() if k.startswith(prefix23))
    n_id = 0
    for k in keys:
        k2 = prefix25 + k[len(prefix23):]
        t1, t2 = f23.get_tensor(k), f25.get_tensor(k2)
        if t1.shape == t2.shape and torch.equal(t1, t2):
            n_id += 1
    print(label, f"{n_id}/{len(keys)} identical")

compare("vae.encoder.", "encoder.", f23, f25v, "VIDEO encoder")
compare("vae.decoder.", "decoder.", f23, f25v, "VIDEO decoder")
compare("audio_vae.encoder.", "audio_vae.encoder.", f23, f25a, "AUDIO encoder")
compare("audio_vae.decoder.", "audio_vae.decoder.", f23, f25a, "AUDIO decoder")
compare("vae.per_channel_statistics.", "per_channel_statistics.", f23, f25v, "VIDEO per-channel stats")
compare("audio_vae.per_channel_statistics.", "audio_vae.per_channel_statistics.", f23, f25a, "AUDIO per-channel stats")

Results

Component Tensors compared Identical
Video VAE encoder 84 84/84
Video VAE decoder 84 0/84 (different key structure/architecture)
Audio VAE encoder 44 44/44
Audio VAE decoder 56 56/56
Video per-channel stats (mean-of-means, std-of-means) 2 2/2
Audio per-channel stats (mean-of-means, std-of-means) 2 2/2

Sample lovely_tensors view (identical stats/histograms, torch.equal True):

vae.encoder.conv_in.conv.weight
 2.3: tensor[128, 48, 3, 3, 3] bf16 x∈[-0.664 | ▁▁▁▁█▁▁▁▁| 0.535] μ=-2.742e-05 σ=0.037
 2.5: tensor[128, 48, 3, 3, 3] bf16 x∈[-0.664 | ▁▁▁▁█▁▁▁▁| 0.535] μ=-2.742e-05 σ=0.037
 equal: True

vae.per_channel_statistics.mean-of-means
 2.3: tensor[128] bf16 x∈[-0.555 |▁ ▁ ▁█▁▁▁▁| 0.428] μ=-0.001 σ=0.082
 2.5: tensor[128] bf16 x∈[-0.555 |▁ ▁ ▁█▁▁▁▁| 0.428] μ=-0.001 σ=0.082
 equal: True

Questions

  1. Is this intentional — i.e. is LTX-2.5's latent space (for both video and audio) guaranteed to stay compatible with LTX-2.3's for the foreseeable future, or could a future 2.x release change the encoder without a major version bump?
  2. Could this be called out explicitly in the release notes / model card? It would save anyone with existing 2.3-encoded training data a redundant (and expensive) re-encoding pass.

Happy to share the full comparison script/output if useful.