@shotstack/shotstack-canvas 2.1.5 → 2.1.7
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/entry.node.cjs +84 -101
- package/dist/entry.node.d.cts +13 -28
- package/dist/entry.node.d.ts +13 -28
- package/dist/entry.node.js +85 -103
- package/dist/entry.web.d.ts +13 -27
- package/dist/entry.web.js +78 -90
- package/package.json +2 -2
package/dist/entry.node.cjs
CHANGED
|
@@ -590,8 +590,7 @@ var richCaptionFontSchema = import_zod.z.object({
|
|
|
590
590
|
weight: import_zod.z.union([import_zod.z.string(), import_zod.z.number()]).default("400"),
|
|
591
591
|
color: import_zod.z.string().regex(HEX6).default("#ffffff"),
|
|
592
592
|
opacity: import_zod.z.number().min(0).max(1).default(1),
|
|
593
|
-
background: import_zod.z.string().regex(HEX6).optional()
|
|
594
|
-
textDecoration: import_zod.z.enum(["none", "underline", "line-through"]).default("none")
|
|
593
|
+
background: import_zod.z.string().regex(HEX6).optional()
|
|
595
594
|
});
|
|
596
595
|
var richCaptionActiveSchema = import_zod2.richCaptionActiveSchema.extend({
|
|
597
596
|
font: import_zod.z.object({
|
|
@@ -600,23 +599,28 @@ var richCaptionActiveSchema = import_zod2.richCaptionActiveSchema.extend({
|
|
|
600
599
|
opacity: import_zod.z.number().min(0).max(1).optional(),
|
|
601
600
|
textDecoration: import_zod.z.enum(["none", "underline", "line-through"]).optional()
|
|
602
601
|
}).optional(),
|
|
603
|
-
stroke: import_zod.z.
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
602
|
+
stroke: import_zod.z.union([
|
|
603
|
+
import_zod.z.object({
|
|
604
|
+
width: import_zod.z.number().min(0).optional(),
|
|
605
|
+
color: import_zod.z.string().regex(HEX6).optional(),
|
|
606
|
+
opacity: import_zod.z.number().min(0).max(1).optional()
|
|
607
|
+
}),
|
|
608
|
+
import_zod.z.literal("none")
|
|
609
|
+
]).optional(),
|
|
610
|
+
shadow: import_zod.z.union([
|
|
611
|
+
import_zod.z.object({
|
|
612
|
+
offsetX: import_zod.z.number().optional(),
|
|
613
|
+
offsetY: import_zod.z.number().optional(),
|
|
614
|
+
blur: import_zod.z.number().min(0).optional(),
|
|
615
|
+
color: import_zod.z.string().regex(HEX6).optional(),
|
|
616
|
+
opacity: import_zod.z.number().min(0).max(1).optional()
|
|
617
|
+
}),
|
|
618
|
+
import_zod.z.literal("none")
|
|
619
|
+
]).optional(),
|
|
615
620
|
scale: import_zod.z.number().min(0.5).max(2).default(1)
|
|
616
621
|
});
|
|
617
|
-
var richCaptionWordAnimationSchema =
|
|
622
|
+
var richCaptionWordAnimationSchema = import_zod.z.object({
|
|
618
623
|
style: import_zod.z.enum(["karaoke", "highlight", "pop", "fade", "slide", "bounce", "typewriter", "none"]).default("highlight"),
|
|
619
|
-
speed: import_zod.z.number().min(0.5).max(2).default(1),
|
|
620
624
|
direction: import_zod.z.enum(["left", "right", "up", "down"]).default("up")
|
|
621
625
|
});
|
|
622
626
|
var richCaptionAssetSchema = import_zod.z.object({
|
|
@@ -1534,7 +1538,7 @@ var LayoutEngine = class {
|
|
|
1534
1538
|
}
|
|
1535
1539
|
async layout(params) {
|
|
1536
1540
|
try {
|
|
1537
|
-
const { textTransform, desc, fontSize, letterSpacing, width, emojiFallback } = params;
|
|
1541
|
+
const { textTransform, desc, fontSize, letterSpacing, wordSpacing = 0, width, emojiFallback } = params;
|
|
1538
1542
|
const input = this.transformText(params.text, textTransform);
|
|
1539
1543
|
if (!input || input.length === 0) {
|
|
1540
1544
|
return [];
|
|
@@ -1564,9 +1568,10 @@ var LayoutEngine = class {
|
|
|
1564
1568
|
char = String.fromCodePoint(codePoint);
|
|
1565
1569
|
}
|
|
1566
1570
|
}
|
|
1571
|
+
const isSpace = char === " ";
|
|
1567
1572
|
return {
|
|
1568
1573
|
id: g.g,
|
|
1569
|
-
xAdvance: g.ax * scale + letterSpacing,
|
|
1574
|
+
xAdvance: g.ax * scale + letterSpacing + (isSpace ? wordSpacing : 0),
|
|
1570
1575
|
xOffset: g.dx * scale,
|
|
1571
1576
|
yOffset: -g.dy * scale,
|
|
1572
1577
|
cluster: g.cl,
|
|
@@ -2843,10 +2848,10 @@ var CaptionLayoutEngine = class {
|
|
|
2843
2848
|
let spaceWidth;
|
|
2844
2849
|
if (config.measureTextWidth) {
|
|
2845
2850
|
const fontString = `${config.fontWeight} ${config.fontSize}px "${config.fontFamily}"`;
|
|
2846
|
-
spaceWidth = config.measureTextWidth(" ", fontString)
|
|
2851
|
+
spaceWidth = config.measureTextWidth(" ", fontString);
|
|
2847
2852
|
} else {
|
|
2848
2853
|
const spaceWord = await this.measureWord(" ", measurementConfig);
|
|
2849
|
-
spaceWidth = spaceWord.width
|
|
2854
|
+
spaceWidth = spaceWord.width;
|
|
2850
2855
|
}
|
|
2851
2856
|
const groups = wordGroups.flatMap((indices) => {
|
|
2852
2857
|
const groupWidths = indices.map((i) => store.widths[i]);
|
|
@@ -3045,12 +3050,8 @@ function calculateWordProgress(ctx) {
|
|
|
3045
3050
|
function isWordActive(ctx) {
|
|
3046
3051
|
return ctx.currentTime >= ctx.wordStart && ctx.currentTime < ctx.wordEnd;
|
|
3047
3052
|
}
|
|
3048
|
-
function calculateKaraokeState(ctx
|
|
3053
|
+
function calculateKaraokeState(ctx) {
|
|
3049
3054
|
const isActive = isWordActive(ctx);
|
|
3050
|
-
const wordDuration = ctx.wordEnd - ctx.wordStart;
|
|
3051
|
-
const adjustedDuration = wordDuration / speed;
|
|
3052
|
-
const adjustedEnd = ctx.wordStart + adjustedDuration;
|
|
3053
|
-
const adjustedCtx = { ...ctx, wordEnd: adjustedEnd };
|
|
3054
3055
|
if (ctx.currentTime < ctx.wordStart) {
|
|
3055
3056
|
return {
|
|
3056
3057
|
fillProgress: 0,
|
|
@@ -3058,7 +3059,7 @@ function calculateKaraokeState(ctx, speed) {
|
|
|
3058
3059
|
opacity: 1
|
|
3059
3060
|
};
|
|
3060
3061
|
}
|
|
3061
|
-
if (ctx.currentTime >=
|
|
3062
|
+
if (ctx.currentTime >= ctx.wordEnd) {
|
|
3062
3063
|
return {
|
|
3063
3064
|
fillProgress: 1,
|
|
3064
3065
|
isActive: false,
|
|
@@ -3066,7 +3067,7 @@ function calculateKaraokeState(ctx, speed) {
|
|
|
3066
3067
|
};
|
|
3067
3068
|
}
|
|
3068
3069
|
return {
|
|
3069
|
-
fillProgress: calculateWordProgress(
|
|
3070
|
+
fillProgress: calculateWordProgress(ctx),
|
|
3070
3071
|
isActive,
|
|
3071
3072
|
opacity: 1
|
|
3072
3073
|
};
|
|
@@ -3079,7 +3080,7 @@ function calculateHighlightState(ctx) {
|
|
|
3079
3080
|
opacity: 1
|
|
3080
3081
|
};
|
|
3081
3082
|
}
|
|
3082
|
-
function calculatePopState(ctx, activeScale
|
|
3083
|
+
function calculatePopState(ctx, activeScale) {
|
|
3083
3084
|
if (ctx.currentTime < ctx.wordStart) {
|
|
3084
3085
|
return {
|
|
3085
3086
|
scale: 0.5,
|
|
@@ -3088,9 +3089,7 @@ function calculatePopState(ctx, activeScale, speed) {
|
|
|
3088
3089
|
fillProgress: 0
|
|
3089
3090
|
};
|
|
3090
3091
|
}
|
|
3091
|
-
const
|
|
3092
|
-
const adjustedCtx = { ...ctx, animationDuration: adjustedDuration };
|
|
3093
|
-
const progress = calculateAnimationProgress(adjustedCtx);
|
|
3092
|
+
const progress = calculateAnimationProgress(ctx);
|
|
3094
3093
|
const easedProgress = easeOutBack(progress);
|
|
3095
3094
|
const startScale = 0.5;
|
|
3096
3095
|
const isActive = isWordActive(ctx);
|
|
@@ -3103,7 +3102,7 @@ function calculatePopState(ctx, activeScale, speed) {
|
|
|
3103
3102
|
fillProgress: isActive ? 1 : 0
|
|
3104
3103
|
};
|
|
3105
3104
|
}
|
|
3106
|
-
function calculateFadeState(ctx
|
|
3105
|
+
function calculateFadeState(ctx) {
|
|
3107
3106
|
if (ctx.currentTime < ctx.wordStart) {
|
|
3108
3107
|
return {
|
|
3109
3108
|
opacity: 0,
|
|
@@ -3111,9 +3110,7 @@ function calculateFadeState(ctx, speed) {
|
|
|
3111
3110
|
fillProgress: 0
|
|
3112
3111
|
};
|
|
3113
3112
|
}
|
|
3114
|
-
const
|
|
3115
|
-
const adjustedCtx = { ...ctx, animationDuration: adjustedDuration };
|
|
3116
|
-
const progress = calculateAnimationProgress(adjustedCtx);
|
|
3113
|
+
const progress = calculateAnimationProgress(ctx);
|
|
3117
3114
|
const easedProgress = easeInOutQuad(progress);
|
|
3118
3115
|
const isActive = isWordActive(ctx);
|
|
3119
3116
|
return {
|
|
@@ -3122,7 +3119,7 @@ function calculateFadeState(ctx, speed) {
|
|
|
3122
3119
|
fillProgress: isActive ? 1 : 0
|
|
3123
3120
|
};
|
|
3124
3121
|
}
|
|
3125
|
-
function calculateSlideState(ctx, direction,
|
|
3122
|
+
function calculateSlideState(ctx, direction, fontSize) {
|
|
3126
3123
|
const slideDistance = fontSize * 1.5;
|
|
3127
3124
|
if (ctx.currentTime < ctx.wordStart) {
|
|
3128
3125
|
const offset2 = getDirectionOffset(direction, slideDistance);
|
|
@@ -3134,9 +3131,7 @@ function calculateSlideState(ctx, direction, speed, fontSize) {
|
|
|
3134
3131
|
fillProgress: 0
|
|
3135
3132
|
};
|
|
3136
3133
|
}
|
|
3137
|
-
const
|
|
3138
|
-
const adjustedCtx = { ...ctx, animationDuration: adjustedDuration };
|
|
3139
|
-
const progress = calculateAnimationProgress(adjustedCtx);
|
|
3134
|
+
const progress = calculateAnimationProgress(ctx);
|
|
3140
3135
|
const easedProgress = easeOutCirc(progress);
|
|
3141
3136
|
const offset = getDirectionOffset(direction, slideDistance);
|
|
3142
3137
|
const translateX = offset.x * (1 - easedProgress);
|
|
@@ -3162,7 +3157,7 @@ function getDirectionOffset(direction, distance) {
|
|
|
3162
3157
|
return { x: 0, y: -distance };
|
|
3163
3158
|
}
|
|
3164
3159
|
}
|
|
3165
|
-
function calculateBounceState(ctx,
|
|
3160
|
+
function calculateBounceState(ctx, fontSize) {
|
|
3166
3161
|
const bounceDistance = fontSize * 0.8;
|
|
3167
3162
|
if (ctx.currentTime < ctx.wordStart) {
|
|
3168
3163
|
return {
|
|
@@ -3172,9 +3167,7 @@ function calculateBounceState(ctx, speed, fontSize) {
|
|
|
3172
3167
|
fillProgress: 0
|
|
3173
3168
|
};
|
|
3174
3169
|
}
|
|
3175
|
-
const
|
|
3176
|
-
const adjustedCtx = { ...ctx, animationDuration: adjustedDuration };
|
|
3177
|
-
const progress = calculateAnimationProgress(adjustedCtx);
|
|
3170
|
+
const progress = calculateAnimationProgress(ctx);
|
|
3178
3171
|
const easedProgress = easeOutBounce(progress);
|
|
3179
3172
|
const isActive = isWordActive(ctx);
|
|
3180
3173
|
return {
|
|
@@ -3184,11 +3177,7 @@ function calculateBounceState(ctx, speed, fontSize) {
|
|
|
3184
3177
|
fillProgress: isActive ? 1 : 0
|
|
3185
3178
|
};
|
|
3186
3179
|
}
|
|
3187
|
-
function calculateTypewriterState(ctx, charCount
|
|
3188
|
-
const wordDuration = ctx.wordEnd - ctx.wordStart;
|
|
3189
|
-
const adjustedDuration = wordDuration / speed;
|
|
3190
|
-
const adjustedEnd = ctx.wordStart + adjustedDuration;
|
|
3191
|
-
const adjustedCtx = { ...ctx, wordEnd: adjustedEnd };
|
|
3180
|
+
function calculateTypewriterState(ctx, charCount) {
|
|
3192
3181
|
if (ctx.currentTime < ctx.wordStart) {
|
|
3193
3182
|
return {
|
|
3194
3183
|
visibleCharacters: 0,
|
|
@@ -3197,7 +3186,7 @@ function calculateTypewriterState(ctx, charCount, speed) {
|
|
|
3197
3186
|
fillProgress: 0
|
|
3198
3187
|
};
|
|
3199
3188
|
}
|
|
3200
|
-
if (ctx.currentTime >=
|
|
3189
|
+
if (ctx.currentTime >= ctx.wordEnd) {
|
|
3201
3190
|
return {
|
|
3202
3191
|
visibleCharacters: charCount,
|
|
3203
3192
|
opacity: 1,
|
|
@@ -3205,7 +3194,7 @@ function calculateTypewriterState(ctx, charCount, speed) {
|
|
|
3205
3194
|
fillProgress: 0
|
|
3206
3195
|
};
|
|
3207
3196
|
}
|
|
3208
|
-
const progress = calculateWordProgress(
|
|
3197
|
+
const progress = calculateWordProgress(ctx);
|
|
3209
3198
|
const visibleCharacters = Math.ceil(progress * charCount);
|
|
3210
3199
|
const isActive = isWordActive(ctx);
|
|
3211
3200
|
return {
|
|
@@ -3223,7 +3212,6 @@ function calculateNoneState(_ctx) {
|
|
|
3223
3212
|
};
|
|
3224
3213
|
}
|
|
3225
3214
|
function calculateWordAnimationState(wordStart, wordEnd, currentTime, config, activeScale = 1, charCount = 0, fontSize = 48, isRTL = false) {
|
|
3226
|
-
const safeSpeed = config.speed > 0 ? config.speed : 1;
|
|
3227
3215
|
const ctx = {
|
|
3228
3216
|
wordStart,
|
|
3229
3217
|
wordEnd,
|
|
@@ -3234,27 +3222,27 @@ function calculateWordAnimationState(wordStart, wordEnd, currentTime, config, ac
|
|
|
3234
3222
|
let partialState;
|
|
3235
3223
|
switch (config.style) {
|
|
3236
3224
|
case "karaoke":
|
|
3237
|
-
partialState = calculateKaraokeState(ctx
|
|
3225
|
+
partialState = calculateKaraokeState(ctx);
|
|
3238
3226
|
break;
|
|
3239
3227
|
case "highlight":
|
|
3240
3228
|
partialState = calculateHighlightState(ctx);
|
|
3241
3229
|
break;
|
|
3242
3230
|
case "pop":
|
|
3243
|
-
partialState = calculatePopState(ctx, activeScale
|
|
3231
|
+
partialState = calculatePopState(ctx, activeScale);
|
|
3244
3232
|
break;
|
|
3245
3233
|
case "fade":
|
|
3246
|
-
partialState = calculateFadeState(ctx
|
|
3234
|
+
partialState = calculateFadeState(ctx);
|
|
3247
3235
|
break;
|
|
3248
3236
|
case "slide": {
|
|
3249
3237
|
const slideDir = mirrorAnimationDirection(config.direction, isRTL);
|
|
3250
|
-
partialState = calculateSlideState(ctx, slideDir,
|
|
3238
|
+
partialState = calculateSlideState(ctx, slideDir, fontSize);
|
|
3251
3239
|
break;
|
|
3252
3240
|
}
|
|
3253
3241
|
case "bounce":
|
|
3254
|
-
partialState = calculateBounceState(ctx,
|
|
3242
|
+
partialState = calculateBounceState(ctx, fontSize);
|
|
3255
3243
|
break;
|
|
3256
3244
|
case "typewriter":
|
|
3257
|
-
partialState = calculateTypewriterState(ctx, charCount
|
|
3245
|
+
partialState = calculateTypewriterState(ctx, charCount);
|
|
3258
3246
|
break;
|
|
3259
3247
|
case "none":
|
|
3260
3248
|
default:
|
|
@@ -3287,7 +3275,6 @@ function calculateAnimationStatesForGroup(words, currentTime, config, activeScal
|
|
|
3287
3275
|
function getDefaultAnimationConfig() {
|
|
3288
3276
|
return {
|
|
3289
3277
|
style: "highlight",
|
|
3290
|
-
speed: 1,
|
|
3291
3278
|
direction: "up"
|
|
3292
3279
|
};
|
|
3293
3280
|
}
|
|
@@ -3328,18 +3315,17 @@ function extractFontConfig(asset) {
|
|
|
3328
3315
|
function extractStrokeConfig(asset, isActive) {
|
|
3329
3316
|
const baseStroke = asset.stroke;
|
|
3330
3317
|
const activeStroke = asset.active?.stroke;
|
|
3331
|
-
if (!baseStroke && !activeStroke) {
|
|
3332
|
-
return void 0;
|
|
3333
|
-
}
|
|
3334
3318
|
if (isActive) {
|
|
3335
|
-
if (
|
|
3319
|
+
if (activeStroke === "none") {
|
|
3336
3320
|
return void 0;
|
|
3337
3321
|
}
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3322
|
+
if (activeStroke && typeof activeStroke === "object") {
|
|
3323
|
+
return {
|
|
3324
|
+
width: activeStroke.width ?? baseStroke?.width ?? 0,
|
|
3325
|
+
color: activeStroke.color ?? baseStroke?.color ?? "#000000",
|
|
3326
|
+
opacity: activeStroke.opacity ?? baseStroke?.opacity ?? 1
|
|
3327
|
+
};
|
|
3328
|
+
}
|
|
3343
3329
|
}
|
|
3344
3330
|
if (baseStroke) {
|
|
3345
3331
|
return {
|
|
@@ -3353,20 +3339,19 @@ function extractStrokeConfig(asset, isActive) {
|
|
|
3353
3339
|
function extractShadowConfig(asset, isActive) {
|
|
3354
3340
|
const baseShadow = asset.shadow;
|
|
3355
3341
|
const activeShadow = asset.active?.shadow;
|
|
3356
|
-
if (!baseShadow && !activeShadow) {
|
|
3357
|
-
return void 0;
|
|
3358
|
-
}
|
|
3359
3342
|
if (isActive) {
|
|
3360
|
-
if (
|
|
3343
|
+
if (activeShadow === "none") {
|
|
3361
3344
|
return void 0;
|
|
3362
3345
|
}
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3346
|
+
if (activeShadow && typeof activeShadow === "object") {
|
|
3347
|
+
return {
|
|
3348
|
+
offsetX: activeShadow.offsetX ?? baseShadow?.offsetX ?? 0,
|
|
3349
|
+
offsetY: activeShadow.offsetY ?? baseShadow?.offsetY ?? 0,
|
|
3350
|
+
blur: activeShadow.blur ?? baseShadow?.blur ?? 0,
|
|
3351
|
+
color: activeShadow.color ?? baseShadow?.color ?? "#000000",
|
|
3352
|
+
opacity: activeShadow.opacity ?? baseShadow?.opacity ?? 0.5
|
|
3353
|
+
};
|
|
3354
|
+
}
|
|
3370
3355
|
}
|
|
3371
3356
|
if (baseShadow) {
|
|
3372
3357
|
return {
|
|
@@ -3382,7 +3367,12 @@ function extractShadowConfig(asset, isActive) {
|
|
|
3382
3367
|
function extractBackgroundConfig(asset, isActive, fontSize) {
|
|
3383
3368
|
const fontBackground = asset.font?.background;
|
|
3384
3369
|
const activeBackground = asset.active?.font?.background;
|
|
3385
|
-
|
|
3370
|
+
let bgColor;
|
|
3371
|
+
if (isActive) {
|
|
3372
|
+
bgColor = activeBackground ?? fontBackground;
|
|
3373
|
+
} else {
|
|
3374
|
+
bgColor = fontBackground;
|
|
3375
|
+
}
|
|
3386
3376
|
if (!bgColor) {
|
|
3387
3377
|
return void 0;
|
|
3388
3378
|
}
|
|
@@ -3433,7 +3423,7 @@ function extractCaptionBorder(asset) {
|
|
|
3433
3423
|
};
|
|
3434
3424
|
}
|
|
3435
3425
|
function extractTextDecoration(asset, isActive) {
|
|
3436
|
-
const baseDecoration = asset.
|
|
3426
|
+
const baseDecoration = asset.style?.textDecoration;
|
|
3437
3427
|
const activeDecoration = asset.active?.font?.textDecoration;
|
|
3438
3428
|
if (isActive && activeDecoration !== void 0) {
|
|
3439
3429
|
return activeDecoration === "none" ? void 0 : activeDecoration;
|
|
@@ -3450,7 +3440,6 @@ function extractAnimationConfig(asset) {
|
|
|
3450
3440
|
}
|
|
3451
3441
|
return {
|
|
3452
3442
|
style: wordAnim.style ?? "highlight",
|
|
3453
|
-
speed: wordAnim.speed ?? 1,
|
|
3454
3443
|
direction: wordAnim.direction ?? "up"
|
|
3455
3444
|
};
|
|
3456
3445
|
}
|
|
@@ -5497,11 +5486,14 @@ function extractSvgDimensions(svgString) {
|
|
|
5497
5486
|
}
|
|
5498
5487
|
|
|
5499
5488
|
// src/core/canvas-text-measurer.ts
|
|
5500
|
-
async function createCanvasTextMeasurer() {
|
|
5489
|
+
async function createCanvasTextMeasurer(letterSpacing) {
|
|
5501
5490
|
const canvasMod = await import("canvas");
|
|
5502
5491
|
const canvas = canvasMod.createCanvas(1, 1);
|
|
5503
5492
|
const ctx = canvas.getContext("2d");
|
|
5504
5493
|
ctx.textBaseline = "alphabetic";
|
|
5494
|
+
if (letterSpacing) {
|
|
5495
|
+
ctx.letterSpacing = `${letterSpacing}px`;
|
|
5496
|
+
}
|
|
5505
5497
|
let lastFont = "";
|
|
5506
5498
|
return (text, font) => {
|
|
5507
5499
|
if (font !== lastFont) {
|
|
@@ -5870,7 +5862,7 @@ function findActiveWordIndex(store, groupWordIndices, timeMs) {
|
|
|
5870
5862
|
}
|
|
5871
5863
|
return -1;
|
|
5872
5864
|
}
|
|
5873
|
-
function getAnimationPhase(store, groupWordIndices, timeMs, animationStyle
|
|
5865
|
+
function getAnimationPhase(store, groupWordIndices, timeMs, animationStyle) {
|
|
5874
5866
|
if (groupWordIndices.length === 0) {
|
|
5875
5867
|
return "idle";
|
|
5876
5868
|
}
|
|
@@ -5887,7 +5879,7 @@ function getAnimationPhase(store, groupWordIndices, timeMs, animationStyle, spee
|
|
|
5887
5879
|
return "after";
|
|
5888
5880
|
}
|
|
5889
5881
|
if (TRANSITION_ANIMATION_STYLES.has(animationStyle)) {
|
|
5890
|
-
const transitionDurationMs =
|
|
5882
|
+
const transitionDurationMs = ANIMATION_DURATION_MS[animationStyle] ?? 200;
|
|
5891
5883
|
for (const idx of groupWordIndices) {
|
|
5892
5884
|
const wordStart = store.startTimes[idx];
|
|
5893
5885
|
if (timeMs >= wordStart && timeMs < wordStart + transitionDurationMs) {
|
|
@@ -5909,7 +5901,7 @@ function getAnimationPhase(store, groupWordIndices, timeMs, animationStyle, spee
|
|
|
5909
5901
|
}
|
|
5910
5902
|
return "before";
|
|
5911
5903
|
}
|
|
5912
|
-
function computeStateSignature(layout, timeMs, animationStyle
|
|
5904
|
+
function computeStateSignature(layout, timeMs, animationStyle) {
|
|
5913
5905
|
const groupIndex = findGroupIndexAtTime(layout.groups, timeMs);
|
|
5914
5906
|
if (groupIndex === -1) {
|
|
5915
5907
|
return { groupIndex: -1, activeWordIndex: -1, animationPhase: "idle" };
|
|
@@ -5920,21 +5912,20 @@ function computeStateSignature(layout, timeMs, animationStyle, speed) {
|
|
|
5920
5912
|
layout.store,
|
|
5921
5913
|
group.wordIndices,
|
|
5922
5914
|
timeMs,
|
|
5923
|
-
animationStyle
|
|
5924
|
-
speed
|
|
5915
|
+
animationStyle
|
|
5925
5916
|
);
|
|
5926
5917
|
return { groupIndex, activeWordIndex, animationPhase };
|
|
5927
5918
|
}
|
|
5928
5919
|
function signaturesMatch(a, b) {
|
|
5929
5920
|
return a.groupIndex === b.groupIndex && a.activeWordIndex === b.activeWordIndex && a.animationPhase === b.animationPhase;
|
|
5930
5921
|
}
|
|
5931
|
-
function createFrameSchedule(layout, durationMs, fps, animationStyle = "highlight"
|
|
5922
|
+
function createFrameSchedule(layout, durationMs, fps, animationStyle = "highlight") {
|
|
5932
5923
|
const totalFrames = Math.max(2, Math.round(durationMs / 1e3 * fps) + 1);
|
|
5933
5924
|
const renderFrames = [];
|
|
5934
5925
|
let previousSignature = null;
|
|
5935
5926
|
for (let frame = 0; frame < totalFrames; frame++) {
|
|
5936
5927
|
const timeMs = frame / (totalFrames - 1) * durationMs;
|
|
5937
|
-
const signature = computeStateSignature(layout, timeMs, animationStyle
|
|
5928
|
+
const signature = computeStateSignature(layout, timeMs, animationStyle);
|
|
5938
5929
|
const isAnimating = signature.animationPhase === "animating";
|
|
5939
5930
|
if (isAnimating || previousSignature === null || !signaturesMatch(signature, previousSignature)) {
|
|
5940
5931
|
renderFrames.push({
|
|
@@ -6281,7 +6272,7 @@ var RichCaptionRenderer = class {
|
|
|
6281
6272
|
}
|
|
6282
6273
|
const font = asset.font;
|
|
6283
6274
|
const style = asset.style;
|
|
6284
|
-
const measureTextWidth = await createCanvasTextMeasurer();
|
|
6275
|
+
const measureTextWidth = await createCanvasTextMeasurer(style?.letterSpacing ?? 0);
|
|
6285
6276
|
const fontSize = font?.size ?? 24;
|
|
6286
6277
|
const lineHeight = style?.lineHeight ?? 1.2;
|
|
6287
6278
|
const padding = extractCaptionPadding(asset);
|
|
@@ -6302,7 +6293,6 @@ var RichCaptionRenderer = class {
|
|
|
6302
6293
|
fontFamily: font?.family ?? "Roboto",
|
|
6303
6294
|
fontWeight: String(font?.weight ?? "400"),
|
|
6304
6295
|
letterSpacing: style?.letterSpacing ?? 0,
|
|
6305
|
-
wordSpacing: typeof style?.wordSpacing === "number" ? style.wordSpacing : 0,
|
|
6306
6296
|
lineHeight,
|
|
6307
6297
|
textTransform: style?.textTransform ?? "none",
|
|
6308
6298
|
pauseThreshold: this.currentAsset?.pauseThreshold ?? 500,
|
|
@@ -6336,14 +6326,12 @@ var RichCaptionRenderer = class {
|
|
|
6336
6326
|
throw new Error("No asset loaded. Call loadAsset() first.");
|
|
6337
6327
|
}
|
|
6338
6328
|
const animationStyle = this.extractAnimationStyle();
|
|
6339
|
-
const animationSpeed = this.extractAnimationSpeed();
|
|
6340
6329
|
const durationMs = duration * 1e3;
|
|
6341
6330
|
const schedule = createFrameSchedule(
|
|
6342
6331
|
this.currentLayout,
|
|
6343
6332
|
durationMs,
|
|
6344
6333
|
this.fps,
|
|
6345
|
-
animationStyle
|
|
6346
|
-
animationSpeed
|
|
6334
|
+
animationStyle
|
|
6347
6335
|
);
|
|
6348
6336
|
const bgColor = options?.bgColor;
|
|
6349
6337
|
const hasAlpha = !bgColor;
|
|
@@ -6504,13 +6492,11 @@ var RichCaptionRenderer = class {
|
|
|
6504
6492
|
throw new Error("No asset loaded. Call loadAsset() first.");
|
|
6505
6493
|
}
|
|
6506
6494
|
const animationStyle = this.extractAnimationStyle();
|
|
6507
|
-
const animationSpeed = this.extractAnimationSpeed();
|
|
6508
6495
|
return createFrameSchedule(
|
|
6509
6496
|
this.currentLayout,
|
|
6510
6497
|
duration * 1e3,
|
|
6511
6498
|
this.fps,
|
|
6512
|
-
animationStyle
|
|
6513
|
-
animationSpeed
|
|
6499
|
+
animationStyle
|
|
6514
6500
|
);
|
|
6515
6501
|
}
|
|
6516
6502
|
getStats() {
|
|
@@ -6548,10 +6534,6 @@ var RichCaptionRenderer = class {
|
|
|
6548
6534
|
const wordAnim = this.currentAsset?.wordAnimation;
|
|
6549
6535
|
return wordAnim?.style ?? "highlight";
|
|
6550
6536
|
}
|
|
6551
|
-
extractAnimationSpeed() {
|
|
6552
|
-
const wordAnim = this.currentAsset?.wordAnimation;
|
|
6553
|
-
return wordAnim?.speed ?? 1;
|
|
6554
|
-
}
|
|
6555
6537
|
logProgress(pct, framesProcessed, totalFrames, uniqueProcessed, uniqueTotal, fps, eta) {
|
|
6556
6538
|
if (typeof process !== "undefined" && process.stderr) {
|
|
6557
6539
|
process.stderr.write(
|
|
@@ -6864,6 +6846,7 @@ async function createTextEngine(opts = {}) {
|
|
|
6864
6846
|
text: asset.text,
|
|
6865
6847
|
width: (asset.width ?? width) - padding2.left - padding2.right,
|
|
6866
6848
|
letterSpacing: asset.style?.letterSpacing ?? 0,
|
|
6849
|
+
wordSpacing: typeof asset.style?.wordSpacing === "number" ? asset.style.wordSpacing : 0,
|
|
6867
6850
|
fontSize: main.size,
|
|
6868
6851
|
lineHeight: asset.style?.lineHeight ?? 1.2,
|
|
6869
6852
|
desc,
|
package/dist/entry.node.d.cts
CHANGED
|
@@ -271,11 +271,6 @@ declare const richCaptionAssetSchema: z.ZodObject<{
|
|
|
271
271
|
color: z.ZodDefault<z.ZodString>;
|
|
272
272
|
opacity: z.ZodDefault<z.ZodNumber>;
|
|
273
273
|
background: z.ZodOptional<z.ZodString>;
|
|
274
|
-
textDecoration: z.ZodDefault<z.ZodEnum<{
|
|
275
|
-
none: "none";
|
|
276
|
-
underline: "underline";
|
|
277
|
-
"line-through": "line-through";
|
|
278
|
-
}>>;
|
|
279
274
|
}, z.core.$strip>>;
|
|
280
275
|
style: z.ZodOptional<z.ZodObject<{
|
|
281
276
|
wordSpacing: z.ZodDefault<z.ZodOptional<z.ZodUnion<readonly [z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNumber>, z.ZodString]>>>;
|
|
@@ -356,39 +351,38 @@ declare const richCaptionAssetSchema: z.ZodObject<{
|
|
|
356
351
|
"line-through": "line-through";
|
|
357
352
|
}>>;
|
|
358
353
|
}, z.core.$strip>>;
|
|
359
|
-
stroke: z.ZodOptional<z.ZodObject<{
|
|
354
|
+
stroke: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
|
|
360
355
|
width: z.ZodOptional<z.ZodNumber>;
|
|
361
356
|
color: z.ZodOptional<z.ZodString>;
|
|
362
357
|
opacity: z.ZodOptional<z.ZodNumber>;
|
|
363
|
-
}, z.core.$strip>>;
|
|
364
|
-
shadow: z.ZodOptional<z.ZodObject<{
|
|
358
|
+
}, z.core.$strip>, z.ZodLiteral<"none">]>>;
|
|
359
|
+
shadow: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
|
|
365
360
|
offsetX: z.ZodOptional<z.ZodNumber>;
|
|
366
361
|
offsetY: z.ZodOptional<z.ZodNumber>;
|
|
367
362
|
blur: z.ZodOptional<z.ZodNumber>;
|
|
368
363
|
color: z.ZodOptional<z.ZodString>;
|
|
369
364
|
opacity: z.ZodOptional<z.ZodNumber>;
|
|
370
|
-
}, z.core.$strip>>;
|
|
365
|
+
}, z.core.$strip>, z.ZodLiteral<"none">]>>;
|
|
371
366
|
scale: z.ZodDefault<z.ZodNumber>;
|
|
372
367
|
}, z.core.$strict>>;
|
|
373
368
|
wordAnimation: z.ZodOptional<z.ZodObject<{
|
|
374
369
|
style: z.ZodDefault<z.ZodEnum<{
|
|
375
370
|
typewriter: "typewriter";
|
|
376
371
|
none: "none";
|
|
372
|
+
pop: "pop";
|
|
377
373
|
karaoke: "karaoke";
|
|
378
374
|
highlight: "highlight";
|
|
379
|
-
pop: "pop";
|
|
380
375
|
fade: "fade";
|
|
381
376
|
slide: "slide";
|
|
382
377
|
bounce: "bounce";
|
|
383
378
|
}>>;
|
|
384
|
-
speed: z.ZodDefault<z.ZodNumber>;
|
|
385
379
|
direction: z.ZodDefault<z.ZodEnum<{
|
|
386
380
|
right: "right";
|
|
387
381
|
left: "left";
|
|
388
382
|
up: "up";
|
|
389
383
|
down: "down";
|
|
390
384
|
}>>;
|
|
391
|
-
}, z.core.$
|
|
385
|
+
}, z.core.$strip>>;
|
|
392
386
|
pauseThreshold: z.ZodOptional<z.ZodDefault<z.ZodNumber>>;
|
|
393
387
|
customFonts: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
394
388
|
src: z.ZodString;
|
|
@@ -414,11 +408,6 @@ declare const CanvasRichCaptionAssetSchema: z.ZodObject<{
|
|
|
414
408
|
color: z.ZodDefault<z.ZodString>;
|
|
415
409
|
opacity: z.ZodDefault<z.ZodNumber>;
|
|
416
410
|
background: z.ZodOptional<z.ZodString>;
|
|
417
|
-
textDecoration: z.ZodDefault<z.ZodEnum<{
|
|
418
|
-
none: "none";
|
|
419
|
-
underline: "underline";
|
|
420
|
-
"line-through": "line-through";
|
|
421
|
-
}>>;
|
|
422
411
|
}, z.core.$strip>>;
|
|
423
412
|
style: z.ZodOptional<z.ZodObject<{
|
|
424
413
|
wordSpacing: z.ZodDefault<z.ZodOptional<z.ZodUnion<readonly [z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNumber>, z.ZodString]>>>;
|
|
@@ -499,39 +488,38 @@ declare const CanvasRichCaptionAssetSchema: z.ZodObject<{
|
|
|
499
488
|
"line-through": "line-through";
|
|
500
489
|
}>>;
|
|
501
490
|
}, z.core.$strip>>;
|
|
502
|
-
stroke: z.ZodOptional<z.ZodObject<{
|
|
491
|
+
stroke: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
|
|
503
492
|
width: z.ZodOptional<z.ZodNumber>;
|
|
504
493
|
color: z.ZodOptional<z.ZodString>;
|
|
505
494
|
opacity: z.ZodOptional<z.ZodNumber>;
|
|
506
|
-
}, z.core.$strip>>;
|
|
507
|
-
shadow: z.ZodOptional<z.ZodObject<{
|
|
495
|
+
}, z.core.$strip>, z.ZodLiteral<"none">]>>;
|
|
496
|
+
shadow: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
|
|
508
497
|
offsetX: z.ZodOptional<z.ZodNumber>;
|
|
509
498
|
offsetY: z.ZodOptional<z.ZodNumber>;
|
|
510
499
|
blur: z.ZodOptional<z.ZodNumber>;
|
|
511
500
|
color: z.ZodOptional<z.ZodString>;
|
|
512
501
|
opacity: z.ZodOptional<z.ZodNumber>;
|
|
513
|
-
}, z.core.$strip>>;
|
|
502
|
+
}, z.core.$strip>, z.ZodLiteral<"none">]>>;
|
|
514
503
|
scale: z.ZodDefault<z.ZodNumber>;
|
|
515
504
|
}, z.core.$strict>>;
|
|
516
505
|
wordAnimation: z.ZodOptional<z.ZodObject<{
|
|
517
506
|
style: z.ZodDefault<z.ZodEnum<{
|
|
518
507
|
typewriter: "typewriter";
|
|
519
508
|
none: "none";
|
|
509
|
+
pop: "pop";
|
|
520
510
|
karaoke: "karaoke";
|
|
521
511
|
highlight: "highlight";
|
|
522
|
-
pop: "pop";
|
|
523
512
|
fade: "fade";
|
|
524
513
|
slide: "slide";
|
|
525
514
|
bounce: "bounce";
|
|
526
515
|
}>>;
|
|
527
|
-
speed: z.ZodDefault<z.ZodNumber>;
|
|
528
516
|
direction: z.ZodDefault<z.ZodEnum<{
|
|
529
517
|
right: "right";
|
|
530
518
|
left: "left";
|
|
531
519
|
up: "up";
|
|
532
520
|
down: "down";
|
|
533
521
|
}>>;
|
|
534
|
-
}, z.core.$
|
|
522
|
+
}, z.core.$strip>>;
|
|
535
523
|
pauseThreshold: z.ZodOptional<z.ZodDefault<z.ZodNumber>>;
|
|
536
524
|
customFonts: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
537
525
|
src: z.ZodString;
|
|
@@ -663,7 +651,6 @@ interface CaptionLayoutConfig {
|
|
|
663
651
|
fontFamily: string;
|
|
664
652
|
fontWeight: string | number;
|
|
665
653
|
letterSpacing: number;
|
|
666
|
-
wordSpacing: number;
|
|
667
654
|
lineHeight: number;
|
|
668
655
|
textTransform: "none" | "uppercase" | "lowercase" | "capitalize";
|
|
669
656
|
pauseThreshold: number;
|
|
@@ -745,7 +732,6 @@ type AnimationStyle = "karaoke" | "highlight" | "pop" | "fade" | "slide" | "boun
|
|
|
745
732
|
type AnimationDirection = "left" | "right" | "up" | "down";
|
|
746
733
|
interface WordAnimationConfig {
|
|
747
734
|
style: AnimationStyle;
|
|
748
|
-
speed: number;
|
|
749
735
|
direction: AnimationDirection;
|
|
750
736
|
}
|
|
751
737
|
interface WordAnimationState {
|
|
@@ -1183,7 +1169,7 @@ interface FrameSchedule {
|
|
|
1183
1169
|
uniqueFrameCount: number;
|
|
1184
1170
|
skipRatio: number;
|
|
1185
1171
|
}
|
|
1186
|
-
declare function createFrameSchedule(layout: CaptionLayout, durationMs: number, fps: number, animationStyle?: AnimationStyle
|
|
1172
|
+
declare function createFrameSchedule(layout: CaptionLayout, durationMs: number, fps: number, animationStyle?: AnimationStyle): FrameSchedule;
|
|
1187
1173
|
|
|
1188
1174
|
interface RichCaptionRendererOptions {
|
|
1189
1175
|
width: number;
|
|
@@ -1252,7 +1238,6 @@ declare class RichCaptionRenderer {
|
|
|
1252
1238
|
private mapVerticalAlign;
|
|
1253
1239
|
private mapHorizontalAlign;
|
|
1254
1240
|
private extractAnimationStyle;
|
|
1255
|
-
private extractAnimationSpeed;
|
|
1256
1241
|
private logProgress;
|
|
1257
1242
|
private logCompletion;
|
|
1258
1243
|
private checkMemoryUsage;
|