multiplane 0.3.8 → 0.3.10
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.
- package/README.en.md +15 -7
- package/README.md +15 -7
- package/package.json +3 -2
- package/skills/multiplane/SKILL.md +1 -1
- package/src/artifacts.mjs +14 -7
package/README.en.md
CHANGED
|
@@ -11,7 +11,7 @@ A local, headless HTML video renderer for AI agents. **A shot is an ordinary web
|
|
|
11
11
|
|
|
12
12
|
<img src="https://raw.githubusercontent.com/LBEILC/Multiplane/main/docs/images/hero.webp" width="720" alt="3D cards rendered by Multiplane, with depth of field and motion blur">
|
|
13
13
|
|
|
14
|
-
> Version `0.3.
|
|
14
|
+
> Version `0.3.8` (the latest version is on the [Releases page](https://github.com/LBEILC/Multiplane/releases)). The full test suite passes in CI on Windows, macOS and Linux; Windows has also been verified on a real machine. Interfaces may still change before 1.0.
|
|
15
15
|
|
|
16
16
|
The name comes from Disney's multiplane camera: flat artwork placed at different depths, photographed frame by frame with real depth of field. Here, this corresponds to layered web content, a 3D card layer, and accumulated depth of field.
|
|
17
17
|
|
|
@@ -133,7 +133,9 @@ For the full contract, patterns that break determinism, and 3D layer usage, see
|
|
|
133
133
|
|
|
134
134
|
Shot paths are relative to the resource root `--root` (the current directory by default). Each run has its own job directory, `out/jobs/<jobId>/`. Without `--out`, artifacts are written there (video, `stills/`, `verify/`), so runs do not overwrite each other. See `artifacts` in the result for the final paths. `--out` sets the output location. An existing target is rejected unless `--overwrite` is given. `render`, `stills`, and `verify` automatically run `lint` before starting and stop on errors. Use `--no-lint` to skip it. `npx multiplane <command> --help` lists all options for that command.
|
|
135
135
|
|
|
136
|
-
`render` encodes in segments of about 10 seconds and keeps each one on disk as soon as it is done. If a render stops part way (the process is killed, the machine crashes or loses power, the browser keeps crashing, or you stop it), `multiplane resume <job>` skips the segments already encoded, renders the rest and joins them without re-encoding; the frames are identical to an uninterrupted render. A resume keeps all of the original job's options. It is refused (`resume_unavailable
|
|
136
|
+
`render` encodes in segments of about 10 seconds and keeps each one on disk as soon as it is done. If a render stops part way (the process is killed, the machine crashes or loses power, the browser keeps crashing, or you stop it), `multiplane resume <job>` skips the segments already encoded, renders the rest and joins them without re-encoding; the frames are identical to an uninterrupted render. A resume keeps all of the original job's options. It is refused (`resume_unavailable`, with the reason) when a file the shot loaded or the audio file has changed, or the Multiplane, Chromium or FFmpeg version, the raster mode or the encoder differs, so a film is never joined from mismatched parts; a different GPU or driver only produces a warning (`resume_renderer_changed`). `multiplane status` reports whether a job can be resumed and how many frames are done. See section 6.1 of the protocol.
|
|
137
|
+
|
|
138
|
+
A stuck browser does not stall a render forever. If a worker holds frames but delivers none for `max(120 seconds, 10 × the slowest frame so far)`, its browser is closed and relaunched, the frame is rendered again from scratch (with the same pixels), and a `worker_stalled` warning is reported. Each frame is retried at most twice; a third stall ends the job with `browser_crashed`. Segments already encoded are kept, so the job can be resumed.
|
|
137
139
|
|
|
138
140
|
Common `render` options:
|
|
139
141
|
|
|
@@ -272,20 +274,26 @@ npm install three@0.180.0
|
|
|
272
274
|
|
|
273
275
|
<picture>
|
|
274
276
|
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/LBEILC/Multiplane/main/docs/images/app-jobs-en-dark.png">
|
|
275
|
-
<img src="https://raw.githubusercontent.com/LBEILC/Multiplane/main/docs/images/app-jobs-en-light.png" width="800" alt="The Jobs page of the Multiplane desktop app:
|
|
277
|
+
<img src="https://raw.githubusercontent.com/LBEILC/Multiplane/main/docs/images/app-jobs-en-light.png" width="800" alt="The Jobs page of the Multiplane desktop app: running, queued and resumable jobs on the left, and the Timeline tab of the selected job on the right, listing how long each phase took and the events">
|
|
276
278
|
</picture>
|
|
277
279
|
|
|
278
280
|
|
|
279
|
-
- **Jobs**: list render, stills, and check jobs across projects, show progress and preview frames in real time,
|
|
280
|
-
- **
|
|
281
|
+
- **Jobs**: list render, stills, and check jobs across projects, show progress and preview frames in real time, and stop running jobs. Opening a job shows four tabs:
|
|
282
|
+
- **Preview**: finished videos play in a frame-accurate player: step one frame at a time, jump between cuts, and read the exact frame number and timecode. Any frame opens in a viewer that zooms to actual pixels, and when a determinism check fails, the reference, actual and difference images can be compared side by side or by flickering between them.
|
|
283
|
+
- **Summary**: the output, whether it was verified, and the picture, post-processing, performance and environment at a glance.
|
|
284
|
+
- **Timeline**: how long each phase took, with the events and warnings along the way.
|
|
285
|
+
- **Options**: the settings the job actually used, in plain words, which can be copied as a command.
|
|
286
|
+
- **Resume**: a failed or stopped render that can continue shows **Resume** with the frames already done, and the new job links back to the original. When resuming is refused, the app explains why, for example which files changed. With hosting on, the app also takes over an agent's `resume` requests.
|
|
287
|
+
- **Tray popover**: on Windows and macOS, clicking the tray icon opens a small panel with running, queued and recently finished jobs. The tray icon and the taskbar button show render progress. Linux keeps the system menu.
|
|
288
|
+
- **Environment**: check whether the browser, GPU rasterization, FFmpeg, and other requirements are ready; on first use, **Install browser** here downloads Chromium. Install and update the Multiplane skill for Claude Code (`~/.claude/skills/`) and Codex (`~/.agents/skills/`), without directly overwriting user modifications.
|
|
281
289
|
- **Settings**: write the user config `config.json` described above.
|
|
282
290
|
- **Hosted renders** (off by default): when turned on in Settings, renders started by an agent are run by the app instead of the agent's session, so they keep going when the session ends. One hosted render runs at a time and the rest wait in a queue. The agent's command and output stay the same, and `multiplane wait <job>` picks a job up again after a session restarts. With hosting on, closing the window keeps the app in the system tray. See section 11 of the protocol.
|
|
283
|
-
- **Updates**: the app checks GitHub for a new release at startup and once a day (can be turned off). On Windows it downloads and installs the update in the app; on macOS and Linux it links to the download page.
|
|
291
|
+
- **Updates**: the app checks GitHub for a new release at startup and once a day (can be turned off). On Windows it downloads and installs the update in the app; on macOS and Linux it links to the download page. The About page lists what changed in each version since the one installed, in the interface language.
|
|
284
292
|
- The interface is in English and Simplified Chinese. It follows the system language and can be switched in Settings.
|
|
285
293
|
|
|
286
294
|
It communicates with the renderer only through the files and commands in [`docs/protocol.md`](https://github.com/LBEILC/Multiplane/blob/main/docs/protocol.md). It is not required for rendering: agents can render from the command line without it.
|
|
287
295
|
|
|
288
|
-
Download an installer from the [Releases page](https://github.com/LBEILC/Multiplane/releases). The installers bundle a renderer of the same version, so the app works without a separate Node.js install. That renderer is also available as a command: `multiplane.cmd` in the install directory on Windows, `Multiplane.app/Contents/Resources/bin/multiplane` on macOS, and `Multiplane-<version>-x86_64.AppImage --multiplane-cli` on Linux. The Environment page shows the exact path when `multiplane` is not on PATH. FFmpeg is not bundled (see above), and Chromium is downloaded on first use
|
|
296
|
+
Download an installer from the [Releases page](https://github.com/LBEILC/Multiplane/releases). The installers bundle a renderer of the same version, so the app works without a separate Node.js install. That renderer is also available as a command: `multiplane.cmd` in the install directory on Windows, `Multiplane.app/Contents/Resources/bin/multiplane` on macOS, and `Multiplane-<version>-x86_64.AppImage --multiplane-cli` on Linux. The Environment page shows the exact path when `multiplane` is not on PATH. FFmpeg is not bundled (see above; install one with libx264 support), and Chromium is downloaded on first use with **Install browser** on the Environment page.
|
|
289
297
|
|
|
290
298
|
| System | Package | First launch (the packages are not code-signed) |
|
|
291
299
|
|---|---|---|
|
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
<img src="https://raw.githubusercontent.com/LBEILC/Multiplane/main/docs/images/hero.webp" width="720" alt="Multiplane 渲染的三维卡片:景深虚化与运动模糊">
|
|
13
13
|
|
|
14
|
-
> 当前版本 `0.3.
|
|
14
|
+
> 当前版本 `0.3.8`(最新版本见 [Releases 页面](https://github.com/LBEILC/Multiplane/releases))。完整测试在 Windows、macOS、Linux 三个平台的 CI 上全部通过;Windows 另在真机上验证过。1.0 之前接口仍可能调整。
|
|
15
15
|
|
|
16
16
|
名字来自迪士尼的多层摄影台(multiplane camera):一层层平面画稿放在不同深度、逐帧拍摄、带真实景深。对应这里的多层网页画面、三维卡片层和累积景深。
|
|
17
17
|
|
|
@@ -133,7 +133,9 @@ Shot.define({
|
|
|
133
133
|
|
|
134
134
|
镜头路径相对资源根 `--root`(默认当前目录)。每次运行都有自己的作业目录 `out/jobs/<jobId>/`,不给 `--out` 时产物就写在里面(视频、`stills/`、`verify/`),多次运行互不覆盖;最终路径见结果里的 `artifacts`。`--out` 指定输出位置,目标已存在时会拒绝覆盖,加 `--overwrite` 才替换。`render`、`stills`、`verify` 启动前自动跑 `lint`,有 error 就停下,`--no-lint` 跳过。`npx multiplane <command> --help` 列出该命令的全部参数。
|
|
135
135
|
|
|
136
|
-
`render` 按约 10 秒一段编码,每段编完就落盘。渲染中途停下(进程被杀、死机、断电、浏览器反复崩溃、手动停止)后,`multiplane resume <job>`
|
|
136
|
+
`render` 按约 10 秒一段编码,每段编完就落盘。渲染中途停下(进程被杀、死机、断电、浏览器反复崩溃、手动停止)后,`multiplane resume <job>` 会跳过已经编好的段、只渲剩下的,最后不重新编码地拼成成片,画面与一次渲完的逐帧相同。续传沿用原作业的全部参数;镜头加载过的文件或音频文件改了,或 Multiplane、Chromium、FFmpeg 的版本、光栅模式、编码器变了,会拒绝续传(`resume_unavailable`,并说明是哪一项),以免拼出前后不一致的片子;只是显卡或驱动不同,则只给出警告(`resume_renderer_changed`)。`multiplane status` 会告诉你一个作业能不能续传、已经渲完多少帧。见协议第 6.1 节。
|
|
137
|
+
|
|
138
|
+
浏览器卡住时,渲染也不会一直挂着:某个进程拿着帧、却在 `max(120 秒, 此前最慢一帧耗时的 10 倍)` 内一帧都交不出来时,会关掉它的浏览器、重新启动,并把那一帧从头重渲(像素相同),同时报 `worker_stalled` 警告。每一帧最多重试两次,第三次再卡住,作业以 `browser_crashed` 结束;已经编好的段会保留,之后可以用 `resume` 接着渲。
|
|
137
139
|
|
|
138
140
|
`render` 的常用参数:
|
|
139
141
|
|
|
@@ -272,20 +274,26 @@ npm install three@0.180.0
|
|
|
272
274
|
|
|
273
275
|
<picture>
|
|
274
276
|
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/LBEILC/Multiplane/main/docs/images/app-jobs-zh-dark.png">
|
|
275
|
-
<img src="https://raw.githubusercontent.com/LBEILC/Multiplane/main/docs/images/app-jobs-zh-light.png" width="800" alt="Multiplane
|
|
277
|
+
<img src="https://raw.githubusercontent.com/LBEILC/Multiplane/main/docs/images/app-jobs-zh-light.png" width="800" alt="Multiplane 桌面软件的作业页:左边是进行中、排队中和可继续渲染的作业,右边是所选作业的“过程”标签,列出各阶段用时和事件">
|
|
276
278
|
</picture>
|
|
277
279
|
|
|
278
280
|
|
|
279
|
-
-
|
|
280
|
-
-
|
|
281
|
+
- **作业**:列出各项目里的渲染、抽帧、检查作业,实时显示进度和预览帧,可以停止进行中的作业。点开一个作业,详情分四个标签:
|
|
282
|
+
- **预览**:成片在逐帧播放器里播放,可以一帧一帧地走、在切点之间跳转,并显示准确的帧号和时间码;任意一帧都能单独打开,放大到实际像素。确定性检查不通过时,参考图、实际图和差异图可以并排看,也可以闪烁对比。
|
|
283
|
+
- **概览**:产物、成品是否核对过,以及画面、后期、性能、环境一目了然。
|
|
284
|
+
- **过程**:每个阶段用了多久,以及过程中的事件和警告。
|
|
285
|
+
- **参数**:用平白的话列出这次作业实际生效的参数,可以复制成命令。
|
|
286
|
+
- **继续渲染**:失败或被停止、又能接着渲的渲染,会显示“继续渲染”和已经完成的帧数;新作业会链回原作业。不能接着渲时(例如镜头用到的文件变了),软件会说明原因。开启托管后,软件也会接管 agent 发起的 `resume`。
|
|
287
|
+
- **托盘弹窗**:在 Windows 和 macOS 上点托盘图标,会打开一个小面板,列出进行中、排队中和最近完成的作业;托盘图标和任务栏按钮会显示渲染进度。Linux 上仍是系统菜单。
|
|
288
|
+
- **环境**:检查浏览器、GPU 光栅、FFmpeg 等是否就绪,首次使用时在这里点“安装浏览器”下载 Chromium;给 Claude Code(`~/.claude/skills/`)和 Codex(`~/.agents/skills/`)安装、更新 Multiplane 的 skill,自己改过的不会被直接覆盖。
|
|
281
289
|
- **设置**:写入上文的用户配置 `config.json`。
|
|
282
290
|
- **托管渲染**(默认关闭):在设置里开启后,agent 发起的渲染改由软件执行,不再挂在 agent 的会话上,会话结束也会照常做完。一次只执行一个托管渲染,其余排队。agent 的命令和输出不变;会话重启后用 `multiplane wait <job>` 接上之前的作业。开启托管后,关闭窗口时软件留在系统托盘。见协议第 11 节。
|
|
283
|
-
- **更新**:启动时和之后每天检查一次 GitHub 上的新版本(可以关闭)。Windows 上在软件里下载并安装;macOS 和 Linux
|
|
291
|
+
- **更新**:启动时和之后每天检查一次 GitHub 上的新版本(可以关闭)。Windows 上在软件里下载并安装;macOS 和 Linux 上打开下载页。“关于”页会按界面语言列出从已安装版本起每个版本的更新内容。
|
|
284
292
|
- 界面有英文和简体中文,默认跟随系统语言,也可以在设置里切换。
|
|
285
293
|
|
|
286
294
|
它只通过 [`docs/protocol.zh-CN.md`](https://github.com/LBEILC/Multiplane/blob/main/docs/protocol.zh-CN.md) 的文件和命令行与渲染器打交道,不是渲染的必需品:不装它,agent 照样可以用命令行渲染。
|
|
287
295
|
|
|
288
|
-
从 [Releases 页面](https://github.com/LBEILC/Multiplane/releases) 下载安装包。安装包里带一份同版本的渲染器,不需要另装 Node.js。这份渲染器也可以当命令用:Windows 为安装目录下的 `multiplane.cmd`,macOS 为 `Multiplane.app/Contents/Resources/bin/multiplane`,Linux 为 `Multiplane-<版本>-x86_64.AppImage --multiplane-cli`。PATH 里找不到 `multiplane` 时,环境页会显示完整路径。FFmpeg
|
|
296
|
+
从 [Releases 页面](https://github.com/LBEILC/Multiplane/releases) 下载安装包。安装包里带一份同版本的渲染器,不需要另装 Node.js。这份渲染器也可以当命令用:Windows 为安装目录下的 `multiplane.cmd`,macOS 为 `Multiplane.app/Contents/Resources/bin/multiplane`,Linux 为 `Multiplane-<版本>-x86_64.AppImage --multiplane-cli`。PATH 里找不到 `multiplane` 时,环境页会显示完整路径。FFmpeg 不随包提供(见上文,需要自己安装一个支持 libx264 的),Chromium 在环境页首次使用时点“安装浏览器”下载。
|
|
289
297
|
|
|
290
298
|
| 系统 | 安装包 | 首次打开(安装包没有代码签名) |
|
|
291
299
|
|---|---|---|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "multiplane",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.10",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"publishConfig": {
|
|
@@ -40,7 +40,8 @@
|
|
|
40
40
|
"export:public": "node tools/export-public.mjs",
|
|
41
41
|
"release:check": "node tools/release-check.mjs",
|
|
42
42
|
"bench": "node tools/bench/run.mjs",
|
|
43
|
-
"test:full": "node --import ./tests/test-home.mjs tools/test-suite.mjs --full"
|
|
43
|
+
"test:full": "node --import ./tests/test-home.mjs tools/test-suite.mjs --full",
|
|
44
|
+
"release": "node tools/release.mjs"
|
|
44
45
|
},
|
|
45
46
|
"dependencies": {
|
|
46
47
|
"acorn": "8.15.0",
|
|
@@ -211,7 +211,7 @@ With `--json`, stdout contains one JSON event per line. **The last line is alway
|
|
|
211
211
|
|
|
212
212
|
## Long renders
|
|
213
213
|
|
|
214
|
-
Rendering may take a long time. Each run creates a job directory, `out/jobs/<jobId>/` (`jobId` appears in both the `start` event and the `result`). Read `status.json` for the latest progress snapshot and `events.jsonl` for the full event stream. To stop a job, run `multiplane cancel <jobId>` or create a file named `stop` in its job directory.
|
|
214
|
+
Rendering may take a long time, often longer than the timeout of your shell or command tool. When the tool lets you, give `render` a timeout long enough for the whole render or run it in the background; if the command is cut off, the job's process usually dies with it, so do not start the same render again: check it with `multiplane status <jobId> --json` and continue it with `multiplane resume` (see below). Each run creates a job directory, `out/jobs/<jobId>/` (`jobId` appears in both the `start` event and the `result`). Read `status.json` for the latest progress snapshot and `events.jsonl` for the full event stream. To stop a job, run `multiplane cancel <jobId>` or create a file named `stop` in its job directory.
|
|
215
215
|
|
|
216
216
|
If the user turned on hosting in the desktop app, the app runs the render and it keeps going after your session ends. Nothing changes in how you call the command; stderr says the job was handed over, and `status.json` may show `queued` while another hosted job runs. When a session resumes and you started a job earlier but never saw its `result`, run `multiplane wait <jobId> --json` to get its events and exit code instead of starting it again. Use `--no-hosted` only when the user asks for a render that should not go through the app.
|
|
217
217
|
|
package/src/artifacts.mjs
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { copyFile, rm, writeFile, access, rename, mkdtemp, mkdir } from 'node:fs/promises';
|
|
1
|
+
import { link, rm, writeFile, access, rename, mkdtemp, mkdir } from 'node:fs/promises';
|
|
3
2
|
import path from 'node:path';
|
|
4
3
|
import { MultiplaneError } from './errors.mjs';
|
|
5
4
|
|
|
@@ -16,11 +15,19 @@ export async function writeArtifact(file, bytes) {
|
|
|
16
15
|
try { await writeFile(file, bytes, { flag: 'wx' }); }
|
|
17
16
|
catch (error) { outputError(error, file); }
|
|
18
17
|
}
|
|
19
|
-
export async function publishVideo(temporary, file, overwrite = false) {
|
|
20
|
-
if (overwrite) { await
|
|
21
|
-
try { await
|
|
22
|
-
catch (error) {
|
|
23
|
-
|
|
18
|
+
export async function publishVideo(temporary, file, overwrite = false, { linkFile = link, move = rename, remove = rm } = {}) {
|
|
19
|
+
if (overwrite) { await move(temporary, file); return; }
|
|
20
|
+
try { await linkFile(temporary, file); }
|
|
21
|
+
catch (error) {
|
|
22
|
+
if (!['ENOTSUP', 'EOPNOTSUPP', 'ENOSYS', 'EPERM'].includes(error.code)) outputError(error, file);
|
|
23
|
+
// The temporary video is in the output directory, so rename publishes it whole.
|
|
24
|
+
// Accept the short race between checking the target and renaming.
|
|
25
|
+
await requireNewOutput(file);
|
|
26
|
+
try { await move(temporary, file); }
|
|
27
|
+
catch (moveError) { outputError(moveError, file); }
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
await remove(temporary);
|
|
24
31
|
}
|
|
25
32
|
|
|
26
33
|
// Build a replacement directory in isolation; publish only after the whole command succeeds.
|