ugcinc-render 1.8.65 → 1.8.67

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
@@ -1922,7 +1922,17 @@ function calculateSegmentTimings(config, fps) {
1922
1922
  const offsetFrames = Math.round(offsetMs / 1e3 * fps);
1923
1923
  const startFrame = currentFrame + offsetFrames;
1924
1924
  let durationMs;
1925
- if (segment.duration) {
1925
+ if (segment.type === "sequence") {
1926
+ const sequenceSegment = segment;
1927
+ const items = sequenceSegment.items ?? [];
1928
+ if (items.length > 0) {
1929
+ durationMs = items.reduce((total, item) => {
1930
+ return total + (item.duration ?? sequenceSegment.defaultDuration);
1931
+ }, 0);
1932
+ } else {
1933
+ durationMs = sequenceSegment.defaultDuration;
1934
+ }
1935
+ } else if (segment.duration) {
1926
1936
  durationMs = segment.duration.type === "absolute" ? segment.duration.value : 5e3;
1927
1937
  } else {
1928
1938
  durationMs = 5e3;
@@ -1976,7 +1986,7 @@ function VideoEditorComposition({
1976
1986
  );
1977
1987
  const activeVisualSegments = (0, import_react5.useMemo)(() => {
1978
1988
  return segmentTimings.filter(({ segment, startFrame, endFrame }) => {
1979
- if (segment.type !== "video" && segment.type !== "image" && segment.type !== "text") {
1989
+ if (segment.type !== "video" && segment.type !== "image" && segment.type !== "text" && segment.type !== "sequence") {
1980
1990
  return false;
1981
1991
  }
1982
1992
  return frame >= startFrame && frame < endFrame;
@@ -2059,6 +2069,88 @@ function VideoEditorComposition({
2059
2069
  segment.id
2060
2070
  );
2061
2071
  }
2072
+ if (segment.type === "sequence") {
2073
+ const sequenceSegment = segment;
2074
+ const items = sequenceSegment.items ?? [];
2075
+ if (items.length === 0) {
2076
+ return null;
2077
+ }
2078
+ const frameIntoSegment = frame - startFrame;
2079
+ let accumulatedFrames = 0;
2080
+ let currentItem = null;
2081
+ let itemStartFrame = startFrame;
2082
+ for (const item of items) {
2083
+ const itemDurationMs = item.duration ?? sequenceSegment.defaultDuration;
2084
+ const itemDurationFrames = Math.round(itemDurationMs / 1e3 * fps);
2085
+ if (frameIntoSegment < accumulatedFrames + itemDurationFrames) {
2086
+ currentItem = item;
2087
+ itemStartFrame = startFrame + accumulatedFrames;
2088
+ break;
2089
+ }
2090
+ accumulatedFrames += itemDurationFrames;
2091
+ }
2092
+ if (!currentItem) {
2093
+ return null;
2094
+ }
2095
+ if (currentItem.type === "image") {
2096
+ const syntheticImageSegment = {
2097
+ id: `${segment.id}-item`,
2098
+ type: "image",
2099
+ source: currentItem.url,
2100
+ order: segment.order,
2101
+ offset: { type: "absolute", value: 0 },
2102
+ xOffset: sequenceSegment.xOffset,
2103
+ yOffset: sequenceSegment.yOffset,
2104
+ width: sequenceSegment.width,
2105
+ height: sequenceSegment.height,
2106
+ fit: sequenceSegment.fit,
2107
+ rotation: sequenceSegment.rotation,
2108
+ opacity: sequenceSegment.opacity,
2109
+ zIndex: sequenceSegment.zIndex,
2110
+ fadeIn: sequenceSegment.fadeIn
2111
+ };
2112
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2113
+ ImageElement,
2114
+ {
2115
+ segment: syntheticImageSegment,
2116
+ src: currentItem.url,
2117
+ startFrame: itemStartFrame,
2118
+ scale: 1
2119
+ },
2120
+ `${segment.id}-${currentItem.url}`
2121
+ );
2122
+ } else {
2123
+ const itemDurationMs = currentItem.duration ?? sequenceSegment.defaultDuration;
2124
+ const itemDurationFrames = Math.round(itemDurationMs / 1e3 * fps);
2125
+ const syntheticVideoSegment = {
2126
+ id: `${segment.id}-item`,
2127
+ type: "video",
2128
+ source: currentItem.url,
2129
+ order: segment.order,
2130
+ offset: { type: "absolute", value: 0 },
2131
+ xOffset: sequenceSegment.xOffset,
2132
+ yOffset: sequenceSegment.yOffset,
2133
+ width: sequenceSegment.width,
2134
+ height: sequenceSegment.height,
2135
+ fit: sequenceSegment.fit,
2136
+ rotation: sequenceSegment.rotation,
2137
+ opacity: sequenceSegment.opacity,
2138
+ zIndex: sequenceSegment.zIndex,
2139
+ fadeIn: sequenceSegment.fadeIn
2140
+ };
2141
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2142
+ VideoElement,
2143
+ {
2144
+ segment: syntheticVideoSegment,
2145
+ src: currentItem.url,
2146
+ startFrame: itemStartFrame,
2147
+ durationInFrames: itemDurationFrames,
2148
+ scale: 1
2149
+ },
2150
+ `${segment.id}-${currentItem.url}`
2151
+ );
2152
+ }
2153
+ }
2062
2154
  return null;
2063
2155
  }),
2064
2156
  audioTimings.map(({ segment, startFrame, durationInFrames: durationInFrames2 }) => {
@@ -2777,6 +2869,8 @@ function DebugOverlay({
2777
2869
  const [mousePos, setMousePos] = (0, import_react7.useState)(null);
2778
2870
  const [viewportPos, setViewportPos] = (0, import_react7.useState)(null);
2779
2871
  const [screenPosPercent, setScreenPosPercent] = (0, import_react7.useState)(null);
2872
+ const [isDragging, setIsDragging] = (0, import_react7.useState)(false);
2873
+ const [lastDragPos, setLastDragPos] = (0, import_react7.useState)(null);
2780
2874
  const zoomScale = zoom / 100;
2781
2875
  const handleMouseMove = (0, import_react7.useCallback)(
2782
2876
  (e) => {
@@ -2795,13 +2889,32 @@ function DebugOverlay({
2795
2889
  const canvasX = Math.round((vpX + scrollX) / zoomScale);
2796
2890
  const canvasY = Math.round((vpY + scrollY) / zoomScale);
2797
2891
  setMousePos({ x: canvasX, y: canvasY });
2892
+ if (isDragging && lastDragPos) {
2893
+ const deltaX = (e.clientX - lastDragPos.x) * remotionScaleX;
2894
+ const deltaY = (e.clientY - lastDragPos.y) * remotionScaleY;
2895
+ const newScrollX = Math.max(0, scrollX - deltaX);
2896
+ const newScrollY = Math.max(0, scrollY - deltaY);
2897
+ onZoomChange(zoom, newScrollX, newScrollY);
2898
+ setLastDragPos({ x: e.clientX, y: e.clientY });
2899
+ }
2798
2900
  },
2799
- [width, height, zoomScale, scrollX, scrollY]
2901
+ [width, height, zoomScale, scrollX, scrollY, isDragging, lastDragPos, zoom, onZoomChange]
2800
2902
  );
2903
+ const handleMouseDown = (0, import_react7.useCallback)((e) => {
2904
+ if (e.target.tagName === "BUTTON") return;
2905
+ setIsDragging(true);
2906
+ setLastDragPos({ x: e.clientX, y: e.clientY });
2907
+ }, []);
2908
+ const handleMouseUp = (0, import_react7.useCallback)(() => {
2909
+ setIsDragging(false);
2910
+ setLastDragPos(null);
2911
+ }, []);
2801
2912
  const handleMouseLeave = (0, import_react7.useCallback)(() => {
2802
2913
  setMousePos(null);
2803
2914
  setViewportPos(null);
2804
2915
  setScreenPosPercent(null);
2916
+ setIsDragging(false);
2917
+ setLastDragPos(null);
2805
2918
  }, []);
2806
2919
  const handleWheel = (0, import_react7.useCallback)(
2807
2920
  (e) => {
@@ -2833,6 +2946,8 @@ function DebugOverlay({
2833
2946
  zIndex: 200
2834
2947
  },
2835
2948
  onMouseMove: handleMouseMove,
2949
+ onMouseDown: handleMouseDown,
2950
+ onMouseUp: handleMouseUp,
2836
2951
  onMouseLeave: handleMouseLeave,
2837
2952
  onWheel: handleWheel,
2838
2953
  children: [
package/dist/index.mjs CHANGED
@@ -1030,7 +1030,17 @@ function calculateSegmentTimings(config, fps) {
1030
1030
  const offsetFrames = Math.round(offsetMs / 1e3 * fps);
1031
1031
  const startFrame = currentFrame + offsetFrames;
1032
1032
  let durationMs;
1033
- if (segment.duration) {
1033
+ if (segment.type === "sequence") {
1034
+ const sequenceSegment = segment;
1035
+ const items = sequenceSegment.items ?? [];
1036
+ if (items.length > 0) {
1037
+ durationMs = items.reduce((total, item) => {
1038
+ return total + (item.duration ?? sequenceSegment.defaultDuration);
1039
+ }, 0);
1040
+ } else {
1041
+ durationMs = sequenceSegment.defaultDuration;
1042
+ }
1043
+ } else if (segment.duration) {
1034
1044
  durationMs = segment.duration.type === "absolute" ? segment.duration.value : 5e3;
1035
1045
  } else {
1036
1046
  durationMs = 5e3;
@@ -1084,7 +1094,7 @@ function VideoEditorComposition({
1084
1094
  );
1085
1095
  const activeVisualSegments = useMemo5(() => {
1086
1096
  return segmentTimings.filter(({ segment, startFrame, endFrame }) => {
1087
- if (segment.type !== "video" && segment.type !== "image" && segment.type !== "text") {
1097
+ if (segment.type !== "video" && segment.type !== "image" && segment.type !== "text" && segment.type !== "sequence") {
1088
1098
  return false;
1089
1099
  }
1090
1100
  return frame >= startFrame && frame < endFrame;
@@ -1167,6 +1177,88 @@ function VideoEditorComposition({
1167
1177
  segment.id
1168
1178
  );
1169
1179
  }
1180
+ if (segment.type === "sequence") {
1181
+ const sequenceSegment = segment;
1182
+ const items = sequenceSegment.items ?? [];
1183
+ if (items.length === 0) {
1184
+ return null;
1185
+ }
1186
+ const frameIntoSegment = frame - startFrame;
1187
+ let accumulatedFrames = 0;
1188
+ let currentItem = null;
1189
+ let itemStartFrame = startFrame;
1190
+ for (const item of items) {
1191
+ const itemDurationMs = item.duration ?? sequenceSegment.defaultDuration;
1192
+ const itemDurationFrames = Math.round(itemDurationMs / 1e3 * fps);
1193
+ if (frameIntoSegment < accumulatedFrames + itemDurationFrames) {
1194
+ currentItem = item;
1195
+ itemStartFrame = startFrame + accumulatedFrames;
1196
+ break;
1197
+ }
1198
+ accumulatedFrames += itemDurationFrames;
1199
+ }
1200
+ if (!currentItem) {
1201
+ return null;
1202
+ }
1203
+ if (currentItem.type === "image") {
1204
+ const syntheticImageSegment = {
1205
+ id: `${segment.id}-item`,
1206
+ type: "image",
1207
+ source: currentItem.url,
1208
+ order: segment.order,
1209
+ offset: { type: "absolute", value: 0 },
1210
+ xOffset: sequenceSegment.xOffset,
1211
+ yOffset: sequenceSegment.yOffset,
1212
+ width: sequenceSegment.width,
1213
+ height: sequenceSegment.height,
1214
+ fit: sequenceSegment.fit,
1215
+ rotation: sequenceSegment.rotation,
1216
+ opacity: sequenceSegment.opacity,
1217
+ zIndex: sequenceSegment.zIndex,
1218
+ fadeIn: sequenceSegment.fadeIn
1219
+ };
1220
+ return /* @__PURE__ */ jsx5(
1221
+ ImageElement,
1222
+ {
1223
+ segment: syntheticImageSegment,
1224
+ src: currentItem.url,
1225
+ startFrame: itemStartFrame,
1226
+ scale: 1
1227
+ },
1228
+ `${segment.id}-${currentItem.url}`
1229
+ );
1230
+ } else {
1231
+ const itemDurationMs = currentItem.duration ?? sequenceSegment.defaultDuration;
1232
+ const itemDurationFrames = Math.round(itemDurationMs / 1e3 * fps);
1233
+ const syntheticVideoSegment = {
1234
+ id: `${segment.id}-item`,
1235
+ type: "video",
1236
+ source: currentItem.url,
1237
+ order: segment.order,
1238
+ offset: { type: "absolute", value: 0 },
1239
+ xOffset: sequenceSegment.xOffset,
1240
+ yOffset: sequenceSegment.yOffset,
1241
+ width: sequenceSegment.width,
1242
+ height: sequenceSegment.height,
1243
+ fit: sequenceSegment.fit,
1244
+ rotation: sequenceSegment.rotation,
1245
+ opacity: sequenceSegment.opacity,
1246
+ zIndex: sequenceSegment.zIndex,
1247
+ fadeIn: sequenceSegment.fadeIn
1248
+ };
1249
+ return /* @__PURE__ */ jsx5(
1250
+ VideoElement,
1251
+ {
1252
+ segment: syntheticVideoSegment,
1253
+ src: currentItem.url,
1254
+ startFrame: itemStartFrame,
1255
+ durationInFrames: itemDurationFrames,
1256
+ scale: 1
1257
+ },
1258
+ `${segment.id}-${currentItem.url}`
1259
+ );
1260
+ }
1261
+ }
1170
1262
  return null;
1171
1263
  }),
1172
1264
  audioTimings.map(({ segment, startFrame, durationInFrames: durationInFrames2 }) => {
@@ -1885,6 +1977,8 @@ function DebugOverlay({
1885
1977
  const [mousePos, setMousePos] = useState2(null);
1886
1978
  const [viewportPos, setViewportPos] = useState2(null);
1887
1979
  const [screenPosPercent, setScreenPosPercent] = useState2(null);
1980
+ const [isDragging, setIsDragging] = useState2(false);
1981
+ const [lastDragPos, setLastDragPos] = useState2(null);
1888
1982
  const zoomScale = zoom / 100;
1889
1983
  const handleMouseMove = useCallback(
1890
1984
  (e) => {
@@ -1903,13 +1997,32 @@ function DebugOverlay({
1903
1997
  const canvasX = Math.round((vpX + scrollX) / zoomScale);
1904
1998
  const canvasY = Math.round((vpY + scrollY) / zoomScale);
1905
1999
  setMousePos({ x: canvasX, y: canvasY });
2000
+ if (isDragging && lastDragPos) {
2001
+ const deltaX = (e.clientX - lastDragPos.x) * remotionScaleX;
2002
+ const deltaY = (e.clientY - lastDragPos.y) * remotionScaleY;
2003
+ const newScrollX = Math.max(0, scrollX - deltaX);
2004
+ const newScrollY = Math.max(0, scrollY - deltaY);
2005
+ onZoomChange(zoom, newScrollX, newScrollY);
2006
+ setLastDragPos({ x: e.clientX, y: e.clientY });
2007
+ }
1906
2008
  },
1907
- [width, height, zoomScale, scrollX, scrollY]
2009
+ [width, height, zoomScale, scrollX, scrollY, isDragging, lastDragPos, zoom, onZoomChange]
1908
2010
  );
2011
+ const handleMouseDown = useCallback((e) => {
2012
+ if (e.target.tagName === "BUTTON") return;
2013
+ setIsDragging(true);
2014
+ setLastDragPos({ x: e.clientX, y: e.clientY });
2015
+ }, []);
2016
+ const handleMouseUp = useCallback(() => {
2017
+ setIsDragging(false);
2018
+ setLastDragPos(null);
2019
+ }, []);
1909
2020
  const handleMouseLeave = useCallback(() => {
1910
2021
  setMousePos(null);
1911
2022
  setViewportPos(null);
1912
2023
  setScreenPosPercent(null);
2024
+ setIsDragging(false);
2025
+ setLastDragPos(null);
1913
2026
  }, []);
1914
2027
  const handleWheel = useCallback(
1915
2028
  (e) => {
@@ -1941,6 +2054,8 @@ function DebugOverlay({
1941
2054
  zIndex: 200
1942
2055
  },
1943
2056
  onMouseMove: handleMouseMove,
2057
+ onMouseDown: handleMouseDown,
2058
+ onMouseUp: handleMouseUp,
1944
2059
  onMouseLeave: handleMouseLeave,
1945
2060
  onWheel: handleWheel,
1946
2061
  children: [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ugcinc-render",
3
- "version": "1.8.65",
3
+ "version": "1.8.67",
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",