reelforge
v0.8.0
Published
CLI for ReelForge Studio — AI video engine. Installs as both `reelforge` and the short alias `rf`. Every REST API exposed as a command, with --help on every level.
Maintainers
Readme
reelforge
CLI for ReelForge Studio — every REST API exposed as a command, with
--helpavailable at every level.
Install
npm install -g reelforgeOr use directly without install:
npx reelforge <command>After install, two binaries are on your PATH — reelforge and the short alias rf. Both behave identically; the docs use rf from here on.
rf --version # same as `reelforge --version`Quick start
The CLI ships pointing at the hosted instance (https://reelforge.timor419.com). Log in once, then call:
npm install -g reelforge
rf login # opens browser; headless? rf login <api_key>
rf whoami # balance + api_keys
rf create "为什么我们还没找到外星文明?" # auto-saves to ./<title>-<id>.mp4 in cwdThat's the whole story — no server to run.
Output behavior
| invocation | result |
|---|---|
| rf create "..." | Saves to ./<sanitized-title>-<task_id_short>.mp4, prints the path |
| rf create "..." -o ./videos/space.mp4 | Saves to that exact path (must include filename, not just a directory) |
| rf create "..." --no-download | Skips local save, prints JSON result with video_url |
| rf create "..." \| jq .video_url | When stdout is piped, download is skipped automatically |
Self-hosting
If you want to run your own ReelForge Studio (own RelayX key, your own pricing) clone the upstream repo, pnpm dev, then point the CLI at it:
rf --server http://localhost:8501 health
# or persist:
export REELFORGE_SERVER=http://localhost:8501
# or via `rf login <key> --server http://localhost:8501`Global options
| flag | description |
|---|---|
| -s, --server <url> | ReelForge server URL (overrides $REELFORGE_SERVER; default https://reelforge.timor419.com) |
| -k, --api-key <key> | API key (overrides $REELFORGE_API_KEY and reelforge login saved key) |
| --json | Output raw JSON instead of pretty text — pipe-friendly |
| --quiet | Suppress informational messages on stderr |
| -v, --version | Show CLI version |
| -h, --help | Show help (works on every sub-command) |
Command map
Run rf <command> --help for full details on any of these.
Core capabilities
| command | what it does |
|---|---|
| llm chat -p <text> | Send one prompt to the configured LLM (RelayX gateway by default) |
| llm presets | List built-in RelayX model presets |
| tts edge -t <text> -o out.mp3 | Local Edge TTS synthesis (free) |
| tts relayx -t <text> -o out.mp3 | RelayX TTS (vox/index-tts-2, 149 built-in voices) |
| tts voices [--locale zh] | List supported Edge TTS voices |
| images generate -p <prompt> -m rx-image-flux | Image generation via RelayX (rx-image-z / rx-image-flux / rx-image-qwen) |
Content / audio / subtitle atomics
| command | what it does |
|---|---|
| content scene-plan -t <topic> | Single LLM call: title + master script + per-scene image prompts (replaces the old narration / split / image-prompts / title trio) |
| content scene-plan --script <text-or-@file> | Same, but the user supplies the script verbatim — LLM only segments and writes image prompts |
| audio transcribe -f <file> / --url <url> | RelayX paraformer-v2 ASR with word + segment timestamps |
| subtitles split -t <text-or-@file> | Deterministic tiered-punctuation subtitle line splitter (pure function, zero billing) |
Composition
| command | what it does |
|---|---|
| templates list [--size 1080x1920] [--type image] | List HTML frame templates |
| templates preview <keyOrPath> [-o out.png] | Render a preview from a preset key or your own local .html file |
| templates show <key> [-o file.html] | Print or save the source HTML of any preset — copy it as a starting point for a custom template |
| frames render -t <keyOrPath> --title ... --text ... | Render a single composed frame to PNG. -t accepts a preset key or a local .html path |
| compositions concat <v1> <v2> -o out.mp4 | FFmpeg concat (+ optional BGM) |
| compositions bgm -i video.mp4 --bgm bgm.mp3 -o out.mp4 | Add background music |
| compositions image-to-video -i img.png -a aud.mp3 -o out.mp4 | Build video from image + audio |
| compositions overlay -v video.mp4 --overlay overlay.png -o out.mp4 | Overlay PNG on video |
End-to-end pipelines
All pipelines * commands submit an async task and (by default) poll until it finishes with a live progress indicator on stderr. Use --no-wait to return immediately with a task_id, then rf tasks wait <id> later.
The standard pipeline is audio-first: scene-plan → one-shot TTS → ASR alignment → per-scene image generation → per-subtitle-line frame rendering → ffmpeg mux. One continuous master audio track; image cuts at scene boundaries; subtitle cuts at line boundaries.
| command | what it does |
|---|---|
| pipelines standard -t <topic> (or --script <text>) | Audio-first pipeline; -d/--duration and -p/--pace are the two main knobs |
Resources
| command | what it does |
|---|---|
| bgm list / upload <file> / delete <name> | Manage background music |
| files list / upload <file> / download <path> / delete <path> | Manage user assets |
System
| command | what it does |
|---|---|
| config get | Read server config (keys masked) |
| config set <key> <value> | Update a dotted-path setting (e.g. llm.api_key sk-xxx) |
| config patch <file> | Apply a JSON-merge patch |
| tasks list [--status running] | List recent tasks |
| tasks get <id> / tasks wait <id> / tasks cancel <id> | Task lifecycle |
| history list / get <id> / delete <id> | Browse / delete completed runs |
| health | Server health + capability check |
Examples
# 1. One-click out a video (45s default, AI writes the script)
rf create "为什么我们还没找到外星文明?"
# 2. Longer video with a slower visual rhythm
rf create "深夜便利店的灯光" -d 90 -p slow
# 3. Your own script — no narration-splitting on your side, the pipeline handles it
rf create --script @./my-script.txt
rf create --script "雨水缓缓滑落在玻璃窗上,像是无声的泪珠。"
# 4. Pick a built-in visual style preset
rf create "美食教程" --style photorealistic
# 5. Pipeline form with explicit output path
rf pipelines standard \
--script @./script.txt \
--frame-template 1080x1920/image_default.html \
-p normal -o smoke.mp4
# 6. Inspect existing tasks & redownload a finished video
rf tasks list --limit 5
rf history get <task-id> --download recovered.mp4
# 7. Atomics for stand-alone use
rf content scene-plan -t "雨天的玻璃窗" -d 45 --json | jq .scenes
rf audio transcribe -f narration.mp3 --json | jq '.words[:5]'
rf subtitles split -t @./narration.txt --min 10 --hard-max 24
# 8. JSON pipe for automation
rf llm presets --json | jq '.[].defaultModel'
# 9. Configure & test LLM (self-hosted)
rf config set llm.api_key rx-xxxxx # RelayX key (or your own provider key)
rf config set llm.base_url https://relayx.timor419.com/v1
rf config set llm.model anthropic/claude-4-7-sonnet
rf llm chat -p 'one-sentence summary of antifragile'
# 10. Use your own HTML template (no PR/release needed)
# Any --frame-template that points to a local .html file is read and sent
# inline. Declare size inside the file via
# <meta name="template:width" content="1080">
# <meta name="template:height" content="1920">
# or pass --frame-template-size 1080x1920.
rf templates show 1080x1920/image_default.html -o my-brand.html # copy a preset
# ...edit my-brand.html to suit your style...
rf templates preview ./my-brand.html --title "Hello" -o preview.png
rf frames render -t ./my-brand.html --values '{"author":"Alice"}' -o frame.png
rf pipelines standard -t "宠物" --frame-template ./my-brand.html -o final.mp4Custom HTML templates
Easiest way to start: grab a preset as a reference.
rf templates list # see all keys
rf templates show 1080x1920/static_default.html # print to stdout
rf templates show 1080x1920/image_default.html -o my-brand.html # save and edit{{title}}, {{text}}, {{image}}, {{index}}, {{total}} are reserved built-ins auto-injected by the pipeline; everything else uses the {{name:type=default}} DSL (type ∈ text|number|color|bool). Pass extras through --values '{"author":"Alice"}' (or template_params on the pipeline API).
{{index}}— current scene number, 1-based{{total}}— scene count the LLM actually produced (use this for "scene N of M" badges; don't hardcode intemplate_params, the scene count is decided at runtime)
Template type — does the pipeline generate an AI image per scene?
When you ship an inline template through rf create / rf pipelines standard, ReelForge needs to know whether each scene should kick off RelayX image generation. Resolution priority (high → low):
- Explicit flag —
--frame-template-type image|static|asset(orframe_template_typein the API body). - Inside the HTML —
<meta name="template:type" content="image">(orstatic/asset). - Default:
image— best practice for zero-config users. If your template doesn't reference scene imagery (pure-text card, etc.), declarestaticexplicitly to skip image generation and its cost.
The placeholder {{image}} no longer doubles as a type signal — declare type explicitly.
Limits and safety:
- Max 2 MB per inline HTML.
- The render sandbox blocks
file://, loopback / private / link-local IPs, CGNAT range, cloud-metadata, and*.local/*.internalhostnames. So your template can only reference publichttps/httpresources ordata:URIs. - If the CLI is talking to a hosted server, local-path
--imagewon't reach the server; either upload torf files uploadfirst or use an HTTPS URL / data: URI.
API field reference
| endpoint | inline HTML field | size field | type field |
|---|---|---|---|
| POST /api/v1/frames/render | template_html | size | — (n/a, no image generation) |
| POST /api/v1/templates/preview | template_html | size | — |
| POST /api/v1/pipelines/standard | frame_template_inline | frame_template_size | frame_template_type |
The pipeline endpoint uses the frame_template_* prefix because it already has a frame_template field (preset key). The single-frame endpoints use the shorter template_html because they don't.
Tip — getting unstuck
Every level has --help:
rf --help # top-level overview
rf pipelines --help # list of pipelines
rf pipelines standard --help # full option reference
rf tts edge --help # one specific commandLicense
Apache-2.0
