polotno-node 2.9.35 → 2.9.37
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 +7 -2
- package/dist/assets/{index-DsVyOnN0.js → index-BWNdW2kw.js} +100 -100
- package/dist/index.html +1 -1
- package/index.js +10 -5
- package/package.json +2 -2
- package/video-parallel.js +25 -10
package/dist/index.html
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
}
|
|
9
9
|
</style>
|
|
10
10
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
11
|
-
<script type="module" crossorigin src="./assets/index-
|
|
11
|
+
<script type="module" crossorigin src="./assets/index-BWNdW2kw.js"></script>
|
|
12
12
|
</head>
|
|
13
13
|
<body>
|
|
14
14
|
<div id="root"></div>
|
package/index.js
CHANGED
|
@@ -73,6 +73,14 @@ const minimal_args = [
|
|
|
73
73
|
'--text-rendering=geometricprecision',
|
|
74
74
|
].filter(Boolean);
|
|
75
75
|
|
|
76
|
+
const browserProps = {
|
|
77
|
+
headless: 'new',
|
|
78
|
+
// make large timeout, because some renders may take a lot of time
|
|
79
|
+
// like large PDF or video render
|
|
80
|
+
protocolTimeout: 60 * 60 * 1000,
|
|
81
|
+
ignoreHTTPSErrors: true,
|
|
82
|
+
};
|
|
83
|
+
|
|
76
84
|
async function createBrowser({ browserArgs = [], ...rest } = {}) {
|
|
77
85
|
return puppeteer.launch({
|
|
78
86
|
args: [
|
|
@@ -83,13 +91,10 @@ async function createBrowser({ browserArgs = [], ...rest } = {}) {
|
|
|
83
91
|
...browserArgs,
|
|
84
92
|
],
|
|
85
93
|
defaultViewport: chrome.defaultViewport,
|
|
86
|
-
|
|
87
|
-
// make default protocol timeout bigger
|
|
88
|
-
// because some clients had issues with it
|
|
89
|
-
protocolTimeout: 10 * 60 * 1000,
|
|
94
|
+
|
|
90
95
|
executablePath:
|
|
91
96
|
isMacOs || isWindows ? undefined : await chrome.executablePath(),
|
|
92
|
-
|
|
97
|
+
...browserProps,
|
|
93
98
|
...rest,
|
|
94
99
|
});
|
|
95
100
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "polotno-node",
|
|
3
|
-
"version": "2.9.
|
|
3
|
+
"version": "2.9.37",
|
|
4
4
|
"description": "Polotno workflow from NodeJS",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"gifencoder": "^2.0.1",
|
|
27
27
|
"pixelmatch": "^6.0.0",
|
|
28
28
|
"pngjs": "^7.0.0",
|
|
29
|
-
"polotno": "^2.11.
|
|
29
|
+
"polotno": "^2.11.5",
|
|
30
30
|
"react": "^18.3.1",
|
|
31
31
|
"react-dom": "^18.3.1",
|
|
32
32
|
"vite": "^5.3.4"
|
package/video-parallel.js
CHANGED
|
@@ -57,21 +57,23 @@ const fileToDataUrl = (filename) => {
|
|
|
57
57
|
});
|
|
58
58
|
};
|
|
59
59
|
|
|
60
|
-
const convertVideo = async (url, tempFolder) => {
|
|
60
|
+
const convertVideo = async (url, tempFolder, skipWebm) => {
|
|
61
61
|
const shortUrl = url.slice(0, 50) + '...';
|
|
62
62
|
console.log('Downloading video: ' + shortUrl);
|
|
63
63
|
const filename = Math.random().toString(36).substring(7);
|
|
64
64
|
const mp4Destination = path.join(tempFolder.name, filename + '.mp4');
|
|
65
65
|
await downloadVideo(url, mp4Destination);
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
let dataURL = '';
|
|
67
|
+
if (!skipWebm) {
|
|
68
|
+
console.log('Converting video to webm: ' + filename);
|
|
69
|
+
const webmDestination = mp4Destination.replace('.mp4', '.webm');
|
|
70
|
+
await convertToWebM(mp4Destination, webmDestination);
|
|
71
|
+
dataURL = await fileToDataUrl(webmDestination);
|
|
72
|
+
console.log('Converting video finished: ' + filename);
|
|
73
|
+
}
|
|
70
74
|
|
|
71
|
-
console.log('Converting video finished: ' + filename);
|
|
72
75
|
return {
|
|
73
76
|
dataURL,
|
|
74
|
-
file: webmDestination,
|
|
75
77
|
mp4File: mp4Destination,
|
|
76
78
|
};
|
|
77
79
|
};
|
|
@@ -106,7 +108,9 @@ module.exports.jsonToVideo = async function jsonToVideo(
|
|
|
106
108
|
tempFolder,
|
|
107
109
|
attrs.skipWebm
|
|
108
110
|
);
|
|
109
|
-
|
|
111
|
+
if (!attrs.skipWebm) {
|
|
112
|
+
el.src = dataURL;
|
|
113
|
+
}
|
|
110
114
|
el.file = file;
|
|
111
115
|
el.mp4File = mp4File;
|
|
112
116
|
})
|
|
@@ -115,9 +119,13 @@ module.exports.jsonToVideo = async function jsonToVideo(
|
|
|
115
119
|
const duration = json.pages.reduce((acc, page) => {
|
|
116
120
|
return acc + (page.duration ?? 5000);
|
|
117
121
|
}, 0);
|
|
122
|
+
|
|
123
|
+
if (duration === 0) {
|
|
124
|
+
throw new Error('Video duration is 0');
|
|
125
|
+
}
|
|
118
126
|
const parallel = attrs.parallel || 5;
|
|
119
127
|
|
|
120
|
-
const fps = attrs.fps ||
|
|
128
|
+
const fps = attrs.fps || 30;
|
|
121
129
|
const timePerFrame = 1000 / fps;
|
|
122
130
|
|
|
123
131
|
// loop through the images and add each to the animation
|
|
@@ -149,6 +157,8 @@ module.exports.jsonToVideo = async function jsonToVideo(
|
|
|
149
157
|
chunks.map(async (chunk, chunkIndex) => {
|
|
150
158
|
const instance = typeof inst === 'function' ? await inst() : inst;
|
|
151
159
|
const page = await instance.createPage();
|
|
160
|
+
page.setDefaultNavigationTimeout(60000); // Increase timeout to 60 seconds
|
|
161
|
+
|
|
152
162
|
await page.evaluate(async (json) => {
|
|
153
163
|
store.loadJSON(json);
|
|
154
164
|
await store.waitLoading();
|
|
@@ -217,7 +227,7 @@ module.exports.jsonToVideo = async function jsonToVideo(
|
|
|
217
227
|
finishedFramesNumber += 1;
|
|
218
228
|
if (attrs.onProgress) {
|
|
219
229
|
const frameTime = Date.now() - startTime;
|
|
220
|
-
const progress = finishedFramesNumber / framesNumber;
|
|
230
|
+
const progress = (finishedFramesNumber / framesNumber) * 0.95;
|
|
221
231
|
attrs.onProgress(progress, frameTime);
|
|
222
232
|
}
|
|
223
233
|
}
|
|
@@ -251,6 +261,7 @@ module.exports.jsonToVideo = async function jsonToVideo(
|
|
|
251
261
|
inputEndTime: elEndTime,
|
|
252
262
|
outputStartTime: pageStartTime,
|
|
253
263
|
outputEndTime: pageStartTime + pageDuration,
|
|
264
|
+
volume: el.volume,
|
|
254
265
|
});
|
|
255
266
|
}
|
|
256
267
|
}
|
|
@@ -275,12 +286,16 @@ module.exports.jsonToVideo = async function jsonToVideo(
|
|
|
275
286
|
1000
|
|
276
287
|
).toFixed(3);
|
|
277
288
|
const outputOffsetSec = (input.outputStartTime / 1000).toFixed(3);
|
|
289
|
+
const volume = input.volume !== undefined ? input.volume : 1;
|
|
278
290
|
|
|
279
291
|
// Apply `-itsoffset` before each input file to shift its audio stream
|
|
280
292
|
ffmpegCmd
|
|
281
293
|
.inputOptions([`-itsoffset ${outputOffsetSec}`]) // Shift the input time
|
|
282
294
|
.input(input.mp4File) // Add the actual input file
|
|
283
295
|
.inputOptions([`-ss ${inputStartSec}`, `-t ${inputDurationSec}`]); // Specify the timing to cut the audio
|
|
296
|
+
|
|
297
|
+
// Apply volume filter to respect the input volume
|
|
298
|
+
ffmpegCmd.audioFilters(`volume=${volume}`);
|
|
284
299
|
});
|
|
285
300
|
|
|
286
301
|
// Map the video stream from the image sequence
|