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/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-DsVyOnN0.js"></script>
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
- headless: 'new',
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
- ignoreHTTPSErrors: true,
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.35",
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.2",
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
- console.log('Converting video to webm: ' + filename);
67
- const webmDestination = mp4Destination.replace('.mp4', '.webm');
68
- await convertToWebM(mp4Destination, webmDestination);
69
- const dataURL = await fileToDataUrl(webmDestination);
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
- el.src = dataURL;
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 || 15;
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