@glissade/cli 0.44.0 → 0.45.0-pre.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/dist/cli.js CHANGED
@@ -25,7 +25,8 @@ const KNOWN_BOOLEAN_FLAGS = new Set([
25
25
  "watch",
26
26
  "write",
27
27
  "keep-voice",
28
- "help"
28
+ "help",
29
+ "lottie"
29
30
  ]);
30
31
  function parseArgs(argv) {
31
32
  const positional = [];
@@ -80,6 +81,7 @@ const USAGE = `usage:
80
81
  gs verify-determinism <scene-module> [--shards <n>] [--against <frames.manifest>] [--range a..b] [--bisect] [--emit <p>]
81
82
  gs dev <scene-module> [--record] [--port <n>]
82
83
  gs import <lottie.json|asset.svg> [--out <dir>] [--allow-degraded]
84
+ gs export --lottie <scene-module> --out <file.json> [--width <n>] [--height <n>] [--fps <n>]
83
85
  gs narrate <scene-module|script.narration.json> [--provider <id>] [--align <id>] [--force]
84
86
  gs narration-lint <scene-module|script.narration.timing.json> [--json] [--fix] [--max-cps <n>]
85
87
  gs sfx <scene-module|script.sfx.json> [--verbose]
@@ -168,6 +170,15 @@ import options (.json = Lottie; .svg = static SVG → a scene that defers to @gl
168
170
  --out <dir> output directory for the generated scene module (default: .)
169
171
  --allow-degraded (Lottie only) downgrade degradable rejections (expressions, merge-paths modes != 1) to warnings
170
172
 
173
+ export options (--lottie: a glissade scene → a Lottie/bodymovin .json — the inverse of gs import):
174
+ --out <file.json> output Lottie document (required)
175
+ --width <n> document width in px (default: the scene size)
176
+ --height <n> document height in px (default: the scene size)
177
+ --fps <n> frame rate (default: the timeline fps, else 60). cubicBezier/hold eases round-trip
178
+ exactly; named eases / springs / expr tracks are sampled to dense linear keys.
179
+ MVP: Group / Rect / Circle / Path with a solid fill (+ optional stroke); Text,
180
+ gradient/mesh paint, and images are dropped with a warning
181
+
171
182
  measure-loudness options (the explicit publish-loudness measure step; commits *.loudness.json):
172
183
  --profile <id> youtube (default) | shorts (both -14 LUFS) | podcast (-16) | broadcast/ebu (-23); all cap at -1 dBTP
173
184
  measures the final mix (ebur128) and commits a deterministic peak-clamped gain; render applies it
@@ -196,7 +207,7 @@ async function main() {
196
207
  process.stdout.write(`${describe().version}\n`);
197
208
  return;
198
209
  }
199
- if (command !== "render" && command !== "diff" && command !== "verify-determinism" && command !== "dev" && command !== "import" && command !== "narrate" && command !== "narration-lint" && command !== "sfx" && command !== "prepare" && command !== "measure-loudness" && command !== "fonts" && command !== "cache" && command !== "mcp" && command !== "build" && command !== "describe" && command !== "migrate" && command !== "repin" && command !== "master" && command !== "localize" && command !== "types") {
210
+ if (command !== "render" && command !== "diff" && command !== "verify-determinism" && command !== "dev" && command !== "import" && command !== "export" && command !== "narrate" && command !== "narration-lint" && command !== "sfx" && command !== "prepare" && command !== "measure-loudness" && command !== "fonts" && command !== "cache" && command !== "mcp" && command !== "build" && command !== "describe" && command !== "migrate" && command !== "repin" && command !== "master" && command !== "localize" && command !== "types") {
200
211
  console.error(USAGE);
201
212
  process.exit(command === void 0 || command === "help" || command === "--help" ? 0 : 1);
202
213
  }
@@ -607,6 +618,35 @@ async function main() {
607
618
  }
608
619
  return;
609
620
  }
621
+ if (command === "export") {
622
+ if (!flags.has("lottie")) fail(`gs export currently supports only --lottie\n gs export --lottie <scene-module> --out <file.json> [--width <n>] [--height <n>] [--fps <n>]`);
623
+ const out = flags.get("out");
624
+ if (!out) fail(`gs export needs --out <file.json>\n${USAGE}`);
625
+ const dim = (name) => {
626
+ const raw = flags.get(name);
627
+ if (raw === void 0 || raw === "") return void 0;
628
+ const n = Number(raw);
629
+ if (!Number.isFinite(n) || n <= 0) fail(`--${name} must be a positive number, got '${raw}'`);
630
+ return n;
631
+ };
632
+ const width = dim("width");
633
+ const height = dim("height");
634
+ const { exportCommand } = await import("./export.js").then((n) => n.n);
635
+ try {
636
+ const result = await exportCommand({
637
+ input: modulePath,
638
+ out,
639
+ ...width !== void 0 ? { width } : {},
640
+ ...height !== void 0 ? { height } : {},
641
+ ...flags.get("fps") ? { fps: parseFpsOrFail(flags.get("fps")) } : {}
642
+ });
643
+ for (const w of result.warnings) process.stderr.write(`gs export: warning: ${w}\n`);
644
+ process.stderr.write(`gs export: wrote ${result.out}\n`);
645
+ } catch (err) {
646
+ fail(err instanceof Error ? err.message : String(err));
647
+ }
648
+ return;
649
+ }
610
650
  if (command === "dev") {
611
651
  const { dev } = await import("./dev.js").then((n) => n.n);
612
652
  const portFlag = flags.get("port");
package/dist/export.js ADDED
@@ -0,0 +1,35 @@
1
+ import { t as __exportAll } from "./rolldown-runtime.js";
2
+ import { o as loadSceneModule } from "./render.js";
3
+ import { mkdirSync, writeFileSync } from "node:fs";
4
+ import { dirname, resolve } from "node:path";
5
+ import { exportLottie } from "@glissade/lottie";
6
+ //#region src/export.ts
7
+ /**
8
+ * gs export --lottie (the inverse of `gs import`): a glissade scene module → a
9
+ * Lottie/bodymovin .json. Loads the SceneModule (the node tree + Timeline), runs
10
+ * the pure `@glissade/lottie` exporter, and writes the document. Scope-out /
11
+ * degrade notes surface as warnings (mirroring `gs import`).
12
+ */
13
+ var export_exports = /* @__PURE__ */ __exportAll({ exportCommand: () => exportCommand });
14
+ async function exportCommand(opts) {
15
+ const mod = await loadSceneModule(opts.input);
16
+ const scene = mod.createScene();
17
+ const width = opts.width ?? scene.size.w;
18
+ const height = opts.height ?? scene.size.h;
19
+ const warnings = [];
20
+ const doc = exportLottie(mod, {
21
+ width,
22
+ height,
23
+ ...opts.fps !== void 0 ? { fps: opts.fps } : {},
24
+ onWarn: (w) => warnings.push(w)
25
+ });
26
+ const outAbs = resolve(opts.out);
27
+ mkdirSync(dirname(outAbs), { recursive: true });
28
+ writeFileSync(outAbs, `${JSON.stringify(doc, null, 2)}\n`);
29
+ return {
30
+ out: outAbs,
31
+ warnings
32
+ };
33
+ }
34
+ //#endregion
35
+ export { export_exports as n, exportCommand as t };
package/dist/index.d.ts CHANGED
@@ -573,6 +573,28 @@ interface ImportCommandResult {
573
573
  }
574
574
  declare function importCommand(opts: ImportOptions): Promise<ImportCommandResult>;
575
575
  //#endregion
576
+ //#region src/export.d.ts
577
+ /**
578
+ * gs export --lottie (the inverse of `gs import`): a glissade scene module → a
579
+ * Lottie/bodymovin .json. Loads the SceneModule (the node tree + Timeline), runs
580
+ * the pure `@glissade/lottie` exporter, and writes the document. Scope-out /
581
+ * degrade notes surface as warnings (mirroring `gs import`).
582
+ */
583
+ interface ExportOptions {
584
+ /** Scene module path. */
585
+ input: string;
586
+ /** Output .json file. */
587
+ out: string;
588
+ width?: number;
589
+ height?: number;
590
+ fps?: number;
591
+ }
592
+ interface ExportCommandResult {
593
+ out: string;
594
+ warnings: string[];
595
+ }
596
+ declare function exportCommand(opts: ExportOptions): Promise<ExportCommandResult>;
597
+ //#endregion
576
598
  //#region src/diff.d.ts
577
599
  interface DiffOptions {
578
600
  modulePath: string;
@@ -814,4 +836,4 @@ declare function cacheVerifyCommand(opts: CacheVerifyOptions): Promise<CacheVeri
814
836
  /** The @glissade/cli package version (the glissade VERSION for the cache key). */
815
837
  declare function glissadeVersion(): string;
816
838
  //#endregion
817
- export { AudioMixError, type AudioMixPlan, type CacheKeyContext, type CacheMode, type CacheVerifyOptions, type CacheVerifyResult, type CaptionProbe, type CommittedLimiter, DEFAULT_CACHE_MAX_SIZE, DEFAULT_FPS, DEFAULT_FRAMES, DEFAULT_MAX_GR_DB, DEFAULT_PROFILE_ID, type DevOptions, type DevServer, type Diagnostic, type DiffOptions, type DiffResult, type EncoderChoice, FfmpegVideoFrameSource, FrameCache, FrameCacheError, type FrameCacheOptions, type ImportCommandResult, type ImportOptions, LOUDNESS_SCHEMA_VERSION, type LintOptions, type LintRule, LocaleArgsError, LoudnessError, type LoudnessMeasurement, MachineExportError, type MachineRenderFlags, type MasterConfig, MasterError, type MasterLimiter, type MasterMemberResult, type MasterPlan, type MasterResult, type MeasureLoudnessOptions, type MeasureLoudnessResult, type MemberMeasure, type MemberPlan, type NarrationLintOptions, type NarrationLintResult, NoEncoderError, PUBLISH_PROFILES, type PublishProfile, type RenderOptions, type RenderShardedArgs, type RepinFrame, type RepinOptions, type RepinResult, type RepinStatus, SceneModuleError, ShardError, type ShardRange, type VideoInfo, VideoProbeError, applyMixGainDb, atempoChain, availableEncoders, buildCaptionProbe, buildMixWav, cacheVerifyCommand, capsId, clearFrameCache, collectAudioClips, computeGainDb, computeMixHash, dev, diffCommand, evaluateAt, ffmpegAvailable, fixDiff, formatTable, frameCacheKey, gainExpression, glissadeVersion, hasErrors, importCommand, lintNarration, lintTimingPathFor, loadSceneModule, localeOutPath, loudnessPathFor, masterAfChain, masterCommand, measureFile, measureLoudnessCommand, narrationLintCommand, normalizeMasterConfig, parseCacheMaxSize, parseEncoderList, parseLocalesList, parseLoudnormJson, peakClampBinds, pickEncoder, planAudioMix, planFinalAudio, planMaster, probeEntryHeader, probeVideo, readLoudness, render, renderLocales, renderSharded, repinCommand, resolveAssetPath, resolveLoudnessGainDb, resolveProfile, resolveRenderDoc, sceneHasGpuNodes, snapshotAt, splitFrameRange };
839
+ export { AudioMixError, type AudioMixPlan, type CacheKeyContext, type CacheMode, type CacheVerifyOptions, type CacheVerifyResult, type CaptionProbe, type CommittedLimiter, DEFAULT_CACHE_MAX_SIZE, DEFAULT_FPS, DEFAULT_FRAMES, DEFAULT_MAX_GR_DB, DEFAULT_PROFILE_ID, type DevOptions, type DevServer, type Diagnostic, type DiffOptions, type DiffResult, type EncoderChoice, type ExportOptions as ExportCommandOptions, type ExportCommandResult, FfmpegVideoFrameSource, FrameCache, FrameCacheError, type FrameCacheOptions, type ImportCommandResult, type ImportOptions, LOUDNESS_SCHEMA_VERSION, type LintOptions, type LintRule, LocaleArgsError, LoudnessError, type LoudnessMeasurement, MachineExportError, type MachineRenderFlags, type MasterConfig, MasterError, type MasterLimiter, type MasterMemberResult, type MasterPlan, type MasterResult, type MeasureLoudnessOptions, type MeasureLoudnessResult, type MemberMeasure, type MemberPlan, type NarrationLintOptions, type NarrationLintResult, NoEncoderError, PUBLISH_PROFILES, type PublishProfile, type RenderOptions, type RenderShardedArgs, type RepinFrame, type RepinOptions, type RepinResult, type RepinStatus, SceneModuleError, ShardError, type ShardRange, type VideoInfo, VideoProbeError, applyMixGainDb, atempoChain, availableEncoders, buildCaptionProbe, buildMixWav, cacheVerifyCommand, capsId, clearFrameCache, collectAudioClips, computeGainDb, computeMixHash, dev, diffCommand, evaluateAt, exportCommand, ffmpegAvailable, fixDiff, formatTable, frameCacheKey, gainExpression, glissadeVersion, hasErrors, importCommand, lintNarration, lintTimingPathFor, loadSceneModule, localeOutPath, loudnessPathFor, masterAfChain, masterCommand, measureFile, measureLoudnessCommand, narrationLintCommand, normalizeMasterConfig, parseCacheMaxSize, parseEncoderList, parseLocalesList, parseLoudnormJson, peakClampBinds, pickEncoder, planAudioMix, planFinalAudio, planMaster, probeEntryHeader, probeVideo, readLoudness, render, renderLocales, renderSharded, repinCommand, resolveAssetPath, resolveLoudnessGainDb, resolveProfile, resolveRenderDoc, sceneHasGpuNodes, snapshotAt, splitFrameRange };
package/dist/index.js CHANGED
@@ -9,9 +9,10 @@ import { a as gainExpression, n as applyMixGainDb, o as planAudioMix, r as atemp
9
9
  import { r as resolveRenderDoc, t as MachineExportError } from "./machines.js";
10
10
  import { t as dev } from "./dev.js";
11
11
  import { t as importCommand } from "./import.js";
12
+ import { t as exportCommand } from "./export.js";
12
13
  import { i as snapshotAt, r as evaluateAt, t as diffCommand } from "./diff.js";
13
14
  import { n as DEFAULT_FRAMES, r as repinCommand, t as DEFAULT_FPS } from "./repin.js";
14
15
  import { a as fixDiff, c as lintNarration, n as lintTimingPathFor, o as formatTable, r as narrationLintCommand, s as hasErrors, t as buildCaptionProbe } from "./narrationLintCommand.js";
15
16
  import { a as clearFrameCache, c as parseCacheMaxSize, i as capsId, l as probeEntryHeader, n as FrameCache, o as frameCacheKey, r as FrameCacheError, t as DEFAULT_CACHE_MAX_SIZE } from "./frameCache.js";
16
17
  import { t as cacheVerifyCommand } from "./cacheVerify.js";
17
- export { AudioMixError, DEFAULT_CACHE_MAX_SIZE, DEFAULT_FPS, DEFAULT_FRAMES, DEFAULT_MAX_GR_DB, DEFAULT_PROFILE_ID, FfmpegVideoFrameSource, FrameCache, FrameCacheError, LOUDNESS_SCHEMA_VERSION, LocaleArgsError, LoudnessError, MachineExportError, MasterError, NoEncoderError, PUBLISH_PROFILES, SceneModuleError, ShardError, VideoProbeError, applyMixGainDb, atempoChain, availableEncoders, buildCaptionProbe, buildMixWav, cacheVerifyCommand, capsId, clearFrameCache, collectAudioClips, computeGainDb, computeMixHash, dev, diffCommand, evaluateAt, ffmpegAvailable, fixDiff, formatTable, frameCacheKey, gainExpression, glissadeVersion, hasErrors, importCommand, lintNarration, lintTimingPathFor, loadSceneModule, localeOutPath, loudnessPathFor, masterAfChain, masterCommand, measureFile, measureLoudnessCommand, narrationLintCommand, normalizeMasterConfig, parseCacheMaxSize, parseEncoderList, parseLocalesList, parseLoudnormJson, peakClampBinds, pickEncoder, planAudioMix, planFinalAudio, planMaster, probeEntryHeader, probeVideo, readLoudness, render, renderLocales, renderSharded, repinCommand, resolveAssetPath, resolveLoudnessGainDb, resolveProfile, resolveRenderDoc, sceneHasGpuNodes, snapshotAt, splitFrameRange };
18
+ export { AudioMixError, DEFAULT_CACHE_MAX_SIZE, DEFAULT_FPS, DEFAULT_FRAMES, DEFAULT_MAX_GR_DB, DEFAULT_PROFILE_ID, FfmpegVideoFrameSource, FrameCache, FrameCacheError, LOUDNESS_SCHEMA_VERSION, LocaleArgsError, LoudnessError, MachineExportError, MasterError, NoEncoderError, PUBLISH_PROFILES, SceneModuleError, ShardError, VideoProbeError, applyMixGainDb, atempoChain, availableEncoders, buildCaptionProbe, buildMixWav, cacheVerifyCommand, capsId, clearFrameCache, collectAudioClips, computeGainDb, computeMixHash, dev, diffCommand, evaluateAt, exportCommand, ffmpegAvailable, fixDiff, formatTable, frameCacheKey, gainExpression, glissadeVersion, hasErrors, importCommand, lintNarration, lintTimingPathFor, loadSceneModule, localeOutPath, loudnessPathFor, masterAfChain, masterCommand, measureFile, measureLoudnessCommand, narrationLintCommand, normalizeMasterConfig, parseCacheMaxSize, parseEncoderList, parseLocalesList, parseLoudnormJson, peakClampBinds, pickEncoder, planAudioMix, planFinalAudio, planMaster, probeEntryHeader, probeVideo, readLoudness, render, renderLocales, renderSharded, repinCommand, resolveAssetPath, resolveLoudnessGainDb, resolveProfile, resolveRenderDoc, sceneHasGpuNodes, snapshotAt, splitFrameRange };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glissade/cli",
3
- "version": "0.44.0",
3
+ "version": "0.45.0-pre.1",
4
4
  "description": "glissade CLI: headless rendering via backend-skia (+ FFmpeg mux).",
5
5
  "license": "Apache-2.0",
6
6
  "engines": {
@@ -28,15 +28,15 @@
28
28
  "@napi-rs/canvas": "^0.1.65",
29
29
  "esbuild": "0.28.0",
30
30
  "jiti": "^2.4.2",
31
- "@glissade/backend-skia": "0.44.0",
32
- "@glissade/core": "0.44.0",
33
- "@glissade/interact": "0.44.0",
34
- "@glissade/lottie": "0.44.0",
35
- "@glissade/narrate": "0.44.0",
36
- "@glissade/player": "0.44.0",
37
- "@glissade/scene": "0.44.0",
38
- "@glissade/sfx": "0.44.0",
39
- "@glissade/svg": "0.44.0"
31
+ "@glissade/backend-skia": "0.45.0-pre.1",
32
+ "@glissade/core": "0.45.0-pre.1",
33
+ "@glissade/interact": "0.45.0-pre.1",
34
+ "@glissade/lottie": "0.45.0-pre.1",
35
+ "@glissade/narrate": "0.45.0-pre.1",
36
+ "@glissade/player": "0.45.0-pre.1",
37
+ "@glissade/scene": "0.45.0-pre.1",
38
+ "@glissade/sfx": "0.45.0-pre.1",
39
+ "@glissade/svg": "0.45.0-pre.1"
40
40
  },
41
41
  "repository": {
42
42
  "type": "git",