@codemovie/cli
v0.0.1
Published
Render Code.Movie animations to videos or image sequences from your terminal
Readme
Code.Movie CLI
Command-line interface to render Code.Movie animations as image sequences. The image sequences are ready to drop into your video editor of choice or can be piped straight into ffmpeg for instant video output:
npm install -g @codemovie/cli
cat > project.json5 <<EOL
{
inputOptions: { languageModule: "ecmascript" },
outputOptions: { width: 800, height: 450 },
frames: [{ code: "// Hello World" }, { code: "console.log(42)" }],
}
EOL
code-movie -p project.json5 |
ffmpeg -y -r 60 -f image2pipe -s 800x450 -vcodec png -i - -vcodec libx264 -pix_fmt yuv420p -vsync cfr -f ismv -movflags +faststart video.mp4For instant videos, pipe stdout into ffmpeg using the image2pipe muxer. Otherwise use the --out argument to specify the directory to dump the image sequence into. The CLI runs Chrome via Puppeteer in deterministic render mode and saves (or pipes to stdout) a screenshot for each frame.
Arguments
Core arguments
-p,--project filePath to JSON5-encoded project file.-o,--out directory(optional) Path to output directory for images, relative to the cwd. If not set either via this flag or in the project file, image buffers are sent to stdout.-d,--dump destination(optional) Dump the generated HTML (scaffold + animation) into the file at the specified path (relative to the cwd).-y,--yoloConfirm all prompts to create and/or delete directories and/or files. Defaults to false.-h,--helpPrint help
Project file overrides (all optional)
The following options override their equivalents in the project file.
--frames(string) JSON5-encoded array ofInputFrameobjects.--scaffold(file) Path to HTML scaffold file, relative to the cwd. Defaults to a built-in scaffold (see below).--properties(string) JSON5-encoded object of CSS properties to set on the scaffold's root element. Defaults to{}.--inputOptions.languageModule(string) Language module (eg."ecmascript"or"php").--inputOptions.languageOptions(string) JSON5-encoded object of language module options. Defaults to{}.--inputOptions.baseTheme(string) Theme module. Defaults todefaultTheme.--inputOptions.tabSize(int) Tab size. Defaults to 2.--inputOptions.minCols(int) Minimum columns. Defaults to 0.--outputOptions.width(int) Output width in px.--outputOptions.height(int) Output height in px.--outputOptions.fps(int) Frames per second. Defaults to 60.--outputOptions.frameTime(int) Time at each frame (including the animation) in ms. Defaults to 2000. Can be overwritten with thedata.frameTimeproperty on each frame object--outputOptions.format(string) Output image format. Defaults to png.--outputOptions.quality(int) Compression quality from range [0..100]. Applied to output formats jpeg and webp only. Defaults to 100.--outputOptions.transparent(boolean) Transparent background. Defaults tofalse.
Project file format (JSON5)
type ProjectFileFormat = {
// Path to the HTML file your animation gets embedded into, relative to the
// project file. Defaults to a built-in scaffold file (see below)
scaffold?: string;
// Path to output directory for images, relative to the project file. If not
// set either via this flag or in the project file, image buffers are sent to
// stdout.
out?: string;
// CSS properties and values to set on the scaffold's root element for
// customization purposes. Defaults to {}
properties?: Record<string, any>;
// List of code keyframes
// See the InputFrame type in https://code.movie/docs/reference/core.html
frames: Array<{
code: string;
decorations: InputDecoration[];
// Additional per-frame metadata
data?:
| {
// How long to pause on this particular frame in ms. Overrides
// "outputOptions.frameTime" on a per-frame basis
frameTime?: number | undefined;
}
| undefined;
}>;
inputOptions: {
// Module name of the language module to use (eg. "ecmascript" or "php").
// See https://code.movie/docs/reference/languages.html
languageModule: string;
// JSON-encoded options for the language module (eg. '{ "ts": true }' to
// enable TypeScript support in the "ecmascript" language module). Defaults
// to {}
// See https://code.movie/docs/reference/languages.html
languageOptions?: Record<string, any>;
// Module export for the built-in theme to use as a base (eg. "monokaiDark")
// Defaults to "defaultTheme"
// See https://code.movie/docs/reference/themes.html for available themes
baseTheme?: string;
// Defaults to 2
tabSize?: number;
// Defaults to 0
minCols?: number;
};
outputOptions: {
// Total dimensions
width: number;
height: number;
// How long to stay on a particular frame in ms. This time includes the
// (theme-dependent) transition time. Defaults to 2000. Can be overridden on
// a per-keyframe basis via a "keyframe.data.frameTime"
frameTime: number;
// Output image format. Defaults to "png"
format?: "png" | "jpeg" | "webp";
// Set the output image quality. Only applies when "format" is either "jpeg"
// or "webp". Defaults to 100.
quality?: number;
// Force transparent background. This not only disabled the browser's
// default white page background but also sets --cm-scene-background to
// "transparent". Optional, defaults to false.
transparent?: boolean;
};
};Default scaffold file
Every scaffold file must contain a <main> element into which the animation HTML gets injected. The CSS variable --animation-scale is added during rendering and contains the factor (as a floating-point number) by which the animation element needs to be scaled in order to fit inside <main>.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title></title>
<style>
*,
*::before,
*::after {
box-sizing: border-box;
}
html,
body {
width: 100vw;
height: 100vh;
padding: 0;
margin: 0;
overflow: hidden;
font-size: 48px;
}
main {
position: absolute;
/* set --main-inset to tweak the margin from the edges */
inset: var(--main-inset, 0);
}
/*
This slightly strange method of scaling and aligning the animation
circumvents the use of transition properties. Setting a transition
establishes a stacking context, which prevents backdrop-filter,
mix-blend-mode and other effects from affecting the page background.
*/
.cm-animation {
position: absolute;
--cm-font-size: calc(var(--animation-scale) * 1em);
top: calc(50% - var(--total-height) / 2);
left: calc(50% - var(--total-width) / 2);
}
</style>
</head>
<body>
<main>
<!-- Animation gets added here and is scaled to fit <main> -->
</main>
</body>
</html>Troubleshooting
Crash on Linux with either no error message or error message "No usable sandbox!"
See AppArmor User Namespace Restrictions vs. Chromium Developer Builds. An easy and safe workaround is to prefix the CLI command with CHROME_DEVEL_SANDBOX=/opt/google/chrome/chrome-sandbox.
