@remotion/renderer 4.0.46 → 4.0.48

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
@@ -38,4 +38,4 @@ Support is provided on a best-we-can-do basis via GitHub Issues and Discord.
38
38
 
39
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
- Visit [companies.remotion.dev](https://companies.remotion.dev) for pricing and to buy a license.
41
+ Visit [remotion.pro](https://www.remotion.pro) for pricing and to buy a license.
@@ -43,6 +43,7 @@ const calculateAssetPositions = (frames) => {
43
43
  volume: [],
44
44
  playbackRate: asset.playbackRate,
45
45
  allowAmplificationDuringRender: asset.allowAmplificationDuringRender,
46
+ toneFrequency: asset.toneFrequency,
46
47
  });
47
48
  }
48
49
  const found = assets.find((a) => a.duration === null && areEqual(a, asset));
@@ -7,6 +7,7 @@ export type UnsafeAsset = Omit<TRenderAsset, 'frame' | 'id' | 'volume' | 'mediaF
7
7
  id: string;
8
8
  playbackRate: number;
9
9
  allowAmplificationDuringRender: boolean;
10
+ toneFrequency: number | null;
10
11
  };
11
12
  export type AssetVolume = number | number[];
12
13
  export type MediaAsset = Omit<UnsafeAsset, 'duration' | 'volume'> & {
@@ -32,14 +32,24 @@ export declare const enum BrowserEmittedEvents {
32
32
  }
33
33
  export declare class HeadlessBrowser extends EventEmitter {
34
34
  #private;
35
- static _create({ connection, defaultViewport, closeCallback, }: {
35
+ static _create({ connection, defaultViewport, closeCallback, forgetEventLoop, rememberEventLoop, }: {
36
36
  connection: Connection;
37
37
  defaultViewport: Viewport;
38
38
  closeCallback: BrowserCloseCallback;
39
+ forgetEventLoop: () => void;
40
+ rememberEventLoop: () => void;
39
41
  }): Promise<HeadlessBrowser>;
40
42
  connection: Connection;
43
+ forgetEventLoop: () => void;
44
+ rememberEventLoop: () => void;
41
45
  get _targets(): Map<string, Target>;
42
- constructor(connection: Connection, defaultViewport: Viewport, closeCallback?: BrowserCloseCallback);
46
+ constructor({ closeCallback, connection, defaultViewport, forgetEventLoop, rememberEventLoop, }: {
47
+ connection: Connection;
48
+ defaultViewport: Viewport;
49
+ closeCallback: BrowserCloseCallback;
50
+ forgetEventLoop: () => void;
51
+ rememberEventLoop: () => void;
52
+ });
43
53
  browserContexts(): BrowserContext[];
44
54
  newPage(context: Promise<AnySourceMapConsumer | null>, logLevel: LogLevel, indent: boolean): Promise<Page>;
45
55
  _createPageInContext(context: Promise<AnySourceMapConsumer | null>, logLevel: LogLevel, indent: boolean): Promise<Page>;
@@ -33,15 +33,21 @@ const EventEmitter_1 = require("./EventEmitter");
33
33
  const Target_1 = require("./Target");
34
34
  const util_1 = require("./util");
35
35
  class HeadlessBrowser extends EventEmitter_1.EventEmitter {
36
- static async _create({ connection, defaultViewport, closeCallback, }) {
37
- const browser = new HeadlessBrowser(connection, defaultViewport, closeCallback);
36
+ static async _create({ connection, defaultViewport, closeCallback, forgetEventLoop, rememberEventLoop, }) {
37
+ const browser = new HeadlessBrowser({
38
+ connection,
39
+ defaultViewport,
40
+ closeCallback,
41
+ forgetEventLoop,
42
+ rememberEventLoop,
43
+ });
38
44
  await connection.send('Target.setDiscoverTargets', { discover: true });
39
45
  return browser;
40
46
  }
41
47
  get _targets() {
42
48
  return __classPrivateFieldGet(this, _HeadlessBrowser_targets, "f");
43
49
  }
44
- constructor(connection, defaultViewport, closeCallback) {
50
+ constructor({ closeCallback, connection, defaultViewport, forgetEventLoop, rememberEventLoop, }) {
45
51
  super();
46
52
  _HeadlessBrowser_instances.add(this);
47
53
  _HeadlessBrowser_defaultViewport.set(this, void 0);
@@ -51,16 +57,15 @@ class HeadlessBrowser extends EventEmitter_1.EventEmitter {
51
57
  _HeadlessBrowser_targets.set(this, void 0);
52
58
  __classPrivateFieldSet(this, _HeadlessBrowser_defaultViewport, defaultViewport, "f");
53
59
  this.connection = connection;
54
- __classPrivateFieldSet(this, _HeadlessBrowser_closeCallback, closeCallback ||
55
- function () {
56
- return undefined;
57
- }, "f");
60
+ __classPrivateFieldSet(this, _HeadlessBrowser_closeCallback, closeCallback, "f");
58
61
  __classPrivateFieldSet(this, _HeadlessBrowser_defaultContext, new BrowserContext(this), "f");
59
62
  __classPrivateFieldSet(this, _HeadlessBrowser_contexts, new Map(), "f");
60
63
  __classPrivateFieldSet(this, _HeadlessBrowser_targets, new Map(), "f");
61
64
  this.connection.on('Target.targetCreated', __classPrivateFieldGet(this, _HeadlessBrowser_instances, "m", _HeadlessBrowser_targetCreated).bind(this));
62
65
  this.connection.on('Target.targetDestroyed', __classPrivateFieldGet(this, _HeadlessBrowser_instances, "m", _HeadlessBrowser_targetDestroyed).bind(this));
63
66
  this.connection.on('Target.targetInfoChanged', __classPrivateFieldGet(this, _HeadlessBrowser_instances, "m", _HeadlessBrowser_targetInfoChanged).bind(this));
67
+ this.forgetEventLoop = forgetEventLoop;
68
+ this.rememberEventLoop = rememberEventLoop;
64
69
  }
65
70
  browserContexts() {
66
71
  return [__classPrivateFieldGet(this, _HeadlessBrowser_defaultContext, "f"), ...Array.from(__classPrivateFieldGet(this, _HeadlessBrowser_contexts, "f").values())];
@@ -28,6 +28,8 @@ export declare class BrowserRunner {
28
28
  });
29
29
  start(options: LaunchOptions): void;
30
30
  close(): Promise<void>;
31
+ forgetEventLoop(): void;
32
+ rememberEventLoop(): void;
31
33
  kill(): void;
32
34
  setupConnection(options: {
33
35
  timeout: number;
@@ -153,6 +153,28 @@ class BrowserRunner {
153
153
  (0, util_1.removeEventListeners)(__classPrivateFieldGet(this, _BrowserRunner_listeners, "f"));
154
154
  return __classPrivateFieldGet(this, _BrowserRunner_processClosing, "f");
155
155
  }
156
+ forgetEventLoop() {
157
+ var _a, _b;
158
+ (0, assert_1.assert)(this.proc, 'BrowserRunner not started.');
159
+ this.proc.unref();
160
+ // @ts-expect-error
161
+ (_a = this.proc.stdout) === null || _a === void 0 ? void 0 : _a.unref();
162
+ // @ts-expect-error
163
+ (_b = this.proc.stderr) === null || _b === void 0 ? void 0 : _b.unref();
164
+ (0, assert_1.assert)(this.connection, 'BrowserRunner not connected.');
165
+ this.connection.transport.forgetEventLoop();
166
+ }
167
+ rememberEventLoop() {
168
+ var _a, _b;
169
+ (0, assert_1.assert)(this.proc, 'BrowserRunner not started.');
170
+ this.proc.ref();
171
+ // @ts-expect-error
172
+ (_a = this.proc.stdout) === null || _a === void 0 ? void 0 : _a.ref();
173
+ // @ts-expect-error
174
+ (_b = this.proc.stderr) === null || _b === void 0 ? void 0 : _b.ref();
175
+ (0, assert_1.assert)(this.connection, 'BrowserRunner not connected.');
176
+ this.connection.transport.rememberEventLoop();
177
+ }
156
178
  kill() {
157
179
  var _a;
158
180
  // If the process failed to launch (for example if the browser executable path
@@ -4,6 +4,7 @@ import { EventEmitter } from './EventEmitter';
4
4
  import type { NodeWebSocketTransport } from './NodeWebSocketTransport';
5
5
  export declare class Connection extends EventEmitter {
6
6
  #private;
7
+ transport: NodeWebSocketTransport;
7
8
  constructor(transport: NodeWebSocketTransport);
8
9
  static fromSession(session: CDPSession): Connection | undefined;
9
10
  session(sessionId: string): CDPSession | null;
@@ -1,16 +1,16 @@
1
1
  "use strict";
2
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
3
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
4
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
5
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
6
+ };
2
7
  var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
3
8
  if (kind === "m") throw new TypeError("Private method is not writable");
4
9
  if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
5
10
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
6
11
  return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
7
12
  };
8
- var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
9
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
10
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
- };
13
- var _Connection_instances, _Connection_transport, _Connection_lastId, _Connection_sessions, _Connection_closed, _Connection_callbacks, _Connection_onMessage, _Connection_onClose, _CDPSession_sessionId, _CDPSession_targetType, _CDPSession_callbacks, _CDPSession_connection;
13
+ var _Connection_instances, _Connection_lastId, _Connection_sessions, _Connection_closed, _Connection_callbacks, _Connection_onMessage, _Connection_onClose, _CDPSession_sessionId, _CDPSession_targetType, _CDPSession_callbacks, _CDPSession_connection;
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.CDPSession = exports.CDPSessionEmittedEvents = exports.Connection = void 0;
16
16
  /**
@@ -38,14 +38,13 @@ class Connection extends EventEmitter_1.EventEmitter {
38
38
  constructor(transport) {
39
39
  super();
40
40
  _Connection_instances.add(this);
41
- _Connection_transport.set(this, void 0);
42
41
  _Connection_lastId.set(this, 0);
43
42
  _Connection_sessions.set(this, new Map());
44
43
  _Connection_closed.set(this, false);
45
44
  _Connection_callbacks.set(this, new Map());
46
- __classPrivateFieldSet(this, _Connection_transport, transport, "f");
47
- __classPrivateFieldGet(this, _Connection_transport, "f").onmessage = __classPrivateFieldGet(this, _Connection_instances, "m", _Connection_onMessage).bind(this);
48
- __classPrivateFieldGet(this, _Connection_transport, "f").onclose = __classPrivateFieldGet(this, _Connection_instances, "m", _Connection_onClose).bind(this);
45
+ this.transport = transport;
46
+ this.transport.onmessage = __classPrivateFieldGet(this, _Connection_instances, "m", _Connection_onMessage).bind(this);
47
+ this.transport.onclose = __classPrivateFieldGet(this, _Connection_instances, "m", _Connection_onClose).bind(this);
49
48
  }
50
49
  static fromSession(session) {
51
50
  return session.connection();
@@ -75,12 +74,12 @@ class Connection extends EventEmitter_1.EventEmitter {
75
74
  var _a;
76
75
  const id = __classPrivateFieldSet(this, _Connection_lastId, (_a = __classPrivateFieldGet(this, _Connection_lastId, "f"), ++_a), "f");
77
76
  const stringifiedMessage = JSON.stringify({ ...message, id });
78
- __classPrivateFieldGet(this, _Connection_transport, "f").send(stringifiedMessage);
77
+ this.transport.send(stringifiedMessage);
79
78
  return id;
80
79
  }
81
80
  dispose() {
82
81
  __classPrivateFieldGet(this, _Connection_instances, "m", _Connection_onClose).call(this);
83
- __classPrivateFieldGet(this, _Connection_transport, "f").close();
82
+ this.transport.close();
84
83
  }
85
84
  /**
86
85
  * @param targetInfo - The target info
@@ -99,7 +98,7 @@ class Connection extends EventEmitter_1.EventEmitter {
99
98
  }
100
99
  }
101
100
  exports.Connection = Connection;
102
- _Connection_transport = new WeakMap(), _Connection_lastId = new WeakMap(), _Connection_sessions = new WeakMap(), _Connection_closed = new WeakMap(), _Connection_callbacks = new WeakMap(), _Connection_instances = new WeakSet(), _Connection_onMessage = function _Connection_onMessage(message) {
101
+ _Connection_lastId = new WeakMap(), _Connection_sessions = new WeakMap(), _Connection_closed = new WeakMap(), _Connection_callbacks = new WeakMap(), _Connection_instances = new WeakSet(), _Connection_onMessage = function _Connection_onMessage(message) {
103
102
  const object = JSON.parse(message);
104
103
  if (object.method === 'Target.attachedToTarget') {
105
104
  const { sessionId } = object.params;
@@ -152,8 +151,8 @@ _Connection_transport = new WeakMap(), _Connection_lastId = new WeakMap(), _Conn
152
151
  if (__classPrivateFieldGet(this, _Connection_closed, "f")) {
153
152
  return;
154
153
  }
155
- __classPrivateFieldGet(this, _Connection_transport, "f").onmessage = undefined;
156
- __classPrivateFieldGet(this, _Connection_transport, "f").onclose = undefined;
154
+ this.transport.onmessage = undefined;
155
+ this.transport.onclose = undefined;
157
156
  for (const callback of __classPrivateFieldGet(this, _Connection_callbacks, "f").values()) {
158
157
  callback.reject(rewriteError(new Errors_1.ProtocolError(), `Protocol error (${callback.method}): Target closed. https://www.remotion.dev/docs/target-closed`));
159
158
  }
@@ -92,6 +92,8 @@ class ChromeLauncher {
92
92
  connection,
93
93
  defaultViewport,
94
94
  closeCallback: runner.close.bind(runner),
95
+ forgetEventLoop: runner.forgetEventLoop.bind(runner),
96
+ rememberEventLoop: runner.rememberEventLoop.bind(runner),
95
97
  });
96
98
  }
97
99
  catch (error) {
@@ -6,12 +6,14 @@ interface ConnectionTransport {
6
6
  onclose?: () => void;
7
7
  }
8
8
  export declare class NodeWebSocketTransport implements ConnectionTransport {
9
- #private;
10
9
  static create(urlString: string): Promise<NodeWebSocketTransport>;
10
+ websocket: WS;
11
11
  onmessage?: (message: string) => void;
12
12
  onclose?: () => void;
13
13
  constructor(ws: WS);
14
14
  send(message: string): void;
15
15
  close(): void;
16
+ forgetEventLoop(): void;
17
+ rememberEventLoop(): void;
16
18
  }
17
19
  export {};
@@ -1,16 +1,4 @@
1
1
  "use strict";
2
- var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
3
- if (kind === "m") throw new TypeError("Private method is not writable");
4
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
5
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
6
- return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
7
- };
8
- var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
9
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
10
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
- };
13
- var _NodeWebSocketTransport_ws;
14
2
  Object.defineProperty(exports, "__esModule", { value: true });
15
3
  exports.NodeWebSocketTransport = void 0;
16
4
  /**
@@ -61,27 +49,33 @@ class NodeWebSocketTransport {
61
49
  });
62
50
  }
63
51
  constructor(ws) {
64
- _NodeWebSocketTransport_ws.set(this, void 0);
65
- __classPrivateFieldSet(this, _NodeWebSocketTransport_ws, ws, "f");
66
- __classPrivateFieldGet(this, _NodeWebSocketTransport_ws, "f").addEventListener('message', (event) => {
52
+ this.websocket = ws;
53
+ this.websocket.addEventListener('message', (event) => {
67
54
  if (this.onmessage) {
68
55
  this.onmessage.call(null, event.data);
69
56
  }
70
57
  });
71
- __classPrivateFieldGet(this, _NodeWebSocketTransport_ws, "f").addEventListener('close', () => {
58
+ this.websocket.addEventListener('close', () => {
72
59
  if (this.onclose) {
73
60
  this.onclose.call(null);
74
61
  }
75
62
  });
76
63
  // Silently ignore all errors - we don't know what to do with them.
77
- __classPrivateFieldGet(this, _NodeWebSocketTransport_ws, "f").addEventListener('error', () => undefined);
64
+ this.websocket.addEventListener('error', () => undefined);
78
65
  }
79
66
  send(message) {
80
- __classPrivateFieldGet(this, _NodeWebSocketTransport_ws, "f").send(message);
67
+ this.websocket.send(message);
81
68
  }
82
69
  close() {
83
- __classPrivateFieldGet(this, _NodeWebSocketTransport_ws, "f").close();
70
+ this.websocket.close();
71
+ }
72
+ forgetEventLoop() {
73
+ // @ts-expect-error
74
+ this.websocket._socket.unref();
75
+ }
76
+ rememberEventLoop() {
77
+ // @ts-expect-error
78
+ this.websocket._socket.ref();
84
79
  }
85
80
  }
86
81
  exports.NodeWebSocketTransport = NodeWebSocketTransport;
87
- _NodeWebSocketTransport_ws = new WeakMap();
@@ -20,6 +20,7 @@ const calculateFfmpegFilter = ({ asset, fps, durationInFrames, channels, assetDu
20
20
  durationInFrames,
21
21
  assetDuration,
22
22
  allowAmplificationDuringRender: asset.allowAmplificationDuringRender,
23
+ toneFrequency: asset.toneFrequency,
23
24
  });
24
25
  };
25
26
  exports.calculateFfmpegFilter = calculateFfmpegFilter;
package/dist/client.d.ts CHANGED
@@ -1,10 +1,11 @@
1
+ /// <reference types="react" />
1
2
  export declare const BrowserSafeApis: {
2
- getFileExtensionFromCodec: <T extends "aac" | "mp3" | "h264" | "h265" | "vp8" | "vp9" | "wav" | "prores" | "h264-mkv" | "gif">(codec: T, audioCodec: "pcm-16" | "aac" | "mp3" | "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;
3
4
  validCodecs: readonly ["h264", "h265", "vp8", "vp9", "mp3", "aac", "wav", "prores", "h264-mkv", "gif"];
4
5
  validAudioCodecs: readonly ["pcm-16", "aac", "mp3", "opus"];
5
- getDefaultCrfForCodec: (codec: "aac" | "mp3" | "h264" | "h265" | "vp8" | "vp9" | "wav" | "prores" | "h264-mkv" | "gif") => number;
6
- getValidCrfRanges: (codec: "aac" | "mp3" | "h264" | "h265" | "vp8" | "vp9" | "wav" | "prores" | "h264-mkv" | "gif") => [number, number];
7
- isAudioCodec: (codec: "aac" | "mp3" | "h264" | "h265" | "vp8" | "vp9" | "wav" | "prores" | "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;
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"];
10
11
  validPixelFormats: readonly ["yuv420p", "yuva420p", "yuv422p", "yuv444p", "yuv420p10le", "yuv422p10le", "yuv444p10le", "yuva444p10le"];
@@ -22,10 +23,10 @@ export declare const BrowserSafeApis: {
22
23
  readonly wav: readonly ["pcm-16"];
23
24
  };
24
25
  defaultFileExtensionMap: {
25
- aac: {
26
+ h264: {
26
27
  default: import("./file-extensions").FileExtension;
27
28
  forAudioCodec: {
28
- "pcm-16": {
29
+ mp3: {
29
30
  possible: import("./file-extensions").FileExtension[];
30
31
  default: import("./file-extensions").FileExtension;
31
32
  };
@@ -33,72 +34,72 @@ export declare const BrowserSafeApis: {
33
34
  possible: import("./file-extensions").FileExtension[];
34
35
  default: import("./file-extensions").FileExtension;
35
36
  };
37
+ "pcm-16": {
38
+ possible: import("./file-extensions").FileExtension[];
39
+ default: import("./file-extensions").FileExtension;
40
+ };
36
41
  };
37
42
  };
38
- mp3: {
43
+ h265: {
39
44
  default: import("./file-extensions").FileExtension;
40
45
  forAudioCodec: {
41
- "pcm-16": {
46
+ aac: {
42
47
  possible: import("./file-extensions").FileExtension[];
43
48
  default: import("./file-extensions").FileExtension;
44
49
  };
45
- mp3: {
50
+ "pcm-16": {
46
51
  possible: import("./file-extensions").FileExtension[];
47
52
  default: import("./file-extensions").FileExtension;
48
53
  };
49
54
  };
50
55
  };
51
- h264: {
56
+ vp8: {
52
57
  default: import("./file-extensions").FileExtension;
53
58
  forAudioCodec: {
54
59
  "pcm-16": {
55
60
  possible: import("./file-extensions").FileExtension[];
56
61
  default: import("./file-extensions").FileExtension;
57
62
  };
58
- aac: {
59
- possible: import("./file-extensions").FileExtension[];
60
- default: import("./file-extensions").FileExtension;
61
- };
62
- mp3: {
63
+ opus: {
63
64
  possible: import("./file-extensions").FileExtension[];
64
65
  default: import("./file-extensions").FileExtension;
65
66
  };
66
67
  };
67
68
  };
68
- h265: {
69
+ vp9: {
69
70
  default: import("./file-extensions").FileExtension;
70
71
  forAudioCodec: {
71
72
  "pcm-16": {
72
73
  possible: import("./file-extensions").FileExtension[];
73
74
  default: import("./file-extensions").FileExtension;
74
75
  };
75
- aac: {
76
+ opus: {
76
77
  possible: import("./file-extensions").FileExtension[];
77
78
  default: import("./file-extensions").FileExtension;
78
79
  };
79
80
  };
80
81
  };
81
- vp8: {
82
+ mp3: {
82
83
  default: import("./file-extensions").FileExtension;
83
84
  forAudioCodec: {
84
- "pcm-16": {
85
+ mp3: {
85
86
  possible: import("./file-extensions").FileExtension[];
86
87
  default: import("./file-extensions").FileExtension;
87
88
  };
88
- opus: {
89
+ "pcm-16": {
89
90
  possible: import("./file-extensions").FileExtension[];
90
91
  default: import("./file-extensions").FileExtension;
91
92
  };
92
93
  };
93
94
  };
94
- vp9: {
95
+ aac: {
95
96
  default: import("./file-extensions").FileExtension;
96
97
  forAudioCodec: {
97
- "pcm-16": {
98
+ aac: {
98
99
  possible: import("./file-extensions").FileExtension[];
99
100
  default: import("./file-extensions").FileExtension;
100
101
  };
101
- opus: {
102
+ "pcm-16": {
102
103
  possible: import("./file-extensions").FileExtension[];
103
104
  default: import("./file-extensions").FileExtension;
104
105
  };
@@ -116,11 +117,11 @@ export declare const BrowserSafeApis: {
116
117
  prores: {
117
118
  default: import("./file-extensions").FileExtension;
118
119
  forAudioCodec: {
119
- "pcm-16": {
120
+ aac: {
120
121
  possible: import("./file-extensions").FileExtension[];
121
122
  default: import("./file-extensions").FileExtension;
122
123
  };
123
- aac: {
124
+ "pcm-16": {
124
125
  possible: import("./file-extensions").FileExtension[];
125
126
  default: import("./file-extensions").FileExtension;
126
127
  };
@@ -129,11 +130,11 @@ export declare const BrowserSafeApis: {
129
130
  "h264-mkv": {
130
131
  default: import("./file-extensions").FileExtension;
131
132
  forAudioCodec: {
132
- "pcm-16": {
133
+ mp3: {
133
134
  possible: import("./file-extensions").FileExtension[];
134
135
  default: import("./file-extensions").FileExtension;
135
136
  };
136
- mp3: {
137
+ "pcm-16": {
137
138
  possible: import("./file-extensions").FileExtension[];
138
139
  default: import("./file-extensions").FileExtension;
139
140
  };
@@ -145,21 +146,13 @@ export declare const BrowserSafeApis: {
145
146
  };
146
147
  };
147
148
  defaultAudioCodecs: {
148
- aac: {
149
- compressed: "pcm-16" | "aac" | null;
150
- lossless: "pcm-16" | "aac" | null;
151
- };
152
- mp3: {
153
- compressed: "pcm-16" | "mp3" | null;
154
- lossless: "pcm-16" | "mp3" | null;
155
- };
156
149
  h264: {
157
- compressed: "pcm-16" | "aac" | "mp3" | null;
158
- lossless: "pcm-16" | "aac" | "mp3" | null;
150
+ compressed: "mp3" | "aac" | "pcm-16" | null;
151
+ lossless: "mp3" | "aac" | "pcm-16" | null;
159
152
  };
160
153
  h265: {
161
- compressed: "pcm-16" | "aac" | null;
162
- lossless: "pcm-16" | "aac" | null;
154
+ compressed: "aac" | "pcm-16" | null;
155
+ lossless: "aac" | "pcm-16" | null;
163
156
  };
164
157
  vp8: {
165
158
  compressed: "pcm-16" | "opus" | null;
@@ -169,27 +162,35 @@ export declare const BrowserSafeApis: {
169
162
  compressed: "pcm-16" | "opus" | null;
170
163
  lossless: "pcm-16" | "opus" | null;
171
164
  };
165
+ mp3: {
166
+ compressed: "mp3" | "pcm-16" | null;
167
+ lossless: "mp3" | "pcm-16" | null;
168
+ };
169
+ aac: {
170
+ compressed: "aac" | "pcm-16" | null;
171
+ lossless: "aac" | "pcm-16" | null;
172
+ };
172
173
  wav: {
173
174
  compressed: "pcm-16" | null;
174
175
  lossless: "pcm-16" | null;
175
176
  };
176
177
  prores: {
177
- compressed: "pcm-16" | "aac" | null;
178
- lossless: "pcm-16" | "aac" | null;
178
+ compressed: "aac" | "pcm-16" | null;
179
+ lossless: "aac" | "pcm-16" | null;
179
180
  };
180
181
  "h264-mkv": {
181
- compressed: "pcm-16" | "mp3" | null;
182
- lossless: "pcm-16" | "mp3" | null;
182
+ compressed: "mp3" | "pcm-16" | null;
183
+ lossless: "mp3" | "pcm-16" | null;
183
184
  };
184
185
  gif: {
185
186
  compressed: null;
186
187
  lossless: null;
187
188
  };
188
189
  };
189
- defaultCodecsForFileExtension: Record<import("./file-extensions").FileExtension, "aac" | "mp3" | "h264" | "h265" | "vp8" | "vp9" | "wav" | "prores" | "h264-mkv" | "gif">;
190
- validateOutputFilename: <T_1 extends "aac" | "mp3" | "h264" | "h265" | "vp8" | "vp9" | "wav" | "prores" | "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, }: {
191
192
  codec: T_1;
192
- audioCodec: "pcm-16" | "aac" | "mp3" | "opus" | null;
193
+ audioCodec: "mp3" | "aac" | "pcm-16" | "opus" | null;
193
194
  extension: string;
194
195
  preferLossless: boolean;
195
196
  }) => void;
@@ -390,6 +391,6 @@ export declare const BrowserSafeApis: {
390
391
  type: number | null;
391
392
  }];
392
393
  };
393
- codecSupportsCrf: (codec: "aac" | "mp3" | "h264" | "h265" | "vp8" | "vp9" | "wav" | "prores" | "h264-mkv" | "gif") => boolean;
394
- codecSupportsVideoBitrate: (codec: "aac" | "mp3" | "h264" | "h265" | "vp8" | "vp9" | "wav" | "prores" | "h264-mkv" | "gif") => boolean;
394
+ codecSupportsCrf: (codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif") => boolean;
395
+ codecSupportsVideoBitrate: (codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif") => boolean;
395
396
  };
@@ -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 "aac" | "mp3" | "h264" | "h265" | "vp8" | "vp9" | "wav" | "prores" | "h264-mkv" | "gif">(codec: T, audioCodec: AudioCodec | null) => FileExtension;
5
- export declare const makeFileExtensionMap: () => Record<string, ("aac" | "mp3" | "h264" | "h265" | "vp8" | "vp9" | "wav" | "prores" | "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,4 +1,15 @@
1
- export declare const getDesiredPort: (desiredPort: number | undefined, from: number, to: number) => Promise<{
1
+ type PortStatus = 'available' | 'unavailable';
2
+ export declare const testPortAvailableOnMultipleHosts: ({ hosts, port, }: {
3
+ port: number;
4
+ hosts: string[];
5
+ }) => Promise<PortStatus>;
6
+ export declare const getDesiredPort: ({ desiredPort, from, hostsToTry, to, }: {
7
+ desiredPort: number | undefined;
8
+ from: number;
9
+ to: number;
10
+ hostsToTry: string[];
11
+ }) => Promise<{
2
12
  port: number;
3
13
  didUsePort: () => void;
4
14
  }>;
15
+ export {};
package/dist/get-port.js CHANGED
@@ -3,48 +3,62 @@ 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.getDesiredPort = void 0;
6
+ exports.getDesiredPort = exports.testPortAvailableOnMultipleHosts = void 0;
7
7
  const net_1 = __importDefault(require("net"));
8
8
  const locks_1 = require("./locks");
9
- const getAvailablePort = (portToTry) => new Promise((resolve) => {
10
- let status = 'unavailable';
11
- const host = '127.0.0.1';
12
- const socket = new net_1.default.Socket();
13
- socket.on('connect', () => {
14
- status = 'unavailable';
15
- socket.destroy();
9
+ const isPortAvailableOnHost = ({ portToTry, host, }) => {
10
+ return new Promise((resolve) => {
11
+ let status = 'unavailable';
12
+ const socket = new net_1.default.Socket();
13
+ socket.on('connect', () => {
14
+ status = 'unavailable';
15
+ socket.destroy();
16
+ });
17
+ socket.setTimeout(3000);
18
+ socket.on('timeout', () => {
19
+ status = 'unavailable';
20
+ socket.destroy();
21
+ resolve(status);
22
+ });
23
+ socket.on('error', () => {
24
+ status = 'available';
25
+ });
26
+ socket.on('close', () => resolve(status));
27
+ socket.connect(portToTry, host);
16
28
  });
17
- socket.setTimeout(3000);
18
- socket.on('timeout', () => {
19
- status = 'unavailable';
20
- socket.destroy();
21
- resolve(status);
22
- });
23
- socket.on('error', () => {
24
- status = 'available';
25
- });
26
- socket.on('close', () => resolve(status));
27
- socket.connect(portToTry, host);
28
- });
29
- const getPort = async (from, to) => {
29
+ };
30
+ const testPortAvailableOnMultipleHosts = async ({ hosts, port, }) => {
31
+ const results = await Promise.all(hosts.map((host) => {
32
+ return isPortAvailableOnHost({ portToTry: port, host });
33
+ }));
34
+ return results.every((r) => r === 'available') ? 'available' : 'unavailable';
35
+ };
36
+ exports.testPortAvailableOnMultipleHosts = testPortAvailableOnMultipleHosts;
37
+ const getPort = async ({ from, to, hostsToTest, }) => {
30
38
  const ports = makeRange(from, to);
31
39
  for (const port of ports) {
32
- if ((await getAvailablePort(port)) === 'available') {
40
+ if ((await (0, exports.testPortAvailableOnMultipleHosts)({
41
+ port,
42
+ hosts: hostsToTest,
43
+ })) === 'available') {
33
44
  return port;
34
45
  }
35
46
  }
36
47
  throw new Error('No available ports found');
37
48
  };
38
49
  const portLocks = (0, locks_1.createLock)({ timeout: 10000 });
39
- const getDesiredPort = async (desiredPort, from, to) => {
50
+ const getDesiredPort = async ({ desiredPort, from, hostsToTry, to, }) => {
40
51
  await portLocks.waitForAllToBeDone();
41
52
  const lockPortSelection = portLocks.lock();
42
53
  const didUsePort = () => portLocks.unlock(lockPortSelection);
43
54
  if (typeof desiredPort !== 'undefined' &&
44
- (await getAvailablePort(desiredPort)) === 'available') {
55
+ (await (0, exports.testPortAvailableOnMultipleHosts)({
56
+ port: desiredPort,
57
+ hosts: ['0.0.0.0', '127.0.0.1'],
58
+ })) === 'available') {
45
59
  return { port: desiredPort, didUsePort };
46
60
  }
47
- const actualPort = await getPort(from, to);
61
+ const actualPort = await getPort({ from, to, hostsToTest: hostsToTry });
48
62
  // If did specify a port but did not get that one, fail hard.
49
63
  if (desiredPort && desiredPort !== actualPort) {
50
64
  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.`);
@@ -3,6 +3,6 @@ import type { LogLevel } from './log-level';
3
3
  export declare const getSilentParts: ({ src, noiseThresholdInDecibels: passedNoiseThresholdInDecibels, minDurationInSeconds: passedMinDuration, logLevel, }: {
4
4
  src: string;
5
5
  minDurationInSeconds?: number | undefined;
6
- logLevel?: "verbose" | "info" | "warn" | "error" | undefined;
6
+ logLevel?: "error" | "verbose" | "info" | "warn" | undefined;
7
7
  noiseThresholdInDecibels?: number | undefined;
8
8
  }) => Promise<GetSilentPartsResponse>;
package/dist/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ /// <reference types="node" />
2
+ /// <reference types="react" />
1
3
  import execa from 'execa';
2
4
  import { HeadlessBrowser } from './browser/Browser';
3
5
  import { SymbolicateableError } from './error-handling/symbolicateable-error';
@@ -58,10 +60,10 @@ export declare const RenderInternals: {
58
60
  width: number;
59
61
  height: number;
60
62
  scale: number;
61
- codec: "aac" | "mp3" | "h264" | "h265" | "vp8" | "vp9" | "wav" | "prores" | "h264-mkv" | "gif";
63
+ codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif";
62
64
  wantsImageSequence: boolean;
63
65
  }) => void;
64
- getFileExtensionFromCodec: <T extends "aac" | "mp3" | "h264" | "h265" | "vp8" | "vp9" | "wav" | "prores" | "h264-mkv" | "gif">(codec: T, audioCodec: "pcm-16" | "aac" | "mp3" | "opus" | null) => import("./file-extensions").FileExtension;
66
+ 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
67
  tmpDir: (str: string) => string;
66
68
  deleteDirectory: (directory: string) => void;
67
69
  isServeUrl: (potentialUrl: string) => boolean;
@@ -86,7 +88,12 @@ export declare const RenderInternals: {
86
88
  SymbolicateableError: typeof SymbolicateableError;
87
89
  getFramesToRender: (frameRange: [number, number], everyNthFrame: number) => number[];
88
90
  getExtensionOfFilename: (filename: string | null) => string | null;
89
- getDesiredPort: (desiredPort: number | undefined, from: number, to: number) => Promise<{
91
+ getDesiredPort: ({ desiredPort, from, hostsToTry, to, }: {
92
+ desiredPort: number | undefined;
93
+ from: number;
94
+ to: number;
95
+ hostsToTry: string[];
96
+ }) => Promise<{
90
97
  port: number;
91
98
  didUsePort: () => void;
92
99
  }>;
@@ -111,7 +118,7 @@ export declare const RenderInternals: {
111
118
  };
112
119
  registerErrorSymbolicationLock: () => number;
113
120
  unlockErrorSymbolicationLock: (id: number) => void;
114
- canUseParallelEncoding: (codec: "aac" | "mp3" | "h264" | "h265" | "vp8" | "vp9" | "wav" | "prores" | "h264-mkv" | "gif") => boolean;
121
+ canUseParallelEncoding: (codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif") => boolean;
115
122
  mimeContentType: typeof mimeContentType;
116
123
  mimeLookup: typeof mimeLookup;
117
124
  validateConcurrency: ({ setting, value, checkIfValidForCurrentMachine, }: {
@@ -122,14 +129,14 @@ export declare const RenderInternals: {
122
129
  validPixelFormats: readonly ["yuv420p", "yuva420p", "yuv422p", "yuv444p", "yuv420p10le", "yuv422p10le", "yuv444p10le", "yuva444p10le"];
123
130
  DEFAULT_BROWSER: "chrome";
124
131
  validateFrameRange: (frameRange: import("./frame-range").FrameRange | null) => void;
125
- DEFAULT_OPENGL_RENDERER: "swangle" | "angle" | "egl" | "swiftshader" | "vulkan" | null;
126
- validateOpenGlRenderer: (option: "swangle" | "angle" | "egl" | "swiftshader" | "vulkan" | null) => "swangle" | "angle" | "egl" | "swiftshader" | "vulkan" | null;
132
+ DEFAULT_OPENGL_RENDERER: "angle" | "swangle" | "egl" | "swiftshader" | "vulkan" | null;
133
+ validateOpenGlRenderer: (option: "angle" | "swangle" | "egl" | "swiftshader" | "vulkan" | null) => "angle" | "swangle" | "egl" | "swiftshader" | "vulkan" | null;
127
134
  validCodecs: readonly ["h264", "h265", "vp8", "vp9", "mp3", "aac", "wav", "prores", "h264-mkv", "gif"];
128
135
  DEFAULT_PIXEL_FORMAT: "yuv420p" | "yuva420p" | "yuv422p" | "yuv444p" | "yuv420p10le" | "yuv422p10le" | "yuv444p10le" | "yuva444p10le";
129
136
  validateJpegQuality: (q: number | undefined) => void;
130
137
  DEFAULT_TIMEOUT: number;
131
- DEFAULT_CODEC: "aac" | "mp3" | "h264" | "h265" | "vp8" | "vp9" | "wav" | "prores" | "h264-mkv" | "gif";
132
- isAudioCodec: (codec: "aac" | "mp3" | "h264" | "h265" | "vp8" | "vp9" | "wav" | "prores" | "h264-mkv" | "gif" | undefined) => boolean;
138
+ DEFAULT_CODEC: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif";
139
+ isAudioCodec: (codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif" | undefined) => boolean;
133
140
  logLevels: readonly ["verbose", "info", "warn", "error"];
134
141
  isEqualOrBelowLogLevel: (currentLevel: "verbose" | "info" | "warn" | "error", level: "verbose" | "info" | "warn" | "error") => boolean;
135
142
  isValidLogLevel: (level: string) => boolean;
@@ -146,24 +153,24 @@ export declare const RenderInternals: {
146
153
  output: string;
147
154
  onProgress: (p: number) => void;
148
155
  numberOfFrames: number;
149
- codec: "aac" | "mp3" | "h264" | "h265" | "vp8" | "vp9" | "wav" | "prores" | "h264-mkv" | "gif";
156
+ codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif";
150
157
  fps: number;
151
158
  numberOfGifLoops: number | null;
152
- audioCodec: "pcm-16" | "aac" | "mp3" | "opus" | null;
159
+ audioCodec: "mp3" | "aac" | "pcm-16" | "opus" | null;
153
160
  audioBitrate: string | null;
154
161
  }) => Promise<void>;
155
162
  getMinConcurrency: () => number;
156
163
  getMaxConcurrency: () => number;
157
164
  getDefaultAudioCodec: ({ codec, preferLossless, }: {
158
- codec: "aac" | "mp3" | "h264" | "h265" | "vp8" | "vp9" | "wav" | "prores" | "h264-mkv" | "gif";
165
+ codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif";
159
166
  preferLossless: boolean;
160
- }) => "pcm-16" | "aac" | "mp3" | "opus" | null;
167
+ }) => "mp3" | "aac" | "pcm-16" | "opus" | null;
161
168
  validAudioCodecs: readonly ["pcm-16", "aac", "mp3", "opus"];
162
169
  defaultFileExtensionMap: {
163
- aac: {
170
+ h264: {
164
171
  default: import("./file-extensions").FileExtension;
165
172
  forAudioCodec: {
166
- "pcm-16": {
173
+ mp3: {
167
174
  possible: import("./file-extensions").FileExtension[];
168
175
  default: import("./file-extensions").FileExtension;
169
176
  };
@@ -171,72 +178,72 @@ export declare const RenderInternals: {
171
178
  possible: import("./file-extensions").FileExtension[];
172
179
  default: import("./file-extensions").FileExtension;
173
180
  };
181
+ "pcm-16": {
182
+ possible: import("./file-extensions").FileExtension[];
183
+ default: import("./file-extensions").FileExtension;
184
+ };
174
185
  };
175
186
  };
176
- mp3: {
187
+ h265: {
177
188
  default: import("./file-extensions").FileExtension;
178
189
  forAudioCodec: {
179
- "pcm-16": {
190
+ aac: {
180
191
  possible: import("./file-extensions").FileExtension[];
181
192
  default: import("./file-extensions").FileExtension;
182
193
  };
183
- mp3: {
194
+ "pcm-16": {
184
195
  possible: import("./file-extensions").FileExtension[];
185
196
  default: import("./file-extensions").FileExtension;
186
197
  };
187
198
  };
188
199
  };
189
- h264: {
200
+ vp8: {
190
201
  default: import("./file-extensions").FileExtension;
191
202
  forAudioCodec: {
192
203
  "pcm-16": {
193
204
  possible: import("./file-extensions").FileExtension[];
194
205
  default: import("./file-extensions").FileExtension;
195
206
  };
196
- aac: {
197
- possible: import("./file-extensions").FileExtension[];
198
- default: import("./file-extensions").FileExtension;
199
- };
200
- mp3: {
207
+ opus: {
201
208
  possible: import("./file-extensions").FileExtension[];
202
209
  default: import("./file-extensions").FileExtension;
203
210
  };
204
211
  };
205
212
  };
206
- h265: {
213
+ vp9: {
207
214
  default: import("./file-extensions").FileExtension;
208
215
  forAudioCodec: {
209
216
  "pcm-16": {
210
217
  possible: import("./file-extensions").FileExtension[];
211
218
  default: import("./file-extensions").FileExtension;
212
219
  };
213
- aac: {
220
+ opus: {
214
221
  possible: import("./file-extensions").FileExtension[];
215
222
  default: import("./file-extensions").FileExtension;
216
223
  };
217
224
  };
218
225
  };
219
- vp8: {
226
+ mp3: {
220
227
  default: import("./file-extensions").FileExtension;
221
228
  forAudioCodec: {
222
- "pcm-16": {
229
+ mp3: {
223
230
  possible: import("./file-extensions").FileExtension[];
224
231
  default: import("./file-extensions").FileExtension;
225
232
  };
226
- opus: {
233
+ "pcm-16": {
227
234
  possible: import("./file-extensions").FileExtension[];
228
235
  default: import("./file-extensions").FileExtension;
229
236
  };
230
237
  };
231
238
  };
232
- vp9: {
239
+ aac: {
233
240
  default: import("./file-extensions").FileExtension;
234
241
  forAudioCodec: {
235
- "pcm-16": {
242
+ aac: {
236
243
  possible: import("./file-extensions").FileExtension[];
237
244
  default: import("./file-extensions").FileExtension;
238
245
  };
239
- opus: {
246
+ "pcm-16": {
240
247
  possible: import("./file-extensions").FileExtension[];
241
248
  default: import("./file-extensions").FileExtension;
242
249
  };
@@ -254,11 +261,11 @@ export declare const RenderInternals: {
254
261
  prores: {
255
262
  default: import("./file-extensions").FileExtension;
256
263
  forAudioCodec: {
257
- "pcm-16": {
264
+ aac: {
258
265
  possible: import("./file-extensions").FileExtension[];
259
266
  default: import("./file-extensions").FileExtension;
260
267
  };
261
- aac: {
268
+ "pcm-16": {
262
269
  possible: import("./file-extensions").FileExtension[];
263
270
  default: import("./file-extensions").FileExtension;
264
271
  };
@@ -267,11 +274,11 @@ export declare const RenderInternals: {
267
274
  "h264-mkv": {
268
275
  default: import("./file-extensions").FileExtension;
269
276
  forAudioCodec: {
270
- "pcm-16": {
277
+ mp3: {
271
278
  possible: import("./file-extensions").FileExtension[];
272
279
  default: import("./file-extensions").FileExtension;
273
280
  };
274
- mp3: {
281
+ "pcm-16": {
275
282
  possible: import("./file-extensions").FileExtension[];
276
283
  default: import("./file-extensions").FileExtension;
277
284
  };
@@ -294,8 +301,8 @@ export declare const RenderInternals: {
294
301
  readonly vp9: readonly ["opus", "pcm-16"];
295
302
  readonly wav: readonly ["pcm-16"];
296
303
  };
297
- makeFileExtensionMap: () => Record<string, ("aac" | "mp3" | "h264" | "h265" | "vp8" | "vp9" | "wav" | "prores" | "h264-mkv" | "gif")[]>;
298
- defaultCodecsForFileExtension: Record<import("./file-extensions").FileExtension, "aac" | "mp3" | "h264" | "h265" | "vp8" | "vp9" | "wav" | "prores" | "h264-mkv" | "gif">;
304
+ makeFileExtensionMap: () => Record<string, ("h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif")[]>;
305
+ defaultCodecsForFileExtension: Record<import("./file-extensions").FileExtension, "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif">;
299
306
  getExecutablePath: (type: "compositor" | "ffmpeg" | "ffprobe" | "ffmpeg-cwd") => string;
300
307
  callFf: (bin: "ffmpeg" | "ffprobe", args: (string | null)[], options?: execa.Options<string> | undefined) => execa.ExecaChildProcess<string>;
301
308
  dynamicLibraryPathOptions: () => {
@@ -312,8 +319,8 @@ export declare const RenderInternals: {
312
319
  };
313
320
  validStillImageFormats: readonly ["png", "jpeg", "pdf", "webp"];
314
321
  validVideoImageFormats: readonly ["png", "jpeg", "none"];
315
- DEFAULT_STILL_IMAGE_FORMAT: "png" | "jpeg" | "pdf" | "webp";
316
- DEFAULT_VIDEO_IMAGE_FORMAT: "png" | "jpeg" | "none";
322
+ DEFAULT_STILL_IMAGE_FORMAT: "jpeg" | "png" | "webp" | "pdf";
323
+ DEFAULT_VIDEO_IMAGE_FORMAT: "jpeg" | "png" | "none";
317
324
  DEFAULT_JPEG_QUALITY: number;
318
325
  chalk: {
319
326
  enabled: () => boolean;
@@ -426,7 +433,7 @@ export declare const RenderInternals: {
426
433
  frame: number;
427
434
  serializedInputPropsWithCustomSchema: string;
428
435
  serializedResolvedPropsWithCustomSchema: string;
429
- imageFormat: "png" | "jpeg" | "pdf" | "webp";
436
+ imageFormat: "jpeg" | "png" | "webp" | "pdf";
430
437
  jpegQuality: number;
431
438
  puppeteerInstance: HeadlessBrowser | null;
432
439
  envVariables: Record<string, string>;
package/dist/locks.js CHANGED
@@ -25,6 +25,9 @@ const createLock = ({ timeout }) => {
25
25
  });
26
26
  });
27
27
  resolveWaiters();
28
+ if (locks.length === 0) {
29
+ return Promise.resolve();
30
+ }
28
31
  if (timeout === null) {
29
32
  return success;
30
33
  }
package/dist/logger.d.ts CHANGED
@@ -19,6 +19,6 @@ export declare const Log: {
19
19
  error: (message?: any, ...optionalParams: any[]) => void;
20
20
  errorAdvanced: (options: VerboseLogOptions, message?: any, ...optionalParams: any[]) => void;
21
21
  };
22
- export declare const getLogLevel: () => "verbose" | "info" | "warn" | "error";
22
+ export declare const getLogLevel: () => "error" | "verbose" | "info" | "warn";
23
23
  export declare const setLogLevel: (newLogLevel: LogLevel) => void;
24
24
  export {};
@@ -1,3 +1,4 @@
1
+ /// <reference types="node" />
1
2
  import type { ClipRegion } from 'remotion';
2
3
  import type { Page } from './browser/BrowserPage';
3
4
  import type { StillImageFormat } from './image-format';
@@ -26,9 +26,10 @@ function valueFromRemoteObject(remoteObject) {
26
26
  return remoteObject.value;
27
27
  }
28
28
  function puppeteerEvaluateWithCatchAndTimeout({ args, frame, page, pageFunction, }) {
29
+ let timeout = null;
29
30
  return Promise.race([
30
31
  new Promise((_, reject) => {
31
- setTimeout(() => {
32
+ timeout = setTimeout(() => {
32
33
  reject(new Error(
33
34
  // This means the page is not responding anymore
34
35
  // This error message is retryable - sync it with packages/lambda/src/shared/is-flaky-error.ts
@@ -41,7 +42,12 @@ function puppeteerEvaluateWithCatchAndTimeout({ args, frame, page, pageFunction,
41
42
  page,
42
43
  pageFunction,
43
44
  }),
44
- ]);
45
+ ]).then((data) => {
46
+ if (timeout !== null) {
47
+ clearTimeout(timeout);
48
+ }
49
+ return data;
50
+ });
45
51
  }
46
52
  exports.puppeteerEvaluateWithCatchAndTimeout = puppeteerEvaluateWithCatchAndTimeout;
47
53
  async function puppeteerEvaluateWithCatch({ page, pageFunction, frame, args, }) {
@@ -1,3 +1,4 @@
1
+ /// <reference types="node" />
1
2
  import type { ClipRegion } from 'remotion';
2
3
  import type { Page } from './browser/BrowserPage';
3
4
  import type { StillImageFormat } from './image-format';
@@ -1,3 +1,4 @@
1
+ /// <reference types="node" />
1
2
  import type { ClipRegion } from 'remotion';
2
3
  import type { Page } from './browser/BrowserPage';
3
4
  import type { StillImageFormat } from './image-format';
@@ -1,3 +1,4 @@
1
+ /// <reference types="node" />
1
2
  import type { ClipRegion } from 'remotion';
2
3
  import type { Page } from './browser/BrowserPage';
3
4
  import type { StillImageFormat } from './image-format';
@@ -45,13 +45,20 @@ const serveStatic = async (path, options) => {
45
45
  });
46
46
  let selectedPort = null;
47
47
  const maxTries = 5;
48
+ // Default Node.js host, but explicity
49
+ const host = '0.0.0.0';
48
50
  for (let i = 0; i < maxTries; i++) {
49
51
  try {
50
52
  selectedPort = await new Promise((resolve, reject) => {
51
53
  var _a;
52
- (0, get_port_1.getDesiredPort)((_a = options === null || options === void 0 ? void 0 : options.port) !== null && _a !== void 0 ? _a : undefined, 3000, 3100)
54
+ (0, get_port_1.getDesiredPort)({
55
+ desiredPort: (_a = options === null || options === void 0 ? void 0 : options.port) !== null && _a !== void 0 ? _a : undefined,
56
+ from: 3000,
57
+ to: 3100,
58
+ hostsToTry: ['0.0.0.0', '127.0.0.1'],
59
+ })
53
60
  .then(({ port, didUsePort }) => {
54
- server.listen(port);
61
+ server.listen({ port, host });
55
62
  server.on('listening', () => {
56
63
  resolve(port);
57
64
  return didUsePort();
@@ -150,14 +150,19 @@ const innerSetPropsAndEnv = async ({ serializedInputPropsWithCustomSchema, envVa
150
150
  }
151
151
  }
152
152
  };
153
- const setPropsAndEnv = (params) => {
154
- return Promise.race([
153
+ const setPropsAndEnv = async (params) => {
154
+ let timeout = null;
155
+ const result = await Promise.race([
155
156
  innerSetPropsAndEnv(params),
156
157
  new Promise((_, reject) => {
157
- setTimeout(() => {
158
+ timeout = setTimeout(() => {
158
159
  reject(new Error(`Timed out after ${params.timeoutInMilliseconds} while setting up the headless browser. This could be because the you specified takes a long time to load (or network resources that it includes like fonts) or because the browser is not responding. Optimize the site or increase the browser timeout.`));
159
160
  }, params.timeoutInMilliseconds);
160
161
  }),
161
162
  ]);
163
+ if (timeout !== null) {
164
+ clearTimeout(timeout);
165
+ }
166
+ return result;
162
167
  };
163
168
  exports.setPropsAndEnv = setPropsAndEnv;
@@ -1,3 +1,4 @@
1
+ /// <reference types="node" />
1
2
  import type { RenderMediaOnDownload } from './assets/download-and-map-assets-to-file';
2
3
  import type { RenderAssetInfo } from './assets/download-map';
3
4
  import type { AudioCodec } from './audio-codec';
@@ -6,7 +6,7 @@ export type ProcessedTrack = {
6
6
  pad_start: string | null;
7
7
  pad_end: string | null;
8
8
  };
9
- export declare const stringifyFfmpegFilter: ({ trimLeft, trimRight, channels, startInVideo, volume, fps, playbackRate, durationInFrames, assetDuration, allowAmplificationDuringRender, }: {
9
+ export declare const stringifyFfmpegFilter: ({ trimLeft, trimRight, channels, startInVideo, volume, fps, playbackRate, durationInFrames, assetDuration, allowAmplificationDuringRender, toneFrequency, }: {
10
10
  trimLeft: number;
11
11
  trimRight: number;
12
12
  channels: number;
@@ -17,4 +17,5 @@ export declare const stringifyFfmpegFilter: ({ trimLeft, trimRight, channels, st
17
17
  playbackRate: number;
18
18
  assetDuration: number | null;
19
19
  allowAmplificationDuringRender: boolean;
20
+ toneFrequency: number | null;
20
21
  }) => FilterWithoutPaddingApplied | null;
@@ -5,11 +5,14 @@ const calculate_atempo_1 = require("./assets/calculate-atempo");
5
5
  const ffmpeg_volume_expression_1 = require("./assets/ffmpeg-volume-expression");
6
6
  const sample_rate_1 = require("./sample-rate");
7
7
  const truthy_1 = require("./truthy");
8
- const stringifyFfmpegFilter = ({ trimLeft, trimRight, channels, startInVideo, volume, fps, playbackRate, durationInFrames, assetDuration, allowAmplificationDuringRender, }) => {
8
+ const stringifyFfmpegFilter = ({ trimLeft, trimRight, channels, startInVideo, volume, fps, playbackRate, durationInFrames, assetDuration, allowAmplificationDuringRender, toneFrequency, }) => {
9
9
  const startInVideoSeconds = startInVideo / fps;
10
10
  if (assetDuration && trimLeft >= assetDuration) {
11
11
  return null;
12
12
  }
13
+ if (toneFrequency !== null && (toneFrequency <= 0 || toneFrequency > 2)) {
14
+ throw new Error('toneFrequency must be a positive number between 0.01 and 2');
15
+ }
13
16
  const volumeFilter = (0, ffmpeg_volume_expression_1.ffmpegVolumeExpression)({
14
17
  volume,
15
18
  fps,
@@ -37,6 +40,9 @@ const stringifyFfmpegFilter = ({ trimLeft, trimRight, channels, startInVideo, vo
37
40
  volumeFilter.value === '1'
38
41
  ? null
39
42
  : `volume=${volumeFilter.value}:eval=${volumeFilter.eval}`,
43
+ toneFrequency && toneFrequency !== 1
44
+ ? `asetrate=${sample_rate_1.DEFAULT_SAMPLE_RATE}*${toneFrequency},aresample=${sample_rate_1.DEFAULT_SAMPLE_RATE},atempo=1/${toneFrequency}`
45
+ : null,
40
46
  // For n channels, we delay n + 1 channels.
41
47
  // This is because `ffprobe` for some audio files reports the wrong amount
42
48
  // of channels.
@@ -1,3 +1,4 @@
1
+ /// <reference types="node" />
1
2
  import type { TRenderAsset } from 'remotion';
2
3
  import type { DownloadMap } from './assets/download-map';
3
4
  import type { Page } from './browser/BrowserPage';
@@ -1,5 +1,5 @@
1
1
  import type { AudioCodec } from './audio-codec';
2
- export declare const validateOutputFilename: <T extends "aac" | "mp3" | "h264" | "h265" | "vp8" | "vp9" | "wav" | "prores" | "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.46",
3
+ "version": "4.0.48",
4
4
  "description": "Renderer for Remotion",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -18,14 +18,14 @@
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.46"
21
+ "remotion": "4.0.48"
22
22
  },
23
23
  "peerDependencies": {
24
24
  "react": ">=16.8.0",
25
25
  "react-dom": ">=16.8.0"
26
26
  },
27
27
  "devDependencies": {
28
- "@jonny/eslint-config": "3.0.266",
28
+ "@jonny/eslint-config": "3.0.276",
29
29
  "@testing-library/dom": "^8.16.0",
30
30
  "@testing-library/react": "13.3.0",
31
31
  "@types/node": "18.14.6",
@@ -40,13 +40,13 @@
40
40
  "vitest": "0.31.1"
41
41
  },
42
42
  "optionalDependencies": {
43
- "@remotion/compositor-darwin-arm64": "4.0.46",
44
- "@remotion/compositor-linux-arm64-gnu": "4.0.46",
45
- "@remotion/compositor-linux-arm64-musl": "4.0.46",
46
- "@remotion/compositor-darwin-x64": "4.0.46",
47
- "@remotion/compositor-linux-x64-gnu": "4.0.46",
48
- "@remotion/compositor-linux-x64-musl": "4.0.46",
49
- "@remotion/compositor-win32-x64-msvc": "4.0.46"
43
+ "@remotion/compositor-linux-arm64-gnu": "4.0.48",
44
+ "@remotion/compositor-darwin-arm64": "4.0.48",
45
+ "@remotion/compositor-darwin-x64": "4.0.48",
46
+ "@remotion/compositor-linux-arm64-musl": "4.0.48",
47
+ "@remotion/compositor-linux-x64-gnu": "4.0.48",
48
+ "@remotion/compositor-linux-x64-musl": "4.0.48",
49
+ "@remotion/compositor-win32-x64-msvc": "4.0.48"
50
50
  },
51
51
  "keywords": [
52
52
  "remotion",