Skip to content
helmstudio
Contents

ltx studio's manifest

ltx studio makes video with sound from LTX-2.5 on MLX, behind a Python server with no front-end toolchain. Its own repository ships this manifest as helmstudio.yaml; the copy here is the registry's, kept in step with it. It passes six of the seven criteria a manifest can answer; it declares no test profile.

The file is studios/ltx-studio.yaml, shown in full. A note follows the line it explains.

# A registry entry: a pointer at ltx studio's repository
# (schema/registry-entry.json, docs/design/05-sdk-and-custom-studios.md §5a).
#
# The manifest belongs in the studio's own repository as helmstudio.yaml, beside
# the code it describes, so that a studio can announce a new build step without
# waiting for a helmstudio release. ltx studio does not ship one yet, so the
# manifest is carried inline here — and the pull request that moves `ref` to a
# commit where it does ship one deletes the inline copy, leaving one copy again.
#
# Where the inline manifest sets id, repo or ref, each must equal this entry's;
# the validator enforces it. There is no `certified` field: a level is derived
# from what has actually been checked, never declared by the thing being
# checked (docs/decisions.md M7 Q4, Q15).

id: ltx-studio
The id the studio is known by everywhere, and the file is named for it.repo: https://github.com/janishar/ltx-2-studio
Where helmstudio clones from, with git.ref: main
A branch, so an install takes whatever it points at when the clone runs. A registry entry normally pins a commit; docs/decisions.md 2026-09-19 says why this one does not.manifest:
Inline, because the repository ships no helmstudio.yaml at this commit. Its id, repo and ref must equal the pointer's.  # ltx studio's manifest for helmstudio: the same studio the registry points at,
  # described by its own repository, beside the code it runs.
  id: ltx-studio
The same id as the pointer's.  name: ltx studio
The name people see.  description: MLX video and audio generation against a user-selected LTX checkpoint.
One sentence saying what the studio does.  kinds: [video, audio]
Video with sound.  hue: { dark: "#5b8def", light: "#2f5fc4" }
Its identity colour in each theme: a stripe, a dot and its clips on the timeline in the launcher, and the accent on its own page.  license: MIT
The studio's own licence.  repo: https://github.com/janishar/ltx-2-studio
The same repository as the pointer's.  ref: main
The same branch as the pointer's.  python: { version: "3.11" }
Python 3.11. helmstudio creates an environment with uv, pinned to this version, before the build step, and the studio runs with it active. No other studio shares it.  peak_ram_gb: 21
The memory at the validated default. The comment says why one number cannot carry the range: a longer, larger clip peaked far higher.  requires:
An Apple Silicon Mac with 64 GB of memory and 90 GB of disk. uv is the one tool it needs; the build fetches everything else.    os: [darwin]
    arch: [arm64]
    tools: [uv]
    ram_gb: 64
    disk_gb: 90
  runtime:
MLX on Metal, quantised on load: Apple-native, like a Metal kernel, and a different claim from one.    framework: mlx
    backends: [metal]
    precision: [bf16, int8]
    language: python
  # ltx studio keeps nothing of its own; helmstudio keeps it all (State in web/server.py):
  # sessions with their settings and inputs, and the page's preferences (kv); the
  # folders training tools write (records); inputs and takes (assets); takes with
  # their provenance (gallery); sequences (timeline); renders with their logs (jobs).
  capabilities: [kv, records, assets, gallery, timeline, jobs]
Settings and sessions, the files it makes, the gallery and the timeline.  storage:
One collection, folders, indexed by session: the folders a training tool writes, which ltx studio keeps as records rather than as files of its own.    collections:
      - { name: folders, index: [session_id] }
  sdk: { runtime: "^1", ui: "^1", css: "^1" }
Pins major 1 of the runtime SDK, helm-css and helm-ui — the components it draws its gallery, timeline and terminal with, which is why this one names three where a studio drawing its own names two.  network: [huggingface.co, cdn-lfs.huggingface.co]
The hosts it is expected to contact, for its weights.  build:
One step: install exactly the locked dependencies, and fail rather than change the lock file in the checkout.    # --locked: install exactly uv.lock, and fail rather than rewrite it.
    - name: Sync dependencies
      run: uv sync --locked --all-extras
  weights:
Three weights, all from one repository into one directory. The first set is required. The AV video VAE and the dev transformer are optional, so an install does not wait for them: the first is what --video-decoder diffusion decodes with, the second, the dev transformer with the distilled LoRA its stage 2 fuses, is what the two-stage, HQ, a2v and keyframe pipelines run.    - name: ltx
      repo: Lightricks/LTX-2.5
      dest: LTX-2.5
      files:
        - diffusion_models/ltx-2.5-22b-distilled-transformer-bf16.safetensors
        - text_encoders/gemma4-12b-with-proj-ltx-2.5-bf16.safetensors
        - vae/ltx-2.5-video-vae-conv-bf16.safetensors
        - vae/ltx-2.5-audio-vae-bf16.safetensors
        - latent_upscale_models/ltx-2.5-latent-spatial-upscaler-x2-bf16-1.0.safetensors
        - model_patches/ltx-2.5-duration-head-bf16.safetensors
      size_gb: 71
    - name: ltx_video_vae_av
      repo: Lightricks/LTX-2.5
      dest: LTX-2.5
      files: ["vae/ltx-2.5-video-vae-bf16.safetensors"]
      size_gb: 1.4
      optional: true
    - name: ltx_dev_transformer
      repo: Lightricks/LTX-2.5
      dest: LTX-2.5
      # The distilled LoRA is what stage 2 of every dev pipeline fuses.
      files:
        - diffusion_models/ltx-2.5-22b-dev-transformer-bf16.safetensors
        - loras/ltx-2.5-22b-distilled-lora-450-bf16.safetensors
      size_gb: 51
      optional: true
  processes:
One process: the Python server in web/.    - name: studio
      role: main
      heavy: true
      cwd: web
The command runs in web/, relative to the checkout.      # Not `uv run`, which would sync the environment at every launch.
      cmd: "python server.py --host 127.0.0.1 --port {port} --model {models.ltx}"
Plain python, not uv run, which would sync the environment and reach the network at every launch.      port: { prefer: 8720 }
      health: { tcp: true, timeout_s: 30, interval_s: 2 }
      busy: { path: /api/queue }
Declared, so the switch dialog asks before stopping it. Its answer is not the busy contract yet, so the dialog reads it as unknown, never as idle.      ui: /