@remotion/renderer 3.2.29 → 3.2.30

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.
@@ -0,0 +1 @@
1
+ export declare const downloadBrowser: (url: string) => Promise<void>;
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.downloadBrowser = void 0;
4
+ const listeners = {};
5
+ const isDownloading = {};
6
+ const waitForFfmpegToBeDownloaded = (url) => {
7
+ return new Promise((resolve) => {
8
+ if (!listeners[url]) {
9
+ listeners[url] = [];
10
+ }
11
+ listeners[url].push(resolve);
12
+ });
13
+ };
14
+ const downloadBrowser = async (url) => {
15
+ if (isDownloading[url]) {
16
+ console.log('WAITING');
17
+ return waitForFfmpegToBeDownloaded(url);
18
+ }
19
+ isDownloading[url] = true;
20
+ await new Promise((resolve) => {
21
+ console.log('DOWNLOADING BROWSER');
22
+ setTimeout(resolve, 20000);
23
+ });
24
+ isDownloading[url] = false;
25
+ if (!listeners[url]) {
26
+ listeners[url] = [];
27
+ }
28
+ listeners[url].forEach((listener) => listener());
29
+ listeners[url] = [];
30
+ };
31
+ exports.downloadBrowser = downloadBrowser;
32
+ (0, exports.downloadBrowser)('https://remotion.dev').then(() => {
33
+ (0, exports.downloadBrowser)('https://remotion.dev').then(() => {
34
+ (0, exports.downloadBrowser)('https://remotion.dev').then(() => console.log('FINISHED DOWNLOADING'));
35
+ (0, exports.downloadBrowser)('https://remotion.dev').then(() => console.log('FINISHED DOWNLOADING'));
36
+ (0, exports.downloadBrowser)('https://remotion.dev').then(() => console.log('FINISHED DOWNLOADING'));
37
+ });
38
+ });
package/dist/index.d.ts CHANGED
@@ -25,7 +25,7 @@ export type { ChromiumOptions } from './open-browser';
25
25
  export { PixelFormat } from './pixel-format';
26
26
  export { ProResProfile } from './prores-profile';
27
27
  export { renderFrames } from './render-frames';
28
- export { renderMedia, RenderMediaOnProgress, RenderMediaOptions, StitchingState, } from './render-media';
28
+ export { OnSlowestFrames, renderMedia, RenderMediaOnProgress, RenderMediaOptions, SlowFrame, StitchingState, } from './render-media';
29
29
  export { renderStill, RenderStillOptions } from './render-still';
30
30
  export { StitcherOptions, stitchFramesToVideo } from './stitch-frames-to-video';
31
31
  export { SymbolicatedStackFrame } from './symbolicate-stacktrace';
@@ -30,7 +30,7 @@ declare type ConcurrencyOrParallelism = {
30
30
  };
31
31
  declare type RenderFramesOptions = {
32
32
  onStart: (data: OnStartData) => void;
33
- onFrameUpdate: (framesRendered: number, frameIndex: number) => void;
33
+ onFrameUpdate: (framesRendered: number, frameIndex: number, timeToRenderInMilliseconds: number) => void;
34
34
  outputDir: string | null;
35
35
  inputProps: unknown;
36
36
  envVariables?: Record<string, string>;
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.renderFrames = void 0;
7
7
  const fs_1 = __importDefault(require("fs"));
8
8
  const path_1 = __importDefault(require("path"));
9
+ const perf_hooks_1 = require("perf_hooks");
9
10
  const remotion_1 = require("remotion");
10
11
  const download_and_map_assets_to_file_1 = require("./assets/download-and-map-assets-to-file");
11
12
  const download_map_1 = require("./assets/download-map");
@@ -150,6 +151,7 @@ const innerRenderFrames = ({ onFrameUpdate, outputDir, onStart, inputProps, qual
150
151
  if (stopped) {
151
152
  throw new Error('Render was stopped');
152
153
  }
154
+ const startTime = perf_hooks_1.performance.now();
153
155
  const errorCallbackOnFrame = (err) => {
154
156
  onError(err);
155
157
  };
@@ -219,7 +221,7 @@ const innerRenderFrames = ({ onFrameUpdate, outputDir, onStart, inputProps, qual
219
221
  });
220
222
  pool.release(freePage);
221
223
  framesRendered++;
222
- onFrameUpdate(framesRendered, frame);
224
+ onFrameUpdate(framesRendered, frame, perf_hooks_1.performance.now() - startTime);
223
225
  cleanupPageError();
224
226
  freePage.off('error', errorCallbackOnFrame);
225
227
  return compressedAssets;
@@ -16,6 +16,11 @@ import type { PixelFormat } from './pixel-format';
16
16
  import type { ProResProfile } from './prores-profile';
17
17
  import type { OnStartData } from './types';
18
18
  export declare type StitchingState = 'encoding' | 'muxing';
19
+ export declare type SlowFrame = {
20
+ frame: number;
21
+ time: number;
22
+ };
23
+ export declare type OnSlowestFrames = (frames: SlowFrame[]) => void;
19
24
  export declare type RenderMediaOnProgress = (progress: {
20
25
  renderedFrames: number;
21
26
  encodedFrames: number;
@@ -61,6 +66,7 @@ export declare type RenderMediaOptions = {
61
66
  muted?: boolean;
62
67
  enforceAudioTrack?: boolean;
63
68
  ffmpegOverride?: FfmpegOverrideFn;
69
+ onSlowestFrames?: OnSlowestFrames;
64
70
  disallowParallelEncoding?: boolean;
65
71
  } & ServeUrlOrWebpackBundle & ConcurrencyOrParallelism;
66
72
  declare type ConcurrencyOrParallelism = {
@@ -76,5 +82,5 @@ declare type ConcurrencyOrParallelism = {
76
82
  * @description Render a video from a composition
77
83
  * @link https://www.remotion.dev/docs/renderer/render-media
78
84
  */
79
- export declare const renderMedia: ({ proResProfile, crf, composition, ffmpegExecutable, ffprobeExecutable, inputProps, pixelFormat, codec, envVariables, frameRange, puppeteerInstance, outputLocation, onProgress, overwrite, onDownload, dumpBrowserLogs, onBrowserLog, onStart, timeoutInMilliseconds, chromiumOptions, scale, browserExecutable, port, cancelSignal, muted, enforceAudioTrack, ffmpegOverride, ...options }: RenderMediaOptions) => Promise<Buffer | null>;
85
+ export declare const renderMedia: ({ proResProfile, crf, composition, ffmpegExecutable, ffprobeExecutable, inputProps, pixelFormat, codec, envVariables, frameRange, puppeteerInstance, outputLocation, onProgress, overwrite, onDownload, dumpBrowserLogs, onBrowserLog, onStart, timeoutInMilliseconds, chromiumOptions, scale, browserExecutable, port, cancelSignal, muted, enforceAudioTrack, ffmpegOverride, onSlowestFrames, ...options }: RenderMediaOptions) => Promise<Buffer | null>;
80
86
  export {};
@@ -33,6 +33,7 @@ const validate_even_dimensions_with_codec_1 = require("./validate-even-dimension
33
33
  const validate_ffmpeg_override_1 = require("./validate-ffmpeg-override");
34
34
  const validate_output_filename_1 = require("./validate-output-filename");
35
35
  const validate_scale_1 = require("./validate-scale");
36
+ const SLOWEST_FRAME_COUNT = 10;
36
37
  const getConcurrency = (others) => {
37
38
  if ('concurrency' in others) {
38
39
  return others.concurrency;
@@ -47,7 +48,7 @@ const getConcurrency = (others) => {
47
48
  * @description Render a video from a composition
48
49
  * @link https://www.remotion.dev/docs/renderer/render-media
49
50
  */
50
- const renderMedia = ({ proResProfile, crf, composition, ffmpegExecutable, ffprobeExecutable, inputProps, pixelFormat, codec, envVariables, frameRange, puppeteerInstance, outputLocation, onProgress, overwrite, onDownload, dumpBrowserLogs, onBrowserLog, onStart, timeoutInMilliseconds, chromiumOptions, scale, browserExecutable, port, cancelSignal, muted, enforceAudioTrack, ffmpegOverride, ...options }) => {
51
+ const renderMedia = ({ proResProfile, crf, composition, ffmpegExecutable, ffprobeExecutable, inputProps, pixelFormat, codec, envVariables, frameRange, puppeteerInstance, outputLocation, onProgress, overwrite, onDownload, dumpBrowserLogs, onBrowserLog, onStart, timeoutInMilliseconds, chromiumOptions, scale, browserExecutable, port, cancelSignal, muted, enforceAudioTrack, ffmpegOverride, onSlowestFrames, ...options }) => {
51
52
  var _a, _b, _c, _d;
52
53
  (0, quality_1.validateQuality)(options.quality);
53
54
  if (typeof crf !== 'undefined' && crf !== null) {
@@ -171,13 +172,38 @@ const renderMedia = ({ proResProfile, crf, composition, ffmpegExecutable, ffprob
171
172
  };
172
173
  const mediaSupport = (0, codec_supports_media_1.codecSupportsMedia)(codec);
173
174
  const disableAudio = !mediaSupport.audio || muted;
175
+ const slowestFrames = [];
176
+ let maxTime = 0;
177
+ let minTime = 0;
178
+ const recordFrameTime = (frameIndex, time) => {
179
+ var _a, _b;
180
+ const frameTime = { frame: frameIndex, time };
181
+ if (time < minTime && slowestFrames.length === SLOWEST_FRAME_COUNT) {
182
+ return;
183
+ }
184
+ if (time > maxTime) {
185
+ // add at starting;
186
+ slowestFrames.unshift(frameTime);
187
+ maxTime = time;
188
+ }
189
+ else {
190
+ // add frame at appropriate position
191
+ const index = slowestFrames.findIndex(({ time: indexTime }) => indexTime < time);
192
+ slowestFrames.splice(index, 0, frameTime);
193
+ }
194
+ if (slowestFrames.length > SLOWEST_FRAME_COUNT) {
195
+ slowestFrames.pop();
196
+ }
197
+ minTime = (_b = (_a = slowestFrames[slowestFrames.length - 1]) === null || _a === void 0 ? void 0 : _a.time) !== null && _b !== void 0 ? _b : minTime;
198
+ };
174
199
  const happyPath = createPrestitcherIfNecessary()
175
200
  .then(() => {
176
201
  const renderFramesProc = (0, render_frames_1.renderFrames)({
177
202
  config: composition,
178
- onFrameUpdate: (frame) => {
203
+ onFrameUpdate: (frame, frameIndex, timeToRenderInMilliseconds) => {
179
204
  renderedFrames = frame;
180
205
  callUpdate();
206
+ recordFrameTime(frameIndex, timeToRenderInMilliseconds);
181
207
  },
182
208
  concurrency,
183
209
  outputDir,
@@ -272,6 +298,8 @@ const renderMedia = ({ proResProfile, crf, composition, ffmpegExecutable, ffprob
272
298
  encodedFrames = (0, get_duration_from_frame_range_1.getFramesToRender)(realFrameRange, everyNthFrame).length;
273
299
  encodedDoneIn = Date.now() - stitchStart;
274
300
  callUpdate();
301
+ slowestFrames.sort((a, b) => b.time - a.time);
302
+ onSlowestFrames === null || onSlowestFrames === void 0 ? void 0 : onSlowestFrames(slowestFrames);
275
303
  return buffer;
276
304
  })
277
305
  .catch((err) => {
@@ -8,7 +8,7 @@ const validatePuppeteerTimeout = (timeoutInMilliseconds) => {
8
8
  if (typeof timeoutInMilliseconds !== 'number') {
9
9
  throw new TypeError(`'timeoutInMilliseconds' should be a number, but is: ${JSON.stringify(timeoutInMilliseconds)}`);
10
10
  }
11
- if (timeoutInMilliseconds < 7000) {
11
+ if (timeoutInMilliseconds < 7000 && process.env.NODE_ENV !== 'test') {
12
12
  throw new TypeError(`'timeoutInMilliseconds' should be bigger or equal than 7000, but is ${timeoutInMilliseconds}`);
13
13
  }
14
14
  if (Number.isNaN(timeoutInMilliseconds)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remotion/renderer",
3
- "version": "3.2.29",
3
+ "version": "3.2.30",
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.29",
25
+ "remotion": "3.2.30",
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": "9a2ff4d68324af8d1fe55ebdf94bdadccf446a10"
60
+ "gitHead": "5dc5f4c010c47186c7911b575998296d6a65f7cb"
61
61
  }
@@ -1,4 +0,0 @@
1
- export declare type FfmpegArgsHook = (info: {
2
- type: 'pre-stitcher' | 'stitcher';
3
- args: string[];
4
- }) => string[];
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
@@ -1 +0,0 @@
1
- export declare const makeAssetsDownloadTmpDir: () => string;
@@ -1,13 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.makeAssetsDownloadTmpDir = void 0;
4
- const tmp_dir_1 = require("./tmp-dir");
5
- let dir = null;
6
- const makeAssetsDownloadTmpDir = () => {
7
- if (dir) {
8
- return dir;
9
- }
10
- dir = (0, tmp_dir_1.tmpDir)('remotion-assets-dir');
11
- return dir;
12
- };
13
- exports.makeAssetsDownloadTmpDir = makeAssetsDownloadTmpDir;
@@ -1,2 +0,0 @@
1
- import type { FfmpegOverrideFn } from './ffmpeg-override';
2
- export declare const validateFfmpegArgsHook: (ffmpegArgsHook?: FfmpegOverrideFn) => void;
@@ -1,12 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.validateFfmpegArgsHook = void 0;
4
- const validateFfmpegArgsHook = (ffmpegArgsHook) => {
5
- if (typeof ffmpegArgsHook === 'undefined') {
6
- return;
7
- }
8
- if (ffmpegArgsHook && typeof ffmpegArgsHook !== 'function') {
9
- throw new TypeError(`Argument passed for "ffmpegArgsHook" is not a function: ${ffmpegArgsHook}`);
10
- }
11
- };
12
- exports.validateFfmpegArgsHook = validateFfmpegArgsHook;
@@ -1,2 +0,0 @@
1
- import type { FfmpegOverrideFn } from './ffmpeg-override';
2
- export declare const validateFfmpegOverride: (ffmpegArgsHook?: FfmpegOverrideFn) => void;
@@ -1,12 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.validateFfmpegOverride = void 0;
4
- const validateFfmpegOverride = (ffmpegArgsHook) => {
5
- if (typeof ffmpegArgsHook === 'undefined') {
6
- return;
7
- }
8
- if (ffmpegArgsHook && typeof ffmpegArgsHook !== 'function') {
9
- throw new TypeError(`Argument passed for "ffmpegArgsHook" is not a function: ${ffmpegArgsHook}`);
10
- }
11
- };
12
- exports.validateFfmpegOverride = validateFfmpegOverride;