@remotion/renderer 4.0.0-spawn.10 → 4.0.0-spawn.15

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.
@@ -1,6 +1,7 @@
1
1
  import { openBrowser } from './open-browser';
2
2
  declare type Await<T> = T extends PromiseLike<infer U> ? U : T;
3
- export declare const cycleBrowserTabs: (puppeteerInstance: Await<ReturnType<typeof openBrowser>>, concurrency: number) => {
3
+ declare type Browser = ReturnType<typeof openBrowser>;
4
+ export declare const cycleBrowserTabs: (puppeteerInstance: Browser | Await<Browser>, concurrency: number) => {
4
5
  stopCycling: () => void;
5
6
  };
6
7
  export {};
@@ -11,8 +11,8 @@ const cycleBrowserTabs = (puppeteerInstance, concurrency) => {
11
11
  let i = 0;
12
12
  const set = () => {
13
13
  interval = setTimeout(() => {
14
- puppeteerInstance
15
- .pages()
14
+ Promise.resolve(puppeteerInstance)
15
+ .then((instance) => instance.pages())
16
16
  .then((pages) => {
17
17
  var _a, _b;
18
18
  const currentPage = pages[i % pages.length];
@@ -36,5 +36,8 @@ declare type RenderFramesOptions = {
36
36
  ffmpegExecutable?: FfmpegExecutable;
37
37
  port?: number | null;
38
38
  } & ConfigOrComposition & ServeUrlOrWebpackBundle;
39
- export declare const renderFrames: (options: RenderFramesOptions) => Promise<RenderFramesOutput>;
39
+ declare type ReturnTypeWithCancel = Promise<RenderFramesOutput> & {
40
+ cancel: () => void;
41
+ };
42
+ export declare const renderFrames: (options: RenderFramesOptions) => ReturnTypeWithCancel;
40
43
  export {};
@@ -33,7 +33,12 @@ const getComposition = (others) => {
33
33
  }
34
34
  return undefined;
35
35
  };
36
- const innerRenderFrames = async ({ onFrameUpdate, outputDir, onStart, inputProps, quality, imageFormat = image_format_1.DEFAULT_IMAGE_FORMAT, frameRange, puppeteerInstance, onError, envVariables, onBrowserLog, onFrameBuffer, onDownload, pagesArray, serveUrl, composition, timeoutInMilliseconds, scale, actualParallelism, downloadDir, proxyPort, }) => {
36
+ const getPool = async (pages) => {
37
+ const puppeteerPages = await Promise.all(pages);
38
+ const pool = new pool_1.Pool(puppeteerPages);
39
+ return pool;
40
+ };
41
+ const innerRenderFrames = ({ onFrameUpdate, outputDir, onStart, inputProps, quality, imageFormat = image_format_1.DEFAULT_IMAGE_FORMAT, frameRange, puppeteerInstance, onError, envVariables, onBrowserLog, onFrameBuffer, onDownload, pagesArray, serveUrl, composition, timeoutInMilliseconds, scale, actualParallelism, downloadDir, proxyPort, }) => {
37
42
  if (!puppeteerInstance) {
38
43
  throw new Error('weird');
39
44
  }
@@ -93,23 +98,27 @@ const innerRenderFrames = async ({ onFrameUpdate, outputDir, onStart, inputProps
93
98
  page.off('console', logCallback);
94
99
  return page;
95
100
  });
96
- const puppeteerPages = await Promise.all(pages);
97
- const pool = new pool_1.Pool(puppeteerPages);
98
101
  const [firstFrameIndex, lastFrameIndex] = realFrameRange;
99
102
  // Substract one because 100 frames will be 00-99
100
103
  // --> 2 digits
101
104
  const filePadLength = String(lastFrameIndex).length;
102
105
  let framesRendered = 0;
106
+ const poolPromise = getPool(pages);
103
107
  onStart({
104
108
  frameCount,
105
109
  });
106
110
  const assets = new Array(frameCount).fill(undefined);
107
- await Promise.all(new Array(frameCount)
111
+ let stopped = false;
112
+ const progress = Promise.all(new Array(frameCount)
108
113
  .fill(Boolean)
109
114
  .map((_x, i) => i)
110
115
  .map(async (index) => {
111
116
  const frame = realFrameRange[0] + index;
117
+ const pool = await poolPromise;
112
118
  const freePage = await pool.acquire();
119
+ if (stopped) {
120
+ throw new Error('Render was stopped');
121
+ }
113
122
  const paddedIndex = String(frame).padStart(filePadLength, '0');
114
123
  const errorCallbackOnFrame = (err) => {
115
124
  onError(err);
@@ -176,18 +185,29 @@ const innerRenderFrames = async ({ onFrameUpdate, outputDir, onStart, inputProps
176
185
  freePage.off('error', errorCallbackOnFrame);
177
186
  return compressedAssets;
178
187
  }));
179
- const returnValue = {
180
- assetsInfo: {
181
- assets,
182
- downloadDir,
183
- firstFrameIndex,
184
- imageSequenceName: `element-%0${filePadLength}d.${imageFormat}`,
188
+ const prom = Object.assign(new Promise((res, rej) => {
189
+ progress
190
+ .then(() => {
191
+ const returnValue = {
192
+ assetsInfo: {
193
+ assets,
194
+ downloadDir,
195
+ firstFrameIndex,
196
+ imageSequenceName: `element-%0${filePadLength}d.${imageFormat}`,
197
+ },
198
+ frameCount,
199
+ };
200
+ res(returnValue);
201
+ })
202
+ .catch((err) => rej(err));
203
+ }), {
204
+ cancel: () => {
205
+ stopped = true;
185
206
  },
186
- frameCount,
187
- };
188
- return returnValue;
207
+ });
208
+ return prom;
189
209
  };
190
- const renderFrames = async (options) => {
210
+ const renderFrames = (options) => {
191
211
  var _a, _b, _c, _d;
192
212
  const composition = getComposition(options);
193
213
  if (!composition) {
@@ -203,34 +223,38 @@ const renderFrames = async (options) => {
203
223
  const selectedServeUrl = (0, legacy_webpack_config_1.getServeUrlWithFallback)(options);
204
224
  remotion_1.Internals.validateQuality(options.quality);
205
225
  (0, validate_scale_1.validateScale)(options.scale);
206
- const browserInstance = (_a = options.puppeteerInstance) !== null && _a !== void 0 ? _a : (await (0, open_browser_1.openBrowser)(remotion_1.Internals.DEFAULT_BROWSER, {
226
+ const browserInstance = (_a = options.puppeteerInstance) !== null && _a !== void 0 ? _a : (0, open_browser_1.openBrowser)(remotion_1.Internals.DEFAULT_BROWSER, {
207
227
  shouldDumpIo: options.dumpBrowserLogs,
208
228
  browserExecutable: options.browserExecutable,
209
229
  chromiumOptions: options.chromiumOptions,
210
230
  forceDeviceScaleFactor: (_b = options.scale) !== null && _b !== void 0 ? _b : 1,
211
- }));
231
+ });
212
232
  const downloadDir = (0, make_assets_download_dir_1.makeAssetsDownloadTmpDir)();
213
233
  const onDownload = (_c = options.onDownload) !== null && _c !== void 0 ? _c : (() => () => undefined);
214
234
  const actualParallelism = (0, get_concurrency_1.getActualConcurrency)((_d = options.parallelism) !== null && _d !== void 0 ? _d : null);
215
235
  const { stopCycling } = (0, cycle_browser_tabs_1.cycleBrowserTabs)(browserInstance, actualParallelism);
216
236
  const openedPages = [];
217
- return new Promise((resolve, reject) => {
237
+ let cancel = () => undefined;
238
+ const prom = new Promise((resolve, reject) => {
218
239
  var _a, _b;
219
240
  let cleanup = null;
220
241
  const onError = (err) => reject(err);
221
- (0, prepare_server_1.prepareServer)({
222
- webpackConfigOrServeUrl: selectedServeUrl,
223
- downloadDir,
224
- onDownload,
225
- onError,
226
- ffmpegExecutable: (_a = options.ffmpegExecutable) !== null && _a !== void 0 ? _a : null,
227
- port: (_b = options.port) !== null && _b !== void 0 ? _b : null,
228
- })
229
- .then(({ serveUrl, closeServer, offthreadPort }) => {
242
+ Promise.all([
243
+ (0, prepare_server_1.prepareServer)({
244
+ webpackConfigOrServeUrl: selectedServeUrl,
245
+ downloadDir,
246
+ onDownload,
247
+ onError,
248
+ ffmpegExecutable: (_a = options.ffmpegExecutable) !== null && _a !== void 0 ? _a : null,
249
+ port: (_b = options.port) !== null && _b !== void 0 ? _b : null,
250
+ }),
251
+ browserInstance,
252
+ ])
253
+ .then(([{ serveUrl, closeServer, offthreadPort }, puppeteerInstance]) => {
230
254
  cleanup = closeServer;
231
- return innerRenderFrames({
255
+ const renderFramesProm = innerRenderFrames({
232
256
  ...options,
233
- puppeteerInstance: browserInstance,
257
+ puppeteerInstance,
234
258
  onError,
235
259
  pagesArray: openedPages,
236
260
  serveUrl,
@@ -240,6 +264,10 @@ const renderFrames = async (options) => {
240
264
  downloadDir,
241
265
  proxyPort: offthreadPort,
242
266
  });
267
+ cancel = () => {
268
+ renderFramesProm.cancel();
269
+ };
270
+ return renderFramesProm;
243
271
  })
244
272
  .then((res) => resolve(res))
245
273
  .catch((err) => reject(err))
@@ -253,7 +281,11 @@ const renderFrames = async (options) => {
253
281
  });
254
282
  }
255
283
  else {
256
- browserInstance.close().catch((err) => {
284
+ Promise.resolve(browserInstance)
285
+ .then((puppeteerInstance) => {
286
+ return puppeteerInstance.close();
287
+ })
288
+ .catch((err) => {
257
289
  console.log('Unable to close browser', err);
258
290
  });
259
291
  }
@@ -261,5 +293,11 @@ const renderFrames = async (options) => {
261
293
  cleanup === null || cleanup === void 0 ? void 0 : cleanup();
262
294
  });
263
295
  });
296
+ const returnType = Object.assign(prom, {
297
+ cancel: () => {
298
+ cancel();
299
+ },
300
+ });
301
+ return returnType;
264
302
  };
265
303
  exports.renderFrames = renderFrames;
@@ -40,4 +40,8 @@ export declare type RenderMediaOptions = {
40
40
  port?: number | null;
41
41
  browserExecutable?: BrowserExecutable;
42
42
  } & ServeUrlOrWebpackBundle;
43
- export declare const renderMedia: ({ parallelism, proResProfile, crf, composition, imageFormat, ffmpegExecutable, inputProps, pixelFormat, codec, envVariables, quality, frameRange, puppeteerInstance, outputLocation, onProgress, overwrite, onDownload, dumpBrowserLogs, onBrowserLog, onStart, timeoutInMilliseconds, chromiumOptions, scale, browserExecutable, port, ...options }: RenderMediaOptions) => Promise<void>;
43
+ declare type RenderMediaReturnType = Promise<void> & {
44
+ cancel: () => void;
45
+ };
46
+ export declare const renderMedia: (options: RenderMediaOptions) => RenderMediaReturnType;
47
+ export {};
@@ -23,7 +23,22 @@ const tmp_dir_1 = require("./tmp-dir");
23
23
  const validate_even_dimensions_with_codec_1 = require("./validate-even-dimensions-with-codec");
24
24
  const validate_output_filename_1 = require("./validate-output-filename");
25
25
  const validate_scale_1 = require("./validate-scale");
26
- const renderMedia = async ({ parallelism, proResProfile, crf, composition, imageFormat, ffmpegExecutable, inputProps, pixelFormat, codec, envVariables, quality, frameRange, puppeteerInstance, outputLocation, onProgress, overwrite, onDownload, dumpBrowserLogs, onBrowserLog, onStart, timeoutInMilliseconds, chromiumOptions, scale, browserExecutable, port, ...options }) => {
26
+ const renderMedia = (options) => {
27
+ let resolve = () => undefined;
28
+ let reject = () => undefined;
29
+ const rejectIfCancel = new Promise((res, rej) => {
30
+ resolve = res;
31
+ reject = rej;
32
+ });
33
+ const prom = innerRenderMedia({ ...options, rejectIfCancel }).then(() => {
34
+ resolve();
35
+ });
36
+ return Object.assign(prom, {
37
+ cancel: () => reject(new Error('Render got cancelled')),
38
+ });
39
+ };
40
+ exports.renderMedia = renderMedia;
41
+ const innerRenderMedia = async ({ parallelism, proResProfile, crf, composition, imageFormat, ffmpegExecutable, inputProps, pixelFormat, codec, envVariables, quality, frameRange, puppeteerInstance, outputLocation, onProgress, overwrite, onDownload, dumpBrowserLogs, onBrowserLog, onStart, timeoutInMilliseconds, chromiumOptions, scale, browserExecutable, port, rejectIfCancel, ...options }) => {
27
42
  var _a;
28
43
  remotion_1.Internals.validateQuality(quality);
29
44
  if (typeof crf !== 'undefined' && crf !== null) {
@@ -39,6 +54,16 @@ const renderMedia = async ({ parallelism, proResProfile, crf, composition, image
39
54
  let renderedFrames = 0;
40
55
  let renderedDoneIn = null;
41
56
  let encodedDoneIn = null;
57
+ let cancelled = false;
58
+ let cancelRenderFrames = () => undefined;
59
+ rejectIfCancel
60
+ .then(() => undefined)
61
+ .catch((err) => {
62
+ cancelled = true;
63
+ preStitcher === null || preStitcher === void 0 ? void 0 : preStitcher.task.kill();
64
+ cancelRenderFrames();
65
+ throw err;
66
+ });
42
67
  const renderStart = Date.now();
43
68
  const tmpdir = (0, tmp_dir_1.tmpDir)('pre-encode');
44
69
  const parallelEncoding = (0, can_use_parallel_encoding_1.canUseParallelEncoding)(codec);
@@ -87,7 +112,7 @@ const renderMedia = async ({ parallelism, proResProfile, crf, composition, image
87
112
  }
88
113
  const realFrameRange = (0, get_frame_to_render_1.getRealFrameRange)(composition.durationInFrames, frameRange !== null && frameRange !== void 0 ? frameRange : null);
89
114
  const { waitForRightTimeOfFrameToBeInserted, setFrameToStitch, waitForFinish, } = (0, ensure_frames_in_order_1.ensureFramesInOrder)(realFrameRange);
90
- const { assetsInfo } = await (0, render_frames_1.renderFrames)({
115
+ const renderFramesProc = (0, render_frames_1.renderFrames)({
91
116
  config: composition,
92
117
  onFrameUpdate: (frame) => {
93
118
  renderedFrames = frame;
@@ -110,6 +135,9 @@ const renderMedia = async ({ parallelism, proResProfile, crf, composition, image
110
135
  ? async (buffer, frame) => {
111
136
  var _a;
112
137
  await waitForRightTimeOfFrameToBeInserted(frame);
138
+ if (cancelled) {
139
+ return;
140
+ }
113
141
  (_a = stitcherFfmpeg === null || stitcherFfmpeg === void 0 ? void 0 : stitcherFfmpeg.stdin) === null || _a === void 0 ? void 0 : _a.write(buffer);
114
142
  setFrameToStitch(frame + 1);
115
143
  }
@@ -125,6 +153,10 @@ const renderMedia = async ({ parallelism, proResProfile, crf, composition, image
125
153
  browserExecutable,
126
154
  port,
127
155
  });
156
+ cancelRenderFrames = () => {
157
+ renderFramesProc.cancel();
158
+ };
159
+ const { assetsInfo } = await renderFramesProc;
128
160
  if (stitcherFfmpeg) {
129
161
  await waitForFinish();
130
162
  (_a = stitcherFfmpeg === null || stitcherFfmpeg === void 0 ? void 0 : stitcherFfmpeg.stdin) === null || _a === void 0 ? void 0 : _a.end();
@@ -173,6 +205,8 @@ const renderMedia = async ({ parallelism, proResProfile, crf, composition, image
173
205
  * When an error is thrown in renderFrames(...) (e.g., when delayRender() is used incorrectly), fs.unlinkSync(...) throws an error that the file is locked because ffmpeg is still running, and renderMedia returns it.
174
206
  * Therefore we first kill the FFMPEG process before deleting the file
175
207
  */
208
+ cancelled = true;
209
+ cancelRenderFrames();
176
210
  if (stitcherFfmpeg !== undefined && stitcherFfmpeg.exitCode === null) {
177
211
  const promise = new Promise((resolve) => {
178
212
  setTimeout(() => {
@@ -194,4 +228,3 @@ const renderMedia = async ({ parallelism, proResProfile, crf, composition, image
194
228
  }
195
229
  }
196
230
  };
197
- exports.renderMedia = renderMedia;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remotion/renderer",
3
- "version": "4.0.0-spawn.10+911177607",
3
+ "version": "4.0.0-spawn.15+87508e2d3",
4
4
  "description": "Renderer for Remotion",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -22,7 +22,7 @@
22
22
  "dependencies": {
23
23
  "execa": "5.1.1",
24
24
  "puppeteer-core": "13.5.1",
25
- "remotion": "4.0.0-spawn.10+911177607",
25
+ "remotion": "4.0.0-spawn.15+87508e2d3",
26
26
  "serve-handler": "6.1.3",
27
27
  "source-map": "^0.8.0-beta.0"
28
28
  },
@@ -59,5 +59,5 @@
59
59
  "publishConfig": {
60
60
  "access": "public"
61
61
  },
62
- "gitHead": "911177607ac127d9f4d1c014ad8ae32fd14947dd"
62
+ "gitHead": "87508e2d3155ca3f7804ede63ea9b82bd2b3749f"
63
63
  }