Using Soundbox
Artwork
Cover art for generated music, avatars for saved voices, and the image models behind them.
Cover art for music you generate, and avatars for saved voices. Artwork is off by default, and nothing is downloaded until you turn it on.
Three of the four places artwork appears need an image model. Stem icons do not.
Stem icons need nothing
When you split a track into stems, each stem gets its instrument's icon (vocals, drums, bass, guitar, keys) in the stem list and in the library row. The app draws these from a fixed set, because a separator emits a closed set of stem names. They appear instantly, look the same every time, and work with artwork off. An unrecognised instrument gets a plain note icon.
Nothing else in this document is required for stem icons.
Turning artwork on
Go to Settings → Artwork and pick one of three modes (the same three the prompt assistant has):
| Mode | What it does |
|---|---|
| Off (default) | No artwork anywhere. |
| Local | Soundbox installs stable-diffusion.cpp's sd-server and a small checkpoint, and runs them for you. |
| External | Soundbox talks to an image server you already run. |
If Automatic1111 or a compatible server is already listening, Soundbox finds it and offers a one-click switch to External. It probes 127.0.0.1 on 7860, 1234 and 8080 on every status fetch, with a 400 ms timeout.
Local
The engine is one native binary, fetched from stable-diffusion.cpp's GitHub
releases and cached under <data dir>/bin/sd/<version>/. It uses the same
managed-binary system as audiocpp_cli and llama-server, including the
SOUNDBOX_SD_SERVER_BIN override for your own build. See
INSTALL.md.
Three models are offered:
| Model | Files | Size | Licence |
|---|---|---|---|
| SD-Turbo (Q8) | 1 | 2.0 GB | Stability AI Community: commercial below $1M revenue |
| SDXL-Turbo (Q8) | 1 | 4.1 GB | Stability AI Non-Commercial |
| Stable Diffusion 3.5 Medium | 4 | 11.6 GB | Stability AI Community |
The licence is shown before you download. The licences differ, and under the non-commercial one you cannot ship what the model makes.
The first two are turbo-distilled: a cover takes one to four steps instead of
twenty-eight. The auto-cover switch is designed around them. SD 3.5 Medium is
the quality option: 1024px, 28 steps, and most of a 16 GB card. It loads with
--clip-on-cpu so its three text encoders stay off the GPU, which lets it
share the card with a resident audio model.
Weights go in <data dir>/models/image/<id>/, beside the audio and LLM model
directories, and can be deleted independently of both.
Models made of several files
SD 3.5 is a transformer plus three text encoders, each passed to sd-server under its own flag:
-m sd3.5_medium.safetensors
--clip_l text_encoders/clip_l.safetensors
--clip_g text_encoders/clip_g.safetensors
--t5xxl text_encoders/t5xxl_fp8_e4m3fn.safetensorsA catalog entry is therefore a list of files, each with the flag it loads under. A family that needs a different flag, or an upstream rename, is a catalog edit. Downloads skip files already present, so an interrupted 11.6 GB pull resumes file by file.
The catalog uses the fp8 T5 instead of the fp16, which halves its 9.8 GB size. The T5 encoder mainly helps with prompts that contain text, and cover-art prompts avoid text.
Bring your own image model
Add entries to the same file the audio side uses,
<data dir>/models/custom.json, under an image_models key:
{
"image_models": [
{
"id": "sd35-mine",
"name": "SD 3.5 (my copy)",
"files": [
{ "flag": "-m", "path": "D:/models/sd3.5_medium.safetensors" },
{ "flag": "--clip_l", "path": "D:/models/clip_l.safetensors" },
{ "flag": "--clip_g", "path": "D:/models/clip_g.safetensors" },
{ "flag": "--t5xxl", "path": "D:/models/t5xxl_fp8_e4m3fn.safetensors" }
],
"resolution": 1024,
"steps": 28,
"cfg": 4.5,
"extra_args": ["--sampling-method", "euler", "--clip-on-cpu"]
}
]
}- An absolute
pathis a file already on your disk. Nothing is downloaded, and Soundbox never deletes weights it did not fetch. A relative path needs anhf_repoto resolve against. flagis passed to sd-server verbatim, so anything it accepts works, including--vaeand--diffusion-model.- If you omit
license, the model shows as Unspecified / not commercial, as in the audio catalog. - An id matching a shipped model replaces it. Use this to point an existing entry at your own copy.
- The file is re-read whenever it changes. A malformed entry is skipped with a console warning.
Models in diffusers format are not supported: a directory of
model_index.json, transformer/, text_encoder/, vae/, the layout the
Python diffusers library downloads. sd-server needs single files. Repos
usually publish the same weights in both layouts, so fetch the single-file
copies instead of converting.
External
Set the base URL and pick the API it speaks. Image generation has no common
standard like /v1/chat/completions for chat, so you choose the API
explicitly:
- Automatic1111:
POST /sdapi/v1/txt2img. Automatic1111, Forge, SD.Next, and stable-diffusion.cpp's ownsd-server. - OpenAI-compatible:
POST /v1/images/generations. OpenAI, LocalAI, most proxies.
An API key is optional and write-only, like the Hugging Face token. The server never returns it.
Soundbox always requests the image inline as base64 (response_format: "b64_json"). An endpoint that answers with a URL is refused, so Soundbox
never fetches from a second host.
What gets drawn
Cover art comes from the track's generation prompt, then its track name, then its tags. Lyrics are excluded, because image models tend to render words as text on the cover. The negative prompt leads with text, typography and watermarks for the same reason.
Voice avatars come from the voice's notes field, falling back to its name. A voice annotated "gravelly old sea captain, mid-Atlantic accent" gets a portrait of one; a voice called "Voice 3" with no notes gets very little. Fill in the notes to control the avatar. Avatars render as stylised illustration, not photoreal portraits, so they do not look like a real person.
Prompts are built deterministically, without the prompt assistant. Artwork works with the LLM off, and redrawing a cover gives another take on the same subject.
When it runs
By default, only when you ask: a Draw cover action on a music track, and an Avatar action on a voice. The Draw covers automatically switch queues a cover after each music render.
That switch is off by default because the image model needs the same VRAM the
audio model is using. Artwork is queued only after the generation it belongs
to has finished and been saved, and a failed render is logged without failing
the generation. The engine stops after the same idle period that unloads
audio models (auto_unload_minutes), so it does not hold VRAM between covers.
Where images live
<data dir>/artwork/<uuid>.pngImages are served at /artwork/<file> and referenced from a sound's
artwork field and a voice's artwork field. They are derived files:
deleting the directory loses only the pictures. Redrawing writes a new file
and removes the old one only once the new one exists, so a failed redraw keeps
the existing cover.
API
GET /api/image/status engine, model, catalog, detected endpoints
POST /api/image/engine/install -> 202 { job_id }
POST /api/image/models/{id}/download -> 202 { job_id }
DELETE /api/image/models/{id} -> 204
POST /api/sounds/{id}/artwork -> 200 Sound (with artwork set)
DELETE /api/sounds/{id}/artwork -> 204
POST /api/voices/{id}/artwork -> 200 Voice
DELETE /api/voices/{id}/artwork -> 204The UI shows its draw actions only when status.ready is true. It combines
the mode, whether the engine is installed and whether the checkpoint is
downloaded. status.detail says in words which of those is missing.
Installs run as jobs because they download gigabytes. Generation is synchronous because a turbo render takes seconds.