@remotion/renderer 4.0.10 → 4.0.11

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.
@@ -31,6 +31,5 @@ export declare class BrowserRunner {
31
31
  kill(): void;
32
32
  setupConnection(options: {
33
33
  timeout: number;
34
- preferredRevision: string;
35
34
  }): Promise<Connection>;
36
35
  }
@@ -200,8 +200,8 @@ class BrowserRunner {
200
200
  }
201
201
  async setupConnection(options) {
202
202
  (0, assert_1.assert)(this.proc, 'BrowserRunner not started.');
203
- const { timeout, preferredRevision } = options;
204
- const browserWSEndpoint = await waitForWSEndpoint(this.proc, timeout, preferredRevision);
203
+ const { timeout } = options;
204
+ const browserWSEndpoint = await waitForWSEndpoint(this.proc, timeout);
205
205
  const transport = await NodeWebSocketTransport_1.NodeWebSocketTransport.create(browserWSEndpoint);
206
206
  this.connection = new Connection_1.Connection(transport);
207
207
  return this.connection;
@@ -209,7 +209,7 @@ class BrowserRunner {
209
209
  }
210
210
  exports.BrowserRunner = BrowserRunner;
211
211
  _BrowserRunner_executablePath = new WeakMap(), _BrowserRunner_processArguments = new WeakMap(), _BrowserRunner_userDataDir = new WeakMap(), _BrowserRunner_closed = new WeakMap(), _BrowserRunner_listeners = new WeakMap(), _BrowserRunner_processClosing = new WeakMap();
212
- function waitForWSEndpoint(browserProcess, timeout, preferredRevision) {
212
+ function waitForWSEndpoint(browserProcess, timeout) {
213
213
  (0, assert_1.assert)(browserProcess.stderr, '`browserProcess` does not have stderr.');
214
214
  const rl = readline.createInterface(browserProcess.stderr);
215
215
  let stderr = '';
@@ -240,7 +240,7 @@ function waitForWSEndpoint(browserProcess, timeout, preferredRevision) {
240
240
  }
241
241
  function onTimeout() {
242
242
  cleanup();
243
- reject(new Errors_1.TimeoutError(`Timed out after ${timeout} ms while trying to connect to the browser! Only Chrome at revision r${preferredRevision} is guaranteed to work.`));
243
+ reject(new Errors_1.TimeoutError(`Timed out after ${timeout} ms while trying to connect to the browser!`));
244
244
  }
245
245
  function onLine(line) {
246
246
  stderr += line + '\n';
@@ -29,11 +29,12 @@ export declare class DOMWorld {
29
29
  executionContext(): Promise<ExecutionContext>;
30
30
  evaluateHandle<HandlerType extends JSHandle = JSHandle>(pageFunction: EvaluateHandleFn, ...args: SerializableOrJSHandle[]): Promise<HandlerType>;
31
31
  evaluate<T extends EvaluateFn>(pageFunction: T, ...args: SerializableOrJSHandle[]): Promise<UnwrapPromiseLike<EvaluateFnReturnType<T>>>;
32
- waitForFunction({ browser, timeout, pageFunction, title, }: {
32
+ waitForFunction({ browser, timeout, pageFunction, title, shouldClosePage, }: {
33
33
  browser: HeadlessBrowser;
34
- timeout: number;
34
+ timeout: number | null;
35
35
  pageFunction: Function | string;
36
36
  title: string;
37
+ shouldClosePage: boolean;
37
38
  }): Promise<JSHandle>;
38
39
  title(): Promise<string>;
39
40
  }
@@ -41,9 +42,10 @@ interface WaitTaskOptions {
41
42
  domWorld: DOMWorld;
42
43
  predicateBody: Function | string;
43
44
  title: string;
44
- timeout: number;
45
+ timeout: number | null;
45
46
  browser: HeadlessBrowser;
46
47
  args: SerializableOrJSHandle[];
48
+ shouldClosePage: boolean;
47
49
  }
48
50
  declare class WaitTask {
49
51
  #private;
@@ -25,7 +25,7 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
25
25
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
26
26
  return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
27
27
  };
28
- var _DOMWorld_frame, _DOMWorld_contextPromise, _DOMWorld_contextResolveCallback, _DOMWorld_detached, _DOMWorld_waitTasks, _WaitTask_instances, _WaitTask_domWorld, _WaitTask_timeout, _WaitTask_predicateBody, _WaitTask_args, _WaitTask_runCount, _WaitTask_resolve, _WaitTask_reject, _WaitTask_timeoutTimer, _WaitTask_terminated, _WaitTask_browser, _WaitTask_cleanup;
28
+ var _DOMWorld_frame, _DOMWorld_contextPromise, _DOMWorld_contextResolveCallback, _DOMWorld_detached, _DOMWorld_waitTasks, _WaitTask_instances, _WaitTask_domWorld, _WaitTask_timeout, _WaitTask_predicateBody, _WaitTask_args, _WaitTask_runCount, _WaitTask_resolve, _WaitTask_reject, _WaitTask_timeoutTimer, _WaitTask_terminated, _WaitTask_browser, _WaitTask_shouldClosePage, _WaitTask_cleanup;
29
29
  Object.defineProperty(exports, "__esModule", { value: true });
30
30
  exports.DOMWorld = void 0;
31
31
  const assert_1 = require("./assert");
@@ -91,7 +91,7 @@ class DOMWorld {
91
91
  const context = await this.executionContext();
92
92
  return context.evaluate(pageFunction, ...args);
93
93
  }
94
- waitForFunction({ browser, timeout, pageFunction, title, }) {
94
+ waitForFunction({ browser, timeout, pageFunction, title, shouldClosePage, }) {
95
95
  return new WaitTask({
96
96
  domWorld: this,
97
97
  predicateBody: pageFunction,
@@ -99,6 +99,7 @@ class DOMWorld {
99
99
  timeout,
100
100
  args: [],
101
101
  browser,
102
+ shouldClosePage,
102
103
  }).promise;
103
104
  }
104
105
  title() {
@@ -123,6 +124,7 @@ class WaitTask {
123
124
  _WaitTask_timeoutTimer.set(this, void 0);
124
125
  _WaitTask_terminated.set(this, false);
125
126
  _WaitTask_browser.set(this, void 0);
127
+ _WaitTask_shouldClosePage.set(this, void 0);
126
128
  this.onBrowserClose = () => {
127
129
  return this.terminate(new Error('Browser was closed'));
128
130
  };
@@ -140,6 +142,7 @@ class WaitTask {
140
142
  __classPrivateFieldSet(this, _WaitTask_predicateBody, getPredicateBody(options.predicateBody), "f");
141
143
  __classPrivateFieldSet(this, _WaitTask_args, options.args, "f");
142
144
  __classPrivateFieldSet(this, _WaitTask_runCount, 0, "f");
145
+ __classPrivateFieldSet(this, _WaitTask_shouldClosePage, options.shouldClosePage, "f");
143
146
  __classPrivateFieldGet(this, _WaitTask_domWorld, "f")._waitTasks.add(this);
144
147
  this.promise = new Promise((resolve, reject) => {
145
148
  __classPrivateFieldSet(this, _WaitTask_resolve, resolve, "f");
@@ -150,7 +153,10 @@ class WaitTask {
150
153
  if (options.timeout) {
151
154
  const timeoutError = new Errors_1.TimeoutError(`waiting for ${options.title} failed: timeout ${options.timeout}ms exceeded`);
152
155
  __classPrivateFieldSet(this, _WaitTask_timeoutTimer, setTimeout(() => {
153
- return this.terminate(timeoutError);
156
+ if (__classPrivateFieldGet(this, _WaitTask_shouldClosePage, "f")) {
157
+ return this.terminate(timeoutError);
158
+ }
159
+ return __classPrivateFieldGet(this, _WaitTask_reject, "f").call(this, timeoutError);
154
160
  }, options.timeout), "f");
155
161
  }
156
162
  __classPrivateFieldSet(this, _WaitTask_browser, options.browser, "f");
@@ -238,7 +244,7 @@ class WaitTask {
238
244
  __classPrivateFieldGet(this, _WaitTask_instances, "m", _WaitTask_cleanup).call(this);
239
245
  }
240
246
  }
241
- _WaitTask_domWorld = new WeakMap(), _WaitTask_timeout = new WeakMap(), _WaitTask_predicateBody = new WeakMap(), _WaitTask_args = new WeakMap(), _WaitTask_runCount = new WeakMap(), _WaitTask_resolve = new WeakMap(), _WaitTask_reject = new WeakMap(), _WaitTask_timeoutTimer = new WeakMap(), _WaitTask_terminated = new WeakMap(), _WaitTask_browser = new WeakMap(), _WaitTask_instances = new WeakSet(), _WaitTask_cleanup = function _WaitTask_cleanup() {
247
+ _WaitTask_domWorld = new WeakMap(), _WaitTask_timeout = new WeakMap(), _WaitTask_predicateBody = new WeakMap(), _WaitTask_args = new WeakMap(), _WaitTask_runCount = new WeakMap(), _WaitTask_resolve = new WeakMap(), _WaitTask_reject = new WeakMap(), _WaitTask_timeoutTimer = new WeakMap(), _WaitTask_terminated = new WeakMap(), _WaitTask_browser = new WeakMap(), _WaitTask_shouldClosePage = new WeakMap(), _WaitTask_instances = new WeakSet(), _WaitTask_cleanup = function _WaitTask_cleanup() {
242
248
  if (__classPrivateFieldGet(this, _WaitTask_timeoutTimer, "f") !== undefined) {
243
249
  clearTimeout(__classPrivateFieldGet(this, _WaitTask_timeoutTimer, "f"));
244
250
  }
@@ -90,7 +90,6 @@ class ChromeLauncher {
90
90
  try {
91
91
  const connection = await runner.setupConnection({
92
92
  timeout,
93
- preferredRevision: this._preferredRevision,
94
93
  });
95
94
  browser = await Browser_1.HeadlessBrowser._create({
96
95
  connection,
@@ -126,7 +125,7 @@ function resolveExecutablePath(launcher) {
126
125
  const { product, _preferredRevision } = launcher;
127
126
  const revisionInfo = (0, BrowserFetcher_1.getRevisionInfo)(_preferredRevision, 'chrome');
128
127
  const firefoxHelp = `Run \`PUPPETEER_PRODUCT=firefox npm install\` to download a supported Firefox browser binary.`;
129
- const chromeHelp = `Run \`npm install\` to download the correct Chromium revision (${launcher._preferredRevision}).`;
128
+ const chromeHelp = `Run \`npm install\` to download the correct Chromium revision.`;
130
129
  const missingText = revisionInfo.local
131
130
  ? undefined
132
131
  : `Could not find expected browser (${product}) locally. ${product === 'chrome' ? chromeHelp : firefoxHelp}`;
@@ -20,8 +20,8 @@ const getIdealMaximumFrameCacheItems = () => {
20
20
  // Assuming only half the available memory should be used
21
21
  const max = Math.floor(freeMemory / (1024 * 1024 * 6));
22
22
  // Never store more than 2000 frames
23
- // But 500 is needed even if it's going to swap
24
- return Math.max(500, Math.min(max, 2000));
23
+ // But 60 is needed even if it's going to swap
24
+ return Math.max(60, Math.min(max, 2000));
25
25
  };
26
26
  exports.getIdealMaximumFrameCacheItems = getIdealMaximumFrameCacheItems;
27
27
  const startLongRunningCompositor = (maximumFrameCacheItems, logLevel, indent) => {
@@ -45,7 +45,8 @@ export type CompositorCommand = {
45
45
  output_format: CompositorImageFormat;
46
46
  };
47
47
  ExtractFrame: {
48
- input: string;
48
+ src: string;
49
+ original_src: string;
49
50
  time: number;
50
51
  transparent: boolean;
51
52
  };
package/dist/index.d.ts CHANGED
@@ -44,7 +44,7 @@ export declare const RenderInternals: {
44
44
  downloadMap: import("./assets/download-map").DownloadMap;
45
45
  remotionRoot: string;
46
46
  concurrency: number;
47
- logLevel: "verbose" | "info" | "warn" | "error";
47
+ logLevel: "error" | "verbose" | "info" | "warn";
48
48
  indent: boolean;
49
49
  }) => Promise<{
50
50
  port: number;
@@ -123,7 +123,7 @@ export declare const RenderInternals: {
123
123
  DEFAULT_CODEC: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif";
124
124
  isAudioCodec: (codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif" | undefined) => boolean;
125
125
  logLevels: readonly ["verbose", "info", "warn", "error"];
126
- isEqualOrBelowLogLevel: (currentLevel: "verbose" | "info" | "warn" | "error", level: "verbose" | "info" | "warn" | "error") => boolean;
126
+ isEqualOrBelowLogLevel: (currentLevel: "error" | "verbose" | "info" | "warn", level: "error" | "verbose" | "info" | "warn") => boolean;
127
127
  isValidLogLevel: (level: string) => boolean;
128
128
  perf: typeof perf;
129
129
  convertToPositiveFrameIndex: ({ frame, durationInFrames, }: {
@@ -352,30 +352,30 @@ export declare const RenderInternals: {
352
352
  verbose: (message?: any, ...optionalParams: any[]) => void;
353
353
  verboseAdvanced: (options: {
354
354
  indent: boolean;
355
- logLevel: "verbose" | "info" | "warn" | "error";
355
+ logLevel: "error" | "verbose" | "info" | "warn";
356
356
  } & {
357
357
  tag?: string | undefined;
358
358
  }, message?: any, ...optionalParams: any[]) => void;
359
359
  info: (message?: any, ...optionalParams: any[]) => void;
360
360
  infoAdvanced: (options: {
361
361
  indent: boolean;
362
- logLevel: "verbose" | "info" | "warn" | "error";
362
+ logLevel: "error" | "verbose" | "info" | "warn";
363
363
  }, message?: any, ...optionalParams: any[]) => void;
364
364
  warn: (message?: any, ...optionalParams: any[]) => void;
365
365
  warnAdvanced: (options: {
366
366
  indent: boolean;
367
- logLevel: "verbose" | "info" | "warn" | "error";
367
+ logLevel: "error" | "verbose" | "info" | "warn";
368
368
  }, message?: any, ...optionalParams: any[]) => void;
369
369
  error: (message?: any, ...optionalParams: any[]) => void;
370
370
  errorAdvanced: (options: {
371
371
  indent: boolean;
372
- logLevel: "verbose" | "info" | "warn" | "error";
372
+ logLevel: "error" | "verbose" | "info" | "warn";
373
373
  } & {
374
374
  tag?: string | undefined;
375
375
  }, message?: any, ...optionalParams: any[]) => void;
376
376
  };
377
- getLogLevel: () => "verbose" | "info" | "warn" | "error";
378
- setLogLevel: (newLogLevel: "verbose" | "info" | "warn" | "error") => void;
377
+ getLogLevel: () => "error" | "verbose" | "info" | "warn";
378
+ setLogLevel: (newLogLevel: "error" | "verbose" | "info" | "warn") => void;
379
379
  INDENT_TOKEN: string;
380
380
  isColorSupported: () => boolean;
381
381
  HeadlessBrowser: typeof HeadlessBrowser;
@@ -384,7 +384,7 @@ export declare const RenderInternals: {
384
384
  port: number | null;
385
385
  remotionRoot: string;
386
386
  concurrency: number;
387
- logLevel: "verbose" | "info" | "warn" | "error";
387
+ logLevel: "error" | "verbose" | "info" | "warn";
388
388
  indent: boolean;
389
389
  }) => Promise<import("./prepare-server").RemotionServer>;
390
390
  makeOrReuseServer: (server: import("./prepare-server").RemotionServer | undefined, config: {
@@ -392,7 +392,7 @@ export declare const RenderInternals: {
392
392
  port: number | null;
393
393
  remotionRoot: string;
394
394
  concurrency: number;
395
- logLevel: "verbose" | "info" | "warn" | "error";
395
+ logLevel: "error" | "verbose" | "info" | "warn";
396
396
  indent: boolean;
397
397
  }, { onDownload, onError, }: {
398
398
  onError: (err: Error) => void;
@@ -421,7 +421,7 @@ export declare const RenderInternals: {
421
421
  cancelSignal: import("./make-cancel-signal").CancelSignal | null;
422
422
  indent: boolean;
423
423
  server: import("./prepare-server").RemotionServer | undefined;
424
- logLevel: "verbose" | "info" | "warn" | "error";
424
+ logLevel: "error" | "verbose" | "info" | "warn";
425
425
  serveUrl: string;
426
426
  port: number | null;
427
427
  }) => Promise<{
@@ -434,7 +434,7 @@ export declare const RenderInternals: {
434
434
  viewport: import("./browser/PuppeteerViewport").Viewport | null;
435
435
  indent: boolean;
436
436
  browser: import("./browser").Browser;
437
- logLevel: "verbose" | "info" | "warn" | "error";
437
+ logLevel: "error" | "verbose" | "info" | "warn";
438
438
  }) => Promise<HeadlessBrowser>;
439
439
  internalSelectComposition: (options: {
440
440
  serializedInputPropsWithCustomSchema: string;
@@ -447,7 +447,7 @@ export declare const RenderInternals: {
447
447
  port: number | null;
448
448
  indent: boolean;
449
449
  server: import("./prepare-server").RemotionServer | undefined;
450
- logLevel: "verbose" | "info" | "warn" | "error";
450
+ logLevel: "error" | "verbose" | "info" | "warn";
451
451
  serveUrl: string;
452
452
  id: string;
453
453
  }) => Promise<{
@@ -465,7 +465,7 @@ export declare const RenderInternals: {
465
465
  port: number | null;
466
466
  server: import("./prepare-server").RemotionServer | undefined;
467
467
  indent: boolean;
468
- logLevel: "verbose" | "info" | "warn" | "error";
468
+ logLevel: "error" | "verbose" | "info" | "warn";
469
469
  serveUrlOrWebpackUrl: string;
470
470
  }) => Promise<import("remotion").VideoConfig[]>;
471
471
  internalRenderFrames: ({ browserExecutable, cancelSignal, chromiumOptions, composition, concurrency, envVariables, everyNthFrame, frameRange, imageFormat, indent, jpegQuality, muted, onBrowserLog, onDownload, onFrameBuffer, onFrameUpdate, onStart, outputDir, port, puppeteerInstance, scale, server, timeoutInMilliseconds, logLevel, webpackBundleOrServeUrl, serializedInputPropsWithCustomSchema, serializedResolvedPropsWithCustomSchema, }: import("./render-frames").InternalRenderFramesOptions) => Promise<import("./types").RenderFramesOutput>;
package/dist/logger.d.ts CHANGED
@@ -19,6 +19,6 @@ export declare const Log: {
19
19
  error: (message?: any, ...optionalParams: any[]) => void;
20
20
  errorAdvanced: (options: VerboseLogOptions, message?: any, ...optionalParams: any[]) => void;
21
21
  };
22
- export declare const getLogLevel: () => "verbose" | "info" | "warn" | "error";
22
+ export declare const getLogLevel: () => "error" | "verbose" | "info" | "warn";
23
23
  export declare const setLogLevel: (newLogLevel: LogLevel) => void;
24
24
  export {};
@@ -29,6 +29,7 @@ const extractUrlAndSourceFromUrl = (url) => {
29
29
  };
30
30
  };
31
31
  exports.extractUrlAndSourceFromUrl = extractUrlAndSourceFromUrl;
32
+ const REQUEST_CLOSED_TOKEN = 'Request closed';
32
33
  const startOffthreadVideoServer = ({ downloadMap, concurrency, logLevel, indent, }) => {
33
34
  const compositor = (0, compositor_1.startCompositor)('StartLongRunningProcess', {
34
35
  concurrency,
@@ -40,62 +41,90 @@ const startOffthreadVideoServer = ({ downloadMap, concurrency, logLevel, indent,
40
41
  compositor.finishCommands();
41
42
  return compositor.waitForDone();
42
43
  },
43
- listener: (req, res) => {
44
+ listener: (req, response) => {
44
45
  if (!req.url) {
45
46
  throw new Error('Request came in without URL');
46
47
  }
47
48
  if (!req.url.startsWith('/proxy')) {
48
- res.writeHead(404);
49
- res.end();
49
+ response.writeHead(404);
50
+ response.end();
50
51
  return;
51
52
  }
52
53
  const { src, time, transparent } = (0, exports.extractUrlAndSourceFromUrl)(req.url);
53
- res.setHeader('access-control-allow-origin', '*');
54
+ response.setHeader('access-control-allow-origin', '*');
54
55
  if (transparent) {
55
- res.setHeader('content-type', `image/png`);
56
+ response.setHeader('content-type', `image/png`);
56
57
  }
57
58
  else {
58
- res.setHeader('content-type', `image/bmp`);
59
+ response.setHeader('content-type', `image/bmp`);
59
60
  }
60
61
  // Handling this case on Lambda:
61
62
  // https://support.google.com/chrome/a/answer/7679408?hl=en
62
63
  // Chrome sends Private Network Access preflights for subresources
63
64
  if (req.method === 'OPTIONS') {
64
- res.statusCode = 200;
65
+ response.statusCode = 200;
65
66
  if (req.headers['access-control-request-private-network']) {
66
- res.setHeader('Access-Control-Allow-Private-Network', 'true');
67
+ response.setHeader('Access-Control-Allow-Private-Network', 'true');
67
68
  }
68
- res.end();
69
+ response.end();
69
70
  return;
70
71
  }
72
+ let closed = false;
73
+ req.on('close', () => {
74
+ closed = true;
75
+ });
71
76
  let extractStart = Date.now();
72
77
  (0, download_and_map_assets_to_file_1.downloadAsset)({ src, downloadMap })
73
78
  .then((to) => {
74
- extractStart = Date.now();
75
- return compositor.executeCommand('ExtractFrame', {
76
- input: to,
77
- time,
78
- transparent,
79
+ return new Promise((resolve, reject) => {
80
+ if (closed) {
81
+ reject(Error(REQUEST_CLOSED_TOKEN));
82
+ return;
83
+ }
84
+ extractStart = Date.now();
85
+ resolve(compositor.executeCommand('ExtractFrame', {
86
+ src: to,
87
+ original_src: src,
88
+ time,
89
+ transparent,
90
+ }));
79
91
  });
80
92
  })
81
93
  .then((readable) => {
82
- const extractEnd = Date.now();
83
- const timeToExtract = extractEnd - extractStart;
84
- if (timeToExtract > 1000) {
85
- logger_1.Log.verbose(`Took ${timeToExtract}ms to extract frame from ${src} at ${time}`);
86
- }
87
- if (!readable) {
88
- throw new Error('no readable from ffmpeg');
89
- }
90
- res.writeHead(200);
91
- res.write(readable);
92
- res.end();
94
+ return new Promise((resolve, reject) => {
95
+ if (closed) {
96
+ reject(Error(REQUEST_CLOSED_TOKEN));
97
+ return;
98
+ }
99
+ if (!readable) {
100
+ reject(new Error('no readable from compositor'));
101
+ return;
102
+ }
103
+ const extractEnd = Date.now();
104
+ const timeToExtract = extractEnd - extractStart;
105
+ if (timeToExtract > 1000) {
106
+ logger_1.Log.verbose(`Took ${timeToExtract}ms to extract frame from ${src} at ${time}`);
107
+ }
108
+ response.writeHead(200);
109
+ response.write(readable, (err) => {
110
+ response.end();
111
+ if (err) {
112
+ reject(err);
113
+ }
114
+ else {
115
+ resolve();
116
+ }
117
+ });
118
+ });
93
119
  })
94
120
  .catch((err) => {
95
- res.writeHead(500);
96
- res.end();
97
- downloadMap.emitter.dispatchError(err);
98
- console.log('Error occurred', err);
121
+ response.writeHead(500);
122
+ response.end();
123
+ // Any errors occurred due to the render being aborted don't need to be logged.
124
+ if (err.message !== REQUEST_CLOSED_TOKEN) {
125
+ downloadMap.emitter.dispatchError(err);
126
+ console.log('Error occurred', err);
127
+ }
99
128
  });
100
129
  },
101
130
  compositor,
@@ -1,6 +1,6 @@
1
1
  /// <reference types="node" />
2
2
  import type { VideoConfig } from 'remotion';
3
- import type { RenderMediaOnDownload } from './assets/download-and-map-assets-to-file';
3
+ import { type RenderMediaOnDownload } from './assets/download-and-map-assets-to-file';
4
4
  import type { AudioCodec } from './audio-codec';
5
5
  import type { BrowserExecutable } from './browser-executable';
6
6
  import type { BrowserLog } from './browser-log';
@@ -72,6 +72,7 @@ const internalRenderMedia = ({ proResProfile, crf, composition, serializedInputP
72
72
  let stitcherFfmpeg;
73
73
  let preStitcher = null;
74
74
  let encodedFrames = 0;
75
+ let muxedFrames = 0;
75
76
  let renderedFrames = 0;
76
77
  let renderedDoneIn = null;
77
78
  let encodedDoneIn = null;
@@ -135,13 +136,12 @@ const internalRenderMedia = ({ proResProfile, crf, composition, serializedInputP
135
136
  const callUpdate = () => {
136
137
  onProgress === null || onProgress === void 0 ? void 0 : onProgress({
137
138
  encodedDoneIn,
138
- encodedFrames,
139
+ encodedFrames: Math.round(0.5 * encodedFrames + 0.5 * muxedFrames),
139
140
  renderedDoneIn,
140
141
  renderedFrames,
141
142
  stitchStage,
142
- progress: Math.round(((0.7 * renderedFrames + 0.3 * encodedFrames) /
143
- composition.durationInFrames) *
144
- 100) / 100,
143
+ progress: Math.round((70 * renderedFrames + 15 * encodedFrames + 15 * muxedFrames) /
144
+ composition.durationInFrames) / 100,
145
145
  });
146
146
  };
147
147
  const realFrameRange = (0, get_frame_to_render_1.getRealFrameRange)(composition.durationInFrames, frameRange);
@@ -324,7 +324,12 @@ const internalRenderMedia = ({ proResProfile, crf, composition, serializedInputP
324
324
  assetsInfo,
325
325
  onProgress: (frame) => {
326
326
  stitchStage = 'muxing';
327
- encodedFrames = frame;
327
+ if (preEncodedFileLocation) {
328
+ muxedFrames = frame;
329
+ }
330
+ else {
331
+ encodedFrames = frame;
332
+ }
328
333
  callUpdate();
329
334
  },
330
335
  onDownload,
@@ -1,62 +1,114 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.seekToFrame = exports.waitForReady = void 0;
4
+ const _1 = require(".");
4
5
  const symbolicateable_error_1 = require("./error-handling/symbolicateable-error");
5
6
  const parse_browser_error_stack_1 = require("./parse-browser-error-stack");
6
7
  const puppeteer_evaluate_1 = require("./puppeteer-evaluate");
7
- const waitForReady = ({ page, timeoutInMilliseconds, frame, }) => Promise.race([
8
- new Promise((_, reject) => {
9
- page.on("disposed" /* PageEmittedEvents.Disposed */, () => {
10
- reject(new Error('Target closed (page disposed)'));
8
+ const waitForReady = ({ page, timeoutInMilliseconds, frame, }) => {
9
+ const waitForReadyProm = new Promise((resolve, reject) => {
10
+ page
11
+ .mainFrame()
12
+ ._mainWorld.waitForFunction({
13
+ browser: page.browser,
14
+ // Increase timeout so the delayRender() timeout fires earlier
15
+ timeout: timeoutInMilliseconds + 3000,
16
+ pageFunction: 'window.remotion_renderReady === true',
17
+ title: frame === null
18
+ ? 'the page to render the React component'
19
+ : `the page to render the React component at frame ${frame}`,
20
+ shouldClosePage: false,
21
+ })
22
+ .then((a) => resolve(a))
23
+ .catch((err) => {
24
+ if (err.message.includes('timeout') &&
25
+ err.message.includes('exceeded')) {
26
+ (0, puppeteer_evaluate_1.puppeteerEvaluateWithCatch)({
27
+ pageFunction: () => {
28
+ return Object.keys(window.remotion_delayRenderTimeouts)
29
+ .map((id, i) => {
30
+ const { label } = window.remotion_delayRenderTimeouts[id];
31
+ if (label === null) {
32
+ return `${i + 1}. (no label)`;
33
+ }
34
+ return `"${i + 1}. ${label}"`;
35
+ })
36
+ .join(', ');
37
+ },
38
+ args: [],
39
+ frame,
40
+ page,
41
+ })
42
+ .then((res) => {
43
+ reject(new Error(`Timeout exceeded rendering the component${frame ? ' at frame ' + frame : ''}. ${res.value ? `Open delayRender() handles: ${res.value}` : ''}`));
44
+ })
45
+ .catch((newErr) => {
46
+ _1.RenderInternals.Log.warn('Tried to get delayRender() handles for timeout, but could not do so because of', newErr);
47
+ // Ignore, use prev error
48
+ reject(err);
49
+ });
50
+ }
51
+ else {
52
+ reject(err);
53
+ }
11
54
  });
12
- }),
13
- new Promise((_, reject) => {
14
- page.browser.on("closed-silent" /* BrowserEmittedEvents.ClosedSilent */, () => {
15
- reject(new Error('Target closed'));
16
- });
17
- }),
18
- page
19
- .mainFrame()
20
- ._mainWorld.waitForFunction({
21
- browser: page.browser,
22
- timeout: timeoutInMilliseconds,
23
- pageFunction: 'window.remotion_renderReady === true',
24
- title: frame === null
25
- ? 'the page to render the React component'
26
- : `the page to render the React component at frame ${frame}`,
27
- })
28
- .catch((err) => {
29
- throw err;
30
- }),
31
- page
32
- .mainFrame()
33
- ._mainWorld.waitForFunction({
34
- browser: page.browser,
35
- timeout: timeoutInMilliseconds,
36
- pageFunction: 'window.remotion_cancelledError !== undefined',
37
- title: 'remotion_cancelledError variable to appear on the page',
38
- })
39
- .then(() => {
40
- return (0, puppeteer_evaluate_1.puppeteerEvaluateWithCatch)({
41
- pageFunction: () => window.remotion_cancelledError,
42
- args: [],
43
- frame: null,
44
- page,
45
- });
46
- })
47
- .then(({ value: val }) => {
48
- if (typeof val !== 'string') {
49
- throw val;
50
- }
51
- throw new symbolicateable_error_1.SymbolicateableError({
52
- frame: null,
53
- stack: val,
54
- name: 'CancelledError',
55
- message: val.split('\n')[0],
56
- stackFrame: (0, parse_browser_error_stack_1.parseStack)(val.split('\n')),
55
+ });
56
+ const waitForErrorProm = new Promise((_shouldNeverResolve, reject) => {
57
+ page
58
+ .mainFrame()
59
+ ._mainWorld.waitForFunction({
60
+ browser: page.browser,
61
+ timeout: null,
62
+ pageFunction: 'window.remotion_cancelledError !== undefined',
63
+ title: 'remotion_cancelledError variable to appear on the page',
64
+ shouldClosePage: false,
65
+ })
66
+ .then(() => {
67
+ return (0, puppeteer_evaluate_1.puppeteerEvaluateWithCatch)({
68
+ pageFunction: () => window.remotion_cancelledError,
69
+ args: [],
70
+ frame: null,
71
+ page,
72
+ });
73
+ })
74
+ .then(({ value: val }) => {
75
+ if (typeof val !== 'string') {
76
+ reject(val);
77
+ return;
78
+ }
79
+ reject(new symbolicateable_error_1.SymbolicateableError({
80
+ frame: null,
81
+ stack: val,
82
+ name: 'CancelledError',
83
+ message: val.split('\n')[0],
84
+ stackFrame: (0, parse_browser_error_stack_1.parseStack)(val.split('\n')),
85
+ }));
86
+ })
87
+ .catch((err) => {
88
+ if (err.message.includes('timeout') &&
89
+ err.message.includes('exceeded')) {
90
+ // Don't care if a error never appeared
91
+ }
92
+ else {
93
+ reject(err);
94
+ }
57
95
  });
58
- }),
59
- ]);
96
+ });
97
+ return Promise.race([
98
+ new Promise((_, reject) => {
99
+ page.on("disposed" /* PageEmittedEvents.Disposed */, () => {
100
+ reject(new Error('Target closed (page disposed)'));
101
+ });
102
+ }),
103
+ new Promise((_, reject) => {
104
+ page.browser.on("closed-silent" /* BrowserEmittedEvents.ClosedSilent */, () => {
105
+ reject(new Error('Target closed'));
106
+ });
107
+ }),
108
+ waitForReadyProm,
109
+ waitForErrorProm,
110
+ ]);
111
+ };
60
112
  exports.waitForReady = waitForReady;
61
113
  const seekToFrame = async ({ frame, page, composition, timeoutInMilliseconds, }) => {
62
114
  await (0, exports.waitForReady)({ page, timeoutInMilliseconds, frame: null });
@@ -67,7 +67,13 @@ const serveStatic = async (path, options) => {
67
67
  };
68
68
  const close = async () => {
69
69
  await Promise.all([
70
- closeCompositor(),
70
+ new Promise((resolve) => {
71
+ // compositor may have already quit before,
72
+ // this is okay as we are in cleanup phase
73
+ closeCompositor().finally(() => {
74
+ resolve();
75
+ });
76
+ }),
71
77
  new Promise((resolve, reject) => {
72
78
  destroyConnections();
73
79
  server.close((err) => {
@@ -110,7 +110,7 @@ const innerSetPropsAndEnv = async ({ serializedInputPropsWithCustomSchema, envVa
110
110
  frame: null,
111
111
  page,
112
112
  });
113
- const requiredVersion = '8';
113
+ const requiredVersion = '9';
114
114
  if (siteVersion !== requiredVersion) {
115
115
  throw new Error([
116
116
  `Incompatible site: When visiting ${urlToVisit}, a bundle was found, but one that is not compatible with this version of Remotion. Found version: ${siteVersion} - Required version: ${requiredVersion}. To resolve this error:`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remotion/renderer",
3
- "version": "4.0.10",
3
+ "version": "4.0.11",
4
4
  "description": "Renderer for Remotion",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -18,7 +18,7 @@
18
18
  "extract-zip": "2.0.1",
19
19
  "source-map": "^0.8.0-beta.0",
20
20
  "ws": "8.7.0",
21
- "remotion": "4.0.10"
21
+ "remotion": "4.0.11"
22
22
  },
23
23
  "peerDependencies": {
24
24
  "react": ">=16.8.0",
@@ -42,13 +42,13 @@
42
42
  "zod": "^3.21.4"
43
43
  },
44
44
  "optionalDependencies": {
45
- "@remotion/compositor-darwin-arm64": "4.0.10",
46
- "@remotion/compositor-linux-arm64-musl": "4.0.10",
47
- "@remotion/compositor-linux-arm64-gnu": "4.0.10",
48
- "@remotion/compositor-linux-x64-gnu": "4.0.10",
49
- "@remotion/compositor-linux-x64-musl": "4.0.10",
50
- "@remotion/compositor-win32-x64-msvc": "4.0.10",
51
- "@remotion/compositor-darwin-x64": "4.0.10"
45
+ "@remotion/compositor-linux-arm64-musl": "4.0.11",
46
+ "@remotion/compositor-darwin-arm64": "4.0.11",
47
+ "@remotion/compositor-linux-x64-gnu": "4.0.11",
48
+ "@remotion/compositor-linux-arm64-gnu": "4.0.11",
49
+ "@remotion/compositor-darwin-x64": "4.0.11",
50
+ "@remotion/compositor-linux-x64-musl": "4.0.11",
51
+ "@remotion/compositor-win32-x64-msvc": "4.0.11"
52
52
  },
53
53
  "keywords": [
54
54
  "remotion",
@@ -1,6 +0,0 @@
1
- import type { SerializedJSONWithCustomFields } from 'remotion';
2
- export declare const serializeJSONWithDate: ({ data, indent, staticBase, }: {
3
- data: Record<string, unknown>;
4
- indent: number | undefined;
5
- staticBase: string | null;
6
- }) => SerializedJSONWithCustomFields;
@@ -1,36 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.serializeJSONWithDate = void 0;
4
- // Keep in sync with /packages/core/src/input-props-serialization.ts
5
- const DATE_TOKEN = 'remotion-date:';
6
- const FILE_TOKEN = 'remotion-file:';
7
- const serializeJSONWithDate = ({ data, indent, staticBase, }) => {
8
- let customDateUsed = false;
9
- let customFileUsed = false;
10
- let mapUsed = false;
11
- let setUsed = false;
12
- const serializedString = JSON.stringify(data, function (key, value) {
13
- const item = this[key];
14
- if (item instanceof Date) {
15
- customDateUsed = true;
16
- return `${DATE_TOKEN}${item.toISOString()}`;
17
- }
18
- if (item instanceof Map) {
19
- mapUsed = true;
20
- return value;
21
- }
22
- if (item instanceof Set) {
23
- setUsed = true;
24
- return value;
25
- }
26
- if (typeof item === 'string' &&
27
- staticBase !== null &&
28
- item.startsWith(staticBase)) {
29
- customFileUsed = true;
30
- return `${FILE_TOKEN}${item.replace(staticBase + '/', '')}`;
31
- }
32
- return value;
33
- }, indent);
34
- return { serializedString, customDateUsed, customFileUsed, mapUsed, setUsed };
35
- };
36
- exports.serializeJSONWithDate = serializeJSONWithDate;