@shaztech/video-pipeline 1.3.0 → 1.4.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.
- package/README.md +3 -1
- package/dist/editor/assets/{index-yrb6jZba.js → index-DK9i7gno.js} +13 -13
- package/dist/editor/index.html +1 -1
- package/package.json +1 -1
- package/src/executor/nodeHandlers/imageAnnotate.js +9 -0
- package/src/executor/nodeHandlers/video-stitcher.js +4 -0
- package/src/server/routes.js +35 -15
package/dist/editor/index.html
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
html, body, #root { height: 100%; width: 100%; overflow: hidden; }
|
|
10
10
|
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: #1a1a2e; color: #e0e0e0; }
|
|
11
11
|
</style>
|
|
12
|
-
<script type="module" crossorigin src="./assets/index-
|
|
12
|
+
<script type="module" crossorigin src="./assets/index-DK9i7gno.js"></script>
|
|
13
13
|
<link rel="stylesheet" crossorigin href="./assets/index-CUxLpKni.css">
|
|
14
14
|
</head>
|
|
15
15
|
<body>
|
package/package.json
CHANGED
|
@@ -50,6 +50,8 @@ function buildDrawtextArgs(srcLabel, {
|
|
|
50
50
|
fontFile,
|
|
51
51
|
fontSize = 48,
|
|
52
52
|
fontColor = 'white',
|
|
53
|
+
borderColor,
|
|
54
|
+
borderWidth,
|
|
53
55
|
box = false,
|
|
54
56
|
boxColor = 'black@0.5',
|
|
55
57
|
padding = 20,
|
|
@@ -89,6 +91,11 @@ function buildDrawtextArgs(srcLabel, {
|
|
|
89
91
|
`:x=${x}` +
|
|
90
92
|
`:y=${y}`
|
|
91
93
|
|
|
94
|
+
if (borderWidth != null && borderWidth > 0) {
|
|
95
|
+
filterStr += `:borderw=${borderWidth}`
|
|
96
|
+
if (borderColor) filterStr += `:bordercolor=${borderColor}`
|
|
97
|
+
}
|
|
98
|
+
|
|
92
99
|
if (box) {
|
|
93
100
|
filterStr += `:box=1:boxcolor=${boxColor}:boxborderw=8`
|
|
94
101
|
}
|
|
@@ -112,6 +119,8 @@ function buildDrawtextArgs(srcLabel, {
|
|
|
112
119
|
* @param {string} opts.fontFile - path to a .ttf/.otf/.ttc font file (required)
|
|
113
120
|
* @param {number} [opts.fontSize=48]
|
|
114
121
|
* @param {string} [opts.fontColor='white']
|
|
122
|
+
* @param {string} [opts.borderColor] - color of text stroke/outline (e.g. 'black')
|
|
123
|
+
* @param {number} [opts.borderWidth] - width of text stroke in pixels (0 = off)
|
|
115
124
|
* @param {boolean} [opts.box=false] - draw a semi-transparent background box
|
|
116
125
|
* @param {string} [opts.boxColor='black@0.5']
|
|
117
126
|
* @param {number} [opts.padding=20] - px distance from edges (used by presets)
|
|
@@ -209,6 +209,8 @@ export async function handleVideoStitcher(node, context, tempRoot, incomingEdges
|
|
|
209
209
|
fontFile: sl.fontFile,
|
|
210
210
|
fontSize: sl.fontSize,
|
|
211
211
|
fontColor: sl.fontColor,
|
|
212
|
+
borderColor: sl.borderColor,
|
|
213
|
+
borderWidth: sl.borderWidth,
|
|
212
214
|
box: sl.box,
|
|
213
215
|
boxColor: sl.boxColor,
|
|
214
216
|
padding: sl.padding,
|
|
@@ -251,6 +253,8 @@ export async function handleVideoStitcher(node, context, tempRoot, incomingEdges
|
|
|
251
253
|
fontFile: videoSl.fontFile,
|
|
252
254
|
fontSize: videoSl.fontSize,
|
|
253
255
|
fontColor: videoSl.fontColor,
|
|
256
|
+
borderColor: videoSl.borderColor,
|
|
257
|
+
borderWidth: videoSl.borderWidth,
|
|
254
258
|
box: videoSl.box,
|
|
255
259
|
boxColor: videoSl.boxColor,
|
|
256
260
|
padding: videoSl.padding,
|
package/src/server/routes.js
CHANGED
|
@@ -14,27 +14,40 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import { readFileSync, writeFileSync, renameSync } from 'fs'
|
|
17
|
+
import { readFileSync, writeFileSync, renameSync, existsSync, statSync } from 'fs'
|
|
18
18
|
import { execFile } from 'child_process'
|
|
19
19
|
import path from 'path'
|
|
20
20
|
import { Router } from 'express'
|
|
21
21
|
|
|
22
|
-
function
|
|
22
|
+
function resolveStartFolder(from) {
|
|
23
|
+
if (!from || typeof from !== 'string') return null
|
|
24
|
+
try {
|
|
25
|
+
if (!existsSync(from)) return null
|
|
26
|
+
return statSync(from).isDirectory() ? from : path.dirname(from)
|
|
27
|
+
} catch { return null }
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function nativeBrowse(from) {
|
|
31
|
+
const start = resolveStartFolder(from)
|
|
23
32
|
return new Promise((resolve) => {
|
|
24
33
|
const { platform } = process
|
|
25
34
|
if (platform === 'darwin') {
|
|
26
|
-
|
|
35
|
+
const loc = start ? ` default location (POSIX file "${start.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}")` : ''
|
|
36
|
+
execFile('osascript', ['-e', `POSIX path of (choose file${loc})`], (err, stdout) => {
|
|
27
37
|
resolve(err ? null : stdout.trim())
|
|
28
38
|
})
|
|
29
39
|
} else if (platform === 'linux') {
|
|
30
|
-
|
|
40
|
+
const args = ['--file-selection']
|
|
41
|
+
if (start) args.push(`--filename=${start.endsWith('/') ? start : start + '/'}`)
|
|
42
|
+
execFile('zenity', args, (err, stdout) => {
|
|
31
43
|
if (!err) return resolve(stdout.trim())
|
|
32
|
-
execFile('kdialog', ['--getopenfilename', '.'], (err2, stdout2) => {
|
|
44
|
+
execFile('kdialog', ['--getopenfilename', start || '.'], (err2, stdout2) => {
|
|
33
45
|
resolve(err2 ? null : stdout2.trim())
|
|
34
46
|
})
|
|
35
47
|
})
|
|
36
48
|
} else if (platform === 'win32') {
|
|
37
|
-
const
|
|
49
|
+
const initLine = start ? `$d.InitialDirectory = '${start.replace(/'/g, "''")}'; ` : ''
|
|
50
|
+
const ps = `Add-Type -AssemblyName System.Windows.Forms; $d = New-Object System.Windows.Forms.OpenFileDialog; ${initLine}if ($d.ShowDialog() -eq 'OK') { $d.FileName }`
|
|
38
51
|
execFile('powershell', ['-Command', ps], (err, stdout) => {
|
|
39
52
|
resolve(err ? null : stdout.trim())
|
|
40
53
|
})
|
|
@@ -44,22 +57,27 @@ function nativeBrowse() {
|
|
|
44
57
|
})
|
|
45
58
|
}
|
|
46
59
|
|
|
47
|
-
function nativeBrowseFolder() {
|
|
60
|
+
function nativeBrowseFolder(from) {
|
|
61
|
+
const start = resolveStartFolder(from)
|
|
48
62
|
return new Promise((resolve) => {
|
|
49
63
|
const { platform } = process
|
|
50
64
|
if (platform === 'darwin') {
|
|
51
|
-
|
|
65
|
+
const loc = start ? ` default location (POSIX file "${start.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}")` : ''
|
|
66
|
+
execFile('osascript', ['-e', `POSIX path of (choose folder${loc})`], (err, stdout) => {
|
|
52
67
|
resolve(err ? null : stdout.trim())
|
|
53
68
|
})
|
|
54
69
|
} else if (platform === 'linux') {
|
|
55
|
-
|
|
70
|
+
const args = ['--file-selection', '--directory']
|
|
71
|
+
if (start) args.push(`--filename=${start.endsWith('/') ? start : start + '/'}`)
|
|
72
|
+
execFile('zenity', args, (err, stdout) => {
|
|
56
73
|
if (!err) return resolve(stdout.trim())
|
|
57
|
-
execFile('kdialog', ['--getexistingdirectory', '.'], (err2, stdout2) => {
|
|
74
|
+
execFile('kdialog', ['--getexistingdirectory', start || '.'], (err2, stdout2) => {
|
|
58
75
|
resolve(err2 ? null : stdout2.trim())
|
|
59
76
|
})
|
|
60
77
|
})
|
|
61
78
|
} else if (platform === 'win32') {
|
|
62
|
-
const
|
|
79
|
+
const initLine = start ? `$d.SelectedPath = '${start.replace(/'/g, "''")}'; ` : ''
|
|
80
|
+
const ps = `Add-Type -AssemblyName System.Windows.Forms; $d = New-Object System.Windows.Forms.FolderBrowserDialog; ${initLine}if ($d.ShowDialog() -eq 'OK') { $d.SelectedPath }`
|
|
63
81
|
execFile('powershell', ['-Command', ps], (err, stdout) => {
|
|
64
82
|
resolve(err ? null : stdout.trim())
|
|
65
83
|
})
|
|
@@ -89,14 +107,16 @@ export function createRoutes(specPath, broadcast) {
|
|
|
89
107
|
})
|
|
90
108
|
|
|
91
109
|
// GET /api/browse — open a native OS file picker, return full path
|
|
92
|
-
|
|
93
|
-
|
|
110
|
+
// Optional ?from=<path> opens the picker at that path's parent folder
|
|
111
|
+
router.get('/api/browse', async (req, res) => {
|
|
112
|
+
const filePath = await nativeBrowse(typeof req.query.from === 'string' ? req.query.from : null)
|
|
94
113
|
res.json({ path: filePath })
|
|
95
114
|
})
|
|
96
115
|
|
|
97
116
|
// GET /api/browse-folder — open a native OS folder picker, return full path
|
|
98
|
-
|
|
99
|
-
|
|
117
|
+
// Optional ?from=<path> opens the picker at that path (or its parent if a file)
|
|
118
|
+
router.get('/api/browse-folder', async (req, res) => {
|
|
119
|
+
const folderPath = await nativeBrowseFolder(typeof req.query.from === 'string' ? req.query.from : null)
|
|
100
120
|
res.json({ path: folderPath })
|
|
101
121
|
})
|
|
102
122
|
|