@bendyline/squisq-cli 1.2.2 → 2.0.0
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.md +81 -30
- package/dist/api-6KN3F6IQ.js +34 -0
- package/dist/api-6KN3F6IQ.js.map +1 -0
- package/dist/api.d.ts +172 -36
- package/dist/api.js +263 -121
- package/dist/api.js.map +1 -1
- package/dist/chunk-ESFEFKY4.js +175 -0
- package/dist/chunk-ESFEFKY4.js.map +1 -0
- package/dist/chunk-JEE26SZS.js +668 -0
- package/dist/chunk-JEE26SZS.js.map +1 -0
- package/dist/chunk-VM3ZFP3J.js +177 -0
- package/dist/chunk-VM3ZFP3J.js.map +1 -0
- package/dist/index.js +116 -539
- package/dist/index.js.map +1 -1
- package/dist/nativeEncoder-IQPN2RMC.js +15 -0
- package/dist/nativeEncoder-IQPN2RMC.js.map +1 -0
- package/dist/nativeEncoder-WHUIQZLL.js +16 -0
- package/dist/nativeEncoder-WHUIQZLL.js.map +1 -0
- package/package.json +7 -7
- package/dist/nativeEncoder-2HGWDEZZ.js +0 -86
- package/dist/nativeEncoder-2HGWDEZZ.js.map +0 -1
- package/dist/nativeEncoder-DLLAT2RT.js +0 -88
- package/dist/nativeEncoder-DLLAT2RT.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @bendyline/squisq-cli
|
|
2
2
|
|
|
3
|
-
Command-line tool and programmatic API for converting Squisq documents between DOCX, PPTX, PDF, XLSX, CSV, HTML, EPUB, Markdown, and container ZIP — and rendering them to MP4 video. Reads Markdown, binary documents (`.docx`/`.pptx`/`.pdf`/`.xlsx`/`.csv`/`.html`), ZIP/`.dbk` containers, folders, or pre-built Doc JSON as input.
|
|
3
|
+
Command-line tool and programmatic API for converting Squisq documents between DOCX, PPTX, PDF, XLSX, CSV, HTML, EPUB, Markdown, and container ZIP — and rendering them to MP4 video or animated GIF. Reads Markdown, binary documents (`.docx`/`.pptx`/`.pdf`/`.xlsx`/`.csv`/`.html`), ZIP/`.dbk` containers, folders, or pre-built Doc JSON as input.
|
|
4
4
|
|
|
5
5
|
Part of the [Squisq](https://github.com/bendyline/squisq) monorepo.
|
|
6
6
|
|
|
@@ -13,7 +13,7 @@ Part of the [Squisq](https://github.com/bendyline/squisq) monorepo.
|
|
|
13
13
|
npm install -g @bendyline/squisq-cli
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
For `squisq video` (and `convert` to `mp4`) you also need:
|
|
16
|
+
For `squisq video` (and `convert` to `mp4` or `gif`) you also need:
|
|
17
17
|
|
|
18
18
|
- ffmpeg — resolved from the `SQUISQ_FFMPEG` env var, then your `PATH` (`brew install ffmpeg` / `apt install ffmpeg` / `winget install ffmpeg`), then an optionally-installed `ffmpeg-static` package.
|
|
19
19
|
- A Playwright-managed Chromium for headless frame capture (e.g. `npx playwright install chromium`)
|
|
@@ -29,55 +29,62 @@ Convert a document to one or more formats. Input can be Markdown or a binary doc
|
|
|
29
29
|
```bash
|
|
30
30
|
squisq convert input.md -o report.docx # single file; format inferred from extension
|
|
31
31
|
squisq convert report.docx -o report.md # binary input → markdown
|
|
32
|
-
squisq convert input.md --
|
|
32
|
+
squisq convert input.md --formats pptx # single format to the default output dir
|
|
33
33
|
squisq convert input.md --formats docx,pptx,pdf # multiple formats
|
|
34
34
|
squisq convert project.dbk --output-dir ./out --formats html,docx
|
|
35
|
-
squisq convert input.md --theme cinematic --transform magazine --
|
|
35
|
+
squisq convert input.md --theme cinematic --transform magazine --formats pptx
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
-
| Option | Description
|
|
39
|
-
| --------------------- |
|
|
40
|
-
| `-o, --output <file>` | **Single** output file; format inferred from its extension (cannot combine with `--formats
|
|
41
|
-
| `-d, --output-dir` | Output directory (multi-format mode)
|
|
42
|
-
| `-f, --formats` | Comma-separated: `docx`, `pptx`, `pdf`, `html`, `htmlzip`, `epub`, `dbk`, `md`, `xlsx`, `csv`, `mp4`
|
|
43
|
-
|
|
|
44
|
-
|
|
|
45
|
-
| `--
|
|
46
|
-
| `--no-auto-templates` | Disable content-aware template auto-picking for unannotated headings | (auto on) |
|
|
38
|
+
| Option | Description | Default |
|
|
39
|
+
| --------------------- | ----------------------------------------------------------------------------------------------------------- | ------------- |
|
|
40
|
+
| `-o, --output <file>` | **Single** output file; format inferred from its extension (cannot combine with `--formats`) | — |
|
|
41
|
+
| `-d, --output-dir` | Output directory (multi-format mode) | same as input |
|
|
42
|
+
| `-f, --formats` | Comma-separated: `docx`, `pptx`, `pdf`, `html`, `htmlzip`, `epub`, `dbk`, `md`, `xlsx`, `csv`, `mp4`, `gif` | default set |
|
|
43
|
+
| `-t, --theme` | Squisq theme id — built-in or a custom theme inlined in the doc's frontmatter | none |
|
|
44
|
+
| `--transform` | Transform style applied before export (e.g. `documentary`, `magazine`, `minimal`) | none |
|
|
45
|
+
| `--no-auto-templates` | Disable content-aware template auto-picking for unannotated headings | (auto on) |
|
|
47
46
|
|
|
48
|
-
> **v1.5 breaking flag change:** `-o` is now a **single-file** destination (format inferred from the extension). The old `-o` output-**directory** behavior is now `-d, --output-dir`. A bare `convert <input>` with no `-o`/`--
|
|
47
|
+
> **v1.5 breaking flag change:** `-o` is now a **single-file** destination (format inferred from the extension). The old `-o` output-**directory** behavior is now `-d, --output-dir`. A bare `convert <input>` with no `-o`/`--formats` writes a default set that deliberately excludes `md`/`xlsx`/`csv`/`mp4`/`gif`.
|
|
49
48
|
|
|
50
49
|
Notes:
|
|
51
50
|
|
|
52
51
|
- `html` produces a single self-contained file with the standalone player inlined (static mode); `htmlzip` produces a `<name>.html.zip` archive with external assets and optional audio.
|
|
53
52
|
- `epub` embeds images from the input container and, when the doc has narration segments, generates EPUB 3 Media Overlays.
|
|
54
|
-
- `xlsx` export is tables-only; `csv` export emits the first table; `mp4`
|
|
53
|
+
- `xlsx` export is tables-only; `csv` export emits the first table; `mp4` and `gif` require the render toolchain (see Install).
|
|
55
54
|
- `dbk` re-serializes the input container as a ZIP.
|
|
56
55
|
|
|
57
56
|
### `squisq video <input> [output]`
|
|
58
57
|
|
|
59
|
-
Render a document to MP4
|
|
58
|
+
Render a document to MP4 or animated GIF. Playwright captures deterministic frames from a headless player page; native ffmpeg encodes H.264 + AAC for MP4 or a generated global palette for GIF. GIF has no audio track.
|
|
60
59
|
|
|
61
60
|
```bash
|
|
62
61
|
squisq video input.md output.mp4
|
|
62
|
+
squisq video input.md output.gif
|
|
63
|
+
squisq video input.md --format gif --no-animations
|
|
63
64
|
squisq video project.dbk --quality high --fps 30
|
|
64
65
|
squisq video ./my-folder --orientation portrait --captions social
|
|
65
66
|
squisq video input.md -t documentary --transform magazine --cover-preroll 1.5
|
|
66
67
|
squisq video doc.json -o out.mp4
|
|
67
68
|
```
|
|
68
69
|
|
|
69
|
-
| Option
|
|
70
|
-
|
|
|
71
|
-
| `-o, --output`
|
|
72
|
-
| `--
|
|
73
|
-
| `--
|
|
74
|
-
| `--
|
|
75
|
-
| `--
|
|
76
|
-
|
|
|
77
|
-
| `--
|
|
78
|
-
| `--
|
|
79
|
-
| `--
|
|
80
|
-
| `--
|
|
70
|
+
| Option | Description | Default |
|
|
71
|
+
| ---------------------------------- | -------------------------------------------------------------------- | ------------------------- |
|
|
72
|
+
| `-o, --output` | Output `.mp4` or `.gif` path; extension selects the format | `<input>.mp4` |
|
|
73
|
+
| `--format` | `mp4` or `gif` | inferred, otherwise `mp4` |
|
|
74
|
+
| `--fps` | Frames per second (MP4 1–120; GIF 1–100) | MP4 30; GIF 10 |
|
|
75
|
+
| `--quality` | MP4-only quality: `draft`, `normal`, or `high` | normal |
|
|
76
|
+
| `--orientation` | `landscape` or `portrait` | landscape |
|
|
77
|
+
| `--captions` | `off`, `standard`, or `social` | off |
|
|
78
|
+
| `--animations` / `--no-animations` | Enable/disable layer animations and block transitions | MP4 enabled; GIF disabled |
|
|
79
|
+
| `--loop` | GIF repeat count (`0` forever, `-1` no loop) | 0 |
|
|
80
|
+
| `--max-colors` | GIF palette size, 2–256 | 256 |
|
|
81
|
+
| `--dither` | GIF dithering: `bayer`, `sierra2_4a`, or `none` | `sierra2_4a` |
|
|
82
|
+
| `--bayer-scale` | Ordered Bayer strength, 0–5 | 3 |
|
|
83
|
+
| `-t, --theme` | Squisq theme id to apply | none |
|
|
84
|
+
| `--transform` | Transform style to apply before rendering | none |
|
|
85
|
+
| `--cover-preroll` | Seconds of cover-slide pre-roll before the story starts | 2 |
|
|
86
|
+
| `--width` / `--height` | Dimension overrides in pixels | MP4 1080p; GIF 960×540 |
|
|
87
|
+
| `--no-auto-templates` | Disable content-aware template auto-picking for unannotated headings | (auto on) |
|
|
81
88
|
|
|
82
89
|
### `squisq doctor`
|
|
83
90
|
|
|
@@ -118,11 +125,11 @@ All commands accept:
|
|
|
118
125
|
|
|
119
126
|
## Programmatic API
|
|
120
127
|
|
|
121
|
-
Import `@bendyline/squisq-cli/api` to use the same pipeline as a library from Node.js — no shell-out required. Like the CLI, `renderDocToMp4`
|
|
128
|
+
Import `@bendyline/squisq-cli/api` to use the same pipeline as a library from Node.js — no shell-out required. Like the CLI, `renderDocToMp4` and `renderDocToGif` require ffmpeg and a Playwright-managed Chromium.
|
|
122
129
|
|
|
123
130
|
### `convert()`
|
|
124
131
|
|
|
125
|
-
A pre-bound wrapper over `@bendyline/squisq-formats`' `convert()` that injects the CLI's format registry (every built-in exporter plus the CLI-only `mp4`
|
|
132
|
+
A pre-bound wrapper over `@bendyline/squisq-formats`' `convert()` that injects the CLI's format registry (every built-in exporter plus the CLI-only `mp4` and `gif` formats) and a default `resolvePlayerScript` (so HTML/player-embedding exports work out of the box). Both are overridable via `options`. `createCliRegistry()` returns that same registry for direct use.
|
|
126
133
|
|
|
127
134
|
```ts
|
|
128
135
|
import { convert, createCliRegistry, ConversionError } from '@bendyline/squisq-cli/api';
|
|
@@ -153,6 +160,7 @@ const result = await renderDocToMp4(doc, input.container, {
|
|
|
153
160
|
quality: 'high', // 'draft' | 'normal' | 'high' (default 'normal')
|
|
154
161
|
orientation: 'landscape', // 'landscape' | 'portrait' (default 'landscape')
|
|
155
162
|
captionStyle: 'social', // 'standard' | 'social' — omit for no captions
|
|
163
|
+
animationsEnabled: false, // static slide changes; media/timing remain active
|
|
156
164
|
coverPreRoll: 2, // seconds of cover-slide pre-roll (default 0)
|
|
157
165
|
onProgress: (phase, pct) => console.log(`${phase}: ${pct}%`),
|
|
158
166
|
});
|
|
@@ -162,6 +170,49 @@ console.log(`Rendered ${result.frameCount} frames (${result.duration}s) → ${re
|
|
|
162
170
|
|
|
163
171
|
The container's audio segments become the MP4's audio track; timed media clips and block videos found in the doc are embedded and mixed at their scheduled positions.
|
|
164
172
|
|
|
173
|
+
### `renderDocToGif`
|
|
174
|
+
|
|
175
|
+
```ts
|
|
176
|
+
import { renderDocToGif } from '@bendyline/squisq-cli/api';
|
|
177
|
+
|
|
178
|
+
const result = await renderDocToGif(doc, input.container, {
|
|
179
|
+
outputPath: './output.gif',
|
|
180
|
+
fps: 10,
|
|
181
|
+
animationsEnabled: false,
|
|
182
|
+
maxColors: 256,
|
|
183
|
+
loop: 0,
|
|
184
|
+
});
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
GIF defaults to 960×540 landscape (540×960 portrait), 10 fps, an infinite
|
|
188
|
+
loop, and disabled slide animations/transitions. Embedded video still advances,
|
|
189
|
+
but all audio is omitted and reported through `result.warnings`.
|
|
190
|
+
|
|
191
|
+
### Native frame encoding
|
|
192
|
+
|
|
193
|
+
For callers that already have PNG frames and do not need Playwright capture,
|
|
194
|
+
the API exposes the native FFmpeg layer directly:
|
|
195
|
+
|
|
196
|
+
```ts
|
|
197
|
+
import { framesToGifNativeBytes, framesToMp4NativeBytes } from '@bendyline/squisq-cli/api';
|
|
198
|
+
|
|
199
|
+
const mp4 = await framesToMp4NativeBytes('/usr/bin/ffmpeg', pngFrames, audioBytes, {
|
|
200
|
+
fps: 30,
|
|
201
|
+
quality: 'high',
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
const gif = await framesToGifNativeBytes('/usr/bin/ffmpeg', pngFrames, {
|
|
205
|
+
fps: 10,
|
|
206
|
+
width: 960,
|
|
207
|
+
height: 540,
|
|
208
|
+
});
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
The path variants write to a caller-supplied output; each `Bytes` variant returns
|
|
212
|
+
a `Uint8Array`. MP4 pads short audio with silence so narration cannot truncate
|
|
213
|
+
the timeline. GIF uses a compression-friendly diff palette and changed-rectangle
|
|
214
|
+
application.
|
|
215
|
+
|
|
165
216
|
### `extractThumbnails`
|
|
166
217
|
|
|
167
218
|
Extract JPEG thumbnails from the first frame of a rendered video:
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
ConversionError,
|
|
4
|
+
MemoryContentContainer,
|
|
5
|
+
convert,
|
|
6
|
+
createCliRegistry,
|
|
7
|
+
extractThumbnails,
|
|
8
|
+
readInput,
|
|
9
|
+
renderDocToGif,
|
|
10
|
+
renderDocToMp4
|
|
11
|
+
} from "./chunk-JEE26SZS.js";
|
|
12
|
+
import {
|
|
13
|
+
GIF_EXPORT_DEFAULTS,
|
|
14
|
+
framesToGifNative,
|
|
15
|
+
framesToGifNativeBytes,
|
|
16
|
+
framesToMp4Native,
|
|
17
|
+
framesToMp4NativeBytes
|
|
18
|
+
} from "./chunk-VM3ZFP3J.js";
|
|
19
|
+
export {
|
|
20
|
+
ConversionError,
|
|
21
|
+
GIF_EXPORT_DEFAULTS,
|
|
22
|
+
MemoryContentContainer,
|
|
23
|
+
convert,
|
|
24
|
+
createCliRegistry,
|
|
25
|
+
extractThumbnails,
|
|
26
|
+
framesToGifNative,
|
|
27
|
+
framesToGifNativeBytes,
|
|
28
|
+
framesToMp4Native,
|
|
29
|
+
framesToMp4NativeBytes,
|
|
30
|
+
readInput,
|
|
31
|
+
renderDocToGif,
|
|
32
|
+
renderDocToMp4
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=api-6KN3F6IQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/dist/api.d.ts
CHANGED
|
@@ -1,12 +1,51 @@
|
|
|
1
1
|
import { Doc } from '@bendyline/squisq/schemas';
|
|
2
2
|
import { ContentContainer } from '@bendyline/squisq/storage';
|
|
3
3
|
export { MemoryContentContainer } from '@bendyline/squisq/storage';
|
|
4
|
-
import { VideoQuality, VideoOrientation } from '@bendyline/squisq-video';
|
|
5
|
-
export { VideoOrientation, VideoQuality } from '@bendyline/squisq-video';
|
|
6
|
-
import { FormatId,
|
|
4
|
+
import { VideoQuality, VideoOrientation, GifDither, VideoExportOptions } from '@bendyline/squisq-video';
|
|
5
|
+
export { GifDither, VideoOrientation, VideoQuality } from '@bendyline/squisq-video';
|
|
6
|
+
import { FormatRegistry, FormatId, ConvertOptions, ConvertSource, ConversionResult } from '@bendyline/squisq-formats';
|
|
7
7
|
export { ConversionError, ConversionErrorCode, ConversionErrorOptions, ConversionResult, ConvertOptions, ConvertSource, FormatDefinition, FormatId, FormatRegistry, NormalizedInput } from '@bendyline/squisq-formats';
|
|
8
8
|
import { MarkdownDocument } from '@bendyline/squisq/markdown';
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* CLI format registry.
|
|
12
|
+
*
|
|
13
|
+
* The CLI extends the formats package's default registry with `mp4` and `gif`
|
|
14
|
+
* formats so `convert()` can produce rendered media like DOCX/PDF/HTML. These
|
|
15
|
+
* exports are Node-only (Playwright + FFmpeg), which is why they live here
|
|
16
|
+
* rather than in the browser-pure formats package.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
interface Mp4FormatOptions {
|
|
20
|
+
fps?: number;
|
|
21
|
+
quality?: VideoQuality;
|
|
22
|
+
orientation?: VideoOrientation;
|
|
23
|
+
width?: number;
|
|
24
|
+
height?: number;
|
|
25
|
+
captionStyle?: 'standard' | 'social';
|
|
26
|
+
coverPreRoll?: number;
|
|
27
|
+
animationsEnabled?: boolean;
|
|
28
|
+
}
|
|
29
|
+
/** Per-export options for `convert(..., 'gif')`. */
|
|
30
|
+
interface GifFormatOptions {
|
|
31
|
+
fps?: number;
|
|
32
|
+
orientation?: VideoOrientation;
|
|
33
|
+
width?: number;
|
|
34
|
+
height?: number;
|
|
35
|
+
captionStyle?: 'standard' | 'social';
|
|
36
|
+
coverPreRoll?: number;
|
|
37
|
+
animationsEnabled?: boolean;
|
|
38
|
+
loop?: number;
|
|
39
|
+
maxColors?: number;
|
|
40
|
+
dither?: GifDither;
|
|
41
|
+
bayerScale?: number;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Build the CLI's format registry: every built-in format from
|
|
45
|
+
* `@bendyline/squisq-formats` plus the CLI-only rendered-media exporters.
|
|
46
|
+
*/
|
|
47
|
+
declare function createCliRegistry(): FormatRegistry;
|
|
48
|
+
|
|
10
49
|
/**
|
|
11
50
|
* readInput
|
|
12
51
|
*
|
|
@@ -37,33 +76,95 @@ interface ReadInputResult {
|
|
|
37
76
|
/** Detected source format id (registry id, or `md`/`json`/`dbk`/`folder`). */
|
|
38
77
|
sourceFormat: FormatId;
|
|
39
78
|
}
|
|
79
|
+
interface ReadInputOptions {
|
|
80
|
+
/**
|
|
81
|
+
* Infer a Squisq theme from an OOXML source's theme part (PPTX today).
|
|
82
|
+
* Default true — the importer carries it as frontmatter.
|
|
83
|
+
*/
|
|
84
|
+
inferTheme?: boolean;
|
|
85
|
+
/** Derive custom layout templates from PPTX slide layouts. Default true. */
|
|
86
|
+
inferLayouts?: boolean;
|
|
87
|
+
}
|
|
40
88
|
/**
|
|
41
89
|
* Read input from a file path (markdown, JSON Doc, ZIP/DBK container, folder,
|
|
42
90
|
* or an importable binary format) and resolve it to a populated
|
|
43
91
|
* {@link ReadInputResult}.
|
|
44
92
|
*/
|
|
45
|
-
declare function readInput(inputPath: string): Promise<ReadInputResult>;
|
|
93
|
+
declare function readInput(inputPath: string, options?: ReadInputOptions): Promise<ReadInputResult>;
|
|
46
94
|
|
|
47
95
|
/**
|
|
48
|
-
*
|
|
96
|
+
* Native FFmpeg Encoder
|
|
97
|
+
*
|
|
98
|
+
* Encodes PNG frames to MP4 or animated GIF using a locally installed ffmpeg
|
|
99
|
+
* binary. Writes frames to a temporary directory, invokes ffmpeg as a child
|
|
100
|
+
* process, and reads the resulting media file.
|
|
49
101
|
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
* export is Node-only (it needs Playwright + FFmpeg), which is why it lives
|
|
53
|
-
* here in the CLI rather than in the browser-pure formats package.
|
|
102
|
+
* This is the Node fast path used after the CLI detects native FFmpeg. Browser
|
|
103
|
+
* callers use the WebCodecs/ffmpeg.wasm paths in the video packages instead.
|
|
54
104
|
*/
|
|
55
105
|
|
|
106
|
+
/** Options for native animated-GIF encoding. */
|
|
107
|
+
interface GifExportOptions {
|
|
108
|
+
/** Frames per second (default: 10; GIF timing is centisecond-based). */
|
|
109
|
+
fps?: number;
|
|
110
|
+
/** Output width in pixels (default: 960 landscape / 540 portrait). */
|
|
111
|
+
width?: number;
|
|
112
|
+
/** Output height in pixels (default: 540 landscape / 960 portrait). */
|
|
113
|
+
height?: number;
|
|
114
|
+
/** Viewport orientation used for default dimensions. */
|
|
115
|
+
orientation?: VideoOrientation;
|
|
116
|
+
/** Number of repeats; 0 loops forever and -1 disables looping. */
|
|
117
|
+
loop?: number;
|
|
118
|
+
/** Palette size, between 2 and 256 (default: 256). */
|
|
119
|
+
maxColors?: number;
|
|
120
|
+
/** Palette dithering algorithm (default: sierra2_4a). */
|
|
121
|
+
dither?: GifDither;
|
|
122
|
+
/** Bayer strength when dither is bayer (0-5, default: 3). */
|
|
123
|
+
bayerScale?: number;
|
|
124
|
+
/** Encoding progress callback. */
|
|
125
|
+
onProgress?: (percent: number, phase: string) => void;
|
|
126
|
+
}
|
|
127
|
+
/** Compression-friendly defaults for animated GIF output. */
|
|
128
|
+
declare const GIF_EXPORT_DEFAULTS: {
|
|
129
|
+
readonly fps: 10;
|
|
130
|
+
readonly width: 960;
|
|
131
|
+
readonly height: 540;
|
|
132
|
+
readonly loop: 0;
|
|
133
|
+
readonly maxColors: 256;
|
|
134
|
+
readonly dither: GifDither;
|
|
135
|
+
};
|
|
56
136
|
/**
|
|
57
|
-
*
|
|
58
|
-
*
|
|
137
|
+
* Encode frame PNGs to MP4 using native ffmpeg.
|
|
138
|
+
*
|
|
139
|
+
* @param ffmpegPath - Absolute path to the ffmpeg binary
|
|
140
|
+
* @param frames - Array of PNG image bytes (one per frame)
|
|
141
|
+
* @param audio - Optional audio file bytes to mux
|
|
142
|
+
* @param outputPath - Where to write the final MP4
|
|
143
|
+
* @param options - Encoding options (fps, quality, dimensions, progress)
|
|
59
144
|
*/
|
|
60
|
-
declare function
|
|
145
|
+
declare function framesToMp4Native(ffmpegPath: string, frames: Uint8Array[], audio: Uint8Array | null, outputPath: string, options?: VideoExportOptions): Promise<void>;
|
|
146
|
+
/**
|
|
147
|
+
* Encode frames using native ffmpeg and return the MP4 bytes (instead of writing to disk).
|
|
148
|
+
* Useful when the caller needs the bytes in memory.
|
|
149
|
+
*/
|
|
150
|
+
declare function framesToMp4NativeBytes(ffmpegPath: string, frames: Uint8Array[], audio: Uint8Array | null, options?: VideoExportOptions): Promise<Uint8Array>;
|
|
151
|
+
/**
|
|
152
|
+
* Encode PNG frames to an animated GIF using native FFmpeg.
|
|
153
|
+
*
|
|
154
|
+
* The shared palette graph uses changed-frame statistics and rectangle-scoped
|
|
155
|
+
* palette application so static slide regions remain stable and compress well.
|
|
156
|
+
* GIF has no audio track; callers should surface that limitation before calling.
|
|
157
|
+
*/
|
|
158
|
+
declare function framesToGifNative(ffmpegPath: string, frames: Uint8Array[], outputPath: string, options?: GifExportOptions): Promise<void>;
|
|
159
|
+
/** Encode frames with native FFmpeg and return animated-GIF bytes. */
|
|
160
|
+
declare function framesToGifNativeBytes(ffmpegPath: string, frames: Uint8Array[], options?: GifExportOptions): Promise<Uint8Array>;
|
|
61
161
|
|
|
62
162
|
/**
|
|
63
|
-
* Programmatic
|
|
163
|
+
* Programmatic Rendered-Media API
|
|
64
164
|
*
|
|
65
|
-
* Provides
|
|
66
|
-
* from Node.js callers (e.g., Qualla's pipeline). This avoids
|
|
165
|
+
* Provides library-style entry points for rendering Squisq documents to MP4
|
|
166
|
+
* or animated GIF from Node.js callers (e.g., Qualla's pipeline). This avoids
|
|
167
|
+
* the need to shell
|
|
67
168
|
* out to the `squisq video` CLI and gives callers full control over the Doc,
|
|
68
169
|
* MemoryContentContainer, and encoding options.
|
|
69
170
|
*
|
|
@@ -78,26 +179,39 @@ declare function createCliRegistry(): FormatRegistry;
|
|
|
78
179
|
* quality: 'normal',
|
|
79
180
|
* orientation: 'landscape',
|
|
80
181
|
* });
|
|
182
|
+
*
|
|
183
|
+
* await renderDocToGif(doc, container, {
|
|
184
|
+
* outputPath: '/tmp/output.gif',
|
|
185
|
+
* animationsEnabled: false,
|
|
186
|
+
* });
|
|
81
187
|
*/
|
|
82
188
|
|
|
189
|
+
/** Convert options with the CLI-only rendered-media adapters strongly typed. */
|
|
190
|
+
type CliConvertOptions = Omit<ConvertOptions, 'formatOptions'> & {
|
|
191
|
+
formatOptions?: ConvertOptions['formatOptions'] & {
|
|
192
|
+
mp4?: Mp4FormatOptions;
|
|
193
|
+
gif?: GifFormatOptions;
|
|
194
|
+
};
|
|
195
|
+
};
|
|
196
|
+
|
|
83
197
|
/**
|
|
84
198
|
* Convert a document to a target format using the CLI's format registry.
|
|
85
199
|
*
|
|
86
200
|
* This is a thin, pre-bound wrapper over `convert()` from
|
|
87
201
|
* `@bendyline/squisq-formats`: it injects the CLI registry (which adds the
|
|
88
|
-
* `mp4`
|
|
202
|
+
* `mp4` and `gif` formats on top of every built-in exporter) and a default
|
|
89
203
|
* `resolvePlayerScript` that lazily loads the standalone player IIFE bundle
|
|
90
204
|
* (required for HTML/EPUB-style exports). Callers may override either via
|
|
91
205
|
* `options`.
|
|
92
206
|
*
|
|
93
207
|
* @param source - A bytes / markdown / doc {@link ConvertSource}.
|
|
94
|
-
* @param to - Target format id (`docx`, `pdf`, `pptx`, `html`, `mp4`, …).
|
|
208
|
+
* @param to - Target format id (`docx`, `pdf`, `pptx`, `html`, `mp4`, `gif`, …).
|
|
95
209
|
* @param options - Conversion options; `registry` and `resolvePlayerScript`
|
|
96
210
|
* default to the CLI's values but can be overridden.
|
|
97
211
|
* @returns The encoded bytes plus mime type, suggested filename, and warnings.
|
|
98
212
|
* @throws {@link ConversionError} on any failure, with a stable `code`.
|
|
99
213
|
*/
|
|
100
|
-
declare function convert(source: ConvertSource, to: FormatId, options?:
|
|
214
|
+
declare function convert(source: ConvertSource, to: FormatId, options?: CliConvertOptions): Promise<ConversionResult>;
|
|
101
215
|
/** Options for renderDocToMp4. */
|
|
102
216
|
interface RenderDocToMp4Options {
|
|
103
217
|
/** Output file path for the MP4. */
|
|
@@ -114,6 +228,8 @@ interface RenderDocToMp4Options {
|
|
|
114
228
|
height?: number;
|
|
115
229
|
/** Caption style to bake into the video (default: none). */
|
|
116
230
|
captionStyle?: 'standard' | 'social';
|
|
231
|
+
/** Render layer animations and block transitions (default: true). */
|
|
232
|
+
animationsEnabled?: boolean;
|
|
117
233
|
/**
|
|
118
234
|
* Seconds of cover-slide pre-roll before the story starts (default: 0).
|
|
119
235
|
*
|
|
@@ -127,6 +243,35 @@ interface RenderDocToMp4Options {
|
|
|
127
243
|
*/
|
|
128
244
|
onProgress?: (phase: string, percent: number) => void;
|
|
129
245
|
}
|
|
246
|
+
/** Options for rendering a document to an animated GIF. */
|
|
247
|
+
interface RenderDocToGifOptions {
|
|
248
|
+
/** Output file path for the GIF. */
|
|
249
|
+
outputPath: string;
|
|
250
|
+
/** Frames per second (default: 10). */
|
|
251
|
+
fps?: number;
|
|
252
|
+
/** Viewport orientation (default: landscape). */
|
|
253
|
+
orientation?: VideoOrientation;
|
|
254
|
+
/** Override output width (default: 960 landscape / 540 portrait). */
|
|
255
|
+
width?: number;
|
|
256
|
+
/** Override output height (default: 540 landscape / 960 portrait). */
|
|
257
|
+
height?: number;
|
|
258
|
+
/** Caption style to bake into the GIF (default: none). */
|
|
259
|
+
captionStyle?: 'standard' | 'social';
|
|
260
|
+
/** Seconds of cover-slide pre-roll (default: 0). */
|
|
261
|
+
coverPreRoll?: number;
|
|
262
|
+
/** Render layer animations and block transitions (default: false). */
|
|
263
|
+
animationsEnabled?: boolean;
|
|
264
|
+
/** Number of repeats; 0 loops forever and -1 disables looping. */
|
|
265
|
+
loop?: number;
|
|
266
|
+
/** Palette size, from 2 through 256 (default: 256). */
|
|
267
|
+
maxColors?: number;
|
|
268
|
+
/** Palette dithering algorithm (default: sierra2_4a). */
|
|
269
|
+
dither?: GifDither;
|
|
270
|
+
/** Bayer strength when dither is bayer (0-5, default: 3). */
|
|
271
|
+
bayerScale?: number;
|
|
272
|
+
/** Progress callback. */
|
|
273
|
+
onProgress?: (phase: string, percent: number) => void;
|
|
274
|
+
}
|
|
130
275
|
/** Result returned by renderDocToMp4. */
|
|
131
276
|
interface RenderDocToMp4Result {
|
|
132
277
|
/** Duration of the rendered video in seconds (including pre-roll). */
|
|
@@ -136,24 +281,15 @@ interface RenderDocToMp4Result {
|
|
|
136
281
|
/** Output file path. */
|
|
137
282
|
outputPath: string;
|
|
138
283
|
}
|
|
139
|
-
/**
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
*
|
|
146
|
-
* Requires:
|
|
147
|
-
* - Playwright (chromium) — for headless frame capture
|
|
148
|
-
* - FFmpeg — for video encoding (resolved from SQUISQ_FFMPEG, PATH, or an
|
|
149
|
-
* optionally installed `ffmpeg-static` package — see detectFfmpeg)
|
|
150
|
-
*
|
|
151
|
-
* @param doc - The Doc structure to render
|
|
152
|
-
* @param container - MemoryContentContainer with audio/image files
|
|
153
|
-
* @param options - Rendering and encoding options
|
|
154
|
-
* @returns Result with duration and frame count
|
|
155
|
-
*/
|
|
284
|
+
/** Result returned by renderDocToGif. */
|
|
285
|
+
interface RenderDocToGifResult extends RenderDocToMp4Result {
|
|
286
|
+
/** Non-fatal fidelity warnings, including GIF's lack of audio. */
|
|
287
|
+
warnings: string[];
|
|
288
|
+
}
|
|
289
|
+
/** Render a Doc + media container to an MP4 video file. */
|
|
156
290
|
declare function renderDocToMp4(doc: Doc, container: ContentContainer, options: RenderDocToMp4Options): Promise<RenderDocToMp4Result>;
|
|
291
|
+
/** Render a Doc + media container to a silent animated GIF. */
|
|
292
|
+
declare function renderDocToGif(doc: Doc, container: ContentContainer, options: RenderDocToGifOptions): Promise<RenderDocToGifResult>;
|
|
157
293
|
/** A thumbnail size specification. */
|
|
158
294
|
interface ThumbnailSpec {
|
|
159
295
|
/** Label for the thumbnail (used in filename: `{slug}-{width}x{height}.jpg`). */
|
|
@@ -184,4 +320,4 @@ interface ExtractThumbnailsOptions {
|
|
|
184
320
|
*/
|
|
185
321
|
declare function extractThumbnails(options: ExtractThumbnailsOptions): Promise<void>;
|
|
186
322
|
|
|
187
|
-
export { type ExtractThumbnailsOptions, type ReadInputResult, type RenderDocToMp4Options, type RenderDocToMp4Result, type ThumbnailSpec, convert, createCliRegistry, extractThumbnails, readInput, renderDocToMp4 };
|
|
323
|
+
export { type CliConvertOptions, type ExtractThumbnailsOptions, GIF_EXPORT_DEFAULTS, type GifExportOptions, type GifFormatOptions, type Mp4FormatOptions, type ReadInputResult, type RenderDocToGifOptions, type RenderDocToGifResult, type RenderDocToMp4Options, type RenderDocToMp4Result, type ThumbnailSpec, convert, createCliRegistry, extractThumbnails, framesToGifNative, framesToGifNativeBytes, framesToMp4Native, framesToMp4NativeBytes, readInput, renderDocToGif, renderDocToMp4 };
|