@bendyline/squisq-cli 1.0.0 → 1.0.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.
@@ -0,0 +1,253 @@
1
+ /**
2
+ * video command
3
+ *
4
+ * Renders a squisq document to MP4 video by:
5
+ * 1. Parsing the input (markdown, container, or folder)
6
+ * 2. Generating a self-contained render HTML
7
+ * 3. Capturing frames via Playwright headless browser
8
+ * 4. Encoding to MP4 using native ffmpeg (fast) or ffmpeg.wasm (fallback)
9
+ *
10
+ * Usage:
11
+ * squisq video <input> [-o output.mp4] [--fps 30] [--quality normal] [--orientation landscape]
12
+ */
13
+ import { mkdir } from 'node:fs/promises';
14
+ import { dirname, basename, extname, resolve } from 'node:path';
15
+ import { readInput } from '../util/readInput.js';
16
+ import { detectFfmpeg } from '../util/detectFfmpeg.js';
17
+ const VALID_QUALITIES = ['draft', 'normal', 'high'];
18
+ const VALID_ORIENTATIONS = ['landscape', 'portrait'];
19
+ const VALID_CAPTIONS = ['off', 'standard', 'social'];
20
+ export function registerVideoCommand(program) {
21
+ program
22
+ .command('video')
23
+ .description('Render a squisq document to MP4 video')
24
+ .argument('<input>', 'Path to .md file, .zip/.dbk container, or folder')
25
+ .argument('[output]', 'Output MP4 path (default: <input>.mp4)')
26
+ .option('-o, --output <path>', 'Output MP4 path (default: <input>.mp4)')
27
+ .option('--fps <number>', 'Frames per second (default: 30)', '30')
28
+ .option('--quality <level>', `Encoding quality: ${VALID_QUALITIES.join(', ')} (default: normal)`, 'normal')
29
+ .option('--orientation <orient>', `Video orientation: ${VALID_ORIENTATIONS.join(', ')} (default: landscape)`, 'landscape')
30
+ .option('--captions <style>', `Caption style: ${VALID_CAPTIONS.join(', ')} (default: off)`, 'off')
31
+ .option('--width <pixels>', 'Override video width')
32
+ .option('--height <pixels>', 'Override video height')
33
+ .action(async (inputPath, outputArg, opts) => {
34
+ try {
35
+ // Positional output arg takes precedence, then -o flag
36
+ if (outputArg && !opts.output) {
37
+ opts.output = outputArg;
38
+ }
39
+ await runVideo(inputPath, opts);
40
+ }
41
+ catch (err) {
42
+ const message = err instanceof Error ? err.message : String(err);
43
+ console.error(`Error: ${message}`);
44
+ process.exitCode = 1;
45
+ }
46
+ });
47
+ }
48
+ async function runVideo(inputPath, opts) {
49
+ const resolvedInput = resolve(inputPath);
50
+ // Validate options
51
+ const fps = parseInt(opts.fps ?? '30', 10);
52
+ if (isNaN(fps) || fps < 1 || fps > 120) {
53
+ throw new Error('FPS must be a number between 1 and 120');
54
+ }
55
+ const quality = opts.quality ?? 'normal';
56
+ if (!VALID_QUALITIES.includes(quality)) {
57
+ throw new Error(`Invalid quality "${quality}". Valid: ${VALID_QUALITIES.join(', ')}`);
58
+ }
59
+ const orientation = opts.orientation ?? 'landscape';
60
+ if (!VALID_ORIENTATIONS.includes(orientation)) {
61
+ throw new Error(`Invalid orientation "${orientation}". Valid: ${VALID_ORIENTATIONS.join(', ')}`);
62
+ }
63
+ const captions = opts.captions ?? 'off';
64
+ if (!VALID_CAPTIONS.includes(captions)) {
65
+ throw new Error(`Invalid captions "${captions}". Valid: ${VALID_CAPTIONS.join(', ')}`);
66
+ }
67
+ const captionStyle = captions === 'off' ? undefined : captions;
68
+ // Determine output path
69
+ const inputBasename = basename(resolvedInput);
70
+ const inputExt = extname(inputBasename);
71
+ const baseName = inputExt ? inputBasename.slice(0, -inputExt.length) : inputBasename;
72
+ const outputPath = opts.output
73
+ ? resolve(opts.output)
74
+ : resolve(dirname(resolvedInput), `${baseName}.mp4`);
75
+ // Ensure output directory exists
76
+ await mkdir(dirname(outputPath), { recursive: true });
77
+ // ── Step 1: Read input ──────────────────────────────────────────
78
+ console.error(`Reading: ${resolvedInput}`);
79
+ const { container, markdownDoc } = await readInput(resolvedInput);
80
+ // ── Step 2: Parse to Doc ────────────────────────────────────────
81
+ const { markdownToDoc } = await import('@bendyline/squisq/doc');
82
+ const doc = markdownToDoc(markdownDoc);
83
+ // ── Step 3: Collect media from container ────────────────────────
84
+ const { collectImagePaths } = await import('@bendyline/squisq-formats/html');
85
+ const imagePaths = collectImagePaths(doc);
86
+ const images = new Map();
87
+ for (const imgPath of imagePaths) {
88
+ const data = await container.readFile(imgPath);
89
+ if (data) {
90
+ images.set(imgPath, data);
91
+ }
92
+ }
93
+ // Collect audio segments
94
+ const audio = new Map();
95
+ let concatenatedAudio = null;
96
+ if (doc.audio?.segments?.length) {
97
+ for (const seg of doc.audio.segments) {
98
+ const data = await container.readFile(seg.src);
99
+ if (data) {
100
+ audio.set(seg.src, data);
101
+ // Also map by name for the audio URL rewriting in the player
102
+ audio.set(seg.name, data);
103
+ }
104
+ }
105
+ // For encoding, concatenate audio segments into one file
106
+ // The player handles segment playback internally, but the encoder
107
+ // needs a single audio track. We'll use the first segment as a
108
+ // representative — full audio concatenation would need ffmpeg.
109
+ // For now, pass audio map to the render HTML so the player handles it.
110
+ if (audio.size > 0) {
111
+ // Use the first segment's raw bytes — the encoder will handle it
112
+ const firstSeg = doc.audio.segments[0];
113
+ const firstData = await container.readFile(firstSeg.src);
114
+ if (firstData) {
115
+ concatenatedAudio = new Uint8Array(firstData);
116
+ }
117
+ }
118
+ }
119
+ // ── Step 4: Generate render HTML ────────────────────────────────
120
+ const { generateRenderHtml } = await import('@bendyline/squisq-video');
121
+ const { PLAYER_BUNDLE } = await import('@bendyline/squisq-react/standalone-source');
122
+ const { resolveDimensions } = await import('@bendyline/squisq-video');
123
+ const dimensions = resolveDimensions({
124
+ orientation,
125
+ width: opts.width ? parseInt(opts.width, 10) : undefined,
126
+ height: opts.height ? parseInt(opts.height, 10) : undefined,
127
+ });
128
+ const renderHtml = generateRenderHtml(doc, {
129
+ playerScript: PLAYER_BUNDLE,
130
+ images,
131
+ audio: audio.size > 0 ? audio : undefined,
132
+ width: dimensions.width,
133
+ height: dimensions.height,
134
+ captionStyle,
135
+ });
136
+ console.error(`Viewport: ${dimensions.width}x${dimensions.height}, ${fps} fps, quality: ${quality}, captions: ${captions}`);
137
+ // ── Step 5: Capture frames via Playwright ───────────────────────
138
+ const { chromium } = await import('playwright-core');
139
+ const browser = await chromium.launch({ headless: true });
140
+ const page = await browser.newPage({
141
+ viewport: { width: dimensions.width, height: dimensions.height },
142
+ });
143
+ // Capture page errors so they don't vanish silently
144
+ const pageErrors = [];
145
+ page.on('pageerror', (err) => pageErrors.push(err.message));
146
+ page.on('console', (msg) => {
147
+ if (msg.type() === 'error')
148
+ pageErrors.push(msg.text());
149
+ });
150
+ // Load the render HTML — use 'load' since everything is inline (no network)
151
+ await page.setContent(renderHtml, { waitUntil: 'load' });
152
+ // Give React one frame to mount and run useEffect
153
+ await page.waitForTimeout(500);
154
+ // Wait for the render API to be available
155
+ try {
156
+ await page.waitForFunction(() => typeof window.getDuration === 'function', { timeout: 15000 });
157
+ }
158
+ catch {
159
+ await browser.close();
160
+ const errorDetail = pageErrors.length
161
+ ? `\nPage errors:\n ${pageErrors.join('\n ')}`
162
+ : '\nNo page errors captured — the player may have failed to mount.';
163
+ throw new Error(`Render API did not initialize within 15 seconds.${errorDetail}`);
164
+ }
165
+ // Get duration from the player
166
+ const duration = await page.evaluate(() => {
167
+ return window.getDuration();
168
+ });
169
+ if (duration <= 0) {
170
+ await browser.close();
171
+ throw new Error('Document has zero duration — nothing to render');
172
+ }
173
+ const totalFrames = Math.ceil(duration * fps);
174
+ console.error(`Duration: ${duration.toFixed(1)}s, ${totalFrames} frames to capture`);
175
+ const frames = [];
176
+ const frameInterval = 1 / fps;
177
+ // Optional: render cover frame (time 0)
178
+ const hasCover = await page.evaluate(() => {
179
+ const w = window;
180
+ return typeof w.hasCoverBlock === 'function' ? w.hasCoverBlock() : false;
181
+ });
182
+ if (hasCover) {
183
+ const coverFrameCount = 2 * fps;
184
+ await page.evaluate(() => {
185
+ window.showCover();
186
+ });
187
+ await page.waitForTimeout(100);
188
+ const coverScreenshot = await page.screenshot({ type: 'png' });
189
+ const coverFrame = new Uint8Array(coverScreenshot);
190
+ for (let i = 0; i < coverFrameCount; i++) {
191
+ frames.push(coverFrame);
192
+ }
193
+ await page.evaluate(() => {
194
+ window.hideCover();
195
+ });
196
+ writeProgress('Capturing', coverFrameCount, totalFrames + coverFrameCount);
197
+ }
198
+ // Capture animation frames
199
+ const totalWithCover = totalFrames + frames.length;
200
+ for (let i = 0; i < totalFrames; i++) {
201
+ const time = i * frameInterval;
202
+ await page.evaluate((t) => {
203
+ return window.seekTo(t);
204
+ }, time);
205
+ const screenshot = await page.screenshot({ type: 'png' });
206
+ frames.push(new Uint8Array(screenshot));
207
+ if (i % Math.max(1, Math.floor(fps / 2)) === 0 || i === totalFrames - 1) {
208
+ writeProgress('Capturing', frames.length, totalWithCover);
209
+ }
210
+ }
211
+ clearProgress();
212
+ await browser.close();
213
+ // ── Step 6: Encode to MP4 ───────────────────────────────────────
214
+ const ffmpegPath = await detectFfmpeg();
215
+ const exportOptions = {
216
+ fps,
217
+ quality: quality,
218
+ orientation: orientation,
219
+ width: dimensions.width,
220
+ height: dimensions.height,
221
+ onProgress: (percent, phase) => {
222
+ writeProgress('Encoding', percent, 100, phase);
223
+ },
224
+ };
225
+ if (ffmpegPath) {
226
+ console.error(`Using native ffmpeg: ${ffmpegPath}`);
227
+ const { framesToMp4Native } = await import('../util/nativeEncoder.js');
228
+ await framesToMp4Native(ffmpegPath, frames, concatenatedAudio, outputPath, exportOptions);
229
+ }
230
+ else {
231
+ throw new Error('ffmpeg is required but not found in PATH.\n' +
232
+ 'Install it with:\n' +
233
+ ' macOS: brew install ffmpeg\n' +
234
+ ' Ubuntu: sudo apt install ffmpeg\n' +
235
+ ' Windows: winget install ffmpeg');
236
+ }
237
+ clearProgress();
238
+ console.error(` ✓ ${outputPath}`);
239
+ console.error('Done.');
240
+ }
241
+ // ── Progress helpers ──────────────────────────────────────────────
242
+ const BAR_WIDTH = 30;
243
+ function writeProgress(label, current, total, detail) {
244
+ const pct = Math.min(100, Math.round((current / total) * 100));
245
+ const filled = Math.round((pct / 100) * BAR_WIDTH);
246
+ const bar = '█'.repeat(filled) + '░'.repeat(BAR_WIDTH - filled);
247
+ const suffix = detail ? ` (${detail})` : '';
248
+ process.stderr.write(`\r ${label}: ${bar} ${pct}%${suffix} `);
249
+ }
250
+ function clearProgress() {
251
+ process.stderr.write('\r' + ' '.repeat(80) + '\r');
252
+ }
253
+ //# sourceMappingURL=video.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"video.js","sourceRoot":"","sources":["../../src/commands/video.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,2 +1,12 @@
1
-
2
- export { }
1
+ /**
2
+ * squisq CLI
3
+ *
4
+ * Command-line tool for converting and processing Squisq documents.
5
+ * Designed for easy addition of future subcommands (e.g., import).
6
+ *
7
+ * Usage:
8
+ * squisq convert <input> [options]
9
+ * squisq --help
10
+ */
11
+ export {};
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG"}