@remotion/renderer 4.1.0-alpha10 → 4.1.0-alpha12
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/assets/calculate-asset-positions.d.ts +2 -2
- package/dist/assets/calculate-asset-positions.js +6 -6
- package/dist/assets/convert-assets-to-file-urls.d.ts +3 -3
- package/dist/assets/convert-assets-to-file-urls.js +1 -1
- package/dist/assets/download-and-map-assets-to-file.d.ts +4 -4
- package/dist/assets/download-and-map-assets-to-file.js +3 -3
- package/dist/assets/download-map.d.ts +2 -2
- package/dist/assets/types.d.ts +3 -3
- package/dist/assets/types.js +3 -3
- package/dist/audio-codec.d.ts +2 -2
- package/dist/audio-codec.js +2 -2
- package/dist/client.d.ts +36 -28
- package/dist/combine-videos.js +36 -30
- package/dist/compositor/compositor.js +9 -5
- package/dist/compress-assets.d.ts +2 -2
- package/dist/compress-assets.js +6 -6
- package/dist/file-extensions.js +2 -0
- package/dist/get-extension-from-codec.d.ts +2 -2
- package/dist/get-silent-parts.d.ts +8 -0
- package/dist/get-silent-parts.js +56 -0
- package/dist/index.d.ts +35 -26
- package/dist/offthread-video-server.js +11 -2
- package/dist/render-frames.js +2 -2
- package/dist/symbolicate-stacktrace.js +7 -1
- package/dist/take-frame-and-compose.d.ts +2 -2
- package/dist/validate-output-filename.d.ts +1 -1
- package/package.json +9 -9
- package/dist/serialize-props.d.ts +0 -6
- package/dist/serialize-props.js +0 -36
- package/install-toolchain.mjs +0 -36
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { TRenderAsset } from 'remotion';
|
|
2
2
|
import type { Assets } from './types';
|
|
3
|
-
export declare const calculateAssetPositions: (frames:
|
|
3
|
+
export declare const calculateAssetPositions: (frames: TRenderAsset[][]) => Assets;
|
|
@@ -7,19 +7,19 @@ const types_1 = require("./types");
|
|
|
7
7
|
const areEqual = (a, b) => {
|
|
8
8
|
return a.id === b.id;
|
|
9
9
|
};
|
|
10
|
-
const findFrom = (target,
|
|
11
|
-
const index = target.findIndex((a) => areEqual(a,
|
|
10
|
+
const findFrom = (target, renderAsset) => {
|
|
11
|
+
const index = target.findIndex((a) => areEqual(a, renderAsset));
|
|
12
12
|
if (index === -1) {
|
|
13
13
|
return false;
|
|
14
14
|
}
|
|
15
15
|
target.splice(index, 1);
|
|
16
16
|
return true;
|
|
17
17
|
};
|
|
18
|
-
const copyAndDeduplicateAssets = (
|
|
18
|
+
const copyAndDeduplicateAssets = (renderAssets) => {
|
|
19
19
|
const deduplicated = [];
|
|
20
|
-
for (const
|
|
21
|
-
if (!deduplicated.find((d) => d.id ===
|
|
22
|
-
deduplicated.push(
|
|
20
|
+
for (const renderAsset of renderAssets) {
|
|
21
|
+
if (!deduplicated.find((d) => d.id === renderAsset.id)) {
|
|
22
|
+
deduplicated.push(renderAsset);
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
return deduplicated;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { TRenderAsset } from 'remotion';
|
|
2
2
|
import type { RenderMediaOnDownload } from './download-and-map-assets-to-file';
|
|
3
3
|
import type { DownloadMap } from './download-map';
|
|
4
4
|
export declare const convertAssetsToFileUrls: ({ assets, onDownload, downloadMap, }: {
|
|
5
|
-
assets:
|
|
5
|
+
assets: TRenderAsset[][];
|
|
6
6
|
onDownload: RenderMediaOnDownload;
|
|
7
7
|
downloadMap: DownloadMap;
|
|
8
|
-
}) => Promise<
|
|
8
|
+
}) => Promise<TRenderAsset[][]>;
|
|
@@ -16,7 +16,7 @@ const convertAssetsToFileUrls = async ({ assets, onDownload, downloadMap, }) =>
|
|
|
16
16
|
const result = await Promise.all(ch.map((assetsForFrame) => {
|
|
17
17
|
return Promise.all(assetsForFrame.map((a) => {
|
|
18
18
|
return (0, download_and_map_assets_to_file_1.downloadAndMapAssetsToFileUrl)({
|
|
19
|
-
|
|
19
|
+
renderAsset: a,
|
|
20
20
|
onDownload,
|
|
21
21
|
downloadMap,
|
|
22
22
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { TRenderAsset } from 'remotion';
|
|
2
2
|
import type { DownloadMap } from './download-map';
|
|
3
3
|
export type RenderMediaOnDownload = (src: string) => ((progress: {
|
|
4
4
|
percent: number | null;
|
|
@@ -16,9 +16,9 @@ export declare const getSanitizedFilenameForAssetUrl: ({ src, downloadDir, conte
|
|
|
16
16
|
contentDisposition: string | null;
|
|
17
17
|
contentType: string | null;
|
|
18
18
|
}) => string;
|
|
19
|
-
export declare const downloadAndMapAssetsToFileUrl: ({
|
|
20
|
-
|
|
19
|
+
export declare const downloadAndMapAssetsToFileUrl: ({ renderAsset, onDownload, downloadMap, }: {
|
|
20
|
+
renderAsset: TRenderAsset;
|
|
21
21
|
onDownload: RenderMediaOnDownload | null;
|
|
22
22
|
downloadMap: DownloadMap;
|
|
23
|
-
}) => Promise<
|
|
23
|
+
}) => Promise<TRenderAsset>;
|
|
24
24
|
export declare const attachDownloadListenerToEmitter: (downloadMap: DownloadMap, onDownload: RenderMediaOnDownload | null) => () => void;
|
|
@@ -241,15 +241,15 @@ const getSanitizedFilenameForAssetUrl = ({ src, downloadDir, contentDisposition,
|
|
|
241
241
|
return node_path_1.default.join(downloadDir, (0, sanitize_filepath_1.sanitizeFilePath)(filename));
|
|
242
242
|
};
|
|
243
243
|
exports.getSanitizedFilenameForAssetUrl = getSanitizedFilenameForAssetUrl;
|
|
244
|
-
const downloadAndMapAssetsToFileUrl = async ({
|
|
244
|
+
const downloadAndMapAssetsToFileUrl = async ({ renderAsset, onDownload, downloadMap, }) => {
|
|
245
245
|
const cleanup = (0, exports.attachDownloadListenerToEmitter)(downloadMap, onDownload);
|
|
246
246
|
const newSrc = await (0, exports.downloadAsset)({
|
|
247
|
-
src:
|
|
247
|
+
src: renderAsset.src,
|
|
248
248
|
downloadMap,
|
|
249
249
|
});
|
|
250
250
|
cleanup();
|
|
251
251
|
return {
|
|
252
|
-
...
|
|
252
|
+
...renderAsset,
|
|
253
253
|
src: newSrc,
|
|
254
254
|
};
|
|
255
255
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { TRenderAsset } from 'remotion';
|
|
2
2
|
import { OffthreadVideoServerEmitter } from '../offthread-video-server';
|
|
3
3
|
import type { RenderMediaOnDownload } from './download-and-map-assets-to-file';
|
|
4
4
|
export type AudioChannelsAndDurationResultCache = {
|
|
@@ -38,7 +38,7 @@ export type DownloadMap = {
|
|
|
38
38
|
};
|
|
39
39
|
};
|
|
40
40
|
export type RenderAssetInfo = {
|
|
41
|
-
assets:
|
|
41
|
+
assets: TRenderAsset[][];
|
|
42
42
|
imageSequenceName: string;
|
|
43
43
|
firstFrameIndex: number;
|
|
44
44
|
downloadMap: DownloadMap;
|
package/dist/assets/types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export type UnsafeAsset = Omit<
|
|
1
|
+
import type { TRenderAsset } from 'remotion';
|
|
2
|
+
export type UnsafeAsset = Omit<TRenderAsset, 'frame' | 'id' | 'volume' | 'mediaFrame'> & {
|
|
3
3
|
startInVideo: number;
|
|
4
4
|
duration: number | null;
|
|
5
5
|
trimLeft: number;
|
|
@@ -13,5 +13,5 @@ export type MediaAsset = Omit<UnsafeAsset, 'duration' | 'volume'> & {
|
|
|
13
13
|
duration: number;
|
|
14
14
|
volume: AssetVolume;
|
|
15
15
|
};
|
|
16
|
-
export declare const uncompressMediaAsset: (
|
|
16
|
+
export declare const uncompressMediaAsset: (allRenderAssets: TRenderAsset[], assetToUncompress: TRenderAsset) => TRenderAsset;
|
|
17
17
|
export type Assets = MediaAsset[];
|
package/dist/assets/types.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.uncompressMediaAsset = void 0;
|
|
4
|
-
const uncompressMediaAsset = (
|
|
4
|
+
const uncompressMediaAsset = (allRenderAssets, assetToUncompress) => {
|
|
5
5
|
const isCompressed = assetToUncompress.src.match(/same-as-(.*)-([0-9]+)$/);
|
|
6
6
|
if (!isCompressed) {
|
|
7
7
|
return assetToUncompress;
|
|
8
8
|
}
|
|
9
9
|
const [, id, frame] = isCompressed;
|
|
10
|
-
const assetToFill =
|
|
10
|
+
const assetToFill = allRenderAssets.find((a) => a.id === id && String(a.frame) === frame);
|
|
11
11
|
if (!assetToFill) {
|
|
12
12
|
console.log('List of assets:');
|
|
13
|
-
console.log(
|
|
13
|
+
console.log(allRenderAssets);
|
|
14
14
|
throw new TypeError(`Cannot uncompress asset, asset list seems corrupt. Please file a bug in the Remotion repo with the debug information above.`);
|
|
15
15
|
}
|
|
16
16
|
return {
|
package/dist/audio-codec.d.ts
CHANGED
|
@@ -2,8 +2,8 @@ import type { Codec } from './codec';
|
|
|
2
2
|
export declare const validAudioCodecs: readonly ["pcm-16", "aac", "mp3", "opus"];
|
|
3
3
|
export type AudioCodec = typeof validAudioCodecs[number];
|
|
4
4
|
export declare const supportedAudioCodecs: {
|
|
5
|
-
readonly h264: readonly ["aac", "pcm-16"];
|
|
6
|
-
readonly 'h264-mkv': readonly ["pcm-16"];
|
|
5
|
+
readonly h264: readonly ["aac", "pcm-16", "mp3"];
|
|
6
|
+
readonly 'h264-mkv': readonly ["pcm-16", "mp3"];
|
|
7
7
|
readonly aac: readonly ["aac", "pcm-16"];
|
|
8
8
|
readonly gif: readonly [];
|
|
9
9
|
readonly h265: readonly ["aac", "pcm-16"];
|
package/dist/audio-codec.js
CHANGED
|
@@ -3,8 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.getDefaultAudioCodec = exports.defaultAudioCodecs = exports.mapAudioCodecToFfmpegAudioCodecName = exports.supportedAudioCodecs = exports.validAudioCodecs = void 0;
|
|
4
4
|
exports.validAudioCodecs = ['pcm-16', 'aac', 'mp3', 'opus'];
|
|
5
5
|
exports.supportedAudioCodecs = {
|
|
6
|
-
h264: ['aac', 'pcm-16'],
|
|
7
|
-
'h264-mkv': ['pcm-16'],
|
|
6
|
+
h264: ['aac', 'pcm-16', 'mp3'],
|
|
7
|
+
'h264-mkv': ['pcm-16', 'mp3'],
|
|
8
8
|
aac: ['aac', 'pcm-16'],
|
|
9
9
|
gif: [],
|
|
10
10
|
h265: ['aac', 'pcm-16'],
|
package/dist/client.d.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
export declare const BrowserSafeApis: {
|
|
2
|
-
getFileExtensionFromCodec: <T extends "h264" | "h265" | "vp8" | "vp9" | "
|
|
2
|
+
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
3
|
validCodecs: readonly ["h264", "h265", "vp8", "vp9", "mp3", "aac", "wav", "prores", "h264-mkv", "gif"];
|
|
4
4
|
validAudioCodecs: readonly ["pcm-16", "aac", "mp3", "opus"];
|
|
5
|
-
getDefaultCrfForCodec: (codec: "h264" | "h265" | "vp8" | "vp9" | "
|
|
6
|
-
getValidCrfRanges: (codec: "h264" | "h265" | "vp8" | "vp9" | "
|
|
7
|
-
isAudioCodec: (codec: "h264" | "h265" | "vp8" | "vp9" | "
|
|
5
|
+
getDefaultCrfForCodec: (codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif") => number;
|
|
6
|
+
getValidCrfRanges: (codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif") => [number, number];
|
|
7
|
+
isAudioCodec: (codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif" | undefined) => boolean;
|
|
8
8
|
proResProfileOptions: readonly ["4444-xq", "4444", "hq", "standard", "light", "proxy"];
|
|
9
9
|
validPixelFormats: readonly ["yuv420p", "yuva420p", "yuv422p", "yuv444p", "yuv420p10le", "yuv422p10le", "yuv444p10le", "yuva444p10le"];
|
|
10
10
|
DEFAULT_PIXEL_FORMAT: "yuv420p" | "yuva420p" | "yuv422p" | "yuv444p" | "yuv420p10le" | "yuv422p10le" | "yuv444p10le" | "yuva444p10le";
|
|
11
11
|
supportedAudioCodecs: {
|
|
12
|
-
readonly h264: readonly ["aac", "pcm-16"];
|
|
13
|
-
readonly 'h264-mkv': readonly ["pcm-16"];
|
|
12
|
+
readonly h264: readonly ["aac", "pcm-16", "mp3"];
|
|
13
|
+
readonly 'h264-mkv': readonly ["pcm-16", "mp3"];
|
|
14
14
|
readonly aac: readonly ["aac", "pcm-16"];
|
|
15
15
|
readonly gif: readonly [];
|
|
16
16
|
readonly h265: readonly ["aac", "pcm-16"];
|
|
@@ -24,6 +24,10 @@ export declare const BrowserSafeApis: {
|
|
|
24
24
|
h264: {
|
|
25
25
|
default: import("./file-extensions").FileExtension;
|
|
26
26
|
forAudioCodec: {
|
|
27
|
+
mp3: {
|
|
28
|
+
possible: import("./file-extensions").FileExtension[];
|
|
29
|
+
default: import("./file-extensions").FileExtension;
|
|
30
|
+
};
|
|
27
31
|
aac: {
|
|
28
32
|
possible: import("./file-extensions").FileExtension[];
|
|
29
33
|
default: import("./file-extensions").FileExtension;
|
|
@@ -73,10 +77,10 @@ export declare const BrowserSafeApis: {
|
|
|
73
77
|
};
|
|
74
78
|
};
|
|
75
79
|
};
|
|
76
|
-
|
|
80
|
+
mp3: {
|
|
77
81
|
default: import("./file-extensions").FileExtension;
|
|
78
82
|
forAudioCodec: {
|
|
79
|
-
|
|
83
|
+
mp3: {
|
|
80
84
|
possible: import("./file-extensions").FileExtension[];
|
|
81
85
|
default: import("./file-extensions").FileExtension;
|
|
82
86
|
};
|
|
@@ -86,10 +90,10 @@ export declare const BrowserSafeApis: {
|
|
|
86
90
|
};
|
|
87
91
|
};
|
|
88
92
|
};
|
|
89
|
-
|
|
93
|
+
aac: {
|
|
90
94
|
default: import("./file-extensions").FileExtension;
|
|
91
95
|
forAudioCodec: {
|
|
92
|
-
|
|
96
|
+
aac: {
|
|
93
97
|
possible: import("./file-extensions").FileExtension[];
|
|
94
98
|
default: import("./file-extensions").FileExtension;
|
|
95
99
|
};
|
|
@@ -99,22 +103,22 @@ export declare const BrowserSafeApis: {
|
|
|
99
103
|
};
|
|
100
104
|
};
|
|
101
105
|
};
|
|
102
|
-
|
|
106
|
+
wav: {
|
|
103
107
|
default: import("./file-extensions").FileExtension;
|
|
104
108
|
forAudioCodec: {
|
|
105
|
-
aac: {
|
|
106
|
-
possible: import("./file-extensions").FileExtension[];
|
|
107
|
-
default: import("./file-extensions").FileExtension;
|
|
108
|
-
};
|
|
109
109
|
"pcm-16": {
|
|
110
110
|
possible: import("./file-extensions").FileExtension[];
|
|
111
111
|
default: import("./file-extensions").FileExtension;
|
|
112
112
|
};
|
|
113
113
|
};
|
|
114
114
|
};
|
|
115
|
-
|
|
115
|
+
prores: {
|
|
116
116
|
default: import("./file-extensions").FileExtension;
|
|
117
117
|
forAudioCodec: {
|
|
118
|
+
aac: {
|
|
119
|
+
possible: import("./file-extensions").FileExtension[];
|
|
120
|
+
default: import("./file-extensions").FileExtension;
|
|
121
|
+
};
|
|
118
122
|
"pcm-16": {
|
|
119
123
|
possible: import("./file-extensions").FileExtension[];
|
|
120
124
|
default: import("./file-extensions").FileExtension;
|
|
@@ -124,6 +128,10 @@ export declare const BrowserSafeApis: {
|
|
|
124
128
|
"h264-mkv": {
|
|
125
129
|
default: import("./file-extensions").FileExtension;
|
|
126
130
|
forAudioCodec: {
|
|
131
|
+
mp3: {
|
|
132
|
+
possible: import("./file-extensions").FileExtension[];
|
|
133
|
+
default: import("./file-extensions").FileExtension;
|
|
134
|
+
};
|
|
127
135
|
"pcm-16": {
|
|
128
136
|
possible: import("./file-extensions").FileExtension[];
|
|
129
137
|
default: import("./file-extensions").FileExtension;
|
|
@@ -137,8 +145,8 @@ export declare const BrowserSafeApis: {
|
|
|
137
145
|
};
|
|
138
146
|
defaultAudioCodecs: {
|
|
139
147
|
h264: {
|
|
140
|
-
compressed: "aac" | "pcm-16" | null;
|
|
141
|
-
lossless: "aac" | "pcm-16" | null;
|
|
148
|
+
compressed: "mp3" | "aac" | "pcm-16" | null;
|
|
149
|
+
lossless: "mp3" | "aac" | "pcm-16" | null;
|
|
142
150
|
};
|
|
143
151
|
h265: {
|
|
144
152
|
compressed: "aac" | "pcm-16" | null;
|
|
@@ -152,10 +160,6 @@ export declare const BrowserSafeApis: {
|
|
|
152
160
|
compressed: "pcm-16" | "opus" | null;
|
|
153
161
|
lossless: "pcm-16" | "opus" | null;
|
|
154
162
|
};
|
|
155
|
-
prores: {
|
|
156
|
-
compressed: "aac" | "pcm-16" | null;
|
|
157
|
-
lossless: "aac" | "pcm-16" | null;
|
|
158
|
-
};
|
|
159
163
|
mp3: {
|
|
160
164
|
compressed: "mp3" | "pcm-16" | null;
|
|
161
165
|
lossless: "mp3" | "pcm-16" | null;
|
|
@@ -168,17 +172,21 @@ export declare const BrowserSafeApis: {
|
|
|
168
172
|
compressed: "pcm-16" | null;
|
|
169
173
|
lossless: "pcm-16" | null;
|
|
170
174
|
};
|
|
175
|
+
prores: {
|
|
176
|
+
compressed: "aac" | "pcm-16" | null;
|
|
177
|
+
lossless: "aac" | "pcm-16" | null;
|
|
178
|
+
};
|
|
171
179
|
"h264-mkv": {
|
|
172
|
-
compressed: "pcm-16" | null;
|
|
173
|
-
lossless: "pcm-16" | null;
|
|
180
|
+
compressed: "mp3" | "pcm-16" | null;
|
|
181
|
+
lossless: "mp3" | "pcm-16" | null;
|
|
174
182
|
};
|
|
175
183
|
gif: {
|
|
176
184
|
compressed: null;
|
|
177
185
|
lossless: null;
|
|
178
186
|
};
|
|
179
187
|
};
|
|
180
|
-
defaultCodecsForFileExtension: Record<import("./file-extensions").FileExtension, "h264" | "h265" | "vp8" | "vp9" | "
|
|
181
|
-
validateOutputFilename: <T_1 extends "h264" | "h265" | "vp8" | "vp9" | "
|
|
188
|
+
defaultCodecsForFileExtension: Record<import("./file-extensions").FileExtension, "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif">;
|
|
189
|
+
validateOutputFilename: <T_1 extends "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif">({ codec, audioCodec, extension, preferLossless, }: {
|
|
182
190
|
codec: T_1;
|
|
183
191
|
audioCodec: "mp3" | "aac" | "pcm-16" | "opus" | null;
|
|
184
192
|
extension: string;
|
|
@@ -194,6 +202,6 @@ export declare const BrowserSafeApis: {
|
|
|
194
202
|
muteOption: import(".").RemotionOption;
|
|
195
203
|
videoCodecOption: import(".").RemotionOption;
|
|
196
204
|
};
|
|
197
|
-
codecSupportsCrf: (codec: "h264" | "h265" | "vp8" | "vp9" | "
|
|
198
|
-
codecSupportsVideoBitrate: (codec: "h264" | "h265" | "vp8" | "vp9" | "
|
|
205
|
+
codecSupportsCrf: (codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif") => boolean;
|
|
206
|
+
codecSupportsVideoBitrate: (codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif") => boolean;
|
|
199
207
|
};
|
package/dist/combine-videos.js
CHANGED
|
@@ -7,6 +7,7 @@ const node_path_1 = require("node:path");
|
|
|
7
7
|
const audio_codec_1 = require("./audio-codec");
|
|
8
8
|
const call_ffmpeg_1 = require("./call-ffmpeg");
|
|
9
9
|
const is_audio_codec_1 = require("./is-audio-codec");
|
|
10
|
+
const logger_1 = require("./logger");
|
|
10
11
|
const parse_ffmpeg_progress_1 = require("./parse-ffmpeg-progress");
|
|
11
12
|
const truthy_1 = require("./truthy");
|
|
12
13
|
const combineVideos = async (options) => {
|
|
@@ -16,40 +17,45 @@ const combineVideos = async (options) => {
|
|
|
16
17
|
const fileListTxt = (0, node_path_1.join)(filelistDir, 'files.txt');
|
|
17
18
|
(0, node_fs_1.writeFileSync)(fileListTxt, fileList);
|
|
18
19
|
const resolvedAudioCodec = audioCodec !== null && audioCodec !== void 0 ? audioCodec : (0, audio_codec_1.getDefaultAudioCodec)({ codec, preferLossless: false });
|
|
20
|
+
const command = [
|
|
21
|
+
(0, is_audio_codec_1.isAudioCodec)(codec) ? null : '-r',
|
|
22
|
+
(0, is_audio_codec_1.isAudioCodec)(codec) ? null : String(fps),
|
|
23
|
+
'-f',
|
|
24
|
+
'concat',
|
|
25
|
+
'-safe',
|
|
26
|
+
'0',
|
|
27
|
+
'-i',
|
|
28
|
+
fileListTxt,
|
|
29
|
+
numberOfGifLoops === null ? null : '-loop',
|
|
30
|
+
numberOfGifLoops === null
|
|
31
|
+
? null
|
|
32
|
+
: typeof numberOfGifLoops === 'number'
|
|
33
|
+
? String(numberOfGifLoops)
|
|
34
|
+
: '-1',
|
|
35
|
+
(0, is_audio_codec_1.isAudioCodec)(codec) ? null : '-c:v',
|
|
36
|
+
(0, is_audio_codec_1.isAudioCodec)(codec) ? null : codec === 'gif' ? 'gif' : 'copy',
|
|
37
|
+
resolvedAudioCodec ? '-c:a' : null,
|
|
38
|
+
resolvedAudioCodec
|
|
39
|
+
? (0, audio_codec_1.mapAudioCodecToFfmpegAudioCodecName)(resolvedAudioCodec)
|
|
40
|
+
: null,
|
|
41
|
+
// Set max bitrate up to 512kbps, will choose lower if that's too much
|
|
42
|
+
'-b:a',
|
|
43
|
+
'512K',
|
|
44
|
+
codec === 'h264' ? '-movflags' : null,
|
|
45
|
+
codec === 'h264' ? 'faststart' : null,
|
|
46
|
+
'-y',
|
|
47
|
+
output,
|
|
48
|
+
].filter(truthy_1.truthy);
|
|
49
|
+
logger_1.Log.verbose('Combining command: ', command);
|
|
19
50
|
try {
|
|
20
|
-
const task = (0, call_ffmpeg_1.callFf)('ffmpeg',
|
|
21
|
-
(0, is_audio_codec_1.isAudioCodec)(codec) ? null : '-r',
|
|
22
|
-
(0, is_audio_codec_1.isAudioCodec)(codec) ? null : String(fps),
|
|
23
|
-
'-f',
|
|
24
|
-
'concat',
|
|
25
|
-
'-safe',
|
|
26
|
-
'0',
|
|
27
|
-
'-i',
|
|
28
|
-
fileListTxt,
|
|
29
|
-
numberOfGifLoops === null ? null : '-loop',
|
|
30
|
-
numberOfGifLoops === null
|
|
31
|
-
? null
|
|
32
|
-
: typeof numberOfGifLoops === 'number'
|
|
33
|
-
? String(numberOfGifLoops)
|
|
34
|
-
: '-1',
|
|
35
|
-
(0, is_audio_codec_1.isAudioCodec)(codec) ? null : '-c:v',
|
|
36
|
-
(0, is_audio_codec_1.isAudioCodec)(codec) ? null : codec === 'gif' ? 'gif' : 'copy',
|
|
37
|
-
resolvedAudioCodec ? '-c:a' : null,
|
|
38
|
-
resolvedAudioCodec
|
|
39
|
-
? (0, audio_codec_1.mapAudioCodecToFfmpegAudioCodecName)(resolvedAudioCodec)
|
|
40
|
-
: null,
|
|
41
|
-
// Set max bitrate up to 512kbps, will choose lower if that's too much
|
|
42
|
-
'-b:a',
|
|
43
|
-
'512K',
|
|
44
|
-
codec === 'h264' ? '-movflags' : null,
|
|
45
|
-
codec === 'h264' ? 'faststart' : null,
|
|
46
|
-
'-y',
|
|
47
|
-
output,
|
|
48
|
-
].filter(truthy_1.truthy));
|
|
51
|
+
const task = (0, call_ffmpeg_1.callFf)('ffmpeg', command);
|
|
49
52
|
(_a = task.stderr) === null || _a === void 0 ? void 0 : _a.on('data', (data) => {
|
|
50
53
|
if (onProgress) {
|
|
51
54
|
const parsed = (0, parse_ffmpeg_progress_1.parseFfmpegProgress)(data.toString('utf8'));
|
|
52
|
-
if (parsed
|
|
55
|
+
if (parsed === undefined) {
|
|
56
|
+
logger_1.Log.verbose(data.toString('utf8'));
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
53
59
|
onProgress(parsed);
|
|
54
60
|
}
|
|
55
61
|
}
|
|
@@ -16,9 +16,10 @@ const get_executable_path_1 = require("./get-executable-path");
|
|
|
16
16
|
const make_nonce_1 = require("./make-nonce");
|
|
17
17
|
const getIdealMaximumFrameCacheItems = () => {
|
|
18
18
|
const freeMemory = node_os_1.default.freemem();
|
|
19
|
-
// Assuming 1 frame is approximately
|
|
19
|
+
// Assuming 1 frame is approximately 24MB
|
|
20
|
+
// (4K video)
|
|
20
21
|
// Assuming only half the available memory should be used
|
|
21
|
-
const max = Math.floor(freeMemory / (1024 * 1024 *
|
|
22
|
+
const max = Math.floor(freeMemory / (1024 * 1024 * 24));
|
|
22
23
|
// Never store more than 2000 frames
|
|
23
24
|
// But 60 is needed even if it's going to swap
|
|
24
25
|
return Math.max(60, Math.min(max, 2000));
|
|
@@ -145,7 +146,7 @@ const startCompositor = (type, payload, logLevel, indent) => {
|
|
|
145
146
|
});
|
|
146
147
|
let resolve = null;
|
|
147
148
|
let reject = null;
|
|
148
|
-
child.on('close', (code) => {
|
|
149
|
+
child.on('close', (code, signal) => {
|
|
149
150
|
const waitersToKill = Array.from(waiters.values());
|
|
150
151
|
if (code === 0) {
|
|
151
152
|
runningStatus = { type: 'quit-without-error' };
|
|
@@ -156,9 +157,12 @@ const startCompositor = (type, payload, logLevel, indent) => {
|
|
|
156
157
|
waiters.clear();
|
|
157
158
|
}
|
|
158
159
|
else {
|
|
159
|
-
const errorMessage = Buffer.concat(stderrChunks).toString('utf-8')
|
|
160
|
+
const errorMessage = Buffer.concat(stderrChunks).toString('utf-8') +
|
|
161
|
+
outputBuffer.toString('utf-8');
|
|
160
162
|
runningStatus = { type: 'quit-with-error', error: errorMessage };
|
|
161
|
-
const error =
|
|
163
|
+
const error = code === null
|
|
164
|
+
? new Error(`Compositor exited with signal ${signal}`)
|
|
165
|
+
: new Error(`Compositor panicked with code ${code}: ${errorMessage}`);
|
|
162
166
|
for (const waiter of waitersToKill) {
|
|
163
167
|
waiter.reject(error);
|
|
164
168
|
}
|
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
* Since audio or video can be base64-encoded, those can be really long strings.
|
|
3
3
|
* Since we track the `src` property for every frame, Node.JS can run out of memory easily. Instead of duplicating the src for every frame, we save memory by replacing the full base 64 encoded data with a string `same-as-[asset-id]-[frame]` referencing a previous asset with the same src.
|
|
4
4
|
*/
|
|
5
|
-
import type {
|
|
6
|
-
export declare const compressAsset: (
|
|
5
|
+
import type { TRenderAsset } from 'remotion';
|
|
6
|
+
export declare const compressAsset: (previousRenderAssets: TRenderAsset[], newRenderAsset: TRenderAsset) => TRenderAsset;
|
|
7
7
|
export declare const isAssetCompressed: (src: string) => boolean;
|
package/dist/compress-assets.js
CHANGED
|
@@ -5,16 +5,16 @@
|
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
7
|
exports.isAssetCompressed = exports.compressAsset = void 0;
|
|
8
|
-
const compressAsset = (
|
|
9
|
-
if (
|
|
10
|
-
return
|
|
8
|
+
const compressAsset = (previousRenderAssets, newRenderAsset) => {
|
|
9
|
+
if (newRenderAsset.src.length < 400) {
|
|
10
|
+
return newRenderAsset;
|
|
11
11
|
}
|
|
12
|
-
const assetWithSameSrc =
|
|
12
|
+
const assetWithSameSrc = previousRenderAssets.find((a) => a.src === newRenderAsset.src);
|
|
13
13
|
if (!assetWithSameSrc) {
|
|
14
|
-
return
|
|
14
|
+
return newRenderAsset;
|
|
15
15
|
}
|
|
16
16
|
return {
|
|
17
|
-
...
|
|
17
|
+
...newRenderAsset,
|
|
18
18
|
src: `same-as-${assetWithSameSrc.id}-${assetWithSameSrc.frame}`,
|
|
19
19
|
};
|
|
20
20
|
};
|
package/dist/file-extensions.js
CHANGED
|
@@ -6,6 +6,7 @@ exports.defaultFileExtensionMap = {
|
|
|
6
6
|
default: 'mkv',
|
|
7
7
|
forAudioCodec: {
|
|
8
8
|
'pcm-16': { possible: ['mkv'], default: 'mkv' },
|
|
9
|
+
mp3: { possible: ['mkv'], default: 'mkv' },
|
|
9
10
|
},
|
|
10
11
|
},
|
|
11
12
|
aac: {
|
|
@@ -30,6 +31,7 @@ exports.defaultFileExtensionMap = {
|
|
|
30
31
|
forAudioCodec: {
|
|
31
32
|
'pcm-16': { possible: ['mkv', 'mov'], default: 'mkv' },
|
|
32
33
|
aac: { possible: ['mp4', 'mkv', 'mov'], default: 'mp4' },
|
|
34
|
+
mp3: { possible: ['mp4', 'mkv', 'mov'], default: 'mp4' },
|
|
33
35
|
},
|
|
34
36
|
},
|
|
35
37
|
h265: {
|
|
@@ -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" | "
|
|
5
|
-
export declare const makeFileExtensionMap: () => Record<string, ("h264" | "h265" | "vp8" | "vp9" | "
|
|
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>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { GetSilentPartsResponse } from './compositor/payloads';
|
|
2
|
+
import type { LogLevel } from './log-level';
|
|
3
|
+
export declare const getSilentParts: ({ src, noiseThresholdInDecibels: passedNoiseThresholdInDecibels, minDuration: passedMinDuration, logLevel, }: {
|
|
4
|
+
src: string;
|
|
5
|
+
minDuration?: number | undefined;
|
|
6
|
+
logLevel?: "verbose" | "info" | "warn" | "error" | undefined;
|
|
7
|
+
noiseThresholdInDecibels?: number | undefined;
|
|
8
|
+
}) => Promise<GetSilentPartsResponse>;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getSilentParts = void 0;
|
|
4
|
+
const compositor_1 = require("./compositor/compositor");
|
|
5
|
+
const getSilentParts = async ({ src, noiseThresholdInDecibels: passedNoiseThresholdInDecibels, minDuration: passedMinDuration, logLevel, }) => {
|
|
6
|
+
const compositor = (0, compositor_1.startLongRunningCompositor)((0, compositor_1.getIdealMaximumFrameCacheItems)(), logLevel !== null && logLevel !== void 0 ? logLevel : 'info', false);
|
|
7
|
+
const minDuration = passedMinDuration !== null && passedMinDuration !== void 0 ? passedMinDuration : 1;
|
|
8
|
+
if (typeof minDuration !== 'number') {
|
|
9
|
+
throw new Error(`minDuration must be a number, but was ${minDuration}`);
|
|
10
|
+
}
|
|
11
|
+
if (minDuration <= 0) {
|
|
12
|
+
throw new Error(`minDuration must be greater than 0, but was ${minDuration}`);
|
|
13
|
+
}
|
|
14
|
+
const noiseThresholdInDecibels = passedNoiseThresholdInDecibels !== null && passedNoiseThresholdInDecibels !== void 0 ? passedNoiseThresholdInDecibels : -20;
|
|
15
|
+
if (typeof noiseThresholdInDecibels !== 'number') {
|
|
16
|
+
throw new Error(`noiseThresholdInDecibels must be a number, but was ${noiseThresholdInDecibels}`);
|
|
17
|
+
}
|
|
18
|
+
if (noiseThresholdInDecibels >= 30) {
|
|
19
|
+
throw new Error(`noiseThresholdInDecibels must be less than 30, but was ${noiseThresholdInDecibels}`);
|
|
20
|
+
}
|
|
21
|
+
const res = await compositor.executeCommand('GetSilences', {
|
|
22
|
+
src,
|
|
23
|
+
minDuration,
|
|
24
|
+
noiseThresholdInDecibels,
|
|
25
|
+
});
|
|
26
|
+
const response = JSON.parse(res.toString('utf-8'));
|
|
27
|
+
compositor.finishCommands();
|
|
28
|
+
await compositor.waitForDone();
|
|
29
|
+
const { silentParts, durationInSeconds } = response;
|
|
30
|
+
return {
|
|
31
|
+
silentParts,
|
|
32
|
+
audibleParts: getAudibleParts({ silentParts, durationInSeconds }),
|
|
33
|
+
durationInSeconds,
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
exports.getSilentParts = getSilentParts;
|
|
37
|
+
const getAudibleParts = ({ silentParts, durationInSeconds, }) => {
|
|
38
|
+
const audibleParts = [];
|
|
39
|
+
let lastEnd = 0;
|
|
40
|
+
for (const silentPart of silentParts) {
|
|
41
|
+
if (silentPart.startInSeconds - lastEnd > 0) {
|
|
42
|
+
audibleParts.push({
|
|
43
|
+
startInSeconds: lastEnd,
|
|
44
|
+
endInSeconds: silentPart.startInSeconds,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
lastEnd = silentPart.endInSeconds;
|
|
48
|
+
}
|
|
49
|
+
if (durationInSeconds - lastEnd > 0) {
|
|
50
|
+
audibleParts.push({
|
|
51
|
+
startInSeconds: lastEnd,
|
|
52
|
+
endInSeconds: durationInSeconds,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
return audibleParts;
|
|
56
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
1
2
|
import execa from 'execa';
|
|
2
3
|
import { HeadlessBrowser } from './browser/Browser';
|
|
3
4
|
import { SymbolicateableError } from './error-handling/symbolicateable-error';
|
|
@@ -54,9 +55,9 @@ export declare const RenderInternals: {
|
|
|
54
55
|
width: number;
|
|
55
56
|
height: number;
|
|
56
57
|
scale: number;
|
|
57
|
-
codec: "h264" | "h265" | "vp8" | "vp9" | "
|
|
58
|
+
codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif";
|
|
58
59
|
}) => void;
|
|
59
|
-
getFileExtensionFromCodec: <T extends "h264" | "h265" | "vp8" | "vp9" | "
|
|
60
|
+
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;
|
|
60
61
|
tmpDir: (str: string) => string;
|
|
61
62
|
deleteDirectory: (directory: string) => void;
|
|
62
63
|
isServeUrl: (potentialUrl: string) => boolean;
|
|
@@ -106,21 +107,21 @@ export declare const RenderInternals: {
|
|
|
106
107
|
};
|
|
107
108
|
registerErrorSymbolicationLock: () => number;
|
|
108
109
|
unlockErrorSymbolicationLock: (id: number) => void;
|
|
109
|
-
canUseParallelEncoding: (codec: "h264" | "h265" | "vp8" | "vp9" | "
|
|
110
|
+
canUseParallelEncoding: (codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif") => boolean;
|
|
110
111
|
mimeContentType: typeof mimeContentType;
|
|
111
112
|
mimeLookup: typeof mimeLookup;
|
|
112
113
|
validateConcurrency: (value: unknown, setting: string) => void;
|
|
113
114
|
validPixelFormats: readonly ["yuv420p", "yuva420p", "yuv422p", "yuv444p", "yuv420p10le", "yuv422p10le", "yuv444p10le", "yuva444p10le"];
|
|
114
115
|
DEFAULT_BROWSER: import("./browser").Browser;
|
|
115
116
|
validateFrameRange: (frameRange: import("./frame-range").FrameRange | null) => void;
|
|
116
|
-
DEFAULT_OPENGL_RENDERER: "
|
|
117
|
-
validateOpenGlRenderer: (option: "
|
|
117
|
+
DEFAULT_OPENGL_RENDERER: "angle" | "swangle" | "egl" | "swiftshader" | null;
|
|
118
|
+
validateOpenGlRenderer: (option: "angle" | "swangle" | "egl" | "swiftshader" | null) => "angle" | "swangle" | "egl" | "swiftshader" | null;
|
|
118
119
|
validCodecs: readonly ["h264", "h265", "vp8", "vp9", "mp3", "aac", "wav", "prores", "h264-mkv", "gif"];
|
|
119
120
|
DEFAULT_PIXEL_FORMAT: "yuv420p" | "yuva420p" | "yuv422p" | "yuv444p" | "yuv420p10le" | "yuv422p10le" | "yuv444p10le" | "yuva444p10le";
|
|
120
121
|
validateJpegQuality: (q: number | undefined) => void;
|
|
121
122
|
DEFAULT_TIMEOUT: number;
|
|
122
|
-
DEFAULT_CODEC: "h264" | "h265" | "vp8" | "vp9" | "
|
|
123
|
-
isAudioCodec: (codec: "h264" | "h265" | "vp8" | "vp9" | "
|
|
123
|
+
DEFAULT_CODEC: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif";
|
|
124
|
+
isAudioCodec: (codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif" | undefined) => boolean;
|
|
124
125
|
logLevels: readonly ["verbose", "info", "warn", "error"];
|
|
125
126
|
isEqualOrBelowLogLevel: (currentLevel: "verbose" | "info" | "warn" | "error", level: "verbose" | "info" | "warn" | "error") => boolean;
|
|
126
127
|
isValidLogLevel: (level: string) => boolean;
|
|
@@ -137,7 +138,7 @@ export declare const RenderInternals: {
|
|
|
137
138
|
output: string;
|
|
138
139
|
onProgress: (p: number) => void;
|
|
139
140
|
numberOfFrames: number;
|
|
140
|
-
codec: "h264" | "h265" | "vp8" | "vp9" | "
|
|
141
|
+
codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif";
|
|
141
142
|
fps: number;
|
|
142
143
|
numberOfGifLoops: number | null;
|
|
143
144
|
audioCodec: "mp3" | "aac" | "pcm-16" | "opus" | null;
|
|
@@ -145,7 +146,7 @@ export declare const RenderInternals: {
|
|
|
145
146
|
getMinConcurrency: () => number;
|
|
146
147
|
getMaxConcurrency: () => any;
|
|
147
148
|
getDefaultAudioCodec: ({ codec, preferLossless, }: {
|
|
148
|
-
codec: "h264" | "h265" | "vp8" | "vp9" | "
|
|
149
|
+
codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif";
|
|
149
150
|
preferLossless: boolean;
|
|
150
151
|
}) => "mp3" | "aac" | "pcm-16" | "opus" | null;
|
|
151
152
|
validAudioCodecs: readonly ["pcm-16", "aac", "mp3", "opus"];
|
|
@@ -153,6 +154,10 @@ export declare const RenderInternals: {
|
|
|
153
154
|
h264: {
|
|
154
155
|
default: import("./file-extensions").FileExtension;
|
|
155
156
|
forAudioCodec: {
|
|
157
|
+
mp3: {
|
|
158
|
+
possible: import("./file-extensions").FileExtension[];
|
|
159
|
+
default: import("./file-extensions").FileExtension;
|
|
160
|
+
};
|
|
156
161
|
aac: {
|
|
157
162
|
possible: import("./file-extensions").FileExtension[];
|
|
158
163
|
default: import("./file-extensions").FileExtension;
|
|
@@ -202,10 +207,10 @@ export declare const RenderInternals: {
|
|
|
202
207
|
};
|
|
203
208
|
};
|
|
204
209
|
};
|
|
205
|
-
|
|
210
|
+
mp3: {
|
|
206
211
|
default: import("./file-extensions").FileExtension;
|
|
207
212
|
forAudioCodec: {
|
|
208
|
-
|
|
213
|
+
mp3: {
|
|
209
214
|
possible: import("./file-extensions").FileExtension[];
|
|
210
215
|
default: import("./file-extensions").FileExtension;
|
|
211
216
|
};
|
|
@@ -215,10 +220,10 @@ export declare const RenderInternals: {
|
|
|
215
220
|
};
|
|
216
221
|
};
|
|
217
222
|
};
|
|
218
|
-
|
|
223
|
+
aac: {
|
|
219
224
|
default: import("./file-extensions").FileExtension;
|
|
220
225
|
forAudioCodec: {
|
|
221
|
-
|
|
226
|
+
aac: {
|
|
222
227
|
possible: import("./file-extensions").FileExtension[];
|
|
223
228
|
default: import("./file-extensions").FileExtension;
|
|
224
229
|
};
|
|
@@ -228,22 +233,22 @@ export declare const RenderInternals: {
|
|
|
228
233
|
};
|
|
229
234
|
};
|
|
230
235
|
};
|
|
231
|
-
|
|
236
|
+
wav: {
|
|
232
237
|
default: import("./file-extensions").FileExtension;
|
|
233
238
|
forAudioCodec: {
|
|
234
|
-
aac: {
|
|
235
|
-
possible: import("./file-extensions").FileExtension[];
|
|
236
|
-
default: import("./file-extensions").FileExtension;
|
|
237
|
-
};
|
|
238
239
|
"pcm-16": {
|
|
239
240
|
possible: import("./file-extensions").FileExtension[];
|
|
240
241
|
default: import("./file-extensions").FileExtension;
|
|
241
242
|
};
|
|
242
243
|
};
|
|
243
244
|
};
|
|
244
|
-
|
|
245
|
+
prores: {
|
|
245
246
|
default: import("./file-extensions").FileExtension;
|
|
246
247
|
forAudioCodec: {
|
|
248
|
+
aac: {
|
|
249
|
+
possible: import("./file-extensions").FileExtension[];
|
|
250
|
+
default: import("./file-extensions").FileExtension;
|
|
251
|
+
};
|
|
247
252
|
"pcm-16": {
|
|
248
253
|
possible: import("./file-extensions").FileExtension[];
|
|
249
254
|
default: import("./file-extensions").FileExtension;
|
|
@@ -253,6 +258,10 @@ export declare const RenderInternals: {
|
|
|
253
258
|
"h264-mkv": {
|
|
254
259
|
default: import("./file-extensions").FileExtension;
|
|
255
260
|
forAudioCodec: {
|
|
261
|
+
mp3: {
|
|
262
|
+
possible: import("./file-extensions").FileExtension[];
|
|
263
|
+
default: import("./file-extensions").FileExtension;
|
|
264
|
+
};
|
|
256
265
|
"pcm-16": {
|
|
257
266
|
possible: import("./file-extensions").FileExtension[];
|
|
258
267
|
default: import("./file-extensions").FileExtension;
|
|
@@ -265,8 +274,8 @@ export declare const RenderInternals: {
|
|
|
265
274
|
};
|
|
266
275
|
};
|
|
267
276
|
supportedAudioCodecs: {
|
|
268
|
-
readonly h264: readonly ["aac", "pcm-16"];
|
|
269
|
-
readonly 'h264-mkv': readonly ["pcm-16"];
|
|
277
|
+
readonly h264: readonly ["aac", "pcm-16", "mp3"];
|
|
278
|
+
readonly 'h264-mkv': readonly ["pcm-16", "mp3"];
|
|
270
279
|
readonly aac: readonly ["aac", "pcm-16"];
|
|
271
280
|
readonly gif: readonly [];
|
|
272
281
|
readonly h265: readonly ["aac", "pcm-16"];
|
|
@@ -276,8 +285,8 @@ export declare const RenderInternals: {
|
|
|
276
285
|
readonly vp9: readonly ["opus", "pcm-16"];
|
|
277
286
|
readonly wav: readonly ["pcm-16"];
|
|
278
287
|
};
|
|
279
|
-
makeFileExtensionMap: () => Record<string, ("h264" | "h265" | "vp8" | "vp9" | "
|
|
280
|
-
defaultCodecsForFileExtension: Record<import("./file-extensions").FileExtension, "h264" | "h265" | "vp8" | "vp9" | "
|
|
288
|
+
makeFileExtensionMap: () => Record<string, ("h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif")[]>;
|
|
289
|
+
defaultCodecsForFileExtension: Record<import("./file-extensions").FileExtension, "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif">;
|
|
281
290
|
getExecutablePath: (type: "compositor" | "ffmpeg" | "ffprobe" | "ffmpeg-cwd") => string;
|
|
282
291
|
callFf: (bin: "ffmpeg" | "ffprobe", args: (string | null)[], options?: execa.Options<string> | undefined) => execa.ExecaChildProcess<string>;
|
|
283
292
|
dynamicLibraryPathOptions: () => {
|
|
@@ -294,8 +303,8 @@ export declare const RenderInternals: {
|
|
|
294
303
|
};
|
|
295
304
|
validStillImageFormats: readonly ["png", "jpeg", "pdf", "webp"];
|
|
296
305
|
validVideoImageFormats: readonly ["png", "jpeg", "none"];
|
|
297
|
-
DEFAULT_STILL_IMAGE_FORMAT: "
|
|
298
|
-
DEFAULT_VIDEO_IMAGE_FORMAT: "
|
|
306
|
+
DEFAULT_STILL_IMAGE_FORMAT: "jpeg" | "png" | "webp" | "pdf";
|
|
307
|
+
DEFAULT_VIDEO_IMAGE_FORMAT: "jpeg" | "png" | "none";
|
|
299
308
|
DEFAULT_JPEG_QUALITY: number;
|
|
300
309
|
chalk: {
|
|
301
310
|
enabled: () => boolean;
|
|
@@ -406,7 +415,7 @@ export declare const RenderInternals: {
|
|
|
406
415
|
frame: number;
|
|
407
416
|
serializedInputPropsWithCustomSchema: string;
|
|
408
417
|
serializedResolvedPropsWithCustomSchema: string;
|
|
409
|
-
imageFormat: "
|
|
418
|
+
imageFormat: "jpeg" | "png" | "webp" | "pdf";
|
|
410
419
|
jpegQuality: number;
|
|
411
420
|
puppeteerInstance: HeadlessBrowser | null;
|
|
412
421
|
envVariables: Record<string, string>;
|
|
@@ -38,8 +38,17 @@ const startOffthreadVideoServer = ({ downloadMap, concurrency, logLevel, indent,
|
|
|
38
38
|
}, logLevel, indent);
|
|
39
39
|
return {
|
|
40
40
|
close: () => {
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
// Note: This is being used as a promise:
|
|
42
|
+
// .close().then()
|
|
43
|
+
// but if finishCommands() fails, it acts like a sync function,
|
|
44
|
+
// therefore we have to catch an error and put a promise rejection
|
|
45
|
+
try {
|
|
46
|
+
compositor.finishCommands();
|
|
47
|
+
return compositor.waitForDone();
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
return Promise.reject(err);
|
|
51
|
+
}
|
|
43
52
|
},
|
|
44
53
|
listener: (req, response) => {
|
|
45
54
|
if (!req.url) {
|
package/dist/render-frames.js
CHANGED
|
@@ -199,9 +199,9 @@ const innerRenderFrames = async ({ onFrameUpdate, outputDir, onStart, serialized
|
|
|
199
199
|
(0, perf_1.stopPerfMeasure)(id);
|
|
200
200
|
const compressedAssets = collectedAssets.map((asset) => (0, compress_assets_1.compressAsset)(assets.filter(truthy_1.truthy).flat(1), asset));
|
|
201
201
|
assets[index] = compressedAssets;
|
|
202
|
-
compressedAssets.forEach((
|
|
202
|
+
compressedAssets.forEach((renderAsset) => {
|
|
203
203
|
(0, download_and_map_assets_to_file_1.downloadAndMapAssetsToFileUrl)({
|
|
204
|
-
|
|
204
|
+
renderAsset,
|
|
205
205
|
onDownload,
|
|
206
206
|
downloadMap,
|
|
207
207
|
}).catch((err) => {
|
|
@@ -44,7 +44,13 @@ const getSourceMap = (filePath, fileContents, type) => {
|
|
|
44
44
|
throw new Error('Sorry, non-base64 inline source-map encoding is not supported.');
|
|
45
45
|
}
|
|
46
46
|
const converted = window.atob(sm.substring(match2[0].length));
|
|
47
|
-
|
|
47
|
+
try {
|
|
48
|
+
const sourceMapConsumer = new source_map_1.SourceMapConsumer(JSON.parse(converted));
|
|
49
|
+
return Promise.resolve(sourceMapConsumer);
|
|
50
|
+
}
|
|
51
|
+
catch (_a) {
|
|
52
|
+
return Promise.resolve(null);
|
|
53
|
+
}
|
|
48
54
|
}
|
|
49
55
|
if (type === 'local') {
|
|
50
56
|
// Find adjacent file: bundle.js -> bundle.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
-
import type {
|
|
2
|
+
import type { TRenderAsset } from 'remotion';
|
|
3
3
|
import type { DownloadMap } from './assets/download-map';
|
|
4
4
|
import type { Page } from './browser/BrowserPage';
|
|
5
5
|
import type { Compositor } from './compositor/compositor';
|
|
@@ -18,5 +18,5 @@ export declare const takeFrameAndCompose: ({ freePage, imageFormat, jpegQuality,
|
|
|
18
18
|
compositor: Compositor;
|
|
19
19
|
}) => Promise<{
|
|
20
20
|
buffer: Buffer | null;
|
|
21
|
-
collectedAssets:
|
|
21
|
+
collectedAssets: TRenderAsset[];
|
|
22
22
|
}>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AudioCodec } from './audio-codec';
|
|
2
|
-
export declare const validateOutputFilename: <T extends "h264" | "h265" | "vp8" | "vp9" | "
|
|
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.1.0-
|
|
3
|
+
"version": "4.1.0-alpha12",
|
|
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.1.0-
|
|
21
|
+
"remotion": "4.1.0-alpha12"
|
|
22
22
|
},
|
|
23
23
|
"peerDependencies": {
|
|
24
24
|
"react": ">=16.8.0",
|
|
@@ -42,13 +42,13 @@
|
|
|
42
42
|
"zod": "^3.21.4"
|
|
43
43
|
},
|
|
44
44
|
"optionalDependencies": {
|
|
45
|
-
"@remotion/compositor-darwin-
|
|
46
|
-
"@remotion/compositor-darwin-
|
|
47
|
-
"@remotion/compositor-linux-
|
|
48
|
-
"@remotion/compositor-linux-
|
|
49
|
-
"@remotion/compositor-linux-arm64-musl": "4.1.0-
|
|
50
|
-
"@remotion/compositor-
|
|
51
|
-
"@remotion/compositor-
|
|
45
|
+
"@remotion/compositor-darwin-x64": "4.1.0-alpha12",
|
|
46
|
+
"@remotion/compositor-darwin-arm64": "4.1.0-alpha12",
|
|
47
|
+
"@remotion/compositor-linux-x64-gnu": "4.1.0-alpha12",
|
|
48
|
+
"@remotion/compositor-linux-arm64-gnu": "4.1.0-alpha12",
|
|
49
|
+
"@remotion/compositor-linux-arm64-musl": "4.1.0-alpha12",
|
|
50
|
+
"@remotion/compositor-win32-x64-msvc": "4.1.0-alpha12",
|
|
51
|
+
"@remotion/compositor-linux-x64-musl": "4.1.0-alpha12"
|
|
52
52
|
},
|
|
53
53
|
"keywords": [
|
|
54
54
|
"remotion",
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import type { SerializedJSONWithCustomFields } from 'remotion';
|
|
2
|
-
export declare const serializeJSONWithDate: ({ data, indent, staticBase, }: {
|
|
3
|
-
data: Record<string, unknown>;
|
|
4
|
-
indent: number | undefined;
|
|
5
|
-
staticBase: string | null;
|
|
6
|
-
}) => SerializedJSONWithCustomFields;
|
package/dist/serialize-props.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.serializeJSONWithDate = void 0;
|
|
4
|
-
// Keep in sync with /packages/core/src/input-props-serialization.ts
|
|
5
|
-
const DATE_TOKEN = 'remotion-date:';
|
|
6
|
-
const FILE_TOKEN = 'remotion-file:';
|
|
7
|
-
const serializeJSONWithDate = ({ data, indent, staticBase, }) => {
|
|
8
|
-
let customDateUsed = false;
|
|
9
|
-
let customFileUsed = false;
|
|
10
|
-
let mapUsed = false;
|
|
11
|
-
let setUsed = false;
|
|
12
|
-
const serializedString = JSON.stringify(data, function (key, value) {
|
|
13
|
-
const item = this[key];
|
|
14
|
-
if (item instanceof Date) {
|
|
15
|
-
customDateUsed = true;
|
|
16
|
-
return `${DATE_TOKEN}${item.toISOString()}`;
|
|
17
|
-
}
|
|
18
|
-
if (item instanceof Map) {
|
|
19
|
-
mapUsed = true;
|
|
20
|
-
return value;
|
|
21
|
-
}
|
|
22
|
-
if (item instanceof Set) {
|
|
23
|
-
setUsed = true;
|
|
24
|
-
return value;
|
|
25
|
-
}
|
|
26
|
-
if (typeof item === 'string' &&
|
|
27
|
-
staticBase !== null &&
|
|
28
|
-
item.startsWith(staticBase)) {
|
|
29
|
-
customFileUsed = true;
|
|
30
|
-
return `${FILE_TOKEN}${item.replace(staticBase + '/', '')}`;
|
|
31
|
-
}
|
|
32
|
-
return value;
|
|
33
|
-
}, indent);
|
|
34
|
-
return { serializedString, customDateUsed, customFileUsed, mapUsed, setUsed };
|
|
35
|
-
};
|
|
36
|
-
exports.serializeJSONWithDate = serializeJSONWithDate;
|
package/install-toolchain.mjs
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import {execSync} from 'node:child_process';
|
|
2
|
-
import {existsSync, mkdirSync, unlinkSync} from 'node:fs';
|
|
3
|
-
import {toolchains} from './toolchains.mjs';
|
|
4
|
-
|
|
5
|
-
const unpatched = [
|
|
6
|
-
'x86_64-apple-darwin',
|
|
7
|
-
'aarch64-apple-darwin',
|
|
8
|
-
'x86_64-pc-windows-gnu',
|
|
9
|
-
];
|
|
10
|
-
|
|
11
|
-
for (const toolchain of toolchains) {
|
|
12
|
-
process.stdout.write(toolchain + '...');
|
|
13
|
-
|
|
14
|
-
execSync(
|
|
15
|
-
`curl https://remotion-ffmpeg-binaries.s3.eu-central-1.amazonaws.com/${toolchain}.zip -o ${toolchain}.zip`
|
|
16
|
-
);
|
|
17
|
-
|
|
18
|
-
if (!existsSync('toolchains')) {
|
|
19
|
-
mkdirSync('toolchains');
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
if (!existsSync('toolchains/' + toolchain)) {
|
|
23
|
-
mkdirSync('toolchains/' + toolchain);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
execSync(`tar -xzf ../../${toolchain}.zip`, {
|
|
27
|
-
cwd: `toolchains/${toolchain}`,
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
unlinkSync(`${toolchain}.zip`);
|
|
31
|
-
process.stdout.write('Done.\n');
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
for (const target of unpatched) {
|
|
35
|
-
execSync(`rustup target add ${target}`);
|
|
36
|
-
}
|