ugcinc 4.5.89 → 4.5.91
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
CHANGED
|
@@ -33,18 +33,23 @@ const definition = (0, types_1.defineNode)({
|
|
|
33
33
|
const editorConfig = config?.videoEditor;
|
|
34
34
|
const inputs = [];
|
|
35
35
|
const addedIds = new Set();
|
|
36
|
+
const addInputPort = (port) => {
|
|
37
|
+
if (addedIds.has(port.id))
|
|
38
|
+
return;
|
|
39
|
+
addedIds.add(port.id);
|
|
40
|
+
inputs.push(port);
|
|
41
|
+
};
|
|
36
42
|
if (editorConfig) {
|
|
37
43
|
editorConfig.channels.forEach(channel => {
|
|
38
44
|
channel.segments.forEach(segment => {
|
|
39
45
|
// inputRef exists on all segments except 'text'
|
|
40
46
|
if (segment.type !== 'text') {
|
|
41
47
|
const isVar = !('isVariable' in segment) || segment.isVariable !== false;
|
|
42
|
-
if (segment.inputRef &&
|
|
43
|
-
addedIds.add(segment.inputRef);
|
|
48
|
+
if (segment.inputRef && isVar) {
|
|
44
49
|
const inputType = segment.type === 'video' || segment.type === 'video-sequence' ? 'video'
|
|
45
50
|
: segment.type === 'audio' ? ['audio', 'social_audio']
|
|
46
51
|
: 'image';
|
|
47
|
-
|
|
52
|
+
addInputPort({
|
|
48
53
|
id: segment.inputRef,
|
|
49
54
|
type: inputType,
|
|
50
55
|
isArray: segment.type === 'image-sequence' || segment.type === 'video-sequence',
|
|
@@ -54,9 +59,8 @@ const definition = (0, types_1.defineNode)({
|
|
|
54
59
|
}
|
|
55
60
|
// textInputRef only exists on 'text' segments
|
|
56
61
|
if (segment.type === 'text') {
|
|
57
|
-
if (segment.textInputRef &&
|
|
58
|
-
|
|
59
|
-
inputs.push({
|
|
62
|
+
if (segment.textInputRef && segment.textIsVariable !== false) {
|
|
63
|
+
addInputPort({
|
|
60
64
|
id: segment.textInputRef,
|
|
61
65
|
type: 'text',
|
|
62
66
|
isArray: false,
|
|
@@ -64,6 +68,22 @@ const definition = (0, types_1.defineNode)({
|
|
|
64
68
|
});
|
|
65
69
|
}
|
|
66
70
|
}
|
|
71
|
+
if (segment.startTrimInputRef) {
|
|
72
|
+
addInputPort({
|
|
73
|
+
id: segment.startTrimInputRef,
|
|
74
|
+
type: 'number',
|
|
75
|
+
isArray: false,
|
|
76
|
+
required: false,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
if (segment.endTrimInputRef) {
|
|
80
|
+
addInputPort({
|
|
81
|
+
id: segment.endTrimInputRef,
|
|
82
|
+
type: 'number',
|
|
83
|
+
isArray: false,
|
|
84
|
+
required: false,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
67
87
|
});
|
|
68
88
|
});
|
|
69
89
|
}
|
|
@@ -152,6 +172,28 @@ function omit(obj, keys) {
|
|
|
152
172
|
}
|
|
153
173
|
return result;
|
|
154
174
|
}
|
|
175
|
+
function getVideoSourceDurationMs({ inputValueDuration, staticMediaDuration, }) {
|
|
176
|
+
const duration = inputValueDuration ?? staticMediaDuration ?? undefined;
|
|
177
|
+
return typeof duration === 'number' && duration > 0 ? duration : undefined;
|
|
178
|
+
}
|
|
179
|
+
function getTrimmedVideoWindowMs({ sourceDurationMs, startTrim, endTrim, }) {
|
|
180
|
+
const safeStartTrim = Math.max(0, startTrim ?? 0);
|
|
181
|
+
const safeEndTrim = typeof endTrim === 'number' && endTrim > safeStartTrim
|
|
182
|
+
? Math.min(endTrim, sourceDurationMs)
|
|
183
|
+
: sourceDurationMs;
|
|
184
|
+
return Math.max(1, safeEndTrim - safeStartTrim);
|
|
185
|
+
}
|
|
186
|
+
function getFitSegmentSpeed({ sourceDurationMs, targetDurationMs, startTrim, endTrim, }) {
|
|
187
|
+
if (!sourceDurationMs || !targetDurationMs || targetDurationMs <= 0) {
|
|
188
|
+
return undefined;
|
|
189
|
+
}
|
|
190
|
+
const sourceWindowMs = getTrimmedVideoWindowMs({
|
|
191
|
+
sourceDurationMs,
|
|
192
|
+
startTrim,
|
|
193
|
+
endTrim,
|
|
194
|
+
});
|
|
195
|
+
return Math.max(0.01, sourceWindowMs / targetDurationMs);
|
|
196
|
+
}
|
|
155
197
|
/**
|
|
156
198
|
* Ensure all segments have explicit zIndex values for proper layering in the renderer.
|
|
157
199
|
*/
|
|
@@ -192,7 +234,25 @@ function transformSegment(segment, inputs) {
|
|
|
192
234
|
if (pick?.url) {
|
|
193
235
|
const keysToOmit = ['inputRef', 'timeMode', 'isVariable', 'staticMedia'];
|
|
194
236
|
if (segment.type === 'video') {
|
|
195
|
-
|
|
237
|
+
const sourceDurationMs = getVideoSourceDurationMs({
|
|
238
|
+
staticMediaDuration: pick.duration,
|
|
239
|
+
});
|
|
240
|
+
const fittedSpeed = segment.speedMode === 'fit-segment'
|
|
241
|
+
? getFitSegmentSpeed({
|
|
242
|
+
sourceDurationMs,
|
|
243
|
+
targetDurationMs: segment.duration?.type === 'absolute' ? segment.duration.value : undefined,
|
|
244
|
+
startTrim: segment.startTrim,
|
|
245
|
+
endTrim: segment.endTrim,
|
|
246
|
+
})
|
|
247
|
+
: undefined;
|
|
248
|
+
result = {
|
|
249
|
+
...omit(segment, [...keysToOmit]),
|
|
250
|
+
type: 'video',
|
|
251
|
+
source: pick.url,
|
|
252
|
+
sourceDurationMs,
|
|
253
|
+
speed: fittedSpeed ?? segment.speed,
|
|
254
|
+
loop: segment.speedMode === 'fit-segment' ? false : segment.loop,
|
|
255
|
+
};
|
|
196
256
|
}
|
|
197
257
|
else if (segment.type === 'audio') {
|
|
198
258
|
result = { ...omit(segment, [...keysToOmit]), type: 'audio', source: pick.url };
|
|
@@ -256,7 +316,25 @@ function transformSegment(segment, inputs) {
|
|
|
256
316
|
const source = mediaValue.url;
|
|
257
317
|
const keysToOmit = ['inputRef', 'timeMode'];
|
|
258
318
|
if (segment.type === 'video') {
|
|
259
|
-
|
|
319
|
+
const sourceDurationMs = getVideoSourceDurationMs({
|
|
320
|
+
inputValueDuration: 'duration' in mediaValue ? mediaValue.duration : undefined,
|
|
321
|
+
});
|
|
322
|
+
const fittedSpeed = segment.speedMode === 'fit-segment'
|
|
323
|
+
? getFitSegmentSpeed({
|
|
324
|
+
sourceDurationMs,
|
|
325
|
+
targetDurationMs: segment.duration?.type === 'absolute' ? segment.duration.value : undefined,
|
|
326
|
+
startTrim: segment.startTrim,
|
|
327
|
+
endTrim: segment.endTrim,
|
|
328
|
+
})
|
|
329
|
+
: undefined;
|
|
330
|
+
result = {
|
|
331
|
+
...omit(segment, [...keysToOmit]),
|
|
332
|
+
type: 'video',
|
|
333
|
+
source,
|
|
334
|
+
sourceDurationMs,
|
|
335
|
+
speed: fittedSpeed ?? segment.speed,
|
|
336
|
+
loop: segment.speedMode === 'fit-segment' ? false : segment.loop,
|
|
337
|
+
};
|
|
260
338
|
}
|
|
261
339
|
else if (segment.type === 'audio') {
|
|
262
340
|
result = { ...omit(segment, [...keysToOmit]), type: 'audio', source };
|
|
@@ -312,7 +390,7 @@ function transformSegment(segment, inputs) {
|
|
|
312
390
|
}
|
|
313
391
|
}
|
|
314
392
|
// Remove UI-only fields
|
|
315
|
-
const uiOnlyKeys = ['timeMode', 'startTrimInputRef', 'endTrimInputRef', 'isVariable', 'staticMedia', 'textIsVariable'];
|
|
393
|
+
const uiOnlyKeys = ['timeMode', 'startTrimInputRef', 'endTrimInputRef', 'isVariable', 'staticMedia', 'textIsVariable', 'speedMode'];
|
|
316
394
|
const resultWithUiFields = result;
|
|
317
395
|
for (const key of uiOnlyKeys) {
|
|
318
396
|
if (key in resultWithUiFields) {
|
|
@@ -75,9 +75,14 @@ export interface VideoEditorVideoSegment extends VideoEditorVisualSegment {
|
|
|
75
75
|
isVariable?: boolean;
|
|
76
76
|
/** UI-only: static media items when isVariable is false */
|
|
77
77
|
staticMedia?: StaticMediaItem[];
|
|
78
|
+
/** UI-only: how playback speed should be resolved */
|
|
79
|
+
speedMode?: 'manual' | 'fit-segment';
|
|
78
80
|
fit?: FitMode;
|
|
79
81
|
speed?: number;
|
|
82
|
+
/** Natural duration of the source video in milliseconds */
|
|
83
|
+
sourceDurationMs?: number;
|
|
80
84
|
volume?: number;
|
|
85
|
+
loop?: boolean;
|
|
81
86
|
borderRadius?: number | BorderRadiusConfig;
|
|
82
87
|
}
|
|
83
88
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ugcinc",
|
|
3
|
-
"version": "4.5.
|
|
3
|
+
"version": "4.5.91",
|
|
4
4
|
"description": "TypeScript/JavaScript client for the UGC Inc API",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -31,9 +31,14 @@
|
|
|
31
31
|
"ugcinc",
|
|
32
32
|
"api",
|
|
33
33
|
"client",
|
|
34
|
+
"ugc",
|
|
34
35
|
"tiktok",
|
|
36
|
+
"instagram",
|
|
37
|
+
"clawbot",
|
|
35
38
|
"automation",
|
|
39
|
+
"social-automation",
|
|
36
40
|
"social-media",
|
|
41
|
+
"social-publishing",
|
|
37
42
|
"content-management",
|
|
38
43
|
"video-rendering"
|
|
39
44
|
],
|