@bendyline/squisq-video 2.2.0 → 2.2.2
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 +1 -1
- package/THIRD_PARTY_LICENSES.txt +8 -0
- package/dist/index.d.ts +7 -1
- package/dist/index.js +42 -4
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@ npm install @bendyline/squisq-video
|
|
|
22
22
|
| `computeAudioTimeline(doc, coverPreRoll?)` | Flatten a doc's narration + timed media into absolute-timed audio clips (browser export and CLI mix share this) |
|
|
23
23
|
| `bitrateForQuality(quality, width, height)` | Target H.264 bitrate (`w*h*bitsPerPixel`) — the single source of truth for WebCodecs bitrate |
|
|
24
24
|
| `ffmpegVideoQualityArgs`, `audioBitrateArg`, `ffmpegAudioMuxArgs` | Shared FFmpeg flags; audio muxing pads short narration so it cannot truncate the video |
|
|
25
|
-
| `ffmpegGifFilterGraph`, `ffmpegGifOutputArgs`
|
|
25
|
+
| `ffmpegGifFilterGraph`, `ffmpegGifOutputArgs`, `ffmpegGifPalette*` helpers | Shared global-palette GIF filters, including bounded two-pass palette generation/application |
|
|
26
26
|
| `QUALITY_PRESETS`, `ORIENTATION_DIMENSIONS`, `resolveDimensions` | Quality/dimension presets and helpers |
|
|
27
27
|
| `validateVideoExportOptions(options)` | Fail-fast runtime validation for FPS, dimensions, quality, and orientation |
|
|
28
28
|
| `VideoExportOptions`, `VideoQuality`, `VideoOrientation`, `GifDither`, `QualityPreset`, `EncoderResult` | Shared video and GIF types |
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
THIRD-PARTY LICENSES FOR @bendyline/squisq-video
|
|
2
|
+
|
|
3
|
+
Generated from the actual esbuild input graph. Package-local license, copying,
|
|
4
|
+
and notice files are reproduced verbatim. When an npm tarball omits its
|
|
5
|
+
repository license, the pinned upstream copy is vendored and identified below.
|
|
6
|
+
|
|
7
|
+
COMPONENTS
|
|
8
|
+
|
package/dist/index.d.ts
CHANGED
|
@@ -296,6 +296,12 @@ declare function audioBitrateArg(quality: VideoQuality): string;
|
|
|
296
296
|
* audio longer than the video is trimmed while shorter audio becomes silence.
|
|
297
297
|
*/
|
|
298
298
|
declare function ffmpegAudioMuxArgs(bitrate: string | number): string[];
|
|
299
|
+
/** First pass of the bounded-memory GIF workflow: video -> one palette image. */
|
|
300
|
+
declare function ffmpegGifPaletteGenerationFilter(options: GifFilterOptions): string;
|
|
301
|
+
/** Second pass of the bounded-memory GIF workflow: video + palette -> GIF frames. */
|
|
302
|
+
declare function ffmpegGifPaletteApplicationGraph(options: GifFilterOptions): string;
|
|
303
|
+
/** Output arguments for the second, two-input pass of GIF encoding. */
|
|
304
|
+
declare function ffmpegGifPaletteApplicationArgs(options: GifOutputOptions): string[];
|
|
299
305
|
/**
|
|
300
306
|
* Build a high-quality, compression-friendly GIF palette filter graph.
|
|
301
307
|
*
|
|
@@ -327,4 +333,4 @@ declare function ffmpegGifOutputArgs(options: GifOutputOptions): string[];
|
|
|
327
333
|
*/
|
|
328
334
|
declare function framesToMp4Wasm(frames: Uint8Array[], audio: Uint8Array | null, options?: VideoExportOptions): Promise<EncoderResult>;
|
|
329
335
|
|
|
330
|
-
export { type AudioTimelineClip, type EncoderResult, FFMPEG_WASM_SETUP_HINT, type FfmpegWasmLoadConfig, type GifDither, type GifFilterOptions, type GifOutputOptions, ORIENTATION_DIMENSIONS, QUALITY_PRESETS, type QualityPreset, type RenderHtmlOptions, type VideoExportOptions, type VideoOrientation, type VideoQuality, audioBitrateArg, bitrateForQuality, computeAudioTimeline, ffmpegAudioMuxArgs, ffmpegGifFilterGraph, ffmpegGifOutputArgs, ffmpegVideoQualityArgs, framesToMp4Wasm, generateRenderHtml, resolveDimensions, resolveFfmpegWasmLoad, validateVideoExportOptions };
|
|
336
|
+
export { type AudioTimelineClip, type EncoderResult, FFMPEG_WASM_SETUP_HINT, type FfmpegWasmLoadConfig, type GifDither, type GifFilterOptions, type GifOutputOptions, ORIENTATION_DIMENSIONS, QUALITY_PRESETS, type QualityPreset, type RenderHtmlOptions, type VideoExportOptions, type VideoOrientation, type VideoQuality, audioBitrateArg, bitrateForQuality, computeAudioTimeline, ffmpegAudioMuxArgs, ffmpegGifFilterGraph, ffmpegGifOutputArgs, ffmpegGifPaletteApplicationArgs, ffmpegGifPaletteApplicationGraph, ffmpegGifPaletteGenerationFilter, ffmpegVideoQualityArgs, framesToMp4Wasm, generateRenderHtml, resolveDimensions, resolveFfmpegWasmLoad, validateVideoExportOptions };
|
package/dist/index.js
CHANGED
|
@@ -205,7 +205,7 @@ function audioBitrateArg(quality) {
|
|
|
205
205
|
function ffmpegAudioMuxArgs(bitrate) {
|
|
206
206
|
return ["-c:a", "aac", "-b:a", String(bitrate), "-af", "apad", "-shortest"];
|
|
207
207
|
}
|
|
208
|
-
function
|
|
208
|
+
function resolveGifFilterOptions(options) {
|
|
209
209
|
const { width, height } = options;
|
|
210
210
|
const maxColors = options.maxColors ?? 256;
|
|
211
211
|
const dither = options.dither ?? "sierra2_4a";
|
|
@@ -227,14 +227,49 @@ function ffmpegGifFilterGraph(options) {
|
|
|
227
227
|
if (!Number.isSafeInteger(bayerScale) || bayerScale < 0 || bayerScale > 5) {
|
|
228
228
|
throw new RangeError("GIF bayerScale must be an integer between 0 and 5.");
|
|
229
229
|
}
|
|
230
|
-
|
|
231
|
-
|
|
230
|
+
return {
|
|
231
|
+
width,
|
|
232
|
+
height,
|
|
233
|
+
maxColors,
|
|
234
|
+
ditherArgs: dither === "bayer" ? `dither=bayer:bayer_scale=${bayerScale}` : `dither=${dither}`
|
|
235
|
+
};
|
|
232
236
|
}
|
|
233
|
-
function
|
|
237
|
+
function gifScaleFilter({ width, height }) {
|
|
238
|
+
return `scale=${width}:${height}:force_original_aspect_ratio=decrease:flags=lanczos,pad=${width}:${height}:(ow-iw)/2:(oh-ih)/2:black`;
|
|
239
|
+
}
|
|
240
|
+
function ffmpegGifPaletteGenerationFilter(options) {
|
|
241
|
+
const resolved = resolveGifFilterOptions(options);
|
|
242
|
+
return `${gifScaleFilter(resolved)},palettegen=stats_mode=diff:max_colors=${resolved.maxColors}:reserve_transparent=0`;
|
|
243
|
+
}
|
|
244
|
+
function ffmpegGifPaletteApplicationGraph(options) {
|
|
245
|
+
const resolved = resolveGifFilterOptions(options);
|
|
246
|
+
return `[0:v]${gifScaleFilter(resolved)}[gif_frames];[gif_frames][1:v]paletteuse=${resolved.ditherArgs}:diff_mode=rectangle[gif_out]`;
|
|
247
|
+
}
|
|
248
|
+
function ffmpegGifPaletteApplicationArgs(options) {
|
|
249
|
+
const loop = resolveGifLoop(options);
|
|
250
|
+
return [
|
|
251
|
+
"-filter_complex",
|
|
252
|
+
ffmpegGifPaletteApplicationGraph(options),
|
|
253
|
+
"-map",
|
|
254
|
+
"[gif_out]",
|
|
255
|
+
"-an",
|
|
256
|
+
"-loop",
|
|
257
|
+
String(loop)
|
|
258
|
+
];
|
|
259
|
+
}
|
|
260
|
+
function ffmpegGifFilterGraph(options) {
|
|
261
|
+
const resolved = resolveGifFilterOptions(options);
|
|
262
|
+
return `[0:v]${gifScaleFilter(resolved)},split[gif_frames][gif_palette_source];[gif_palette_source]palettegen=stats_mode=diff:max_colors=${resolved.maxColors}:reserve_transparent=0[gif_palette];[gif_frames][gif_palette]paletteuse=${resolved.ditherArgs}:diff_mode=rectangle[gif_out]`;
|
|
263
|
+
}
|
|
264
|
+
function resolveGifLoop(options) {
|
|
234
265
|
const loop = options.loop ?? 0;
|
|
235
266
|
if (!Number.isSafeInteger(loop) || loop < -1 || loop > 65535) {
|
|
236
267
|
throw new RangeError("GIF loop must be an integer between -1 and 65535.");
|
|
237
268
|
}
|
|
269
|
+
return loop;
|
|
270
|
+
}
|
|
271
|
+
function ffmpegGifOutputArgs(options) {
|
|
272
|
+
const loop = resolveGifLoop(options);
|
|
238
273
|
return [
|
|
239
274
|
"-filter_complex",
|
|
240
275
|
ffmpegGifFilterGraph(options),
|
|
@@ -337,6 +372,9 @@ export {
|
|
|
337
372
|
ffmpegAudioMuxArgs,
|
|
338
373
|
ffmpegGifFilterGraph,
|
|
339
374
|
ffmpegGifOutputArgs,
|
|
375
|
+
ffmpegGifPaletteApplicationArgs,
|
|
376
|
+
ffmpegGifPaletteApplicationGraph,
|
|
377
|
+
ffmpegGifPaletteGenerationFilter,
|
|
340
378
|
ffmpegVideoQualityArgs,
|
|
341
379
|
framesToMp4Wasm,
|
|
342
380
|
generateRenderHtml,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bendyline/squisq-video",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.2",
|
|
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",
|
|
@@ -39,15 +39,16 @@
|
|
|
39
39
|
"dist",
|
|
40
40
|
"!dist/**/*.map",
|
|
41
41
|
"LICENSE",
|
|
42
|
-
"NOTICE.md"
|
|
42
|
+
"NOTICE.md",
|
|
43
|
+
"THIRD_PARTY_LICENSES.txt"
|
|
43
44
|
],
|
|
44
45
|
"scripts": {
|
|
45
|
-
"build": "tsup && node ../../scripts/remove-empty-chunks.mjs dist",
|
|
46
|
+
"build": "tsup && node ../../scripts/generate-bundle-licenses.mjs . && node ../../scripts/remove-empty-chunks.mjs dist",
|
|
46
47
|
"dev": "concurrently -n js,dts -c blue,gray -r \"tsup --watch --no-dts --no-clean\" \"tsup --watch --dts-only --no-clean\"",
|
|
47
48
|
"typecheck": "tsc --noEmit"
|
|
48
49
|
},
|
|
49
50
|
"dependencies": {
|
|
50
|
-
"@bendyline/squisq": "2.3.
|
|
51
|
+
"@bendyline/squisq": "2.3.2",
|
|
51
52
|
"@ffmpeg/ffmpeg": "0.12.15",
|
|
52
53
|
"@ffmpeg/util": "0.12.2"
|
|
53
54
|
},
|