janction-render 0.4.0__tar.gz → 0.4.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {janction_render-0.4.0 → janction_render-0.4.2}/PKG-INFO +23 -7
- {janction_render-0.4.0 → janction_render-0.4.2}/README.md +22 -6
- {janction_render-0.4.0 → janction_render-0.4.2}/janction_render/__init__.py +1 -1
- {janction_render-0.4.0 → janction_render-0.4.2}/janction_render/brief.py +3 -3
- {janction_render-0.4.0 → janction_render-0.4.2}/janction_render/cli.py +6 -3
- {janction_render-0.4.0 → janction_render-0.4.2}/janction_render/mcp_app.html +2 -0
- {janction_render-0.4.0 → janction_render-0.4.2}/janction_render/mcp_server.py +50 -28
- {janction_render-0.4.0 → janction_render-0.4.2}/janction_render.egg-info/PKG-INFO +23 -7
- {janction_render-0.4.0 → janction_render-0.4.2}/pyproject.toml +1 -1
- {janction_render-0.4.0 → janction_render-0.4.2}/LICENSE +0 -0
- {janction_render-0.4.0 → janction_render-0.4.2}/janction_render/client.py +0 -0
- {janction_render-0.4.0 → janction_render-0.4.2}/janction_render.egg-info/SOURCES.txt +0 -0
- {janction_render-0.4.0 → janction_render-0.4.2}/janction_render.egg-info/dependency_links.txt +0 -0
- {janction_render-0.4.0 → janction_render-0.4.2}/janction_render.egg-info/entry_points.txt +0 -0
- {janction_render-0.4.0 → janction_render-0.4.2}/janction_render.egg-info/requires.txt +0 -0
- {janction_render-0.4.0 → janction_render-0.4.2}/janction_render.egg-info/top_level.txt +0 -0
- {janction_render-0.4.0 → janction_render-0.4.2}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: janction-render
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.2
|
|
4
4
|
Summary: Cloud GPU render farm for Blender, for AI agents: MCP server (remote + stdio) and CLI. Render Blender without a GPU from Claude, ChatGPT, Claude Code, Codex, Cursor.
|
|
5
5
|
Requires-Python: >=3.11
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -31,7 +31,8 @@ without a GPU, or when rendering locally is slow.
|
|
|
31
31
|
- `orbit=True` turns any scene or imported model into a turntable: an orbit camera circles it once (`orbit_frames`, default 24;
|
|
32
32
|
a preview shows 0/90/180/270 degrees, a final render without `frame_end` gives the whole turn as an MP4). Flat floors and
|
|
33
33
|
walls are ignored when framing; `orbit_target` (object name or `x,y,z`) and `orbit_distance` (multiplier) adjust the shot.
|
|
34
|
-
- While the GPU is lent to another workload, tools answer right away with the queued job and a
|
|
34
|
+
- While the GPU is lent to another workload, tools answer right away with the queued job and a wait estimate (how long it
|
|
35
|
+
has been out, how long it usually stays out, how much longer to expect; `eta.gate`) instead of waiting.
|
|
35
36
|
- While a job renders, `render_status` counts finished frames inside the running chunk, so the ETA updates every few seconds.
|
|
36
37
|
- In hosts that support MCP Apps (Claude web and desktop, among others), previews, progress and download links also appear
|
|
37
38
|
as an interactive panel in the chat: the image, a progress bar, "Open MP4", and preset buttons after an `environment="compare"` preview.
|
|
@@ -51,7 +52,8 @@ Free beta. Service page: `https://render.janction.jp` (`/v1/health`, `/llms.txt`
|
|
|
51
52
|
Guides: [render farm for agents](https://render.janction.jp/blender-render-farm) · [without a GPU](https://render.janction.jp/render-blender-without-gpu) ·
|
|
52
53
|
[Claude](https://render.janction.jp/claude-blender) · [ChatGPT](https://render.janction.jp/chatgpt-blender) · [Claude Code](https://render.janction.jp/claude-code-blender) ·
|
|
53
54
|
[Codex](https://render.janction.jp/codex-blender) · [bpy scripts](https://render.janction.jp/bpy-script-cloud-gpu) · [API](https://render.janction.jp/blender-render-api) ·
|
|
54
|
-
[comparison](https://render.janction.jp/blender-render-farm-api-comparison) ·
|
|
55
|
+
[comparison](https://render.janction.jp/blender-render-farm-api-comparison) · [Blender add-on](https://render.janction.jp/blender-addon) ·
|
|
56
|
+
[Maya / Houdini / Cinema 4D](https://render.janction.jp/maya-houdini-cinema4d) · 日本語は `/ja/`
|
|
55
57
|
|
|
56
58
|
## Connect (remote MCP, nothing to install)
|
|
57
59
|
|
|
@@ -114,7 +116,7 @@ Then, in Claude Code:
|
|
|
114
116
|
| `scene_info(scene_script | scene_url | scene_path | scene_id, assets?)` | cameras, frame range, fps, resolution, objects, lights, missing files. No render. |
|
|
115
117
|
| `render_preview(..., frames="1-24", environment?, blender?)` | up to 4 frames (720p budget) tiled with frame labels; returns the image inline |
|
|
116
118
|
| `render_estimate(scene_id, frame_start, frame_end, width, height, samples)` | GPU seconds, queue wait, "about N minutes", fits today's free quota? No GPU time used |
|
|
117
|
-
| `render_final(scene_id, frame_start, frame_end, width, height, samples, fps, output, environment?, blender?, engine?)` | frames (png / exr) or video (mp4 / webm / prores); returns job_id + estimate |
|
|
119
|
+
| `render_final(scene_id, frame_start, frame_end, width, height, samples, fps, output, environment?, blender?, engine?, transparent?, notify_url?)` | frames (png / exr) or video (mp4 / webm / prores / gif / webp); `transparent=True` keeps an alpha background (png / exr / webm / gif / webp); `notify_url` gets one JSON POST when the job finishes; returns job_id + estimate |
|
|
118
120
|
| `render_status(job_id)` | progress and ETA (`eta.human`); `render_download(job_id, only="mp4" / "frames" / "all")` files or links; `render_cancel(job_id)` |
|
|
119
121
|
| `billing()` | free-beta quota (used today, daily limit, reset time); later balance and top-up link |
|
|
120
122
|
| `render_info()` | workers online or gated (GPU lent to another workload), queue, expected wait, supported inputs, environment presets, Blender versions |
|
|
@@ -153,7 +155,7 @@ POST /v1/keys -> {api_key} (header X-A
|
|
|
153
155
|
POST /v1/files multipart "file" (.blend|.py|.glb|.fbx|.usd|.obj|...) -> {scene_id}
|
|
154
156
|
POST /v1/files/{id}/assets multipart "files" textures, glTF .bin ... GET /v1/files/lookup?sha256= reuse an upload
|
|
155
157
|
POST /v1/estimate {kind, frames|frame_start/frame_end, width, height, samples, scene_id?} -> seconds, wall_seconds, human, quota
|
|
156
|
-
POST /v1/jobs {scene_id, kind: info|preview|final, frames|frame_start/frame_end, width, height, samples, camera, fps, output (png|exr|mp4|webm|prores), engine (cycles|eevee),
|
|
158
|
+
POST /v1/jobs {scene_id, kind: info|preview|final, frames|frame_start/frame_end, width, height, samples, camera, fps, output (png|exr|mp4|webm|prores|gif|webp), transparent, notify_url (https), engine (cycles|eevee),
|
|
157
159
|
environment, environment_strength, environment_visible, blender, orbit, orbit_frames, orbit_elevation}
|
|
158
160
|
GET /v1/jobs/{id} status, progress, eta, artifacts[], cost, warnings, info DELETE /v1/jobs/{id} cancel
|
|
159
161
|
GET /v1/jobs/{id}/artifacts/{name} PNG / MP4
|
|
@@ -166,11 +168,24 @@ GET /llms.txt /llms-full.txt /ja/llms.txt /faq /terms /privacy /legal /s
|
|
|
166
168
|
During the free beta a `429 quota_exceeded` response carries `resets_at`; a `400 beta_limit` means the job is too big
|
|
167
169
|
(split it). Once paid plans start, a `402 payment_required` response carries `checkout_url`.
|
|
168
170
|
|
|
171
|
+
## Blender add-on and DCC tools (for people, not agents)
|
|
172
|
+
|
|
173
|
+
- **Blender extension** (`addons/blender/`, Blender 4.2+): a JANCTION Render panel under Properties → Render with Preview,
|
|
174
|
+
Estimate and Final. A copy of the open file and the textures it references with relative paths are uploaded; results land
|
|
175
|
+
next to the .blend. Install from the extension repository `https://render.janction.jp/extensions/index.json`
|
|
176
|
+
(Preferences → Get Extensions → Repositories → + → Add Remote Repository), or install the zip from
|
|
177
|
+
`https://render.janction.jp/extensions/janction_render-0.1.0.zip` (`python scripts/build_blender_addon.py` builds it
|
|
178
|
+
from this repository). Guide: https://render.janction.jp/blender-addon
|
|
179
|
+
- **Maya, Houdini, Cinema 4D** (`integrations/`): export to USD / FBX / Alembic, upload with textures, render with Cycles,
|
|
180
|
+
open the result; Preview, Final (MP4) and Turntable. Standard-library Python only; `jr_submit.py` is the shared client.
|
|
181
|
+
Guide: https://render.janction.jp/maya-houdini-cinema4d
|
|
182
|
+
|
|
169
183
|
## Self-hosting
|
|
170
184
|
|
|
171
185
|
The server (FastAPI + SQLite, with the remote MCP endpoint) and the worker (Blender in disposable Docker containers,
|
|
172
186
|
`--network none --cap-drop ALL`) live in the internal repository and are not part of this package yet. This repository
|
|
173
|
-
holds the client side: stdio MCP server, CLI, HTTP client, samples
|
|
187
|
+
holds the client side: stdio MCP server, CLI, HTTP client, samples, the Claude Code plugin, the Blender add-on and the
|
|
188
|
+
DCC tools.
|
|
174
189
|
|
|
175
190
|
## MCP registry
|
|
176
191
|
|
|
@@ -180,4 +195,5 @@ mcp-name: io.github.JasmyLab-JANCTION/janction-render
|
|
|
180
195
|
|
|
181
196
|
## License
|
|
182
197
|
|
|
183
|
-
MIT (see LICENSE).
|
|
198
|
+
MIT (see LICENSE) for the package, the MCP servers, the CLI and the DCC tools. The Blender extension under
|
|
199
|
+
`addons/blender/` is GPL-3.0-or-later, as Blender requires for add-ons. Operated by JasmyLab Inc.
|
|
@@ -14,7 +14,8 @@ without a GPU, or when rendering locally is slow.
|
|
|
14
14
|
- `orbit=True` turns any scene or imported model into a turntable: an orbit camera circles it once (`orbit_frames`, default 24;
|
|
15
15
|
a preview shows 0/90/180/270 degrees, a final render without `frame_end` gives the whole turn as an MP4). Flat floors and
|
|
16
16
|
walls are ignored when framing; `orbit_target` (object name or `x,y,z`) and `orbit_distance` (multiplier) adjust the shot.
|
|
17
|
-
- While the GPU is lent to another workload, tools answer right away with the queued job and a
|
|
17
|
+
- While the GPU is lent to another workload, tools answer right away with the queued job and a wait estimate (how long it
|
|
18
|
+
has been out, how long it usually stays out, how much longer to expect; `eta.gate`) instead of waiting.
|
|
18
19
|
- While a job renders, `render_status` counts finished frames inside the running chunk, so the ETA updates every few seconds.
|
|
19
20
|
- In hosts that support MCP Apps (Claude web and desktop, among others), previews, progress and download links also appear
|
|
20
21
|
as an interactive panel in the chat: the image, a progress bar, "Open MP4", and preset buttons after an `environment="compare"` preview.
|
|
@@ -34,7 +35,8 @@ Free beta. Service page: `https://render.janction.jp` (`/v1/health`, `/llms.txt`
|
|
|
34
35
|
Guides: [render farm for agents](https://render.janction.jp/blender-render-farm) · [without a GPU](https://render.janction.jp/render-blender-without-gpu) ·
|
|
35
36
|
[Claude](https://render.janction.jp/claude-blender) · [ChatGPT](https://render.janction.jp/chatgpt-blender) · [Claude Code](https://render.janction.jp/claude-code-blender) ·
|
|
36
37
|
[Codex](https://render.janction.jp/codex-blender) · [bpy scripts](https://render.janction.jp/bpy-script-cloud-gpu) · [API](https://render.janction.jp/blender-render-api) ·
|
|
37
|
-
[comparison](https://render.janction.jp/blender-render-farm-api-comparison) ·
|
|
38
|
+
[comparison](https://render.janction.jp/blender-render-farm-api-comparison) · [Blender add-on](https://render.janction.jp/blender-addon) ·
|
|
39
|
+
[Maya / Houdini / Cinema 4D](https://render.janction.jp/maya-houdini-cinema4d) · 日本語は `/ja/`
|
|
38
40
|
|
|
39
41
|
## Connect (remote MCP, nothing to install)
|
|
40
42
|
|
|
@@ -97,7 +99,7 @@ Then, in Claude Code:
|
|
|
97
99
|
| `scene_info(scene_script | scene_url | scene_path | scene_id, assets?)` | cameras, frame range, fps, resolution, objects, lights, missing files. No render. |
|
|
98
100
|
| `render_preview(..., frames="1-24", environment?, blender?)` | up to 4 frames (720p budget) tiled with frame labels; returns the image inline |
|
|
99
101
|
| `render_estimate(scene_id, frame_start, frame_end, width, height, samples)` | GPU seconds, queue wait, "about N minutes", fits today's free quota? No GPU time used |
|
|
100
|
-
| `render_final(scene_id, frame_start, frame_end, width, height, samples, fps, output, environment?, blender?, engine?)` | frames (png / exr) or video (mp4 / webm / prores); returns job_id + estimate |
|
|
102
|
+
| `render_final(scene_id, frame_start, frame_end, width, height, samples, fps, output, environment?, blender?, engine?, transparent?, notify_url?)` | frames (png / exr) or video (mp4 / webm / prores / gif / webp); `transparent=True` keeps an alpha background (png / exr / webm / gif / webp); `notify_url` gets one JSON POST when the job finishes; returns job_id + estimate |
|
|
101
103
|
| `render_status(job_id)` | progress and ETA (`eta.human`); `render_download(job_id, only="mp4" / "frames" / "all")` files or links; `render_cancel(job_id)` |
|
|
102
104
|
| `billing()` | free-beta quota (used today, daily limit, reset time); later balance and top-up link |
|
|
103
105
|
| `render_info()` | workers online or gated (GPU lent to another workload), queue, expected wait, supported inputs, environment presets, Blender versions |
|
|
@@ -136,7 +138,7 @@ POST /v1/keys -> {api_key} (header X-A
|
|
|
136
138
|
POST /v1/files multipart "file" (.blend|.py|.glb|.fbx|.usd|.obj|...) -> {scene_id}
|
|
137
139
|
POST /v1/files/{id}/assets multipart "files" textures, glTF .bin ... GET /v1/files/lookup?sha256= reuse an upload
|
|
138
140
|
POST /v1/estimate {kind, frames|frame_start/frame_end, width, height, samples, scene_id?} -> seconds, wall_seconds, human, quota
|
|
139
|
-
POST /v1/jobs {scene_id, kind: info|preview|final, frames|frame_start/frame_end, width, height, samples, camera, fps, output (png|exr|mp4|webm|prores), engine (cycles|eevee),
|
|
141
|
+
POST /v1/jobs {scene_id, kind: info|preview|final, frames|frame_start/frame_end, width, height, samples, camera, fps, output (png|exr|mp4|webm|prores|gif|webp), transparent, notify_url (https), engine (cycles|eevee),
|
|
140
142
|
environment, environment_strength, environment_visible, blender, orbit, orbit_frames, orbit_elevation}
|
|
141
143
|
GET /v1/jobs/{id} status, progress, eta, artifacts[], cost, warnings, info DELETE /v1/jobs/{id} cancel
|
|
142
144
|
GET /v1/jobs/{id}/artifacts/{name} PNG / MP4
|
|
@@ -149,11 +151,24 @@ GET /llms.txt /llms-full.txt /ja/llms.txt /faq /terms /privacy /legal /s
|
|
|
149
151
|
During the free beta a `429 quota_exceeded` response carries `resets_at`; a `400 beta_limit` means the job is too big
|
|
150
152
|
(split it). Once paid plans start, a `402 payment_required` response carries `checkout_url`.
|
|
151
153
|
|
|
154
|
+
## Blender add-on and DCC tools (for people, not agents)
|
|
155
|
+
|
|
156
|
+
- **Blender extension** (`addons/blender/`, Blender 4.2+): a JANCTION Render panel under Properties → Render with Preview,
|
|
157
|
+
Estimate and Final. A copy of the open file and the textures it references with relative paths are uploaded; results land
|
|
158
|
+
next to the .blend. Install from the extension repository `https://render.janction.jp/extensions/index.json`
|
|
159
|
+
(Preferences → Get Extensions → Repositories → + → Add Remote Repository), or install the zip from
|
|
160
|
+
`https://render.janction.jp/extensions/janction_render-0.1.0.zip` (`python scripts/build_blender_addon.py` builds it
|
|
161
|
+
from this repository). Guide: https://render.janction.jp/blender-addon
|
|
162
|
+
- **Maya, Houdini, Cinema 4D** (`integrations/`): export to USD / FBX / Alembic, upload with textures, render with Cycles,
|
|
163
|
+
open the result; Preview, Final (MP4) and Turntable. Standard-library Python only; `jr_submit.py` is the shared client.
|
|
164
|
+
Guide: https://render.janction.jp/maya-houdini-cinema4d
|
|
165
|
+
|
|
152
166
|
## Self-hosting
|
|
153
167
|
|
|
154
168
|
The server (FastAPI + SQLite, with the remote MCP endpoint) and the worker (Blender in disposable Docker containers,
|
|
155
169
|
`--network none --cap-drop ALL`) live in the internal repository and are not part of this package yet. This repository
|
|
156
|
-
holds the client side: stdio MCP server, CLI, HTTP client, samples
|
|
170
|
+
holds the client side: stdio MCP server, CLI, HTTP client, samples, the Claude Code plugin, the Blender add-on and the
|
|
171
|
+
DCC tools.
|
|
157
172
|
|
|
158
173
|
## MCP registry
|
|
159
174
|
|
|
@@ -163,4 +178,5 @@ mcp-name: io.github.JasmyLab-JANCTION/janction-render
|
|
|
163
178
|
|
|
164
179
|
## License
|
|
165
180
|
|
|
166
|
-
MIT (see LICENSE).
|
|
181
|
+
MIT (see LICENSE) for the package, the MCP servers, the CLI and the DCC tools. The Blender extension under
|
|
182
|
+
`addons/blender/` is GPL-3.0-or-later, as Blender requires for add-ons. Operated by JasmyLab Inc.
|
|
@@ -8,7 +8,7 @@ JST = 9 * 3600
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
def iso(ts: float | int | None) -> str | None:
|
|
11
|
-
"""epoch 秒 → "2026-10-
|
|
11
|
+
"""epoch 秒 → "2026-10-01T04:12:00Z (2026-10-01 13:12 JST)"。エージェントがそのまま伝えられる形。"""
|
|
12
12
|
if ts is None:
|
|
13
13
|
return None
|
|
14
14
|
try:
|
|
@@ -34,7 +34,7 @@ def eta_brief(e: dict[str, Any] | None) -> dict[str, Any] | None:
|
|
|
34
34
|
if not e:
|
|
35
35
|
return None
|
|
36
36
|
keep = ("human", "remaining_seconds", "queue_wait_seconds", "remaining_gpu_seconds", "elapsed_seconds",
|
|
37
|
-
"running_for_seconds", "took_seconds", "workers_online", "basis")
|
|
37
|
+
"running_for_seconds", "took_seconds", "workers_online", "basis", "gate")
|
|
38
38
|
return {k: e[k] for k in keep if e.get(k) is not None}
|
|
39
39
|
|
|
40
40
|
|
|
@@ -42,7 +42,7 @@ def estimate_brief(e: dict[str, Any] | None) -> dict[str, Any] | None:
|
|
|
42
42
|
if not e:
|
|
43
43
|
return None
|
|
44
44
|
keep = ("human", "seconds", "wall_seconds", "queue_wait_seconds", "per_frame_seconds", "frames", "chunks",
|
|
45
|
-
"workers_online", "basis", "basis_note", "note", "quota", "cost")
|
|
45
|
+
"workers_online", "basis", "basis_note", "note", "quota", "cost", "gate")
|
|
46
46
|
return {k: e[k] for k in keep if e.get(k) is not None}
|
|
47
47
|
|
|
48
48
|
|
|
@@ -98,7 +98,8 @@ def cmd_render(c: Client, args: argparse.Namespace) -> int:
|
|
|
98
98
|
w, h = args.size
|
|
99
99
|
fs, fe = args.frames
|
|
100
100
|
j = c.submit(sid, kind="final", frame_start=fs, frame_end=fe, width=w, height=h,
|
|
101
|
-
samples=args.samples, fps=args.fps, output=args.output, camera=args.camera, engine=args.engine
|
|
101
|
+
samples=args.samples, fps=args.fps, output=args.output, camera=args.camera, engine=args.engine,
|
|
102
|
+
transparent=args.transparent or None, notify_url=args.notify_url or None)
|
|
102
103
|
print(f"job {j['job_id']} queued: {fe - fs + 1} frames in {j['progress']['chunks_total']} chunks, "
|
|
103
104
|
f"estimate ~{j['estimate']['seconds']}s", file=sys.stderr)
|
|
104
105
|
if not args.wait:
|
|
@@ -200,8 +201,10 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
200
201
|
s.add_argument("--samples", type=int, default=128)
|
|
201
202
|
s.add_argument("--engine", choices=["cycles", "eevee"], default=None, help="cycles (default) or eevee (cheaper drafts)")
|
|
202
203
|
s.add_argument("--fps", type=int, default=24)
|
|
203
|
-
s.add_argument("--output", choices=["auto", "png", "exr", "mp4", "webm", "prores"], default="auto",
|
|
204
|
-
help="png/exr = frames, mp4/webm/prores = video (auto: mp4 for a range, png for one frame)")
|
|
204
|
+
s.add_argument("--output", choices=["auto", "png", "exr", "mp4", "webm", "prores", "gif", "webp"], default="auto",
|
|
205
|
+
help="png/exr = frames, mp4/webm/prores/gif/webp = video (auto: mp4 for a range, png for one frame)")
|
|
206
|
+
s.add_argument("--transparent", action="store_true", help="transparent background (png/exr/webm/gif/webp)")
|
|
207
|
+
s.add_argument("--notify-url", default=None, help="https URL that receives one JSON POST when the job finishes")
|
|
205
208
|
s.add_argument("--camera", default=None)
|
|
206
209
|
s.add_argument("--out", default=None)
|
|
207
210
|
s.add_argument("--wait", action="store_true", help="wait until done and download")
|
|
@@ -92,6 +92,8 @@ function render() {
|
|
|
92
92
|
const links = job.links || {};
|
|
93
93
|
if (status === "done" && out && /\.(mp4|webm|mov)(\?|$)/.test(out)) {
|
|
94
94
|
html += `<video controls playsinline src="${esc(out)}"></video>`;
|
|
95
|
+
} else if (status === "done" && out && /\.(gif|webp)(\?|$)/.test(out)) {
|
|
96
|
+
html += `<img class="sheet" src="${esc(out)}" alt="animation">`;
|
|
95
97
|
}
|
|
96
98
|
if (status === "done" && isCompare(job)) {
|
|
97
99
|
html += `<div class="muted">Pick the lighting for the final render:</div><div class="grid">` +
|
|
@@ -52,6 +52,13 @@ mcp = MCPServer(
|
|
|
52
52
|
),
|
|
53
53
|
)
|
|
54
54
|
|
|
55
|
+
OUTPUT_DOC = (" output: 'auto' (mp4 for a frame range, png for one frame) | 'png' | 'exr' (16-bit linear OpenEXR frames) | "
|
|
56
|
+
"'mp4' (H.264) | 'webm' (VP9) | 'prores' (ProRes 422 HQ .mov) | 'gif' | 'webp' (animated, at most 960 px wide; "
|
|
57
|
+
"good for chat and web). transparent=True renders on a transparent background (alpha): png / exr frames, webm, gif "
|
|
58
|
+
"and webp keep it, mp4 and prores cannot. notify_url: an https URL that receives one JSON POST when the job "
|
|
59
|
+
"finishes (event job.done / job.failed, artifacts with download links).")
|
|
60
|
+
TRANSPARENT_DOC = (" transparent=True: transparent background (alpha) instead of the world/HDRI backdrop; the preview sheet "
|
|
61
|
+
"shows it over dark grey.")
|
|
55
62
|
ORBIT_DOC = (" orbit=True: turntable; an orbit camera circles the scene once over orbit_frames frames (default 24, "
|
|
56
63
|
"elevation orbit_elevation deg, default 18). Flat floors/walls are ignored when framing; orbit_target = an "
|
|
57
64
|
"object name or 'x,y,z' centres on that, orbit_distance scales the distance (1.0). A preview without frames "
|
|
@@ -110,8 +117,10 @@ def _wait_unless_gated(c: Client, job: dict[str, Any], timeout: float) -> dict[s
|
|
|
110
117
|
|
|
111
118
|
def _gated_hint(j: dict[str, Any], again: str) -> str:
|
|
112
119
|
if j.get("gated"):
|
|
113
|
-
|
|
114
|
-
|
|
120
|
+
# 受付の eta.human に「閉じてからの経過・ふだん戻るまでの時間・あと何分」が入っている
|
|
121
|
+
why = str((j.get("eta") or {}).get("human") or "the GPU is lent to another workload right now; the job stays queued and starts when the GPU returns")
|
|
122
|
+
return (f"{why}. Tell the user how long the wait is likely to be and offer to check later with {again}; "
|
|
123
|
+
"do not poll continuously")
|
|
115
124
|
return ""
|
|
116
125
|
|
|
117
126
|
|
|
@@ -239,7 +248,24 @@ def scene_info(scene_path: str = "", scene_id: str = "", scene_script: str = "",
|
|
|
239
248
|
return _j(_attach_upload_notes(info))
|
|
240
249
|
|
|
241
250
|
|
|
242
|
-
|
|
251
|
+
RENDER_PREVIEW_DESCRIPTION = (
|
|
252
|
+
"""Render a fast, cheap preview of a Blender scene on a JANCTION GPU and show the image.
|
|
253
|
+
|
|
254
|
+
Use this when the user is making 3DCG with Blender and wants to see how it looks, but has no
|
|
255
|
+
GPU or local rendering is slow. Give the scene as scene_path (a .blend file OR a bpy Python
|
|
256
|
+
script), scene_script (bpy code as text; no file and no local Blender needed), or scene_id
|
|
257
|
+
from a previous call. frames: '' = frame 1;
|
|
258
|
+
'12' = one frame; '1,8,16,24' or '1-24' = up to 4 frames tiled in ONE image (2x2, each tile
|
|
259
|
+
labeled with its frame number) so you can judge camera motion and animation. Same GPU cost as
|
|
260
|
+
one 720p frame. Quality is deliberately low (up to 1280x720, few samples, denoised).
|
|
261
|
+
Look at the returned image, fix the scene, preview again; when it looks right, ask the user and
|
|
262
|
+
call render_final. Returns scene_id (reuse it without re-uploading), job_id, saved PNG paths,
|
|
263
|
+
Blender warnings (e.g. missing textures), GPU seconds, and the expiry time (24h after last use).
|
|
264
|
+
""" + ENV_DOC + ORBIT_DOC + TRANSPARENT_DOC
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
@mcp.tool(structured_output=False, meta=_ui_meta(), description=RENDER_PREVIEW_DESCRIPTION)
|
|
243
269
|
def render_preview(
|
|
244
270
|
scene_path: str = "",
|
|
245
271
|
scene_id: str = "",
|
|
@@ -261,26 +287,15 @@ def render_preview(
|
|
|
261
287
|
orbit_target: str = "",
|
|
262
288
|
orbit_distance: float = 1.0,
|
|
263
289
|
engine: str = "",
|
|
290
|
+
transparent: bool = False,
|
|
264
291
|
) -> list[Any]:
|
|
265
|
-
"""Render a fast, cheap preview of a Blender scene on a JANCTION GPU and show the image.
|
|
266
|
-
|
|
267
|
-
Use this when the user is making 3DCG with Blender and wants to see how it looks, but has no
|
|
268
|
-
GPU or local rendering is slow. Give the scene as scene_path (a .blend file OR a bpy Python
|
|
269
|
-
script), scene_script (bpy code as text; no file and no local Blender needed), or scene_id
|
|
270
|
-
from a previous call. frames: '' = frame 1;
|
|
271
|
-
'12' = one frame; '1,8,16,24' or '1-24' = up to 4 frames tiled in ONE image (2x2, each tile
|
|
272
|
-
labeled with its frame number) so you can judge camera motion and animation. Same GPU cost as
|
|
273
|
-
one 720p frame. Quality is deliberately low (up to 1280x720, few samples, denoised).
|
|
274
|
-
Look at the returned image, fix the scene, preview again; when it looks right, ask the user and
|
|
275
|
-
call render_final. Returns scene_id (reuse it without re-uploading), job_id, saved PNG paths,
|
|
276
|
-
Blender warnings (e.g. missing textures), GPU seconds, and the expiry time (24h after last use).
|
|
277
|
-
""" + ENV_DOC + ORBIT_DOC
|
|
292
|
+
"""Render a fast, cheap preview of a Blender scene on a JANCTION GPU and show the image. (full description on the tool)."""
|
|
278
293
|
c = _client()
|
|
279
294
|
try:
|
|
280
295
|
frame_list = parse_frames(frames) if (frames or not orbit) else None
|
|
281
296
|
sid = _resolve_scene(c, scene_path, scene_id, scene_script, assets)
|
|
282
297
|
j = c.submit(sid, kind="preview", frames=frame_list, camera=camera or None,
|
|
283
|
-
width=width, height=height, samples=samples,
|
|
298
|
+
width=width, height=height, samples=samples, transparent=(True if transparent else None),
|
|
284
299
|
**_job_params(environment, environment_strength, environment_visible, blender, engine=engine),
|
|
285
300
|
**({"orbit": True, "orbit_frames": orbit_frames, "orbit_elevation": orbit_elevation,
|
|
286
301
|
"orbit_target": orbit_target, "orbit_distance": orbit_distance} if orbit else {}))
|
|
@@ -341,7 +356,20 @@ def render_estimate(scene_id: str = "", kind: str = "final", frame_start: int =
|
|
|
341
356
|
return _j(out)
|
|
342
357
|
|
|
343
358
|
|
|
344
|
-
|
|
359
|
+
RENDER_FINAL_DESCRIPTION = (
|
|
360
|
+
"""Render the final frames (or a video) of a Blender scene on JANCTION GPUs.
|
|
361
|
+
|
|
362
|
+
Call this after the user approved a preview. Pass scene_id from render_preview (or scene_path /
|
|
363
|
+
scene_script to upload a new .blend / bpy script / 3D file). frame_start..frame_end are inclusive; several frames are
|
|
364
|
+
split across GPUs and joined into output.mp4 (output='mp4', fps), a single frame gives a PNG
|
|
365
|
+
(output='png'; 'auto' picks). Use the same environment / blender as the approved preview. Returns job_id and a
|
|
366
|
+
time estimate right away; the render runs in the background: poll with render_status, then fetch with
|
|
367
|
+
render_download. Inputs and results are deleted 24 hours after last use, so download them.
|
|
368
|
+
""" + ENV_DOC + ORBIT_DOC + OUTPUT_DOC
|
|
369
|
+
)
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
@mcp.tool(meta=_ui_meta(), description=RENDER_FINAL_DESCRIPTION)
|
|
345
373
|
def render_final(
|
|
346
374
|
scene_path: str = "",
|
|
347
375
|
scene_id: str = "",
|
|
@@ -365,16 +393,10 @@ def render_final(
|
|
|
365
393
|
orbit_target: str = "",
|
|
366
394
|
orbit_distance: float = 1.0,
|
|
367
395
|
engine: str = "",
|
|
396
|
+
transparent: bool = False,
|
|
397
|
+
notify_url: str = "",
|
|
368
398
|
) -> str:
|
|
369
|
-
"""Render the final frames (or a video) of a Blender scene on JANCTION GPUs.
|
|
370
|
-
|
|
371
|
-
Call this after the user approved a preview. Pass scene_id from render_preview (or scene_path /
|
|
372
|
-
scene_script to upload a new .blend / bpy script / 3D file). frame_start..frame_end are inclusive; several frames are
|
|
373
|
-
split across GPUs and joined into output.mp4 (output='mp4', fps), a single frame gives a PNG
|
|
374
|
-
(output='png'; 'auto' picks). Use the same environment / blender as the approved preview. Returns job_id and a
|
|
375
|
-
time estimate right away; the render runs in the background: poll with render_status, then fetch with
|
|
376
|
-
render_download. Inputs and results are deleted 24 hours after last use, so download them.
|
|
377
|
-
""" + ENV_DOC + ORBIT_DOC
|
|
399
|
+
"""Render the final frames (or a video) of a Blender scene on JANCTION GPUs. (full description on the tool)."""
|
|
378
400
|
c = _client()
|
|
379
401
|
try:
|
|
380
402
|
sid = _resolve_scene(c, scene_path, scene_id, scene_script, assets)
|
|
@@ -386,7 +408,7 @@ def render_final(
|
|
|
386
408
|
frame_end = None # type: ignore[assignment] # 1 周ぶんは受付が決める
|
|
387
409
|
j = c.submit(sid, kind="final", frame_start=frame_start, frame_end=frame_end,
|
|
388
410
|
width=width, height=height, samples=samples, fps=fps, output=output,
|
|
389
|
-
camera=camera or None,
|
|
411
|
+
camera=camera or None, transparent=(True if transparent else None), notify_url=notify_url or None,
|
|
390
412
|
**_job_params(environment, environment_strength, environment_visible, blender, engine=engine), **extra)
|
|
391
413
|
except ClientError as exc:
|
|
392
414
|
block = _payment_block(exc) or _quota_block(exc)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: janction-render
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.2
|
|
4
4
|
Summary: Cloud GPU render farm for Blender, for AI agents: MCP server (remote + stdio) and CLI. Render Blender without a GPU from Claude, ChatGPT, Claude Code, Codex, Cursor.
|
|
5
5
|
Requires-Python: >=3.11
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -31,7 +31,8 @@ without a GPU, or when rendering locally is slow.
|
|
|
31
31
|
- `orbit=True` turns any scene or imported model into a turntable: an orbit camera circles it once (`orbit_frames`, default 24;
|
|
32
32
|
a preview shows 0/90/180/270 degrees, a final render without `frame_end` gives the whole turn as an MP4). Flat floors and
|
|
33
33
|
walls are ignored when framing; `orbit_target` (object name or `x,y,z`) and `orbit_distance` (multiplier) adjust the shot.
|
|
34
|
-
- While the GPU is lent to another workload, tools answer right away with the queued job and a
|
|
34
|
+
- While the GPU is lent to another workload, tools answer right away with the queued job and a wait estimate (how long it
|
|
35
|
+
has been out, how long it usually stays out, how much longer to expect; `eta.gate`) instead of waiting.
|
|
35
36
|
- While a job renders, `render_status` counts finished frames inside the running chunk, so the ETA updates every few seconds.
|
|
36
37
|
- In hosts that support MCP Apps (Claude web and desktop, among others), previews, progress and download links also appear
|
|
37
38
|
as an interactive panel in the chat: the image, a progress bar, "Open MP4", and preset buttons after an `environment="compare"` preview.
|
|
@@ -51,7 +52,8 @@ Free beta. Service page: `https://render.janction.jp` (`/v1/health`, `/llms.txt`
|
|
|
51
52
|
Guides: [render farm for agents](https://render.janction.jp/blender-render-farm) · [without a GPU](https://render.janction.jp/render-blender-without-gpu) ·
|
|
52
53
|
[Claude](https://render.janction.jp/claude-blender) · [ChatGPT](https://render.janction.jp/chatgpt-blender) · [Claude Code](https://render.janction.jp/claude-code-blender) ·
|
|
53
54
|
[Codex](https://render.janction.jp/codex-blender) · [bpy scripts](https://render.janction.jp/bpy-script-cloud-gpu) · [API](https://render.janction.jp/blender-render-api) ·
|
|
54
|
-
[comparison](https://render.janction.jp/blender-render-farm-api-comparison) ·
|
|
55
|
+
[comparison](https://render.janction.jp/blender-render-farm-api-comparison) · [Blender add-on](https://render.janction.jp/blender-addon) ·
|
|
56
|
+
[Maya / Houdini / Cinema 4D](https://render.janction.jp/maya-houdini-cinema4d) · 日本語は `/ja/`
|
|
55
57
|
|
|
56
58
|
## Connect (remote MCP, nothing to install)
|
|
57
59
|
|
|
@@ -114,7 +116,7 @@ Then, in Claude Code:
|
|
|
114
116
|
| `scene_info(scene_script | scene_url | scene_path | scene_id, assets?)` | cameras, frame range, fps, resolution, objects, lights, missing files. No render. |
|
|
115
117
|
| `render_preview(..., frames="1-24", environment?, blender?)` | up to 4 frames (720p budget) tiled with frame labels; returns the image inline |
|
|
116
118
|
| `render_estimate(scene_id, frame_start, frame_end, width, height, samples)` | GPU seconds, queue wait, "about N minutes", fits today's free quota? No GPU time used |
|
|
117
|
-
| `render_final(scene_id, frame_start, frame_end, width, height, samples, fps, output, environment?, blender?, engine?)` | frames (png / exr) or video (mp4 / webm / prores); returns job_id + estimate |
|
|
119
|
+
| `render_final(scene_id, frame_start, frame_end, width, height, samples, fps, output, environment?, blender?, engine?, transparent?, notify_url?)` | frames (png / exr) or video (mp4 / webm / prores / gif / webp); `transparent=True` keeps an alpha background (png / exr / webm / gif / webp); `notify_url` gets one JSON POST when the job finishes; returns job_id + estimate |
|
|
118
120
|
| `render_status(job_id)` | progress and ETA (`eta.human`); `render_download(job_id, only="mp4" / "frames" / "all")` files or links; `render_cancel(job_id)` |
|
|
119
121
|
| `billing()` | free-beta quota (used today, daily limit, reset time); later balance and top-up link |
|
|
120
122
|
| `render_info()` | workers online or gated (GPU lent to another workload), queue, expected wait, supported inputs, environment presets, Blender versions |
|
|
@@ -153,7 +155,7 @@ POST /v1/keys -> {api_key} (header X-A
|
|
|
153
155
|
POST /v1/files multipart "file" (.blend|.py|.glb|.fbx|.usd|.obj|...) -> {scene_id}
|
|
154
156
|
POST /v1/files/{id}/assets multipart "files" textures, glTF .bin ... GET /v1/files/lookup?sha256= reuse an upload
|
|
155
157
|
POST /v1/estimate {kind, frames|frame_start/frame_end, width, height, samples, scene_id?} -> seconds, wall_seconds, human, quota
|
|
156
|
-
POST /v1/jobs {scene_id, kind: info|preview|final, frames|frame_start/frame_end, width, height, samples, camera, fps, output (png|exr|mp4|webm|prores), engine (cycles|eevee),
|
|
158
|
+
POST /v1/jobs {scene_id, kind: info|preview|final, frames|frame_start/frame_end, width, height, samples, camera, fps, output (png|exr|mp4|webm|prores|gif|webp), transparent, notify_url (https), engine (cycles|eevee),
|
|
157
159
|
environment, environment_strength, environment_visible, blender, orbit, orbit_frames, orbit_elevation}
|
|
158
160
|
GET /v1/jobs/{id} status, progress, eta, artifacts[], cost, warnings, info DELETE /v1/jobs/{id} cancel
|
|
159
161
|
GET /v1/jobs/{id}/artifacts/{name} PNG / MP4
|
|
@@ -166,11 +168,24 @@ GET /llms.txt /llms-full.txt /ja/llms.txt /faq /terms /privacy /legal /s
|
|
|
166
168
|
During the free beta a `429 quota_exceeded` response carries `resets_at`; a `400 beta_limit` means the job is too big
|
|
167
169
|
(split it). Once paid plans start, a `402 payment_required` response carries `checkout_url`.
|
|
168
170
|
|
|
171
|
+
## Blender add-on and DCC tools (for people, not agents)
|
|
172
|
+
|
|
173
|
+
- **Blender extension** (`addons/blender/`, Blender 4.2+): a JANCTION Render panel under Properties → Render with Preview,
|
|
174
|
+
Estimate and Final. A copy of the open file and the textures it references with relative paths are uploaded; results land
|
|
175
|
+
next to the .blend. Install from the extension repository `https://render.janction.jp/extensions/index.json`
|
|
176
|
+
(Preferences → Get Extensions → Repositories → + → Add Remote Repository), or install the zip from
|
|
177
|
+
`https://render.janction.jp/extensions/janction_render-0.1.0.zip` (`python scripts/build_blender_addon.py` builds it
|
|
178
|
+
from this repository). Guide: https://render.janction.jp/blender-addon
|
|
179
|
+
- **Maya, Houdini, Cinema 4D** (`integrations/`): export to USD / FBX / Alembic, upload with textures, render with Cycles,
|
|
180
|
+
open the result; Preview, Final (MP4) and Turntable. Standard-library Python only; `jr_submit.py` is the shared client.
|
|
181
|
+
Guide: https://render.janction.jp/maya-houdini-cinema4d
|
|
182
|
+
|
|
169
183
|
## Self-hosting
|
|
170
184
|
|
|
171
185
|
The server (FastAPI + SQLite, with the remote MCP endpoint) and the worker (Blender in disposable Docker containers,
|
|
172
186
|
`--network none --cap-drop ALL`) live in the internal repository and are not part of this package yet. This repository
|
|
173
|
-
holds the client side: stdio MCP server, CLI, HTTP client, samples
|
|
187
|
+
holds the client side: stdio MCP server, CLI, HTTP client, samples, the Claude Code plugin, the Blender add-on and the
|
|
188
|
+
DCC tools.
|
|
174
189
|
|
|
175
190
|
## MCP registry
|
|
176
191
|
|
|
@@ -180,4 +195,5 @@ mcp-name: io.github.JasmyLab-JANCTION/janction-render
|
|
|
180
195
|
|
|
181
196
|
## License
|
|
182
197
|
|
|
183
|
-
MIT (see LICENSE).
|
|
198
|
+
MIT (see LICENSE) for the package, the MCP servers, the CLI and the DCC tools. The Blender extension under
|
|
199
|
+
`addons/blender/` is GPL-3.0-or-later, as Blender requires for add-ons. Operated by JasmyLab Inc.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "janction-render"
|
|
7
|
-
version = "0.4.
|
|
7
|
+
version = "0.4.2"
|
|
8
8
|
description = "Cloud GPU render farm for Blender, for AI agents: MCP server (remote + stdio) and CLI. Render Blender without a GPU from Claude, ChatGPT, Claude Code, Codex, Cursor."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{janction_render-0.4.0 → janction_render-0.4.2}/janction_render.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|