@remotion/renderer 4.0.226 → 4.0.228

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.
Files changed (71) hide show
  1. package/dist/assets/download-and-map-assets-to-file.js +0 -2
  2. package/dist/assets/download-map.d.ts +0 -3
  3. package/dist/assets/download-map.js +0 -1
  4. package/dist/browser-instances.js +1 -1
  5. package/dist/client.d.ts +48 -1
  6. package/dist/client.js +2 -0
  7. package/dist/combine-audio.js +1 -1
  8. package/dist/compositor/compose.d.ts +1 -21
  9. package/dist/compositor/compose.js +2 -34
  10. package/dist/compositor/compositor.js +1 -1
  11. package/dist/compositor/payloads.d.ts +0 -35
  12. package/dist/crf.d.ts +4 -2
  13. package/dist/crf.js +12 -6
  14. package/dist/delete-directory.js +1 -1
  15. package/dist/error-handling/handle-javascript-exception.js +1 -0
  16. package/dist/ffmpeg-args.d.ts +6 -1
  17. package/dist/ffmpeg-args.js +14 -5
  18. package/dist/get-browser-instance.js +3 -2
  19. package/dist/get-codec-name.d.ts +5 -1
  20. package/dist/get-codec-name.js +38 -15
  21. package/dist/get-cpu-count.js +1 -1
  22. package/dist/get-local-browser-executable.d.ts +6 -1
  23. package/dist/get-local-browser-executable.js +9 -4
  24. package/dist/get-port.js +1 -0
  25. package/dist/index.d.ts +5 -5
  26. package/dist/logger.d.ts +4 -4
  27. package/dist/logger.js +20 -1
  28. package/dist/open-browser.js +5 -1
  29. package/dist/options/audio-codec.d.ts +1 -1
  30. package/dist/options/audio-codec.js +1 -0
  31. package/dist/options/hardware-acceleration.d.ts +18 -0
  32. package/dist/options/hardware-acceleration.js +56 -0
  33. package/dist/options/index.d.ts +15 -0
  34. package/dist/options/index.js +2 -0
  35. package/dist/options/options-map.d.ts +30 -0
  36. package/dist/options/options-map.js +3 -0
  37. package/dist/path-normalize.js +1 -1
  38. package/dist/prespawn-ffmpeg.d.ts +2 -0
  39. package/dist/prespawn-ffmpeg.js +3 -0
  40. package/dist/provide-screenshot.d.ts +1 -3
  41. package/dist/provide-screenshot.js +1 -2
  42. package/dist/puppeteer-evaluate.js +2 -3
  43. package/dist/puppeteer-screenshot.d.ts +0 -2
  44. package/dist/puppeteer-screenshot.js +0 -1
  45. package/dist/render-frames.js +4 -7
  46. package/dist/render-media.d.ts +1 -1
  47. package/dist/render-media.js +12 -8
  48. package/dist/render-still.js +10 -13
  49. package/dist/screenshot-dom-element.d.ts +1 -3
  50. package/dist/screenshot-dom-element.js +1 -2
  51. package/dist/screenshot-task.d.ts +1 -3
  52. package/dist/screenshot-task.js +8 -16
  53. package/dist/serve-handler/index.js +2 -2
  54. package/dist/stitch-frames-to-video.d.ts +2 -2
  55. package/dist/stitch-frames-to-video.js +7 -2
  56. package/dist/take-frame.d.ts +18 -0
  57. package/dist/take-frame.js +34 -0
  58. package/ensure-browser.mjs +13 -1
  59. package/eslint.config.mjs +34 -0
  60. package/package.json +15 -14
  61. package/Cargo.lock +0 -952
  62. package/Cargo.toml +0 -26
  63. package/build.ts +0 -311
  64. package/dist/browser/BrowserConnector.d.ts +0 -19
  65. package/dist/browser/BrowserConnector.js +0 -17
  66. package/dist/browser/PuppeteerNode.d.ts +0 -30
  67. package/dist/browser/PuppeteerNode.js +0 -52
  68. package/dist/browser/node.d.ts +0 -2
  69. package/dist/browser/node.js +0 -5
  70. package/dist/copy-to-clipboard.d.ts +0 -2
  71. package/dist/copy-to-clipboard.js +0 -18
@@ -125,12 +125,10 @@ const downloadAsset = async ({ src, downloadMap, indent, logLevel, shouldAnalyze
125
125
  if (node_fs_1.default.existsSync(claimedDownloadLocation)) {
126
126
  return claimedDownloadLocation;
127
127
  }
128
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
129
128
  downloadMap.hasBeenDownloadedMap[src][downloadDir] = null;
130
129
  if (!downloadMap.isDownloadingMap[src]) {
131
130
  downloadMap.isDownloadingMap[src] = {};
132
131
  }
133
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
134
132
  downloadMap.isDownloadingMap[src][downloadDir] = false;
135
133
  }
136
134
  if ((_c = downloadMap.isDownloadingMap[src]) === null || _c === void 0 ? void 0 : _c[downloadDir]) {
@@ -33,9 +33,6 @@ export type DownloadMap = {
33
33
  stitchFrames: string;
34
34
  assetDir: string;
35
35
  compositingDir: string;
36
- compositorCache: {
37
- [key: string]: string;
38
- };
39
36
  preventCleanup: () => void;
40
37
  allowCleanup: () => void;
41
38
  isPreventedFromCleanup: () => boolean;
@@ -61,7 +61,6 @@ const makeDownloadMap = () => {
61
61
  audioPreprocessing: makeAndReturn(dir, 'remotion-audio-preprocessing'),
62
62
  stitchFrames: makeAndReturn(dir, 'remotion-stitch-temp-dir'),
63
63
  compositingDir: makeAndReturn(dir, 'remotion-compositing-temp-dir'),
64
- compositorCache: {},
65
64
  emitter: new offthread_video_server_1.OffthreadVideoServerEmitter(),
66
65
  preventCleanup: () => {
67
66
  prevented = true;
@@ -7,7 +7,7 @@ const killAllBrowsers = async () => {
7
7
  try {
8
8
  await browser.close(true, 'info', false);
9
9
  }
10
- catch (err) { }
10
+ catch (_a) { }
11
11
  }
12
12
  };
13
13
  exports.killAllBrowsers = killAllBrowsers;
package/dist/client.d.ts CHANGED
@@ -1,12 +1,14 @@
1
1
  export { AvailableOptions, TypeOfOption } from './options';
2
+ export { HardwareAccelerationOption } from './options/hardware-acceleration';
2
3
  export declare const BrowserSafeApis: {
3
4
  getFileExtensionFromCodec: <T extends import("./codec").Codec>(codec: T, audioCodec: import("./options/audio-codec").AudioCodec | null) => import("./file-extensions").FileExtension;
4
5
  validCodecs: readonly ["h264", "h265", "vp8", "vp9", "mp3", "aac", "wav", "prores", "h264-mkv", "h264-ts", "gif"];
5
6
  validAudioCodecs: readonly ["pcm-16", "aac", "mp3", "opus"];
6
- getDefaultCrfForCodec: (codec: import("./codec").Codec) => number;
7
+ getDefaultCrfForCodec: (codec: import("./codec").Codec) => number | null;
7
8
  getValidCrfRanges: (codec: import("./codec").Codec) => [number, number];
8
9
  proResProfileOptions: readonly ["4444-xq", "4444", "hq", "standard", "light", "proxy"];
9
10
  x264PresetOptions: readonly ["ultrafast", "superfast", "veryfast", "faster", "fast", "medium", "slow", "slower", "veryslow", "placebo"];
11
+ hardwareAccelerationOptions: readonly ["disable", "if-possible", "required"];
10
12
  validPixelFormats: readonly ["yuv420p", "yuva420p", "yuv422p", "yuv444p", "yuv420p10le", "yuv422p10le", "yuv444p10le", "yuva444p10le"];
11
13
  validOpenGlRenderers: readonly ["swangle", "angle", "egl", "swiftshader", "vulkan", "angle-egl"];
12
14
  validPixelFormatsForCodec: (codec: import("./codec").Codec) => readonly ["yuv420p", "yuva420p", "yuv422p", "yuv444p", "yuv420p10le", "yuv422p10le", "yuv444p10le", "yuva444p10le"] | ("yuv420p" | "yuv422p" | "yuv444p" | "yuv420p10le" | "yuv422p10le" | "yuv444p10le" | "yuva444p10le")[];
@@ -819,6 +821,21 @@ export declare const BrowserSafeApis: {
819
821
  setConfig: (newMetadata: import("./options/metadata").Metadata) => void;
820
822
  ssrName: string;
821
823
  };
824
+ hardwareAccelerationOption: {
825
+ name: string;
826
+ cliFlag: "hardware-acceleration";
827
+ description: () => string;
828
+ ssrName: string;
829
+ docLink: string;
830
+ type: import("./options/hardware-acceleration").HardwareAccelerationOption;
831
+ getValue: ({ commandLine }: {
832
+ commandLine: Record<string, unknown>;
833
+ }) => {
834
+ source: string;
835
+ value: "disable" | "if-possible" | "required";
836
+ };
837
+ setConfig: (value: import("./options/hardware-acceleration").HardwareAccelerationOption) => void;
838
+ };
822
839
  };
823
840
  validColorSpaces: readonly ["default", "bt709", "bt2020-ncl"];
824
841
  optionsMap: {
@@ -1136,6 +1153,21 @@ export declare const BrowserSafeApis: {
1136
1153
  getValue: () => never;
1137
1154
  setConfig: () => never;
1138
1155
  };
1156
+ readonly hardwareAcceleration: {
1157
+ name: string;
1158
+ cliFlag: "hardware-acceleration";
1159
+ description: () => string;
1160
+ ssrName: string;
1161
+ docLink: string;
1162
+ type: import("./options/hardware-acceleration").HardwareAccelerationOption;
1163
+ getValue: ({ commandLine }: {
1164
+ commandLine: Record<string, unknown>;
1165
+ }) => {
1166
+ source: string;
1167
+ value: "disable" | "if-possible" | "required";
1168
+ };
1169
+ setConfig: (value: import("./options/hardware-acceleration").HardwareAccelerationOption) => void;
1170
+ };
1139
1171
  };
1140
1172
  readonly stitchFramesToVideo: {
1141
1173
  readonly separateAudioTo: {
@@ -1156,6 +1188,21 @@ export declare const BrowserSafeApis: {
1156
1188
  ssrName: string;
1157
1189
  type: string | null;
1158
1190
  };
1191
+ readonly hardwareAcceleration: {
1192
+ name: string;
1193
+ cliFlag: "hardware-acceleration";
1194
+ description: () => string;
1195
+ ssrName: string;
1196
+ docLink: string;
1197
+ type: import("./options/hardware-acceleration").HardwareAccelerationOption;
1198
+ getValue: ({ commandLine }: {
1199
+ commandLine: Record<string, unknown>;
1200
+ }) => {
1201
+ source: string;
1202
+ value: "disable" | "if-possible" | "required";
1203
+ };
1204
+ setConfig: (value: import("./options/hardware-acceleration").HardwareAccelerationOption) => void;
1205
+ };
1159
1206
  };
1160
1207
  readonly renderStill: {
1161
1208
  readonly offthreadVideoCacheSizeInBytes: {
package/dist/client.js CHANGED
@@ -14,6 +14,7 @@ const options_1 = require("./options");
14
14
  const audio_codec_1 = require("./options/audio-codec");
15
15
  const color_space_1 = require("./options/color-space");
16
16
  const gl_1 = require("./options/gl");
17
+ const hardware_acceleration_1 = require("./options/hardware-acceleration");
17
18
  const options_map_1 = require("./options/options-map");
18
19
  const video_codec_1 = require("./options/video-codec");
19
20
  const x264_preset_1 = require("./options/x264-preset");
@@ -28,6 +29,7 @@ exports.BrowserSafeApis = {
28
29
  getValidCrfRanges: crf_1.getValidCrfRanges,
29
30
  proResProfileOptions: prores_profile_1.proResProfileOptions,
30
31
  x264PresetOptions: x264_preset_1.x264PresetOptions,
32
+ hardwareAccelerationOptions: hardware_acceleration_1.hardwareAccelerationOptions,
31
33
  validPixelFormats: pixel_format_1.validPixelFormats,
32
34
  validOpenGlRenderers: gl_1.validOpenGlRenderers,
33
35
  validPixelFormatsForCodec: pixel_format_1.validPixelFormatsForCodec,
@@ -145,7 +145,7 @@ const combineAudioSeamlessly = async ({ files, filelistDir, indent, logLevel, ou
145
145
  }
146
146
  catch (e) {
147
147
  (0, fs_1.rmSync)(fileListTxt, { recursive: true });
148
- console.log(e);
148
+ logger_1.Log.error({ indent, logLevel }, e);
149
149
  throw e;
150
150
  }
151
151
  };
@@ -1,24 +1,4 @@
1
- import type { DownloadMap } from '../assets/download-map';
2
1
  import type { LogLevel } from '../log-level';
3
- import type { Compositor } from './compositor';
4
- import type { CompositorCommand, CompositorCommandSerialized, CompositorImageFormat, Layer } from './payloads';
5
- type CompositorInput = {
6
- height: number;
7
- width: number;
8
- layers: Layer[];
9
- imageFormat: CompositorImageFormat;
10
- };
11
- type ComposeInput = CompositorInput & {
12
- output: string;
13
- compositor: Compositor;
14
- };
2
+ import type { CompositorCommand, CompositorCommandSerialized } from './payloads';
15
3
  export declare const serializeCommand: <Type extends keyof CompositorCommand>(command: Type, params: CompositorCommand[Type]) => CompositorCommandSerialized<Type>;
16
- export declare const composeWithoutCache: ({ height, width, layers, output, imageFormat, compositor, }: CompositorInput & {
17
- output: string;
18
- compositor: Compositor;
19
- }) => Promise<void>;
20
- export declare const compose: ({ height, width, layers, output, downloadMap, imageFormat, compositor, }: ComposeInput & {
21
- downloadMap: DownloadMap;
22
- }) => Promise<void>;
23
4
  export declare const callCompositor: (payload: string, indent: boolean, logLevel: LogLevel, binariesDirectory: string | null) => Promise<void>;
24
- export {};
@@ -3,17 +3,12 @@ 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.callCompositor = exports.compose = exports.composeWithoutCache = exports.serializeCommand = void 0;
6
+ exports.callCompositor = exports.serializeCommand = void 0;
7
7
  const node_child_process_1 = require("node:child_process");
8
- const node_crypto_1 = require("node:crypto");
9
- const promises_1 = require("node:fs/promises");
10
8
  const node_path_1 = __importDefault(require("node:path"));
11
9
  const get_executable_path_1 = require("./get-executable-path");
12
10
  const make_file_executable_1 = require("./make-file-executable");
13
11
  const make_nonce_1 = require("./make-nonce");
14
- const getCompositorHash = ({ ...input }) => {
15
- return (0, node_crypto_1.createHash)('sha256').update(JSON.stringify(input)).digest('base64');
16
- };
17
12
  const serializeCommand = (command, params) => {
18
13
  return {
19
14
  nonce: (0, make_nonce_1.makeNonce)(),
@@ -24,33 +19,6 @@ const serializeCommand = (command, params) => {
24
19
  };
25
20
  };
26
21
  exports.serializeCommand = serializeCommand;
27
- const composeWithoutCache = async ({ height, width, layers, output, imageFormat, compositor, }) => {
28
- await compositor.executeCommand('Compose', {
29
- height,
30
- width,
31
- layers,
32
- output,
33
- output_format: imageFormat,
34
- });
35
- };
36
- exports.composeWithoutCache = composeWithoutCache;
37
- const compose = async ({ height, width, layers, output, downloadMap, imageFormat, compositor, }) => {
38
- const hash = getCompositorHash({ height, width, layers, imageFormat });
39
- if (downloadMap.compositorCache[hash]) {
40
- await (0, promises_1.copyFile)(downloadMap.compositorCache[hash], output);
41
- return;
42
- }
43
- await (0, exports.composeWithoutCache)({
44
- compositor,
45
- height,
46
- imageFormat,
47
- layers,
48
- output,
49
- width,
50
- });
51
- downloadMap.compositorCache[hash] = output;
52
- };
53
- exports.compose = compose;
54
22
  const callCompositor = (payload, indent, logLevel, binariesDirectory) => {
55
23
  return new Promise((resolve, reject) => {
56
24
  const execPath = (0, get_executable_path_1.getExecutablePath)({
@@ -78,7 +46,7 @@ const callCompositor = (payload, indent, logLevel, binariesDirectory) => {
78
46
  const err = new Error(`${msg}\n${parsed.backtrace}`);
79
47
  reject(err);
80
48
  }
81
- catch (err) {
49
+ catch (_a) {
82
50
  reject(new Error(`Compositor panicked with code ${code}: ${message}`));
83
51
  }
84
52
  }
@@ -62,7 +62,7 @@ const startCompositor = ({ type, payload, logLevel, indent, binariesDirectory =
62
62
  const parsed = JSON.parse(new TextDecoder('utf8').decode(data));
63
63
  waiters.get(nonce).reject(new Error(`Compositor error: ${parsed.error}\n${parsed.backtrace}`));
64
64
  }
65
- catch (err) {
65
+ catch (_a) {
66
66
  waiters.get(nonce).reject(new Error(new TextDecoder('utf8').decode(data)));
67
67
  }
68
68
  }
@@ -1,31 +1,3 @@
1
- export type Layer = {
2
- type: 'PngImage';
3
- params: {
4
- src: string;
5
- x: number;
6
- y: number;
7
- width: number;
8
- height: number;
9
- };
10
- } | {
11
- type: 'JpgImage';
12
- params: {
13
- src: string;
14
- x: number;
15
- y: number;
16
- width: number;
17
- height: number;
18
- };
19
- } | {
20
- type: 'Solid';
21
- params: {
22
- fill: [number, number, number, number];
23
- x: number;
24
- y: number;
25
- width: number;
26
- height: number;
27
- };
28
- };
29
1
  export type CompositorImageFormat = 'Png' | 'Jpeg';
30
2
  export type VideoMetadata = {
31
3
  fps: number;
@@ -53,13 +25,6 @@ export type GetSilentPartsResponse = GetSilentPartsResponseRust & {
53
25
  audibleParts: SilentParts;
54
26
  };
55
27
  export type CompositorCommand = {
56
- Compose: {
57
- output: string;
58
- width: number;
59
- height: number;
60
- layers: Layer[];
61
- output_format: CompositorImageFormat;
62
- };
63
28
  ExtractFrame: {
64
29
  src: string;
65
30
  original_src: string;
package/dist/crf.d.ts CHANGED
@@ -1,11 +1,13 @@
1
+ import type { HardwareAccelerationOption } from './client';
1
2
  import type { Codec } from './codec';
2
3
  export type Crf = number | undefined;
3
- export declare const getDefaultCrfForCodec: (codec: Codec) => number;
4
+ export declare const getDefaultCrfForCodec: (codec: Codec) => number | null;
4
5
  export declare const getValidCrfRanges: (codec: Codec) => [number, number];
5
- export declare const validateQualitySettings: ({ codec, crf, videoBitrate, encodingMaxRate, encodingBufferSize, }: {
6
+ export declare const validateQualitySettings: ({ codec, crf, videoBitrate, encodingMaxRate, encodingBufferSize, hardwareAcceleration, }: {
6
7
  crf: unknown;
7
8
  codec: Codec;
8
9
  videoBitrate: string | null;
9
10
  encodingMaxRate: string | null;
10
11
  encodingBufferSize: string | null;
12
+ hardwareAcceleration: HardwareAccelerationOption;
11
13
  }) => string[];
package/dist/crf.js CHANGED
@@ -7,13 +7,13 @@ const defaultCrfMap = {
7
7
  h265: 23,
8
8
  vp8: 9,
9
9
  vp9: 28,
10
- prores: 0,
11
- gif: 0,
10
+ prores: null,
11
+ gif: null,
12
12
  'h264-mkv': 18,
13
13
  'h264-ts': 18,
14
- aac: 0,
15
- mp3: 0,
16
- wav: 0,
14
+ aac: null,
15
+ mp3: null,
16
+ wav: null,
17
17
  };
18
18
  const getDefaultCrfForCodec = (codec) => {
19
19
  const val = defaultCrfMap[codec];
@@ -44,10 +44,13 @@ const getValidCrfRanges = (codec) => {
44
44
  return val;
45
45
  };
46
46
  exports.getValidCrfRanges = getValidCrfRanges;
47
- const validateQualitySettings = ({ codec, crf, videoBitrate, encodingMaxRate, encodingBufferSize, }) => {
47
+ const validateQualitySettings = ({ codec, crf, videoBitrate, encodingMaxRate, encodingBufferSize, hardwareAcceleration, }) => {
48
48
  if (crf && videoBitrate) {
49
49
  throw new Error('"crf" and "videoBitrate" can not both be set. Choose one of either.');
50
50
  }
51
+ if (crf && hardwareAcceleration === 'required') {
52
+ throw new Error('"crf" option is not supported with hardware acceleration');
53
+ }
51
54
  if (encodingMaxRate && !encodingBufferSize) {
52
55
  throw new Error('"encodingMaxRate" can not be set without also setting "encodingBufferSize".');
53
56
  }
@@ -68,6 +71,9 @@ const validateQualitySettings = ({ codec, crf, videoBitrate, encodingMaxRate, en
68
71
  }
69
72
  if (crf === null || typeof crf === 'undefined') {
70
73
  const actualCrf = (0, exports.getDefaultCrfForCodec)(codec);
74
+ if (actualCrf === null) {
75
+ return [...bufSizeArray, ...maxRateArray];
76
+ }
71
77
  return ['-crf', String(actualCrf), ...bufSizeArray, ...maxRateArray];
72
78
  }
73
79
  if (typeof crf !== 'number') {
@@ -48,7 +48,7 @@ const deleteDirectory = (directory) => {
48
48
  retryDelay: 100,
49
49
  });
50
50
  }
51
- catch (err) {
51
+ catch (_a) {
52
52
  retries--;
53
53
  continue;
54
54
  }
@@ -53,6 +53,7 @@ const handleJavascriptException = ({ page, onError, frame, }) => {
53
53
  const rawErrorMessage = (_a = exception.exceptionDetails.exception) === null || _a === void 0 ? void 0 : _a.description;
54
54
  const cleanErrorMessage = cleanUpErrorMessage(exception);
55
55
  if (!cleanErrorMessage) {
56
+ // eslint-disable-next-line no-console
56
57
  console.error(exception);
57
58
  const err = new Error(rawErrorMessage);
58
59
  err.stack = rawErrorMessage;
@@ -1,8 +1,10 @@
1
+ import type { HardwareAccelerationOption } from './client';
1
2
  import type { Codec } from './codec';
3
+ import type { LogLevel } from './log-level';
2
4
  import { type ColorSpace } from './options/color-space';
3
5
  import type { X264Preset } from './options/x264-preset';
4
6
  import type { PixelFormat } from './pixel-format';
5
- export declare const generateFfmpegArgs: ({ hasPreencoded, proResProfileName, pixelFormat, x264Preset, codec, crf, videoBitrate, encodingMaxRate, encodingBufferSize, colorSpace, }: {
7
+ export declare const generateFfmpegArgs: ({ hasPreencoded, proResProfileName, pixelFormat, x264Preset, codec, crf, videoBitrate, encodingMaxRate, encodingBufferSize, colorSpace, hardwareAcceleration, indent, logLevel, }: {
6
8
  hasPreencoded: boolean;
7
9
  proResProfileName: string | null;
8
10
  pixelFormat: PixelFormat;
@@ -13,4 +15,7 @@ export declare const generateFfmpegArgs: ({ hasPreencoded, proResProfileName, pi
13
15
  encodingMaxRate: string | null;
14
16
  encodingBufferSize: string | null;
15
17
  colorSpace: ColorSpace | null;
18
+ hardwareAcceleration: HardwareAccelerationOption;
19
+ indent: boolean;
20
+ logLevel: LogLevel;
16
21
  }) => string[][];
@@ -3,9 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.generateFfmpegArgs = void 0;
4
4
  const crf_1 = require("./crf");
5
5
  const get_codec_name_1 = require("./get-codec-name");
6
+ const logger_1 = require("./logger");
6
7
  const color_space_1 = require("./options/color-space");
7
8
  const truthy_1 = require("./truthy");
8
- const firstEncodingStepOnly = ({ hasPreencoded, proResProfileName, pixelFormat, x264Preset, codec, crf, videoBitrate, encodingMaxRate, encodingBufferSize, }) => {
9
+ const firstEncodingStepOnly = ({ hasPreencoded, proResProfileName, pixelFormat, x264Preset, codec, crf, videoBitrate, encodingMaxRate, encodingBufferSize, hardwareAcceleration, }) => {
9
10
  if (hasPreencoded || codec === 'gif') {
10
11
  return [];
11
12
  }
@@ -22,14 +23,21 @@ const firstEncodingStepOnly = ({ hasPreencoded, proResProfileName, pixelFormat,
22
23
  codec,
23
24
  encodingMaxRate,
24
25
  encodingBufferSize,
26
+ hardwareAcceleration,
25
27
  }),
26
28
  ].filter(truthy_1.truthy);
27
29
  };
28
- const generateFfmpegArgs = ({ hasPreencoded, proResProfileName, pixelFormat, x264Preset, codec, crf, videoBitrate, encodingMaxRate, encodingBufferSize, colorSpace, }) => {
29
- const encoderName = (0, get_codec_name_1.getCodecName)(codec);
30
- if (encoderName === null) {
31
- throw new TypeError('encoderName is null: ' + JSON.stringify(codec));
30
+ const generateFfmpegArgs = ({ hasPreencoded, proResProfileName, pixelFormat, x264Preset, codec, crf, videoBitrate, encodingMaxRate, encodingBufferSize, colorSpace, hardwareAcceleration, indent, logLevel, }) => {
31
+ const encoderSettings = (0, get_codec_name_1.getCodecName)(codec, hardwareAcceleration === 'required' ||
32
+ hardwareAcceleration === 'if-possible');
33
+ if (encoderSettings === null) {
34
+ throw new TypeError(`encoderSettings is null: ${JSON.stringify(codec)} (hwaccel = ${hardwareAcceleration})`);
32
35
  }
36
+ const { encoderName, hardwareAccelerated } = encoderSettings;
37
+ if (!hardwareAccelerated && hardwareAcceleration === 'required') {
38
+ throw new Error(`Codec ${codec} does not support hardware acceleration on ${process.platform}, but "hardwareAcceleration" is set to "required"`);
39
+ }
40
+ logger_1.Log.verbose({ indent, logLevel, tag: 'stitchFramesToVideo()' }, `Encoder: ${encoderName}, hardware accelerated: ${hardwareAccelerated}`);
33
41
  const resolvedColorSpace = colorSpace !== null && colorSpace !== void 0 ? colorSpace : color_space_1.DEFAULT_COLOR_SPACE;
34
42
  const colorSpaceOptions = resolvedColorSpace === 'bt709'
35
43
  ? [
@@ -74,6 +82,7 @@ const generateFfmpegArgs = ({ hasPreencoded, proResProfileName, pixelFormat, x26
74
82
  encodingMaxRate,
75
83
  encodingBufferSize,
76
84
  x264Preset,
85
+ hardwareAcceleration,
77
86
  }),
78
87
  ].filter(truthy_1.truthy);
79
88
  };
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getPageAndCleanupFn = void 0;
4
4
  const browser_1 = require("./browser");
5
+ const logger_1 = require("./logger");
5
6
  const open_browser_1 = require("./open-browser");
6
7
  const getPageAndCleanupFn = async ({ passedInInstance, browserExecutable, chromiumOptions, forceDeviceScaleFactor, indent, logLevel, onBrowserDownload, }) => {
7
8
  if (passedInInstance) {
@@ -13,7 +14,7 @@ const getPageAndCleanupFn = async ({ passedInInstance, browserExecutable, chromi
13
14
  // Keep browser open.
14
15
  page.close().catch((err) => {
15
16
  if (!err.message.includes('Target closed')) {
16
- console.error('Was not able to close puppeteer page', err);
17
+ logger_1.Log.error({ indent, logLevel }, 'Was not able to close puppeteer page', err);
17
18
  }
18
19
  });
19
20
  return Promise.resolve();
@@ -37,7 +38,7 @@ const getPageAndCleanupFn = async ({ passedInInstance, browserExecutable, chromi
37
38
  // Close whole browser that was just created and don't wait for it to finish.
38
39
  browserInstance.close(true, logLevel, indent).catch((err) => {
39
40
  if (!err.message.includes('Target closed')) {
40
- console.error('Was not able to close puppeteer page', err);
41
+ logger_1.Log.error({ indent, logLevel }, 'Was not able to close puppeteer page', err);
41
42
  }
42
43
  });
43
44
  return Promise.resolve();
@@ -1,2 +1,6 @@
1
1
  import type { Codec } from './codec';
2
- export declare const getCodecName: (codec: Codec) => string | null;
2
+ export type CodecSettings = {
3
+ encoderName: string;
4
+ hardwareAccelerated: boolean;
5
+ };
6
+ export declare const getCodecName: (codec: Codec, preferredHwAcceleration: boolean) => CodecSettings | null;
@@ -1,20 +1,43 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getCodecName = void 0;
4
- const map = {
5
- h264: 'libx264',
6
- h265: 'libx265',
7
- vp8: 'libvpx',
8
- vp9: 'libvpx-vp9',
9
- prores: 'prores_ks',
10
- gif: 'gif',
11
- mp3: null,
12
- aac: null,
13
- wav: null,
14
- 'h264-mkv': 'libx264',
15
- 'h264-ts': 'libx264',
16
- };
17
- const getCodecName = (codec) => {
18
- return map[codec];
4
+ const getCodecName = (codec, preferredHwAcceleration) => {
5
+ if (codec === 'prores') {
6
+ if (preferredHwAcceleration && process.platform === 'darwin') {
7
+ return { encoderName: 'prores_videotoolbox', hardwareAccelerated: true };
8
+ }
9
+ return { encoderName: 'prores_ks', hardwareAccelerated: false };
10
+ }
11
+ if (codec === 'h264') {
12
+ return { encoderName: 'libx264', hardwareAccelerated: false };
13
+ }
14
+ if (codec === 'h265') {
15
+ return { encoderName: 'libx265', hardwareAccelerated: false };
16
+ }
17
+ if (codec === 'vp8') {
18
+ return { encoderName: 'libvpx', hardwareAccelerated: false };
19
+ }
20
+ if (codec === 'vp9') {
21
+ return { encoderName: 'libvpx-vp9', hardwareAccelerated: false };
22
+ }
23
+ if (codec === 'gif') {
24
+ return { encoderName: 'gif', hardwareAccelerated: false };
25
+ }
26
+ if (codec === 'mp3') {
27
+ return null;
28
+ }
29
+ if (codec === 'aac') {
30
+ return null;
31
+ }
32
+ if (codec === 'wav') {
33
+ return null;
34
+ }
35
+ if (codec === 'h264-mkv') {
36
+ return { encoderName: 'libx264', hardwareAccelerated: false };
37
+ }
38
+ if (codec === 'h264-ts') {
39
+ return { encoderName: 'libx264', hardwareAccelerated: false };
40
+ }
41
+ throw new Error(`Could not get codec for ${codec}`);
19
42
  };
20
43
  exports.getCodecName = getCodecName;
@@ -11,7 +11,7 @@ const getConcurrencyFromNProc = () => {
11
11
  try {
12
12
  return parseInt((0, node_child_process_1.execSync)('nproc', { stdio: 'pipe' }).toString().trim(), 10);
13
13
  }
14
- catch (error) {
14
+ catch (_a) {
15
15
  return null;
16
16
  }
17
17
  };
@@ -1,2 +1,7 @@
1
1
  import type { BrowserExecutable } from './browser-executable';
2
- export declare const getLocalBrowserExecutable: (preferredBrowserExecutable: BrowserExecutable) => string;
2
+ import type { LogLevel } from './log-level';
3
+ export declare const getLocalBrowserExecutable: ({ preferredBrowserExecutable, logLevel, indent, }: {
4
+ preferredBrowserExecutable: BrowserExecutable;
5
+ logLevel: LogLevel;
6
+ indent: boolean;
7
+ }) => string;
@@ -7,10 +7,11 @@ exports.getLocalBrowserExecutable = void 0;
7
7
  const node_fs_1 = __importDefault(require("node:fs"));
8
8
  const BrowserFetcher_1 = require("./browser/BrowserFetcher");
9
9
  const get_local_browser_1 = require("./get-local-browser");
10
- const getBrowserStatus = (browserExecutablePath) => {
10
+ const logger_1 = require("./logger");
11
+ const getBrowserStatus = ({ browserExecutablePath, indent, logLevel, }) => {
11
12
  if (browserExecutablePath) {
12
13
  if (!node_fs_1.default.existsSync(browserExecutablePath)) {
13
- console.warn(`Browser executable was specified as '${browserExecutablePath}' but the path doesn't exist.`);
14
+ logger_1.Log.warn({ indent, logLevel }, `Browser executable was specified as '${browserExecutablePath}' but the path doesn't exist.`);
14
15
  }
15
16
  return { path: browserExecutablePath, type: 'user-defined-path' };
16
17
  }
@@ -24,8 +25,12 @@ const getBrowserStatus = (browserExecutablePath) => {
24
25
  }
25
26
  return { type: 'no-browser' };
26
27
  };
27
- const getLocalBrowserExecutable = (preferredBrowserExecutable) => {
28
- const status = getBrowserStatus(preferredBrowserExecutable);
28
+ const getLocalBrowserExecutable = ({ preferredBrowserExecutable, logLevel, indent, }) => {
29
+ const status = getBrowserStatus({
30
+ browserExecutablePath: preferredBrowserExecutable,
31
+ indent,
32
+ logLevel,
33
+ });
29
34
  if (status.type === 'no-browser') {
30
35
  throw new TypeError('No browser found for rendering frames! Please open a GitHub issue and describe ' +
31
36
  'how you reached this error: https://remotion.dev/issue');
package/dist/get-port.js CHANGED
@@ -61,6 +61,7 @@ const getDesiredPort = async ({ desiredPort, from, hostsToTry, to, }) => {
61
61
  const actualPort = await getPort({ from, to, hostsToTest: hostsToTry });
62
62
  // If did specify a port but did not get that one, fail hard.
63
63
  if (desiredPort && desiredPort !== actualPort) {
64
+ unlockPort();
64
65
  throw new Error(`You specified port ${desiredPort} to be used for the HTTP server, but it is not available. Choose a different port or remove the setting to let Remotion automatically select a free port.`);
65
66
  }
66
67
  return { port: actualPort, unlockPort };
package/dist/index.d.ts CHANGED
@@ -353,7 +353,7 @@ export declare const RenderInternals: {
353
353
  validStillImageFormats: readonly ["png", "jpeg", "pdf", "webp"];
354
354
  validVideoImageFormats: readonly ["png", "jpeg", "none"];
355
355
  DEFAULT_STILL_IMAGE_FORMAT: "png" | "jpeg" | "pdf" | "webp";
356
- DEFAULT_VIDEO_IMAGE_FORMAT: "png" | "jpeg" | "none";
356
+ DEFAULT_VIDEO_IMAGE_FORMAT: "none" | "png" | "jpeg";
357
357
  DEFAULT_JPEG_QUALITY: number;
358
358
  chalk: {
359
359
  enabled: () => boolean;
@@ -408,12 +408,12 @@ export declare const RenderInternals: {
408
408
  Log: {
409
409
  verbose: (options: import("./logger").LogOptions & {
410
410
  tag?: string;
411
- }, ...args: Parameters<typeof console.log>) => void;
412
- info: (options: import("./logger").LogOptions, ...args: Parameters<typeof console.log>) => void;
413
- warn: (options: import("./logger").LogOptions, ...args: Parameters<typeof console.log>) => void;
411
+ }, ...args: Parameters<typeof console.log>) => boolean | void;
412
+ info: (options: import("./logger").LogOptions, ...args: Parameters<typeof console.log>) => boolean | void;
413
+ warn: (options: import("./logger").LogOptions, ...args: Parameters<typeof console.log>) => boolean | void;
414
414
  error: (options: import("./logger").LogOptions & {
415
415
  tag?: string;
416
- }, ...args: Parameters<typeof console.log>) => void;
416
+ }, ...args: Parameters<typeof console.log>) => boolean | void;
417
417
  };
418
418
  INDENT_TOKEN: string;
419
419
  isColorSupported: () => boolean;
package/dist/logger.d.ts CHANGED
@@ -10,9 +10,9 @@ type VerboseLogOptions = LogOptions & {
10
10
  export declare const verboseTag: (str: string) => string;
11
11
  export declare const secondverboseTag: (str: string) => string;
12
12
  export declare const Log: {
13
- verbose: (options: VerboseLogOptions, ...args: Parameters<typeof console.log>) => void;
14
- info: (options: LogOptions, ...args: Parameters<typeof console.log>) => void;
15
- warn: (options: LogOptions, ...args: Parameters<typeof console.log>) => void;
16
- error: (options: VerboseLogOptions, ...args: Parameters<typeof console.log>) => void;
13
+ verbose: (options: VerboseLogOptions, ...args: Parameters<typeof console.log>) => boolean | void;
14
+ info: (options: LogOptions, ...args: Parameters<typeof console.log>) => boolean | void;
15
+ warn: (options: LogOptions, ...args: Parameters<typeof console.log>) => boolean | void;
16
+ error: (options: VerboseLogOptions, ...args: Parameters<typeof console.log>) => boolean | void;
17
17
  };
18
18
  export {};