@uploadista/flow-videos-nodes 0.0.20 → 0.1.0-beta.5

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.
@@ -1,22 +1,23 @@
1
-
2
- > @uploadista/flow-videos-nodes@0.0.20-beta.9 build /Users/denislaboureyras/Documents/uploadista/dev/uploadista-workspace/uploadista-sdk/packages/flow/videos/nodes
3
- > tsc --noEmit && tsdown
4
-
5
- ℹ tsdown v0.18.0 powered by rolldown v1.0.0-beta.53
6
- ℹ config file: /Users/denislaboureyras/Documents/uploadista/dev/uploadista-workspace/uploadista-sdk/packages/flow/videos/nodes/tsdown.config.ts
7
- ℹ entry: src/index.ts
8
- ℹ tsconfig: tsconfig.json
9
- ℹ Build start
10
- ℹ Cleaning 7 files
11
- ℹ [CJS] dist/index.cjs 5.29 kB │ gzip: 1.60 kB
12
- ℹ [CJS] 1 files, total: 5.29 kB
13
- ℹ [ESM] dist/index.mjs  4.91 kB │ gzip: 1.62 kB
14
- ℹ [ESM] dist/index.mjs.map 26.96 kB │ gzip: 5.12 kB
15
- ℹ [ESM] dist/index.d.mts.map  2.51 kB │ gzip: 0.78 kB
16
- ℹ [ESM] dist/index.d.mts 13.70 kB │ gzip: 2.07 kB
17
- ℹ [ESM] 4 files, total: 48.08 kB
18
- ✔ Build complete in 7775ms
19
- ℹ [CJS] dist/index.d.cts.map  2.51 kB │ gzip: 0.78 kB
20
- ℹ [CJS] dist/index.d.cts 13.70 kB │ gzip: 2.07 kB
21
- ℹ [CJS] 2 files, total: 16.21 kB
22
- ✔ Build complete in 7776ms
1
+
2
+ 
3
+ > @uploadista/flow-videos-nodes@0.1.0-beta.4 build /Users/denislaboureyras/Documents/uploadista/dev/uploadista-workspace/uploadista-sdk/packages/flow/videos/nodes
4
+ > tsc --noEmit && tsdown
5
+
6
+ ℹ tsdown v0.19.0 powered by rolldown v1.0.0-beta.59
7
+ ℹ config file: /Users/denislaboureyras/Documents/uploadista/dev/uploadista-workspace/uploadista-sdk/packages/flow/videos/nodes/tsdown.config.ts
8
+ ℹ entry: src/index.ts
9
+ ℹ tsconfig: tsconfig.json
10
+ ℹ Build start
11
+ ℹ Cleaning 7 files
12
+ ℹ [CJS] dist/index.cjs 5.29 kB │ gzip: 1.60 kB
13
+ ℹ [CJS] 1 files, total: 5.29 kB
14
+ ℹ [ESM] dist/index.mjs  4.91 kB │ gzip: 1.62 kB
15
+ ℹ [ESM] dist/index.mjs.map 26.39 kB │ gzip: 5.07 kB
16
+ ℹ [ESM] dist/index.d.mts.map  2.51 kB │ gzip: 0.78 kB
17
+ ℹ [ESM] dist/index.d.mts 13.70 kB │ gzip: 2.07 kB
18
+ ℹ [ESM] 4 files, total: 47.51 kB
19
+ ✔ Build complete in 5066ms
20
+ ℹ [CJS] dist/index.d.cts.map  2.51 kB │ gzip: 0.78 kB
21
+ ℹ [CJS] dist/index.d.cts 13.70 kB │ gzip: 2.07 kB
22
+ ℹ [CJS] 2 files, total: 16.21 kB
23
+ ✔ Build complete in 5067ms
@@ -0,0 +1,6 @@
1
+
2
+ 
3
+ > @uploadista/flow-videos-nodes@0.1.0-beta.2 check /Users/denislaboureyras/Documents/uploadista/dev/uploadista-workspace/uploadista-sdk/packages/flow/videos/nodes
4
+ > biome check --write ./src
5
+
6
+ Checked 6 files in 251ms. No fixes applied.
@@ -0,0 +1,150 @@
1
+
2
+ 
3
+ > @uploadista/flow-videos-nodes@0.1.0-beta.2 test /Users/denislaboureyras/Documents/uploadista/dev/uploadista-workspace/uploadista-sdk/packages/flow/videos/nodes
4
+ > vitest run
5
+
6
+ [?25l
7
+  RUN  v4.0.17 /Users/denislaboureyras/Documents/uploadista/dev/uploadista-workspace/uploadista-sdk/packages/flow/videos/nodes
8
+
9
+ [?2026h
10
+  Test Files 0 passed (1)
11
+  Tests 0 passed (0)
12
+  Start at 16:51:02
13
+  Duration 924ms
14
+ [?2026l[?2026h
15
+  ❯ tests/video-nodes.test.ts [queued]
16
+
17
+  Test Files 0 passed (1)
18
+  Tests 0 passed (0)
19
+  Start at 16:51:02
20
+  Duration 1.33s
21
+ [?2026l[?2026h
22
+  ❯ tests/video-nodes.test.ts [queued]
23
+
24
+  Test Files 0 passed (1)
25
+  Tests 0 passed (0)
26
+  Start at 16:51:02
27
+  Duration 1.93s
28
+ [?2026l[?2026h
29
+  ❯ tests/video-nodes.test.ts [queued]
30
+
31
+  Test Files 0 passed (1)
32
+  Tests 0 passed (0)
33
+  Start at 16:51:02
34
+  Duration 2.90s
35
+ [?2026l[?2026h
36
+  ❯ tests/video-nodes.test.ts [queued]
37
+
38
+  Test Files 0 passed (1)
39
+  Tests 0 passed (0)
40
+  Start at 16:51:02
41
+  Duration 3.91s
42
+ [?2026l[?2026h
43
+  ❯ tests/video-nodes.test.ts [queued]
44
+
45
+  Test Files 0 passed (1)
46
+  Tests 0 passed (0)
47
+  Start at 16:51:02
48
+  Duration 4.93s
49
+ [?2026l[?2026h
50
+  ❯ tests/video-nodes.test.ts [queued]
51
+
52
+  Test Files 0 passed (1)
53
+  Tests 0 passed (0)
54
+  Start at 16:51:02
55
+  Duration 5.95s
56
+ [?2026l[?2026h
57
+  ❯ tests/video-nodes.test.ts 0/17
58
+
59
+  Test Files 0 passed (1)
60
+  Tests 0 passed (17)
61
+  Start at 16:51:02
62
+  Duration 6.36s
63
+ [?2026l[?2026h
64
+  ❯ tests/video-nodes.test.ts 0/17
65
+
66
+  Test Files 0 passed (1)
67
+  Tests 0 passed (17)
68
+  Start at 16:51:02
69
+  Duration 6.96s
70
+ [?2026l[?2026h
71
+  ❯ tests/video-nodes.test.ts 2/17
72
+
73
+  Test Files 0 passed (1)
74
+  Tests 2 passed (17)
75
+  Start at 16:51:02
76
+  Duration 7.17s
77
+ [?2026l[?2026h
78
+  ❯ tests/video-nodes.test.ts 5/17
79
+
80
+  Test Files 0 passed (1)
81
+  Tests 5 passed (17)
82
+  Start at 16:51:02
83
+  Duration 7.57s
84
+ [?2026l[?2026h
85
+  ❯ tests/video-nodes.test.ts 6/17
86
+
87
+  Test Files 0 passed (1)
88
+  Tests 6 passed (17)
89
+  Start at 16:51:02
90
+  Duration 7.67s
91
+ [?2026l[?2026h
92
+  ❯ tests/video-nodes.test.ts 7/17
93
+
94
+  Test Files 0 passed (1)
95
+  Tests 7 passed (17)
96
+  Start at 16:51:02
97
+  Duration 7.77s
98
+ [?2026l[?2026h
99
+  ❯ tests/video-nodes.test.ts 10/17
100
+
101
+  Test Files 0 passed (1)
102
+  Tests 10 passed (17)
103
+  Start at 16:51:02
104
+  Duration 7.97s
105
+ [?2026l[?2026h
106
+  ❯ tests/video-nodes.test.ts 11/17
107
+
108
+  Test Files 0 passed (1)
109
+  Tests 11 passed (17)
110
+  Start at 16:51:02
111
+  Duration 8.07s
112
+ [?2026l[?2026h
113
+  ❯ tests/video-nodes.test.ts 16/17
114
+
115
+  Test Files 0 passed (1)
116
+  Tests 16 passed (17)
117
+  Start at 16:51:02
118
+  Duration 8.17s
119
+ [?2026l ✓ tests/video-nodes.test.ts (17 tests) 1830ms
120
+ ✓ Video Flow Nodes (17)
121
+ ✓ DescribeVideoNode (2)
122
+ ✓ should execute without errors  561ms
123
+ ✓ should pass through original video bytes 85ms
124
+ ✓ TranscodeVideoNode (3)
125
+ ✓ should transcode video to WebM 8ms
126
+ ✓ should transcode video to MOV 71ms
127
+ ✓ should transcode video to AVI  396ms
128
+ ✓ ResizeVideoNode (3)
129
+ ✓ should resize video to 720p 139ms
130
+ ✓ should resize video to 1080p 5ms
131
+ ✓ should resize video with only width specified 4ms
132
+ ✓ ThumbnailNode (3)
133
+ ✓ should extract frame as JPEG thumbnail 99ms
134
+ ✓ should extract frame as PNG thumbnail 156ms
135
+ ✓ should default to JPEG format 31ms
136
+ ✓ TrimVideoNode (3)
137
+ ✓ should trim video with endTime 12ms
138
+ ✓ should trim video with duration 9ms
139
+ ✓ should trim from start to end of video 42ms
140
+ ✓ Video transformation chains (3)
141
+ ✓ should chain transcode and resize operations 43ms
142
+ ✓ should chain trim and thumbnail operations 146ms
143
+ ✓ should handle describe followed by transcode 11ms
144
+
145
+  Test Files  1 passed (1)
146
+  Tests  17 passed (17)
147
+  Start at  16:51:02
148
+  Duration  8.35s (transform 1.20s, setup 0ms, import 5.09s, tests 1.83s, environment 0ms)
149
+
150
+ [?25h
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../src/describe-video-node.ts","../src/resize-node.ts","../src/thumbnail-node.ts","../src/transcode-node.ts","../src/trim-node.ts"],"sourcesContent":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/describe-video-node.ts","../src/resize-node.ts","../src/thumbnail-node.ts","../src/transcode-node.ts","../src/trim-node.ts"],"sourcesContent":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/describe-video-node.ts","../src/resize-node.ts","../src/thumbnail-node.ts","../src/transcode-node.ts","../src/trim-node.ts"],"sourcesContent":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/describe-video-node.ts","../src/resize-node.ts","../src/thumbnail-node.ts","../src/transcode-node.ts","../src/trim-node.ts"],"sourcesContent":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["DEFAULT_VIDEO_STREAMING_CONFIG: StreamingConfig","effectiveMode: TransformMode","streamingConfig: StreamingConfig","DEFAULT_VIDEO_STREAMING_CONFIG","namingConfig: FileNamingConfig | undefined","newFileName: string | undefined","namingConfig: FileNamingConfig","DEFAULT_VIDEO_STREAMING_CONFIG: StreamingConfig","formatToMimeType: Record<TranscodeVideoParams[\"format\"], string>","formatToExtension: Record<TranscodeVideoParams[\"format\"], string>","effectiveMode: TransformMode","streamingConfig: StreamingConfig","DEFAULT_VIDEO_STREAMING_CONFIG","newFileName: string | undefined","namingConfig: FileNamingConfig","DEFAULT_VIDEO_STREAMING_CONFIG: StreamingConfig","effectiveMode: TransformMode","streamingConfig: StreamingConfig","namingConfig: FileNamingConfig | undefined"],"sources":["../src/describe-video-node.ts","../src/resize-node.ts","../src/thumbnail-node.ts","../src/transcode-node.ts","../src/trim-node.ts"],"sourcesContent":["import {\n createTransformNode,\n STORAGE_OUTPUT_TYPE_ID,\n VideoPlugin,\n} from \"@uploadista/core/flow\";\nimport { Effect } from \"effect\";\n\n/**\n * Creates a Describe Video metadata extraction node\n *\n * Extracts comprehensive metadata from the video file including duration,\n * resolution, codec, bitrate, and audio information. The metadata is stored\n * in the file context for downstream nodes while passing through the original bytes.\n *\n * @param id - Unique node identifier\n * @returns Effect that resolves to the configured node\n *\n * @example\n * ```typescript\n * const node = yield* createDescribeVideoNode(\"describe-1\");\n * ```\n */\nexport function createDescribeVideoNode(\n id: string,\n options?: { keepOutput?: boolean },\n) {\n return Effect.gen(function* () {\n const videoService = yield* VideoPlugin;\n\n return yield* createTransformNode({\n id,\n name: \"Describe Video\",\n description:\n \"Extracts video metadata (duration, resolution, codec, etc.)\",\n nodeTypeId: \"describe-video\",\n outputTypeId: STORAGE_OUTPUT_TYPE_ID,\n keepOutput: options?.keepOutput,\n transform: (inputBytes, file) =>\n Effect.gen(function* () {\n // Extract metadata\n const metadata = yield* videoService.describe(inputBytes);\n\n // Store metadata in file context for downstream nodes\n return {\n bytes: inputBytes, // Pass through original bytes unchanged\n metadata: {\n ...file.metadata,\n videoInfo: metadata,\n },\n };\n }),\n });\n });\n}\n","import {\n createTransformNode,\n type FileNamingConfig,\n type ResizeVideoParams,\n STORAGE_OUTPUT_TYPE_ID,\n type StreamingConfig,\n type TransformMode,\n VideoPlugin,\n} from \"@uploadista/core/flow\";\nimport { Effect } from \"effect\";\n\n// Default streaming config for video processing\nconst DEFAULT_VIDEO_STREAMING_CONFIG: StreamingConfig = {\n fileSizeThreshold: 10_000_000, // 10MB threshold for video\n chunkSize: 1_048_576, // 1MB chunks\n};\n\n/**\n * Creates a Resize video processing node\n *\n * Changes video resolution while optionally maintaining aspect ratio.\n *\n * Supports both buffered and streaming modes for memory-efficient processing\n * of large videos. In streaming mode, the output is streamed directly to storage,\n * reducing peak memory usage.\n *\n * @param id - Unique node identifier\n * @param params - Resize parameters\n * @param options - Optional configuration\n * @param options.keepOutput - Whether to keep output in flow results\n * @param options.naming - File naming configuration (auto suffix: `${width}x${height}`)\n * @param options.mode - Transform mode: \"buffered\", \"streaming\", or \"auto\" (default)\n * @param options.streamingConfig - Streaming configuration (file size threshold, chunk size)\n *\n * @example\n * ```typescript\n * // Auto mode (default) - uses streaming for files > 10MB, otherwise buffered\n * const node = yield* createVideoResizeNode(\"resize-1\", {\n * width: 1280,\n * height: 720,\n * aspectRatio: \"keep\",\n * scaling: \"bicubic\"\n * }, {\n * naming: { mode: \"auto\" }\n * });\n *\n * // Force buffered mode for small files\n * const nodeBuffered = yield* createVideoResizeNode(\"resize-2\", {\n * width: 1920,\n * height: 1080\n * }, {\n * mode: \"buffered\",\n * naming: { mode: \"auto\" }\n * });\n *\n * // Force streaming mode for memory efficiency\n * const nodeStreaming = yield* createVideoResizeNode(\"resize-3\", {\n * width: 1280,\n * height: 720\n * }, {\n * mode: \"streaming\",\n * naming: { mode: \"auto\" }\n * });\n * ```\n */\nexport function createVideoResizeNode(\n id: string,\n params: ResizeVideoParams,\n options?: {\n keepOutput?: boolean;\n naming?: FileNamingConfig;\n mode?: TransformMode;\n streamingConfig?: StreamingConfig;\n },\n) {\n return Effect.gen(function* () {\n const videoService = yield* VideoPlugin;\n\n // Determine if streaming is available and requested\n const supportsStreaming = videoService.supportsStreaming ?? false;\n const requestedMode = options?.mode ?? \"auto\";\n\n // If streaming requested but not supported, fall back to buffered\n const effectiveMode: TransformMode =\n requestedMode === \"buffered\"\n ? \"buffered\"\n : supportsStreaming\n ? requestedMode\n : \"buffered\";\n\n // Use video-specific streaming config as default\n const streamingConfig: StreamingConfig = {\n ...DEFAULT_VIDEO_STREAMING_CONFIG,\n ...options?.streamingConfig,\n };\n\n // Build naming config with auto suffix for video resize\n const namingConfig: FileNamingConfig | undefined = options?.naming\n ? {\n ...options.naming,\n autoSuffix:\n options.naming.autoSuffix ??\n ((ctx) => `${ctx.width ?? params.width}x${ctx.height ?? params.height}`),\n }\n : undefined;\n\n return yield* createTransformNode({\n id,\n name: \"Resize Video\",\n description: \"Changes video resolution\",\n nodeTypeId: \"resize-video\",\n outputTypeId: STORAGE_OUTPUT_TYPE_ID,\n keepOutput: options?.keepOutput,\n naming: namingConfig,\n nodeType: \"resize-video\",\n namingVars: { width: params.width, height: params.height },\n mode: effectiveMode,\n streamingConfig,\n // Buffered transform\n transform: (inputBytes) =>\n Effect.map(videoService.resize(inputBytes, params), (resizedBytes) => ({\n bytes: resizedBytes,\n })),\n // Streaming transform\n streamingTransform: videoService.resizeStream\n ? (inputStream) =>\n Effect.gen(function* () {\n const resizeStreamFn = videoService.resizeStream;\n if (!resizeStreamFn) {\n throw new Error(\"resizeStream not available\");\n }\n const outputStream = yield* resizeStreamFn(inputStream, params);\n return { stream: outputStream };\n })\n : undefined,\n });\n });\n}\n","import {\n applyFileNaming,\n buildNamingContext,\n createTransformNode,\n type ExtractFrameVideoParams,\n type FileNamingConfig,\n getBaseName,\n STORAGE_OUTPUT_TYPE_ID,\n VideoPlugin,\n} from \"@uploadista/core/flow\";\nimport { Effect } from \"effect\";\n\n/**\n * Creates a Thumbnail generation node\n *\n * Extracts a single frame from the video as an image (JPEG or PNG).\n *\n * @param id - Unique node identifier\n * @param params - Frame extraction parameters\n * @param options - Optional configuration\n * @param options.keepOutput - Whether to keep output in flow results\n * @param options.naming - File naming configuration (auto suffix: `thumb`)\n *\n * @example\n * ```typescript\n * // With auto-naming: \"video.mp4\" -> \"video-thumb.jpg\"\n * const node = yield* createVideoThumbnailNode(\"thumbnail-1\", {\n * timestamp: 15,\n * format: \"jpeg\",\n * quality: 85\n * }, {\n * naming: { mode: \"auto\" }\n * });\n * ```\n */\nexport function createVideoThumbnailNode(\n id: string,\n params: ExtractFrameVideoParams,\n options?: { keepOutput?: boolean; naming?: FileNamingConfig },\n) {\n return Effect.gen(function* () {\n const videoService = yield* VideoPlugin;\n\n const format = params.format || \"jpeg\";\n\n return yield* createTransformNode({\n id,\n name: \"Generate Thumbnail\",\n description: \"Extracts a frame from video as an image\",\n nodeTypeId: \"thumbnail-video\",\n outputTypeId: STORAGE_OUTPUT_TYPE_ID,\n keepOutput: options?.keepOutput,\n // Note: naming is handled in transform since format changes extension\n nodeType: \"thumbnail\",\n namingVars: { format },\n transform: (inputBytes, file) =>\n Effect.map(\n videoService.extractFrame(inputBytes, params),\n (imageBytes) => {\n // Map output to image MIME type and extension\n const mimeType = format === \"png\" ? \"image/png\" : \"image/jpeg\";\n const extension = format === \"png\" ? \"png\" : \"jpg\";\n\n // Get original fileName\n const fileName = file.metadata?.fileName;\n let newFileName: string | undefined;\n\n if (fileName && typeof fileName === \"string\") {\n // Apply naming if configured\n if (options?.naming) {\n const namingConfig: FileNamingConfig = {\n ...options.naming,\n autoSuffix: options.naming.autoSuffix ?? (() => \"thumb\"),\n };\n const namingContext = buildNamingContext(\n file,\n {\n flowId: file.flow?.flowId ?? \"\",\n jobId: file.flow?.jobId ?? \"\",\n nodeId: id,\n nodeType: \"thumbnail\",\n },\n { format },\n );\n // Apply naming to get base name with suffix\n const namedFile = applyFileNaming(file, namingContext, namingConfig);\n // Replace extension with image extension\n newFileName = `${getBaseName(namedFile)}.${extension}`;\n } else {\n // No naming config, just update extension\n newFileName = fileName.replace(/\\.[^.]+$/, `.${extension}`);\n }\n }\n\n return {\n bytes: imageBytes,\n type: mimeType,\n fileName: newFileName,\n };\n },\n ),\n });\n });\n}\n","import {\n applyFileNaming,\n buildNamingContext,\n createTransformNode,\n type FileNamingConfig,\n getBaseName,\n STORAGE_OUTPUT_TYPE_ID,\n type StreamingConfig,\n type TranscodeVideoParams,\n type TransformMode,\n VideoPlugin,\n} from \"@uploadista/core/flow\";\nimport { Effect } from \"effect\";\n\n// Default streaming config for video processing\nconst DEFAULT_VIDEO_STREAMING_CONFIG: StreamingConfig = {\n fileSizeThreshold: 10_000_000, // 10MB threshold for video\n chunkSize: 1_048_576, // 1MB chunks\n};\n\n// Map video format to MIME type\nconst formatToMimeType: Record<TranscodeVideoParams[\"format\"], string> = {\n mp4: \"video/mp4\",\n webm: \"video/webm\",\n mov: \"video/quicktime\",\n avi: \"video/x-msvideo\",\n};\n\n// Map video format to file extension\nconst formatToExtension: Record<TranscodeVideoParams[\"format\"], string> = {\n mp4: \"mp4\",\n webm: \"webm\",\n mov: \"mov\",\n avi: \"avi\",\n};\n\n/**\n * Creates a Transcode video processing node\n *\n * Converts video to specified format and codec, optionally adjusting bitrates.\n *\n * Supports both buffered and streaming modes for memory-efficient processing\n * of large videos. In streaming mode, the output is streamed directly to storage,\n * reducing peak memory usage.\n *\n * @param id - Unique node identifier\n * @param params - Transcode parameters\n * @param options - Optional configuration\n * @param options.keepOutput - Whether to keep output in flow results\n * @param options.naming - File naming configuration (auto suffix: `${format}`)\n * @param options.mode - Transform mode: \"buffered\", \"streaming\", or \"auto\" (default)\n * @param options.streamingConfig - Streaming configuration (file size threshold, chunk size)\n *\n * @example\n * ```typescript\n * // Auto mode (default) - uses streaming for files > 10MB, otherwise buffered\n * const node = yield* createTranscodeVideoNode(\"transcode-1\", {\n * format: \"webm\",\n * codec: \"vp9\",\n * videoBitrate: \"1000k\"\n * }, {\n * naming: { mode: \"auto\" }\n * });\n *\n * // Force buffered mode for small files\n * const nodeBuffered = yield* createTranscodeVideoNode(\"transcode-2\", {\n * format: \"mp4\",\n * codec: \"h264\"\n * }, {\n * mode: \"buffered\",\n * naming: { mode: \"auto\" }\n * });\n *\n * // Force streaming mode for memory efficiency\n * const nodeStreaming = yield* createTranscodeVideoNode(\"transcode-3\", {\n * format: \"mp4\",\n * codec: \"h264\"\n * }, {\n * mode: \"streaming\",\n * naming: { mode: \"auto\" }\n * });\n * ```\n */\nexport function createTranscodeVideoNode(\n id: string,\n params: TranscodeVideoParams,\n options?: {\n keepOutput?: boolean;\n naming?: FileNamingConfig;\n mode?: TransformMode;\n streamingConfig?: StreamingConfig;\n },\n) {\n return Effect.gen(function* () {\n const videoService = yield* VideoPlugin;\n\n // Determine if streaming is available and requested\n const supportsStreaming = videoService.supportsStreaming ?? false;\n const requestedMode = options?.mode ?? \"auto\";\n\n // If streaming requested but not supported, fall back to buffered\n const effectiveMode: TransformMode =\n requestedMode === \"buffered\"\n ? \"buffered\"\n : supportsStreaming\n ? requestedMode\n : \"buffered\";\n\n // Use video-specific streaming config as default\n const streamingConfig: StreamingConfig = {\n ...DEFAULT_VIDEO_STREAMING_CONFIG,\n ...options?.streamingConfig,\n };\n\n // Helper to build output metadata\n const buildOutputMetadata = (file: {\n metadata?: Record<string, unknown>;\n flow?: { flowId?: string; jobId?: string };\n }) => {\n const newType = formatToMimeType[params.format];\n const newExtension = formatToExtension[params.format];\n\n const fileName = file.metadata?.fileName;\n let newFileName: string | undefined;\n\n if (fileName && typeof fileName === \"string\") {\n if (options?.naming) {\n const namingConfig: FileNamingConfig = {\n ...options.naming,\n autoSuffix:\n options.naming.autoSuffix ?? ((ctx) => ctx.format ?? params.format),\n };\n const namingContext = buildNamingContext(\n file as Parameters<typeof buildNamingContext>[0],\n {\n flowId: file.flow?.flowId ?? \"\",\n jobId: file.flow?.jobId ?? \"\",\n nodeId: id,\n nodeType: \"transcode\",\n },\n { format: params.format },\n );\n const namedFile = applyFileNaming(\n file as Parameters<typeof applyFileNaming>[0],\n namingContext,\n namingConfig,\n );\n newFileName = `${getBaseName(namedFile)}.${newExtension}`;\n } else {\n newFileName = fileName.replace(/\\.[^.]+$/, `.${newExtension}`);\n }\n }\n\n return { newType, newFileName };\n };\n\n return yield* createTransformNode({\n id,\n name: \"Transcode\",\n description: \"Converts video to specified format and codec\",\n nodeTypeId: \"transcode-video\",\n outputTypeId: STORAGE_OUTPUT_TYPE_ID,\n keepOutput: options?.keepOutput,\n nodeType: \"transcode\",\n namingVars: { format: params.format },\n mode: effectiveMode,\n streamingConfig,\n // Buffered transform\n transform: (inputBytes, file) =>\n Effect.map(\n videoService.transcode(inputBytes, params),\n (transcodedBytes) => {\n const { newType, newFileName } = buildOutputMetadata(file);\n return {\n bytes: transcodedBytes,\n type: newType,\n fileName: newFileName,\n };\n },\n ),\n // Streaming transform\n streamingTransform: videoService.transcodeStream\n ? (inputStream, file) =>\n Effect.gen(function* () {\n const transcodeStreamFn = videoService.transcodeStream;\n if (!transcodeStreamFn) {\n throw new Error(\"transcodeStream not available\");\n }\n const outputStream = yield* transcodeStreamFn(inputStream, params);\n const { newType, newFileName } = buildOutputMetadata(file);\n return {\n stream: outputStream,\n type: newType,\n fileName: newFileName,\n };\n })\n : undefined,\n });\n });\n}\n","import { UploadistaError } from \"@uploadista/core/errors\";\nimport {\n createTransformNode,\n type FileNamingConfig,\n STORAGE_OUTPUT_TYPE_ID,\n type StreamingConfig,\n type TransformMode,\n type TrimVideoParams,\n VideoPlugin,\n} from \"@uploadista/core/flow\";\nimport { Effect } from \"effect\";\n\n// Default streaming config for video processing\nconst DEFAULT_VIDEO_STREAMING_CONFIG: StreamingConfig = {\n fileSizeThreshold: 10_000_000, // 10MB threshold for video\n chunkSize: 1_048_576, // 1MB chunks\n};\n\n/**\n * Creates a Trim video processing node\n *\n * Extracts a segment from the video by time range.\n *\n * Supports both buffered and streaming modes for memory-efficient processing\n * of large videos. In streaming mode, the output is streamed directly to storage,\n * reducing peak memory usage.\n *\n * @param id - Unique node identifier\n * @param params - Trim parameters\n * @param options - Optional configuration\n * @param options.keepOutput - Whether to keep output in flow results\n * @param options.naming - File naming configuration (auto suffix: `trimmed`)\n * @param options.mode - Transform mode: \"buffered\", \"streaming\", or \"auto\" (default)\n * @param options.streamingConfig - Streaming configuration (file size threshold, chunk size)\n *\n * @example\n * ```typescript\n * // Auto mode (default) - uses streaming for files > 10MB, otherwise buffered\n * const node = yield* createTrimVideoNode(\"trim-1\", {\n * startTime: 10,\n * endTime: 30\n * }, {\n * naming: { mode: \"auto\" }\n * });\n *\n * // Force buffered mode for small files\n * const nodeBuffered = yield* createTrimVideoNode(\"trim-2\", {\n * startTime: 0,\n * duration: 60\n * }, {\n * mode: \"buffered\",\n * naming: { mode: \"auto\" }\n * });\n *\n * // Force streaming mode for memory efficiency\n * const nodeStreaming = yield* createTrimVideoNode(\"trim-3\", {\n * startTime: 5,\n * endTime: 25\n * }, {\n * mode: \"streaming\",\n * naming: { mode: \"auto\" }\n * });\n * ```\n */\nexport function createTrimVideoNode(\n id: string,\n params: TrimVideoParams,\n options?: {\n keepOutput?: boolean;\n naming?: FileNamingConfig;\n mode?: TransformMode;\n streamingConfig?: StreamingConfig;\n },\n) {\n return Effect.gen(function* () {\n const videoService = yield* VideoPlugin;\n\n // Validate params\n if (params.endTime !== undefined && params.endTime <= params.startTime) {\n return yield* UploadistaError.fromCode(\"VALIDATION_ERROR\", {\n body: \"endTime must be greater than startTime\",\n details: { params },\n }).toEffect();\n }\n\n if (\n params.duration !== undefined &&\n params.endTime !== undefined &&\n params.duration !== params.endTime - params.startTime\n ) {\n return yield* UploadistaError.fromCode(\"VALIDATION_ERROR\", {\n body: \"Cannot specify both endTime and duration with conflicting values\",\n details: { params },\n }).toEffect();\n }\n\n if (params.duration !== undefined && params.duration <= 0) {\n return yield* UploadistaError.fromCode(\"VALIDATION_ERROR\", {\n body: \"duration must be greater than 0\",\n details: { params },\n }).toEffect();\n }\n\n // Determine if streaming is available and requested\n const supportsStreaming = videoService.supportsStreaming ?? false;\n const requestedMode = options?.mode ?? \"auto\";\n\n // If streaming requested but not supported, fall back to buffered\n const effectiveMode: TransformMode =\n requestedMode === \"buffered\"\n ? \"buffered\"\n : supportsStreaming\n ? requestedMode\n : \"buffered\";\n\n // Use video-specific streaming config as default\n const streamingConfig: StreamingConfig = {\n ...DEFAULT_VIDEO_STREAMING_CONFIG,\n ...options?.streamingConfig,\n };\n\n // Build naming config with auto suffix for trim\n const namingConfig: FileNamingConfig | undefined = options?.naming\n ? {\n ...options.naming,\n autoSuffix: options.naming.autoSuffix ?? (() => \"trimmed\"),\n }\n : undefined;\n\n return yield* createTransformNode({\n id,\n name: \"Trim Video\",\n description: \"Extracts a segment from the video\",\n nodeTypeId: \"trim-video\",\n outputTypeId: STORAGE_OUTPUT_TYPE_ID,\n keepOutput: options?.keepOutput,\n naming: namingConfig,\n nodeType: \"trim\",\n mode: effectiveMode,\n streamingConfig,\n // Buffered transform\n transform: (inputBytes) =>\n Effect.map(videoService.trim(inputBytes, params), (trimmedBytes) => ({\n bytes: trimmedBytes,\n })),\n // Streaming transform\n streamingTransform: videoService.trimStream\n ? (inputStream) =>\n Effect.gen(function* () {\n const trimStreamFn = videoService.trimStream;\n if (!trimStreamFn) {\n throw new Error(\"trimStream not available\");\n }\n const outputStream = yield* trimStreamFn(inputStream, params);\n return { stream: outputStream };\n })\n : undefined,\n });\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["DEFAULT_VIDEO_STREAMING_CONFIG","DEFAULT_VIDEO_STREAMING_CONFIG"],"sources":["../src/describe-video-node.ts","../src/resize-node.ts","../src/thumbnail-node.ts","../src/transcode-node.ts","../src/trim-node.ts"],"sourcesContent":["import {\n createTransformNode,\n STORAGE_OUTPUT_TYPE_ID,\n VideoPlugin,\n} from \"@uploadista/core/flow\";\nimport { Effect } from \"effect\";\n\n/**\n * Creates a Describe Video metadata extraction node\n *\n * Extracts comprehensive metadata from the video file including duration,\n * resolution, codec, bitrate, and audio information. The metadata is stored\n * in the file context for downstream nodes while passing through the original bytes.\n *\n * @param id - Unique node identifier\n * @returns Effect that resolves to the configured node\n *\n * @example\n * ```typescript\n * const node = yield* createDescribeVideoNode(\"describe-1\");\n * ```\n */\nexport function createDescribeVideoNode(\n id: string,\n options?: { keepOutput?: boolean },\n) {\n return Effect.gen(function* () {\n const videoService = yield* VideoPlugin;\n\n return yield* createTransformNode({\n id,\n name: \"Describe Video\",\n description:\n \"Extracts video metadata (duration, resolution, codec, etc.)\",\n nodeTypeId: \"describe-video\",\n outputTypeId: STORAGE_OUTPUT_TYPE_ID,\n keepOutput: options?.keepOutput,\n transform: (inputBytes, file) =>\n Effect.gen(function* () {\n // Extract metadata\n const metadata = yield* videoService.describe(inputBytes);\n\n // Store metadata in file context for downstream nodes\n return {\n bytes: inputBytes, // Pass through original bytes unchanged\n metadata: {\n ...file.metadata,\n videoInfo: metadata,\n },\n };\n }),\n });\n });\n}\n","import {\n createTransformNode,\n type FileNamingConfig,\n type ResizeVideoParams,\n STORAGE_OUTPUT_TYPE_ID,\n type StreamingConfig,\n type TransformMode,\n VideoPlugin,\n} from \"@uploadista/core/flow\";\nimport { Effect } from \"effect\";\n\n// Default streaming config for video processing\nconst DEFAULT_VIDEO_STREAMING_CONFIG: StreamingConfig = {\n fileSizeThreshold: 10_000_000, // 10MB threshold for video\n chunkSize: 1_048_576, // 1MB chunks\n};\n\n/**\n * Creates a Resize video processing node\n *\n * Changes video resolution while optionally maintaining aspect ratio.\n *\n * Supports both buffered and streaming modes for memory-efficient processing\n * of large videos. In streaming mode, the output is streamed directly to storage,\n * reducing peak memory usage.\n *\n * @param id - Unique node identifier\n * @param params - Resize parameters\n * @param options - Optional configuration\n * @param options.keepOutput - Whether to keep output in flow results\n * @param options.naming - File naming configuration (auto suffix: `${width}x${height}`)\n * @param options.mode - Transform mode: \"buffered\", \"streaming\", or \"auto\" (default)\n * @param options.streamingConfig - Streaming configuration (file size threshold, chunk size)\n *\n * @example\n * ```typescript\n * // Auto mode (default) - uses streaming for files > 10MB, otherwise buffered\n * const node = yield* createVideoResizeNode(\"resize-1\", {\n * width: 1280,\n * height: 720,\n * aspectRatio: \"keep\",\n * scaling: \"bicubic\"\n * }, {\n * naming: { mode: \"auto\" }\n * });\n *\n * // Force buffered mode for small files\n * const nodeBuffered = yield* createVideoResizeNode(\"resize-2\", {\n * width: 1920,\n * height: 1080\n * }, {\n * mode: \"buffered\",\n * naming: { mode: \"auto\" }\n * });\n *\n * // Force streaming mode for memory efficiency\n * const nodeStreaming = yield* createVideoResizeNode(\"resize-3\", {\n * width: 1280,\n * height: 720\n * }, {\n * mode: \"streaming\",\n * naming: { mode: \"auto\" }\n * });\n * ```\n */\nexport function createVideoResizeNode(\n id: string,\n params: ResizeVideoParams,\n options?: {\n keepOutput?: boolean;\n naming?: FileNamingConfig;\n mode?: TransformMode;\n streamingConfig?: StreamingConfig;\n },\n) {\n return Effect.gen(function* () {\n const videoService = yield* VideoPlugin;\n\n // Determine if streaming is available and requested\n const supportsStreaming = videoService.supportsStreaming ?? false;\n const requestedMode = options?.mode ?? \"auto\";\n\n // If streaming requested but not supported, fall back to buffered\n const effectiveMode: TransformMode =\n requestedMode === \"buffered\"\n ? \"buffered\"\n : supportsStreaming\n ? requestedMode\n : \"buffered\";\n\n // Use video-specific streaming config as default\n const streamingConfig: StreamingConfig = {\n ...DEFAULT_VIDEO_STREAMING_CONFIG,\n ...options?.streamingConfig,\n };\n\n // Build naming config with auto suffix for video resize\n const namingConfig: FileNamingConfig | undefined = options?.naming\n ? {\n ...options.naming,\n autoSuffix:\n options.naming.autoSuffix ??\n ((ctx) =>\n `${ctx.width ?? params.width}x${ctx.height ?? params.height}`),\n }\n : undefined;\n\n return yield* createTransformNode({\n id,\n name: \"Resize Video\",\n description: \"Changes video resolution\",\n nodeTypeId: \"resize-video\",\n outputTypeId: STORAGE_OUTPUT_TYPE_ID,\n keepOutput: options?.keepOutput,\n naming: namingConfig,\n nodeType: \"resize-video\",\n namingVars: { width: params.width, height: params.height },\n mode: effectiveMode,\n streamingConfig,\n // Buffered transform\n transform: (inputBytes) =>\n Effect.map(videoService.resize(inputBytes, params), (resizedBytes) => ({\n bytes: resizedBytes,\n })),\n // Streaming transform\n streamingTransform: videoService.resizeStream\n ? (inputStream) =>\n Effect.gen(function* () {\n const resizeStreamFn = videoService.resizeStream;\n if (!resizeStreamFn) {\n throw new Error(\"resizeStream not available\");\n }\n const outputStream = yield* resizeStreamFn(inputStream, params);\n return { stream: outputStream };\n })\n : undefined,\n });\n });\n}\n","import {\n applyFileNaming,\n buildNamingContext,\n createTransformNode,\n type ExtractFrameVideoParams,\n type FileNamingConfig,\n getBaseName,\n STORAGE_OUTPUT_TYPE_ID,\n VideoPlugin,\n} from \"@uploadista/core/flow\";\nimport { Effect } from \"effect\";\n\n/**\n * Creates a Thumbnail generation node\n *\n * Extracts a single frame from the video as an image (JPEG or PNG).\n *\n * @param id - Unique node identifier\n * @param params - Frame extraction parameters\n * @param options - Optional configuration\n * @param options.keepOutput - Whether to keep output in flow results\n * @param options.naming - File naming configuration (auto suffix: `thumb`)\n *\n * @example\n * ```typescript\n * // With auto-naming: \"video.mp4\" -> \"video-thumb.jpg\"\n * const node = yield* createVideoThumbnailNode(\"thumbnail-1\", {\n * timestamp: 15,\n * format: \"jpeg\",\n * quality: 85\n * }, {\n * naming: { mode: \"auto\" }\n * });\n * ```\n */\nexport function createVideoThumbnailNode(\n id: string,\n params: ExtractFrameVideoParams,\n options?: { keepOutput?: boolean; naming?: FileNamingConfig },\n) {\n return Effect.gen(function* () {\n const videoService = yield* VideoPlugin;\n\n const format = params.format || \"jpeg\";\n\n return yield* createTransformNode({\n id,\n name: \"Generate Thumbnail\",\n description: \"Extracts a frame from video as an image\",\n nodeTypeId: \"thumbnail-video\",\n outputTypeId: STORAGE_OUTPUT_TYPE_ID,\n keepOutput: options?.keepOutput,\n // Note: naming is handled in transform since format changes extension\n nodeType: \"thumbnail\",\n namingVars: { format },\n transform: (inputBytes, file) =>\n Effect.map(\n videoService.extractFrame(inputBytes, params),\n (imageBytes) => {\n // Map output to image MIME type and extension\n const mimeType = format === \"png\" ? \"image/png\" : \"image/jpeg\";\n const extension = format === \"png\" ? \"png\" : \"jpg\";\n\n // Get original fileName\n const fileName = file.metadata?.fileName;\n let newFileName: string | undefined;\n\n if (fileName && typeof fileName === \"string\") {\n // Apply naming if configured\n if (options?.naming) {\n const namingConfig: FileNamingConfig = {\n ...options.naming,\n autoSuffix: options.naming.autoSuffix ?? (() => \"thumb\"),\n };\n const namingContext = buildNamingContext(\n file,\n {\n flowId: file.flow?.flowId ?? \"\",\n jobId: file.flow?.jobId ?? \"\",\n nodeId: id,\n nodeType: \"thumbnail\",\n },\n { format },\n );\n // Apply naming to get base name with suffix\n const namedFile = applyFileNaming(\n file,\n namingContext,\n namingConfig,\n );\n // Replace extension with image extension\n newFileName = `${getBaseName(namedFile)}.${extension}`;\n } else {\n // No naming config, just update extension\n newFileName = fileName.replace(/\\.[^.]+$/, `.${extension}`);\n }\n }\n\n return {\n bytes: imageBytes,\n type: mimeType,\n fileName: newFileName,\n };\n },\n ),\n });\n });\n}\n","import {\n applyFileNaming,\n buildNamingContext,\n createTransformNode,\n type FileNamingConfig,\n getBaseName,\n STORAGE_OUTPUT_TYPE_ID,\n type StreamingConfig,\n type TranscodeVideoParams,\n type TransformMode,\n VideoPlugin,\n} from \"@uploadista/core/flow\";\nimport { Effect } from \"effect\";\n\n// Default streaming config for video processing\nconst DEFAULT_VIDEO_STREAMING_CONFIG: StreamingConfig = {\n fileSizeThreshold: 10_000_000, // 10MB threshold for video\n chunkSize: 1_048_576, // 1MB chunks\n};\n\n// Map video format to MIME type\nconst formatToMimeType: Record<TranscodeVideoParams[\"format\"], string> = {\n mp4: \"video/mp4\",\n webm: \"video/webm\",\n mov: \"video/quicktime\",\n avi: \"video/x-msvideo\",\n};\n\n// Map video format to file extension\nconst formatToExtension: Record<TranscodeVideoParams[\"format\"], string> = {\n mp4: \"mp4\",\n webm: \"webm\",\n mov: \"mov\",\n avi: \"avi\",\n};\n\n/**\n * Creates a Transcode video processing node\n *\n * Converts video to specified format and codec, optionally adjusting bitrates.\n *\n * Supports both buffered and streaming modes for memory-efficient processing\n * of large videos. In streaming mode, the output is streamed directly to storage,\n * reducing peak memory usage.\n *\n * @param id - Unique node identifier\n * @param params - Transcode parameters\n * @param options - Optional configuration\n * @param options.keepOutput - Whether to keep output in flow results\n * @param options.naming - File naming configuration (auto suffix: `${format}`)\n * @param options.mode - Transform mode: \"buffered\", \"streaming\", or \"auto\" (default)\n * @param options.streamingConfig - Streaming configuration (file size threshold, chunk size)\n *\n * @example\n * ```typescript\n * // Auto mode (default) - uses streaming for files > 10MB, otherwise buffered\n * const node = yield* createTranscodeVideoNode(\"transcode-1\", {\n * format: \"webm\",\n * codec: \"vp9\",\n * videoBitrate: \"1000k\"\n * }, {\n * naming: { mode: \"auto\" }\n * });\n *\n * // Force buffered mode for small files\n * const nodeBuffered = yield* createTranscodeVideoNode(\"transcode-2\", {\n * format: \"mp4\",\n * codec: \"h264\"\n * }, {\n * mode: \"buffered\",\n * naming: { mode: \"auto\" }\n * });\n *\n * // Force streaming mode for memory efficiency\n * const nodeStreaming = yield* createTranscodeVideoNode(\"transcode-3\", {\n * format: \"mp4\",\n * codec: \"h264\"\n * }, {\n * mode: \"streaming\",\n * naming: { mode: \"auto\" }\n * });\n * ```\n */\nexport function createTranscodeVideoNode(\n id: string,\n params: TranscodeVideoParams,\n options?: {\n keepOutput?: boolean;\n naming?: FileNamingConfig;\n mode?: TransformMode;\n streamingConfig?: StreamingConfig;\n },\n) {\n return Effect.gen(function* () {\n const videoService = yield* VideoPlugin;\n\n // Determine if streaming is available and requested\n const supportsStreaming = videoService.supportsStreaming ?? false;\n const requestedMode = options?.mode ?? \"auto\";\n\n // If streaming requested but not supported, fall back to buffered\n const effectiveMode: TransformMode =\n requestedMode === \"buffered\"\n ? \"buffered\"\n : supportsStreaming\n ? requestedMode\n : \"buffered\";\n\n // Use video-specific streaming config as default\n const streamingConfig: StreamingConfig = {\n ...DEFAULT_VIDEO_STREAMING_CONFIG,\n ...options?.streamingConfig,\n };\n\n // Helper to build output metadata\n const buildOutputMetadata = (file: {\n metadata?: Record<string, unknown>;\n flow?: { flowId?: string; jobId?: string };\n }) => {\n const newType = formatToMimeType[params.format];\n const newExtension = formatToExtension[params.format];\n\n const fileName = file.metadata?.fileName;\n let newFileName: string | undefined;\n\n if (fileName && typeof fileName === \"string\") {\n if (options?.naming) {\n const namingConfig: FileNamingConfig = {\n ...options.naming,\n autoSuffix:\n options.naming.autoSuffix ??\n ((ctx) => ctx.format ?? params.format),\n };\n const namingContext = buildNamingContext(\n file as Parameters<typeof buildNamingContext>[0],\n {\n flowId: file.flow?.flowId ?? \"\",\n jobId: file.flow?.jobId ?? \"\",\n nodeId: id,\n nodeType: \"transcode\",\n },\n { format: params.format },\n );\n const namedFile = applyFileNaming(\n file as Parameters<typeof applyFileNaming>[0],\n namingContext,\n namingConfig,\n );\n newFileName = `${getBaseName(namedFile)}.${newExtension}`;\n } else {\n newFileName = fileName.replace(/\\.[^.]+$/, `.${newExtension}`);\n }\n }\n\n return { newType, newFileName };\n };\n\n return yield* createTransformNode({\n id,\n name: \"Transcode\",\n description: \"Converts video to specified format and codec\",\n nodeTypeId: \"transcode-video\",\n outputTypeId: STORAGE_OUTPUT_TYPE_ID,\n keepOutput: options?.keepOutput,\n nodeType: \"transcode\",\n namingVars: { format: params.format },\n mode: effectiveMode,\n streamingConfig,\n // Buffered transform\n transform: (inputBytes, file) =>\n Effect.map(\n videoService.transcode(inputBytes, params),\n (transcodedBytes) => {\n const { newType, newFileName } = buildOutputMetadata(file);\n return {\n bytes: transcodedBytes,\n type: newType,\n fileName: newFileName,\n };\n },\n ),\n // Streaming transform\n streamingTransform: videoService.transcodeStream\n ? (inputStream, file) =>\n Effect.gen(function* () {\n const transcodeStreamFn = videoService.transcodeStream;\n if (!transcodeStreamFn) {\n throw new Error(\"transcodeStream not available\");\n }\n const outputStream = yield* transcodeStreamFn(\n inputStream,\n params,\n );\n const { newType, newFileName } = buildOutputMetadata(file);\n return {\n stream: outputStream,\n type: newType,\n fileName: newFileName,\n };\n })\n : undefined,\n });\n });\n}\n","import { UploadistaError } from \"@uploadista/core/errors\";\nimport {\n createTransformNode,\n type FileNamingConfig,\n STORAGE_OUTPUT_TYPE_ID,\n type StreamingConfig,\n type TransformMode,\n type TrimVideoParams,\n VideoPlugin,\n} from \"@uploadista/core/flow\";\nimport { Effect } from \"effect\";\n\n// Default streaming config for video processing\nconst DEFAULT_VIDEO_STREAMING_CONFIG: StreamingConfig = {\n fileSizeThreshold: 10_000_000, // 10MB threshold for video\n chunkSize: 1_048_576, // 1MB chunks\n};\n\n/**\n * Creates a Trim video processing node\n *\n * Extracts a segment from the video by time range.\n *\n * Supports both buffered and streaming modes for memory-efficient processing\n * of large videos. In streaming mode, the output is streamed directly to storage,\n * reducing peak memory usage.\n *\n * @param id - Unique node identifier\n * @param params - Trim parameters\n * @param options - Optional configuration\n * @param options.keepOutput - Whether to keep output in flow results\n * @param options.naming - File naming configuration (auto suffix: `trimmed`)\n * @param options.mode - Transform mode: \"buffered\", \"streaming\", or \"auto\" (default)\n * @param options.streamingConfig - Streaming configuration (file size threshold, chunk size)\n *\n * @example\n * ```typescript\n * // Auto mode (default) - uses streaming for files > 10MB, otherwise buffered\n * const node = yield* createTrimVideoNode(\"trim-1\", {\n * startTime: 10,\n * endTime: 30\n * }, {\n * naming: { mode: \"auto\" }\n * });\n *\n * // Force buffered mode for small files\n * const nodeBuffered = yield* createTrimVideoNode(\"trim-2\", {\n * startTime: 0,\n * duration: 60\n * }, {\n * mode: \"buffered\",\n * naming: { mode: \"auto\" }\n * });\n *\n * // Force streaming mode for memory efficiency\n * const nodeStreaming = yield* createTrimVideoNode(\"trim-3\", {\n * startTime: 5,\n * endTime: 25\n * }, {\n * mode: \"streaming\",\n * naming: { mode: \"auto\" }\n * });\n * ```\n */\nexport function createTrimVideoNode(\n id: string,\n params: TrimVideoParams,\n options?: {\n keepOutput?: boolean;\n naming?: FileNamingConfig;\n mode?: TransformMode;\n streamingConfig?: StreamingConfig;\n },\n) {\n return Effect.gen(function* () {\n const videoService = yield* VideoPlugin;\n\n // Validate params\n if (params.endTime !== undefined && params.endTime <= params.startTime) {\n return yield* UploadistaError.fromCode(\"VALIDATION_ERROR\", {\n body: \"endTime must be greater than startTime\",\n details: { params },\n }).toEffect();\n }\n\n if (\n params.duration !== undefined &&\n params.endTime !== undefined &&\n params.duration !== params.endTime - params.startTime\n ) {\n return yield* UploadistaError.fromCode(\"VALIDATION_ERROR\", {\n body: \"Cannot specify both endTime and duration with conflicting values\",\n details: { params },\n }).toEffect();\n }\n\n if (params.duration !== undefined && params.duration <= 0) {\n return yield* UploadistaError.fromCode(\"VALIDATION_ERROR\", {\n body: \"duration must be greater than 0\",\n details: { params },\n }).toEffect();\n }\n\n // Determine if streaming is available and requested\n const supportsStreaming = videoService.supportsStreaming ?? false;\n const requestedMode = options?.mode ?? \"auto\";\n\n // If streaming requested but not supported, fall back to buffered\n const effectiveMode: TransformMode =\n requestedMode === \"buffered\"\n ? \"buffered\"\n : supportsStreaming\n ? requestedMode\n : \"buffered\";\n\n // Use video-specific streaming config as default\n const streamingConfig: StreamingConfig = {\n ...DEFAULT_VIDEO_STREAMING_CONFIG,\n ...options?.streamingConfig,\n };\n\n // Build naming config with auto suffix for trim\n const namingConfig: FileNamingConfig | undefined = options?.naming\n ? {\n ...options.naming,\n autoSuffix: options.naming.autoSuffix ?? (() => \"trimmed\"),\n }\n : undefined;\n\n return yield* createTransformNode({\n id,\n name: \"Trim Video\",\n description: \"Extracts a segment from the video\",\n nodeTypeId: \"trim-video\",\n outputTypeId: STORAGE_OUTPUT_TYPE_ID,\n keepOutput: options?.keepOutput,\n naming: namingConfig,\n nodeType: \"trim\",\n mode: effectiveMode,\n streamingConfig,\n // Buffered transform\n transform: (inputBytes) =>\n Effect.map(videoService.trim(inputBytes, params), (trimmedBytes) => ({\n bytes: trimmedBytes,\n })),\n // Streaming transform\n streamingTransform: videoService.trimStream\n ? (inputStream) =>\n Effect.gen(function* () {\n const trimStreamFn = videoService.trimStream;\n if (!trimStreamFn) {\n throw new Error(\"trimStream not available\");\n }\n const outputStream = yield* trimStreamFn(inputStream, params);\n return { stream: outputStream };\n })\n : undefined,\n });\n });\n}\n"],"mappings":"iQAsBA,SAAgB,EACd,EACA,EACA,CACA,OAAO,EAAO,IAAI,WAAa,CAC7B,IAAM,EAAe,MAAO,EAE5B,OAAO,MAAO,EAAoB,CAChC,KACA,KAAM,iBACN,YACE,8DACF,WAAY,iBACZ,aAAc,EACd,WAAY,GAAS,WACrB,WAAY,EAAY,IACtB,EAAO,IAAI,WAAa,CAEtB,IAAM,EAAW,MAAO,EAAa,SAAS,EAAW,CAGzD,MAAO,CACL,MAAO,EACP,SAAU,CACR,GAAG,EAAK,SACR,UAAW,EACZ,CACF,EACD,CACL,CAAC,EACF,CCxCJ,MAAMA,EAAkD,CACtD,kBAAmB,IACnB,UAAW,QACZ,CAkDD,SAAgB,EACd,EACA,EACA,EAMA,CACA,OAAO,EAAO,IAAI,WAAa,CAC7B,IAAM,EAAe,MAAO,EAGtB,EAAoB,EAAa,mBAAqB,GACtD,EAAgB,GAAS,MAAQ,OAGjC,EACJ,IAAkB,WACd,WACA,EACE,EACA,WAGF,EAAmC,CACvC,GAAGA,EACH,GAAG,GAAS,gBACb,CAGK,EAA6C,GAAS,OACxD,CACE,GAAG,EAAQ,OACX,WACE,EAAQ,OAAO,aACb,GACA,GAAG,EAAI,OAAS,EAAO,MAAM,GAAG,EAAI,QAAU,EAAO,UAC1D,CACD,IAAA,GAEJ,OAAO,MAAO,EAAoB,CAChC,KACA,KAAM,eACN,YAAa,2BACb,WAAY,eACZ,aAAc,EACd,WAAY,GAAS,WACrB,OAAQ,EACR,SAAU,eACV,WAAY,CAAE,MAAO,EAAO,MAAO,OAAQ,EAAO,OAAQ,CAC1D,KAAM,EACN,kBAEA,UAAY,GACV,EAAO,IAAI,EAAa,OAAO,EAAY,EAAO,CAAG,IAAkB,CACrE,MAAO,EACR,EAAE,CAEL,mBAAoB,EAAa,aAC5B,GACC,EAAO,IAAI,WAAa,CACtB,IAAM,EAAiB,EAAa,aACpC,GAAI,CAAC,EACH,MAAU,MAAM,6BAA6B,CAG/C,MAAO,CAAE,OADY,MAAO,EAAe,EAAa,EAAO,CAChC,EAC/B,CACJ,IAAA,GACL,CAAC,EACF,CCtGJ,SAAgB,EACd,EACA,EACA,EACA,CACA,OAAO,EAAO,IAAI,WAAa,CAC7B,IAAM,EAAe,MAAO,EAEtB,EAAS,EAAO,QAAU,OAEhC,OAAO,MAAO,EAAoB,CAChC,KACA,KAAM,qBACN,YAAa,0CACb,WAAY,kBACZ,aAAc,EACd,WAAY,GAAS,WAErB,SAAU,YACV,WAAY,CAAE,SAAQ,CACtB,WAAY,EAAY,IACtB,EAAO,IACL,EAAa,aAAa,EAAY,EAAO,CAC5C,GAAe,CAEd,IAAM,EAAW,IAAW,MAAQ,YAAc,aAC5C,EAAY,IAAW,MAAQ,MAAQ,MAGvC,EAAW,EAAK,UAAU,SAC5B,EAEJ,GAAI,GAAY,OAAO,GAAa,SAElC,GAAI,GAAS,OAAQ,CACnB,IAAM,EAAiC,CACrC,GAAG,EAAQ,OACX,WAAY,EAAQ,OAAO,iBAAqB,SACjD,CAkBD,EAAc,GAAG,EANC,EAChB,EAZoB,EACpB,EACA,CACE,OAAQ,EAAK,MAAM,QAAU,GAC7B,MAAO,EAAK,MAAM,OAAS,GAC3B,OAAQ,EACR,SAAU,YACX,CACD,CAAE,SAAQ,CACX,CAKC,EACD,CAEsC,CAAC,GAAG,SAG3C,EAAc,EAAS,QAAQ,WAAY,IAAI,IAAY,CAI/D,MAAO,CACL,MAAO,EACP,KAAM,EACN,SAAU,EACX,EAEJ,CACJ,CAAC,EACF,CC3FJ,MAAMC,EAAkD,CACtD,kBAAmB,IACnB,UAAW,QACZ,CAGK,EAAmE,CACvE,IAAK,YACL,KAAM,aACN,IAAK,kBACL,IAAK,kBACN,CAGK,EAAoE,CACxE,IAAK,MACL,KAAM,OACN,IAAK,MACL,IAAK,MACN,CAiDD,SAAgB,EACd,EACA,EACA,EAMA,CACA,OAAO,EAAO,IAAI,WAAa,CAC7B,IAAM,EAAe,MAAO,EAGtB,EAAoB,EAAa,mBAAqB,GACtD,EAAgB,GAAS,MAAQ,OAGjC,EACJ,IAAkB,WACd,WACA,EACE,EACA,WAGF,EAAmC,CACvC,GAAGA,EACH,GAAG,GAAS,gBACb,CAGK,EAAuB,GAGvB,CACJ,IAAM,EAAU,EAAiB,EAAO,QAClC,EAAe,EAAkB,EAAO,QAExC,EAAW,EAAK,UAAU,SAC5B,EAEJ,GAAI,GAAY,OAAO,GAAa,SAClC,GAAI,GAAS,OAAQ,CACnB,IAAM,EAAiC,CACrC,GAAG,EAAQ,OACX,WACE,EAAQ,OAAO,aACb,GAAQ,EAAI,QAAU,EAAO,QAClC,CAgBD,EAAc,GAAG,EALC,EAChB,EAXoB,EACpB,EACA,CACE,OAAQ,EAAK,MAAM,QAAU,GAC7B,MAAO,EAAK,MAAM,OAAS,GAC3B,OAAQ,EACR,SAAU,YACX,CACD,CAAE,OAAQ,EAAO,OAAQ,CAC1B,CAIC,EACD,CACsC,CAAC,GAAG,SAE3C,EAAc,EAAS,QAAQ,WAAY,IAAI,IAAe,CAIlE,MAAO,CAAE,UAAS,cAAa,EAGjC,OAAO,MAAO,EAAoB,CAChC,KACA,KAAM,YACN,YAAa,+CACb,WAAY,kBACZ,aAAc,EACd,WAAY,GAAS,WACrB,SAAU,YACV,WAAY,CAAE,OAAQ,EAAO,OAAQ,CACrC,KAAM,EACN,kBAEA,WAAY,EAAY,IACtB,EAAO,IACL,EAAa,UAAU,EAAY,EAAO,CACzC,GAAoB,CACnB,GAAM,CAAE,UAAS,eAAgB,EAAoB,EAAK,CAC1D,MAAO,CACL,MAAO,EACP,KAAM,EACN,SAAU,EACX,EAEJ,CAEH,mBAAoB,EAAa,iBAC5B,EAAa,IACZ,EAAO,IAAI,WAAa,CACtB,IAAM,EAAoB,EAAa,gBACvC,GAAI,CAAC,EACH,MAAU,MAAM,gCAAgC,CAElD,IAAM,EAAe,MAAO,EAC1B,EACA,EACD,CACK,CAAE,UAAS,eAAgB,EAAoB,EAAK,CAC1D,MAAO,CACL,OAAQ,EACR,KAAM,EACN,SAAU,EACX,EACD,CACJ,IAAA,GACL,CAAC,EACF,CC7LJ,MAAM,EAAkD,CACtD,kBAAmB,IACnB,UAAW,QACZ,CAgDD,SAAgB,EACd,EACA,EACA,EAMA,CACA,OAAO,EAAO,IAAI,WAAa,CAC7B,IAAM,EAAe,MAAO,EAG5B,GAAI,EAAO,UAAY,IAAA,IAAa,EAAO,SAAW,EAAO,UAC3D,OAAO,MAAO,EAAgB,SAAS,mBAAoB,CACzD,KAAM,yCACN,QAAS,CAAE,SAAQ,CACpB,CAAC,CAAC,UAAU,CAGf,GACE,EAAO,WAAa,IAAA,IACpB,EAAO,UAAY,IAAA,IACnB,EAAO,WAAa,EAAO,QAAU,EAAO,UAE5C,OAAO,MAAO,EAAgB,SAAS,mBAAoB,CACzD,KAAM,mEACN,QAAS,CAAE,SAAQ,CACpB,CAAC,CAAC,UAAU,CAGf,GAAI,EAAO,WAAa,IAAA,IAAa,EAAO,UAAY,EACtD,OAAO,MAAO,EAAgB,SAAS,mBAAoB,CACzD,KAAM,kCACN,QAAS,CAAE,SAAQ,CACpB,CAAC,CAAC,UAAU,CAIf,IAAM,EAAoB,EAAa,mBAAqB,GACtD,EAAgB,GAAS,MAAQ,OAGjC,EACJ,IAAkB,WACd,WACA,EACE,EACA,WAGF,EAAmC,CACvC,GAAG,EACH,GAAG,GAAS,gBACb,CAGK,EAA6C,GAAS,OACxD,CACE,GAAG,EAAQ,OACX,WAAY,EAAQ,OAAO,iBAAqB,WACjD,CACD,IAAA,GAEJ,OAAO,MAAO,EAAoB,CAChC,KACA,KAAM,aACN,YAAa,oCACb,WAAY,aACZ,aAAc,EACd,WAAY,GAAS,WACrB,OAAQ,EACR,SAAU,OACV,KAAM,EACN,kBAEA,UAAY,GACV,EAAO,IAAI,EAAa,KAAK,EAAY,EAAO,CAAG,IAAkB,CACnE,MAAO,EACR,EAAE,CAEL,mBAAoB,EAAa,WAC5B,GACC,EAAO,IAAI,WAAa,CACtB,IAAM,EAAe,EAAa,WAClC,GAAI,CAAC,EACH,MAAU,MAAM,2BAA2B,CAG7C,MAAO,CAAE,OADY,MAAO,EAAa,EAAa,EAAO,CAC9B,EAC/B,CACJ,IAAA,GACL,CAAC,EACF"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@uploadista/flow-videos-nodes",
3
3
  "type": "module",
4
- "version": "0.0.20",
4
+ "version": "0.1.0-beta.5",
5
5
  "description": "Video processing nodes for Uploadista Flow",
6
6
  "license": "MIT",
7
7
  "author": "Uploadista",
@@ -14,7 +14,7 @@
14
14
  }
15
15
  },
16
16
  "dependencies": {
17
- "@uploadista/core": "0.0.20"
17
+ "@uploadista/core": "0.1.0-beta.5"
18
18
  },
19
19
  "peerDependencies": {
20
20
  "effect": "^3.0.0",
@@ -22,19 +22,19 @@
22
22
  },
23
23
  "devDependencies": {
24
24
  "@effect/vitest": "0.27.0",
25
- "@types/node": "24.10.4",
26
- "effect": "3.19.12",
27
- "tsdown": "0.18.0",
28
- "vitest": "4.0.15",
29
- "zod": "4.2.0",
30
- "@uploadista/typescript-config": "0.0.20"
25
+ "@types/node": "24.10.8",
26
+ "effect": "3.19.14",
27
+ "tsdown": "0.19.0",
28
+ "vitest": "4.0.17",
29
+ "zod": "4.3.5",
30
+ "@uploadista/typescript-config": "0.1.0-beta.5"
31
31
  },
32
32
  "scripts": {
33
33
  "build": "tsc --noEmit && tsdown",
34
34
  "format": "biome format --write ./src",
35
35
  "lint": "biome lint --write ./src",
36
36
  "check": "biome check --write ./src",
37
- "test": "vitest",
37
+ "test": "vitest run",
38
38
  "test:run": "vitest run",
39
39
  "test:watch": "vitest watch"
40
40
  }
@@ -100,7 +100,8 @@ export function createVideoResizeNode(
100
100
  ...options.naming,
101
101
  autoSuffix:
102
102
  options.naming.autoSuffix ??
103
- ((ctx) => `${ctx.width ?? params.width}x${ctx.height ?? params.height}`),
103
+ ((ctx) =>
104
+ `${ctx.width ?? params.width}x${ctx.height ?? params.height}`),
104
105
  }
105
106
  : undefined;
106
107
 
@@ -83,7 +83,11 @@ export function createVideoThumbnailNode(
83
83
  { format },
84
84
  );
85
85
  // Apply naming to get base name with suffix
86
- const namedFile = applyFileNaming(file, namingContext, namingConfig);
86
+ const namedFile = applyFileNaming(
87
+ file,
88
+ namingContext,
89
+ namingConfig,
90
+ );
87
91
  // Replace extension with image extension
88
92
  newFileName = `${getBaseName(namedFile)}.${extension}`;
89
93
  } else {
@@ -128,7 +128,8 @@ export function createTranscodeVideoNode(
128
128
  const namingConfig: FileNamingConfig = {
129
129
  ...options.naming,
130
130
  autoSuffix:
131
- options.naming.autoSuffix ?? ((ctx) => ctx.format ?? params.format),
131
+ options.naming.autoSuffix ??
132
+ ((ctx) => ctx.format ?? params.format),
132
133
  };
133
134
  const namingContext = buildNamingContext(
134
135
  file as Parameters<typeof buildNamingContext>[0],
@@ -186,7 +187,10 @@ export function createTranscodeVideoNode(
186
187
  if (!transcodeStreamFn) {
187
188
  throw new Error("transcodeStream not available");
188
189
  }
189
- const outputStream = yield* transcodeStreamFn(inputStream, params);
190
+ const outputStream = yield* transcodeStreamFn(
191
+ inputStream,
192
+ params,
193
+ );
190
194
  const { newType, newFileName } = buildOutputMetadata(file);
191
195
  return {
192
196
  stream: outputStream,
@@ -1,4 +1,4 @@
1
- import { TestUploadServer, TestVideoPlugin } from "@uploadista/core/testing";
1
+ import { TestUploadEngine, TestVideoPlugin } from "@uploadista/core/testing";
2
2
  import type { UploadFile } from "@uploadista/core/types";
3
3
  import { it as effectIt } from "@effect/vitest";
4
4
  import { Effect, Layer } from "effect";
@@ -12,7 +12,7 @@ import {
12
12
  } from "../src";
13
13
 
14
14
  // Combined test layer with all required dependencies
15
- const TestLayer = Layer.merge(TestUploadServer, TestVideoPlugin);
15
+ const TestLayer = Layer.mergeAll(TestUploadEngine, TestVideoPlugin);
16
16
 
17
17
  // Helper to create test video file
18
18
  const createTestVideoFile = (): UploadFile => ({