@remotion/renderer 4.0.27 → 4.0.29

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/dist/client.d.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  /// <reference types="react" />
2
2
  export declare const BrowserSafeApis: {
3
- getFileExtensionFromCodec: <T extends "h264" | "h265" | "vp8" | "vp9" | "prores" | "mp3" | "aac" | "wav" | "h264-mkv" | "gif">(codec: T, audioCodec: "mp3" | "aac" | "pcm-16" | "opus" | null) => import("./file-extensions").FileExtension;
3
+ getFileExtensionFromCodec: <T extends "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif">(codec: T, audioCodec: "mp3" | "aac" | "pcm-16" | "opus" | null) => import("./file-extensions").FileExtension;
4
4
  validCodecs: readonly ["h264", "h265", "vp8", "vp9", "mp3", "aac", "wav", "prores", "h264-mkv", "gif"];
5
5
  validAudioCodecs: readonly ["pcm-16", "aac", "mp3", "opus"];
6
- getDefaultCrfForCodec: (codec: "h264" | "h265" | "vp8" | "vp9" | "prores" | "mp3" | "aac" | "wav" | "h264-mkv" | "gif") => number;
7
- getValidCrfRanges: (codec: "h264" | "h265" | "vp8" | "vp9" | "prores" | "mp3" | "aac" | "wav" | "h264-mkv" | "gif") => [number, number];
8
- isAudioCodec: (codec: "h264" | "h265" | "vp8" | "vp9" | "prores" | "mp3" | "aac" | "wav" | "h264-mkv" | "gif" | undefined) => boolean;
6
+ getDefaultCrfForCodec: (codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif") => number;
7
+ getValidCrfRanges: (codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif") => [number, number];
8
+ isAudioCodec: (codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif" | undefined) => boolean;
9
9
  proResProfileOptions: readonly ["4444-xq", "4444", "hq", "standard", "light", "proxy"];
10
10
  x264PresetOptions: readonly ["ultrafast", "superfast", "veryfast", "faster", "fast", "medium", "slow", "slower", "veryslow", "placebo"];
11
11
  validPixelFormats: readonly ["yuv420p", "yuva420p", "yuv422p", "yuv444p", "yuv420p10le", "yuv422p10le", "yuv444p10le", "yuva444p10le"];
@@ -79,10 +79,10 @@ export declare const BrowserSafeApis: {
79
79
  };
80
80
  };
81
81
  };
82
- prores: {
82
+ mp3: {
83
83
  default: import("./file-extensions").FileExtension;
84
84
  forAudioCodec: {
85
- aac: {
85
+ mp3: {
86
86
  possible: import("./file-extensions").FileExtension[];
87
87
  default: import("./file-extensions").FileExtension;
88
88
  };
@@ -92,10 +92,10 @@ export declare const BrowserSafeApis: {
92
92
  };
93
93
  };
94
94
  };
95
- mp3: {
95
+ aac: {
96
96
  default: import("./file-extensions").FileExtension;
97
97
  forAudioCodec: {
98
- mp3: {
98
+ aac: {
99
99
  possible: import("./file-extensions").FileExtension[];
100
100
  default: import("./file-extensions").FileExtension;
101
101
  };
@@ -105,22 +105,22 @@ export declare const BrowserSafeApis: {
105
105
  };
106
106
  };
107
107
  };
108
- aac: {
108
+ wav: {
109
109
  default: import("./file-extensions").FileExtension;
110
110
  forAudioCodec: {
111
- aac: {
112
- possible: import("./file-extensions").FileExtension[];
113
- default: import("./file-extensions").FileExtension;
114
- };
115
111
  "pcm-16": {
116
112
  possible: import("./file-extensions").FileExtension[];
117
113
  default: import("./file-extensions").FileExtension;
118
114
  };
119
115
  };
120
116
  };
121
- wav: {
117
+ prores: {
122
118
  default: import("./file-extensions").FileExtension;
123
119
  forAudioCodec: {
120
+ aac: {
121
+ possible: import("./file-extensions").FileExtension[];
122
+ default: import("./file-extensions").FileExtension;
123
+ };
124
124
  "pcm-16": {
125
125
  possible: import("./file-extensions").FileExtension[];
126
126
  default: import("./file-extensions").FileExtension;
@@ -162,10 +162,6 @@ export declare const BrowserSafeApis: {
162
162
  compressed: "pcm-16" | "opus" | null;
163
163
  lossless: "pcm-16" | "opus" | null;
164
164
  };
165
- prores: {
166
- compressed: "aac" | "pcm-16" | null;
167
- lossless: "aac" | "pcm-16" | null;
168
- };
169
165
  mp3: {
170
166
  compressed: "mp3" | "pcm-16" | null;
171
167
  lossless: "mp3" | "pcm-16" | null;
@@ -178,6 +174,10 @@ export declare const BrowserSafeApis: {
178
174
  compressed: "pcm-16" | null;
179
175
  lossless: "pcm-16" | null;
180
176
  };
177
+ prores: {
178
+ compressed: "aac" | "pcm-16" | null;
179
+ lossless: "aac" | "pcm-16" | null;
180
+ };
181
181
  "h264-mkv": {
182
182
  compressed: "mp3" | "pcm-16" | null;
183
183
  lossless: "mp3" | "pcm-16" | null;
@@ -187,8 +187,8 @@ export declare const BrowserSafeApis: {
187
187
  lossless: null;
188
188
  };
189
189
  };
190
- defaultCodecsForFileExtension: Record<import("./file-extensions").FileExtension, "h264" | "h265" | "vp8" | "vp9" | "prores" | "mp3" | "aac" | "wav" | "h264-mkv" | "gif">;
191
- validateOutputFilename: <T_1 extends "h264" | "h265" | "vp8" | "vp9" | "prores" | "mp3" | "aac" | "wav" | "h264-mkv" | "gif">({ codec, audioCodec, extension, preferLossless, }: {
190
+ defaultCodecsForFileExtension: Record<import("./file-extensions").FileExtension, "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif">;
191
+ validateOutputFilename: <T_1 extends "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif">({ codec, audioCodec, extension, preferLossless, }: {
192
192
  codec: T_1;
193
193
  audioCodec: "mp3" | "aac" | "pcm-16" | "opus" | null;
194
194
  extension: string;
@@ -275,7 +275,16 @@ export declare const BrowserSafeApis: {
275
275
  docLink: string;
276
276
  type: Record<string, unknown> | null;
277
277
  };
278
+ colorSpaceOption: {
279
+ name: string;
280
+ cliFlag: "color-space";
281
+ description: () => JSX.Element;
282
+ docLink: string;
283
+ ssrName: string;
284
+ type: "default" | "bt709";
285
+ };
278
286
  };
287
+ validColorSpaces: readonly ["default", "bt709"];
279
288
  optionsMap: {
280
289
  readonly renderMedia: readonly [{
281
290
  name: string;
@@ -358,6 +367,6 @@ export declare const BrowserSafeApis: {
358
367
  type: number | null;
359
368
  }];
360
369
  };
361
- codecSupportsCrf: (codec: "h264" | "h265" | "vp8" | "vp9" | "prores" | "mp3" | "aac" | "wav" | "h264-mkv" | "gif") => boolean;
362
- codecSupportsVideoBitrate: (codec: "h264" | "h265" | "vp8" | "vp9" | "prores" | "mp3" | "aac" | "wav" | "h264-mkv" | "gif") => boolean;
370
+ codecSupportsCrf: (codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif") => boolean;
371
+ codecSupportsVideoBitrate: (codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif") => boolean;
363
372
  };
package/dist/client.js CHANGED
@@ -9,6 +9,7 @@ const file_extensions_1 = require("./file-extensions");
9
9
  const get_extension_from_codec_1 = require("./get-extension-from-codec");
10
10
  const is_audio_codec_1 = require("./is-audio-codec");
11
11
  const audio_bitrate_1 = require("./options/audio-bitrate");
12
+ const color_space_1 = require("./options/color-space");
12
13
  const crf_2 = require("./options/crf");
13
14
  const enforce_audio_1 = require("./options/enforce-audio");
14
15
  const jpeg_quality_1 = require("./options/jpeg-quality");
@@ -50,7 +51,9 @@ exports.BrowserSafeApis = {
50
51
  videoCodecOption: video_codec_1.videoCodecOption,
51
52
  offthreadVideoCacheSizeInBytesOption: offthreadvideo_cache_size_1.offthreadVideoCacheSizeInBytesOption,
52
53
  webhookCustomDataOption: webhook_custom_data_1.webhookCustomDataOption,
54
+ colorSpaceOption: color_space_1.colorSpaceOption,
53
55
  },
56
+ validColorSpaces: color_space_1.validColorSpaces,
54
57
  optionsMap: options_map_1.optionsMap,
55
58
  codecSupportsCrf: codec_supports_media_1.codecSupportsCrf,
56
59
  codecSupportsVideoBitrate: codec_supports_media_1.codecSupportsVideoBitrate,
@@ -35,6 +35,7 @@ export type VideoMetadata = {
35
35
  codec: 'h264' | 'h265' | 'vp8' | 'vp9' | 'av1' | 'prores' | 'unknown';
36
36
  canPlayInVideoTag: boolean;
37
37
  supportsSeeking: boolean;
38
+ colorSpace: 'rgb' | 'bt601' | 'bt709' | 'bt2020-ncl' | 'bt2020-cl' | 'fcc' | 'bt470bg' | 'smpte170m' | 'smpte240m' | 'ycgco' | 'smpte2085' | 'chroma-derived-ncl' | 'chroma-derived-cl' | 'ictcp' | 'unknown';
38
39
  };
39
40
  type SilentPart = {
40
41
  startInSeconds: number;
@@ -0,0 +1,14 @@
1
+ import type { Codec } from './codec';
2
+ import type { ColorSpace } from './options/color-space';
3
+ import type { PixelFormat } from './pixel-format';
4
+ import type { X264Preset } from './x264-preset';
5
+ export declare const generateFfmpegArgs: ({ hasPreencoded, proResProfileName, pixelFormat, x264Preset, codec, crf, videoBitrate, colorSpace, }: {
6
+ hasPreencoded: boolean;
7
+ proResProfileName: string | null;
8
+ pixelFormat: PixelFormat;
9
+ x264Preset: X264Preset | null;
10
+ crf: unknown;
11
+ codec: Codec;
12
+ videoBitrate: string | null | undefined;
13
+ colorSpace: ColorSpace;
14
+ }) => string[][];
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateFfmpegArgs = void 0;
4
+ const crf_1 = require("./crf");
5
+ const get_codec_name_1 = require("./get-codec-name");
6
+ const truthy_1 = require("./truthy");
7
+ const firstEncodingStepOnly = ({ hasPreencoded, proResProfileName, pixelFormat, x264Preset, codec, crf, videoBitrate, }) => {
8
+ if (hasPreencoded) {
9
+ return [];
10
+ }
11
+ return [
12
+ proResProfileName ? ['-profile:v', proResProfileName] : null,
13
+ ['-pix_fmt', pixelFormat],
14
+ // Without explicitly disabling auto-alt-ref,
15
+ // transparent WebM generation doesn't work
16
+ pixelFormat === 'yuva420p' ? ['-auto-alt-ref', '0'] : null,
17
+ x264Preset ? ['-preset', x264Preset] : null,
18
+ (0, crf_1.validateQualitySettings)({
19
+ crf,
20
+ videoBitrate,
21
+ codec,
22
+ }),
23
+ ].filter(truthy_1.truthy);
24
+ };
25
+ const generateFfmpegArgs = ({ hasPreencoded, proResProfileName, pixelFormat, x264Preset, codec, crf, videoBitrate, colorSpace, }) => {
26
+ const encoderName = (0, get_codec_name_1.getCodecName)(codec);
27
+ if (encoderName === null) {
28
+ throw new TypeError('encoderName is null: ' + JSON.stringify(codec));
29
+ }
30
+ const colorSpaceOptions = colorSpace === 'bt709'
31
+ ? [
32
+ ['-colorspace:v', 'bt709'],
33
+ ['-color_primaries:v', 'bt709'],
34
+ ['-color_trc:v', 'bt709'],
35
+ ['-color_range:v', 'tv'],
36
+ ]
37
+ : [];
38
+ return [
39
+ ['-c:v', hasPreencoded ? 'copy' : encoderName],
40
+ // -c:v is the same as -vcodec as -codec:video
41
+ // and specified the video codec.
42
+ ...colorSpaceOptions,
43
+ ...firstEncodingStepOnly({
44
+ codec,
45
+ crf,
46
+ hasPreencoded,
47
+ pixelFormat,
48
+ proResProfileName,
49
+ videoBitrate,
50
+ x264Preset,
51
+ }),
52
+ ].filter(truthy_1.truthy);
53
+ };
54
+ exports.generateFfmpegArgs = generateFfmpegArgs;
@@ -1,6 +1,6 @@
1
1
  import type { AudioCodec } from './audio-codec';
2
2
  import type { Codec } from './codec';
3
3
  import type { FileExtension } from './file-extensions';
4
- export declare const getFileExtensionFromCodec: <T extends "h264" | "h265" | "vp8" | "vp9" | "prores" | "mp3" | "aac" | "wav" | "h264-mkv" | "gif">(codec: T, audioCodec: AudioCodec | null) => FileExtension;
5
- export declare const makeFileExtensionMap: () => Record<string, ("h264" | "h265" | "vp8" | "vp9" | "prores" | "mp3" | "aac" | "wav" | "h264-mkv" | "gif")[]>;
4
+ export declare const getFileExtensionFromCodec: <T extends "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif">(codec: T, audioCodec: AudioCodec | null) => FileExtension;
5
+ export declare const makeFileExtensionMap: () => Record<string, ("h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif")[]>;
6
6
  export declare const defaultCodecsForFileExtension: Record<FileExtension, Codec>;
@@ -1,2 +1,5 @@
1
1
  import type { VideoMetadata } from './compositor/payloads';
2
- export declare const getVideoMetadata: (videoSource: string) => Promise<VideoMetadata>;
2
+ import type { LogLevel } from './log-level';
3
+ export declare const getVideoMetadata: (videoSource: string, options?: {
4
+ logLevel?: LogLevel;
5
+ }) => Promise<VideoMetadata>;
@@ -2,8 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getVideoMetadata = void 0;
4
4
  const compositor_1 = require("./compositor/compositor");
5
- const getVideoMetadata = async (videoSource) => {
6
- const compositor = (0, compositor_1.startLongRunningCompositor)((0, compositor_1.getIdealMaximumFrameCacheSizeInBytes)(), 'info', false);
5
+ const getVideoMetadata = async (videoSource, options) => {
6
+ var _a;
7
+ const compositor = (0, compositor_1.startLongRunningCompositor)((0, compositor_1.getIdealMaximumFrameCacheSizeInBytes)(), (_a = options === null || options === void 0 ? void 0 : options.logLevel) !== null && _a !== void 0 ? _a : 'info', false);
7
8
  const metadataResponse = await compositor.executeCommand('GetVideoMetadata', {
8
9
  src: videoSource,
9
10
  });
package/dist/index.d.ts CHANGED
@@ -25,6 +25,7 @@ export type { LogLevel } from './log-level';
25
25
  export { CancelSignal, makeCancelSignal } from './make-cancel-signal';
26
26
  export { openBrowser } from './open-browser';
27
27
  export type { ChromiumOptions } from './open-browser';
28
+ export { ColorSpace } from './options/color-space';
28
29
  export { AnyRemotionOption, RemotionOption, ToOptions } from './options/option';
29
30
  export { PixelFormat } from './pixel-format';
30
31
  export { RemotionServer } from './prepare-server';
@@ -59,9 +60,9 @@ export declare const RenderInternals: {
59
60
  width: number;
60
61
  height: number;
61
62
  scale: number;
62
- codec: "h264" | "h265" | "vp8" | "vp9" | "prores" | "mp3" | "aac" | "wav" | "h264-mkv" | "gif";
63
+ codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif";
63
64
  }) => void;
64
- getFileExtensionFromCodec: <T extends "h264" | "h265" | "vp8" | "vp9" | "prores" | "mp3" | "aac" | "wav" | "h264-mkv" | "gif">(codec: T, audioCodec: "mp3" | "aac" | "pcm-16" | "opus" | null) => import("./file-extensions").FileExtension;
65
+ getFileExtensionFromCodec: <T extends "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif">(codec: T, audioCodec: "mp3" | "aac" | "pcm-16" | "opus" | null) => import("./file-extensions").FileExtension;
65
66
  tmpDir: (str: string) => string;
66
67
  deleteDirectory: (directory: string) => void;
67
68
  isServeUrl: (potentialUrl: string) => boolean;
@@ -111,7 +112,7 @@ export declare const RenderInternals: {
111
112
  };
112
113
  registerErrorSymbolicationLock: () => number;
113
114
  unlockErrorSymbolicationLock: (id: number) => void;
114
- canUseParallelEncoding: (codec: "h264" | "h265" | "vp8" | "vp9" | "prores" | "mp3" | "aac" | "wav" | "h264-mkv" | "gif") => boolean;
115
+ canUseParallelEncoding: (codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif") => boolean;
115
116
  mimeContentType: typeof mimeContentType;
116
117
  mimeLookup: typeof mimeLookup;
117
118
  validateConcurrency: ({ setting, value, checkIfValidForCurrentMachine, }: {
@@ -122,14 +123,14 @@ export declare const RenderInternals: {
122
123
  validPixelFormats: readonly ["yuv420p", "yuva420p", "yuv422p", "yuv444p", "yuv420p10le", "yuv422p10le", "yuv444p10le", "yuva444p10le"];
123
124
  DEFAULT_BROWSER: "chrome";
124
125
  validateFrameRange: (frameRange: import("./frame-range").FrameRange | null) => void;
125
- DEFAULT_OPENGL_RENDERER: "swangle" | "angle" | "egl" | "swiftshader" | null;
126
- validateOpenGlRenderer: (option: "swangle" | "angle" | "egl" | "swiftshader" | null) => "swangle" | "angle" | "egl" | "swiftshader" | null;
126
+ DEFAULT_OPENGL_RENDERER: "angle" | "swangle" | "egl" | "swiftshader" | null;
127
+ validateOpenGlRenderer: (option: "angle" | "swangle" | "egl" | "swiftshader" | null) => "angle" | "swangle" | "egl" | "swiftshader" | null;
127
128
  validCodecs: readonly ["h264", "h265", "vp8", "vp9", "mp3", "aac", "wav", "prores", "h264-mkv", "gif"];
128
129
  DEFAULT_PIXEL_FORMAT: "yuv420p" | "yuva420p" | "yuv422p" | "yuv444p" | "yuv420p10le" | "yuv422p10le" | "yuv444p10le" | "yuva444p10le";
129
130
  validateJpegQuality: (q: number | undefined) => void;
130
131
  DEFAULT_TIMEOUT: number;
131
- DEFAULT_CODEC: "h264" | "h265" | "vp8" | "vp9" | "prores" | "mp3" | "aac" | "wav" | "h264-mkv" | "gif";
132
- isAudioCodec: (codec: "h264" | "h265" | "vp8" | "vp9" | "prores" | "mp3" | "aac" | "wav" | "h264-mkv" | "gif" | undefined) => boolean;
132
+ DEFAULT_CODEC: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif";
133
+ isAudioCodec: (codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif" | undefined) => boolean;
133
134
  logLevels: readonly ["verbose", "info", "warn", "error"];
134
135
  isEqualOrBelowLogLevel: (currentLevel: "verbose" | "info" | "warn" | "error", level: "verbose" | "info" | "warn" | "error") => boolean;
135
136
  isValidLogLevel: (level: string) => boolean;
@@ -146,7 +147,7 @@ export declare const RenderInternals: {
146
147
  output: string;
147
148
  onProgress: (p: number) => void;
148
149
  numberOfFrames: number;
149
- codec: "h264" | "h265" | "vp8" | "vp9" | "prores" | "mp3" | "aac" | "wav" | "h264-mkv" | "gif";
150
+ codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif";
150
151
  fps: number;
151
152
  numberOfGifLoops: number | null;
152
153
  audioCodec: "mp3" | "aac" | "pcm-16" | "opus" | null;
@@ -154,7 +155,7 @@ export declare const RenderInternals: {
154
155
  getMinConcurrency: () => number;
155
156
  getMaxConcurrency: () => any;
156
157
  getDefaultAudioCodec: ({ codec, preferLossless, }: {
157
- codec: "h264" | "h265" | "vp8" | "vp9" | "prores" | "mp3" | "aac" | "wav" | "h264-mkv" | "gif";
158
+ codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif";
158
159
  preferLossless: boolean;
159
160
  }) => "mp3" | "aac" | "pcm-16" | "opus" | null;
160
161
  validAudioCodecs: readonly ["pcm-16", "aac", "mp3", "opus"];
@@ -215,10 +216,10 @@ export declare const RenderInternals: {
215
216
  };
216
217
  };
217
218
  };
218
- prores: {
219
+ mp3: {
219
220
  default: import("./file-extensions").FileExtension;
220
221
  forAudioCodec: {
221
- aac: {
222
+ mp3: {
222
223
  possible: import("./file-extensions").FileExtension[];
223
224
  default: import("./file-extensions").FileExtension;
224
225
  };
@@ -228,10 +229,10 @@ export declare const RenderInternals: {
228
229
  };
229
230
  };
230
231
  };
231
- mp3: {
232
+ aac: {
232
233
  default: import("./file-extensions").FileExtension;
233
234
  forAudioCodec: {
234
- mp3: {
235
+ aac: {
235
236
  possible: import("./file-extensions").FileExtension[];
236
237
  default: import("./file-extensions").FileExtension;
237
238
  };
@@ -241,22 +242,22 @@ export declare const RenderInternals: {
241
242
  };
242
243
  };
243
244
  };
244
- aac: {
245
+ wav: {
245
246
  default: import("./file-extensions").FileExtension;
246
247
  forAudioCodec: {
247
- aac: {
248
- possible: import("./file-extensions").FileExtension[];
249
- default: import("./file-extensions").FileExtension;
250
- };
251
248
  "pcm-16": {
252
249
  possible: import("./file-extensions").FileExtension[];
253
250
  default: import("./file-extensions").FileExtension;
254
251
  };
255
252
  };
256
253
  };
257
- wav: {
254
+ prores: {
258
255
  default: import("./file-extensions").FileExtension;
259
256
  forAudioCodec: {
257
+ aac: {
258
+ possible: import("./file-extensions").FileExtension[];
259
+ default: import("./file-extensions").FileExtension;
260
+ };
260
261
  "pcm-16": {
261
262
  possible: import("./file-extensions").FileExtension[];
262
263
  default: import("./file-extensions").FileExtension;
@@ -293,8 +294,8 @@ export declare const RenderInternals: {
293
294
  readonly vp9: readonly ["opus", "pcm-16"];
294
295
  readonly wav: readonly ["pcm-16"];
295
296
  };
296
- makeFileExtensionMap: () => Record<string, ("h264" | "h265" | "vp8" | "vp9" | "prores" | "mp3" | "aac" | "wav" | "h264-mkv" | "gif")[]>;
297
- defaultCodecsForFileExtension: Record<import("./file-extensions").FileExtension, "h264" | "h265" | "vp8" | "vp9" | "prores" | "mp3" | "aac" | "wav" | "h264-mkv" | "gif">;
297
+ makeFileExtensionMap: () => Record<string, ("h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif")[]>;
298
+ defaultCodecsForFileExtension: Record<import("./file-extensions").FileExtension, "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif">;
298
299
  getExecutablePath: (type: "compositor" | "ffmpeg" | "ffprobe" | "ffmpeg-cwd") => string;
299
300
  callFf: (bin: "ffmpeg" | "ffprobe", args: (string | null)[], options?: execa.Options<string> | undefined) => execa.ExecaChildProcess<string>;
300
301
  dynamicLibraryPathOptions: () => {
@@ -311,8 +312,8 @@ export declare const RenderInternals: {
311
312
  };
312
313
  validStillImageFormats: readonly ["png", "jpeg", "pdf", "webp"];
313
314
  validVideoImageFormats: readonly ["png", "jpeg", "none"];
314
- DEFAULT_STILL_IMAGE_FORMAT: "png" | "jpeg" | "pdf" | "webp";
315
- DEFAULT_VIDEO_IMAGE_FORMAT: "none" | "png" | "jpeg";
315
+ DEFAULT_STILL_IMAGE_FORMAT: "jpeg" | "png" | "webp" | "pdf";
316
+ DEFAULT_VIDEO_IMAGE_FORMAT: "jpeg" | "png" | "none";
316
317
  DEFAULT_JPEG_QUALITY: number;
317
318
  chalk: {
318
319
  enabled: () => boolean;
@@ -425,7 +426,7 @@ export declare const RenderInternals: {
425
426
  frame: number;
426
427
  serializedInputPropsWithCustomSchema: string;
427
428
  serializedResolvedPropsWithCustomSchema: string;
428
- imageFormat: "png" | "jpeg" | "pdf" | "webp";
429
+ imageFormat: "jpeg" | "png" | "webp" | "pdf";
429
430
  jpegQuality: number;
430
431
  puppeteerInstance: HeadlessBrowser | null;
431
432
  envVariables: Record<string, string>;
@@ -4,7 +4,7 @@ exports.audioBitrateOption = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  exports.audioBitrateOption = {
6
6
  name: 'Audio Bitrate',
7
- cliFlag: '--audio-bitrate',
7
+ cliFlag: 'audio-bitrate',
8
8
  description: () => ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: ["Specify the target bitrate for the generated video. The syntax for FFMPEGs", (0, jsx_runtime_1.jsx)("code", { children: "-b:a" }), " parameter should be used. FFMPEG may encode the video in a way that will not result in the exact audio bitrate specified. Example values: ", (0, jsx_runtime_1.jsx)("code", { children: "512K" }), " for 512 kbps, ", (0, jsx_runtime_1.jsx)("code", { children: "1M" }), " for 1 Mbps. Default: ", (0, jsx_runtime_1.jsx)("code", { children: "320k" })] })),
9
9
  ssrName: 'audioBitrate',
10
10
  docLink: 'https://www.remotion.dev/docs/renderer/render-media#audiobitrate-',
@@ -0,0 +1,12 @@
1
+ /// <reference types="react" />
2
+ export declare const validColorSpaces: readonly ["default", "bt709"];
3
+ export type ColorSpace = (typeof validColorSpaces)[number];
4
+ export declare const colorSpaceOption: {
5
+ name: string;
6
+ cliFlag: "color-space";
7
+ description: () => JSX.Element;
8
+ docLink: string;
9
+ ssrName: string;
10
+ type: "default" | "bt709";
11
+ };
12
+ export declare const validateColorSpace: (option: unknown) => void;
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateColorSpace = exports.colorSpaceOption = exports.validColorSpaces = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ exports.validColorSpaces = ['default', 'bt709'];
6
+ exports.colorSpaceOption = {
7
+ name: 'Color space',
8
+ cliFlag: 'color-space',
9
+ description: () => ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: ["Color space to use for the video. Acceptable values:", ' ', (0, jsx_runtime_1.jsxs)("code", { children: ['"', "default", '"'] }), ",", ' ', (0, jsx_runtime_1.jsxs)("code", { children: ['"', "bt709", '"'] })] })),
10
+ docLink: 'https://www.remotion.dev/docs/renderer/render-media#colorspace',
11
+ ssrName: 'colorSpace',
12
+ type: 'default',
13
+ };
14
+ const validateColorSpace = (option) => {
15
+ if (exports.validColorSpaces.includes(option)) {
16
+ return;
17
+ }
18
+ throw new Error(`Expected one of ${exports.validColorSpaces.map((c) => `"${c}"`).join(', ')} for ${exports.colorSpaceOption.ssrName} but got "${option}"`);
19
+ };
20
+ exports.validateColorSpace = validateColorSpace;
@@ -4,7 +4,7 @@ exports.crfOption = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  exports.crfOption = {
6
6
  name: 'CRF',
7
- cliFlag: '--crf',
7
+ cliFlag: 'crf',
8
8
  description: () => ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: "No matter which codec you end up using, there's always a tradeoff between file size and video quality. You can control it by setting the CRF (Constant Rate Factor). The lower the number, the better the quality, the higher the number, the smaller the file is \u2013 of course at the cost of quality." })),
9
9
  ssrName: 'crf',
10
10
  docLink: 'https://www.remotion.dev/docs/encoding/#controlling-quality-using-the-crf-setting',
@@ -4,7 +4,7 @@ exports.enforceAudioOption = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  exports.enforceAudioOption = {
6
6
  name: 'Enforce Audio Track',
7
- cliFlag: '--enforce-audio-track',
7
+ cliFlag: 'enforce-audio-track',
8
8
  description: () => ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: "Render a silent audio track if there would be none otherwise." })),
9
9
  ssrName: 'enforceAudioTrack',
10
10
  docLink: 'https://www.remotion.dev/docs/config#setenforceaudiotrack-',
@@ -4,7 +4,7 @@ exports.jpegQualityOption = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  exports.jpegQualityOption = {
6
6
  name: 'JPEG Quality',
7
- cliFlag: '--jpeg-quality',
7
+ cliFlag: 'jpeg-quality',
8
8
  description: () => ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: "Sets the quality of the generated JPEG images. Must be an integer between 0 and 100. Default: 80." })),
9
9
  ssrName: 'jpegQuality',
10
10
  docLink: 'https://www.remotion.dev/docs/renderer/render-media#jpeg-quality',
@@ -4,7 +4,7 @@ exports.muteOption = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  exports.muteOption = {
6
6
  name: 'Muted',
7
- cliFlag: '--muted',
7
+ cliFlag: 'muted',
8
8
  description: () => (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: "The Audio of the video will be omitted." }),
9
9
  ssrName: 'muted',
10
10
  docLink: 'https://www.remotion.dev/docs/using-audio/#muted-property',
@@ -4,7 +4,7 @@ exports.scaleOption = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  exports.scaleOption = {
6
6
  name: 'Scale',
7
- cliFlag: '--scale',
7
+ cliFlag: 'scale',
8
8
  description: () => ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: ["Scales the output by a factor. For example, a 1280x720px frame will become a 1920x1080px frame with a scale factor of ", (0, jsx_runtime_1.jsx)("code", { children: "1.5" }), ". Vector elements like fonts and HTML markups will be rendered with extra details."] })),
9
9
  ssrName: 'scale',
10
10
  docLink: 'https://www.remotion.dev/docs/scaling',
@@ -4,7 +4,7 @@ exports.videoBitrate = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  exports.videoBitrate = {
6
6
  name: 'Video Bitrate',
7
- cliFlag: '--video-bitrate',
7
+ cliFlag: 'video-bitrate',
8
8
  description: () => ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: ["Specify the target bitrate for the generated video. The syntax for FFMPEGs", (0, jsx_runtime_1.jsx)("code", { children: "-b:v" }), " parameter should be used. FFMPEG may encode the video in a way that will not result in the exact video bitrate specified. Example values: ", (0, jsx_runtime_1.jsx)("code", { children: "512K" }), " for 512 kbps, ", (0, jsx_runtime_1.jsx)("code", { children: "1M" }), " for 1 Mbps."] })),
9
9
  ssrName: 'videoBitrate',
10
10
  docLink: 'https://www.remotion.dev/docs/renderer/render-media#videobitrate-',
@@ -4,7 +4,7 @@ exports.videoCodecOption = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  exports.videoCodecOption = {
6
6
  name: 'Codec',
7
- cliFlag: '--codec',
7
+ cliFlag: 'codec',
8
8
  description: () => ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: "H264 works well in most cases, but sometimes it's worth going for a different codec. WebM achieves higher compression but is slower to render. WebM and ProRes support transparency." })),
9
9
  ssrName: 'codec',
10
10
  docLink: 'https://www.remotion.dev/docs/encoding/#choosing-a-codec',
@@ -3,8 +3,10 @@ import type { FfmpegOverrideFn } from './ffmpeg-override';
3
3
  import type { VideoImageFormat } from './image-format';
4
4
  import type { LogLevel } from './log-level';
5
5
  import type { CancelSignal } from './make-cancel-signal';
6
+ import type { ColorSpace } from './options/color-space';
6
7
  import type { PixelFormat } from './pixel-format';
7
8
  import type { ProResProfile } from './prores-profile';
9
+ import type { X264Preset } from './x264-preset';
8
10
  type RunningStatus = {
9
11
  type: 'running';
10
12
  } | {
@@ -23,6 +25,7 @@ type PreStitcherOptions = {
23
25
  pixelFormat: PixelFormat | undefined;
24
26
  codec: Codec | undefined;
25
27
  crf: number | null | undefined;
28
+ x264Preset: X264Preset | null;
26
29
  onProgress: (progress: number) => void;
27
30
  proResProfile: ProResProfile | undefined;
28
31
  logLevel: LogLevel;
@@ -31,6 +34,7 @@ type PreStitcherOptions = {
31
34
  signal: CancelSignal;
32
35
  videoBitrate: string | null;
33
36
  indent: boolean;
37
+ colorSpace: ColorSpace;
34
38
  };
35
39
  export declare const prespawnFfmpeg: (options: PreStitcherOptions) => {
36
40
  task: import("execa").ExecaChildProcess<string>;
@@ -3,8 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.prespawnFfmpeg = void 0;
4
4
  const call_ffmpeg_1 = require("./call-ffmpeg");
5
5
  const codec_1 = require("./codec");
6
- const crf_1 = require("./crf");
7
- const get_codec_name_1 = require("./get-codec-name");
6
+ const ffmpeg_args_1 = require("./ffmpeg-args");
8
7
  const get_prores_profile_name_1 = require("./get-prores-profile-name");
9
8
  const logger_1 = require("./logger");
10
9
  const parse_ffmpeg_progress_1 = require("./parse-ffmpeg-progress");
@@ -24,11 +23,7 @@ const prespawnFfmpeg = (options) => {
24
23
  scale: 1,
25
24
  });
26
25
  const pixelFormat = (_b = options.pixelFormat) !== null && _b !== void 0 ? _b : pixel_format_1.DEFAULT_PIXEL_FORMAT;
27
- const encoderName = (0, get_codec_name_1.getCodecName)(codec);
28
26
  const proResProfileName = (0, get_prores_profile_name_1.getProResProfileName)(codec, options.proResProfile);
29
- if (encoderName === null) {
30
- throw new TypeError('encoderName is null: ' + JSON.stringify(options));
31
- }
32
27
  (0, pixel_format_1.validateSelectedPixelFormatAndCodecCombination)(pixelFormat, codec);
33
28
  const ffmpegArgs = [
34
29
  ['-r', options.fps],
@@ -40,18 +35,15 @@ const prespawnFfmpeg = (options) => {
40
35
  ['-vcodec', options.imageFormat === 'jpeg' ? 'mjpeg' : 'png'],
41
36
  ['-i', '-'],
42
37
  ],
43
- // -c:v is the same as -vcodec as -codec:video
44
- // and specified the video codec.
45
- ['-c:v', encoderName],
46
- proResProfileName ? ['-profile:v', proResProfileName] : null,
47
- ['-pix_fmt', pixelFormat],
48
- // Without explicitly disabling auto-alt-ref,
49
- // transparent WebM generation doesn't work
50
- pixelFormat === 'yuva420p' ? ['-auto-alt-ref', '0'] : null,
51
- ...(0, crf_1.validateQualitySettings)({
38
+ ...(0, ffmpeg_args_1.generateFfmpegArgs)({
39
+ hasPreencoded: false,
40
+ proResProfileName,
41
+ pixelFormat,
42
+ x264Preset: options.x264Preset,
43
+ codec,
52
44
  crf: options.crf,
53
45
  videoBitrate: options.videoBitrate,
54
- codec,
46
+ colorSpace: options.colorSpace,
55
47
  }),
56
48
  '-y',
57
49
  options.outputLocation,
@@ -12,6 +12,7 @@ import type { VideoImageFormat } from './image-format';
12
12
  import { type LogLevel } from './log-level';
13
13
  import type { CancelSignal } from './make-cancel-signal';
14
14
  import type { ChromiumOptions } from './open-browser';
15
+ import type { ColorSpace } from './options/color-space';
15
16
  import type { ToOptions } from './options/option';
16
17
  import type { optionsMap } from './options/options-map';
17
18
  import type { PixelFormat } from './pixel-format';
@@ -74,6 +75,7 @@ export type InternalRenderMediaOptions = {
74
75
  audioCodec: AudioCodec | null;
75
76
  serveUrl: string;
76
77
  concurrency: number | string | null;
78
+ colorSpace: ColorSpace;
77
79
  } & ToOptions<typeof optionsMap.renderMedia>;
78
80
  export type RenderMediaOptions = {
79
81
  outputLocation?: string | null;
@@ -126,6 +128,7 @@ export type RenderMediaOptions = {
126
128
  concurrency?: number | string | null;
127
129
  logLevel?: LogLevel;
128
130
  offthreadVideoCacheSizeInBytes?: number | null;
131
+ colorSpace?: ColorSpace;
129
132
  };
130
133
  type RenderMediaResult = {
131
134
  buffer: Buffer | null;
@@ -137,5 +140,5 @@ export declare const internalRenderMedia: (args_0: InternalRenderMediaOptions) =
137
140
  * @description Render a video from a composition
138
141
  * @see [Documentation](https://www.remotion.dev/docs/renderer/render-media)
139
142
  */
140
- export declare const renderMedia: ({ proResProfile, x264Preset, crf, composition, inputProps, pixelFormat, codec, envVariables, frameRange, puppeteerInstance, outputLocation, onProgress, overwrite, onDownload, onBrowserLog, onStart, timeoutInMilliseconds, chromiumOptions, scale, browserExecutable, port, cancelSignal, muted, enforceAudioTrack, ffmpegOverride, audioBitrate, videoBitrate, audioCodec, jpegQuality, concurrency, serveUrl, disallowParallelEncoding, everyNthFrame, imageFormat, numberOfGifLoops, dumpBrowserLogs, preferLossless, verbose, quality, logLevel, offthreadVideoCacheSizeInBytes, }: RenderMediaOptions) => Promise<RenderMediaResult>;
143
+ export declare const renderMedia: ({ proResProfile, x264Preset, crf, composition, inputProps, pixelFormat, codec, envVariables, frameRange, puppeteerInstance, outputLocation, onProgress, overwrite, onDownload, onBrowserLog, onStart, timeoutInMilliseconds, chromiumOptions, scale, browserExecutable, port, cancelSignal, muted, enforceAudioTrack, ffmpegOverride, audioBitrate, videoBitrate, audioCodec, jpegQuality, concurrency, serveUrl, disallowParallelEncoding, everyNthFrame, imageFormat, numberOfGifLoops, dumpBrowserLogs, preferLossless, verbose, quality, logLevel, offthreadVideoCacheSizeInBytes, colorSpace, }: RenderMediaOptions) => Promise<RenderMediaResult>;
141
144
  export {};
@@ -46,7 +46,7 @@ const validate_videobitrate_1 = require("./validate-videobitrate");
46
46
  const wrap_with_error_handling_1 = require("./wrap-with-error-handling");
47
47
  const x264_preset_1 = require("./x264-preset");
48
48
  const SLOWEST_FRAME_COUNT = 10;
49
- const internalRenderMediaRaw = ({ proResProfile, x264Preset, crf, composition, serializedInputPropsWithCustomSchema, pixelFormat, codec, envVariables, frameRange, puppeteerInstance, outputLocation, onProgress, overwrite, onDownload, onBrowserLog, onStart, timeoutInMilliseconds, chromiumOptions, scale, browserExecutable, port, cancelSignal, muted, enforceAudioTrack, ffmpegOverride, audioBitrate, videoBitrate, audioCodec, concurrency, disallowParallelEncoding, everyNthFrame, imageFormat: provisionalImageFormat, indent, jpegQuality, numberOfGifLoops, onCtrlCExit, preferLossless, serveUrl, server: reusedServer, logLevel, serializedResolvedPropsWithCustomSchema, offthreadVideoCacheSizeInBytes, }) => {
49
+ const internalRenderMediaRaw = ({ proResProfile, x264Preset, crf, composition, serializedInputPropsWithCustomSchema, pixelFormat, codec, envVariables, frameRange, puppeteerInstance, outputLocation, onProgress, overwrite, onDownload, onBrowserLog, onStart, timeoutInMilliseconds, chromiumOptions, scale, browserExecutable, port, cancelSignal, muted, enforceAudioTrack, ffmpegOverride, audioBitrate, videoBitrate, audioCodec, concurrency, disallowParallelEncoding, everyNthFrame, imageFormat: provisionalImageFormat, indent, jpegQuality, numberOfGifLoops, onCtrlCExit, preferLossless, serveUrl, server: reusedServer, logLevel, serializedResolvedPropsWithCustomSchema, offthreadVideoCacheSizeInBytes, colorSpace, }) => {
50
50
  (0, jpeg_quality_1.validateJpegQuality)(jpegQuality);
51
51
  (0, crf_1.validateQualitySettings)({ crf, codec, videoBitrate });
52
52
  (0, validate_videobitrate_1.validateBitrate)(audioBitrate, 'audioBitrate');
@@ -183,6 +183,8 @@ const internalRenderMediaRaw = ({ proResProfile, x264Preset, crf, composition, s
183
183
  ffmpegOverride: ffmpegOverride !== null && ffmpegOverride !== void 0 ? ffmpegOverride : (({ args }) => args),
184
184
  videoBitrate,
185
185
  indent,
186
+ x264Preset: x264Preset !== null && x264Preset !== void 0 ? x264Preset : null,
187
+ colorSpace,
186
188
  });
187
189
  stitcherFfmpeg = preStitcher.task;
188
190
  }
@@ -356,6 +358,7 @@ const internalRenderMediaRaw = ({ proResProfile, x264Preset, crf, composition, s
356
358
  videoBitrate,
357
359
  audioCodec,
358
360
  x264Preset: x264Preset !== null && x264Preset !== void 0 ? x264Preset : null,
361
+ colorSpace,
359
362
  }),
360
363
  stitchStart,
361
364
  ]);
@@ -421,7 +424,7 @@ exports.internalRenderMedia = (0, wrap_with_error_handling_1.wrapWithErrorHandli
421
424
  * @description Render a video from a composition
422
425
  * @see [Documentation](https://www.remotion.dev/docs/renderer/render-media)
423
426
  */
424
- const renderMedia = ({ proResProfile, x264Preset, crf, composition, inputProps, pixelFormat, codec, envVariables, frameRange, puppeteerInstance, outputLocation, onProgress, overwrite, onDownload, onBrowserLog, onStart, timeoutInMilliseconds, chromiumOptions, scale, browserExecutable, port, cancelSignal, muted, enforceAudioTrack, ffmpegOverride, audioBitrate, videoBitrate, audioCodec, jpegQuality, concurrency, serveUrl, disallowParallelEncoding, everyNthFrame, imageFormat, numberOfGifLoops, dumpBrowserLogs, preferLossless, verbose, quality, logLevel, offthreadVideoCacheSizeInBytes, }) => {
427
+ const renderMedia = ({ proResProfile, x264Preset, crf, composition, inputProps, pixelFormat, codec, envVariables, frameRange, puppeteerInstance, outputLocation, onProgress, overwrite, onDownload, onBrowserLog, onStart, timeoutInMilliseconds, chromiumOptions, scale, browserExecutable, port, cancelSignal, muted, enforceAudioTrack, ffmpegOverride, audioBitrate, videoBitrate, audioCodec, jpegQuality, concurrency, serveUrl, disallowParallelEncoding, everyNthFrame, imageFormat, numberOfGifLoops, dumpBrowserLogs, preferLossless, verbose, quality, logLevel, offthreadVideoCacheSizeInBytes, colorSpace, }) => {
425
428
  var _a, _b;
426
429
  if (quality !== undefined) {
427
430
  console.warn(`The "quality" option has been renamed. Please use "jpegQuality" instead.`);
@@ -477,6 +480,7 @@ const renderMedia = ({ proResProfile, x264Preset, crf, composition, inputProps,
477
480
  data: (_b = composition.props) !== null && _b !== void 0 ? _b : {},
478
481
  }).serializedString,
479
482
  offthreadVideoCacheSizeInBytes: offthreadVideoCacheSizeInBytes !== null && offthreadVideoCacheSizeInBytes !== void 0 ? offthreadVideoCacheSizeInBytes : null,
483
+ colorSpace: colorSpace !== null && colorSpace !== void 0 ? colorSpace : 'default',
480
484
  });
481
485
  };
482
486
  exports.renderMedia = renderMedia;
@@ -42,9 +42,7 @@ const innerSetPropsAndEnv = async ({ serializedInputPropsWithCustomSchema, envVa
42
42
  throw new Error(`Visited "${urlToVisit}" but got no response.`);
43
43
  }
44
44
  const status = pageRes.status();
45
- // S3 in rare occasions returns a 500 or 503 error code for GET operations.
46
- // Usually it is fixed by retrying.
47
- if (status >= 500 && status <= 504 && retriesRemaining > 0) {
45
+ const retry = async () => {
48
46
  await new Promise((resolve) => {
49
47
  setTimeout(() => {
50
48
  resolve();
@@ -64,6 +62,11 @@ const innerSetPropsAndEnv = async ({ serializedInputPropsWithCustomSchema, envVa
64
62
  indent,
65
63
  logLevel,
66
64
  });
65
+ };
66
+ // S3 in rare occasions returns a 500 or 503 error code for GET operations.
67
+ // Usually it is fixed by retrying.
68
+ if (status >= 500 && status <= 504 && retriesRemaining > 0) {
69
+ return retry();
67
70
  }
68
71
  if (!redirect_status_codes_1.redirectStatusCodes.every((code) => code !== status)) {
69
72
  throw new Error(`Error while getting compositions: Tried to go to ${urlToVisit} but the status code was ${status} instead of 200. Does the site you specified exist?`);
@@ -85,6 +88,10 @@ const innerSetPropsAndEnv = async ({ serializedInputPropsWithCustomSchema, envVa
85
88
  frame: null,
86
89
  page,
87
90
  });
91
+ // AWS shakyness
92
+ if (body.includes('We encountered an internal error.')) {
93
+ return retry();
94
+ }
88
95
  const errorMessage = [
89
96
  `Error while getting compositions: Tried to go to ${urlToVisit} and verify that it is a Remotion project by checking if window.getStaticCompositions is defined.`,
90
97
  'However, the function was undefined, which indicates that this is not a valid Remotion project. Please check the URL you passed.',
@@ -6,6 +6,7 @@ import type { Codec } from './codec';
6
6
  import type { FfmpegOverrideFn } from './ffmpeg-override';
7
7
  import type { LogLevel } from './log-level';
8
8
  import type { CancelSignal } from './make-cancel-signal';
9
+ import type { ColorSpace } from './options/color-space';
9
10
  import type { PixelFormat } from './pixel-format';
10
11
  import type { ProResProfile } from './prores-profile';
11
12
  import type { X264Preset } from './x264-preset';
@@ -36,6 +37,7 @@ type InternalStitchFramesToVideoOptions = {
36
37
  x264Preset: X264Preset | null;
37
38
  enforceAudioTrack: boolean;
38
39
  ffmpegOverride: null | FfmpegOverrideFn;
40
+ colorSpace: ColorSpace;
39
41
  };
40
42
  export type StitchFramesToVideoOptions = {
41
43
  audioBitrate?: string | null;
@@ -61,11 +63,12 @@ export type StitchFramesToVideoOptions = {
61
63
  enforceAudioTrack?: boolean;
62
64
  ffmpegOverride?: FfmpegOverrideFn;
63
65
  x264Preset?: X264Preset | null;
66
+ colorSpace?: ColorSpace;
64
67
  };
65
68
  export declare const internalStitchFramesToVideo: (options: InternalStitchFramesToVideoOptions) => Promise<Buffer | null>;
66
69
  /**
67
70
  * @description Takes a series of images and audio information generated by renderFrames() and encodes it to a video.
68
71
  * @see [Documentation](https://www.remotion.dev/docs/renderer/stitch-frames-to-video)
69
72
  */
70
- export declare const stitchFramesToVideo: ({ assetsInfo, force, fps, height, width, audioBitrate, audioCodec, cancelSignal, codec, crf, dir, enforceAudioTrack, ffmpegOverride, muted, numberOfGifLoops, onDownload, onProgress, outputLocation, pixelFormat, proResProfile, verbose, videoBitrate, x264Preset, }: StitchFramesToVideoOptions) => Promise<Buffer | null>;
73
+ export declare const stitchFramesToVideo: ({ assetsInfo, force, fps, height, width, audioBitrate, audioCodec, cancelSignal, codec, crf, dir, enforceAudioTrack, ffmpegOverride, muted, numberOfGifLoops, onDownload, onProgress, outputLocation, pixelFormat, proResProfile, verbose, videoBitrate, x264Preset, colorSpace, }: StitchFramesToVideoOptions) => Promise<Buffer | null>;
71
74
  export {};
@@ -41,8 +41,8 @@ const convert_number_of_gif_loops_to_ffmpeg_1 = require("./convert-number-of-gif
41
41
  const crf_1 = require("./crf");
42
42
  const delete_directory_1 = require("./delete-directory");
43
43
  const does_have_m2_bug_1 = require("./does-have-m2-bug");
44
+ const ffmpeg_args_1 = require("./ffmpeg-args");
44
45
  const find_closest_package_json_1 = require("./find-closest-package-json");
45
- const get_codec_name_1 = require("./get-codec-name");
46
46
  const get_extension_from_codec_1 = require("./get-extension-from-codec");
47
47
  const get_prores_profile_name_1 = require("./get-prores-profile-name");
48
48
  const logger_1 = require("./logger");
@@ -101,7 +101,7 @@ const getAssetsData = async ({ assets, onDownload, fps, expectedFrames, logLevel
101
101
  });
102
102
  return outName;
103
103
  };
104
- const innerStitchFramesToVideo = async ({ assetsInfo, audioBitrate, audioCodec, cancelSignal, codec, crf, dir, enforceAudioTrack, ffmpegOverride, force, fps, height, indent, muted, onDownload, outputLocation, pixelFormat, preEncodedFileLocation, preferLossless, proResProfile, logLevel, videoBitrate, width, numberOfGifLoops, onProgress, x264Preset, }, remotionRoot) => {
104
+ const innerStitchFramesToVideo = async ({ assetsInfo, audioBitrate, audioCodec, cancelSignal, codec, crf, dir, enforceAudioTrack, ffmpegOverride, force, fps, height, indent, muted, onDownload, outputLocation, pixelFormat, preEncodedFileLocation, preferLossless, proResProfile, logLevel, videoBitrate, width, numberOfGifLoops, onProgress, x264Preset, colorSpace, }, remotionRoot) => {
105
105
  var _a;
106
106
  (0, validate_1.validateDimension)(height, 'height', 'passed to `stitchFramesToVideo()`');
107
107
  (0, validate_1.validateDimension)(width, 'width', 'passed to `stitchFramesToVideo()`');
@@ -118,7 +118,6 @@ const innerStitchFramesToVideo = async ({ assetsInfo, audioBitrate, audioCodec,
118
118
  (0, validate_videobitrate_1.validateBitrate)(audioBitrate, 'audioBitrate');
119
119
  (0, validate_videobitrate_1.validateBitrate)(videoBitrate, 'videoBitrate');
120
120
  (0, validate_1.validateFps)(fps, 'in `stitchFramesToVideo()`', false);
121
- const encoderName = (0, get_codec_name_1.getCodecName)(codec);
122
121
  const proResProfileName = (0, get_prores_profile_name_1.getProResProfileName)(codec, proResProfile);
123
122
  const mediaSupport = (0, codec_supports_media_1.codecSupportsMedia)(codec);
124
123
  const shouldRenderAudio = mediaSupport.audio &&
@@ -240,24 +239,16 @@ const innerStitchFramesToVideo = async ({ assetsInfo, audioBitrate, audioCodec,
240
239
  numberOfGifLoops === null
241
240
  ? null
242
241
  : ['-loop', (0, convert_number_of_gif_loops_to_ffmpeg_1.convertNumberOfGifLoopsToFfmpegSyntax)(numberOfGifLoops)],
243
- // -c:v is the same as -vcodec as -codec:video
244
- // and specified the video codec.
245
- ['-c:v', encoderName],
246
- ...(preEncodedFileLocation
247
- ? []
248
- : [
249
- proResProfileName ? ['-profile:v', proResProfileName] : null,
250
- ['-pix_fmt', pixelFormat],
251
- // Without explicitly disabling auto-alt-ref,
252
- // transparent WebM generation doesn't work
253
- pixelFormat === 'yuva420p' ? ['-auto-alt-ref', '0'] : null,
254
- ...(0, crf_1.validateQualitySettings)({
255
- crf,
256
- videoBitrate,
257
- codec,
258
- }),
259
- ]),
260
- x264Preset ? ['-preset', x264Preset] : null,
242
+ ...(0, ffmpeg_args_1.generateFfmpegArgs)({
243
+ codec,
244
+ crf,
245
+ videoBitrate,
246
+ hasPreencoded: Boolean(preEncodedFileLocation),
247
+ proResProfileName,
248
+ pixelFormat,
249
+ x264Preset,
250
+ colorSpace,
251
+ }),
261
252
  codec === 'h264' ? ['-movflags', 'faststart'] : null,
262
253
  resolvedAudioCodec
263
254
  ? ['-c:a', (0, audio_codec_1.mapAudioCodecToFfmpegAudioCodecName)(resolvedAudioCodec)]
@@ -361,7 +352,7 @@ exports.internalStitchFramesToVideo = internalStitchFramesToVideo;
361
352
  * @description Takes a series of images and audio information generated by renderFrames() and encodes it to a video.
362
353
  * @see [Documentation](https://www.remotion.dev/docs/renderer/stitch-frames-to-video)
363
354
  */
364
- const stitchFramesToVideo = ({ assetsInfo, force, fps, height, width, audioBitrate, audioCodec, cancelSignal, codec, crf, dir, enforceAudioTrack, ffmpegOverride, muted, numberOfGifLoops, onDownload, onProgress, outputLocation, pixelFormat, proResProfile, verbose, videoBitrate, x264Preset, }) => {
355
+ const stitchFramesToVideo = ({ assetsInfo, force, fps, height, width, audioBitrate, audioCodec, cancelSignal, codec, crf, dir, enforceAudioTrack, ffmpegOverride, muted, numberOfGifLoops, onDownload, onProgress, outputLocation, pixelFormat, proResProfile, verbose, videoBitrate, x264Preset, colorSpace, }) => {
365
356
  return (0, exports.internalStitchFramesToVideo)({
366
357
  assetsInfo,
367
358
  audioBitrate: audioBitrate !== null && audioBitrate !== void 0 ? audioBitrate : null,
@@ -389,6 +380,7 @@ const stitchFramesToVideo = ({ assetsInfo, force, fps, height, width, audioBitra
389
380
  preEncodedFileLocation: null,
390
381
  preferLossless: false,
391
382
  x264Preset: x264Preset !== null && x264Preset !== void 0 ? x264Preset : null,
383
+ colorSpace: colorSpace !== null && colorSpace !== void 0 ? colorSpace : 'default',
392
384
  });
393
385
  };
394
386
  exports.stitchFramesToVideo = stitchFramesToVideo;
@@ -1,5 +1,5 @@
1
1
  import type { AudioCodec } from './audio-codec';
2
- export declare const validateOutputFilename: <T extends "h264" | "h265" | "vp8" | "vp9" | "prores" | "mp3" | "aac" | "wav" | "h264-mkv" | "gif">({ codec, audioCodec, extension, preferLossless, }: {
2
+ export declare const validateOutputFilename: <T extends "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif">({ codec, audioCodec, extension, preferLossless, }: {
3
3
  codec: T;
4
4
  audioCodec: AudioCodec | null;
5
5
  extension: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remotion/renderer",
3
- "version": "4.0.27",
3
+ "version": "4.0.29",
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.27"
21
+ "remotion": "4.0.29"
22
22
  },
23
23
  "peerDependencies": {
24
24
  "react": ">=16.8.0",
@@ -40,13 +40,13 @@
40
40
  "vitest": "0.31.1"
41
41
  },
42
42
  "optionalDependencies": {
43
- "@remotion/compositor-linux-arm64-gnu": "4.0.27",
44
- "@remotion/compositor-linux-arm64-musl": "4.0.27",
45
- "@remotion/compositor-darwin-arm64": "4.0.27",
46
- "@remotion/compositor-darwin-x64": "4.0.27",
47
- "@remotion/compositor-win32-x64-msvc": "4.0.27",
48
- "@remotion/compositor-linux-x64-musl": "4.0.27",
49
- "@remotion/compositor-linux-x64-gnu": "4.0.27"
43
+ "@remotion/compositor-darwin-x64": "4.0.29",
44
+ "@remotion/compositor-linux-arm64-gnu": "4.0.29",
45
+ "@remotion/compositor-linux-x64-gnu": "4.0.29",
46
+ "@remotion/compositor-win32-x64-msvc": "4.0.29",
47
+ "@remotion/compositor-darwin-arm64": "4.0.29",
48
+ "@remotion/compositor-linux-arm64-musl": "4.0.29",
49
+ "@remotion/compositor-linux-x64-musl": "4.0.29"
50
50
  },
51
51
  "keywords": [
52
52
  "remotion",