n8n-nodes-sb-render 1.0.0

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.
Files changed (37) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +442 -0
  3. package/dist/nodes/SbRender/SbRender.node.d.ts +10 -0
  4. package/dist/nodes/SbRender/SbRender.node.d.ts.map +1 -0
  5. package/dist/nodes/SbRender/SbRender.node.js +768 -0
  6. package/dist/nodes/SbRender/SbRender.node.js.map +1 -0
  7. package/dist/nodes/SbRender/interfaces/index.d.ts +155 -0
  8. package/dist/nodes/SbRender/interfaces/index.d.ts.map +1 -0
  9. package/dist/nodes/SbRender/interfaces/index.js +41 -0
  10. package/dist/nodes/SbRender/interfaces/index.js.map +1 -0
  11. package/dist/nodes/SbRender/sbrender.svg +7 -0
  12. package/dist/nodes/SbRender/services/AudioMixer.d.ts +26 -0
  13. package/dist/nodes/SbRender/services/AudioMixer.d.ts.map +1 -0
  14. package/dist/nodes/SbRender/services/AudioMixer.js +120 -0
  15. package/dist/nodes/SbRender/services/AudioMixer.js.map +1 -0
  16. package/dist/nodes/SbRender/services/FileManager.d.ts +37 -0
  17. package/dist/nodes/SbRender/services/FileManager.d.ts.map +1 -0
  18. package/dist/nodes/SbRender/services/FileManager.js +157 -0
  19. package/dist/nodes/SbRender/services/FileManager.js.map +1 -0
  20. package/dist/nodes/SbRender/services/SubtitleEngine.d.ts +64 -0
  21. package/dist/nodes/SbRender/services/SubtitleEngine.d.ts.map +1 -0
  22. package/dist/nodes/SbRender/services/SubtitleEngine.js +213 -0
  23. package/dist/nodes/SbRender/services/SubtitleEngine.js.map +1 -0
  24. package/dist/nodes/SbRender/services/VideoComposer.d.ts +28 -0
  25. package/dist/nodes/SbRender/services/VideoComposer.d.ts.map +1 -0
  26. package/dist/nodes/SbRender/services/VideoComposer.js +228 -0
  27. package/dist/nodes/SbRender/services/VideoComposer.js.map +1 -0
  28. package/dist/nodes/SbRender/utils/ffmpeg.d.ts +32 -0
  29. package/dist/nodes/SbRender/utils/ffmpeg.d.ts.map +1 -0
  30. package/dist/nodes/SbRender/utils/ffmpeg.js +107 -0
  31. package/dist/nodes/SbRender/utils/ffmpeg.js.map +1 -0
  32. package/dist/nodes/SbRender/utils/validation.d.ts +32 -0
  33. package/dist/nodes/SbRender/utils/validation.d.ts.map +1 -0
  34. package/dist/nodes/SbRender/utils/validation.js +210 -0
  35. package/dist/nodes/SbRender/utils/validation.js.map +1 -0
  36. package/index.js +3 -0
  37. package/package.json +69 -0
@@ -0,0 +1,64 @@
1
+ import type { ISubtitleEngine, ISubtitleConfig } from '../interfaces';
2
+ /**
3
+ * SubtitleEngine Service
4
+ * Generates SRT and ASS subtitle files with customizable styling
5
+ */
6
+ export declare class SubtitleEngine implements ISubtitleEngine {
7
+ /**
8
+ * Generate SRT subtitle file (simple format, limited styling)
9
+ */
10
+ generateSRT(subtitles: ISubtitleConfig[]): string;
11
+ /**
12
+ * Generate ASS subtitle file with full styling support
13
+ */
14
+ generateASS(subtitles: ISubtitleConfig[], videoWidth: number, videoHeight: number): string;
15
+ /**
16
+ * Write subtitle file to disk
17
+ */
18
+ writeSubtitleFile(content: string, format: 'srt' | 'ass'): Promise<string>;
19
+ /**
20
+ * Format time in SRT format (HH:MM:SS,mmm)
21
+ */
22
+ private formatSRTTime;
23
+ /**
24
+ * Format time in ASS format (H:MM:SS.cc)
25
+ */
26
+ private formatASSTime;
27
+ /**
28
+ * Generate ASS file header
29
+ */
30
+ private generateASSHeader;
31
+ /**
32
+ * Generate ASS styles section
33
+ */
34
+ private generateASSStyles;
35
+ /**
36
+ * Generate ASS events section
37
+ */
38
+ private generateASSEvents;
39
+ /**
40
+ * Convert hex color to ASS color format (&HAABBGGRR)
41
+ */
42
+ private hexToASSColor;
43
+ /**
44
+ * Get ASS alignment number based on position and alignment
45
+ */
46
+ private getASSAlignment;
47
+ /**
48
+ * Calculate vertical margin based on position
49
+ */
50
+ private getMarginV;
51
+ /**
52
+ * Convert number to 2-digit hex
53
+ */
54
+ private toHex;
55
+ /**
56
+ * Pad number with zeros
57
+ */
58
+ private pad;
59
+ /**
60
+ * Validate subtitle configuration
61
+ */
62
+ validateSubtitles(subtitles: ISubtitleConfig[]): void;
63
+ }
64
+ //# sourceMappingURL=SubtitleEngine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SubtitleEngine.d.ts","sourceRoot":"","sources":["../../../../nodes/SbRender/services/SubtitleEngine.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEtE;;;GAGG;AACH,qBAAa,cAAe,YAAW,eAAe;IACpD;;OAEG;IACH,WAAW,CAAC,SAAS,EAAE,eAAe,EAAE,GAAG,MAAM;IAejD;;OAEG;IACH,WAAW,CAAC,SAAS,EAAE,eAAe,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM;IAQ1F;;OAEG;IACG,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,GAAG,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC;IAWhF;;OAEG;IACH,OAAO,CAAC,aAAa;IASrB;;OAEG;IACH,OAAO,CAAC,aAAa;IASrB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAUzB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAwBzB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAgCzB;;OAEG;IACH,OAAO,CAAC,aAAa;IAgBrB;;OAEG;IACH,OAAO,CAAC,eAAe;IAkBvB;;OAEG;IACH,OAAO,CAAC,UAAU;IAUlB;;OAEG;IACH,OAAO,CAAC,KAAK;IAIb;;OAEG;IACH,OAAO,CAAC,GAAG;IAIX;;OAEG;IACH,iBAAiB,CAAC,SAAS,EAAE,eAAe,EAAE,GAAG,IAAI;CAyBtD"}
@@ -0,0 +1,213 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SubtitleEngine = void 0;
4
+ const fs_1 = require("fs");
5
+ // import * as path from 'path'; // Unused
6
+ const tmp_promise_1 = require("tmp-promise");
7
+ /**
8
+ * SubtitleEngine Service
9
+ * Generates SRT and ASS subtitle files with customizable styling
10
+ */
11
+ class SubtitleEngine {
12
+ /**
13
+ * Generate SRT subtitle file (simple format, limited styling)
14
+ */
15
+ generateSRT(subtitles) {
16
+ const srtBlocks = [];
17
+ subtitles.forEach((subtitle, index) => {
18
+ const startTime = this.formatSRTTime(subtitle.startTime);
19
+ const endTime = this.formatSRTTime(subtitle.endTime);
20
+ srtBlocks.push(`${index + 1}\n${startTime} --> ${endTime}\n${subtitle.text}\n`);
21
+ });
22
+ return srtBlocks.join('\n');
23
+ }
24
+ /**
25
+ * Generate ASS subtitle file with full styling support
26
+ */
27
+ generateASS(subtitles, videoWidth, videoHeight) {
28
+ const header = this.generateASSHeader(videoWidth, videoHeight);
29
+ const styles = this.generateASSStyles(subtitles);
30
+ const events = this.generateASSEvents(subtitles, videoWidth, videoHeight);
31
+ return `${header}\n\n${styles}\n\n${events}`;
32
+ }
33
+ /**
34
+ * Write subtitle file to disk
35
+ */
36
+ async writeSubtitleFile(content, format) {
37
+ const { path: tempPath } = await (0, tmp_promise_1.file)({
38
+ prefix: 'sb-render-subtitle-',
39
+ postfix: `.${format}`,
40
+ keep: true,
41
+ });
42
+ await fs_1.promises.writeFile(tempPath, content, 'utf8');
43
+ return tempPath;
44
+ }
45
+ /**
46
+ * Format time in SRT format (HH:MM:SS,mmm)
47
+ */
48
+ formatSRTTime(seconds) {
49
+ const hours = Math.floor(seconds / 3600);
50
+ const minutes = Math.floor((seconds % 3600) / 60);
51
+ const secs = Math.floor(seconds % 60);
52
+ const millis = Math.floor((seconds % 1) * 1000);
53
+ return `${this.pad(hours, 2)}:${this.pad(minutes, 2)}:${this.pad(secs, 2)},${this.pad(millis, 3)}`;
54
+ }
55
+ /**
56
+ * Format time in ASS format (H:MM:SS.cc)
57
+ */
58
+ formatASSTime(seconds) {
59
+ const hours = Math.floor(seconds / 3600);
60
+ const minutes = Math.floor((seconds % 3600) / 60);
61
+ const secs = Math.floor(seconds % 60);
62
+ const centisecs = Math.floor((seconds % 1) * 100);
63
+ return `${hours}:${this.pad(minutes, 2)}:${this.pad(secs, 2)}.${this.pad(centisecs, 2)}`;
64
+ }
65
+ /**
66
+ * Generate ASS file header
67
+ */
68
+ generateASSHeader(videoWidth, videoHeight) {
69
+ return `[Script Info]
70
+ Title: sb-render subtitles
71
+ ScriptType: v4.00+
72
+ WrapStyle: 0
73
+ PlayResX: ${videoWidth}
74
+ PlayResY: ${videoHeight}
75
+ ScaledBorderAndShadow: yes`;
76
+ }
77
+ /**
78
+ * Generate ASS styles section
79
+ */
80
+ generateASSStyles(subtitles) {
81
+ const stylesHeader = `[V4+ Styles]
82
+ Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding`;
83
+ const uniqueStyles = new Map();
84
+ subtitles.forEach((subtitle, index) => {
85
+ const styleName = `Style${index}`;
86
+ const primaryColor = this.hexToASSColor(subtitle.fontColor);
87
+ const outlineColor = this.hexToASSColor(subtitle.borderColor || '#000000');
88
+ const backColor = this.hexToASSColor(subtitle.backgroundColor || '#000000', subtitle.backgroundOpacity);
89
+ const alignment = this.getASSAlignment(subtitle.alignment, subtitle.position);
90
+ const outline = subtitle.borderWidth || 2;
91
+ const styleDefinition = `Style: ${styleName},${subtitle.fontFamily},${subtitle.fontSize},${primaryColor},${primaryColor},${outlineColor},${backColor},0,0,0,0,100,100,0,0,1,${outline},2,${alignment},10,10,10,1`;
92
+ uniqueStyles.set(styleName, styleDefinition);
93
+ });
94
+ const styleLines = Array.from(uniqueStyles.values()).join('\n');
95
+ return `${stylesHeader}\n${styleLines}`;
96
+ }
97
+ /**
98
+ * Generate ASS events section
99
+ */
100
+ generateASSEvents(subtitles, _videoWidth, videoHeight) {
101
+ const eventsHeader = `[Events]
102
+ Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text`;
103
+ const eventLines = [];
104
+ subtitles.forEach((subtitle, index) => {
105
+ const startTime = this.formatASSTime(subtitle.startTime);
106
+ const endTime = this.formatASSTime(subtitle.endTime);
107
+ const styleName = `Style${index}`;
108
+ // Calculate position override if custom position
109
+ let positionTag = '';
110
+ if (subtitle.position === 'custom' && subtitle.customX !== undefined && subtitle.customY !== undefined) {
111
+ positionTag = `{\\pos(${subtitle.customX},${subtitle.customY})}`;
112
+ }
113
+ else {
114
+ // Use margin-based positioning
115
+ const marginV = this.getMarginV(subtitle.position, subtitle.customY, videoHeight);
116
+ eventLines.push(`Dialogue: 0,${startTime},${endTime},${styleName},,0,0,${marginV},,${positionTag}${subtitle.text}`);
117
+ return;
118
+ }
119
+ eventLines.push(`Dialogue: 0,${startTime},${endTime},${styleName},,0,0,0,,${positionTag}${subtitle.text}`);
120
+ });
121
+ return `${eventsHeader}\n${eventLines.join('\n')}`;
122
+ }
123
+ /**
124
+ * Convert hex color to ASS color format (&HAABBGGRR)
125
+ */
126
+ hexToASSColor(hex, opacity = 100) {
127
+ // Remove # if present
128
+ hex = hex.replace('#', '');
129
+ // Parse RGB
130
+ const r = parseInt(hex.substring(0, 2), 16);
131
+ const g = parseInt(hex.substring(2, 4), 16);
132
+ const b = parseInt(hex.substring(4, 6), 16);
133
+ // Convert opacity percentage to alpha (0-255, inverted for ASS)
134
+ const alpha = Math.round((100 - opacity) * 2.55);
135
+ // Format as &HAABBGGRR
136
+ return `&H${this.toHex(alpha)}${this.toHex(b)}${this.toHex(g)}${this.toHex(r)}`;
137
+ }
138
+ /**
139
+ * Get ASS alignment number based on position and alignment
140
+ */
141
+ getASSAlignment(alignment, position) {
142
+ // ASS alignment: 1-3 bottom, 4-6 middle, 7-9 top
143
+ // Within each row: 1/4/7 left, 2/5/8 center, 3/6/9 right
144
+ let baseAlignment = 0;
145
+ if (position === 'bottom')
146
+ baseAlignment = 1;
147
+ else if (position === 'middle')
148
+ baseAlignment = 4;
149
+ else if (position === 'top')
150
+ baseAlignment = 7;
151
+ else
152
+ baseAlignment = 5; // default to center-middle
153
+ if (alignment === 'left')
154
+ return baseAlignment;
155
+ if (alignment === 'center')
156
+ return baseAlignment + 1;
157
+ if (alignment === 'right')
158
+ return baseAlignment + 2;
159
+ return baseAlignment + 1; // default center
160
+ }
161
+ /**
162
+ * Calculate vertical margin based on position
163
+ */
164
+ getMarginV(position, customY, videoHeight) {
165
+ if (customY !== undefined)
166
+ return customY;
167
+ if (position === 'top')
168
+ return 50;
169
+ if (position === 'middle')
170
+ return Math.round(videoHeight / 2);
171
+ if (position === 'bottom')
172
+ return 100;
173
+ return 100; // default bottom
174
+ }
175
+ /**
176
+ * Convert number to 2-digit hex
177
+ */
178
+ toHex(num) {
179
+ return num.toString(16).padStart(2, '0').toUpperCase();
180
+ }
181
+ /**
182
+ * Pad number with zeros
183
+ */
184
+ pad(num, length) {
185
+ return num.toString().padStart(length, '0');
186
+ }
187
+ /**
188
+ * Validate subtitle configuration
189
+ */
190
+ validateSubtitles(subtitles) {
191
+ subtitles.forEach((subtitle, index) => {
192
+ if (!subtitle.text || subtitle.text.trim() === '') {
193
+ throw new Error(`Subtitle ${index + 1}: Text cannot be empty`);
194
+ }
195
+ if (subtitle.startTime < 0) {
196
+ throw new Error(`Subtitle ${index + 1}: Start time cannot be negative`);
197
+ }
198
+ if (subtitle.endTime <= subtitle.startTime) {
199
+ throw new Error(`Subtitle ${index + 1}: End time must be greater than start time`);
200
+ }
201
+ if (subtitle.fontSize <= 0) {
202
+ throw new Error(`Subtitle ${index + 1}: Font size must be positive`);
203
+ }
204
+ if (subtitle.position === 'custom') {
205
+ if (subtitle.customX === undefined || subtitle.customY === undefined) {
206
+ throw new Error(`Subtitle ${index + 1}: Custom position requires customX and customY`);
207
+ }
208
+ }
209
+ });
210
+ }
211
+ }
212
+ exports.SubtitleEngine = SubtitleEngine;
213
+ //# sourceMappingURL=SubtitleEngine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SubtitleEngine.js","sourceRoot":"","sources":["../../../../nodes/SbRender/services/SubtitleEngine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import type { IVideoComposer, IVideoMetadata, ISbRenderNodeParams } from '../interfaces';
2
+ /**
3
+ * VideoComposer Service
4
+ * Handles final video composition with audio and subtitles
5
+ */
6
+ export declare class VideoComposer implements IVideoComposer {
7
+ /**
8
+ * Compose final video with audio and subtitles
9
+ */
10
+ compose(videoPath: string, audioPath: string | null, subtitlePath: string | null, outputPath: string, config: ISbRenderNodeParams): Promise<Buffer>;
11
+ /**
12
+ * Compose with complex audio mixing
13
+ */
14
+ composeWithAudioMix(videoPath: string, bgmPath: string | null, narrationPath: string | null, subtitlePath: string | null, audioFilterChain: string, outputPath: string, config: ISbRenderNodeParams): Promise<Buffer>;
15
+ /**
16
+ * Get video metadata (duration, resolution, codec)
17
+ */
18
+ getVideoMetadata(videoPath: string): Promise<IVideoMetadata>;
19
+ /**
20
+ * Get CRF value based on quality setting
21
+ */
22
+ private getCRF;
23
+ /**
24
+ * Validate output configuration
25
+ */
26
+ validateConfig(config: ISbRenderNodeParams): void;
27
+ }
28
+ //# sourceMappingURL=VideoComposer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VideoComposer.d.ts","sourceRoot":"","sources":["../../../../nodes/SbRender/services/VideoComposer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAKzF;;;GAGG;AACH,qBAAa,aAAc,YAAW,cAAc;IAClD;;OAEG;IACG,OAAO,CACX,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,YAAY,EAAE,MAAM,GAAG,IAAI,EAC3B,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAAC,MAAM,CAAC;IAoFlB;;OAEG;IACG,mBAAmB,CACvB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GAAG,IAAI,EACtB,aAAa,EAAE,MAAM,GAAG,IAAI,EAC5B,YAAY,EAAE,MAAM,GAAG,IAAI,EAC3B,gBAAgB,EAAE,MAAM,EACxB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAAC,MAAM,CAAC;IAqFlB;;OAEG;IACG,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IA4BlE;;OAEG;IACH,OAAO,CAAC,MAAM;IAcd;;OAEG;IACH,cAAc,CAAC,MAAM,EAAE,mBAAmB,GAAG,IAAI;CAiBlD"}
@@ -0,0 +1,228 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.VideoComposer = void 0;
7
+ const fs_1 = require("fs");
8
+ const fluent_ffmpeg_1 = __importDefault(require("fluent-ffmpeg"));
9
+ const ffmpeg_1 = __importDefault(require("@ffmpeg-installer/ffmpeg"));
10
+ // Set FFmpeg path
11
+ fluent_ffmpeg_1.default.setFfmpegPath(ffmpeg_1.default.path);
12
+ /**
13
+ * VideoComposer Service
14
+ * Handles final video composition with audio and subtitles
15
+ */
16
+ class VideoComposer {
17
+ /**
18
+ * Compose final video with audio and subtitles
19
+ */
20
+ async compose(videoPath, audioPath, subtitlePath, outputPath, config) {
21
+ return new Promise((resolve, reject) => {
22
+ try {
23
+ const command = (0, fluent_ffmpeg_1.default)(videoPath);
24
+ // Add audio inputs if present
25
+ if (audioPath) {
26
+ // Audio is already mixed, we'll map it
27
+ }
28
+ // Video filters
29
+ const videoFilters = [];
30
+ // Add subtitle overlay if present
31
+ if (subtitlePath) {
32
+ // Escape path for FFmpeg filter
33
+ const escapedPath = subtitlePath.replace(/\\/g, '/').replace(/:/g, '\\:');
34
+ videoFilters.push(`ass=${escapedPath}`);
35
+ }
36
+ // Apply video filters if any
37
+ if (videoFilters.length > 0) {
38
+ command.videoFilters(videoFilters);
39
+ }
40
+ // Set output codec and quality
41
+ const crf = this.getCRF(config.quality, config.customCRF);
42
+ command
43
+ .videoCodec(config.videoCodec)
44
+ .outputOptions([
45
+ `-crf ${crf}`,
46
+ '-preset medium',
47
+ '-movflags +faststart', // Enable streaming
48
+ ]);
49
+ // Audio codec
50
+ if (audioPath) {
51
+ command
52
+ .audioCodec('aac')
53
+ .audioBitrate('192k');
54
+ }
55
+ else {
56
+ command.noAudio();
57
+ }
58
+ // Set output format
59
+ command.format(config.outputFormat);
60
+ // Save to output path
61
+ command.output(outputPath);
62
+ // Handle events
63
+ command.on('start', (commandLine) => {
64
+ console.log('FFmpeg command:', commandLine);
65
+ });
66
+ command.on('progress', (progress) => {
67
+ if (progress.percent) {
68
+ console.log(`Processing: ${Math.round(progress.percent)}% done`);
69
+ }
70
+ });
71
+ command.on('end', async () => {
72
+ try {
73
+ // Read the output file
74
+ const buffer = await fs_1.promises.readFile(outputPath);
75
+ resolve(buffer);
76
+ }
77
+ catch (error) {
78
+ reject(new Error(`Failed to read output file: ${error}`));
79
+ }
80
+ });
81
+ command.on('error', (error) => {
82
+ reject(new Error(`FFmpeg error: ${error.message}`));
83
+ });
84
+ // Run the command
85
+ command.run();
86
+ }
87
+ catch (error) {
88
+ reject(new Error(`Video composition failed: ${error}`));
89
+ }
90
+ });
91
+ }
92
+ /**
93
+ * Compose with complex audio mixing
94
+ */
95
+ async composeWithAudioMix(videoPath, bgmPath, narrationPath, subtitlePath, audioFilterChain, outputPath, config) {
96
+ return new Promise((resolve, reject) => {
97
+ try {
98
+ const command = (0, fluent_ffmpeg_1.default)(videoPath);
99
+ // Add BGM input
100
+ if (bgmPath) {
101
+ command.input(bgmPath);
102
+ }
103
+ // Add narration input
104
+ if (narrationPath) {
105
+ command.input(narrationPath);
106
+ }
107
+ // Apply complex audio filter
108
+ if (audioFilterChain) {
109
+ command.complexFilter(audioFilterChain);
110
+ }
111
+ // Video filters
112
+ const videoFilters = [];
113
+ // Add subtitle overlay if present
114
+ if (subtitlePath) {
115
+ const escapedPath = subtitlePath.replace(/\\/g, '/').replace(/:/g, '\\:');
116
+ videoFilters.push(`ass=${escapedPath}`);
117
+ }
118
+ if (videoFilters.length > 0) {
119
+ command.videoFilters(videoFilters);
120
+ }
121
+ // Map video and mixed audio
122
+ command.outputOptions([
123
+ '-map 0:v',
124
+ audioFilterChain ? '-map [mixed]' : '',
125
+ ].filter(Boolean));
126
+ // Set output codec and quality
127
+ const crf = this.getCRF(config.quality, config.customCRF);
128
+ command
129
+ .videoCodec(config.videoCodec)
130
+ .outputOptions([
131
+ `-crf ${crf}`,
132
+ '-preset medium',
133
+ '-movflags +faststart',
134
+ ])
135
+ .audioCodec('aac')
136
+ .audioBitrate('192k')
137
+ .format(config.outputFormat)
138
+ .output(outputPath);
139
+ // Handle events
140
+ command.on('start', (commandLine) => {
141
+ console.log('FFmpeg command:', commandLine);
142
+ });
143
+ command.on('progress', (progress) => {
144
+ if (progress.percent) {
145
+ console.log(`Processing: ${Math.round(progress.percent)}% done`);
146
+ }
147
+ });
148
+ command.on('end', async () => {
149
+ try {
150
+ const buffer = await fs_1.promises.readFile(outputPath);
151
+ resolve(buffer);
152
+ }
153
+ catch (error) {
154
+ reject(new Error(`Failed to read output file: ${error}`));
155
+ }
156
+ });
157
+ command.on('error', (error) => {
158
+ reject(new Error(`FFmpeg error: ${error.message}`));
159
+ });
160
+ command.run();
161
+ }
162
+ catch (error) {
163
+ reject(new Error(`Video composition failed: ${error}`));
164
+ }
165
+ });
166
+ }
167
+ /**
168
+ * Get video metadata (duration, resolution, codec)
169
+ */
170
+ async getVideoMetadata(videoPath) {
171
+ return new Promise((resolve, reject) => {
172
+ fluent_ffmpeg_1.default.ffprobe(videoPath, (error, metadata) => {
173
+ if (error) {
174
+ reject(new Error(`Failed to get video metadata: ${error.message}`));
175
+ return;
176
+ }
177
+ const videoStream = metadata.streams.find((s) => s.codec_type === 'video');
178
+ const audioStream = metadata.streams.find((s) => s.codec_type === 'audio');
179
+ if (!videoStream) {
180
+ reject(new Error('No video stream found in file'));
181
+ return;
182
+ }
183
+ resolve({
184
+ duration: metadata.format.duration || 0,
185
+ width: videoStream.width || 1920,
186
+ height: videoStream.height || 1080,
187
+ hasAudio: !!audioStream,
188
+ videoCodec: videoStream.codec_name || 'unknown',
189
+ audioCodec: audioStream === null || audioStream === void 0 ? void 0 : audioStream.codec_name,
190
+ });
191
+ });
192
+ });
193
+ }
194
+ /**
195
+ * Get CRF value based on quality setting
196
+ */
197
+ getCRF(quality, customCRF) {
198
+ if (quality === 'custom' && customCRF !== undefined) {
199
+ return Math.max(0, Math.min(51, customCRF));
200
+ }
201
+ const crfMap = {
202
+ low: 28,
203
+ medium: 23,
204
+ high: 18,
205
+ };
206
+ return crfMap[quality] || 23;
207
+ }
208
+ /**
209
+ * Validate output configuration
210
+ */
211
+ validateConfig(config) {
212
+ const validFormats = ['mp4', 'mov', 'webm'];
213
+ if (!validFormats.includes(config.outputFormat)) {
214
+ throw new Error(`Invalid output format: ${config.outputFormat}`);
215
+ }
216
+ const validCodecs = ['libx264', 'libx265', 'vp9'];
217
+ if (!validCodecs.includes(config.videoCodec)) {
218
+ throw new Error(`Invalid video codec: ${config.videoCodec}`);
219
+ }
220
+ if (config.quality === 'custom') {
221
+ if (config.customCRF === undefined || config.customCRF < 0 || config.customCRF > 51) {
222
+ throw new Error('Custom CRF must be between 0 and 51');
223
+ }
224
+ }
225
+ }
226
+ }
227
+ exports.VideoComposer = VideoComposer;
228
+ //# sourceMappingURL=VideoComposer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VideoComposer.js","sourceRoot":"","sources":["../../../../nodes/SbRender/services/VideoComposer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * FFmpeg utility functions
3
+ */
4
+ /**
5
+ * Format seconds to HH:MM:SS format
6
+ */
7
+ export declare function formatTime(seconds: number): string;
8
+ /**
9
+ * Pad number with zeros
10
+ */
11
+ export declare function pad(num: number, length: number): string;
12
+ /**
13
+ * Escape special characters for FFmpeg filter syntax
14
+ */
15
+ export declare function escapeFilterString(str: string): string;
16
+ /**
17
+ * Escape file path for FFmpeg
18
+ */
19
+ export declare function escapeFilePath(path: string): string;
20
+ /**
21
+ * Convert percentage to decimal
22
+ */
23
+ export declare function percentageToDecimal(percentage: number): number;
24
+ /**
25
+ * Get file extension from path
26
+ */
27
+ export declare function getFileExtension(path: string): string;
28
+ /**
29
+ * Validate FFmpeg is available
30
+ */
31
+ export declare function validateFFmpegAvailable(): Promise<boolean>;
32
+ //# sourceMappingURL=ffmpeg.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ffmpeg.d.ts","sourceRoot":"","sources":["../../../../nodes/SbRender/utils/ffmpeg.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAMlD;AAED;;GAEG;AACH,wBAAgB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAStD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAInD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGrD;AAED;;GAEG;AACH,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,OAAO,CAAC,CAOhE"}