n8n-nodes-sb-render 1.3.24 → 1.3.26
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/LICENSE +21 -21
- package/README.md +474 -474
- package/dist/nodes/SbRender/SbRender.node.d.ts.map +1 -1
- package/dist/nodes/SbRender/SbRender.node.js +17 -2
- package/dist/nodes/SbRender/SbRender.node.js.map +1 -1
- package/dist/nodes/SbRender/sbrender.svg +7 -7
- package/dist/nodes/SbRender/services/SubtitleEngine.js +8 -8
- package/index.js +3 -3
- package/package.json +75 -75
- package/scripts/fix-ffprobe-permissions.js +209 -209
package/README.md
CHANGED
|
@@ -1,474 +1,474 @@
|
|
|
1
|
-
# n8n-nodes-sb-render
|
|
2
|
-
|
|
3
|
-
[](https://badge.fury.io/js/n8n-nodes-sb-render)
|
|
4
|
-
[](https://opensource.org/licenses/MIT)
|
|
5
|
-
|
|
6
|
-
This is an n8n community node for video rendering with customizable subtitles, background music (BGM), and narration using FFmpeg.
|
|
7
|
-
|
|
8
|
-
**sb-render** allows you to automate video composition workflows in n8n, combining video files with:
|
|
9
|
-
- 🎵 Background music with volume control and fade effects
|
|
10
|
-
- 🎙️ Narration audio with timing control
|
|
11
|
-
- 📝 Customizable subtitles with extensive styling options
|
|
12
|
-
- 🎨 Multiple output formats and quality presets
|
|
13
|
-
|
|
14
|
-
Inspired by [n8n-nodes-mediafx](https://github.com/dandacompany/n8n-nodes-mediafx).
|
|
15
|
-
|
|
16
|
-
## Table of Contents
|
|
17
|
-
|
|
18
|
-
- [Installation](#installation)
|
|
19
|
-
- [Prerequisites](#prerequisites)
|
|
20
|
-
- [Operations](#operations)
|
|
21
|
-
- [Configuration](#configuration)
|
|
22
|
-
- [Examples](#examples)
|
|
23
|
-
- [Development](#development)
|
|
24
|
-
- [Troubleshooting](#troubleshooting)
|
|
25
|
-
- [License](#license)
|
|
26
|
-
|
|
27
|
-
## Installation
|
|
28
|
-
|
|
29
|
-
### Community Nodes (Recommended)
|
|
30
|
-
|
|
31
|
-
1. Go to **Settings > Community Nodes** in n8n
|
|
32
|
-
2. Select **Install**
|
|
33
|
-
3. Enter `n8n-nodes-sb-render`
|
|
34
|
-
4. Agree to the risks and install
|
|
35
|
-
|
|
36
|
-
### Manual Installation
|
|
37
|
-
|
|
38
|
-
```bash
|
|
39
|
-
npm install n8n-nodes-sb-render
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
For n8n self-hosted installations:
|
|
43
|
-
|
|
44
|
-
```bash
|
|
45
|
-
cd ~/.n8n
|
|
46
|
-
npm install n8n-nodes-sb-render
|
|
47
|
-
# Restart n8n
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
## Prerequisites
|
|
51
|
-
|
|
52
|
-
- **n8n version**: 1.0.0 or higher
|
|
53
|
-
- **Node.js**: 16.0.0 or higher
|
|
54
|
-
- **FFmpeg**: Auto-detected from system or installed via npm packages
|
|
55
|
-
|
|
56
|
-
### FFmpeg Installation (Docker/n8n Users)
|
|
57
|
-
|
|
58
|
-
For **Docker or self-hosted n8n**, installing system ffmpeg is recommended:
|
|
59
|
-
|
|
60
|
-
```bash
|
|
61
|
-
# Alpine-based containers (n8n official image)
|
|
62
|
-
docker exec <container-name> apk add --no-cache ffmpeg
|
|
63
|
-
|
|
64
|
-
# Debian/Ubuntu-based containers
|
|
65
|
-
docker exec <container-name> apt-get update && apt-get install -y ffmpeg
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
**docker-compose.yml example:**
|
|
69
|
-
```yaml
|
|
70
|
-
services:
|
|
71
|
-
n8n:
|
|
72
|
-
image: n8nio/n8n
|
|
73
|
-
command: >
|
|
74
|
-
sh -c "
|
|
75
|
-
apk add --no-cache ffmpeg &&
|
|
76
|
-
n8n start
|
|
77
|
-
"
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
The node will automatically:
|
|
81
|
-
1. ✅ Use system ffmpeg/ffprobe if available (most reliable)
|
|
82
|
-
2. ✅ Fall back to npm packages with auto-permission fix
|
|
83
|
-
3. ✅ Gracefully degrade with limited functionality
|
|
84
|
-
|
|
85
|
-
> **Note**: v1.1.20+ automatically handles ffmpeg/ffprobe detection and permission issues!
|
|
86
|
-
|
|
87
|
-
## Operations
|
|
88
|
-
|
|
89
|
-
### Video → Render
|
|
90
|
-
|
|
91
|
-
Compose a video with optional background music, narration, and subtitles.
|
|
92
|
-
|
|
93
|
-
**Features:**
|
|
94
|
-
- ✅ Multiple input sources (URL or binary data)
|
|
95
|
-
- ✅ Audio mixing with independent volume controls
|
|
96
|
-
- ✅ Fade in/out effects for BGM
|
|
97
|
-
- ✅ Customizable subtitle positioning and styling
|
|
98
|
-
- ✅ Multiple output formats (MP4, MOV, WebM)
|
|
99
|
-
- ✅ Quality presets (Low, Medium, High, Custom)
|
|
100
|
-
- ✅ Smart audio merging (handles mixed audio/silent video inputs)
|
|
101
|
-
|
|
102
|
-
## Configuration
|
|
103
|
-
|
|
104
|
-
### Video Input
|
|
105
|
-
|
|
106
|
-
| Parameter | Type | Required | Description |
|
|
107
|
-
|-----------|------|----------|-------------|
|
|
108
|
-
| **Video Source** | Options | Yes | `url` or `binary` |
|
|
109
|
-
| **Video URL** | String | If URL | URL of the video file |
|
|
110
|
-
| **Video Binary Property** | String | If Binary | Name of binary property containing video |
|
|
111
|
-
|
|
112
|
-
### Background Music (BGM)
|
|
113
|
-
|
|
114
|
-
| Parameter | Type | Default | Description |
|
|
115
|
-
|-----------|------|---------|-------------|
|
|
116
|
-
| **Enable BGM** | Boolean | false | Add background music |
|
|
117
|
-
| **BGM Source** | Options | - | `url` or `binary` |
|
|
118
|
-
| **BGM URL** | String | - | URL of BGM file |
|
|
119
|
-
| **BGM Volume** | Number | 30 | Volume 0-100 |
|
|
120
|
-
| **BGM Fade In** | Number | 2 | Fade-in duration (seconds) |
|
|
121
|
-
| **BGM Fade Out** | Number | 2 | Fade-out duration (seconds) |
|
|
122
|
-
|
|
123
|
-
### Narration
|
|
124
|
-
|
|
125
|
-
| Parameter | Type | Default | Description |
|
|
126
|
-
|-----------|------|---------|-------------|
|
|
127
|
-
| **Enable Narration** | Boolean | false | Add narration audio |
|
|
128
|
-
| **Narration Source** | Options | - | `url` or `binary` |
|
|
129
|
-
| **Narration URL** | String | - | URL of narration file |
|
|
130
|
-
| **Narration Volume** | Number | 80 | Volume 0-100 |
|
|
131
|
-
| **Narration Delay** | Number | 0 | Delay before start (seconds) |
|
|
132
|
-
|
|
133
|
-
### Subtitles
|
|
134
|
-
|
|
135
|
-
| Parameter | Type | Default | Description |
|
|
136
|
-
|-----------|------|---------|-------------|
|
|
137
|
-
| **Enable Subtitles** | Boolean | false | Add subtitles |
|
|
138
|
-
| **Text** | String | - | Subtitle text content |
|
|
139
|
-
| **Start Time** | Number | - | Start time in seconds |
|
|
140
|
-
| **End Time** | Number | - | End time in seconds |
|
|
141
|
-
| **Position** | Options | bottom | `top`, `middle`, `bottom`, `custom` |
|
|
142
|
-
| **Font Size** | Number | 90 | Text size |
|
|
143
|
-
| **Font Color** | Color | #FFFFFF | Text color (hex) |
|
|
144
|
-
| **Font Family** | String | Arial | Font name |
|
|
145
|
-
| **Alignment** | Options | center | `left`, `center`, `right` |
|
|
146
|
-
| **Background Color** | Color | #000000 | Background color (hex) |
|
|
147
|
-
| **Background Opacity** | Number | 80 | Opacity 0-100 |
|
|
148
|
-
| **Border Color** | Color | #000000 | Border color (hex) |
|
|
149
|
-
| **Border Width** | Number | 2 | Border width (pixels) |
|
|
150
|
-
|
|
151
|
-
### Output Options
|
|
152
|
-
|
|
153
|
-
| Parameter | Type | Default | Description |
|
|
154
|
-
|-----------|------|---------|-------------|
|
|
155
|
-
| **Output Format** | Options | mp4 | `mp4`, `mov`, `webm` |
|
|
156
|
-
| **Video Codec** | Options | libx264 | `libx264`, `libx265`, `vp9` |
|
|
157
|
-
| **Quality** | Options | high | `low`, `medium`, `high`, `custom` |
|
|
158
|
-
| **Custom CRF** | Number | 18 | CRF value 0-51 (if custom quality) |
|
|
159
|
-
| **Output Binary Property** | String | data | Property name for output |
|
|
160
|
-
|
|
161
|
-
## Examples
|
|
162
|
-
|
|
163
|
-
### Example 1: Simple Video with Subtitles
|
|
164
|
-
|
|
165
|
-
```json
|
|
166
|
-
{
|
|
167
|
-
"videoSource": "url",
|
|
168
|
-
"videoUrl": "https://example.com/video.mp4",
|
|
169
|
-
"enableSubtitles": true,
|
|
170
|
-
"subtitles": {
|
|
171
|
-
"subtitle": [
|
|
172
|
-
{
|
|
173
|
-
"text": "Welcome to our video!",
|
|
174
|
-
"startTime": 0,
|
|
175
|
-
"endTime": 5,
|
|
176
|
-
"position": "bottom",
|
|
177
|
-
"fontSize": 48,
|
|
178
|
-
"fontColor": "#FFFFFF",
|
|
179
|
-
"alignment": "center"
|
|
180
|
-
}
|
|
181
|
-
]
|
|
182
|
-
},
|
|
183
|
-
"outputFormat": "mp4",
|
|
184
|
-
"quality": "high"
|
|
185
|
-
}
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
### Example 2: Video with BGM and Narration
|
|
189
|
-
|
|
190
|
-
```json
|
|
191
|
-
{
|
|
192
|
-
"videoSource": "url",
|
|
193
|
-
"videoUrl": "https://example.com/video.mp4",
|
|
194
|
-
"enableBGM": true,
|
|
195
|
-
"bgmSource": "url",
|
|
196
|
-
"bgmUrl": "https://example.com/music.mp3",
|
|
197
|
-
"bgmVolume": 20,
|
|
198
|
-
"bgmFadeIn": 3,
|
|
199
|
-
"bgmFadeOut": 3,
|
|
200
|
-
"enableNarration": true,
|
|
201
|
-
"narrationSource": "url",
|
|
202
|
-
"narrationUrl": "https://example.com/narration.mp3",
|
|
203
|
-
"narrationVolume": 90,
|
|
204
|
-
"narrationDelay": 2,
|
|
205
|
-
"outputFormat": "mp4"
|
|
206
|
-
}
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
### Example 3: Custom Positioned Subtitles
|
|
210
|
-
|
|
211
|
-
```json
|
|
212
|
-
{
|
|
213
|
-
"videoSource": "url",
|
|
214
|
-
"videoUrl": "https://example.com/video.mp4",
|
|
215
|
-
"enableSubtitles": true,
|
|
216
|
-
"subtitles": {
|
|
217
|
-
"subtitle": [
|
|
218
|
-
{
|
|
219
|
-
"text": "Top-left subtitle",
|
|
220
|
-
"startTime": 0,
|
|
221
|
-
"endTime": 5,
|
|
222
|
-
"position": "custom",
|
|
223
|
-
"customX": 100,
|
|
224
|
-
"customY": 100,
|
|
225
|
-
"fontSize": 36,
|
|
226
|
-
"fontColor": "#FFFF00",
|
|
227
|
-
"alignment": "left",
|
|
228
|
-
"backgroundColor": "#000000",
|
|
229
|
-
"backgroundOpacity": 70,
|
|
230
|
-
"borderColor": "#FFFFFF",
|
|
231
|
-
"borderWidth": 3
|
|
232
|
-
}
|
|
233
|
-
]
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
```
|
|
237
|
-
|
|
238
|
-
### Example 4: Workflow Integration
|
|
239
|
-
|
|
240
|
-
**Scenario**: Download video from URL, add BGM and subtitles, upload to cloud storage
|
|
241
|
-
|
|
242
|
-
```
|
|
243
|
-
HTTP Request → SB Render → Google Drive
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
1. **HTTP Request**: Download video file
|
|
247
|
-
2. **SB Render**: Add BGM and subtitles
|
|
248
|
-
3. **Google Drive**: Upload rendered video
|
|
249
|
-
|
|
250
|
-
## Development
|
|
251
|
-
|
|
252
|
-
### Build
|
|
253
|
-
|
|
254
|
-
```bash
|
|
255
|
-
npm install
|
|
256
|
-
npm run build
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
### Development Mode
|
|
260
|
-
|
|
261
|
-
```bash
|
|
262
|
-
npm run dev
|
|
263
|
-
```
|
|
264
|
-
|
|
265
|
-
### Linting
|
|
266
|
-
|
|
267
|
-
```bash
|
|
268
|
-
npm run lint
|
|
269
|
-
npm run lintfix
|
|
270
|
-
```
|
|
271
|
-
|
|
272
|
-
### Project Structure
|
|
273
|
-
|
|
274
|
-
```
|
|
275
|
-
sb-render/
|
|
276
|
-
├── nodes/
|
|
277
|
-
│ └── SbRender/
|
|
278
|
-
│ ├── SbRender.node.ts # Main node implementation
|
|
279
|
-
│ ├── SbRender.node.json # Node metadata
|
|
280
|
-
│ ├── services/
|
|
281
|
-
│ │ ├── FileManager.ts # File handling
|
|
282
|
-
│ │ ├── AudioMixer.ts # Audio composition
|
|
283
|
-
│ │ ├── SubtitleEngine.ts # Subtitle generation
|
|
284
|
-
│ │ └── VideoComposer.ts # Video rendering
|
|
285
|
-
│ ├── interfaces/
|
|
286
|
-
│ │ └── index.ts # TypeScript types
|
|
287
|
-
│ └── utils/
|
|
288
|
-
│ ├── ffmpeg.ts # FFmpeg helpers
|
|
289
|
-
│ └── validation.ts # Input validation
|
|
290
|
-
├── fonts/ # Custom fonts
|
|
291
|
-
├── package.json
|
|
292
|
-
├── tsconfig.json
|
|
293
|
-
└── README.md
|
|
294
|
-
```
|
|
295
|
-
|
|
296
|
-
## Troubleshooting
|
|
297
|
-
|
|
298
|
-
### FFmpeg Not Found
|
|
299
|
-
|
|
300
|
-
The node automatically installs FFmpeg via `@ffmpeg-installer/ffmpeg`. If you encounter issues:
|
|
301
|
-
|
|
302
|
-
```bash
|
|
303
|
-
npm install @ffmpeg-installer/ffmpeg --force
|
|
304
|
-
```
|
|
305
|
-
|
|
306
|
-
### File Download Errors
|
|
307
|
-
|
|
308
|
-
**Issue**: Video/audio URLs fail to download
|
|
309
|
-
|
|
310
|
-
**Solutions**:
|
|
311
|
-
- Verify URL accessibility
|
|
312
|
-
- Check for authentication requirements
|
|
313
|
-
- Ensure sufficient disk space
|
|
314
|
-
- Try using binary data input instead
|
|
315
|
-
|
|
316
|
-
### Subtitle Not Appearing
|
|
317
|
-
|
|
318
|
-
**Issue**: Subtitles don't show in output video
|
|
319
|
-
|
|
320
|
-
**Solutions**:
|
|
321
|
-
- Verify timing (start/end times within video duration)
|
|
322
|
-
- Check subtitle position and size
|
|
323
|
-
- Ensure font is available on system
|
|
324
|
-
- Try different output format (MP4 recommended)
|
|
325
|
-
|
|
326
|
-
### Memory Issues
|
|
327
|
-
|
|
328
|
-
**Issue**: Process crashes with large video files
|
|
329
|
-
|
|
330
|
-
**Solutions**:
|
|
331
|
-
- Reduce video resolution before processing
|
|
332
|
-
- Use lower quality preset
|
|
333
|
-
- Process videos in smaller batches
|
|
334
|
-
- Increase Node.js memory limit:
|
|
335
|
-
|
|
336
|
-
```bash
|
|
337
|
-
export NODE_OPTIONS="--max-old-space-size=4096"
|
|
338
|
-
```
|
|
339
|
-
|
|
340
|
-
### Audio Sync Issues
|
|
341
|
-
|
|
342
|
-
**Issue**: Audio out of sync with video
|
|
343
|
-
|
|
344
|
-
**Solutions**:
|
|
345
|
-
- Ensure all audio files are in compatible formats
|
|
346
|
-
- Check narration delay settings
|
|
347
|
-
- Verify video frame rate compatibility
|
|
348
|
-
- Try re-encoding source files
|
|
349
|
-
|
|
350
|
-
## Technical Details
|
|
351
|
-
|
|
352
|
-
### FFmpeg Commands
|
|
353
|
-
|
|
354
|
-
The node uses **fluent-ffmpeg** to construct FFmpeg commands:
|
|
355
|
-
|
|
356
|
-
**Audio Mixing**:
|
|
357
|
-
```bash
|
|
358
|
-
-filter_complex "[0:a]volume=1.0[original];[1:a]volume=0.3,afade=t=in:st=0:d=2[bgm];[original][bgm]amix=inputs=2[mixed]"
|
|
359
|
-
```
|
|
360
|
-
|
|
361
|
-
**Subtitle Overlay**:
|
|
362
|
-
```bash
|
|
363
|
-
-vf "ass=subtitles.ass"
|
|
364
|
-
```
|
|
365
|
-
|
|
366
|
-
**Complete Command**:
|
|
367
|
-
```bash
|
|
368
|
-
ffmpeg -i video.mp4 -i bgm.mp3 -filter_complex "..." -vf "ass=..." -c:v libx264 -crf 18 output.mp4
|
|
369
|
-
```
|
|
370
|
-
|
|
371
|
-
### Subtitle Formats
|
|
372
|
-
|
|
373
|
-
- **SRT**: Simple subtitle format (limited styling)
|
|
374
|
-
- **ASS**: Advanced SubStation Alpha (full styling support) ← **Used by default**
|
|
375
|
-
|
|
376
|
-
ASS format provides:
|
|
377
|
-
- Custom fonts and colors
|
|
378
|
-
- Precise positioning
|
|
379
|
-
- Background colors and opacity
|
|
380
|
-
- Border/outline effects
|
|
381
|
-
- Multiple alignment options
|
|
382
|
-
|
|
383
|
-
## Performance
|
|
384
|
-
|
|
385
|
-
### Resource Usage
|
|
386
|
-
|
|
387
|
-
| Video Length | Memory | Processing Time |
|
|
388
|
-
|--------------|--------|-----------------|
|
|
389
|
-
| 1 minute | ~200MB | ~30 seconds |
|
|
390
|
-
| 5 minutes | ~500MB | ~2 minutes |
|
|
391
|
-
| 10 minutes | ~1GB | ~5 minutes |
|
|
392
|
-
|
|
393
|
-
*Times measured on standard VPS (2 CPU, 4GB RAM)*
|
|
394
|
-
|
|
395
|
-
### Optimization Tips
|
|
396
|
-
|
|
397
|
-
1. **Use appropriate quality**: High quality for final output, medium for testing
|
|
398
|
-
2. **Compress BGM**: Use lower bitrate audio files (128-192 kbps)
|
|
399
|
-
3. **Batch processing**: Process multiple videos in parallel workflows
|
|
400
|
-
4. **Cache audio files**: Reuse same BGM/narration across multiple videos
|
|
401
|
-
|
|
402
|
-
## Compatibility
|
|
403
|
-
|
|
404
|
-
### Supported Video Formats
|
|
405
|
-
|
|
406
|
-
**Input**: MP4, MOV, WebM, AVI, MKV
|
|
407
|
-
**Output**: MP4, MOV, WebM
|
|
408
|
-
|
|
409
|
-
### Supported Audio Formats
|
|
410
|
-
|
|
411
|
-
**Input**: MP3, WAV, AAC, OGG, M4A
|
|
412
|
-
**Output**: AAC (default)
|
|
413
|
-
|
|
414
|
-
### Codec Compatibility
|
|
415
|
-
|
|
416
|
-
| Codec | Quality | Speed | Browser Support |
|
|
417
|
-
|-------|---------|-------|-----------------|
|
|
418
|
-
| H.264 (libx264) | Good | Fast | Excellent |
|
|
419
|
-
| H.265 (libx265) | Better | Slower | Limited |
|
|
420
|
-
| VP9 | Good | Slow | Good (WebM) |
|
|
421
|
-
|
|
422
|
-
## Contributing
|
|
423
|
-
|
|
424
|
-
Contributions are welcome! Please:
|
|
425
|
-
|
|
426
|
-
1. Fork the repository
|
|
427
|
-
2. Create a feature branch
|
|
428
|
-
3. Make your changes
|
|
429
|
-
4. Add tests if applicable
|
|
430
|
-
5. Submit a pull request
|
|
431
|
-
|
|
432
|
-
### Development Guidelines
|
|
433
|
-
|
|
434
|
-
- Follow existing code style (ESLint configured)
|
|
435
|
-
- Add TypeScript types for new features
|
|
436
|
-
- Update documentation for new parameters
|
|
437
|
-
- Test with various video formats
|
|
438
|
-
|
|
439
|
-
## Roadmap
|
|
440
|
-
|
|
441
|
-
### v1.1 (Planned)
|
|
442
|
-
|
|
443
|
-
- [ ] Multiple video layers
|
|
444
|
-
- [ ] Video transitions
|
|
445
|
-
- [ ] Logo/watermark overlay
|
|
446
|
-
- [ ] Preset subtitle templates
|
|
447
|
-
- [ ] Batch processing mode
|
|
448
|
-
|
|
449
|
-
### v2.0 (Future)
|
|
450
|
-
|
|
451
|
-
- [ ] GPU acceleration (NVENC, VideoToolbox)
|
|
452
|
-
- [ ] Cloud storage integration
|
|
453
|
-
- [ ] Progress callbacks
|
|
454
|
-
- [ ] Advanced video effects
|
|
455
|
-
|
|
456
|
-
## Credits
|
|
457
|
-
|
|
458
|
-
- Inspired by [n8n-nodes-mediafx](https://github.com/dandacompany/n8n-nodes-mediafx)
|
|
459
|
-
- Uses [FFmpeg](https://ffmpeg.org/) for video processing
|
|
460
|
-
- Built with [fluent-ffmpeg](https://github.com/fluent-ffmpeg/node-fluent-ffmpeg)
|
|
461
|
-
|
|
462
|
-
## License
|
|
463
|
-
|
|
464
|
-
[MIT](LICENSE)
|
|
465
|
-
|
|
466
|
-
## Support
|
|
467
|
-
|
|
468
|
-
- **Issues**: [GitHub Issues](https://github.com/choisb87/sb-render/issues)
|
|
469
|
-
- **Documentation**: [GitHub Wiki](https://github.com/choisb87/sb-render/wiki)
|
|
470
|
-
- **n8n Community**: [n8n Community Forum](https://community.n8n.io/)
|
|
471
|
-
|
|
472
|
-
---
|
|
473
|
-
|
|
474
|
-
**Made with ❤️ for the n8n community**
|
|
1
|
+
# n8n-nodes-sb-render
|
|
2
|
+
|
|
3
|
+
[](https://badge.fury.io/js/n8n-nodes-sb-render)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
|
|
6
|
+
This is an n8n community node for video rendering with customizable subtitles, background music (BGM), and narration using FFmpeg.
|
|
7
|
+
|
|
8
|
+
**sb-render** allows you to automate video composition workflows in n8n, combining video files with:
|
|
9
|
+
- 🎵 Background music with volume control and fade effects
|
|
10
|
+
- 🎙️ Narration audio with timing control
|
|
11
|
+
- 📝 Customizable subtitles with extensive styling options
|
|
12
|
+
- 🎨 Multiple output formats and quality presets
|
|
13
|
+
|
|
14
|
+
Inspired by [n8n-nodes-mediafx](https://github.com/dandacompany/n8n-nodes-mediafx).
|
|
15
|
+
|
|
16
|
+
## Table of Contents
|
|
17
|
+
|
|
18
|
+
- [Installation](#installation)
|
|
19
|
+
- [Prerequisites](#prerequisites)
|
|
20
|
+
- [Operations](#operations)
|
|
21
|
+
- [Configuration](#configuration)
|
|
22
|
+
- [Examples](#examples)
|
|
23
|
+
- [Development](#development)
|
|
24
|
+
- [Troubleshooting](#troubleshooting)
|
|
25
|
+
- [License](#license)
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
### Community Nodes (Recommended)
|
|
30
|
+
|
|
31
|
+
1. Go to **Settings > Community Nodes** in n8n
|
|
32
|
+
2. Select **Install**
|
|
33
|
+
3. Enter `n8n-nodes-sb-render`
|
|
34
|
+
4. Agree to the risks and install
|
|
35
|
+
|
|
36
|
+
### Manual Installation
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npm install n8n-nodes-sb-render
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
For n8n self-hosted installations:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
cd ~/.n8n
|
|
46
|
+
npm install n8n-nodes-sb-render
|
|
47
|
+
# Restart n8n
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Prerequisites
|
|
51
|
+
|
|
52
|
+
- **n8n version**: 1.0.0 or higher
|
|
53
|
+
- **Node.js**: 16.0.0 or higher
|
|
54
|
+
- **FFmpeg**: Auto-detected from system or installed via npm packages
|
|
55
|
+
|
|
56
|
+
### FFmpeg Installation (Docker/n8n Users)
|
|
57
|
+
|
|
58
|
+
For **Docker or self-hosted n8n**, installing system ffmpeg is recommended:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
# Alpine-based containers (n8n official image)
|
|
62
|
+
docker exec <container-name> apk add --no-cache ffmpeg
|
|
63
|
+
|
|
64
|
+
# Debian/Ubuntu-based containers
|
|
65
|
+
docker exec <container-name> apt-get update && apt-get install -y ffmpeg
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**docker-compose.yml example:**
|
|
69
|
+
```yaml
|
|
70
|
+
services:
|
|
71
|
+
n8n:
|
|
72
|
+
image: n8nio/n8n
|
|
73
|
+
command: >
|
|
74
|
+
sh -c "
|
|
75
|
+
apk add --no-cache ffmpeg &&
|
|
76
|
+
n8n start
|
|
77
|
+
"
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
The node will automatically:
|
|
81
|
+
1. ✅ Use system ffmpeg/ffprobe if available (most reliable)
|
|
82
|
+
2. ✅ Fall back to npm packages with auto-permission fix
|
|
83
|
+
3. ✅ Gracefully degrade with limited functionality
|
|
84
|
+
|
|
85
|
+
> **Note**: v1.1.20+ automatically handles ffmpeg/ffprobe detection and permission issues!
|
|
86
|
+
|
|
87
|
+
## Operations
|
|
88
|
+
|
|
89
|
+
### Video → Render
|
|
90
|
+
|
|
91
|
+
Compose a video with optional background music, narration, and subtitles.
|
|
92
|
+
|
|
93
|
+
**Features:**
|
|
94
|
+
- ✅ Multiple input sources (URL or binary data)
|
|
95
|
+
- ✅ Audio mixing with independent volume controls
|
|
96
|
+
- ✅ Fade in/out effects for BGM
|
|
97
|
+
- ✅ Customizable subtitle positioning and styling
|
|
98
|
+
- ✅ Multiple output formats (MP4, MOV, WebM)
|
|
99
|
+
- ✅ Quality presets (Low, Medium, High, Custom)
|
|
100
|
+
- ✅ Smart audio merging (handles mixed audio/silent video inputs)
|
|
101
|
+
|
|
102
|
+
## Configuration
|
|
103
|
+
|
|
104
|
+
### Video Input
|
|
105
|
+
|
|
106
|
+
| Parameter | Type | Required | Description |
|
|
107
|
+
|-----------|------|----------|-------------|
|
|
108
|
+
| **Video Source** | Options | Yes | `url` or `binary` |
|
|
109
|
+
| **Video URL** | String | If URL | URL of the video file |
|
|
110
|
+
| **Video Binary Property** | String | If Binary | Name of binary property containing video |
|
|
111
|
+
|
|
112
|
+
### Background Music (BGM)
|
|
113
|
+
|
|
114
|
+
| Parameter | Type | Default | Description |
|
|
115
|
+
|-----------|------|---------|-------------|
|
|
116
|
+
| **Enable BGM** | Boolean | false | Add background music |
|
|
117
|
+
| **BGM Source** | Options | - | `url` or `binary` |
|
|
118
|
+
| **BGM URL** | String | - | URL of BGM file |
|
|
119
|
+
| **BGM Volume** | Number | 30 | Volume 0-100 |
|
|
120
|
+
| **BGM Fade In** | Number | 2 | Fade-in duration (seconds) |
|
|
121
|
+
| **BGM Fade Out** | Number | 2 | Fade-out duration (seconds) |
|
|
122
|
+
|
|
123
|
+
### Narration
|
|
124
|
+
|
|
125
|
+
| Parameter | Type | Default | Description |
|
|
126
|
+
|-----------|------|---------|-------------|
|
|
127
|
+
| **Enable Narration** | Boolean | false | Add narration audio |
|
|
128
|
+
| **Narration Source** | Options | - | `url` or `binary` |
|
|
129
|
+
| **Narration URL** | String | - | URL of narration file |
|
|
130
|
+
| **Narration Volume** | Number | 80 | Volume 0-100 |
|
|
131
|
+
| **Narration Delay** | Number | 0 | Delay before start (seconds) |
|
|
132
|
+
|
|
133
|
+
### Subtitles
|
|
134
|
+
|
|
135
|
+
| Parameter | Type | Default | Description |
|
|
136
|
+
|-----------|------|---------|-------------|
|
|
137
|
+
| **Enable Subtitles** | Boolean | false | Add subtitles |
|
|
138
|
+
| **Text** | String | - | Subtitle text content |
|
|
139
|
+
| **Start Time** | Number | - | Start time in seconds |
|
|
140
|
+
| **End Time** | Number | - | End time in seconds |
|
|
141
|
+
| **Position** | Options | bottom | `top`, `middle`, `bottom`, `custom` |
|
|
142
|
+
| **Font Size** | Number | 90 | Text size |
|
|
143
|
+
| **Font Color** | Color | #FFFFFF | Text color (hex) |
|
|
144
|
+
| **Font Family** | String | Arial | Font name |
|
|
145
|
+
| **Alignment** | Options | center | `left`, `center`, `right` |
|
|
146
|
+
| **Background Color** | Color | #000000 | Background color (hex) |
|
|
147
|
+
| **Background Opacity** | Number | 80 | Opacity 0-100 |
|
|
148
|
+
| **Border Color** | Color | #000000 | Border color (hex) |
|
|
149
|
+
| **Border Width** | Number | 2 | Border width (pixels) |
|
|
150
|
+
|
|
151
|
+
### Output Options
|
|
152
|
+
|
|
153
|
+
| Parameter | Type | Default | Description |
|
|
154
|
+
|-----------|------|---------|-------------|
|
|
155
|
+
| **Output Format** | Options | mp4 | `mp4`, `mov`, `webm` |
|
|
156
|
+
| **Video Codec** | Options | libx264 | `libx264`, `libx265`, `vp9` |
|
|
157
|
+
| **Quality** | Options | high | `low`, `medium`, `high`, `custom` |
|
|
158
|
+
| **Custom CRF** | Number | 18 | CRF value 0-51 (if custom quality) |
|
|
159
|
+
| **Output Binary Property** | String | data | Property name for output |
|
|
160
|
+
|
|
161
|
+
## Examples
|
|
162
|
+
|
|
163
|
+
### Example 1: Simple Video with Subtitles
|
|
164
|
+
|
|
165
|
+
```json
|
|
166
|
+
{
|
|
167
|
+
"videoSource": "url",
|
|
168
|
+
"videoUrl": "https://example.com/video.mp4",
|
|
169
|
+
"enableSubtitles": true,
|
|
170
|
+
"subtitles": {
|
|
171
|
+
"subtitle": [
|
|
172
|
+
{
|
|
173
|
+
"text": "Welcome to our video!",
|
|
174
|
+
"startTime": 0,
|
|
175
|
+
"endTime": 5,
|
|
176
|
+
"position": "bottom",
|
|
177
|
+
"fontSize": 48,
|
|
178
|
+
"fontColor": "#FFFFFF",
|
|
179
|
+
"alignment": "center"
|
|
180
|
+
}
|
|
181
|
+
]
|
|
182
|
+
},
|
|
183
|
+
"outputFormat": "mp4",
|
|
184
|
+
"quality": "high"
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Example 2: Video with BGM and Narration
|
|
189
|
+
|
|
190
|
+
```json
|
|
191
|
+
{
|
|
192
|
+
"videoSource": "url",
|
|
193
|
+
"videoUrl": "https://example.com/video.mp4",
|
|
194
|
+
"enableBGM": true,
|
|
195
|
+
"bgmSource": "url",
|
|
196
|
+
"bgmUrl": "https://example.com/music.mp3",
|
|
197
|
+
"bgmVolume": 20,
|
|
198
|
+
"bgmFadeIn": 3,
|
|
199
|
+
"bgmFadeOut": 3,
|
|
200
|
+
"enableNarration": true,
|
|
201
|
+
"narrationSource": "url",
|
|
202
|
+
"narrationUrl": "https://example.com/narration.mp3",
|
|
203
|
+
"narrationVolume": 90,
|
|
204
|
+
"narrationDelay": 2,
|
|
205
|
+
"outputFormat": "mp4"
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Example 3: Custom Positioned Subtitles
|
|
210
|
+
|
|
211
|
+
```json
|
|
212
|
+
{
|
|
213
|
+
"videoSource": "url",
|
|
214
|
+
"videoUrl": "https://example.com/video.mp4",
|
|
215
|
+
"enableSubtitles": true,
|
|
216
|
+
"subtitles": {
|
|
217
|
+
"subtitle": [
|
|
218
|
+
{
|
|
219
|
+
"text": "Top-left subtitle",
|
|
220
|
+
"startTime": 0,
|
|
221
|
+
"endTime": 5,
|
|
222
|
+
"position": "custom",
|
|
223
|
+
"customX": 100,
|
|
224
|
+
"customY": 100,
|
|
225
|
+
"fontSize": 36,
|
|
226
|
+
"fontColor": "#FFFF00",
|
|
227
|
+
"alignment": "left",
|
|
228
|
+
"backgroundColor": "#000000",
|
|
229
|
+
"backgroundOpacity": 70,
|
|
230
|
+
"borderColor": "#FFFFFF",
|
|
231
|
+
"borderWidth": 3
|
|
232
|
+
}
|
|
233
|
+
]
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### Example 4: Workflow Integration
|
|
239
|
+
|
|
240
|
+
**Scenario**: Download video from URL, add BGM and subtitles, upload to cloud storage
|
|
241
|
+
|
|
242
|
+
```
|
|
243
|
+
HTTP Request → SB Render → Google Drive
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
1. **HTTP Request**: Download video file
|
|
247
|
+
2. **SB Render**: Add BGM and subtitles
|
|
248
|
+
3. **Google Drive**: Upload rendered video
|
|
249
|
+
|
|
250
|
+
## Development
|
|
251
|
+
|
|
252
|
+
### Build
|
|
253
|
+
|
|
254
|
+
```bash
|
|
255
|
+
npm install
|
|
256
|
+
npm run build
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### Development Mode
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
npm run dev
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### Linting
|
|
266
|
+
|
|
267
|
+
```bash
|
|
268
|
+
npm run lint
|
|
269
|
+
npm run lintfix
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### Project Structure
|
|
273
|
+
|
|
274
|
+
```
|
|
275
|
+
sb-render/
|
|
276
|
+
├── nodes/
|
|
277
|
+
│ └── SbRender/
|
|
278
|
+
│ ├── SbRender.node.ts # Main node implementation
|
|
279
|
+
│ ├── SbRender.node.json # Node metadata
|
|
280
|
+
│ ├── services/
|
|
281
|
+
│ │ ├── FileManager.ts # File handling
|
|
282
|
+
│ │ ├── AudioMixer.ts # Audio composition
|
|
283
|
+
│ │ ├── SubtitleEngine.ts # Subtitle generation
|
|
284
|
+
│ │ └── VideoComposer.ts # Video rendering
|
|
285
|
+
│ ├── interfaces/
|
|
286
|
+
│ │ └── index.ts # TypeScript types
|
|
287
|
+
│ └── utils/
|
|
288
|
+
│ ├── ffmpeg.ts # FFmpeg helpers
|
|
289
|
+
│ └── validation.ts # Input validation
|
|
290
|
+
├── fonts/ # Custom fonts
|
|
291
|
+
├── package.json
|
|
292
|
+
├── tsconfig.json
|
|
293
|
+
└── README.md
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
## Troubleshooting
|
|
297
|
+
|
|
298
|
+
### FFmpeg Not Found
|
|
299
|
+
|
|
300
|
+
The node automatically installs FFmpeg via `@ffmpeg-installer/ffmpeg`. If you encounter issues:
|
|
301
|
+
|
|
302
|
+
```bash
|
|
303
|
+
npm install @ffmpeg-installer/ffmpeg --force
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
### File Download Errors
|
|
307
|
+
|
|
308
|
+
**Issue**: Video/audio URLs fail to download
|
|
309
|
+
|
|
310
|
+
**Solutions**:
|
|
311
|
+
- Verify URL accessibility
|
|
312
|
+
- Check for authentication requirements
|
|
313
|
+
- Ensure sufficient disk space
|
|
314
|
+
- Try using binary data input instead
|
|
315
|
+
|
|
316
|
+
### Subtitle Not Appearing
|
|
317
|
+
|
|
318
|
+
**Issue**: Subtitles don't show in output video
|
|
319
|
+
|
|
320
|
+
**Solutions**:
|
|
321
|
+
- Verify timing (start/end times within video duration)
|
|
322
|
+
- Check subtitle position and size
|
|
323
|
+
- Ensure font is available on system
|
|
324
|
+
- Try different output format (MP4 recommended)
|
|
325
|
+
|
|
326
|
+
### Memory Issues
|
|
327
|
+
|
|
328
|
+
**Issue**: Process crashes with large video files
|
|
329
|
+
|
|
330
|
+
**Solutions**:
|
|
331
|
+
- Reduce video resolution before processing
|
|
332
|
+
- Use lower quality preset
|
|
333
|
+
- Process videos in smaller batches
|
|
334
|
+
- Increase Node.js memory limit:
|
|
335
|
+
|
|
336
|
+
```bash
|
|
337
|
+
export NODE_OPTIONS="--max-old-space-size=4096"
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
### Audio Sync Issues
|
|
341
|
+
|
|
342
|
+
**Issue**: Audio out of sync with video
|
|
343
|
+
|
|
344
|
+
**Solutions**:
|
|
345
|
+
- Ensure all audio files are in compatible formats
|
|
346
|
+
- Check narration delay settings
|
|
347
|
+
- Verify video frame rate compatibility
|
|
348
|
+
- Try re-encoding source files
|
|
349
|
+
|
|
350
|
+
## Technical Details
|
|
351
|
+
|
|
352
|
+
### FFmpeg Commands
|
|
353
|
+
|
|
354
|
+
The node uses **fluent-ffmpeg** to construct FFmpeg commands:
|
|
355
|
+
|
|
356
|
+
**Audio Mixing**:
|
|
357
|
+
```bash
|
|
358
|
+
-filter_complex "[0:a]volume=1.0[original];[1:a]volume=0.3,afade=t=in:st=0:d=2[bgm];[original][bgm]amix=inputs=2[mixed]"
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
**Subtitle Overlay**:
|
|
362
|
+
```bash
|
|
363
|
+
-vf "ass=subtitles.ass"
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
**Complete Command**:
|
|
367
|
+
```bash
|
|
368
|
+
ffmpeg -i video.mp4 -i bgm.mp3 -filter_complex "..." -vf "ass=..." -c:v libx264 -crf 18 output.mp4
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
### Subtitle Formats
|
|
372
|
+
|
|
373
|
+
- **SRT**: Simple subtitle format (limited styling)
|
|
374
|
+
- **ASS**: Advanced SubStation Alpha (full styling support) ← **Used by default**
|
|
375
|
+
|
|
376
|
+
ASS format provides:
|
|
377
|
+
- Custom fonts and colors
|
|
378
|
+
- Precise positioning
|
|
379
|
+
- Background colors and opacity
|
|
380
|
+
- Border/outline effects
|
|
381
|
+
- Multiple alignment options
|
|
382
|
+
|
|
383
|
+
## Performance
|
|
384
|
+
|
|
385
|
+
### Resource Usage
|
|
386
|
+
|
|
387
|
+
| Video Length | Memory | Processing Time |
|
|
388
|
+
|--------------|--------|-----------------|
|
|
389
|
+
| 1 minute | ~200MB | ~30 seconds |
|
|
390
|
+
| 5 minutes | ~500MB | ~2 minutes |
|
|
391
|
+
| 10 minutes | ~1GB | ~5 minutes |
|
|
392
|
+
|
|
393
|
+
*Times measured on standard VPS (2 CPU, 4GB RAM)*
|
|
394
|
+
|
|
395
|
+
### Optimization Tips
|
|
396
|
+
|
|
397
|
+
1. **Use appropriate quality**: High quality for final output, medium for testing
|
|
398
|
+
2. **Compress BGM**: Use lower bitrate audio files (128-192 kbps)
|
|
399
|
+
3. **Batch processing**: Process multiple videos in parallel workflows
|
|
400
|
+
4. **Cache audio files**: Reuse same BGM/narration across multiple videos
|
|
401
|
+
|
|
402
|
+
## Compatibility
|
|
403
|
+
|
|
404
|
+
### Supported Video Formats
|
|
405
|
+
|
|
406
|
+
**Input**: MP4, MOV, WebM, AVI, MKV
|
|
407
|
+
**Output**: MP4, MOV, WebM
|
|
408
|
+
|
|
409
|
+
### Supported Audio Formats
|
|
410
|
+
|
|
411
|
+
**Input**: MP3, WAV, AAC, OGG, M4A
|
|
412
|
+
**Output**: AAC (default)
|
|
413
|
+
|
|
414
|
+
### Codec Compatibility
|
|
415
|
+
|
|
416
|
+
| Codec | Quality | Speed | Browser Support |
|
|
417
|
+
|-------|---------|-------|-----------------|
|
|
418
|
+
| H.264 (libx264) | Good | Fast | Excellent |
|
|
419
|
+
| H.265 (libx265) | Better | Slower | Limited |
|
|
420
|
+
| VP9 | Good | Slow | Good (WebM) |
|
|
421
|
+
|
|
422
|
+
## Contributing
|
|
423
|
+
|
|
424
|
+
Contributions are welcome! Please:
|
|
425
|
+
|
|
426
|
+
1. Fork the repository
|
|
427
|
+
2. Create a feature branch
|
|
428
|
+
3. Make your changes
|
|
429
|
+
4. Add tests if applicable
|
|
430
|
+
5. Submit a pull request
|
|
431
|
+
|
|
432
|
+
### Development Guidelines
|
|
433
|
+
|
|
434
|
+
- Follow existing code style (ESLint configured)
|
|
435
|
+
- Add TypeScript types for new features
|
|
436
|
+
- Update documentation for new parameters
|
|
437
|
+
- Test with various video formats
|
|
438
|
+
|
|
439
|
+
## Roadmap
|
|
440
|
+
|
|
441
|
+
### v1.1 (Planned)
|
|
442
|
+
|
|
443
|
+
- [ ] Multiple video layers
|
|
444
|
+
- [ ] Video transitions
|
|
445
|
+
- [ ] Logo/watermark overlay
|
|
446
|
+
- [ ] Preset subtitle templates
|
|
447
|
+
- [ ] Batch processing mode
|
|
448
|
+
|
|
449
|
+
### v2.0 (Future)
|
|
450
|
+
|
|
451
|
+
- [ ] GPU acceleration (NVENC, VideoToolbox)
|
|
452
|
+
- [ ] Cloud storage integration
|
|
453
|
+
- [ ] Progress callbacks
|
|
454
|
+
- [ ] Advanced video effects
|
|
455
|
+
|
|
456
|
+
## Credits
|
|
457
|
+
|
|
458
|
+
- Inspired by [n8n-nodes-mediafx](https://github.com/dandacompany/n8n-nodes-mediafx)
|
|
459
|
+
- Uses [FFmpeg](https://ffmpeg.org/) for video processing
|
|
460
|
+
- Built with [fluent-ffmpeg](https://github.com/fluent-ffmpeg/node-fluent-ffmpeg)
|
|
461
|
+
|
|
462
|
+
## License
|
|
463
|
+
|
|
464
|
+
[MIT](LICENSE)
|
|
465
|
+
|
|
466
|
+
## Support
|
|
467
|
+
|
|
468
|
+
- **Issues**: [GitHub Issues](https://github.com/choisb87/sb-render/issues)
|
|
469
|
+
- **Documentation**: [GitHub Wiki](https://github.com/choisb87/sb-render/wiki)
|
|
470
|
+
- **n8n Community**: [n8n Community Forum](https://community.n8n.io/)
|
|
471
|
+
|
|
472
|
+
---
|
|
473
|
+
|
|
474
|
+
**Made with ❤️ for the n8n community**
|