ugcinc-render 1.8.19 → 1.8.21

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.mts CHANGED
@@ -641,6 +641,8 @@ interface ScreenshotAnimationProps {
641
641
  pauseDurationMs?: number;
642
642
  /** Duration of flash phase (ms) */
643
643
  flashDurationMs?: number;
644
+ /** Duration to hold at end after animation completes (ms) */
645
+ holdDurationMs?: number;
644
646
  /** Border corner radius (px) */
645
647
  borderRadius?: number;
646
648
  /** Border color */
@@ -648,7 +650,7 @@ interface ScreenshotAnimationProps {
648
650
  /** Background color (behind everything) */
649
651
  backgroundColor?: string;
650
652
  }
651
- declare function ScreenshotAnimation({ imageUrl, width, height, pauseDurationMs, flashDurationMs, borderRadius, borderColor, backgroundColor, }: ScreenshotAnimationProps): react_jsx_runtime.JSX.Element;
653
+ declare function ScreenshotAnimation({ imageUrl, width, height, pauseDurationMs, flashDurationMs, holdDurationMs, borderRadius, borderColor, backgroundColor, }: ScreenshotAnimationProps): react_jsx_runtime.JSX.Element;
652
654
 
653
655
  interface TextElementProps {
654
656
  segment: TextSegment;
package/dist/index.d.ts CHANGED
@@ -641,6 +641,8 @@ interface ScreenshotAnimationProps {
641
641
  pauseDurationMs?: number;
642
642
  /** Duration of flash phase (ms) */
643
643
  flashDurationMs?: number;
644
+ /** Duration to hold at end after animation completes (ms) */
645
+ holdDurationMs?: number;
644
646
  /** Border corner radius (px) */
645
647
  borderRadius?: number;
646
648
  /** Border color */
@@ -648,7 +650,7 @@ interface ScreenshotAnimationProps {
648
650
  /** Background color (behind everything) */
649
651
  backgroundColor?: string;
650
652
  }
651
- declare function ScreenshotAnimation({ imageUrl, width, height, pauseDurationMs, flashDurationMs, borderRadius, borderColor, backgroundColor, }: ScreenshotAnimationProps): react_jsx_runtime.JSX.Element;
653
+ declare function ScreenshotAnimation({ imageUrl, width, height, pauseDurationMs, flashDurationMs, holdDurationMs, borderRadius, borderColor, backgroundColor, }: ScreenshotAnimationProps): react_jsx_runtime.JSX.Element;
652
654
 
653
655
  interface TextElementProps {
654
656
  segment: TextSegment;
package/dist/index.js CHANGED
@@ -2248,37 +2248,179 @@ function AutoCaptionCompositionWithVideo({
2248
2248
 
2249
2249
  // src/compositions/ScreenshotAnimation.tsx
2250
2250
  var import_remotion7 = require("remotion");
2251
- var import_jsx_runtime8 = require("react/jsx-runtime");
2252
- var PHASE2_ANIMATION_DURATION = 960;
2253
- var START = {
2254
- ssBorderTop: 0.0276,
2255
- ssBorderTopInner: 0.035,
2256
- ssBorderRight: 0.9883,
2257
- ssBorderLeft: 0,
2258
- ssBorderBottom: 1,
2259
- imgTop: 0.5125,
2260
- imgClipRight: 0.2076,
2261
- imgClipBottom: 0.7103,
2262
- whiteOpacity: 0.862
2251
+
2252
+ // src/data/screenshot.ts
2253
+ var screenshotMovementData = {
2254
+ "ssBorderTop": {
2255
+ "0": 0.0276,
2256
+ "80": 0.2392,
2257
+ "160": 0.3898,
2258
+ "240": 0.497,
2259
+ "320": 0.5732,
2260
+ "400": 0.6275,
2261
+ "480": 0.6661,
2262
+ "560": 0.6936,
2263
+ "640": 0.7131,
2264
+ "720": 0.727,
2265
+ "800": 0.7369,
2266
+ "880": 0.744,
2267
+ "960": 0.749
2268
+ },
2269
+ "ssBorderTopInner": {
2270
+ "0": 0.035,
2271
+ "80": 0.2458,
2272
+ "160": 0.3959,
2273
+ "240": 0.5028,
2274
+ "320": 0.5788,
2275
+ "400": 0.633,
2276
+ "480": 0.6715,
2277
+ "560": 0.699,
2278
+ "640": 0.7185,
2279
+ "720": 0.7324,
2280
+ "800": 0.7423,
2281
+ "880": 0.7493,
2282
+ "960": 0.7543
2283
+ },
2284
+ "ssBorderRight": {
2285
+ "0": 0.9883,
2286
+ "80": 0.7926,
2287
+ "160": 0.6532,
2288
+ "240": 0.5538,
2289
+ "320": 0.4829,
2290
+ "400": 0.4324,
2291
+ "480": 0.3964,
2292
+ "560": 0.3707,
2293
+ "640": 0.3525,
2294
+ "720": 0.3394,
2295
+ "800": 0.3301,
2296
+ "880": 0.3235,
2297
+ "960": 0.3188
2298
+ },
2299
+ "ssBorderLeft": {
2300
+ "0": 0,
2301
+ "80": 0.0197,
2302
+ "160": 0.0393,
2303
+ "240": 0.0537,
2304
+ "320": 0.0642,
2305
+ "400": 0.0719,
2306
+ "480": 0.0776,
2307
+ "560": 0.0817,
2308
+ "640": 0.0848,
2309
+ "720": 0.087,
2310
+ "800": 0.0886,
2311
+ "880": 0.0898,
2312
+ "960": 0.0907
2313
+ },
2314
+ "ssBorderBottom": {
2315
+ "0": 1,
2316
+ "80": 0.9911,
2317
+ "160": 0.9828,
2318
+ "240": 0.9766,
2319
+ "320": 0.9719,
2320
+ "400": 0.9683,
2321
+ "480": 0.9656,
2322
+ "560": 0.9636,
2323
+ "640": 0.9621,
2324
+ "720": 0.961,
2325
+ "800": 0.9601,
2326
+ "880": 0.9595,
2327
+ "960": 0.959
2328
+ },
2329
+ "imgTop": {
2330
+ "0": 0.5125,
2331
+ "80": 0.5833,
2332
+ "160": 0.6336,
2333
+ "240": 0.6693,
2334
+ "320": 0.6946,
2335
+ "400": 0.7126,
2336
+ "480": 0.7254,
2337
+ "560": 0.7345,
2338
+ "640": 0.7409,
2339
+ "720": 0.7455,
2340
+ "800": 0.7488,
2341
+ "880": 0.7511,
2342
+ "960": 0.7527
2343
+ },
2344
+ "imgClipRight": {
2345
+ "0": 0.2076,
2346
+ "80": 0.2348,
2347
+ "160": 0.2548,
2348
+ "240": 0.2696,
2349
+ "320": 0.2804,
2350
+ "400": 0.2884,
2351
+ "480": 0.2943,
2352
+ "560": 0.2987,
2353
+ "640": 0.3019,
2354
+ "720": 0.3042,
2355
+ "800": 0.3059,
2356
+ "880": 0.3072,
2357
+ "960": 0.3082
2358
+ },
2359
+ "imgClipBottom": {
2360
+ "0": 0.7103,
2361
+ "80": 0.7833,
2362
+ "160": 0.8347,
2363
+ "240": 0.8709,
2364
+ "320": 0.8964,
2365
+ "400": 0.9143,
2366
+ "480": 0.927,
2367
+ "560": 0.9358,
2368
+ "640": 0.9421,
2369
+ "720": 0.9465,
2370
+ "800": 0.9496,
2371
+ "880": 0.9518,
2372
+ "960": 0.9533
2373
+ }
2263
2374
  };
2264
- var END = {
2265
- ssBorderTop: 0.749,
2266
- ssBorderTopInner: 0.7543,
2267
- ssBorderRight: 0.3188,
2268
- ssBorderLeft: 0.0907,
2269
- ssBorderBottom: 0.959,
2270
- imgTop: 0.7527,
2271
- imgClipRight: 0.3082,
2272
- imgClipBottom: 0.9533,
2273
- whiteOpacity: 0.1687
2375
+ var whiteOverlayOpacityData = {
2376
+ "0": 0.862,
2377
+ "80": 0.7829,
2378
+ "160": 0.7077,
2379
+ "240": 0.6365,
2380
+ "320": 0.5691,
2381
+ "400": 0.5056,
2382
+ "480": 0.446,
2383
+ "560": 0.3903,
2384
+ "640": 0.3384,
2385
+ "720": 0.2903,
2386
+ "800": 0.246,
2387
+ "880": 0.2054,
2388
+ "960": 0.1687,
2389
+ "1160": 0.093,
2390
+ "1360": 0.0402,
2391
+ "1760": 0
2274
2392
  };
2275
- var WHITE_FADE_DURATION = 960;
2276
- var GRAY_START = { r: 255, g: 255, b: 255 };
2277
- var GRAY_END = { r: 174, g: 169, b: 171 };
2393
+
2394
+ // src/compositions/ScreenshotAnimation.tsx
2395
+ var import_jsx_runtime8 = require("react/jsx-runtime");
2396
+ function interpolateKeyframes(timeMs, data) {
2397
+ const times = Object.keys(data).map(Number).sort((a, b) => a - b);
2398
+ if (timeMs <= times[0]) {
2399
+ return data[times[0].toString()];
2400
+ }
2401
+ if (timeMs >= times[times.length - 1]) {
2402
+ return data[times[times.length - 1].toString()];
2403
+ }
2404
+ let lowerTime = times[0];
2405
+ let upperTime = times[times.length - 1];
2406
+ for (let i = 0; i < times.length - 1; i++) {
2407
+ if (timeMs >= times[i] && timeMs <= times[i + 1]) {
2408
+ lowerTime = times[i];
2409
+ upperTime = times[i + 1];
2410
+ break;
2411
+ }
2412
+ }
2413
+ const lowerValue = data[lowerTime.toString()];
2414
+ const upperValue = data[upperTime.toString()];
2415
+ const progress = (timeMs - lowerTime) / (upperTime - lowerTime);
2416
+ return lowerValue + (upperValue - lowerValue) * progress;
2417
+ }
2278
2418
  var CORNER_RADIUS_START_TIME = 400;
2279
2419
  var CORNER_RADIUS_DURATION = 180;
2420
+ var GRAY_START = { r: 255, g: 255, b: 255 };
2421
+ var GRAY_END = { r: 174, g: 169, b: 171 };
2422
+ var MOVEMENT_DURATION = 960;
2280
2423
  var easeOutQuart = (t) => 1 - Math.pow(1 - t, 4);
2281
- var easeOutExpo = (t) => t === 1 ? 1 : 1 - Math.pow(2, -10 * t);
2282
2424
  function smoothInterpolate(timeMs, startTime, duration, startValue, endValue, easingFn = easeOutQuart) {
2283
2425
  if (timeMs <= startTime) return startValue;
2284
2426
  if (timeMs >= startTime + duration) return endValue;
@@ -2292,6 +2434,7 @@ function ScreenshotAnimation({
2292
2434
  height = 2622,
2293
2435
  pauseDurationMs = 1e3,
2294
2436
  flashDurationMs = 255,
2437
+ holdDurationMs = 500,
2295
2438
  borderRadius = 35,
2296
2439
  borderColor = "rgba(254, 255, 255, 1)",
2297
2440
  backgroundColor = "#000000"
@@ -2311,26 +2454,20 @@ function ScreenshotAnimation({
2311
2454
  if (isPause) {
2312
2455
  whiteOpacity = 0;
2313
2456
  } else if (isFlashPhase) {
2457
+ const startOpacity = interpolateKeyframes(0, whiteOverlayOpacityData);
2314
2458
  const flashProgress = (timeMs - flashStartMs) / flashDurationMs;
2315
- whiteOpacity = (0, import_remotion7.interpolate)(flashProgress, [0, 0.1, 1], [1, 1, START.whiteOpacity], {
2459
+ whiteOpacity = (0, import_remotion7.interpolate)(flashProgress, [0, 0.1, 1], [1, 1, startOpacity], {
2316
2460
  extrapolateRight: "clamp"
2317
2461
  });
2318
2462
  } else if (isPhase2) {
2319
- whiteOpacity = smoothInterpolate(
2320
- phase2TimeMs,
2321
- 0,
2322
- WHITE_FADE_DURATION,
2323
- START.whiteOpacity,
2324
- END.whiteOpacity,
2325
- easeOutExpo
2326
- );
2463
+ whiteOpacity = interpolateKeyframes(phase2TimeMs, whiteOverlayOpacityData);
2327
2464
  }
2328
2465
  let containerTop;
2329
2466
  let containerTopInner;
2330
2467
  let containerLeft;
2331
2468
  let containerRight;
2332
2469
  let containerBottom;
2333
- const borderWidthPercent = START.ssBorderTopInner - START.ssBorderTop;
2470
+ const borderWidthPercent = interpolateKeyframes(0, screenshotMovementData.ssBorderTopInner) - interpolateKeyframes(0, screenshotMovementData.ssBorderTop);
2334
2471
  if (isFlashPhase) {
2335
2472
  containerTop = 0;
2336
2473
  containerTopInner = borderWidthPercent;
@@ -2338,11 +2475,11 @@ function ScreenshotAnimation({
2338
2475
  containerRight = 1;
2339
2476
  containerBottom = 1;
2340
2477
  } else {
2341
- containerTop = smoothInterpolate(phase2TimeMs, 0, PHASE2_ANIMATION_DURATION, START.ssBorderTop, END.ssBorderTop, easeOutQuart);
2342
- containerTopInner = smoothInterpolate(phase2TimeMs, 0, PHASE2_ANIMATION_DURATION, START.ssBorderTopInner, END.ssBorderTopInner, easeOutQuart);
2343
- containerLeft = smoothInterpolate(phase2TimeMs, 0, PHASE2_ANIMATION_DURATION, START.ssBorderLeft, END.ssBorderLeft, easeOutQuart);
2344
- containerRight = smoothInterpolate(phase2TimeMs, 0, PHASE2_ANIMATION_DURATION, START.ssBorderRight, END.ssBorderRight, easeOutQuart);
2345
- containerBottom = smoothInterpolate(phase2TimeMs, 0, PHASE2_ANIMATION_DURATION, START.ssBorderBottom, END.ssBorderBottom, easeOutQuart);
2478
+ containerTop = interpolateKeyframes(phase2TimeMs, screenshotMovementData.ssBorderTop);
2479
+ containerTopInner = interpolateKeyframes(phase2TimeMs, screenshotMovementData.ssBorderTopInner);
2480
+ containerLeft = interpolateKeyframes(phase2TimeMs, screenshotMovementData.ssBorderLeft);
2481
+ containerRight = interpolateKeyframes(phase2TimeMs, screenshotMovementData.ssBorderRight);
2482
+ containerBottom = interpolateKeyframes(phase2TimeMs, screenshotMovementData.ssBorderBottom);
2346
2483
  }
2347
2484
  const borderWidth = (containerTopInner - containerTop) * height;
2348
2485
  const containerX = containerLeft * width;
@@ -2366,17 +2503,17 @@ function ScreenshotAnimation({
2366
2503
  let imgClipRightPercent;
2367
2504
  let imgClipBottomPercent;
2368
2505
  if (isFlashPhase) {
2369
- imgTopPercent = START.imgTop;
2370
- imgClipRightPercent = START.imgClipRight;
2371
- imgClipBottomPercent = START.imgClipBottom;
2506
+ imgTopPercent = interpolateKeyframes(0, screenshotMovementData.imgTop);
2507
+ imgClipRightPercent = interpolateKeyframes(0, screenshotMovementData.imgClipRight);
2508
+ imgClipBottomPercent = interpolateKeyframes(0, screenshotMovementData.imgClipBottom);
2372
2509
  } else {
2373
- imgTopPercent = smoothInterpolate(phase2TimeMs, 0, PHASE2_ANIMATION_DURATION, START.imgTop, END.imgTop, easeOutQuart);
2374
- imgClipRightPercent = smoothInterpolate(phase2TimeMs, 0, PHASE2_ANIMATION_DURATION, START.imgClipRight, END.imgClipRight, easeOutQuart);
2375
- imgClipBottomPercent = smoothInterpolate(phase2TimeMs, 0, PHASE2_ANIMATION_DURATION, START.imgClipBottom, END.imgClipBottom, easeOutQuart);
2510
+ imgTopPercent = interpolateKeyframes(phase2TimeMs, screenshotMovementData.imgTop);
2511
+ imgClipRightPercent = interpolateKeyframes(phase2TimeMs, screenshotMovementData.imgClipRight);
2512
+ imgClipBottomPercent = interpolateKeyframes(phase2TimeMs, screenshotMovementData.imgClipBottom);
2376
2513
  }
2377
2514
  const showSmallClip = isPhase2;
2378
- const thumbnailFilled = phase2TimeMs >= PHASE2_ANIMATION_DURATION;
2379
- const grayProgress = Math.min(1, phase2TimeMs / PHASE2_ANIMATION_DURATION);
2515
+ const thumbnailFilled = phase2TimeMs >= MOVEMENT_DURATION;
2516
+ const grayProgress = Math.min(1, phase2TimeMs / MOVEMENT_DURATION);
2380
2517
  const easedGrayProgress = easeOutQuart(grayProgress);
2381
2518
  const grayR = GRAY_START.r + (GRAY_END.r - GRAY_START.r) * easedGrayProgress;
2382
2519
  const grayG = GRAY_START.g + (GRAY_END.g - GRAY_START.g) * easedGrayProgress;
@@ -2933,6 +3070,7 @@ var defaultScreenshotAnimationProps = {
2933
3070
  height: 2622,
2934
3071
  pauseDurationMs: 1e3,
2935
3072
  flashDurationMs: 255,
3073
+ holdDurationMs: 500,
2936
3074
  borderRadius: 35,
2937
3075
  borderColor: "rgba(254, 255, 255, 1)",
2938
3076
  backgroundColor: "#000000"
@@ -2943,6 +3081,7 @@ var screenshotAnimationSchema = import_zod.z.object({
2943
3081
  height: import_zod.z.number().optional().default(2622).describe("Canvas height (px)"),
2944
3082
  pauseDurationMs: import_zod.z.number().optional().default(1e3).describe("Pause before flash (ms)"),
2945
3083
  flashDurationMs: import_zod.z.number().optional().default(255).describe("Flash phase duration (ms)"),
3084
+ holdDurationMs: import_zod.z.number().optional().default(500).describe("Hold at end after animation (ms)"),
2946
3085
  borderRadius: import_zod.z.number().optional().default(35).describe("Border corner radius (px)"),
2947
3086
  borderColor: import_zod.z.string().optional().default("rgba(254, 255, 255, 1)").describe("Border color"),
2948
3087
  backgroundColor: import_zod.z.string().optional().default("#000000").describe("Background color")
package/dist/index.mjs CHANGED
@@ -1385,37 +1385,179 @@ function AutoCaptionCompositionWithVideo({
1385
1385
 
1386
1386
  // src/compositions/ScreenshotAnimation.tsx
1387
1387
  import { AbsoluteFill as AbsoluteFill4, Img as Img3, interpolate as interpolate2, useCurrentFrame as useCurrentFrame5, useVideoConfig as useVideoConfig5 } from "remotion";
1388
- import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
1389
- var PHASE2_ANIMATION_DURATION = 960;
1390
- var START = {
1391
- ssBorderTop: 0.0276,
1392
- ssBorderTopInner: 0.035,
1393
- ssBorderRight: 0.9883,
1394
- ssBorderLeft: 0,
1395
- ssBorderBottom: 1,
1396
- imgTop: 0.5125,
1397
- imgClipRight: 0.2076,
1398
- imgClipBottom: 0.7103,
1399
- whiteOpacity: 0.862
1388
+
1389
+ // src/data/screenshot.ts
1390
+ var screenshotMovementData = {
1391
+ "ssBorderTop": {
1392
+ "0": 0.0276,
1393
+ "80": 0.2392,
1394
+ "160": 0.3898,
1395
+ "240": 0.497,
1396
+ "320": 0.5732,
1397
+ "400": 0.6275,
1398
+ "480": 0.6661,
1399
+ "560": 0.6936,
1400
+ "640": 0.7131,
1401
+ "720": 0.727,
1402
+ "800": 0.7369,
1403
+ "880": 0.744,
1404
+ "960": 0.749
1405
+ },
1406
+ "ssBorderTopInner": {
1407
+ "0": 0.035,
1408
+ "80": 0.2458,
1409
+ "160": 0.3959,
1410
+ "240": 0.5028,
1411
+ "320": 0.5788,
1412
+ "400": 0.633,
1413
+ "480": 0.6715,
1414
+ "560": 0.699,
1415
+ "640": 0.7185,
1416
+ "720": 0.7324,
1417
+ "800": 0.7423,
1418
+ "880": 0.7493,
1419
+ "960": 0.7543
1420
+ },
1421
+ "ssBorderRight": {
1422
+ "0": 0.9883,
1423
+ "80": 0.7926,
1424
+ "160": 0.6532,
1425
+ "240": 0.5538,
1426
+ "320": 0.4829,
1427
+ "400": 0.4324,
1428
+ "480": 0.3964,
1429
+ "560": 0.3707,
1430
+ "640": 0.3525,
1431
+ "720": 0.3394,
1432
+ "800": 0.3301,
1433
+ "880": 0.3235,
1434
+ "960": 0.3188
1435
+ },
1436
+ "ssBorderLeft": {
1437
+ "0": 0,
1438
+ "80": 0.0197,
1439
+ "160": 0.0393,
1440
+ "240": 0.0537,
1441
+ "320": 0.0642,
1442
+ "400": 0.0719,
1443
+ "480": 0.0776,
1444
+ "560": 0.0817,
1445
+ "640": 0.0848,
1446
+ "720": 0.087,
1447
+ "800": 0.0886,
1448
+ "880": 0.0898,
1449
+ "960": 0.0907
1450
+ },
1451
+ "ssBorderBottom": {
1452
+ "0": 1,
1453
+ "80": 0.9911,
1454
+ "160": 0.9828,
1455
+ "240": 0.9766,
1456
+ "320": 0.9719,
1457
+ "400": 0.9683,
1458
+ "480": 0.9656,
1459
+ "560": 0.9636,
1460
+ "640": 0.9621,
1461
+ "720": 0.961,
1462
+ "800": 0.9601,
1463
+ "880": 0.9595,
1464
+ "960": 0.959
1465
+ },
1466
+ "imgTop": {
1467
+ "0": 0.5125,
1468
+ "80": 0.5833,
1469
+ "160": 0.6336,
1470
+ "240": 0.6693,
1471
+ "320": 0.6946,
1472
+ "400": 0.7126,
1473
+ "480": 0.7254,
1474
+ "560": 0.7345,
1475
+ "640": 0.7409,
1476
+ "720": 0.7455,
1477
+ "800": 0.7488,
1478
+ "880": 0.7511,
1479
+ "960": 0.7527
1480
+ },
1481
+ "imgClipRight": {
1482
+ "0": 0.2076,
1483
+ "80": 0.2348,
1484
+ "160": 0.2548,
1485
+ "240": 0.2696,
1486
+ "320": 0.2804,
1487
+ "400": 0.2884,
1488
+ "480": 0.2943,
1489
+ "560": 0.2987,
1490
+ "640": 0.3019,
1491
+ "720": 0.3042,
1492
+ "800": 0.3059,
1493
+ "880": 0.3072,
1494
+ "960": 0.3082
1495
+ },
1496
+ "imgClipBottom": {
1497
+ "0": 0.7103,
1498
+ "80": 0.7833,
1499
+ "160": 0.8347,
1500
+ "240": 0.8709,
1501
+ "320": 0.8964,
1502
+ "400": 0.9143,
1503
+ "480": 0.927,
1504
+ "560": 0.9358,
1505
+ "640": 0.9421,
1506
+ "720": 0.9465,
1507
+ "800": 0.9496,
1508
+ "880": 0.9518,
1509
+ "960": 0.9533
1510
+ }
1400
1511
  };
1401
- var END = {
1402
- ssBorderTop: 0.749,
1403
- ssBorderTopInner: 0.7543,
1404
- ssBorderRight: 0.3188,
1405
- ssBorderLeft: 0.0907,
1406
- ssBorderBottom: 0.959,
1407
- imgTop: 0.7527,
1408
- imgClipRight: 0.3082,
1409
- imgClipBottom: 0.9533,
1410
- whiteOpacity: 0.1687
1512
+ var whiteOverlayOpacityData = {
1513
+ "0": 0.862,
1514
+ "80": 0.7829,
1515
+ "160": 0.7077,
1516
+ "240": 0.6365,
1517
+ "320": 0.5691,
1518
+ "400": 0.5056,
1519
+ "480": 0.446,
1520
+ "560": 0.3903,
1521
+ "640": 0.3384,
1522
+ "720": 0.2903,
1523
+ "800": 0.246,
1524
+ "880": 0.2054,
1525
+ "960": 0.1687,
1526
+ "1160": 0.093,
1527
+ "1360": 0.0402,
1528
+ "1760": 0
1411
1529
  };
1412
- var WHITE_FADE_DURATION = 960;
1413
- var GRAY_START = { r: 255, g: 255, b: 255 };
1414
- var GRAY_END = { r: 174, g: 169, b: 171 };
1530
+
1531
+ // src/compositions/ScreenshotAnimation.tsx
1532
+ import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
1533
+ function interpolateKeyframes(timeMs, data) {
1534
+ const times = Object.keys(data).map(Number).sort((a, b) => a - b);
1535
+ if (timeMs <= times[0]) {
1536
+ return data[times[0].toString()];
1537
+ }
1538
+ if (timeMs >= times[times.length - 1]) {
1539
+ return data[times[times.length - 1].toString()];
1540
+ }
1541
+ let lowerTime = times[0];
1542
+ let upperTime = times[times.length - 1];
1543
+ for (let i = 0; i < times.length - 1; i++) {
1544
+ if (timeMs >= times[i] && timeMs <= times[i + 1]) {
1545
+ lowerTime = times[i];
1546
+ upperTime = times[i + 1];
1547
+ break;
1548
+ }
1549
+ }
1550
+ const lowerValue = data[lowerTime.toString()];
1551
+ const upperValue = data[upperTime.toString()];
1552
+ const progress = (timeMs - lowerTime) / (upperTime - lowerTime);
1553
+ return lowerValue + (upperValue - lowerValue) * progress;
1554
+ }
1415
1555
  var CORNER_RADIUS_START_TIME = 400;
1416
1556
  var CORNER_RADIUS_DURATION = 180;
1557
+ var GRAY_START = { r: 255, g: 255, b: 255 };
1558
+ var GRAY_END = { r: 174, g: 169, b: 171 };
1559
+ var MOVEMENT_DURATION = 960;
1417
1560
  var easeOutQuart = (t) => 1 - Math.pow(1 - t, 4);
1418
- var easeOutExpo = (t) => t === 1 ? 1 : 1 - Math.pow(2, -10 * t);
1419
1561
  function smoothInterpolate(timeMs, startTime, duration, startValue, endValue, easingFn = easeOutQuart) {
1420
1562
  if (timeMs <= startTime) return startValue;
1421
1563
  if (timeMs >= startTime + duration) return endValue;
@@ -1429,6 +1571,7 @@ function ScreenshotAnimation({
1429
1571
  height = 2622,
1430
1572
  pauseDurationMs = 1e3,
1431
1573
  flashDurationMs = 255,
1574
+ holdDurationMs = 500,
1432
1575
  borderRadius = 35,
1433
1576
  borderColor = "rgba(254, 255, 255, 1)",
1434
1577
  backgroundColor = "#000000"
@@ -1448,26 +1591,20 @@ function ScreenshotAnimation({
1448
1591
  if (isPause) {
1449
1592
  whiteOpacity = 0;
1450
1593
  } else if (isFlashPhase) {
1594
+ const startOpacity = interpolateKeyframes(0, whiteOverlayOpacityData);
1451
1595
  const flashProgress = (timeMs - flashStartMs) / flashDurationMs;
1452
- whiteOpacity = interpolate2(flashProgress, [0, 0.1, 1], [1, 1, START.whiteOpacity], {
1596
+ whiteOpacity = interpolate2(flashProgress, [0, 0.1, 1], [1, 1, startOpacity], {
1453
1597
  extrapolateRight: "clamp"
1454
1598
  });
1455
1599
  } else if (isPhase2) {
1456
- whiteOpacity = smoothInterpolate(
1457
- phase2TimeMs,
1458
- 0,
1459
- WHITE_FADE_DURATION,
1460
- START.whiteOpacity,
1461
- END.whiteOpacity,
1462
- easeOutExpo
1463
- );
1600
+ whiteOpacity = interpolateKeyframes(phase2TimeMs, whiteOverlayOpacityData);
1464
1601
  }
1465
1602
  let containerTop;
1466
1603
  let containerTopInner;
1467
1604
  let containerLeft;
1468
1605
  let containerRight;
1469
1606
  let containerBottom;
1470
- const borderWidthPercent = START.ssBorderTopInner - START.ssBorderTop;
1607
+ const borderWidthPercent = interpolateKeyframes(0, screenshotMovementData.ssBorderTopInner) - interpolateKeyframes(0, screenshotMovementData.ssBorderTop);
1471
1608
  if (isFlashPhase) {
1472
1609
  containerTop = 0;
1473
1610
  containerTopInner = borderWidthPercent;
@@ -1475,11 +1612,11 @@ function ScreenshotAnimation({
1475
1612
  containerRight = 1;
1476
1613
  containerBottom = 1;
1477
1614
  } else {
1478
- containerTop = smoothInterpolate(phase2TimeMs, 0, PHASE2_ANIMATION_DURATION, START.ssBorderTop, END.ssBorderTop, easeOutQuart);
1479
- containerTopInner = smoothInterpolate(phase2TimeMs, 0, PHASE2_ANIMATION_DURATION, START.ssBorderTopInner, END.ssBorderTopInner, easeOutQuart);
1480
- containerLeft = smoothInterpolate(phase2TimeMs, 0, PHASE2_ANIMATION_DURATION, START.ssBorderLeft, END.ssBorderLeft, easeOutQuart);
1481
- containerRight = smoothInterpolate(phase2TimeMs, 0, PHASE2_ANIMATION_DURATION, START.ssBorderRight, END.ssBorderRight, easeOutQuart);
1482
- containerBottom = smoothInterpolate(phase2TimeMs, 0, PHASE2_ANIMATION_DURATION, START.ssBorderBottom, END.ssBorderBottom, easeOutQuart);
1615
+ containerTop = interpolateKeyframes(phase2TimeMs, screenshotMovementData.ssBorderTop);
1616
+ containerTopInner = interpolateKeyframes(phase2TimeMs, screenshotMovementData.ssBorderTopInner);
1617
+ containerLeft = interpolateKeyframes(phase2TimeMs, screenshotMovementData.ssBorderLeft);
1618
+ containerRight = interpolateKeyframes(phase2TimeMs, screenshotMovementData.ssBorderRight);
1619
+ containerBottom = interpolateKeyframes(phase2TimeMs, screenshotMovementData.ssBorderBottom);
1483
1620
  }
1484
1621
  const borderWidth = (containerTopInner - containerTop) * height;
1485
1622
  const containerX = containerLeft * width;
@@ -1503,17 +1640,17 @@ function ScreenshotAnimation({
1503
1640
  let imgClipRightPercent;
1504
1641
  let imgClipBottomPercent;
1505
1642
  if (isFlashPhase) {
1506
- imgTopPercent = START.imgTop;
1507
- imgClipRightPercent = START.imgClipRight;
1508
- imgClipBottomPercent = START.imgClipBottom;
1643
+ imgTopPercent = interpolateKeyframes(0, screenshotMovementData.imgTop);
1644
+ imgClipRightPercent = interpolateKeyframes(0, screenshotMovementData.imgClipRight);
1645
+ imgClipBottomPercent = interpolateKeyframes(0, screenshotMovementData.imgClipBottom);
1509
1646
  } else {
1510
- imgTopPercent = smoothInterpolate(phase2TimeMs, 0, PHASE2_ANIMATION_DURATION, START.imgTop, END.imgTop, easeOutQuart);
1511
- imgClipRightPercent = smoothInterpolate(phase2TimeMs, 0, PHASE2_ANIMATION_DURATION, START.imgClipRight, END.imgClipRight, easeOutQuart);
1512
- imgClipBottomPercent = smoothInterpolate(phase2TimeMs, 0, PHASE2_ANIMATION_DURATION, START.imgClipBottom, END.imgClipBottom, easeOutQuart);
1647
+ imgTopPercent = interpolateKeyframes(phase2TimeMs, screenshotMovementData.imgTop);
1648
+ imgClipRightPercent = interpolateKeyframes(phase2TimeMs, screenshotMovementData.imgClipRight);
1649
+ imgClipBottomPercent = interpolateKeyframes(phase2TimeMs, screenshotMovementData.imgClipBottom);
1513
1650
  }
1514
1651
  const showSmallClip = isPhase2;
1515
- const thumbnailFilled = phase2TimeMs >= PHASE2_ANIMATION_DURATION;
1516
- const grayProgress = Math.min(1, phase2TimeMs / PHASE2_ANIMATION_DURATION);
1652
+ const thumbnailFilled = phase2TimeMs >= MOVEMENT_DURATION;
1653
+ const grayProgress = Math.min(1, phase2TimeMs / MOVEMENT_DURATION);
1517
1654
  const easedGrayProgress = easeOutQuart(grayProgress);
1518
1655
  const grayR = GRAY_START.r + (GRAY_END.r - GRAY_START.r) * easedGrayProgress;
1519
1656
  const grayG = GRAY_START.g + (GRAY_END.g - GRAY_START.g) * easedGrayProgress;
@@ -1787,6 +1924,7 @@ var defaultScreenshotAnimationProps = {
1787
1924
  height: 2622,
1788
1925
  pauseDurationMs: 1e3,
1789
1926
  flashDurationMs: 255,
1927
+ holdDurationMs: 500,
1790
1928
  borderRadius: 35,
1791
1929
  borderColor: "rgba(254, 255, 255, 1)",
1792
1930
  backgroundColor: "#000000"
@@ -1797,6 +1935,7 @@ var screenshotAnimationSchema = z.object({
1797
1935
  height: z.number().optional().default(2622).describe("Canvas height (px)"),
1798
1936
  pauseDurationMs: z.number().optional().default(1e3).describe("Pause before flash (ms)"),
1799
1937
  flashDurationMs: z.number().optional().default(255).describe("Flash phase duration (ms)"),
1938
+ holdDurationMs: z.number().optional().default(500).describe("Hold at end after animation (ms)"),
1800
1939
  borderRadius: z.number().optional().default(35).describe("Border corner radius (px)"),
1801
1940
  borderColor: z.string().optional().default("rgba(254, 255, 255, 1)").describe("Border color"),
1802
1941
  backgroundColor: z.string().optional().default("#000000").describe("Background color")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ugcinc-render",
3
- "version": "1.8.19",
3
+ "version": "1.8.21",
4
4
  "description": "Unified rendering package for UGC Inc - shared types, components, and compositions for pixel-perfect client/server rendering",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",