@remotion/renderer 4.0.540 → 4.0.541

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.
@@ -139,10 +139,7 @@ const downloadFile = async (options, retries = 2, attempt = 1) => {
139
139
  message.includes(incorrectContentLengthToken) ||
140
140
  message.includes(noDataSentToken) ||
141
141
  // Try again if hitting internal errors
142
- message.includes('503') ||
143
- message.includes('502') ||
144
- message.includes('504') ||
145
- message.includes('500')) {
142
+ /^Received a status code of (500|502|503|504) while downloading file /.test(message)) {
146
143
  if (retries === 0) {
147
144
  throw err;
148
145
  }
@@ -100,7 +100,7 @@ const makeBrowserRunner = async ({ executablePath, processArguments, userDataDir
100
100
  // If the process failed to launch (for example if the browser executable path
101
101
  // is invalid), then the process does not get a pid assigned. A call to
102
102
  // `proc.kill` would error, as the `pid` to-be-killed can not be found.
103
- if (proc.pid && pidExists(proc.pid)) {
103
+ if (!closed && proc.pid && pidExists(proc.pid)) {
104
104
  try {
105
105
  if (process.platform === 'win32') {
106
106
  childProcess.exec(`taskkill /pid ${proc.pid} /T /F`, (error) => {
@@ -138,17 +138,43 @@ const makeBrowserRunner = async ({ executablePath, processArguments, userDataDir
138
138
  // perform this earlier, then the previous function calls would not happen.
139
139
  (0, util_1.removeEventListeners)(listeners);
140
140
  };
141
+ let closePromise = null;
141
142
  const closeProcess = () => {
142
- if (closed) {
143
- return Promise.resolve();
143
+ if (closePromise) {
144
+ return closePromise;
144
145
  }
145
- logger_1.Log.verbose({ indent, logLevel }, 'Received SIGTERM signal. Killing browser process');
146
- killProcess();
147
- (0, delete_directory_1.deleteDirectory)(userDataDir);
148
- // Cleanup this listener last, as that makes sure the full callback runs. If we
149
- // perform this earlier, then the previous function calls would not happen.
150
- (0, util_1.removeEventListeners)(listeners);
151
- return processClosing;
146
+ closePromise = (async () => {
147
+ let timeoutId = null;
148
+ try {
149
+ if (!closed) {
150
+ // Let Chrome run its shutdown cleanup, including macOS code-sign
151
+ // clone removal. The CDP response can be lost as Chrome exits.
152
+ try {
153
+ void connection.send('Browser.close').catch(() => undefined);
154
+ }
155
+ catch (_a) { }
156
+ await Promise.race([
157
+ processClosing,
158
+ new Promise((resolve) => {
159
+ timeoutId = setTimeout(resolve, 2000);
160
+ }),
161
+ ]);
162
+ if (!closed) {
163
+ logger_1.Log.verbose({ indent, logLevel }, 'Browser did not exit gracefully. Killing browser process');
164
+ killProcess();
165
+ }
166
+ await processClosing;
167
+ }
168
+ }
169
+ finally {
170
+ if (timeoutId !== null) {
171
+ clearTimeout(timeoutId);
172
+ }
173
+ (0, delete_directory_1.deleteDirectory)(userDataDir);
174
+ (0, util_1.removeEventListeners)(listeners);
175
+ }
176
+ })();
177
+ return closePromise;
152
178
  };
153
179
  if (dumpio) {
154
180
  (_a = proc.stdout) === null || _a === void 0 ? void 0 : _a.on('data', (d) => {
@@ -21,7 +21,7 @@ const collectAssets = async ({ frame, freePage, timeoutInMilliseconds, }) => {
21
21
  throw new Error(`Expected string content for artifact ${asset.id}, but got ${asset.content}`);
22
22
  }
23
23
  const stringOrUintArray = asset.contentType === 'binary'
24
- ? new TextEncoder().encode(atob(asset.content))
24
+ ? new Uint8Array(Buffer.from(asset.content, 'base64'))
25
25
  : asset.content;
26
26
  return {
27
27
  ...asset,
@@ -1329,7 +1329,7 @@ var downloadFile = async (options2, retries = 2, attempt = 1) => {
1329
1329
  if (message === CANCELLED_ERROR) {
1330
1330
  throw err;
1331
1331
  }
1332
- if (message === "aborted" || message.includes("ECONNRESET") || message.includes(incorrectContentLengthToken) || message.includes(noDataSentToken) || message.includes("503") || message.includes("502") || message.includes("504") || message.includes("500")) {
1332
+ if (message === "aborted" || message.includes("ECONNRESET") || message.includes(incorrectContentLengthToken) || message.includes(noDataSentToken) || /^Received a status code of (500|502|503|504) while downloading file /.test(message)) {
1333
1333
  if (retries === 0) {
1334
1334
  throw err;
1335
1335
  }
@@ -4040,7 +4040,7 @@ var makeBrowserRunner = async ({
4040
4040
  const transport = await NodeWebSocketTransport.create(browserWSEndpoint);
4041
4041
  const connection = new Connection(transport);
4042
4042
  const killProcess = () => {
4043
- if (proc.pid && pidExists(proc.pid)) {
4043
+ if (!closed && proc.pid && pidExists(proc.pid)) {
4044
4044
  try {
4045
4045
  if (process.platform === "win32") {
4046
4046
  childProcess.exec(`taskkill /pid ${proc.pid} /T /F`, (error) => {
@@ -4066,15 +4066,41 @@ Error cause: ${isErrorLike(error) ? error.stack : error}`);
4066
4066
  deleteDirectory(userDataDir);
4067
4067
  removeEventListeners(listeners);
4068
4068
  };
4069
+ let closePromise = null;
4069
4070
  const closeProcess = () => {
4070
- if (closed) {
4071
- return Promise.resolve();
4071
+ if (closePromise) {
4072
+ return closePromise;
4072
4073
  }
4073
- Log.verbose({ indent, logLevel }, "Received SIGTERM signal. Killing browser process");
4074
- killProcess();
4075
- deleteDirectory(userDataDir);
4076
- removeEventListeners(listeners);
4077
- return processClosing;
4074
+ closePromise = (async () => {
4075
+ let timeoutId = null;
4076
+ try {
4077
+ if (!closed) {
4078
+ try {
4079
+ connection.send("Browser.close").catch(() => {
4080
+ return;
4081
+ });
4082
+ } catch {}
4083
+ await Promise.race([
4084
+ processClosing,
4085
+ new Promise((resolve) => {
4086
+ timeoutId = setTimeout(resolve, 2000);
4087
+ })
4088
+ ]);
4089
+ if (!closed) {
4090
+ Log.verbose({ indent, logLevel }, "Browser did not exit gracefully. Killing browser process");
4091
+ killProcess();
4092
+ }
4093
+ await processClosing;
4094
+ }
4095
+ } finally {
4096
+ if (timeoutId !== null) {
4097
+ clearTimeout(timeoutId);
4098
+ }
4099
+ deleteDirectory(userDataDir);
4100
+ removeEventListeners(listeners);
4101
+ }
4102
+ })();
4103
+ return closePromise;
4078
4104
  };
4079
4105
  if (dumpio) {
4080
4106
  proc.stdout?.on("data", (d) => {
@@ -7384,6 +7410,7 @@ var internalOpenBrowser = async ({
7384
7410
  "--proxy-server='direct://'",
7385
7411
  "--proxy-bypass-list=*",
7386
7412
  "--force-gpu-mem-available-mb=4096",
7413
+ process.platform === "win32" ? "--disable-skia-graphite" : null,
7387
7414
  process.env.__RESERVED_IS_INSIDE_REMOTION_LAMBDA === "true" ? "--disable-gpu-rasterization" : null,
7388
7415
  "--disable-hang-monitor",
7389
7416
  "--disable-extensions",
@@ -21896,6 +21923,9 @@ class Pool {
21896
21923
  });
21897
21924
  }
21898
21925
  release(resource) {
21926
+ if (resource.closed) {
21927
+ return;
21928
+ }
21899
21929
  const waiter = this.waiters.shift();
21900
21930
  if (waiter === undefined) {
21901
21931
  this.resources.push(resource);
@@ -21960,7 +21990,7 @@ var collectAssets = async ({
21960
21990
  if (typeof asset.content !== "string") {
21961
21991
  throw new Error(`Expected string content for artifact ${asset.id}, but got ${asset.content}`);
21962
21992
  }
21963
- const stringOrUintArray = asset.contentType === "binary" ? new TextEncoder().encode(atob(asset.content)) : asset.content;
21993
+ const stringOrUintArray = asset.contentType === "binary" ? new Uint8Array(Buffer.from(asset.content, "base64")) : asset.content;
21964
21994
  return {
21965
21995
  ...asset,
21966
21996
  content: stringOrUintArray
@@ -22675,16 +22705,17 @@ var renderFrameAndRetryTargetClose = async ({
22675
22705
  });
22676
22706
  }
22677
22707
  Log.warn({ indent, logLevel }, `The browser crashed while rendering frame ${frame}, retrying ${retriesLeft} more times. Learn more about this error under https://www.remotion.dev/docs/target-closed`);
22708
+ nextFrameToRender.returnFrame(frame);
22678
22709
  await remotionSharedMemory?.forgetAllPages();
22679
22710
  await browserReplacer.replaceBrowser(makeBrowser, async () => {
22680
22711
  const pages = new Array(concurrencyOrFramesToRender).fill(true).map((_, i) => makeNewPage(frame, i));
22681
22712
  const puppeteerPages = await Promise.all(pages);
22682
22713
  const pool = await poolPromise;
22714
+ pool.resources = pool.resources.filter((p) => !p.closed);
22683
22715
  for (const newPage of puppeteerPages) {
22684
22716
  pool.release(newPage);
22685
22717
  }
22686
22718
  });
22687
- nextFrameToRender.returnFrame(frame);
22688
22719
  await renderFrameAndRetryTargetClose({
22689
22720
  retriesLeft: retriesLeft - 1,
22690
22721
  attempt: attempt + 1,
@@ -118,6 +118,8 @@ const internalOpenBrowser = async ({ browser, browserExecutable, chromiumOptions
118
118
  "--proxy-server='direct://'",
119
119
  '--proxy-bypass-list=*',
120
120
  '--force-gpu-mem-available-mb=4096',
121
+ // https://github.com/remotion-dev/remotion/issues/12929
122
+ process.platform === 'win32' ? '--disable-skia-graphite' : null,
121
123
  // Prevent duplicated horizontal strips in Lambda renders: https://github.com/remotion-dev/remotion/issues/11428
122
124
  process.env.__RESERVED_IS_INSIDE_REMOTION_LAMBDA === 'true'
123
125
  ? '--disable-gpu-rasterization'
package/dist/pool.js CHANGED
@@ -18,6 +18,9 @@ class Pool {
18
18
  });
19
19
  }
20
20
  release(resource) {
21
+ if (resource.closed) {
22
+ return;
23
+ }
21
24
  const waiter = this.waiters.shift();
22
25
  if (waiter === undefined) {
23
26
  this.resources.push(resource);
@@ -140,6 +140,7 @@ const renderFrameAndRetryTargetClose = async ({ retriesLeft, attempt, assets, as
140
140
  });
141
141
  }
142
142
  logger_1.Log.warn({ indent, logLevel }, `The browser crashed while rendering frame ${frame}, retrying ${retriesLeft} more times. Learn more about this error under https://www.remotion.dev/docs/target-closed`);
143
+ nextFrameToRender.returnFrame(frame);
143
144
  // Replace the entire browser
144
145
  await (remotionSharedMemory === null || remotionSharedMemory === void 0 ? void 0 : remotionSharedMemory.forgetAllPages());
145
146
  await browserReplacer.replaceBrowser(makeBrowser, async () => {
@@ -148,11 +149,11 @@ const renderFrameAndRetryTargetClose = async ({ retriesLeft, attempt, assets, as
148
149
  .map((_, i) => makeNewPage(frame, i));
149
150
  const puppeteerPages = await Promise.all(pages);
150
151
  const pool = await poolPromise;
152
+ pool.resources = pool.resources.filter((p) => !p.closed);
151
153
  for (const newPage of puppeteerPages) {
152
154
  pool.release(newPage);
153
155
  }
154
156
  });
155
- nextFrameToRender.returnFrame(frame);
156
157
  await (0, exports.renderFrameAndRetryTargetClose)({
157
158
  retriesLeft: retriesLeft - 1,
158
159
  attempt: attempt + 1,
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "url": "https://github.com/remotion-dev/remotion/tree/main/packages/renderer"
4
4
  },
5
5
  "name": "@remotion/renderer",
6
- "version": "4.0.540",
6
+ "version": "4.0.541",
7
7
  "description": "Render Remotion videos using Node.js or Bun",
8
8
  "main": "dist/index.js",
9
9
  "types": "dist/index.d.ts",
@@ -22,11 +22,11 @@
22
22
  },
23
23
  "dependencies": {
24
24
  "execa": "5.1.1",
25
- "remotion": "4.0.540",
26
- "@remotion/streaming": "4.0.540",
25
+ "remotion": "4.0.541",
26
+ "@remotion/streaming": "4.0.541",
27
27
  "source-map": "0.8.0",
28
28
  "ws": "8.21.0",
29
- "@remotion/licensing": "4.0.540"
29
+ "@remotion/licensing": "4.0.541"
30
30
  },
31
31
  "peerDependencies": {
32
32
  "react": ">=16.8.0",
@@ -40,21 +40,21 @@
40
40
  "react-dom": "19.3.1",
41
41
  "typescript": "7.1.0-beta",
42
42
  "@types/ws": "8.5.10",
43
- "@remotion/example-videos": "4.0.540",
44
- "@remotion/eslint-config-internal": "4.0.540",
43
+ "@remotion/example-videos": "4.0.541",
44
+ "@remotion/eslint-config-internal": "4.0.541",
45
45
  "eslint": "9.19.0",
46
46
  "@types/node": "20.12.14",
47
47
  "@types/pngjs": "6.0.5",
48
48
  "pngjs": "7.0.0"
49
49
  },
50
50
  "optionalDependencies": {
51
- "@remotion/compositor-darwin-arm64": "4.0.540",
52
- "@remotion/compositor-darwin-x64": "4.0.540",
53
- "@remotion/compositor-linux-arm64-gnu": "4.0.540",
54
- "@remotion/compositor-linux-arm64-musl": "4.0.540",
55
- "@remotion/compositor-linux-x64-gnu": "4.0.540",
56
- "@remotion/compositor-linux-x64-musl": "4.0.540",
57
- "@remotion/compositor-win32-x64-msvc": "4.0.540"
51
+ "@remotion/compositor-darwin-arm64": "4.0.541",
52
+ "@remotion/compositor-darwin-x64": "4.0.541",
53
+ "@remotion/compositor-linux-arm64-gnu": "4.0.541",
54
+ "@remotion/compositor-linux-arm64-musl": "4.0.541",
55
+ "@remotion/compositor-linux-x64-gnu": "4.0.541",
56
+ "@remotion/compositor-linux-x64-musl": "4.0.541",
57
+ "@remotion/compositor-win32-x64-msvc": "4.0.541"
58
58
  },
59
59
  "keywords": [
60
60
  "remotion",