Calliope
Calliope is a local-first story-to-video studio. You type a story idea; Calliope drafts a storyline with beats, characters, and locations, writes a per-scene script, then generates a video clip per scene by driving your own ComfyUI install. When the clips are done, one click stitches them into a finished film with crossfades and matched loudness (ffmpeg). Everything runs on your machine: projects live in SQLite, media lives in folders, and no cloud service is involved beyond the LLM endpoint you point it at.
Install — Windows EXE (recommended)
- Download
Calliope-<version>-win-x64.zip(e.g.Calliope-1.1.0-win-x64.zip) from the latest release. - Unzip it anywhere writable (avoid
Program Files). - Run
win-unpacked\Calliope.exe.
No installer, no dev setup. First launch shows a splash while the backend boots. Windows SmartScreen will warn on first run (unsigned binary) — that's expected: click More info → Run anyway.
Portable: your projects, database, generated media, and settings live next to the app:
<app>\resources\backend\data\ projects database + generated assets
<app>\resources\backend\calliope_config.json created when you save Settings
Move or copy the whole unzipped folder to relocate the app together with its data.
Install — from source (npm + Python)
For development, or if you prefer running the web UI in a browser instead of the Electron shell.
Prerequisites
- Python 3.11+
- Node.js 18+ (npm)
- A running ComfyUI install, with the models your workflows need already set up
- An OpenAI-compatible LLM endpoint — local (LM Studio, Ollama, etc.) or hosted
- ffmpeg on PATH — needed for film export
1. Backend (FastAPI)
cd calliope-backend
python -m venv .venv
.venv\Scripts\pip install -e ".[dev]"
.venv\Scripts\python -m calliope.main --host 127.0.0.1 --port 8247
Optionally copy calliope_config.example.json to calliope_config.json and edit it before starting (LLM endpoint, ComfyUI URL). You can also configure everything later in the app's Settings page. Never commit calliope_config.json — it stores your API key.
2. Frontend (SvelteKit)
cd calliope-web
npm install
npm run dev
Open http://127.0.0.1:5173. The dev server proxies /api to the backend on 127.0.0.1:8247.
First run
Open the app, go to Settings, and set:
- LLM — base URL, model name, and API key of your OpenAI-compatible endpoint
- ComfyUI — the base URL of your running ComfyUI (e.g.
http://127.0.0.1:8188)
Leave Dry-run off — it is meant for testing and produces placeholder results instead of real generations.
Using the app
The app walks a project through four stages — Story, Assets, Script, Video:
- Story: describe your idea and generate a draft storyline with beats, characters, and locations. Generating again replaces the current draft — the UI asks for confirmation first. Edit anything by hand before moving on.
- Assets: each character and location has its own Image prompt. Pick a workflow and shared settings (width/height/etc.) at the top, then click Generate per entity to produce reference images on your ComfyUI. Regenerate any single entity without touching the others.
- Script: generate (or regenerate) the per-scene script. Scenes link back to the characters and locations from the Story stage.
- Video: each scene gets a Generate button that queues a clip job on ComfyUI with the right prompt and reference images. Clips save to local disk and appear in the scene timeline.
- Film view: once scenes have clips, Export film stitches them with ffmpeg: every clip is normalized to 1080p30, joined with 0.5s crossfades, and loudness-normalized into one final file.
- When everything is done the project is automatically marked Completed.
Playground is a free-form generation page outside the project pipeline: run any imported workflow with arbitrary inputs, upload your own files (image / video / audio) as inputs, and optionally attach a result to a project as an asset.
ComfyUI workflows (important)
Calliope does not hardcode Comfy node IDs. It discovers editable nodes from role tags in the node titles of an API Format workflow JSON. The example_ComfyUI_workflows/ folder in this repo contains ready-to-import examples (MiniMax H3 reference-to-video, krea2 text-to-image, character sheet).
1. Tag your nodes in ComfyUI
Rename the input/output nodes so their titles carry a role tag:
Display Name (Input:role)
Display Name (Output:role)
The display name can be anything, in any language. The :role part is the contract. Examples:
Main Prompt (Input:prompt)
Neg (Input:negative)
W (Input:width)
H (Input:height)
Char Ref (Input:character)
Env Ref (Input:location)
Result (Output:image)
Clip (Output:video)
2. Canonical roles
Input roles:
| Role | Aliases | Filled by |
|---|---|---|
prompt |
positive |
Entity Image prompt (Assets), scene/job prompt |
negative |
neg |
Negative prompt when provided |
width |
w |
Shared form / defaults |
height |
h |
Shared form / defaults |
character |
char, portrait, sheet, face, ref |
Character reference path |
location |
loc, environment, env, background, scene |
Location reference path |
image |
img |
Generic image input (ordered ref slot — see below) |
seed |
— | Shared form |
duration |
dur, length, seconds |
Scene duration (video jobs) |
Output roles:
| Role | Aliases |
|---|---|
image |
img |
video |
vid |
Unknown roles still show up in the dynamic form; they just get no special auto-fill. Plain (Input) / (Output) without a role still works through a deprecated label fallback, so old workflows keep working — but tag new workflows with explicit roles.
Prompt profiles
Each workflow has a Prompt format setting (default Plain prose). When set to MiniMax H3 reference (6-section), Calliope rewrites each scene prompt at generation time into MiniMax H3's full-reference format (subject_definitions → summary → retention_analysis → detailed_description → overall_soundscape → non_diegetic_music, with <Subject N> labels and <d>[Language] …</d> dialogue). It is auto-suggested on import when the workflow contains a MiniMaxH3* node.
For multi-reference workflows, generic (Input:image) inputs are filled in node-id order — characters in scene order, then the location — and that order defines the <Subject N> numbering in the prompt. Keep your ref node ids in the order you want subjects numbered. A (Input:duration) node receives the scene's duration in seconds.
Using the H3 profile from the scene form (Generate clip): the form's auto-fill vs. override rule is simple — anything you type or pick wins over the automatic value.
- Text Prompt — leave it empty. An empty field gets the LLM-rewritten six-section H3 prompt built from the scene's action, dialogue, characters, and location. If you type anything, your text is sent verbatim and the model receives plain prose instead of the H3 format.
- Ref 1 / Ref 2 — leave them on "Choose asset…" to auto-fill from the scene's characters (in scene order) then the location, with
<Subject N>numbering matched to those slots. Picking an asset manually overrides just that slot (and you take over subject numbering for it). - Duration auto-fills from the scene's estimated duration; edit it only when you want a different clip length.
3. Export the workflow
In ComfyUI, use Save (API Format) — not the regular UI workflow graph format. Calliope only understands API Format JSON.
4. Import into Calliope
Settings → Workflows → import the JSON → analyze → check the preview shows the expected role next to each input → save → enable the workflow where you want to use it (Assets, Playground, per scene).
5. Troubleshooting
If ComfyUI "doesn't know what to generate" or jobs come back empty:
- The workflow title must be literally
(Input:prompt)— not only(Input)— for prompts to land reliably. - Check the job payload:
input_valuesfor that node must be non-empty (blanks are stripped before submission). - Make sure Dry-run is off in Settings (default is off).
- An unreachable ComfyUI fails the job honestly — Calliope never silently fakes images. Check the base URL and that ComfyUI is running.
6. HTTP only
Calliope talks to ComfyUI purely over its HTTP API: it uploads reference files with POST /upload/image, patches the workflow JSON and queues it via POST /prompt, polls /history/{prompt_id}, and downloads the results. It never reads or writes ComfyUI's local input/ / output/ folders — any folder paths stay configured on the ComfyUI side, not in Calliope.
License
All rights reserved — © 2026 Calliope contributors.
Repo layout
calliope-backend/ FastAPI backend (Python)
calliope-web/ SvelteKit frontend
example_ComfyUI_workflows/ ready-to-import API-format workflow JSONs
The Windows desktop app is built from this repo but not shipped in it — download it from the Releases page.