AuK studio's manifest
AuK studio makes speech and voices with PyTorch on mps, behind a FastAPI server. Its repository ships this manifest, and the registry entry carries a copy so the studio can be described before it is fetched. It passes six of the seven criteria a manifest can answer: it declares no test profile.
The file is studios/auk-studio.yaml, shown in full. A note follows the line it explains.
# A registry entry: a pointer at AuK 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, and AuK studio ships one. This copy is not dead weight
# for that: resolution reaches nothing over the network (M7 Q7), so before a
# studio is fetched this is the only manifest there is, and an entry without one
# shows on the shelf as `not_fetched` — no description, no hue, no checkpoint to
# choose. So the copy stays, and the thing that matters about it is that it
# agrees with the repository.
#
# 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: auk-studio
The id the studio is known by everywhere, and the file is named for it.repo: https://github.com/janishar/AuK
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:
A copy of the helmstudio.yaml the repository ships. Resolution reaches nothing over the network, so without it the studio has no description, hue or checkpoint to choose until it is fetched. Its id, repo and ref must equal the pointer's. id: auk-studio
The same id as the pointer's. name: AuK studio
The name people see. description: PyTorch speech generation and editing on mps, with AuK and AuK-Flash checkpoints.
One sentence saying what the studio does. kinds: [audio]
Sound. hue: { dark: "#8b7cf0", light: "#5c4bc4" }
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/AuK
The same repository as the pointer's. ref: main
The same branch as the pointer's. # Matching pyproject's requires-python: scipy's last 3.10 wheel (1.15.3) no
# longer loads on recent macOS, and qwen-omni-utils imports it through librosa.
# 3.12 resolves scipy 1.18, which does.
python: { version: "3.12" }
Python 3.12. helmstudio creates an environment with uv, pinned to this version, before the build steps. The comment says why not 3.10: scipy's last wheel for it no longer loads on recent macOS. # Measured on this repo, AuK-Flash on mps/bf16: 13.8 GB resident after load
# (DiT 5.7 fp32 + Qwen 7.5 bf16 + VAE 0.6). AuK base is larger, and generation
# adds transient latents on top, so this is an upper bound over both variants.
peak_ram_gb: 25
Measured for the distilled checkpoint and rounded up to cover the base one, as the comment says. requires:
An Apple Silicon Mac, uv, and the memory and disk an install needs. os: [darwin]
arch: [arm64]
tools: [uv]
ram_gb: 32
disk_gb: 40
runtime:
PyTorch on mps, falling back to the CPU. The same framework on cuda would be a different manifest, and the comment says why this one was chosen. framework: pytorch
# web/server.py's _default_device supports cuda too, but nothing here has been
# run on it; the manifest claims only what has been verified on this machine.
backends: [mps, cpu]
precision: [bf16, fp16, fp32]
language: python
# AuK studio keeps nothing of its own. Sessions, the reference audio they hold
# and every generation go through helmstudio: sessions and the settings they
# carry (kv — the sessions API is backed by it, and is 403 without it),
# reference clips and rendered takes (assets), takes with the instruction and
# sampling parameters that made them (gallery), and each generation as a task
# job whose log the page's helm-terminal streams (jobs). web/README.md says
# where each one goes.
capabilities: [kv, assets, gallery, jobs]
Sessions and their settings, the files it makes, the gallery, and a job per render whose log its page streams. sdk: { runtime: "^1", ui: "^1", css: "^1" }
The SDK majors its page is written against, so a helmstudio update never moves it across one. network: [huggingface.co, cdn-lfs.huggingface.co]
The hosts it is expected to contact, for its weights. build:
Two steps, in the studio's environment: the core package, then the web server's requirements. - name: Install the core package
run: uv pip install -e .
- name: Install the web server
run: uv pip install -r web/requirements.txt
weights:
The encoder it always needs, and two checkpoints to choose between. Only the chosen one is downloaded, and the command is given its path. # The MLLM text encoder both checkpoints condition on: needed by either.
- name: qwen
repo: Qwen/Qwen2.5-Omni-3B
dest: Qwen2.5-Omni-3B
size_gb: 11
# One checkpoint at a time: each is 14-25 GB resident, so AuK studio holds a
# single engine and helmstudio owns which one that is. Both are selectable,
# and only the chosen one is downloaded; the studio reads which it was given
# from the config.yaml beside the weights.
- name: auk_flash
repo: tencent/AuK-Flash
dest: AuK-Flash
size_gb: 7
selectable: true
- name: auk
repo: tencent/AuK
dest: AuK
size_gb: 7
selectable: true
processes:
One process: the FastAPI server in web/. - name: studio
role: main
heavy: true
cwd: web
# Not `uv run`, which would sync the environment at every launch.
cmd: "python server.py --host 127.0.0.1 --port {port} --checkpoint {models.selected} --qwen {models.qwen}"
port: { prefer: 8420 }
health: { path: /api/health, timeout_s: 60, interval_s: 2 }
An HTTP GET that answers 200 when the server is ready. # /api/health carries `busy`: true while a generation holds the engine, so
# the switch dialog knows not to stop the studio mid-render.
busy: { path: /api/health }
The same endpoint, which answers the busy contract: busy while a generation holds the engine, so the switch dialog never reads it as idle mid-render. ui: /