@bendyline/squisq-cli 2.9.30 → 2.9.32

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/index.js CHANGED
@@ -313,8 +313,15 @@ async function runConvert(inputPath, opts) {
313
313
  }
314
314
 
315
315
  // src/commands/video.ts
316
- import { mkdir as mkdir2 } from "fs/promises";
316
+ import { mkdir as mkdir2, writeFile as writeFile2 } from "fs/promises";
317
317
  import { dirname as dirname2, basename as basename2, extname as extname2, resolve as resolve2 } from "path";
318
+ import {
319
+ docChapters,
320
+ formatCaptionsSrt,
321
+ formatCaptionsVtt,
322
+ formatChaptersFfmetadata,
323
+ formatChaptersText
324
+ } from "@bendyline/squisq/timing";
318
325
  import { validateVideoExportOptions } from "@bendyline/squisq-video";
319
326
  var VALID_QUALITIES = ["draft", "normal", "high"];
320
327
  var VALID_ORIENTATIONS = ["landscape", "portrait"];
@@ -360,6 +367,12 @@ function registerVideoCommand(program2) {
360
367
  ).option(
361
368
  "--resume",
362
369
  "MP4 only: reuse frames an identical earlier render spooled into --frames-dir"
370
+ ).option(
371
+ "--captions-file <path>",
372
+ "Also write the captions as a sidecar file: .srt, or .vtt (WebVTT) by extension"
373
+ ).option(
374
+ "--chapters-file <path>",
375
+ "Also write the chapters: .txt as a timestamp list, otherwise FFmpeg metadata"
363
376
  ).option("--animations", "Enable slide animations/transitions (GIF default: disabled)").option("--no-animations", "Disable slide animations/transitions").option("--loop <count>", "GIF repeat count: 0 forever, -1 no loop (default: 0)").option("--max-colors <count>", "GIF palette size from 2 to 256 (default: 256)").option(
364
377
  "--dither <algorithm>",
365
378
  `GIF dithering: ${VALID_GIF_DITHERS.join(", ")} (default: sierra2_4a)`
@@ -477,7 +490,12 @@ async function runVideo(inputPath, opts) {
477
490
  const inputExt = extname2(inputBasename);
478
491
  const baseName = inputExt ? inputBasename.slice(0, -inputExt.length) : inputBasename;
479
492
  const outputPath = opts.output ? resolve2(opts.output) : resolve2(dirname2(resolvedInput), `${baseName}.${outputFormat}`);
480
- await assertOutputsWritable([outputPath], opts.overwrite);
493
+ const captionsPath = opts.captionsFile ? resolve2(opts.captionsFile) : void 0;
494
+ const chaptersPath = opts.chaptersFile ? resolve2(opts.chaptersFile) : void 0;
495
+ await assertOutputsWritable(
496
+ [outputPath, captionsPath, chaptersPath].filter((path) => !!path),
497
+ opts.overwrite
498
+ );
481
499
  await mkdir2(dirname2(outputPath), { recursive: true });
482
500
  console.error(`Reading: ${resolvedInput}`);
483
501
  const result = await readInput(resolvedInput);
@@ -546,6 +564,26 @@ async function runVideo(inputPath, opts) {
546
564
  console.error(
547
565
  ` \u2713 ${outputPath} (${result2.duration.toFixed(1)}s, ${result2.frameCount} frames${reused})`
548
566
  );
567
+ if (captionsPath) {
568
+ const format = extname2(captionsPath).toLowerCase() === ".vtt" ? formatCaptionsVtt : formatCaptionsSrt;
569
+ const phrases = doc.captions?.phrases.length ?? 0;
570
+ await mkdir2(dirname2(captionsPath), { recursive: true });
571
+ await writeFile2(captionsPath, format(doc.captions, { offset: coverPreRoll }), "utf8");
572
+ console.error(
573
+ phrases ? ` \u2713 ${captionsPath} (${phrases} captions)` : ` \u26A0 ${captionsPath} is empty: the document has no captions to write`
574
+ );
575
+ }
576
+ if (chaptersPath) {
577
+ const chapters = docChapters(doc, { offset: coverPreRoll });
578
+ await mkdir2(dirname2(chaptersPath), { recursive: true });
579
+ await writeFile2(
580
+ chaptersPath,
581
+ extname2(chaptersPath).toLowerCase() === ".txt" ? `${formatChaptersText(chapters)}
582
+ ` : formatChaptersFfmetadata(chapters, result2.duration),
583
+ "utf8"
584
+ );
585
+ console.error(` \u2713 ${chaptersPath} (${chapters.length} chapters)`);
586
+ }
549
587
  console.error("Done.");
550
588
  }
551
589
  var BAR_WIDTH = 30;