@uploadista/flow-videos-av-node 0.0.13-beta.1
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/.turbo/turbo-build.log +16 -0
- package/LICENSE +21 -0
- package/README.md +186 -0
- package/dist/index.d.mts +99 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +452 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +34 -0
- package/src/index.ts +9 -0
- package/src/utils/av-check.ts +30 -0
- package/src/utils/format-mappings.ts +69 -0
- package/src/utils/temp-file-manager.ts +43 -0
- package/src/video-plugin-layer.ts +71 -0
- package/src/video-plugin.ts +492 -0
- package/tsconfig.json +14 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
> @uploadista/flow-videos-av-node@0.0.12 build /Users/denislaboureyras/Documents/uploadista/dev/uploadista-workspace/uploadista-sdk/packages/flow/videos/av-node
|
|
4
|
+
> tsdown
|
|
5
|
+
|
|
6
|
+
[34mℹ[39m tsdown [2mv0.16.0[22m powered by rolldown [2mv1.0.0-beta.46[22m
|
|
7
|
+
[34mℹ[39m entry: [34msrc/index.ts[39m
|
|
8
|
+
[34mℹ[39m tsconfig: [34mtsconfig.json[39m
|
|
9
|
+
[34mℹ[39m Build start
|
|
10
|
+
[34mℹ[39m Cleaning 4 files
|
|
11
|
+
[34mℹ[39m [2mdist/[22m[1mindex.mjs[22m [2m17.17 kB[22m [2m│ gzip: 3.52 kB[22m
|
|
12
|
+
[34mℹ[39m [2mdist/[22mindex.mjs.map [2m33.87 kB[22m [2m│ gzip: 6.59 kB[22m
|
|
13
|
+
[34mℹ[39m [2mdist/[22mindex.d.mts.map [2m 0.88 kB[22m [2m│ gzip: 0.46 kB[22m
|
|
14
|
+
[34mℹ[39m [2mdist/[22m[32m[1mindex.d.mts[22m[39m [2m 3.37 kB[22m [2m│ gzip: 1.04 kB[22m
|
|
15
|
+
[34mℹ[39m 4 files, total: 55.28 kB
|
|
16
|
+
[32m✔[39m Build complete in [32m10244ms[39m
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 uploadista
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# @uploadista/flow-videos-av-node
|
|
2
|
+
|
|
3
|
+
Modern FFmpeg-based video processing plugin for Uploadista Flow using node-av. Provides video transcoding, resizing, trimming, thumbnail generation, and metadata extraction with native FFmpeg bindings.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **No System Dependencies**: node-av includes prebuilt FFmpeg binaries - no system installation required
|
|
8
|
+
- **TypeScript Native**: Full type safety with modern TypeScript support
|
|
9
|
+
- **Modern API**: Uses native async/await and AsyncIterators
|
|
10
|
+
- **Memory Efficient**: Automatic resource management with `using` declarations
|
|
11
|
+
- **Cross-Platform**: Works on Windows, macOS, and Linux out of the box
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install @uploadista/flow-videos-av-node
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
No additional dependencies or system packages required - FFmpeg binaries are included with node-av.
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
### Provide the Plugin Layer
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
import { AVNodeVideoPluginLive } from "@uploadista/flow-videos-av-node";
|
|
27
|
+
import { Effect } from "effect";
|
|
28
|
+
|
|
29
|
+
// Provide the node-av plugin to your flow execution
|
|
30
|
+
const result = await Effect.runPromise(
|
|
31
|
+
flowProgram.pipe(Effect.provide(AVNodeVideoPluginLive))
|
|
32
|
+
);
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### With Availability Check
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
import { AVNodeVideoPluginWithCheck } from "@uploadista/flow-videos-av-node";
|
|
39
|
+
|
|
40
|
+
// Checks node-av availability on initialization
|
|
41
|
+
const result = await Effect.runPromise(
|
|
42
|
+
flowProgram.pipe(Effect.provide(AVNodeVideoPluginWithCheck))
|
|
43
|
+
);
|
|
44
|
+
// Logs: "✓ node-av 3.x detected" or warning if not found
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Supported Formats
|
|
48
|
+
|
|
49
|
+
### Input Formats
|
|
50
|
+
|
|
51
|
+
- MP4 (MPEG-4)
|
|
52
|
+
- WebM (VP8/VP9)
|
|
53
|
+
- MOV (QuickTime)
|
|
54
|
+
- AVI (Audio Video Interleave)
|
|
55
|
+
- MKV (Matroska)
|
|
56
|
+
- FLV (Flash Video)
|
|
57
|
+
|
|
58
|
+
### Output Formats
|
|
59
|
+
|
|
60
|
+
- MP4 (H.264/AAC) - Most compatible
|
|
61
|
+
- WebM (VP9/Opus) - Modern web standard
|
|
62
|
+
- MOV (H.264/AAC) - Apple ecosystem
|
|
63
|
+
- AVI (various codecs)
|
|
64
|
+
|
|
65
|
+
### Video Codecs
|
|
66
|
+
|
|
67
|
+
- **H.264** (`h264`) - Universal compatibility
|
|
68
|
+
- **H.265/HEVC** (`hevc`) - Better compression
|
|
69
|
+
- **VP9** (`vp9`) - Open-source, good for web
|
|
70
|
+
- **AV1** (`av1`) - Next-gen, best compression
|
|
71
|
+
|
|
72
|
+
### Audio Codecs
|
|
73
|
+
|
|
74
|
+
- **AAC** - Standard for MP4
|
|
75
|
+
- **Opus** - Modern, efficient
|
|
76
|
+
- **MP3** - Legacy compatibility
|
|
77
|
+
- **Vorbis** - WebM standard
|
|
78
|
+
|
|
79
|
+
## Error Handling
|
|
80
|
+
|
|
81
|
+
The plugin uses typed UploadistaError codes:
|
|
82
|
+
|
|
83
|
+
- `VIDEO_PROCESSING_FAILED` - Generic processing error
|
|
84
|
+
- `INVALID_VIDEO_FORMAT` - Unsupported format
|
|
85
|
+
- `CODEC_NOT_SUPPORTED` - Codec unavailable
|
|
86
|
+
- `VIDEO_METADATA_EXTRACTION_FAILED` - Cannot read metadata
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
import { Effect } from "effect";
|
|
90
|
+
import { UploadistaError } from "@uploadista/core/errors";
|
|
91
|
+
|
|
92
|
+
const program = Effect.gen(function* () {
|
|
93
|
+
const videoPlugin = yield* VideoPlugin;
|
|
94
|
+
const result = yield* videoPlugin.transcode(videoBytes, {
|
|
95
|
+
format: "webm",
|
|
96
|
+
codec: "vp9",
|
|
97
|
+
});
|
|
98
|
+
return result;
|
|
99
|
+
}).pipe(
|
|
100
|
+
Effect.catchTag("UploadistaError", (error) => {
|
|
101
|
+
if (error.code === "VIDEO_PROCESSING_FAILED") {
|
|
102
|
+
console.error("Video processing failed:", error.message);
|
|
103
|
+
}
|
|
104
|
+
return Effect.fail(error);
|
|
105
|
+
})
|
|
106
|
+
);
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Performance Considerations
|
|
110
|
+
|
|
111
|
+
Video processing is computationally intensive. Approximate processing times (on modern CPU):
|
|
112
|
+
|
|
113
|
+
| Operation | 1 min video | 5 min video |
|
|
114
|
+
| ------------------------ | ----------- | ----------- |
|
|
115
|
+
| Transcode H.264 → WebM | ~30s | ~2.5m |
|
|
116
|
+
| Resize 1080p → 720p | ~15s | ~1.5m |
|
|
117
|
+
| Thumbnail extraction | ~2s | ~2s |
|
|
118
|
+
| Metadata extraction | <1s | <1s |
|
|
119
|
+
| Trim (with re-encode) | ~10s | ~50s |
|
|
120
|
+
|
|
121
|
+
Times vary based on video complexity, codec settings, and hardware.
|
|
122
|
+
|
|
123
|
+
## Advantages over fluent-ffmpeg
|
|
124
|
+
|
|
125
|
+
- **Modern**: node-av is actively maintained with TypeScript support
|
|
126
|
+
- **No System Dependencies**: Includes prebuilt FFmpeg binaries
|
|
127
|
+
- **Type Safe**: Full TypeScript definitions and modern API
|
|
128
|
+
- **Memory Efficient**: Better resource management with automatic cleanup
|
|
129
|
+
- **Performance**: Direct FFmpeg bindings without wrapper overhead
|
|
130
|
+
|
|
131
|
+
## Current Limitations
|
|
132
|
+
|
|
133
|
+
This is an initial implementation focusing on core functionality:
|
|
134
|
+
|
|
135
|
+
- **Resize Quality**: Currently uses encoder-based resizing. For production use, consider adding FilterAPI support for better quality scaling
|
|
136
|
+
- **Frame Extraction**: Extracts frames as MJPEG or PNG. Additional format support can be added
|
|
137
|
+
- **Hardware Acceleration**: Not yet implemented, but node-av supports it via HardwareContext
|
|
138
|
+
|
|
139
|
+
## Roadmap
|
|
140
|
+
|
|
141
|
+
Future improvements planned:
|
|
142
|
+
|
|
143
|
+
1. **FilterAPI Integration**: Add support for high-quality video filters (scale, crop, overlay, etc.)
|
|
144
|
+
2. **Hardware Acceleration**: GPU-accelerated encoding/decoding support
|
|
145
|
+
3. **Additional Formats**: Support for more image formats in frame extraction
|
|
146
|
+
4. **Stream Processing**: Direct stream input/output without temporary files
|
|
147
|
+
5. **Progress Callbacks**: Real-time progress reporting for long operations
|
|
148
|
+
|
|
149
|
+
## Troubleshooting
|
|
150
|
+
|
|
151
|
+
### Import Error
|
|
152
|
+
|
|
153
|
+
**Error**: Cannot find module 'node-av'
|
|
154
|
+
|
|
155
|
+
**Solution**: Ensure node-av is installed:
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
npm install node-av
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### TypeScript Errors
|
|
162
|
+
|
|
163
|
+
**Error**: TypeScript compilation errors
|
|
164
|
+
|
|
165
|
+
**Solution**: node-av requires modern TypeScript features. Ensure you're using TypeScript 5.2+:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
npm install -D typescript@latest
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Comparison with @uploadista/flow-videos-ffmpeg
|
|
172
|
+
|
|
173
|
+
| Feature | av-node (this package) | ffmpeg (fluent-ffmpeg) |
|
|
174
|
+
|---------|----------------------|------------------------|
|
|
175
|
+
| System Dependencies | ❌ None (bundled) | ✅ Requires FFmpeg install |
|
|
176
|
+
| Maintenance | ✅ Active | ⚠️ Deprecated |
|
|
177
|
+
| TypeScript Support | ✅ Native | ⚠️ Via @types |
|
|
178
|
+
| API Style | ✅ Modern async/await | ⚠️ Callback-based |
|
|
179
|
+
| Memory Management | ✅ Automatic | ⚠️ Manual |
|
|
180
|
+
| Performance | ✅ Direct bindings | ⚠️ CLI wrapper |
|
|
181
|
+
|
|
182
|
+
**Recommendation**: Use this package (@uploadista/flow-videos-av-node) for new projects. The fluent-ffmpeg package is deprecated and unmaintained.
|
|
183
|
+
|
|
184
|
+
## License
|
|
185
|
+
|
|
186
|
+
MIT
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { FFEncoderCodec } from "node-av/constants";
|
|
2
|
+
import { Layer } from "effect";
|
|
3
|
+
import { TranscodeParams, VideoPlugin, VideoPluginShape } from "@uploadista/core/flow";
|
|
4
|
+
|
|
5
|
+
//#region src/utils/av-check.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* Result of node-av availability check
|
|
8
|
+
*/
|
|
9
|
+
type AVCheckResult = {
|
|
10
|
+
available: boolean;
|
|
11
|
+
version?: string;
|
|
12
|
+
error?: string;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Checks if node-av is available and can access FFmpeg binaries
|
|
16
|
+
* @returns Promise with availability status and version info
|
|
17
|
+
*/
|
|
18
|
+
declare function checkAVAvailable(): Promise<AVCheckResult>;
|
|
19
|
+
//#endregion
|
|
20
|
+
//#region src/utils/format-mappings.d.ts
|
|
21
|
+
/**
|
|
22
|
+
* Maps video format to MIME type
|
|
23
|
+
*/
|
|
24
|
+
declare const formatToMimeType: Record<TranscodeParams["format"], string>;
|
|
25
|
+
/**
|
|
26
|
+
* Maps video format to file extension
|
|
27
|
+
*/
|
|
28
|
+
declare const formatToExtension: Record<TranscodeParams["format"], string>;
|
|
29
|
+
/**
|
|
30
|
+
* Maps codec parameter to node-av codec constant
|
|
31
|
+
*/
|
|
32
|
+
declare const codecToAVName: Record<NonNullable<TranscodeParams["codec"]>, FFEncoderCodec>;
|
|
33
|
+
/**
|
|
34
|
+
* Maps audio codec parameter to node-av audio codec constant
|
|
35
|
+
*/
|
|
36
|
+
declare const audioCodecToAVName: Record<NonNullable<TranscodeParams["audioCodec"]>, FFEncoderCodec>;
|
|
37
|
+
/**
|
|
38
|
+
* Maps image format to encoder constant
|
|
39
|
+
*/
|
|
40
|
+
declare const imageFormatToEncoder: Record<string, FFEncoderCodec>;
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region src/video-plugin.d.ts
|
|
43
|
+
/**
|
|
44
|
+
* Creates a node-av based video processing plugin
|
|
45
|
+
*/
|
|
46
|
+
declare function createAVNodeVideoPlugin(): VideoPluginShape;
|
|
47
|
+
//#endregion
|
|
48
|
+
//#region src/video-plugin-layer.d.ts
|
|
49
|
+
/**
|
|
50
|
+
* Effect Layer for the node-av video plugin
|
|
51
|
+
*
|
|
52
|
+
* This layer provides video processing capabilities using node-av (FFmpeg bindings).
|
|
53
|
+
* Note: node-av includes prebuilt FFmpeg binaries, so no system installation is required.
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```typescript
|
|
57
|
+
* import { AVNodeVideoPlugin } from "@uploadista/flow-videos-av-node";
|
|
58
|
+
* import { Effect } from "effect";
|
|
59
|
+
*
|
|
60
|
+
* const program = Effect.gen(function* () {
|
|
61
|
+
* const videoPlugin = yield* VideoPlugin;
|
|
62
|
+
* const metadata = yield* videoPlugin.describe(videoBytes);
|
|
63
|
+
* return metadata;
|
|
64
|
+
* });
|
|
65
|
+
*
|
|
66
|
+
* // Run with node-av plugin layer
|
|
67
|
+
* const result = await Effect.runPromise(
|
|
68
|
+
* program.pipe(Effect.provide(AVNodeVideoPluginLive))
|
|
69
|
+
* );
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
declare const AVNodeVideoPlugin: Layer.Layer<VideoPlugin, never, never>;
|
|
73
|
+
/**
|
|
74
|
+
* Effect Layer for the node-av video plugin with availability check
|
|
75
|
+
*
|
|
76
|
+
* This layer checks if node-av is properly installed and logs status information.
|
|
77
|
+
* The plugin will still be created, but operations will fail if node-av is not available.
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```typescript
|
|
81
|
+
* import { AVNodeVideoPluginWithCheck } from "@uploadista/flow-videos-av-node";
|
|
82
|
+
* import { Effect } from "effect";
|
|
83
|
+
*
|
|
84
|
+
* const program = Effect.gen(function* () {
|
|
85
|
+
* const videoPlugin = yield* VideoPlugin;
|
|
86
|
+
* const metadata = yield* videoPlugin.describe(videoBytes);
|
|
87
|
+
* return metadata;
|
|
88
|
+
* });
|
|
89
|
+
*
|
|
90
|
+
* // Run with node-av plugin layer (with check)
|
|
91
|
+
* const result = await Effect.runPromise(
|
|
92
|
+
* program.pipe(Effect.provide(AVNodeVideoPluginWithCheck))
|
|
93
|
+
* );
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
declare const AVNodeVideoPluginWithCheck: Layer.Layer<VideoPlugin, never, never>;
|
|
97
|
+
//#endregion
|
|
98
|
+
export { AVCheckResult, AVNodeVideoPlugin, AVNodeVideoPluginWithCheck, audioCodecToAVName, checkAVAvailable, codecToAVName, createAVNodeVideoPlugin, formatToExtension, formatToMimeType, imageFormatToEncoder };
|
|
99
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/utils/av-check.ts","../src/utils/format-mappings.ts","../src/video-plugin.ts","../src/video-plugin-layer.ts"],"sourcesContent":[],"mappings":";;;;;;;;KAGY,aAAA;;EAAA,OAAA,CAAA,EAAA,MAAa;EAUH,KAAA,CAAA,EAAA,MAAA;;;;ACKtB;AAUA;AAUa,iBDzBS,gBAAA,CAAA,CCiCrB,EDjCyC,OCiCzC,CDjCiD,aCiCjD,CAAA;;;;;;AD3CW,cCeC,gBDfY,ECeM,MDfN,CCea,eDfb,CAAA,QAAA,CAAA,EAAA,MAAA,CAAA;AAUzB;;;cCea,mBAAmB,OAAO;AAVvC;AAUA;AAUA;AACc,cADD,aACC,EADc,MACd,CAAZ,WAAY,CAAA,eAAA,CAAA,OAAA,CAAA,CAAA,EACZ,cADY,CAAA;;;;AADoB,cAarB,kBAbqB,EAaD,MAbC,CAchC,WAdgC,CAcpB,eAdoB,CAAA,YAAA,CAAA,CAAA,EAehC,cAfgC,CAAA;AAalC;;;AAEE,cAWW,oBAXX,EAWiC,MAXjC,CAAA,MAAA,EAWgD,cAXhD,CAAA;;;;;;iBC9Bc,uBAAA,CAAA,GAA2B;;;;;;AFpB3C;AAUA;;;;ACKA;AAUA;AAUA;;;;;;AAaA;;;;;;AAaA;cEpCa,mBAAiB,KAAA,CAAA,MAAA;;;ADL9B;;;;ACKA;AA4BA;;;;;;;;;;;;;;;;cAAa,4BAA0B,KAAA,CAAA,MAAA"}
|