@bendyline/squisq-video 2.3.12 → 2.3.13

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.d.ts CHANGED
@@ -510,4 +510,21 @@ declare function ffmpegGifOutputArgs(options: GifOutputOptions): string[];
510
510
  */
511
511
  declare function framesToMp4Wasm(frames: Uint8Array[], audio: Uint8Array | null, options?: VideoExportOptions): Promise<EncoderResult>;
512
512
 
513
- export { type AudioTimelineClip, type ComputeAudioTimelineOptions, DASHBOARD_RESOLUTIONS, DEFAULT_DASHBOARD_RESOLUTION, type DashboardResolutionId, type DashboardResolutionPreset, type EncoderResult, FFMPEG_WASM_SETUP_HINT, type FfmpegWasmLoadConfig, type GifDither, type GifFilterOptions, type GifOutputOptions, MAX_DASHBOARD_IMAGE_DIMENSION, MAX_DASHBOARD_IMAGE_PIXELS, MIN_DASHBOARD_IMAGE_DIMENSION, ORIENTATION_DIMENSIONS, QUALITY_PRESETS, type QualityPreset, type RenderHtmlOptions, type ResolveDashboardDimensionsInput, type ResolvedDashboardDimensions, type VideoExportOptions, type VideoOrientation, type VideoQuality, audioBitrateArg, bitrateForQuality, computeAudioTimeline, dashboardFamilyForDimensions, ffmpegAudioMuxArgs, ffmpegGifFilterGraph, ffmpegGifOutputArgs, ffmpegGifPaletteApplicationArgs, ffmpegGifPaletteApplicationGraph, ffmpegGifPaletteGenerationFilter, ffmpegVideoQualityArgs, framesToMp4Wasm, generateRenderHtml, resolveDashboardDimensions, resolveDimensions, resolveFfmpegWasmLoad, validateDashboardImageDimensions, validateVideoExportOptions };
513
+ /**
514
+ * Frame clock — the one place that turns a frame index into a timeline time.
515
+ *
516
+ * Every offline capture path (CLI pipe/memory transports, browser export)
517
+ * must agree on which instant a frame shows, otherwise a resumed or
518
+ * deduplicated render drifts from a fresh one. `i / fps` in floating point is
519
+ * not exactly reproducible across code paths, so the time is rounded to a
520
+ * microsecond: `frameTimeSeconds(370, 30)` equals `frameTimeSeconds(37, 3)`.
521
+ *
522
+ * Contract: a frame's pixels are a function of its time only. Consumers seek
523
+ * the player to this time and pause every animation before capturing.
524
+ */
525
+ /** Timeline second shown by frame `index` at `fps`, rounded to a microsecond. */
526
+ declare function frameTimeSeconds(index: number, fps: number): number;
527
+ /** Number of frames needed to cover `durationSeconds` at `fps` (partial frames round up). */
528
+ declare function frameCountFor(durationSeconds: number, fps: number): number;
529
+
530
+ export { type AudioTimelineClip, type ComputeAudioTimelineOptions, DASHBOARD_RESOLUTIONS, DEFAULT_DASHBOARD_RESOLUTION, type DashboardResolutionId, type DashboardResolutionPreset, type EncoderResult, FFMPEG_WASM_SETUP_HINT, type FfmpegWasmLoadConfig, type GifDither, type GifFilterOptions, type GifOutputOptions, MAX_DASHBOARD_IMAGE_DIMENSION, MAX_DASHBOARD_IMAGE_PIXELS, MIN_DASHBOARD_IMAGE_DIMENSION, ORIENTATION_DIMENSIONS, QUALITY_PRESETS, type QualityPreset, type RenderHtmlOptions, type ResolveDashboardDimensionsInput, type ResolvedDashboardDimensions, type VideoExportOptions, type VideoOrientation, type VideoQuality, audioBitrateArg, bitrateForQuality, computeAudioTimeline, dashboardFamilyForDimensions, ffmpegAudioMuxArgs, ffmpegGifFilterGraph, ffmpegGifOutputArgs, ffmpegGifPaletteApplicationArgs, ffmpegGifPaletteApplicationGraph, ffmpegGifPaletteGenerationFilter, ffmpegVideoQualityArgs, frameCountFor, frameTimeSeconds, framesToMp4Wasm, generateRenderHtml, resolveDashboardDimensions, resolveDimensions, resolveFfmpegWasmLoad, validateDashboardImageDimensions, validateVideoExportOptions };
package/dist/index.js CHANGED
@@ -222,6 +222,10 @@ function generateRenderHtml(doc, options) {
222
222
  const imageMapJson = escapeForScript(JSON.stringify(imageMap));
223
223
  const audioMapJson = hasAudio ? escapeForScript(JSON.stringify(audioMap)) : "null";
224
224
  const playerOptionLines = [
225
+ // Always pin the composed viewport to the export size. The page also
226
+ // pins #squisq-root to it, but an explicit viewport is what stops
227
+ // portrait/custom renders from falling back to the landscape preset.
228
+ ` viewport: ${JSON.stringify({ width, height })}`,
225
229
  ` animationsEnabled: ${JSON.stringify(animationsEnabled)}`,
226
230
  captionStyle ? ` captionStyle: ${JSON.stringify(captionStyle)}` : null,
227
231
  theme ? ` theme: ${escapeForScript(JSON.stringify(theme))}` : null,
@@ -512,6 +516,26 @@ async function framesToMp4Wasm(frames, audio, options = {}) {
512
516
  ffmpeg.terminate();
513
517
  }
514
518
  }
519
+
520
+ // src/frameClock.ts
521
+ function frameTimeSeconds(index, fps) {
522
+ if (!Number.isSafeInteger(index) || index < 0) {
523
+ throw new RangeError("Frame index must be a non-negative integer.");
524
+ }
525
+ if (!Number.isFinite(fps) || fps <= 0) {
526
+ throw new RangeError("Frames per second must be a positive number.");
527
+ }
528
+ return Math.round(index * 1e6 / fps) / 1e6;
529
+ }
530
+ function frameCountFor(durationSeconds, fps) {
531
+ if (!Number.isFinite(durationSeconds) || durationSeconds < 0) {
532
+ throw new RangeError("Duration must be a non-negative number of seconds.");
533
+ }
534
+ if (!Number.isFinite(fps) || fps <= 0) {
535
+ throw new RangeError("Frames per second must be a positive number.");
536
+ }
537
+ return Math.max(0, Math.ceil(durationSeconds * fps - 1e-9)) + 0;
538
+ }
515
539
  export {
516
540
  DASHBOARD_RESOLUTIONS,
517
541
  DEFAULT_DASHBOARD_RESOLUTION,
@@ -533,6 +557,8 @@ export {
533
557
  ffmpegGifPaletteApplicationGraph,
534
558
  ffmpegGifPaletteGenerationFilter,
535
559
  ffmpegVideoQualityArgs,
560
+ frameCountFor,
561
+ frameTimeSeconds,
536
562
  framesToMp4Wasm,
537
563
  generateRenderHtml,
538
564
  resolveDashboardDimensions,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bendyline/squisq-video",
3
- "version": "2.3.12",
3
+ "version": "2.3.13",
4
4
  "description": "Cross-runtime video and animated-GIF helpers with browser-based ffmpeg.wasm encoding for Squisq documents",
5
5
  "license": "MIT",
6
6
  "author": "Bendyline",