multiplane 0.0.0-stage → 0.3.1
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/LICENSE +202 -0
- package/README.en.md +324 -0
- package/README.md +323 -2
- package/THIRD_PARTY_NOTICES.md +30 -0
- package/bin/multiplane +98 -0
- package/examples/alpha.html +18 -0
- package/examples/animation.html +17 -0
- package/examples/assets/OFL.txt +93 -0
- package/examples/assets/Roboto-Variable.ttf +0 -0
- package/examples/assets/card.svg +6 -0
- package/examples/assets/readme-card-0.svg +1 -0
- package/examples/assets/readme-card-1.svg +1 -0
- package/examples/assets/readme-card-2.svg +1 -0
- package/examples/assets/readme-detail.svg +1 -0
- package/examples/readme-cards.html +23 -0
- package/examples/readme-cut.html +13 -0
- package/examples/readme-depth.html +15 -0
- package/examples/readme-wheel.html +14 -0
- package/examples/three-cards.html +17 -0
- package/examples/typography.html +17 -0
- package/licenses/GPL-3.0.txt +232 -0
- package/licenses/LGPL-3.0.txt +304 -0
- package/licenses/acorn-LICENSE +21 -0
- package/licenses/colour-LICENSE.md +82 -0
- package/licenses/detect-libc-LICENSE +201 -0
- package/licenses/entities-LICENSE +11 -0
- package/licenses/nanoid-LICENSE +20 -0
- package/licenses/native/README.ijg +258 -0
- package/licenses/native/aom-LICENSE +27 -0
- package/licenses/native/aom-PATENTS +108 -0
- package/licenses/native/archive-COPYING +65 -0
- package/licenses/native/cairo-COPYING +33 -0
- package/licenses/native/cairo-COPYING-MPL-1.1 +470 -0
- package/licenses/native/cgif-LICENSE +21 -0
- package/licenses/native/exif-COPYING +504 -0
- package/licenses/native/expat-COPYING +21 -0
- package/licenses/native/ffi-LICENSE +21 -0
- package/licenses/native/fontconfig-COPYING +200 -0
- package/licenses/native/freetype-FTL.TXT +169 -0
- package/licenses/native/fribidi-COPYING +501 -0
- package/licenses/native/glib-COPYING +175 -0
- package/licenses/native/harfbuzz-COPYING +42 -0
- package/licenses/native/heif-COPYING +871 -0
- package/licenses/native/highway-LICENSE +371 -0
- package/licenses/native/imagequant-COPYRIGHT +36 -0
- package/licenses/native/lcms-COPYING +22 -0
- package/licenses/native/mozjpeg-LICENSE.md +135 -0
- package/licenses/native/nsgif-COPYING +21 -0
- package/licenses/native/pango-COPYING +482 -0
- package/licenses/native/pixman-COPYING +42 -0
- package/licenses/native/png-LICENSE +134 -0
- package/licenses/native/proxy-libintl-COPYING +482 -0
- package/licenses/native/rsvg-COPYING.LIB +502 -0
- package/licenses/native/sources.json +240 -0
- package/licenses/native/tiff-LICENSE.md +49 -0
- package/licenses/native/uhdr-LICENSE +230 -0
- package/licenses/native/vips-COPYING +502 -0
- package/licenses/native/webp-COPYING +30 -0
- package/licenses/native/webp-PATENTS +23 -0
- package/licenses/native/xml2-Copyright +24 -0
- package/licenses/native/zlib-ng-LICENSE.md +19 -0
- package/licenses/parse5-LICENSE +19 -0
- package/licenses/picocolors-LICENSE +15 -0
- package/licenses/playwright-LICENSE +202 -0
- package/licenses/playwright-NOTICE +5 -0
- package/licenses/playwright-ThirdPartyNotices.txt +14 -0
- package/licenses/playwright-core-ThirdPartyNotices.txt +13 -0
- package/licenses/postcss-LICENSE +20 -0
- package/licenses/postcss-value-parser-LICENSE +22 -0
- package/licenses/semver-LICENSE +15 -0
- package/licenses/sharp-LICENSE +191 -0
- package/licenses/sharp-win32-x64-LICENSE +191 -0
- package/licenses/sharp-win32-x64-NOTICES.md +59 -0
- package/licenses/source-map-js-LICENSE +28 -0
- package/licenses/three-LICENSE +21 -0
- package/package.json +92 -6
- package/skills/multiplane/SKILL.md +213 -0
- package/src/alpha.mjs +69 -0
- package/src/artifacts.mjs +61 -0
- package/src/benchmark.mjs +140 -0
- package/src/browser-recovery.mjs +26 -0
- package/src/capture.mjs +232 -0
- package/src/config.mjs +79 -0
- package/src/doctor.mjs +56 -0
- package/src/draft.mjs +30 -0
- package/src/encoder.mjs +16 -0
- package/src/environment.mjs +56 -0
- package/src/errors.mjs +51 -0
- package/src/events.mjs +252 -0
- package/src/ffmpeg.mjs +32 -0
- package/src/format.mjs +27 -0
- package/src/frame-rate.mjs +28 -0
- package/src/home-migration.mjs +54 -0
- package/src/hosted.mjs +134 -0
- package/src/index.mjs +14 -0
- package/src/inspect.mjs +20 -0
- package/src/jobs.mjs +51 -0
- package/src/lint.mjs +248 -0
- package/src/output-alpha.mjs +36 -0
- package/src/output-check.mjs +110 -0
- package/src/pixel-comparison.mjs +43 -0
- package/src/platform.mjs +114 -0
- package/src/png-native.mjs +12 -0
- package/src/png.mjs +74 -0
- package/src/post.mjs +433 -0
- package/src/preview.mjs +23 -0
- package/src/process-identity.mjs +17 -0
- package/src/process.mjs +9 -0
- package/src/render-pool.mjs +93 -0
- package/src/render-worker.mjs +59 -0
- package/src/render.mjs +157 -0
- package/src/resource-path.mjs +29 -0
- package/src/resources.mjs +27 -0
- package/src/runtime/camera.js +37 -0
- package/src/runtime/shot.css +9 -0
- package/src/runtime/shot.js +71 -0
- package/src/serve.mjs +23 -0
- package/src/server.mjs +93 -0
- package/src/setup.mjs +51 -0
- package/src/skills.mjs +128 -0
- package/src/static-reuse.mjs +267 -0
- package/src/stills.mjs +81 -0
- package/src/three/index.js +348 -0
- package/src/user-home.mjs +105 -0
- package/src/verify.mjs +161 -0
- package/src/video-pipe.mjs +6 -0
- package/src/workers.mjs +62 -0
- package/tools/bench/shots/canvas-2d.html +1 -0
- package/tools/bench/shots/dom-light.html +1 -0
- package/tools/bench/shots/scene.js +45 -0
- package/tools/bench/shots/webgl.html +1 -0
- package/tools/install-browser.mjs +18 -0
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction, and
|
|
10
|
+
distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by the copyright
|
|
13
|
+
owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all other entities
|
|
16
|
+
that control, are controlled by, or are under common control with that entity.
|
|
17
|
+
For the purposes of this definition, "control" means (i) the power, direct or
|
|
18
|
+
indirect, to cause the direction or management of such entity, whether by
|
|
19
|
+
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
20
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
21
|
+
|
|
22
|
+
"You" (or "Your") shall mean an individual or Legal Entity exercising
|
|
23
|
+
permissions granted by this License.
|
|
24
|
+
|
|
25
|
+
"Source" form shall mean the preferred form for making modifications, including
|
|
26
|
+
but not limited to software source code, documentation source, and configuration
|
|
27
|
+
files.
|
|
28
|
+
|
|
29
|
+
"Object" form shall mean any form resulting from mechanical transformation or
|
|
30
|
+
translation of a Source form, including but not limited to compiled object code,
|
|
31
|
+
generated documentation, and conversions to other media types.
|
|
32
|
+
|
|
33
|
+
"Work" shall mean the work of authorship, whether in Source or Object form, made
|
|
34
|
+
available under the License, as indicated by a copyright notice that is included
|
|
35
|
+
in or attached to the work (an example is provided in the Appendix below).
|
|
36
|
+
|
|
37
|
+
"Derivative Works" shall mean any work, whether in Source or Object form, that
|
|
38
|
+
is based on (or derived from) the Work and for which the editorial revisions,
|
|
39
|
+
annotations, elaborations, or other modifications represent, as a whole, an
|
|
40
|
+
original work of authorship. For the purposes of this License, Derivative Works
|
|
41
|
+
shall not include works that remain separable from, or merely link (or bind by
|
|
42
|
+
name) to the interfaces of, the Work and Derivative Works thereof.
|
|
43
|
+
|
|
44
|
+
"Contribution" shall mean any work of authorship, including the original version
|
|
45
|
+
of the Work and any modifications or additions to that Work or Derivative Works
|
|
46
|
+
thereof, that is intentionally submitted to Licensor for inclusion in the Work
|
|
47
|
+
by the copyright owner or by an individual or Legal Entity authorized to submit
|
|
48
|
+
on behalf of the copyright owner. For the purposes of this definition,
|
|
49
|
+
"submitted" means any form of electronic, verbal, or written communication sent
|
|
50
|
+
to the Licensor or its representatives, including but not limited to
|
|
51
|
+
communication on electronic mailing lists, source code control systems, and
|
|
52
|
+
issue tracking systems that are managed by, or on behalf of, the Licensor for
|
|
53
|
+
the purpose of discussing and improving the Work, but excluding communication
|
|
54
|
+
that is conspicuously marked or otherwise designated in writing by the copyright
|
|
55
|
+
owner as "Not a Contribution."
|
|
56
|
+
|
|
57
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
|
|
58
|
+
of whom a Contribution has been received by Licensor and subsequently
|
|
59
|
+
incorporated within the Work.
|
|
60
|
+
|
|
61
|
+
2. Grant of Copyright License.
|
|
62
|
+
|
|
63
|
+
Subject to the terms and conditions of this License, each Contributor hereby
|
|
64
|
+
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
|
|
65
|
+
irrevocable copyright license to reproduce, prepare Derivative Works of,
|
|
66
|
+
publicly display, publicly perform, sublicense, and distribute the Work and such
|
|
67
|
+
Derivative Works in Source or Object form.
|
|
68
|
+
|
|
69
|
+
3. Grant of Patent License.
|
|
70
|
+
|
|
71
|
+
Subject to the terms and conditions of this License, each Contributor hereby
|
|
72
|
+
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
|
|
73
|
+
irrevocable (except as stated in this section) patent license to make, have
|
|
74
|
+
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
|
|
75
|
+
such license applies only to those patent claims licensable by such Contributor
|
|
76
|
+
that are necessarily infringed by their Contribution(s) alone or by combination
|
|
77
|
+
of their Contribution(s) with the Work to which such Contribution(s) was
|
|
78
|
+
submitted. If You institute patent litigation against any entity (including a
|
|
79
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
|
|
80
|
+
Contribution incorporated within the Work constitutes direct or contributory
|
|
81
|
+
patent infringement, then any patent licenses granted to You under this License
|
|
82
|
+
for that Work shall terminate as of the date such litigation is filed.
|
|
83
|
+
|
|
84
|
+
4. Redistribution.
|
|
85
|
+
|
|
86
|
+
You may reproduce and distribute copies of the Work or Derivative Works thereof
|
|
87
|
+
in any medium, with or without modifications, and in Source or Object form,
|
|
88
|
+
provided that You meet the following conditions:
|
|
89
|
+
|
|
90
|
+
You must give any other recipients of the Work or Derivative Works a copy of
|
|
91
|
+
this License; and
|
|
92
|
+
You must cause any modified files to carry prominent notices stating that You
|
|
93
|
+
changed the files; and
|
|
94
|
+
You must retain, in the Source form of any Derivative Works that You distribute,
|
|
95
|
+
all copyright, patent, trademark, and attribution notices from the Source form
|
|
96
|
+
of the Work, excluding those notices that do not pertain to any part of the
|
|
97
|
+
Derivative Works; and
|
|
98
|
+
If the Work includes a "NOTICE" text file as part of its distribution, then any
|
|
99
|
+
Derivative Works that You distribute must include a readable copy of the
|
|
100
|
+
attribution notices contained within such NOTICE file, excluding those notices
|
|
101
|
+
that do not pertain to any part of the Derivative Works, in at least one of the
|
|
102
|
+
following places: within a NOTICE text file distributed as part of the
|
|
103
|
+
Derivative Works; within the Source form or documentation, if provided along
|
|
104
|
+
with the Derivative Works; or, within a display generated by the Derivative
|
|
105
|
+
Works, if and wherever such third-party notices normally appear. The contents of
|
|
106
|
+
the NOTICE file are for informational purposes only and do not modify the
|
|
107
|
+
License. You may add Your own attribution notices within Derivative Works that
|
|
108
|
+
You distribute, alongside or as an addendum to the NOTICE text from the Work,
|
|
109
|
+
provided that such additional attribution notices cannot be construed as
|
|
110
|
+
modifying the License.
|
|
111
|
+
You may add Your own copyright statement to Your modifications and may provide
|
|
112
|
+
additional or different license terms and conditions for use, reproduction, or
|
|
113
|
+
distribution of Your modifications, or for any such Derivative Works as a whole,
|
|
114
|
+
provided Your use, reproduction, and distribution of the Work otherwise complies
|
|
115
|
+
with the conditions stated in this License.
|
|
116
|
+
|
|
117
|
+
5. Submission of Contributions.
|
|
118
|
+
|
|
119
|
+
Unless You explicitly state otherwise, any Contribution intentionally submitted
|
|
120
|
+
for inclusion in the Work by You to the Licensor shall be under the terms and
|
|
121
|
+
conditions of this License, without any additional terms or conditions.
|
|
122
|
+
Notwithstanding the above, nothing herein shall supersede or modify the terms of
|
|
123
|
+
any separate license agreement you may have executed with Licensor regarding
|
|
124
|
+
such Contributions.
|
|
125
|
+
|
|
126
|
+
6. Trademarks.
|
|
127
|
+
|
|
128
|
+
This License does not grant permission to use the trade names, trademarks,
|
|
129
|
+
service marks, or product names of the Licensor, except as required for
|
|
130
|
+
reasonable and customary use in describing the origin of the Work and
|
|
131
|
+
reproducing the content of the NOTICE file.
|
|
132
|
+
|
|
133
|
+
7. Disclaimer of Warranty.
|
|
134
|
+
|
|
135
|
+
Unless required by applicable law or agreed to in writing, Licensor provides the
|
|
136
|
+
Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
137
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
|
|
138
|
+
including, without limitation, any warranties or conditions of TITLE,
|
|
139
|
+
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
|
|
140
|
+
solely responsible for determining the appropriateness of using or
|
|
141
|
+
redistributing the Work and assume any risks associated with Your exercise of
|
|
142
|
+
permissions under this License.
|
|
143
|
+
|
|
144
|
+
8. Limitation of Liability.
|
|
145
|
+
|
|
146
|
+
In no event and under no legal theory, whether in tort (including negligence),
|
|
147
|
+
contract, or otherwise, unless required by applicable law (such as deliberate
|
|
148
|
+
and grossly negligent acts) or agreed to in writing, shall any Contributor be
|
|
149
|
+
liable to You for damages, including any direct, indirect, special, incidental,
|
|
150
|
+
or consequential damages of any character arising as a result of this License or
|
|
151
|
+
out of the use or inability to use the Work (including but not limited to
|
|
152
|
+
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
|
|
153
|
+
any and all other commercial damages or losses), even if such Contributor has
|
|
154
|
+
been advised of the possibility of such damages.
|
|
155
|
+
|
|
156
|
+
9. Accepting Warranty or Additional Liability.
|
|
157
|
+
|
|
158
|
+
While redistributing the Work or Derivative Works thereof, You may choose to
|
|
159
|
+
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
|
|
160
|
+
other liability obligations and/or rights consistent with this License. However,
|
|
161
|
+
in accepting such obligations, You may act only on Your own behalf and on Your
|
|
162
|
+
sole responsibility, not on behalf of any other Contributor, and only if You
|
|
163
|
+
agree to indemnify, defend, and hold each Contributor harmless for any liability
|
|
164
|
+
incurred by, or claims asserted against, such Contributor by reason of your
|
|
165
|
+
accepting any such warranty or additional liability.
|
|
166
|
+
|
|
167
|
+
END OF TERMS AND CONDITIONS
|
|
168
|
+
|
|
169
|
+
APPENDIX: How to apply the Apache License to your work
|
|
170
|
+
|
|
171
|
+
To apply the Apache License to your work, attach the following boilerplate
|
|
172
|
+
notice, with the fields enclosed by brackets "[]" replaced with your own
|
|
173
|
+
identifying information. (Don't include the brackets!) The text should be
|
|
174
|
+
enclosed in the appropriate comment syntax for the file format. We also
|
|
175
|
+
recommend that a file or class name and description of purpose be included on
|
|
176
|
+
the same "printed page" as the copyright notice for easier identification within
|
|
177
|
+
third-party archives.
|
|
178
|
+
|
|
179
|
+
Copyright [yyyy] [name of copyright owner]
|
|
180
|
+
|
|
181
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
182
|
+
you may not use this file except in compliance with the License.
|
|
183
|
+
You may obtain a copy of the License at
|
|
184
|
+
|
|
185
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
186
|
+
|
|
187
|
+
Unless required by applicable law or agreed to in writing, software
|
|
188
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
189
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
190
|
+
See the License for the specific language governing permissions and
|
|
191
|
+
limitations under the License.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# `@img/sharp-win32-x64`
|
|
2
|
+
|
|
3
|
+
Prebuilt sharp for use with Windows x64.
|
|
4
|
+
|
|
5
|
+
## Licensing
|
|
6
|
+
|
|
7
|
+
Copyright 2013 Lovell Fuller and others.
|
|
8
|
+
|
|
9
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
10
|
+
you may not use this file except in compliance with the License.
|
|
11
|
+
You may obtain a copy of the License at
|
|
12
|
+
[https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)
|
|
13
|
+
|
|
14
|
+
Unless required by applicable law or agreed to in writing, software
|
|
15
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
16
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
17
|
+
See the License for the specific language governing permissions and
|
|
18
|
+
limitations under the License.
|
|
19
|
+
|
|
20
|
+
This software contains third-party libraries
|
|
21
|
+
used under the terms of the following licenses:
|
|
22
|
+
|
|
23
|
+
| Library | Used under the terms of |
|
|
24
|
+
|---------------|-----------------------------------------------------------------------------------------------------------|
|
|
25
|
+
| aom | BSD 2-Clause + [Alliance for Open Media Patent License 1.0](https://aomedia.org/license/patent-license/) |
|
|
26
|
+
| cairo | Mozilla Public License 1.1 |
|
|
27
|
+
| cgif | MIT License |
|
|
28
|
+
| expat | MIT License |
|
|
29
|
+
| fontconfig | [fontconfig License](https://gitlab.freedesktop.org/fontconfig/fontconfig/blob/main/COPYING) (BSD-like) |
|
|
30
|
+
| freetype | [freetype License](https://git.savannah.gnu.org/cgit/freetype/freetype2.git/tree/docs/FTL.TXT) (BSD-like) |
|
|
31
|
+
| fribidi | LGPLv3 |
|
|
32
|
+
| glib | LGPLv3 |
|
|
33
|
+
| harfbuzz | MIT License |
|
|
34
|
+
| highway | BSD 3-Clause |
|
|
35
|
+
| lcms | MIT License |
|
|
36
|
+
| libarchive | BSD 2-Clause |
|
|
37
|
+
| libexif | LGPLv3 |
|
|
38
|
+
| libffi | MIT License |
|
|
39
|
+
| libheif | LGPLv3 |
|
|
40
|
+
| libimagequant | [BSD 2-Clause](https://github.com/lovell/libimagequant/blob/main/COPYRIGHT) |
|
|
41
|
+
| libnsgif | MIT License |
|
|
42
|
+
| libpng | [libpng License](https://github.com/pnggroup/libpng/blob/master/LICENSE) |
|
|
43
|
+
| librsvg | LGPLv3 |
|
|
44
|
+
| libtiff | [libtiff License](https://gitlab.com/libtiff/libtiff/blob/master/LICENSE.md) (BSD-like) |
|
|
45
|
+
| libultrahdr | MIT License |
|
|
46
|
+
| libvips | LGPLv3 |
|
|
47
|
+
| libwebp | New BSD License |
|
|
48
|
+
| libxml2 | MIT License |
|
|
49
|
+
| mozjpeg | [zlib License, IJG License, BSD 3-Clause](https://github.com/mozilla/mozjpeg/blob/master/LICENSE.md) |
|
|
50
|
+
| pango | LGPLv3 |
|
|
51
|
+
| pixman | MIT License |
|
|
52
|
+
| proxy-libintl | LGPLv3 |
|
|
53
|
+
| zlib-ng | [zlib License](https://github.com/zlib-ng/zlib-ng/blob/develop/LICENSE.md) |
|
|
54
|
+
|
|
55
|
+
Use of libraries under the terms of the LGPLv3 is via the
|
|
56
|
+
"any later version" clause of the LGPLv2 or LGPLv2.1.
|
|
57
|
+
|
|
58
|
+
Please report any errors or omissions via
|
|
59
|
+
https://github.com/lovell/sharp-libvips/issues/new
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
|
|
2
|
+
Copyright (c) 2009-2011, Mozilla Foundation and contributors
|
|
3
|
+
All rights reserved.
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
* Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
* Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
* Neither the names of the Mozilla Foundation nor the names of project
|
|
16
|
+
contributors may be used to endorse or promote products derived from this
|
|
17
|
+
software without specific prior written permission.
|
|
18
|
+
|
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
20
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
21
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
22
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
23
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
24
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
25
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
26
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
27
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License
|
|
2
|
+
|
|
3
|
+
Copyright © 2010-2025 three.js authors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
package/package.json
CHANGED
|
@@ -1,6 +1,92 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "multiplane",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "multiplane",
|
|
3
|
+
"version": "0.3.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"publishConfig": {
|
|
7
|
+
"registry": "https://registry.npmjs.org/",
|
|
8
|
+
"access": "public"
|
|
9
|
+
},
|
|
10
|
+
"engines": {
|
|
11
|
+
"node": ">=24"
|
|
12
|
+
},
|
|
13
|
+
"exports": {
|
|
14
|
+
".": "./src/index.mjs",
|
|
15
|
+
"./three": "./src/three/index.js",
|
|
16
|
+
"./runtime/*": "./src/runtime/*"
|
|
17
|
+
},
|
|
18
|
+
"bin": {
|
|
19
|
+
"multiplane": "bin/multiplane"
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"src/",
|
|
23
|
+
"bin/",
|
|
24
|
+
"examples/",
|
|
25
|
+
"skills/",
|
|
26
|
+
"tools/install-browser.mjs",
|
|
27
|
+
"tools/bench/shots/dom-light.html",
|
|
28
|
+
"tools/bench/shots/canvas-2d.html",
|
|
29
|
+
"tools/bench/shots/webgl.html",
|
|
30
|
+
"tools/bench/shots/scene.js",
|
|
31
|
+
"LICENSE",
|
|
32
|
+
"THIRD_PARTY_NOTICES.md",
|
|
33
|
+
"licenses/",
|
|
34
|
+
"README.md",
|
|
35
|
+
"README.en.md"
|
|
36
|
+
],
|
|
37
|
+
"scripts": {
|
|
38
|
+
"postinstall": "node tools/install-browser.mjs",
|
|
39
|
+
"test": "node --import ./tests/test-home.mjs tools/test-suite.mjs",
|
|
40
|
+
"export:public": "node tools/export-public.mjs",
|
|
41
|
+
"release:check": "node tools/release-check.mjs",
|
|
42
|
+
"bench": "node tools/bench/run.mjs",
|
|
43
|
+
"test:full": "node --import ./tests/test-home.mjs tools/test-suite.mjs --full"
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"acorn": "8.15.0",
|
|
47
|
+
"parse5": "7.3.0",
|
|
48
|
+
"playwright": "1.63.0",
|
|
49
|
+
"postcss": "8.5.28",
|
|
50
|
+
"postcss-value-parser": "4.2.0",
|
|
51
|
+
"sharp": "0.35.5"
|
|
52
|
+
},
|
|
53
|
+
"peerDependencies": {
|
|
54
|
+
"three": "0.180.0"
|
|
55
|
+
},
|
|
56
|
+
"peerDependenciesMeta": {
|
|
57
|
+
"three": {
|
|
58
|
+
"optional": true
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"devDependencies": {
|
|
62
|
+
"three": "0.180.0"
|
|
63
|
+
},
|
|
64
|
+
"overrides": {
|
|
65
|
+
"postcss": {
|
|
66
|
+
"nanoid": "3.3.19"
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
"description": "Local headless HTML-to-video renderer for AI agents: shots are plain web pages driven by render(t), with determinism checks, cut-aware motion blur and a 3D layer with accumulated depth of field.",
|
|
70
|
+
"keywords": [
|
|
71
|
+
"video",
|
|
72
|
+
"renderer",
|
|
73
|
+
"html",
|
|
74
|
+
"headless",
|
|
75
|
+
"chromium",
|
|
76
|
+
"playwright",
|
|
77
|
+
"ffmpeg",
|
|
78
|
+
"ai-agent",
|
|
79
|
+
"deterministic",
|
|
80
|
+
"motion-blur",
|
|
81
|
+
"depth-of-field",
|
|
82
|
+
"three.js"
|
|
83
|
+
],
|
|
84
|
+
"repository": {
|
|
85
|
+
"type": "git",
|
|
86
|
+
"url": "git+https://github.com/LBEILC/Multiplane.git"
|
|
87
|
+
},
|
|
88
|
+
"homepage": "https://github.com/LBEILC/Multiplane#readme",
|
|
89
|
+
"bugs": {
|
|
90
|
+
"url": "https://github.com/LBEILC/Multiplane/issues"
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: multiplane
|
|
3
|
+
description: 'Use Multiplane to render HTML shots to video: write shot pages that follow the contract (`#stage` + `render(t)`), capture stills for inspection, run determinism checks, render MP4, and read machine-readable results. Use when asked to "make a video shot from a web page", "render HTML to video", "check whether a shot is deterministic", or "render / stills / verify with Multiplane". This skill covers usage and determinism constraints only, not visual design.'
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Multiplane
|
|
7
|
+
|
|
8
|
+
Multiplane is a local headless renderer: a shot is an ordinary HTML page whose image depends only on time `t`. Multiplane captures frames with headless Chromium, applies post-processing such as supersampling, motion blur, and film grain, and encodes video with FFmpeg.
|
|
9
|
+
|
|
10
|
+
Your job has two parts: **write a page that follows the contract**, then **check and render it with the CLI**.
|
|
11
|
+
|
|
12
|
+
## Workflow
|
|
13
|
+
|
|
14
|
+
1. Write the shot page (see "Shot contract" below).
|
|
15
|
+
2. Run `multiplane lint shot.html --json`: it runs without a browser in under a second and flags patterns that break determinism or the contract, with line and column locations. Fix errors first.
|
|
16
|
+
3. Run `multiplane stills shot.html --at 0,1,2.5 --json`: capture a few stills to inspect the images.
|
|
17
|
+
4. Run `multiplane verify shot.html --json`: run a determinism check. **Do not render if it fails** (`ok: false`, code `nondeterministic_output`); fix the issues reported by `finding` first. A `gpu_raster_jitter` warning with `ok: true` is not a failure: GPU rasterization made a few scattered pixels differ by a level or two, which is invisible and not caused by the shot. Render as usual and mention it only if the user asks about determinism.
|
|
18
|
+
5. Run `multiplane render shot.html --json`: produce the video.
|
|
19
|
+
|
|
20
|
+
`stills`, `verify`, and `render` automatically run lint before starting. Errors end the command with `lint_failed`, avoiding wasted rendering time.
|
|
21
|
+
|
|
22
|
+
For environment problems (missing browser or FFmpeg), run `multiplane doctor --json` first. Each entry in `data.checks` has `ok` and a `detail`; when the command fails, the `result` also carries `code` and `hint`. Fix the failing checks before rendering.
|
|
23
|
+
|
|
24
|
+
## Set up a machine
|
|
25
|
+
|
|
26
|
+
Use these commands when the user asks you to set up Multiplane, or approves a fix that `doctor` suggests. They change the user's machine-wide settings, so do not run `set`, `unset`, `install` or `remove` on your own initiative.
|
|
27
|
+
|
|
28
|
+
- `multiplane config get --json` reads the user config; `data.overrides` shows environment variables that currently take priority.
|
|
29
|
+
- `multiplane config set ffmpeg <path> --json` saves the FFmpeg path and checks it at once: read `data.check.usable` and `data.check.reason`. An unusable path is still saved and produces a `warning`. Other keys: `raster` (`gpu` / `software`), `encoder` (`x264` / `nvenc-h264` / `nvenc-hevc`), `workers` (a positive integer, or `auto`), `jobsDir`. `multiplane config unset <key>` restores the default.
|
|
30
|
+
- `multiplane skill status --json` reports this skill for Claude Code and Codex; `multiplane skill install --host claude|codex|all --json` installs or updates it. A copy the user has edited is reported as `modified` and is not replaced unless you pass `--force`, which backs it up first; ask the user before using `--force`.
|
|
31
|
+
- When only the desktop app is installed, `multiplane` may not be on PATH. The app ships its own command: on Windows `<install directory>\multiplane.cmd`, on macOS `/Applications/Multiplane.app/Contents/Resources/bin/multiplane`, and on Linux `<path to the AppImage> --multiplane-cli`. The app's Environment page shows the exact path.
|
|
32
|
+
|
|
33
|
+
## Shot contract
|
|
34
|
+
|
|
35
|
+
Minimal shot:
|
|
36
|
+
|
|
37
|
+
```html
|
|
38
|
+
<!doctype html>
|
|
39
|
+
<html lang="en"><meta charset="utf-8"><title>Example</title>
|
|
40
|
+
<link rel="stylesheet" href="/multiplane/runtime/shot.css">
|
|
41
|
+
<style>
|
|
42
|
+
#stage { width: 1920px; height: 1080px; background: #111; }
|
|
43
|
+
#box { position: absolute; left: 0; top: 490px; width: 100px; height: 100px; background: #eee; }
|
|
44
|
+
</style>
|
|
45
|
+
<div id="stage"><div id="box"></div></div>
|
|
46
|
+
<script src="/multiplane/runtime/shot.js"></script>
|
|
47
|
+
<script>
|
|
48
|
+
const box = document.querySelector('#box');
|
|
49
|
+
Shot.define({
|
|
50
|
+
duration: 4, // seconds
|
|
51
|
+
fps: 30, // optional, default 30
|
|
52
|
+
render(t) { // draw the frame at time t; nothing else may influence it
|
|
53
|
+
const k = Shot.ease.inOutCubic(Shot.ease.prog(t, 0.5, 3));
|
|
54
|
+
box.style.transform = `translateX(${Shot.ease.lerp(0, 1820, k)}px)`;
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
</script></html>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Stage
|
|
61
|
+
|
|
62
|
+
- Include `#stage` in the page and draw everything inside it. Define the frame dimensions with **fixed CSS pixel width and height**. Do not let them vary with the viewport, time, or content.
|
|
63
|
+
- Use only the width and height of `#stage` to define the frame dimensions; there are no separate width and height options. Common sizes: 1920×1080 (16:9), 1080×1920 (9:16), 1080×1080 (1:1), 1080×1350 (4:5).
|
|
64
|
+
- Output pixels = logical dimensions × `--scale`, and must be positive even integers. For example, do not use `--scale 0.5` with 1080×1350 (it produces 675 rows).
|
|
65
|
+
|
|
66
|
+
### `Shot.define(spec)`
|
|
67
|
+
|
|
68
|
+
| Field | Required | Meaning |
|
|
69
|
+
|---|---|---|
|
|
70
|
+
| `duration` | Yes | Duration in seconds. |
|
|
71
|
+
| `render(t)` | Yes | Draw the image at second `t`. Use a **synchronous function**; do not return a Promise. |
|
|
72
|
+
| `fps` | No | Frame rate, default 30. |
|
|
73
|
+
| `fonts` | No | Fonts to wait for: `[['48px MyFont', 'text used'], ...]`. |
|
|
74
|
+
| `setup()` | No | One-time preparation (load images, create a 3D scene, etc.). May return a Promise; the renderer waits for it before starting. |
|
|
75
|
+
| `cuts` | No | Array of hard cut times (seconds). Motion blur time samples do not cross these times. **Declare every hard cut in the image**, or frames on either side of the cut will blur together. |
|
|
76
|
+
| `post` | No | Post-processing defaults: `motionBlur` (time samples per frame; 1 disables it), `maxMotionBlur` (upper limit for adding samples where motion is fast; see below), `shutter` (shutter fraction of a frame; 0.5 means 180°), `grain` (film grain intensity; 0 disables it). Command-line options override these. |
|
|
77
|
+
| `blurAt(t)` | No | Return the required number of time samples (a positive integer) at this time, using fewer samples for static sections and more for fast motion. |
|
|
78
|
+
| `meta` | No | Any JSON data for tools that read the shot (beats, captions, notes), at most 1 MiB. Readable as `SHOT.meta`; returned by `inspect`; never affects pixels. |
|
|
79
|
+
|
|
80
|
+
Use `Shot.ease` for `clamp`, `lerp`, `prog(t, start, dur)`, and several easing curves; use `Shot.size` for the stage's logical dimensions. You may also skip `Shot.define` and define `window.SHOT = { duration, fps, ready, render, cuts, post }` directly, where `ready` is a Promise that resolves when assets are ready.
|
|
81
|
+
|
|
82
|
+
### Resources
|
|
83
|
+
|
|
84
|
+
- Keep the shot file inside the resource root (`--root`, the current directory by default). Relative paths in the page resolve from the shot file's location and must not point outside the root.
|
|
85
|
+
- Treat paths starting with `/multiplane/` as reserved for the renderer's runtime libraries.
|
|
86
|
+
- **Use local files for all resources**: point `@font-face` to local font files and list them in `fonts`. Do not reference remote fonts, CDN scripts, or remote images.
|
|
87
|
+
- Finish loading images, fonts, and other assets in `setup()` / `ready`. Do not start loading in `render(t)`.
|
|
88
|
+
|
|
89
|
+
## Determinism constraints (most important)
|
|
90
|
+
|
|
91
|
+
Multiplane calls `render(t)` out of order, repeatedly, and in parallel across multiple browser processes, then compares the pixels of each frame. **The same `t` must produce identical pixels, regardless of earlier calls or their count.**
|
|
92
|
+
|
|
93
|
+
Do not use the following in `render(t)` or the code it calls:
|
|
94
|
+
|
|
95
|
+
| Do not use | Reason | Use instead |
|
|
96
|
+
|---|---|---|
|
|
97
|
+
| `Date.now()`, `new Date()`, `performance.now()` | Wall-clock time changes on every call | Use only the parameter `t` |
|
|
98
|
+
| `Math.random()`, `crypto.getRandomValues()` | Results change on every call | Use a fixed-seed pseudorandom generator (such as mulberry32), precompute in `setup()`, or derive values from `t` and the element index |
|
|
99
|
+
| CSS `animation`, `transition`, `@keyframes`, Web Animations API | The browser advances them by wall-clock time | Set styles directly in `render(t)` |
|
|
100
|
+
| `requestAnimationFrame`, `setTimeout`, `setInterval` driving the image | Same as above | Same as above; let the runtime handle preview playback, and do not write your own playback loop |
|
|
101
|
+
| `<video>`, `<audio>` playback, animated images such as GIFs | Playback position is not controlled by `t` | Extract individual frames in advance and select a frame by `t` |
|
|
102
|
+
| State that depends on the previous call (accumulated positions, per-frame particle integration, "if the previous frame was...") | With out-of-order or parallel calls, the previous call is not the previous frame | Write a closed-form function of `t`; for simulations, precompute the full result with fixed time steps in `setup()` and only look up values in `render(t)` |
|
|
103
|
+
| An `async` `render`, waiting for loading in `render` | The image may be incomplete when captured | Put all loading in `setup()` / `ready` |
|
|
104
|
+
|
|
105
|
+
The runtime uses wall-clock time for its own preview playback. You do not write that part, and it does not affect rendering.
|
|
106
|
+
|
|
107
|
+
`lint` detects most direct patterns in the table above, but not indirect calls (such as `const now = Date.now; now()`) or accumulated state (such as `x += 1`). So **only a passing `verify` counts** (a pass with `gpu_raster_jitter` warnings still counts).
|
|
108
|
+
|
|
109
|
+
If a prohibited pattern is necessary and you have confirmed that it cannot affect the image (for example, a log only in `setup()`), suppress it with a comment on the line **immediately above** it. Include the rule code:
|
|
110
|
+
|
|
111
|
+
```js
|
|
112
|
+
// multiplane-disable-next-line wall_clock
|
|
113
|
+
console.log('setup took', performance.now() - started);
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Use `/* multiplane-disable-next-line css_animation */` in CSS and `<!-- multiplane-disable-next-line media_playback -->` in HTML. Do not use suppression to bypass issues that actually affect the image. Also, pixel equality holds only on the same machine, with the same browser version, fonts, and assets. Changing the GPU or browser version may produce small differences.
|
|
117
|
+
|
|
118
|
+
## 3D layer (optional)
|
|
119
|
+
|
|
120
|
+
Use `multiplane/three` when you need 3D cards or depth of field. Install `three@0.180.0` in the project (`npm install three@0.180.0`).
|
|
121
|
+
|
|
122
|
+
```html
|
|
123
|
+
<script type="importmap">{"imports":{
|
|
124
|
+
"three": "/multiplane/vendor/three/build/three.module.js",
|
|
125
|
+
"three/addons/": "/multiplane/vendor/three/examples/jsm/"
|
|
126
|
+
}}</script>
|
|
127
|
+
<link rel="stylesheet" href="/multiplane/runtime/shot.css">
|
|
128
|
+
<style>#stage { width: 1920px; height: 1080px; }</style>
|
|
129
|
+
<div id="stage"></div>
|
|
130
|
+
<script src="/multiplane/runtime/shot.js"></script>
|
|
131
|
+
<script type="module">
|
|
132
|
+
import { createThreeLayer } from '/multiplane/three.js';
|
|
133
|
+
const layer = createThreeLayer({ aperture: 0.12, focusDistance: 10 });
|
|
134
|
+
const card = layer.card({ src: './assets/card.png', width: 2.5, height: 2.5, position: [0, 0, 0] }); // your own local image
|
|
135
|
+
Shot.define({
|
|
136
|
+
duration: 3,
|
|
137
|
+
setup: () => layer.ready, // wait for textures
|
|
138
|
+
render(t) {
|
|
139
|
+
card.rotation.y = 0.3 * t;
|
|
140
|
+
layer.render({ t, focusDistance: 10 - t }); // always pass t
|
|
141
|
+
},
|
|
142
|
+
});
|
|
143
|
+
</script>
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
- Use `createThreeLayer(options)` to add a transparent WebGL canvas inside `#stage`, layered with ordinary HTML elements (`zIndex` controls stacking). Common options: `fov`, `focusDistance`, `aperture` (0 keeps everything sharp), `samples` / `maxSamples` (depth-of-field sample count, adaptive to the amount of blur by default), `quality` (`'final'` uses accumulated depth of field and is the default; `'preview'` is a fast approximation for drafts only).
|
|
147
|
+
- Use `style` on `createThreeLayer` for layer-wide defaults, or on a card to override them: `annotationFontFamily`, `annotationColor` (lines), `annotationTextColor`, `textureBackground`, `browserFrameColor`, `browserFrameFontFamily`. Font options take a single family name; the renderer waits for it to load and fails with `resource_failed` instead of falling back.
|
|
148
|
+
- Use `layer.card({ src, width, height, position, rotation, radius, border, shadow, annotations, style })` to get a three.js `Group`. Change its position and rotation in `render(t)`.
|
|
149
|
+
- Call `layer.render({ t, ... })` inside every `render(t)` call and pass the same `t`. The renderer handles motion blur subsamples automatically.
|
|
150
|
+
- Use `layer.scene` and `layer.camera` as ordinary three.js objects and add your own meshes. Their state must likewise depend only on `t`.
|
|
151
|
+
- Use `apertureForBlurRadius({ radiusPixels, depth, focusDistance })` to convert a desired blur radius in pixels at a given depth into an aperture.
|
|
152
|
+
|
|
153
|
+
## Commands
|
|
154
|
+
|
|
155
|
+
Use `--json` with any command. Resolve shot paths relative to `--root` (the current directory by default).
|
|
156
|
+
|
|
157
|
+
| Command | Purpose | Common options |
|
|
158
|
+
|---|---|---|
|
|
159
|
+
| `multiplane lint <shot>` | Static code checks without a browser | `--root` |
|
|
160
|
+
| `multiplane stills <shot>` | PNG stills at given times and a contact sheet; also for final images | `--at 0,1.5,3` (seconds) or `--every 0.5`; `--out` |
|
|
161
|
+
| `multiplane verify <shot>` | Determinism check: pixel comparisons out of order, after reload, and with single/multiple processes | `--at` (must fall on frames), `--workers` (default 2) |
|
|
162
|
+
| `multiplane render <shot>` | Render video | `--out`, `--from` / `--to` (seconds, end excluded), `--fps`, `--scale`, `--workers`, `--quality`, `--motion-blur`, `--max-motion-blur`, `--shutter`, `--grain`, `--no-post`, `--draft`, `--encoder`, `--audio`, `--no-static-reuse` |
|
|
163
|
+
| `multiplane inspect <shot>` | Read duration, frames, stage size, cuts and `meta` without rendering | `--fps`, `--root` |
|
|
164
|
+
| `multiplane serve` | Serve shots on 127.0.0.1 so the user can open them in a browser; stop it when done | `--root`, `--port` |
|
|
165
|
+
| `multiplane benchmark` | Measure the fastest worker count on this machine (2–3 minutes); renders then use it automatically | `--raster` |
|
|
166
|
+
| `multiplane doctor` | Check the environment | — |
|
|
167
|
+
| `multiplane config get\|set\|unset` | Read or change the user config | see "Set up a machine" |
|
|
168
|
+
| `multiplane skill status\|install\|remove` | Manage this skill for Claude Code and Codex | `--host`, `--force` |
|
|
169
|
+
| `multiplane status <job>` | View job status | — |
|
|
170
|
+
| `multiplane cancel <job>` | Stop a job | `--wait` (seconds) |
|
|
171
|
+
| `multiplane wait <job>` | Wait for a job started earlier and print its events | `--timeout` (seconds) |
|
|
172
|
+
|
|
173
|
+
Use `--out`, `--overwrite`, and `--no-lint` (skip automatic lint) with `stills`, `verify`, or `render`. Run `multiplane <command> --help` to list all options for that command.
|
|
174
|
+
|
|
175
|
+
Each run has its own job directory, `out/jobs/<jobId>/`. Without `--out`, artifacts are written there; use `artifacts` in the result for the paths. If `--out` points to an existing file, the command fails with `output_exists`. Add `--overwrite` when you intend to replace it (replacement happens only after the new artifact is fully written; on failure, the old file stays untouched).
|
|
176
|
+
|
|
177
|
+
FFmpeg is not bundled. It is found in this order: `--ffmpeg <path>`, the environment variable `MULTIPLANE_FFMPEG`, `ffmpeg` in the user config `config.json`, then the system PATH. It must support libx264. To save a path for every project, use `multiplane config set ffmpeg <path>` with the user's approval (see "Set up a machine").
|
|
178
|
+
|
|
179
|
+
Motion blur quality: the shot decides whether there is motion blur (`post.motionBlur` above 1, the starting number of samples); `--quality` decides how many samples fast frames get. The default `standard` compares adjacent samples block by block and doubles the count wherever something moved more than about 2 pixels, up to 64; `high` uses about 1 pixel and up to 256. Static frames drop to 1 sample. Use the default `standard` for iterating and for the final render: on real shots `high` takes several times longer for a difference visible only when zoomed in. Use `high` only when the user asks, for stills that will be viewed up close, or when very fast thin motion still strobes under `standard`. Do not raise `motionBlur` for the whole shot to fix strobing; use `high`, or `--max-motion-blur` for a custom limit. `result.data.blurSamples` (`{ min, max, mean, histogram }`) shows the counts used. A shot with its own `blurAt(t)` keeps full control of the count.
|
|
180
|
+
|
|
181
|
+
When the user wants an image rather than a video (a cover, poster, thumbnail or illustration), write a shot and use `stills` for the final output: each PNG gets the same supersampling (`--scale 2`), motion blur, depth of field and `--alpha` as video. Pick a time during motion if the still should show motion blur. Hand over the `t-<seconds>.png` file from `result.data.stills`, not the contact sheet.
|
|
182
|
+
|
|
183
|
+
Use `--draft` with `render` or `stills` while iterating: it captures at a scale of at most 0.5 and upscales, with no motion blur and no grain, so it is faster and visibly lower in quality. Options you pass explicitly override the preset. Render the final video without `--draft`; `result.data.draft` is `true` when a draft was produced, so do not hand a draft over as the final result.
|
|
184
|
+
|
|
185
|
+
## Transparent output
|
|
186
|
+
|
|
187
|
+
When the result must be laid over other footage, render with `--alpha` and `--format webm` (VP9) or `--format mov` (ProRes 4444); MP4 cannot carry alpha and `--alpha` with MP4 fails with `invalid_option`. The page background is transparent; do not give `#stage` (or a full-size element) a background colour if the layer should be transparent. Declare `post: { alpha: true }` in the shot when transparency is its normal output. Check transparent shots with `verify --alpha` and `stills --alpha`. Do not judge alpha by playing the WebM in a browser or a generic player; the renderer has already decoded and checked it.
|
|
188
|
+
|
|
189
|
+
## Read results
|
|
190
|
+
|
|
191
|
+
With `--json`, stdout contains one JSON event per line. **The last line is always `type: "result"`**. Use that line to determine success or failure:
|
|
192
|
+
|
|
193
|
+
```json
|
|
194
|
+
{"schema":"multiplane/1","type":"result","command":"render","ts":"2026-10-11T09:30:09.120Z","ok":true,"code":null,"message":null,"artifacts":[{"path":"/abs/out/jobs/20261011-093000-shot-3f2a/shot.mp4","kind":"video","bytes":812345}],"elapsedMs":9120,"jobId":"20261011-093000-shot-3f2a","data":{"output":"/abs/out/jobs/20261011-093000-shot-3f2a/shot.mp4","frames":120,"fps":30,"width":1920,"height":1080}}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
- When `ok: false`, use `code` to decide what to do next and `hint` for a suggested fix. Do not parse `message` to make decisions.
|
|
198
|
+
- Interpret exit codes as follows: 0 success; 1 shot or check failure (fix the shot); 2 invalid arguments (fix the command); 3 environment problem (run `doctor`); 4 renderer internal error (retry once, then report if it still fails); 130 cancelled.
|
|
199
|
+
- Before a video is published, the renderer reads the encoded file back and compares frame count, duration, size and frame rate with what it rendered (`result.data.outputCheck`). On a mismatch the command ends with `output_invalid` (exit code 4) and nothing is published; an existing file at the output path is left untouched. Retry once and report it if it repeats. A `warning` with `code: "output_unverified"` means the file was published without this check; inspect it before relying on it.
|
|
200
|
+
- `result.data.resources.peakMemoryBytes` is the sampled peak memory of the whole process tree. If jobs fail with `browser_crashed` or `worker_crashed` and this value is close to the machine's memory, lower `--workers` or `--scale`.
|
|
201
|
+
- If the browser process closes unexpectedly, the renderer relaunches it and renders the affected frame again. You will see a `warning` event with `code: "browser_restarted"`; pixels are unaffected, so no action is needed. If it keeps failing, the command ends with `browser_crashed` (exit code 4): this is not a problem in the shot. Retry once, then try `--raster software`, and report it if it still fails.
|
|
202
|
+
- Read each `lint` issue as a `finding`: `code` is the rule code (corresponding to the constraints above, such as `wall_clock`, `css_animation`, `remote_resource`), `location` provides `file`, `line`, and `column`, `details.snippet` is the source line, and `hint` explains what to use instead. Fix every `severity: "error"`. A `"warning"` (such as `timer_driven` or `font_not_awaited`) does not block rendering but usually indicates a problem.
|
|
203
|
+
- When `verify` fails, `code` is `nondeterministic_output`. Read the preceding `finding` events for the failed check (`reorder` for out-of-order calls / `reload` for page reloads / `workers:<n>` for parallel processes / `range` for consecutive frames), time `t`, changed pixel count, changed region `bbox`, and paths to the reference frame, actual frame, and diff image. Inspect the diff image and `bbox` to locate the element, then use the constraint table above to find the cause. Common patterns:
|
|
204
|
+
- Only `reorder` or `workers` fails: `render(t)` depends on state from the previous call.
|
|
205
|
+
- `reload` fails: random numbers or wall-clock time are used, or assets did not finish loading before `ready`.
|
|
206
|
+
- Only text regions fail: fonts are missing from `fonts`, or remote fonts are used.
|
|
207
|
+
- With `--json`, human-readable messages go to stderr. Do not merge them with stdout when parsing.
|
|
208
|
+
|
|
209
|
+
## Long renders
|
|
210
|
+
|
|
211
|
+
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.
|
|
212
|
+
|
|
213
|
+
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.
|