@remotion/renderer 3.2.42 → 3.2.43-retry.19

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.
@@ -25,7 +25,8 @@ interface WaitForTargetOptions {
25
25
  export declare const enum BrowserEmittedEvents {
26
26
  TargetChanged = "targetchanged",
27
27
  TargetCreated = "targetcreated",
28
- Closed = "closed"
28
+ Closed = "closed",
29
+ ClosedSilent = "closed-silent"
29
30
  }
30
31
  export declare class Browser extends EventEmitter {
31
32
  #private;
@@ -35,6 +36,7 @@ export declare class Browser extends EventEmitter {
35
36
  defaultViewport: Viewport;
36
37
  closeCallback?: BrowserCloseCallback;
37
38
  }): Promise<Browser>;
39
+ connection: Connection;
38
40
  get _targets(): Map<string, Target>;
39
41
  constructor(connection: Connection, contextIds: string[], defaultViewport: Viewport, closeCallback?: BrowserCloseCallback);
40
42
  browserContexts(): BrowserContext[];
@@ -43,7 +45,7 @@ export declare class Browser extends EventEmitter {
43
45
  targets(): Target[];
44
46
  waitForTarget(predicate: (x: Target) => boolean | Promise<boolean>, options?: WaitForTargetOptions): Promise<Target>;
45
47
  pages(): Promise<Page[]>;
46
- close(): Promise<void>;
48
+ close(silent: boolean): Promise<void>;
47
49
  disconnect(): void;
48
50
  }
49
51
  export declare class BrowserContext extends EventEmitter {
@@ -25,7 +25,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
25
25
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
26
26
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
27
27
  };
28
- var _Browser_instances, _Browser_defaultViewport, _Browser_connection, _Browser_closeCallback, _Browser_defaultContext, _Browser_contexts, _Browser_targets, _Browser_targetCreated, _Browser_targetDestroyed, _Browser_targetInfoChanged, _BrowserContext_browser, _BrowserContext_id;
28
+ var _Browser_instances, _Browser_defaultViewport, _Browser_closeCallback, _Browser_defaultContext, _Browser_contexts, _Browser_targets, _Browser_targetCreated, _Browser_targetDestroyed, _Browser_targetInfoChanged, _BrowserContext_browser, _BrowserContext_id;
29
29
  Object.defineProperty(exports, "__esModule", { value: true });
30
30
  exports.BrowserContext = exports.Browser = void 0;
31
31
  const assert_1 = require("./assert");
@@ -38,13 +38,12 @@ class Browser extends EventEmitter_1.EventEmitter {
38
38
  super();
39
39
  _Browser_instances.add(this);
40
40
  _Browser_defaultViewport.set(this, void 0);
41
- _Browser_connection.set(this, void 0);
42
41
  _Browser_closeCallback.set(this, void 0);
43
42
  _Browser_defaultContext.set(this, void 0);
44
43
  _Browser_contexts.set(this, void 0);
45
44
  _Browser_targets.set(this, void 0);
46
45
  __classPrivateFieldSet(this, _Browser_defaultViewport, defaultViewport, "f");
47
- __classPrivateFieldSet(this, _Browser_connection, connection, "f");
46
+ this.connection = connection;
48
47
  __classPrivateFieldSet(this, _Browser_closeCallback, closeCallback ||
49
48
  function () {
50
49
  return undefined;
@@ -55,9 +54,9 @@ class Browser extends EventEmitter_1.EventEmitter {
55
54
  __classPrivateFieldGet(this, _Browser_contexts, "f").set(contextId, new BrowserContext(this, contextId));
56
55
  }
57
56
  __classPrivateFieldSet(this, _Browser_targets, new Map(), "f");
58
- __classPrivateFieldGet(this, _Browser_connection, "f").on('Target.targetCreated', __classPrivateFieldGet(this, _Browser_instances, "m", _Browser_targetCreated).bind(this));
59
- __classPrivateFieldGet(this, _Browser_connection, "f").on('Target.targetDestroyed', __classPrivateFieldGet(this, _Browser_instances, "m", _Browser_targetDestroyed).bind(this));
60
- __classPrivateFieldGet(this, _Browser_connection, "f").on('Target.targetInfoChanged', __classPrivateFieldGet(this, _Browser_instances, "m", _Browser_targetInfoChanged).bind(this));
57
+ this.connection.on('Target.targetCreated', __classPrivateFieldGet(this, _Browser_instances, "m", _Browser_targetCreated).bind(this));
58
+ this.connection.on('Target.targetDestroyed', __classPrivateFieldGet(this, _Browser_instances, "m", _Browser_targetDestroyed).bind(this));
59
+ this.connection.on('Target.targetInfoChanged', __classPrivateFieldGet(this, _Browser_instances, "m", _Browser_targetInfoChanged).bind(this));
61
60
  }
62
61
  static async _create({ connection, contextIds, defaultViewport, closeCallback, }) {
63
62
  const browser = new Browser(connection, contextIds, defaultViewport, closeCallback);
@@ -74,7 +73,7 @@ class Browser extends EventEmitter_1.EventEmitter {
74
73
  return __classPrivateFieldGet(this, _Browser_defaultContext, "f").newPage();
75
74
  }
76
75
  async _createPageInContext(contextId) {
77
- const { targetId } = await __classPrivateFieldGet(this, _Browser_connection, "f").send('Target.createTarget', {
76
+ const { targetId } = await this.connection.send('Target.createTarget', {
78
77
  url: 'about:blank',
79
78
  browserContextId: contextId || undefined,
80
79
  });
@@ -133,17 +132,17 @@ class Browser extends EventEmitter_1.EventEmitter {
133
132
  return acc.concat(x);
134
133
  }, []);
135
134
  }
136
- async close() {
135
+ async close(silent) {
137
136
  await __classPrivateFieldGet(this, _Browser_closeCallback, "f").call(null);
138
137
  this.disconnect();
139
- this.emit("closed" /* BrowserEmittedEvents.Closed */);
138
+ this.emit(silent ? "closed-silent" /* BrowserEmittedEvents.ClosedSilent */ : "closed" /* BrowserEmittedEvents.Closed */);
140
139
  }
141
140
  disconnect() {
142
- __classPrivateFieldGet(this, _Browser_connection, "f").dispose();
141
+ this.connection.dispose();
143
142
  }
144
143
  }
145
144
  exports.Browser = Browser;
146
- _Browser_defaultViewport = new WeakMap(), _Browser_connection = new WeakMap(), _Browser_closeCallback = new WeakMap(), _Browser_defaultContext = new WeakMap(), _Browser_contexts = new WeakMap(), _Browser_targets = new WeakMap(), _Browser_instances = new WeakSet(), _Browser_targetCreated = async function _Browser_targetCreated(event) {
145
+ _Browser_defaultViewport = new WeakMap(), _Browser_closeCallback = new WeakMap(), _Browser_defaultContext = new WeakMap(), _Browser_contexts = new WeakMap(), _Browser_targets = new WeakMap(), _Browser_instances = new WeakSet(), _Browser_targetCreated = async function _Browser_targetCreated(event) {
147
146
  var _a;
148
147
  const { targetInfo } = event;
149
148
  const { browserContextId } = targetInfo;
@@ -154,7 +153,7 @@ _Browser_defaultViewport = new WeakMap(), _Browser_connection = new WeakMap(), _
154
153
  throw new Error('Missing browser context');
155
154
  }
156
155
  const target = new Target_1.Target(targetInfo, context, () => {
157
- return __classPrivateFieldGet(this, _Browser_connection, "f").createSession(targetInfo);
156
+ return this.connection.createSession(targetInfo);
158
157
  }, (_a = __classPrivateFieldGet(this, _Browser_defaultViewport, "f")) !== null && _a !== void 0 ? _a : null);
159
158
  (0, assert_1.assert)(!__classPrivateFieldGet(this, _Browser_targets, "f").has(event.targetInfo.targetId), 'Target should not exist before targetCreated');
160
159
  __classPrivateFieldGet(this, _Browser_targets, "f").set(event.targetInfo.targetId, target);
@@ -215,11 +215,11 @@ class CDPSession extends EventEmitter_1.EventEmitter {
215
215
  }
216
216
  }
217
217
  _onClosed() {
218
+ __classPrivateFieldSet(this, _CDPSession_connection, undefined, "f");
218
219
  for (const callback of __classPrivateFieldGet(this, _CDPSession_callbacks, "f").values()) {
219
220
  callback.reject(rewriteError(callback.error, `Protocol error (${callback.method}): Target closed. https://www.remotion.dev/docs/target-closed`));
220
221
  }
221
222
  __classPrivateFieldGet(this, _CDPSession_callbacks, "f").clear();
222
- __classPrivateFieldSet(this, _CDPSession_connection, undefined, "f");
223
223
  this.emit(exports.CDPSessionEmittedEvents.Disconnected);
224
224
  }
225
225
  id() {
@@ -46,7 +46,8 @@ declare class WaitTask {
46
46
  promise: Promise<JSHandle>;
47
47
  constructor(options: WaitTaskOptions);
48
48
  onBrowserClose: () => void;
49
- terminate(error: Error): void;
49
+ onBrowserCloseSilent: () => void;
50
+ terminate(error: Error | null): void;
50
51
  rerun(): Promise<void>;
51
52
  }
52
53
  export {};
@@ -131,6 +131,9 @@ class WaitTask {
131
131
  this.onBrowserClose = () => {
132
132
  return this.terminate(new Error('Browser was closed'));
133
133
  };
134
+ this.onBrowserCloseSilent = () => {
135
+ return this.terminate(null);
136
+ };
134
137
  function getPredicateBody(predicateBody) {
135
138
  if ((0, util_1.isString)(predicateBody)) {
136
139
  return `return (${predicateBody});`;
@@ -157,11 +160,14 @@ class WaitTask {
157
160
  }
158
161
  __classPrivateFieldSet(this, _WaitTask_browser, options.browser, "f");
159
162
  __classPrivateFieldGet(this, _WaitTask_browser, "f").on("closed" /* BrowserEmittedEvents.Closed */, this.onBrowserClose);
163
+ __classPrivateFieldGet(this, _WaitTask_browser, "f").on("closed-silent" /* BrowserEmittedEvents.ClosedSilent */, this.onBrowserCloseSilent);
160
164
  this.rerun();
161
165
  }
162
166
  terminate(error) {
163
167
  __classPrivateFieldSet(this, _WaitTask_terminated, true, "f");
164
- __classPrivateFieldGet(this, _WaitTask_reject, "f").call(this, error);
168
+ if (error) {
169
+ __classPrivateFieldGet(this, _WaitTask_reject, "f").call(this, error);
170
+ }
165
171
  __classPrivateFieldGet(this, _WaitTask_instances, "m", _WaitTask_cleanup).call(this);
166
172
  }
167
173
  async rerun() {
@@ -242,6 +248,7 @@ _WaitTask_domWorld = new WeakMap(), _WaitTask_timeout = new WeakMap(), _WaitTask
242
248
  clearTimeout(__classPrivateFieldGet(this, _WaitTask_timeoutTimer, "f"));
243
249
  }
244
250
  __classPrivateFieldGet(this, _WaitTask_browser, "f").off("closed" /* BrowserEmittedEvents.Closed */, this.onBrowserClose);
251
+ __classPrivateFieldGet(this, _WaitTask_browser, "f").off("closed-silent" /* BrowserEmittedEvents.ClosedSilent */, this.onBrowserCloseSilent);
245
252
  __classPrivateFieldGet(this, _WaitTask_domWorld, "f")._waitTasks.delete(this);
246
253
  };
247
254
  function waitForPredicatePageFunction(predicateBody, timeout, ...args) {
@@ -112,7 +112,7 @@ class ChromeLauncher {
112
112
  }, { timeout });
113
113
  }
114
114
  catch (error) {
115
- await browser.close();
115
+ await browser.close(false);
116
116
  throw error;
117
117
  }
118
118
  return browser;
@@ -65,7 +65,7 @@ class NodeWebSocketTransport {
65
65
  const ws = new ws_types_1.ws(url, [], {
66
66
  followRedirects: true,
67
67
  perMessageDeflate: false,
68
- maxPayload: 256 * 1024 * 1024,
68
+ maxPayload: 1024 * 1024 * 1024,
69
69
  headers: {
70
70
  'User-Agent': `Remotion CLI`,
71
71
  },
@@ -1,7 +1,4 @@
1
- import type { openBrowser } from './open-browser';
2
- declare type Await<T> = T extends PromiseLike<infer U> ? U : T;
3
- declare type Browser = Await<ReturnType<typeof openBrowser>>;
4
- export declare const cycleBrowserTabs: (puppeteerInstance: Browser, concurrency: number) => {
1
+ import type { BrowserReplacer } from './replace-browser';
2
+ export declare const cycleBrowserTabs: (puppeteerInstance: BrowserReplacer, concurrency: number) => {
5
3
  stopCycling: () => void;
6
4
  };
7
- export {};
@@ -13,6 +13,7 @@ const cycleBrowserTabs = (puppeteerInstance, concurrency) => {
13
13
  const set = () => {
14
14
  interval = setTimeout(() => {
15
15
  puppeteerInstance
16
+ .getBrowser()
16
17
  .pages()
17
18
  .then((pages) => {
18
19
  var _a;
@@ -0,0 +1,2 @@
1
+ export declare const findClosestPackageJson: () => string | null;
2
+ export declare const findRemotionRoot: () => string;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.findRemotionRoot = exports.findClosestPackageJson = void 0;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const recursionLimit = 5;
10
+ const findClosestPackageJson = () => {
11
+ let currentDir = process.cwd();
12
+ let possiblePackageJson = '';
13
+ for (let i = 0; i < recursionLimit; i++) {
14
+ possiblePackageJson = path_1.default.join(currentDir, 'package.json');
15
+ const exists = fs_1.default.existsSync(possiblePackageJson);
16
+ if (exists) {
17
+ return possiblePackageJson;
18
+ }
19
+ currentDir = path_1.default.dirname(currentDir);
20
+ }
21
+ return null;
22
+ };
23
+ exports.findClosestPackageJson = findClosestPackageJson;
24
+ const findRemotionRoot = () => {
25
+ const closestPackageJson = (0, exports.findClosestPackageJson)();
26
+ if (closestPackageJson === null) {
27
+ return process.cwd();
28
+ }
29
+ return path_1.default.dirname(closestPackageJson);
30
+ };
31
+ exports.findRemotionRoot = findRemotionRoot;
@@ -26,7 +26,7 @@ const getPageAndCleanupFn = async ({ passedInInstance, browserExecutable, chromi
26
26
  page: browserPage,
27
27
  cleanup: () => {
28
28
  // Close whole browser that was just created and don't wait for it to finish.
29
- browserInstance.close().catch((err) => {
29
+ browserInstance.close(true).catch((err) => {
30
30
  console.error('Was not able to close puppeteer page', err);
31
31
  });
32
32
  },
package/dist/index.d.ts CHANGED
@@ -122,7 +122,7 @@ export declare const RenderInternals: {
122
122
  DEFAULT_CODEC: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif";
123
123
  isAudioCodec: (codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif" | undefined) => boolean;
124
124
  logLevels: readonly ["verbose", "info", "warn", "error"];
125
- isEqualOrBelowLogLevel: (currentLevel: "error" | "info" | "verbose" | "warn", level: "error" | "info" | "verbose" | "warn") => boolean;
125
+ isEqualOrBelowLogLevel: (currentLevel: "error" | "verbose" | "info" | "warn", level: "error" | "verbose" | "info" | "warn") => boolean;
126
126
  isValidLogLevel: (level: string) => boolean;
127
127
  perf: typeof perf;
128
128
  makeDownloadMap: () => import("./assets/download-map").DownloadMap;
@@ -21,7 +21,7 @@ const browserInstances = [];
21
21
  const killAllBrowsers = async () => {
22
22
  for (const browser of browserInstances) {
23
23
  try {
24
- await browser.close();
24
+ await browser.close(true);
25
25
  }
26
26
  catch (err) { }
27
27
  }
@@ -27,6 +27,7 @@ const prepare_server_1 = require("./prepare-server");
27
27
  const provide_screenshot_1 = require("./provide-screenshot");
28
28
  const puppeteer_evaluate_1 = require("./puppeteer-evaluate");
29
29
  const quality_1 = require("./quality");
30
+ const replace_browser_1 = require("./replace-browser");
30
31
  const seek_to_frame_1 = require("./seek-to-frame");
31
32
  const set_props_and_env_1 = require("./set-props-and-env");
32
33
  const truthy_1 = require("./truthy");
@@ -55,10 +56,7 @@ const getPool = async (pages) => {
55
56
  const pool = new pool_1.Pool(puppeteerPages);
56
57
  return pool;
57
58
  };
58
- 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, actualConcurrency, everyNthFrame = 1, proxyPort, cancelSignal, downloadMap, muted, }) => {
59
- if (!puppeteerInstance) {
60
- throw new Error('no puppeteer instance passed to innerRenderFrames - internal error');
61
- }
59
+ const innerRenderFrames = ({ onFrameUpdate, outputDir, onStart, inputProps, quality, imageFormat = image_format_1.DEFAULT_IMAGE_FORMAT, frameRange, onError, envVariables, onBrowserLog, onFrameBuffer, onDownload, pagesArray, serveUrl, composition, timeoutInMilliseconds, scale, actualConcurrency, everyNthFrame = 1, proxyPort, cancelSignal, downloadMap, muted, makeBrowser, browserReplacer, }) => {
62
60
  if (outputDir) {
63
61
  if (!fs_1.default.existsSync(outputDir)) {
64
62
  fs_1.default.mkdirSync(outputDir, {
@@ -71,8 +69,9 @@ const innerRenderFrames = ({ onFrameUpdate, outputDir, onStart, inputProps, qual
71
69
  const framesToRender = (0, get_duration_from_frame_range_1.getFramesToRender)(realFrameRange, everyNthFrame);
72
70
  const lastFrame = framesToRender[framesToRender.length - 1];
73
71
  const makePage = async () => {
74
- const page = await puppeteerInstance.newPage();
72
+ const page = await browserReplacer.getBrowser().newPage();
75
73
  pagesArray.push(page);
74
+ console.log('Made new page');
76
75
  await page.setViewport({
77
76
  width: composition.width,
78
77
  height: composition.height,
@@ -128,7 +127,7 @@ const innerRenderFrames = ({ onFrameUpdate, outputDir, onStart, inputProps, qual
128
127
  page.off('console', logCallback);
129
128
  return page;
130
129
  };
131
- const pages = new Array(actualConcurrency).fill(true).map(makePage);
130
+ const pages = new Array(actualConcurrency).fill(true).map(() => makePage());
132
131
  // If rendering a GIF and skipping frames, we must ensure it starts from 0
133
132
  // and then is consecutive so FFMPEG recognizes the sequence
134
133
  const countType = everyNthFrame === 1 ? 'actual-frames' : 'from-zero';
@@ -239,12 +238,13 @@ const innerRenderFrames = ({ onFrameUpdate, outputDir, onStart, inputProps, qual
239
238
  });
240
239
  };
241
240
  const renderFrameAndRetryTargetClose = async (frame, index, retriesLeft, attempt) => {
242
- var _a;
241
+ var _a, _b;
243
242
  try {
244
243
  await renderFrame(frame, index);
245
244
  }
246
245
  catch (err) {
247
- if (!((_a = err === null || err === void 0 ? void 0 : err.message) === null || _a === void 0 ? void 0 : _a.includes('Target closed'))) {
246
+ if (!((_a = err === null || err === void 0 ? void 0 : err.message) === null || _a === void 0 ? void 0 : _a.includes('Target closed')) &&
247
+ !((_b = err === null || err === void 0 ? void 0 : err.message) === null || _b === void 0 ? void 0 : _b.includes('Session closed'))) {
248
248
  throw err;
249
249
  }
250
250
  if (retriesLeft === 0) {
@@ -253,6 +253,8 @@ const innerRenderFrames = ({ onFrameUpdate, outputDir, onStart, inputProps, qual
253
253
  }
254
254
  console.warn(`The browser crashed while rendering frame ${frame}, retrying ${retriesLeft} more times. Learn more about this error under https://www.remotion.dev/docs/target-closed`);
255
255
  const pool = await poolPromise;
256
+ await browserReplacer.replaceBrowser(makeBrowser);
257
+ console.log('Successfully replaced browser');
256
258
  const page = await makePage();
257
259
  pool.release(page);
258
260
  await renderFrameAndRetryTargetClose(frame, index, retriesLeft - 1, attempt + 1);
@@ -279,7 +281,7 @@ const innerRenderFrames = ({ onFrameUpdate, outputDir, onStart, inputProps, qual
279
281
  .then(() => happyPath);
280
282
  };
281
283
  const renderFrames = (options) => {
282
- var _a, _b, _c, _d;
284
+ var _a, _b, _c;
283
285
  const composition = getComposition(options);
284
286
  const concurrency = getConcurrency(options);
285
287
  if (!composition) {
@@ -295,14 +297,18 @@ const renderFrames = (options) => {
295
297
  const selectedServeUrl = (0, legacy_webpack_config_1.getServeUrlWithFallback)(options);
296
298
  (0, quality_1.validateQuality)(options.quality);
297
299
  (0, validate_scale_1.validateScale)(options.scale);
298
- const browserInstance = (_a = options.puppeteerInstance) !== null && _a !== void 0 ? _a : (0, open_browser_1.openBrowser)(browser_1.DEFAULT_BROWSER, {
299
- shouldDumpIo: options.dumpBrowserLogs,
300
- browserExecutable: options.browserExecutable,
301
- chromiumOptions: options.chromiumOptions,
302
- forceDeviceScaleFactor: (_b = options.scale) !== null && _b !== void 0 ? _b : 1,
303
- });
304
- const downloadMap = (_c = options.downloadMap) !== null && _c !== void 0 ? _c : (0, download_map_1.makeDownloadMap)();
305
- const onDownload = (_d = options.onDownload) !== null && _d !== void 0 ? _d : (() => () => undefined);
300
+ const makeBrowser = () => {
301
+ var _a;
302
+ return (0, open_browser_1.openBrowser)(browser_1.DEFAULT_BROWSER, {
303
+ shouldDumpIo: options.dumpBrowserLogs,
304
+ browserExecutable: options.browserExecutable,
305
+ chromiumOptions: options.chromiumOptions,
306
+ forceDeviceScaleFactor: (_a = options.scale) !== null && _a !== void 0 ? _a : 1,
307
+ });
308
+ };
309
+ const browserInstance = (_a = options.puppeteerInstance) !== null && _a !== void 0 ? _a : makeBrowser();
310
+ const downloadMap = (_b = options.downloadMap) !== null && _b !== void 0 ? _b : (0, download_map_1.makeDownloadMap)();
311
+ const onDownload = (_c = options.onDownload) !== null && _c !== void 0 ? _c : (() => () => undefined);
306
312
  const actualConcurrency = (0, get_concurrency_1.getActualConcurrency)(concurrency !== null && concurrency !== void 0 ? concurrency : null);
307
313
  const openedPages = [];
308
314
  return new Promise((resolve, reject) => {
@@ -330,7 +336,8 @@ const renderFrames = (options) => {
330
336
  }),
331
337
  browserInstance,
332
338
  ]).then(([{ serveUrl, closeServer, offthreadPort }, puppeteerInstance]) => {
333
- const { stopCycling } = (0, cycle_browser_tabs_1.cycleBrowserTabs)(puppeteerInstance, actualConcurrency);
339
+ const browserReplacer = (0, replace_browser_1.handleBrowserCrash)(puppeteerInstance);
340
+ const { stopCycling } = (0, cycle_browser_tabs_1.cycleBrowserTabs)(browserReplacer, actualConcurrency);
334
341
  cleanup.push(stopCycling);
335
342
  cleanup.push(closeServer);
336
343
  return innerRenderFrames({
@@ -344,6 +351,8 @@ const renderFrames = (options) => {
344
351
  onDownload,
345
352
  proxyPort: offthreadPort,
346
353
  downloadMap,
354
+ makeBrowser,
355
+ browserReplacer,
347
356
  });
348
357
  }),
349
358
  ])
@@ -363,7 +372,7 @@ const renderFrames = (options) => {
363
372
  else {
364
373
  Promise.resolve(browserInstance)
365
374
  .then((puppeteerInstance) => {
366
- return puppeteerInstance.close();
375
+ return puppeteerInstance.close(true);
367
376
  })
368
377
  .catch((err) => {
369
378
  console.log('Unable to close browser', err);
@@ -105,7 +105,7 @@ const innerRenderStill = async ({ composition, quality, imageFormat = 'png', ser
105
105
  await page.close();
106
106
  }
107
107
  else {
108
- browserInstance.close().catch((err) => {
108
+ browserInstance.close(true).catch((err) => {
109
109
  console.log('Unable to close browser', err);
110
110
  });
111
111
  }
@@ -0,0 +1,6 @@
1
+ import type { Browser } from './browser/Browser';
2
+ export declare type BrowserReplacer = {
3
+ getBrowser: () => Browser;
4
+ replaceBrowser: (make: () => Promise<Browser>) => Promise<Browser>;
5
+ };
6
+ export declare const handleBrowserCrash: (instance: Browser) => BrowserReplacer;
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleBrowserCrash = void 0;
4
+ const handleBrowserCrash = (instance) => {
5
+ let _instance = instance;
6
+ const waiters = [];
7
+ let replacing = false;
8
+ return {
9
+ getBrowser: () => _instance,
10
+ replaceBrowser: async (make) => {
11
+ if (replacing) {
12
+ const waiter = new Promise((resolve, reject) => {
13
+ waiters.push({
14
+ resolve,
15
+ reject,
16
+ });
17
+ });
18
+ return waiter;
19
+ }
20
+ try {
21
+ replacing = true;
22
+ await instance
23
+ .close(true)
24
+ .then(() => {
25
+ console.log('Killed previous browser and making new one');
26
+ })
27
+ .catch(() => {
28
+ // Ignore as browser crashed
29
+ });
30
+ const browser = await make();
31
+ _instance = browser;
32
+ waiters.forEach((w) => w.resolve(browser));
33
+ console.log('Made new browser');
34
+ return browser;
35
+ }
36
+ catch (err) {
37
+ waiters.forEach((w) => w.reject(err));
38
+ throw err;
39
+ }
40
+ finally {
41
+ replacing = false;
42
+ }
43
+ },
44
+ };
45
+ };
46
+ exports.handleBrowserCrash = handleBrowserCrash;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remotion/renderer",
3
- "version": "3.2.42",
3
+ "version": "3.2.43-retry.19+5671d7797",
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
  "extract-zip": "2.0.1",
25
- "remotion": "3.2.42",
25
+ "remotion": "3.2.43-retry.19+5671d7797",
26
26
  "source-map": "^0.8.0-beta.0",
27
27
  "ws": "8.7.0"
28
28
  },
@@ -57,5 +57,5 @@
57
57
  "publishConfig": {
58
58
  "access": "public"
59
59
  },
60
- "gitHead": "d297af4ecea4d09948bbf05eeb66dfa701be3787"
60
+ "gitHead": "5671d779758f7837f2f50f75e2cccdd7c6b58f43"
61
61
  }