@nexrender/core 1.40.1 → 1.41.1

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 (2) hide show
  1. package/package.json +2 -2
  2. package/src/tasks/render.js +41 -13
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nexrender/core",
3
- "version": "1.40.1",
3
+ "version": "1.41.1",
4
4
  "main": "src/index.js",
5
5
  "author": "Inlife",
6
6
  "scripts": {
@@ -30,5 +30,5 @@
30
30
  "publishConfig": {
31
31
  "access": "public"
32
32
  },
33
- "gitHead": "6eac7cdfed90cc8705320f29b4efe239d559707e"
33
+ "gitHead": "f7cbfd9d2a20c145547c30e16176e2fcb97a8813"
34
34
  }
@@ -14,6 +14,7 @@ const option = (params, name, ...values) => {
14
14
  values.every(value => value !== undefined) ? params.push(name, ...values) : undefined
15
15
  }
16
16
  }
17
+
17
18
  const seconds = (string) => string.split(':')
18
19
  .map((e, i) => (i < 3) ? +e * Math.pow(60, 2 - i) : +e * 10e-6)
19
20
  .reduce((acc, val) => acc + val);
@@ -117,7 +118,7 @@ module.exports = (job, settings) => {
117
118
 
118
119
  // There will be multiple error messages parsed when nexrender throws an error,
119
120
  // but we want only the first
120
- if(matchError !== null && !errorSent){
121
+ if (matchError !== null && !errorSent) {
121
122
  settings.logger.log(`[${job.uid}] rendering reached an error: ${matchError[1]}`);
122
123
  if (job.hasOwnProperty('onRenderError') && typeof job['onRenderError'] == 'function') {
123
124
  job.onRenderError(job, matchError[1]);
@@ -132,6 +133,8 @@ module.exports = (job, settings) => {
132
133
  return new Promise((resolve, reject) => {
133
134
  renderStopwatch = Date.now();
134
135
 
136
+ let timeoutID = 0;
137
+
135
138
  if (settings.debug) {
136
139
  settings.logger.log(`[${job.uid}] spawning aerender process: ${settings.binary} ${params.join(' ')}`);
137
140
  }
@@ -145,7 +148,10 @@ module.exports = (job, settings) => {
145
148
  // env: { PATH: path.dirname(settings.binary) },
146
149
  });
147
150
 
148
- instance.on('error', err => reject(new Error(`Error starting aerender process: ${err}`)));
151
+ instance.on('error', err => {
152
+ clearTimeout(timeoutID);
153
+ return reject(new Error(`Error starting aerender process: ${err}`));
154
+ });
149
155
 
150
156
  instance.stdout.on('data', (data) => {
151
157
  output.push(parse(data.toString('utf8')));
@@ -157,6 +163,17 @@ module.exports = (job, settings) => {
157
163
  (settings.verbose && settings.logger.log(data.toString('utf8')));
158
164
  });
159
165
 
166
+ if (settings.maxRenderTimeout && settings.maxRenderTimeout > 0) {
167
+ const timeout = 1000 * settings.maxRenderTimeout;
168
+ timeoutID = setTimeout(
169
+ () => {
170
+ reject(new Error(`Maximum rendering time exceeded`));
171
+ instance.kill('SIGINT');
172
+ },
173
+ timeout
174
+ );
175
+ }
176
+
160
177
  /* on finish (code 0 - success, other - error) */
161
178
  instance.on('close', (code) => {
162
179
 
@@ -169,6 +186,7 @@ module.exports = (job, settings) => {
169
186
  settings.logger.log(fs.readFileSync(logPath, 'utf8'))
170
187
  }
171
188
 
189
+ clearTimeout(timeoutID);
172
190
  return reject(new Error(outputStr || 'aerender.exe failed to render the output into the file due to an unknown reason'));
173
191
  }
174
192
 
@@ -179,6 +197,7 @@ module.exports = (job, settings) => {
179
197
 
180
198
  /* resolve job without checking if file exists, or its size for image sequences */
181
199
  if (settings.skipRender || job.template.imageSequence || ['jpeg', 'jpg', 'png'].indexOf(outputFile) !== -1) {
200
+ clearTimeout(timeoutID);
182
201
  return resolve(job)
183
202
  }
184
203
 
@@ -186,25 +205,33 @@ module.exports = (job, settings) => {
186
205
  // the outputfile appears to be forced as .mov.
187
206
  // We need to maintain this here while we have 2022 and 2020
188
207
  // workers simultaneously
189
- const movOutputFile = outputFile.replace(/\.avi$/g, '.mov')
190
- const existsMovOutputFile = fs.existsSync(movOutputFile)
191
- if (existsMovOutputFile) {
192
- job.output = movOutputFile
193
- } else {
194
- // AE 2023 use mp4 output files
195
- const mp4OutputFile = outputFile.replace(/\.avi$/g, '.mp4')
196
- const existsMp4OutputFile = fs.existsSync(mp4OutputFile)
197
- if (existsMp4OutputFile) {
198
- job.output = mp4OutputFile
199
- }
208
+
209
+ const defaultOutputs = [
210
+ job.output,
211
+ job.output.replace(/\.avi$/g, '.mov'),
212
+ job.output.replace(/\.avi$/g, '.mp4'),
213
+ job.output.replace(/\.mov$/g, '.avi'),
214
+ job.output.replace(/\.mov$/g, '.mp4'),
215
+ ]
216
+
217
+ while (!fs.existsSync(defaultOutputs[0]) && defaultOutputs.length > 0) {
218
+ defaultOutputs.shift();
200
219
  }
201
220
 
221
+ if (defaultOutputs.length === 0) {
222
+ clearTimeout(timeoutID);
223
+ return reject(new Error(`Output file not found: ${job.output}`));
224
+ }
225
+
226
+ job.output = defaultOutputs[0];
227
+
202
228
  if (!fs.existsSync(job.output)) {
203
229
  if (fs.existsSync(logPath)) {
204
230
  settings.logger.log(`[${job.uid}] dumping aerender log:`)
205
231
  settings.logger.log(fs.readFileSync(logPath, 'utf8'))
206
232
  }
207
233
 
234
+ clearTimeout(timeoutID);
208
235
  return reject(new Error(`Couldn't find a result file: ${outputFile}`))
209
236
  }
210
237
 
@@ -215,6 +242,7 @@ module.exports = (job, settings) => {
215
242
  settings.logger.log(`[${job.uid}] Warning: output file size is less than 1000 bytes (${stats.size} bytes), be advised that file is corrupted, or rendering is still being finished`)
216
243
  }
217
244
 
245
+ clearTimeout(timeoutID);
218
246
  resolve(job)
219
247
  });
220
248