@remotion/renderer 3.2.39 → 3.2.41

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.
package/LICENSE.md CHANGED
@@ -36,6 +36,6 @@ Support is provided on a best-we-can-do basis via GitHub Issues and Discord.
36
36
 
37
37
  ## Company license
38
38
 
39
- You are required to obtain a company license to use Remotion if you are not within the group of entities eligible for a free license. This license will enable you to use Remotion for the allowed use cases specified in the free license, and give you access to prioritized support.
39
+ You are required to obtain a company license to use Remotion if you are not within the group of entities eligible for a free license. This license will enable you to use Remotion for the allowed use cases specified in the free license, and give you access to prioritized support (read the [Support Policy](/docs/support)).
40
40
 
41
41
  Visit [companies.remotion.dev](https://companies.remotion.dev) for pricing and to buy a license.
@@ -3,5 +3,5 @@ export declare const validImageFormats: readonly ["png", "jpeg", "none"];
3
3
  export declare type ImageFormat = typeof validImageFormats[number];
4
4
  export declare type StillImageFormat = 'png' | 'jpeg';
5
5
  export declare const DEFAULT_IMAGE_FORMAT: ImageFormat;
6
- export declare const validateSelectedPixelFormatAndImageFormatCombination: (pixelFormat: PixelFormat, imageFormat: ImageFormat) => 'none' | 'valid';
6
+ export declare const validateSelectedPixelFormatAndImageFormatCombination: (pixelFormat: PixelFormat | undefined, imageFormat: ImageFormat) => 'none' | 'valid';
7
7
  export declare const validateNonNullImageFormat: (imageFormat: ImageFormat) => void;
@@ -11,6 +11,9 @@ const validateSelectedPixelFormatAndImageFormatCombination = (pixelFormat, image
11
11
  if (imageFormat === 'none') {
12
12
  return 'none';
13
13
  }
14
+ if (typeof pixelFormat === 'undefined') {
15
+ return 'valid';
16
+ }
14
17
  if (!exports.validImageFormats.includes(imageFormat)) {
15
18
  throw new TypeError(`Value ${imageFormat} is not valid as an image format.`);
16
19
  }
package/dist/index.d.ts CHANGED
@@ -40,7 +40,6 @@ export declare const RenderInternals: {
40
40
  }) => Promise<boolean>;
41
41
  getActualConcurrency: (userPreference: number | null) => number;
42
42
  validateFfmpeg: (customFfmpegBinary: string | null) => Promise<void>;
43
- binaryExists: (name: "ffmpeg" | "brew", localFFmpeg: string | null) => boolean;
44
43
  serveStatic: (path: string | null, options: {
45
44
  port: number | null;
46
45
  ffmpegExecutable: import("./ffmpeg-executable").FfmpegExecutable;
@@ -58,11 +57,6 @@ export declare const RenderInternals: {
58
57
  scale: number;
59
58
  codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif";
60
59
  }) => void;
61
- normalizeServeUrl: (unnormalized: string) => string;
62
- spawnFfmpeg: (options: import("./stitch-frames-to-video").StitcherOptions) => Promise<{
63
- task: Promise<Buffer | null>;
64
- getLogs: () => string;
65
- }>;
66
60
  getFileExtensionFromCodec: (codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif", type: "chunk" | "final") => "mp3" | "aac" | "wav" | "gif" | "webm" | "mp4" | "mov" | "mkv";
67
61
  tmpDir: (str: string) => string;
68
62
  deleteDirectory: (directory: string) => Promise<void>;
@@ -82,7 +76,6 @@ export declare const RenderInternals: {
82
76
  sizeInBytes: number;
83
77
  to: string;
84
78
  }>;
85
- validateScale: (scale: unknown) => void;
86
79
  killAllBrowsers: () => Promise<void>;
87
80
  parseStack: (stack: string[]) => import("./parse-browser-error-stack").UnsymbolicatedStackFrame[];
88
81
  symbolicateError: (symbolicateableError: SymbolicateableError) => Promise<import("./error-handling/handle-javascript-exception").ErrorWithStackFrame>;
@@ -120,30 +113,17 @@ export declare const RenderInternals: {
120
113
  validateFrameRange: (frameRange: import("./frame-range").FrameRange | null) => void;
121
114
  DEFAULT_OPENGL_RENDERER: "angle" | "swangle" | "egl" | "swiftshader" | null;
122
115
  validateOpenGlRenderer: (option: "angle" | "swangle" | "egl" | "swiftshader" | null) => "angle" | "swangle" | "egl" | "swiftshader" | null;
123
- validateQualitySettings: ({ codec, crf, videoBitrate, }: {
124
- crf: unknown;
125
- codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif";
126
- videoBitrate: string | null | undefined;
127
- }) => string[];
128
116
  validImageFormats: readonly ["png", "jpeg", "none"];
129
117
  validCodecs: readonly ["h264", "h265", "vp8", "vp9", "mp3", "aac", "wav", "prores", "h264-mkv", "gif"];
130
118
  DEFAULT_PIXEL_FORMAT: "yuv420p" | "yuva420p" | "yuv422p" | "yuv444p" | "yuv420p10le" | "yuv422p10le" | "yuv444p10le" | "yuva444p10le";
131
119
  validateQuality: (q: number | undefined) => void;
132
120
  validateFrame: (frame: number, durationInFrames: number) => void;
133
121
  DEFAULT_TIMEOUT: number;
134
- getValidCrfRanges: (codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif") => [number, number];
135
- validateSelectedPixelFormatAndCodecCombination: (pixelFormat: "yuv420p" | "yuva420p" | "yuv422p" | "yuv444p" | "yuv420p10le" | "yuv422p10le" | "yuv444p10le" | "yuva444p10le", codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif") => void;
136
- validateSelectedCodecAndProResCombination: ({ codec, proResProfile, }: {
137
- codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif";
138
- proResProfile: "proxy" | "4444-xq" | "4444" | "hq" | "standard" | "light" | undefined;
139
- }) => void;
140
- validateSelectedPixelFormatAndImageFormatCombination: (pixelFormat: "yuv420p" | "yuva420p" | "yuv422p" | "yuv444p" | "yuv420p10le" | "yuv422p10le" | "yuv444p10le" | "yuva444p10le", imageFormat: "jpeg" | "png" | "none") => "none" | "valid";
141
122
  DEFAULT_CODEC: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif";
142
123
  isAudioCodec: (codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif" | undefined) => boolean;
143
124
  logLevels: readonly ["verbose", "info", "warn", "error"];
144
125
  isEqualOrBelowLogLevel: (currentLevel: "error" | "verbose" | "info" | "warn", level: "error" | "verbose" | "info" | "warn") => boolean;
145
126
  isValidLogLevel: (level: string) => boolean;
146
- validateEveryNthFrame: (everyNthFrame: unknown) => void;
147
127
  perf: typeof perf;
148
128
  makeDownloadMap: () => import("./assets/download-map").DownloadMap;
149
129
  cleanDownloadMap: (downloadMap: import("./assets/download-map").DownloadMap) => Promise<void>;
package/dist/index.js CHANGED
@@ -36,7 +36,6 @@ const can_use_parallel_encoding_1 = require("./can-use-parallel-encoding");
36
36
  const check_apple_silicon_1 = require("./check-apple-silicon");
37
37
  const codec_1 = require("./codec");
38
38
  const convert_to_positive_frame_index_1 = require("./convert-to-positive-frame-index");
39
- const crf_1 = require("./crf");
40
39
  const delete_directory_1 = require("./delete-directory");
41
40
  const ensure_output_directory_1 = require("./ensure-output-directory");
42
41
  const symbolicate_error_1 = require("./error-handling/symbolicate-error");
@@ -55,25 +54,20 @@ const is_audio_codec_1 = require("./is-audio-codec");
55
54
  const is_serve_url_1 = require("./is-serve-url");
56
55
  const log_level_1 = require("./log-level");
57
56
  const mime_types_1 = require("./mime-types");
58
- const normalize_serve_url_1 = require("./normalize-serve-url");
59
57
  const open_browser_1 = require("./open-browser");
60
58
  const parse_browser_error_stack_1 = require("./parse-browser-error-stack");
61
59
  const perf = __importStar(require("./perf"));
62
60
  const pixel_format_1 = require("./pixel-format");
63
- const prores_profile_1 = require("./prores-profile");
64
61
  const quality_1 = require("./quality");
65
62
  const is_path_inside_1 = require("./serve-handler/is-path-inside");
66
63
  const serve_static_1 = require("./serve-static");
67
- const stitch_frames_to_video_1 = require("./stitch-frames-to-video");
68
64
  const tmp_dir_1 = require("./tmp-dir");
69
65
  const validate_concurrency_1 = require("./validate-concurrency");
70
66
  const validate_even_dimensions_with_codec_1 = require("./validate-even-dimensions-with-codec");
71
- const validate_every_nth_frame_1 = require("./validate-every-nth-frame");
72
67
  const validate_ffmpeg_1 = require("./validate-ffmpeg");
73
68
  const validate_frame_1 = require("./validate-frame");
74
69
  const validate_opengl_renderer_1 = require("./validate-opengl-renderer");
75
70
  const validate_puppeteer_timeout_1 = require("./validate-puppeteer-timeout");
76
- const validate_scale_1 = require("./validate-scale");
77
71
  const validate_videobitrate_1 = require("./validate-videobitrate");
78
72
  const wait_for_symbolication_error_to_be_done_1 = require("./wait-for-symbolication-error-to-be-done");
79
73
  var combine_videos_1 = require("./combine-videos");
@@ -95,8 +89,8 @@ var render_media_1 = require("./render-media");
95
89
  Object.defineProperty(exports, "renderMedia", { enumerable: true, get: function () { return render_media_1.renderMedia; } });
96
90
  var render_still_1 = require("./render-still");
97
91
  Object.defineProperty(exports, "renderStill", { enumerable: true, get: function () { return render_still_1.renderStill; } });
98
- var stitch_frames_to_video_2 = require("./stitch-frames-to-video");
99
- Object.defineProperty(exports, "stitchFramesToVideo", { enumerable: true, get: function () { return stitch_frames_to_video_2.stitchFramesToVideo; } });
92
+ var stitch_frames_to_video_1 = require("./stitch-frames-to-video");
93
+ Object.defineProperty(exports, "stitchFramesToVideo", { enumerable: true, get: function () { return stitch_frames_to_video_1.stitchFramesToVideo; } });
100
94
  var validate_output_filename_1 = require("./validate-output-filename");
101
95
  Object.defineProperty(exports, "validateOutputFilename", { enumerable: true, get: function () { return validate_output_filename_1.validateOutputFilename; } });
102
96
  exports.RenderInternals = {
@@ -104,11 +98,8 @@ exports.RenderInternals = {
104
98
  ffmpegHasFeature: ffmpeg_flags_1.ffmpegHasFeature,
105
99
  getActualConcurrency: get_concurrency_1.getActualConcurrency,
106
100
  validateFfmpeg: validate_ffmpeg_1.validateFfmpeg,
107
- binaryExists: validate_ffmpeg_1.binaryExists,
108
101
  serveStatic: serve_static_1.serveStatic,
109
102
  validateEvenDimensionsWithCodec: validate_even_dimensions_with_codec_1.validateEvenDimensionsWithCodec,
110
- normalizeServeUrl: normalize_serve_url_1.normalizeServeUrl,
111
- spawnFfmpeg: stitch_frames_to_video_1.spawnFfmpeg,
112
103
  getFileExtensionFromCodec: get_extension_from_codec_1.getFileExtensionFromCodec,
113
104
  tmpDir: tmp_dir_1.tmpDir,
114
105
  deleteDirectory: delete_directory_1.deleteDirectory,
@@ -117,7 +108,6 @@ exports.RenderInternals = {
117
108
  getRealFrameRange: get_frame_to_render_1.getRealFrameRange,
118
109
  validatePuppeteerTimeout: validate_puppeteer_timeout_1.validatePuppeteerTimeout,
119
110
  downloadFile: download_file_1.downloadFile,
120
- validateScale: validate_scale_1.validateScale,
121
111
  killAllBrowsers: open_browser_1.killAllBrowsers,
122
112
  parseStack: parse_browser_error_stack_1.parseStack,
123
113
  symbolicateError: symbolicate_error_1.symbolicateError,
@@ -138,23 +128,17 @@ exports.RenderInternals = {
138
128
  validateFrameRange: frame_range_1.validateFrameRange,
139
129
  DEFAULT_OPENGL_RENDERER: validate_opengl_renderer_1.DEFAULT_OPENGL_RENDERER,
140
130
  validateOpenGlRenderer: validate_opengl_renderer_1.validateOpenGlRenderer,
141
- validateQualitySettings: crf_1.validateQualitySettings,
142
131
  validImageFormats: image_format_1.validImageFormats,
143
132
  validCodecs: codec_1.validCodecs,
144
133
  DEFAULT_PIXEL_FORMAT: pixel_format_1.DEFAULT_PIXEL_FORMAT,
145
134
  validateQuality: quality_1.validateQuality,
146
135
  validateFrame: validate_frame_1.validateFrame,
147
136
  DEFAULT_TIMEOUT: TimeoutSettings_1.DEFAULT_TIMEOUT,
148
- getValidCrfRanges: crf_1.getValidCrfRanges,
149
- validateSelectedPixelFormatAndCodecCombination: pixel_format_1.validateSelectedPixelFormatAndCodecCombination,
150
- validateSelectedCodecAndProResCombination: prores_profile_1.validateSelectedCodecAndProResCombination,
151
- validateSelectedPixelFormatAndImageFormatCombination: image_format_1.validateSelectedPixelFormatAndImageFormatCombination,
152
137
  DEFAULT_CODEC: codec_1.DEFAULT_CODEC,
153
138
  isAudioCodec: is_audio_codec_1.isAudioCodec,
154
139
  logLevels: log_level_1.logLevels,
155
140
  isEqualOrBelowLogLevel: log_level_1.isEqualOrBelowLogLevel,
156
141
  isValidLogLevel: log_level_1.isValidLogLevel,
157
- validateEveryNthFrame: validate_every_nth_frame_1.validateEveryNthFrame,
158
142
  perf,
159
143
  makeDownloadMap: download_map_1.makeDownloadMap,
160
144
  cleanDownloadMap: download_map_1.cleanDownloadMap,
@@ -2,4 +2,4 @@ import type { Codec } from './codec';
2
2
  export declare const validPixelFormats: readonly ["yuv420p", "yuva420p", "yuv422p", "yuv444p", "yuv420p10le", "yuv422p10le", "yuv444p10le", "yuva444p10le"];
3
3
  export declare type PixelFormat = typeof validPixelFormats[number];
4
4
  export declare const DEFAULT_PIXEL_FORMAT: PixelFormat;
5
- export declare const validateSelectedPixelFormatAndCodecCombination: (pixelFormat: PixelFormat, codec: Codec) => void;
5
+ export declare const validateSelectedPixelFormatAndCodecCombination: (pixelFormat: PixelFormat | undefined, codec: Codec) => undefined;
@@ -13,6 +13,9 @@ exports.validPixelFormats = [
13
13
  ];
14
14
  exports.DEFAULT_PIXEL_FORMAT = 'yuv420p';
15
15
  const validateSelectedPixelFormatAndCodecCombination = (pixelFormat, codec) => {
16
+ if (typeof pixelFormat === 'undefined') {
17
+ return pixelFormat;
18
+ }
16
19
  if (!exports.validPixelFormats.includes(pixelFormat)) {
17
20
  throw new TypeError(`Value ${pixelFormat} is not valid as a pixel format.`);
18
21
  }
@@ -31,6 +31,7 @@ const seek_to_frame_1 = require("./seek-to-frame");
31
31
  const set_props_and_env_1 = require("./set-props-and-env");
32
32
  const truthy_1 = require("./truthy");
33
33
  const validate_scale_1 = require("./validate-scale");
34
+ const MAX_RETRIES_PER_FRAME = 1;
34
35
  const getComposition = (others) => {
35
36
  if ('composition' in others) {
36
37
  return others.composition;
@@ -69,7 +70,7 @@ const innerRenderFrames = ({ onFrameUpdate, outputDir, onStart, inputProps, qual
69
70
  const realFrameRange = (0, get_frame_to_render_1.getRealFrameRange)(composition.durationInFrames, frameRange !== null && frameRange !== void 0 ? frameRange : null);
70
71
  const framesToRender = (0, get_duration_from_frame_range_1.getFramesToRender)(realFrameRange, everyNthFrame);
71
72
  const lastFrame = framesToRender[framesToRender.length - 1];
72
- const pages = new Array(actualConcurrency).fill(true).map(async () => {
73
+ const makePage = async () => {
73
74
  const page = await puppeteerInstance.newPage();
74
75
  pagesArray.push(page);
75
76
  await page.setViewport({
@@ -126,7 +127,8 @@ const innerRenderFrames = ({ onFrameUpdate, outputDir, onStart, inputProps, qual
126
127
  });
127
128
  page.off('console', logCallback);
128
129
  return page;
129
- });
130
+ };
131
+ const pages = new Array(actualConcurrency).fill(true).map(makePage);
130
132
  // If rendering a GIF and skipping frames, we must ensure it starts from 0
131
133
  // and then is consecutive so FFMPEG recognizes the sequence
132
134
  const countType = everyNthFrame === 1 ? 'actual-frames' : 'from-zero';
@@ -145,15 +147,15 @@ const innerRenderFrames = ({ onFrameUpdate, outputDir, onStart, inputProps, qual
145
147
  cancelSignal === null || cancelSignal === void 0 ? void 0 : cancelSignal(() => {
146
148
  stopped = true;
147
149
  });
148
- const progress = Promise.all(framesToRender.map(async (frame, index) => {
150
+ const renderFrameWithOptionToReject = async (frame, index, reject) => {
149
151
  const pool = await poolPromise;
150
152
  const freePage = await pool.acquire();
151
153
  if (stopped) {
152
- throw new Error('Render was stopped');
154
+ return reject(new Error('Render was stopped'));
153
155
  }
154
156
  const startTime = perf_hooks_1.performance.now();
155
157
  const errorCallbackOnFrame = (err) => {
156
- onError(err);
158
+ reject(err);
157
159
  };
158
160
  const cleanupPageError = (0, handle_javascript_exception_1.handleJavascriptException)({
159
161
  page: freePage,
@@ -219,13 +221,44 @@ const innerRenderFrames = ({ onFrameUpdate, outputDir, onStart, inputProps, qual
219
221
  onError(new Error(`Error while downloading asset: ${err.stack}`));
220
222
  });
221
223
  });
222
- pool.release(freePage);
223
224
  framesRendered++;
224
225
  onFrameUpdate(framesRendered, frame, perf_hooks_1.performance.now() - startTime);
225
226
  cleanupPageError();
226
227
  freePage.off('error', errorCallbackOnFrame);
227
- return compressedAssets;
228
- }));
228
+ pool.release(freePage);
229
+ };
230
+ const renderFrame = (frame, index) => {
231
+ return new Promise((resolve, reject) => {
232
+ renderFrameWithOptionToReject(frame, index, reject)
233
+ .then(() => {
234
+ resolve();
235
+ })
236
+ .catch((err) => {
237
+ reject(err);
238
+ });
239
+ });
240
+ };
241
+ const renderFrameAndRetryTargetClose = async (frame, index, retriesLeft, attempt) => {
242
+ var _a;
243
+ try {
244
+ await renderFrame(frame, index);
245
+ }
246
+ catch (err) {
247
+ if (!((_a = err === null || err === void 0 ? void 0 : err.message) === null || _a === void 0 ? void 0 : _a.includes('Target closed'))) {
248
+ throw err;
249
+ }
250
+ if (retriesLeft === 0) {
251
+ console.warn(err, `The browser crashed ${attempt} times while rendering frame ${frame}. Not retrying anymore. Learn more about this error under https://www.remotion.dev/docs/target-closed`);
252
+ throw err;
253
+ }
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
+ const pool = await poolPromise;
256
+ const page = await makePage();
257
+ pool.release(page);
258
+ await renderFrameAndRetryTargetClose(frame, index, retriesLeft - 1, attempt + 1);
259
+ }
260
+ };
261
+ const progress = Promise.all(framesToRender.map((frame, index) => renderFrameAndRetryTargetClose(frame, index, MAX_RETRIES_PER_FRAME, 1)));
229
262
  const happyPath = progress.then(() => {
230
263
  const firstFrameIndex = countType === 'from-zero' ? 0 : framesToRender[0];
231
264
  const returnValue = {
@@ -19,11 +19,13 @@ const get_duration_from_frame_range_1 = require("./get-duration-from-frame-range
19
19
  const get_extension_from_codec_1 = require("./get-extension-from-codec");
20
20
  const get_extension_of_filename_1 = require("./get-extension-of-filename");
21
21
  const get_frame_to_render_1 = require("./get-frame-to-render");
22
+ const image_format_1 = require("./image-format");
22
23
  const is_audio_codec_1 = require("./is-audio-codec");
23
24
  const legacy_webpack_config_1 = require("./legacy-webpack-config");
24
25
  const make_cancel_signal_1 = require("./make-cancel-signal");
25
26
  const overwrite_1 = require("./overwrite");
26
27
  const perf_1 = require("./perf");
28
+ const pixel_format_1 = require("./pixel-format");
27
29
  const prespawn_ffmpeg_1 = require("./prespawn-ffmpeg");
28
30
  const prestitcher_memory_usage_1 = require("./prestitcher-memory-usage");
29
31
  const prores_profile_1 = require("./prores-profile");
@@ -31,6 +33,7 @@ const quality_1 = require("./quality");
31
33
  const render_frames_1 = require("./render-frames");
32
34
  const stitch_frames_to_video_1 = require("./stitch-frames-to-video");
33
35
  const validate_even_dimensions_with_codec_1 = require("./validate-even-dimensions-with-codec");
36
+ const validate_every_nth_frame_1 = require("./validate-every-nth-frame");
34
37
  const validate_ffmpeg_1 = require("./validate-ffmpeg");
35
38
  const validate_ffmpeg_override_1 = require("./validate-ffmpeg-override");
36
39
  const validate_output_filename_1 = require("./validate-output-filename");
@@ -62,6 +65,7 @@ const renderMedia = ({ proResProfile, crf, composition, ffmpegExecutable, ffprob
62
65
  codec,
63
66
  proResProfile,
64
67
  });
68
+ (0, pixel_format_1.validateSelectedPixelFormatAndCodecCombination)(pixelFormat, codec);
65
69
  if (outputLocation) {
66
70
  (0, validate_output_filename_1.validateOutputFilename)(codec, (0, get_extension_of_filename_1.getExtensionOfFilename)(outputLocation));
67
71
  }
@@ -72,6 +76,7 @@ const renderMedia = ({ proResProfile, crf, composition, ffmpegExecutable, ffprob
72
76
  const concurrency = getConcurrency(options);
73
77
  (0, validate_ffmpeg_override_1.validateFfmpegOverride)(ffmpegOverride);
74
78
  const everyNthFrame = (_a = options.everyNthFrame) !== null && _a !== void 0 ? _a : 1;
79
+ (0, validate_every_nth_frame_1.validateEveryNthFrame)(everyNthFrame, codec);
75
80
  const numberOfGifLoops = (_b = options.numberOfGifLoops) !== null && _b !== void 0 ? _b : null;
76
81
  const serveUrl = (0, legacy_webpack_config_1.getServeUrlWithFallback)(options);
77
82
  let stitchStage = 'encoding';
@@ -106,6 +111,7 @@ const renderMedia = ({ proResProfile, crf, composition, ffmpegExecutable, ffprob
106
111
  ? 'none'
107
112
  : (_d = options.imageFormat) !== null && _d !== void 0 ? _d : 'jpeg';
108
113
  const quality = imageFormat === 'jpeg' ? options.quality : undefined;
114
+ (0, image_format_1.validateSelectedPixelFormatAndImageFormatCombination)(pixelFormat, imageFormat);
109
115
  const preEncodedFileLocation = parallelEncoding
110
116
  ? path_1.default.join(downloadMap.preEncode, 'pre-encode.' + (0, get_extension_from_codec_1.getFileExtensionFromCodec)(codec, 'chunk'))
111
117
  : null;
@@ -37,10 +37,4 @@ export declare type StitcherOptions = {
37
37
  enforceAudioTrack?: boolean;
38
38
  ffmpegOverride?: FfmpegOverrideFn;
39
39
  };
40
- declare type ReturnType = {
41
- task: Promise<Buffer | null>;
42
- getLogs: () => string;
43
- };
44
- export declare const spawnFfmpeg: (options: StitcherOptions) => Promise<ReturnType>;
45
40
  export declare const stitchFramesToVideo: (options: StitcherOptions) => Promise<Buffer | null>;
46
- export {};
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.stitchFramesToVideo = exports.spawnFfmpeg = void 0;
6
+ exports.stitchFramesToVideo = void 0;
7
7
  const execa_1 = __importDefault(require("execa"));
8
8
  const fs_1 = __importDefault(require("fs"));
9
9
  const promises_1 = require("fs/promises");
@@ -303,9 +303,8 @@ const spawnFfmpeg = async (options) => {
303
303
  getLogs: () => ffmpegOutput,
304
304
  };
305
305
  };
306
- exports.spawnFfmpeg = spawnFfmpeg;
307
306
  const stitchFramesToVideo = async (options) => {
308
- const { task, getLogs } = await (0, exports.spawnFfmpeg)(options);
307
+ const { task, getLogs } = await spawnFfmpeg(options);
309
308
  const happyPath = task.catch(() => {
310
309
  throw new Error(getLogs());
311
310
  });
@@ -1 +1,2 @@
1
- export declare const validateEveryNthFrame: (everyNthFrame: unknown) => void;
1
+ import type { Codec } from './codec';
2
+ export declare const validateEveryNthFrame: (everyNthFrame: unknown, codec: Codec) => 1 | undefined;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.validateEveryNthFrame = void 0;
4
- const validateEveryNthFrame = (everyNthFrame) => {
4
+ const validateEveryNthFrame = (everyNthFrame, codec) => {
5
5
  if (typeof everyNthFrame === 'undefined') {
6
6
  throw new TypeError(`Argument missing for parameter "everyNthFrame"`);
7
7
  }
@@ -17,5 +17,12 @@ const validateEveryNthFrame = (everyNthFrame) => {
17
17
  if (everyNthFrame % 1 !== 0) {
18
18
  throw new RangeError(`Argument for everyNthFrame must be an integer, but got ${everyNthFrame}`);
19
19
  }
20
+ if (everyNthFrame === 1) {
21
+ return everyNthFrame;
22
+ }
23
+ // h264-mkv because that is what is being used on Lambda
24
+ if (codec !== 'gif' && codec !== 'h264-mkv') {
25
+ throw new Error(`"everyNthFrame" can only be set if "codec" is set to "gif". The codec is "${codec}"`);
26
+ }
20
27
  };
21
28
  exports.validateEveryNthFrame = validateEveryNthFrame;
@@ -0,0 +1,2 @@
1
+ import type { Codec } from './codec';
2
+ export declare const validateNumberOfGifLoops: (numberOfGifLoops: unknown, codec: Codec) => void;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateNumberOfGifLoops = void 0;
4
+ const validateNumberOfGifLoops = (numberOfGifLoops, codec) => {
5
+ if (typeof numberOfGifLoops === 'undefined' || numberOfGifLoops === null) {
6
+ return;
7
+ }
8
+ if (typeof numberOfGifLoops !== 'number') {
9
+ throw new TypeError(`Argument passed to "numberOfGifLoops" is not a number: ${numberOfGifLoops}`);
10
+ }
11
+ if (numberOfGifLoops < 0) {
12
+ throw new RangeError(`The value for "numberOfGifLoops" cannot be below 0, but is ${numberOfGifLoops}`);
13
+ }
14
+ if (!Number.isFinite(numberOfGifLoops)) {
15
+ throw new RangeError(`"numberOfGifLoops" ${numberOfGifLoops} is not finite`);
16
+ }
17
+ if (numberOfGifLoops % 1 !== 0) {
18
+ throw new RangeError(`Argument for numberOfGifLoops must be an integer, but got ${numberOfGifLoops}`);
19
+ }
20
+ if (codec !== 'gif') {
21
+ throw new Error(`"everyNthFrame" can only be set if "codec" is set to "gif". The codec is "${codec}"`);
22
+ }
23
+ };
24
+ exports.validateNumberOfGifLoops = validateNumberOfGifLoops;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remotion/renderer",
3
- "version": "3.2.39",
3
+ "version": "3.2.41",
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.39",
25
+ "remotion": "3.2.41",
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": "406632092cb2b96ac34d489808283508298c4e1f"
60
+ "gitHead": "017d1f002dfe81d451e4707ca0a58f30e3a080b9"
61
61
  }