@remotion/renderer 3.3.40 → 3.3.42
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/client.d.ts +1 -0
- package/client.js +1 -0
- package/dist/audio-codec.d.ts +27 -0
- package/dist/audio-codec.js +89 -0
- package/dist/client.d.ts +170 -2
- package/dist/client.js +5 -2
- package/dist/combine-videos.d.ts +2 -0
- package/dist/combine-videos.js +7 -4
- package/dist/file-extensions.d.ts +25 -0
- package/dist/file-extensions.js +88 -0
- package/dist/get-extension-from-codec.d.ts +5 -1
- package/dist/get-extension-from-codec.js +52 -26
- package/dist/guess-extension-for-media.d.ts +1 -1
- package/dist/index.d.ts +138 -1
- package/dist/index.js +8 -0
- package/dist/render-media.d.ts +7 -1
- package/dist/render-media.js +16 -8
- package/dist/stitch-frames-to-video.d.ts +3 -0
- package/dist/stitch-frames-to-video.js +34 -29
- package/dist/validate-output-filename.d.ts +7 -2
- package/dist/validate-output-filename.js +20 -51
- package/package.json +10 -10
package/client.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './dist/client';
|
package/client.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = require('./dist/client');
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Codec } from './codec';
|
|
2
|
+
export declare const validAudioCodecs: readonly ["pcm-16", "aac", "mp3", "opus"];
|
|
3
|
+
export declare type AudioCodec = typeof validAudioCodecs[number];
|
|
4
|
+
export declare const supportedAudioCodecs: {
|
|
5
|
+
readonly h264: readonly ["aac", "pcm-16"];
|
|
6
|
+
readonly 'h264-mkv': readonly ["pcm-16"];
|
|
7
|
+
readonly aac: readonly ["aac", "pcm-16"];
|
|
8
|
+
readonly gif: readonly [];
|
|
9
|
+
readonly h265: readonly ["aac", "pcm-16"];
|
|
10
|
+
readonly mp3: readonly ["mp3", "pcm-16"];
|
|
11
|
+
readonly prores: readonly ["aac", "pcm-16"];
|
|
12
|
+
readonly vp8: readonly ["opus", "pcm-16"];
|
|
13
|
+
readonly vp9: readonly ["opus", "pcm-16"];
|
|
14
|
+
readonly wav: readonly ["pcm-16"];
|
|
15
|
+
};
|
|
16
|
+
export declare const audioCodecNames: readonly ["pcm_s16le", "aac", "libmp3lame", "libopus"];
|
|
17
|
+
export declare type FfmpegAudioCodecName = typeof audioCodecNames[number];
|
|
18
|
+
export declare const mapAudioCodecToFfmpegAudioCodecName: (audioCodec: AudioCodec) => FfmpegAudioCodecName;
|
|
19
|
+
export declare const defaultAudioCodecs: {
|
|
20
|
+
[key in Codec]: {
|
|
21
|
+
[k in 'compressed' | 'lossless']: typeof supportedAudioCodecs[key][number] | null;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
export declare const getDefaultAudioCodec: ({ codec, preferLossless, }: {
|
|
25
|
+
codec: Codec;
|
|
26
|
+
preferLossless: boolean;
|
|
27
|
+
}) => AudioCodec | null;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getDefaultAudioCodec = exports.defaultAudioCodecs = exports.mapAudioCodecToFfmpegAudioCodecName = exports.audioCodecNames = exports.supportedAudioCodecs = exports.validAudioCodecs = void 0;
|
|
4
|
+
exports.validAudioCodecs = ['pcm-16', 'aac', 'mp3', 'opus'];
|
|
5
|
+
exports.supportedAudioCodecs = {
|
|
6
|
+
h264: ['aac', 'pcm-16'],
|
|
7
|
+
'h264-mkv': ['pcm-16'],
|
|
8
|
+
aac: ['aac', 'pcm-16'],
|
|
9
|
+
gif: [],
|
|
10
|
+
h265: ['aac', 'pcm-16'],
|
|
11
|
+
mp3: ['mp3', 'pcm-16'],
|
|
12
|
+
prores: ['aac', 'pcm-16'],
|
|
13
|
+
vp8: ['opus', 'pcm-16'],
|
|
14
|
+
vp9: ['opus', 'pcm-16'],
|
|
15
|
+
wav: ['pcm-16'],
|
|
16
|
+
};
|
|
17
|
+
const _satisfies = exports.supportedAudioCodecs;
|
|
18
|
+
if (_satisfies) {
|
|
19
|
+
// Just for type checking
|
|
20
|
+
}
|
|
21
|
+
exports.audioCodecNames = [
|
|
22
|
+
'pcm_s16le',
|
|
23
|
+
'aac',
|
|
24
|
+
'libmp3lame',
|
|
25
|
+
'libopus',
|
|
26
|
+
];
|
|
27
|
+
const mapAudioCodecToFfmpegAudioCodecName = (audioCodec) => {
|
|
28
|
+
if (audioCodec === 'aac') {
|
|
29
|
+
return 'aac';
|
|
30
|
+
}
|
|
31
|
+
if (audioCodec === 'mp3') {
|
|
32
|
+
return 'libmp3lame';
|
|
33
|
+
}
|
|
34
|
+
if (audioCodec === 'opus') {
|
|
35
|
+
return 'libopus';
|
|
36
|
+
}
|
|
37
|
+
if (audioCodec === 'pcm-16') {
|
|
38
|
+
return 'pcm_s16le';
|
|
39
|
+
}
|
|
40
|
+
throw new Error('unknown audio codec: ' + audioCodec);
|
|
41
|
+
};
|
|
42
|
+
exports.mapAudioCodecToFfmpegAudioCodecName = mapAudioCodecToFfmpegAudioCodecName;
|
|
43
|
+
exports.defaultAudioCodecs = {
|
|
44
|
+
'h264-mkv': {
|
|
45
|
+
lossless: 'pcm-16',
|
|
46
|
+
compressed: 'pcm-16',
|
|
47
|
+
},
|
|
48
|
+
aac: {
|
|
49
|
+
lossless: 'pcm-16',
|
|
50
|
+
compressed: 'aac',
|
|
51
|
+
},
|
|
52
|
+
gif: {
|
|
53
|
+
lossless: null,
|
|
54
|
+
compressed: null,
|
|
55
|
+
},
|
|
56
|
+
h264: {
|
|
57
|
+
lossless: 'pcm-16',
|
|
58
|
+
compressed: 'aac',
|
|
59
|
+
},
|
|
60
|
+
h265: {
|
|
61
|
+
lossless: 'pcm-16',
|
|
62
|
+
compressed: 'aac',
|
|
63
|
+
},
|
|
64
|
+
mp3: {
|
|
65
|
+
lossless: 'pcm-16',
|
|
66
|
+
compressed: 'mp3',
|
|
67
|
+
},
|
|
68
|
+
prores: {
|
|
69
|
+
lossless: 'pcm-16',
|
|
70
|
+
// V4.0: Make pcm the default
|
|
71
|
+
compressed: 'aac',
|
|
72
|
+
},
|
|
73
|
+
vp8: {
|
|
74
|
+
lossless: 'pcm-16',
|
|
75
|
+
compressed: 'opus',
|
|
76
|
+
},
|
|
77
|
+
vp9: {
|
|
78
|
+
lossless: 'pcm-16',
|
|
79
|
+
compressed: 'opus',
|
|
80
|
+
},
|
|
81
|
+
wav: {
|
|
82
|
+
lossless: 'pcm-16',
|
|
83
|
+
compressed: 'pcm-16',
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
const getDefaultAudioCodec = ({ codec, preferLossless, }) => {
|
|
87
|
+
return exports.defaultAudioCodecs[codec][preferLossless ? 'lossless' : 'compressed'];
|
|
88
|
+
};
|
|
89
|
+
exports.getDefaultAudioCodec = getDefaultAudioCodec;
|
package/dist/client.d.ts
CHANGED
|
@@ -1,10 +1,178 @@
|
|
|
1
1
|
export declare const BrowserSafeApis: {
|
|
2
|
-
getFileExtensionFromCodec:
|
|
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
|
getDefaultCrfForCodec: (codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif") => number;
|
|
5
5
|
getValidCrfRanges: (codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif") => [number, number];
|
|
6
6
|
isAudioCodec: (codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif" | undefined) => boolean;
|
|
7
|
-
proResProfileOptions: readonly ["4444-xq", "4444", "hq", "standard", "light", "proxy"];
|
|
8
7
|
validPixelFormats: readonly ["yuv420p", "yuva420p", "yuv422p", "yuv444p", "yuv420p10le", "yuv422p10le", "yuv444p10le", "yuva444p10le"];
|
|
9
8
|
DEFAULT_PIXEL_FORMAT: "yuv420p" | "yuva420p" | "yuv422p" | "yuv444p" | "yuv420p10le" | "yuv422p10le" | "yuv444p10le" | "yuva444p10le";
|
|
9
|
+
supportedAudioCodecs: {
|
|
10
|
+
readonly h264: readonly ["aac", "pcm-16"];
|
|
11
|
+
readonly 'h264-mkv': readonly ["pcm-16"];
|
|
12
|
+
readonly aac: readonly ["aac", "pcm-16"];
|
|
13
|
+
readonly gif: readonly [];
|
|
14
|
+
readonly h265: readonly ["aac", "pcm-16"];
|
|
15
|
+
readonly mp3: readonly ["mp3", "pcm-16"];
|
|
16
|
+
readonly prores: readonly ["pcm-16", "aac"];
|
|
17
|
+
readonly vp8: readonly ["opus", "pcm-16"];
|
|
18
|
+
readonly vp9: readonly ["opus", "pcm-16"];
|
|
19
|
+
readonly wav: readonly ["pcm-16"];
|
|
20
|
+
};
|
|
21
|
+
defaultFileExtensionMap: {
|
|
22
|
+
h264: {
|
|
23
|
+
default: import("./file-extensions").FileExtension;
|
|
24
|
+
forAudioCodec: {
|
|
25
|
+
aac: {
|
|
26
|
+
possible: import("./file-extensions").FileExtension[];
|
|
27
|
+
default: import("./file-extensions").FileExtension;
|
|
28
|
+
};
|
|
29
|
+
"pcm-16": {
|
|
30
|
+
possible: import("./file-extensions").FileExtension[];
|
|
31
|
+
default: import("./file-extensions").FileExtension;
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
h265: {
|
|
36
|
+
default: import("./file-extensions").FileExtension;
|
|
37
|
+
forAudioCodec: {
|
|
38
|
+
aac: {
|
|
39
|
+
possible: import("./file-extensions").FileExtension[];
|
|
40
|
+
default: import("./file-extensions").FileExtension;
|
|
41
|
+
};
|
|
42
|
+
"pcm-16": {
|
|
43
|
+
possible: import("./file-extensions").FileExtension[];
|
|
44
|
+
default: import("./file-extensions").FileExtension;
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
vp8: {
|
|
49
|
+
default: import("./file-extensions").FileExtension;
|
|
50
|
+
forAudioCodec: {
|
|
51
|
+
"pcm-16": {
|
|
52
|
+
possible: import("./file-extensions").FileExtension[];
|
|
53
|
+
default: import("./file-extensions").FileExtension;
|
|
54
|
+
};
|
|
55
|
+
opus: {
|
|
56
|
+
possible: import("./file-extensions").FileExtension[];
|
|
57
|
+
default: import("./file-extensions").FileExtension;
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
vp9: {
|
|
62
|
+
default: import("./file-extensions").FileExtension;
|
|
63
|
+
forAudioCodec: {
|
|
64
|
+
"pcm-16": {
|
|
65
|
+
possible: import("./file-extensions").FileExtension[];
|
|
66
|
+
default: import("./file-extensions").FileExtension;
|
|
67
|
+
};
|
|
68
|
+
opus: {
|
|
69
|
+
possible: import("./file-extensions").FileExtension[];
|
|
70
|
+
default: import("./file-extensions").FileExtension;
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
mp3: {
|
|
75
|
+
default: import("./file-extensions").FileExtension;
|
|
76
|
+
forAudioCodec: {
|
|
77
|
+
mp3: {
|
|
78
|
+
possible: import("./file-extensions").FileExtension[];
|
|
79
|
+
default: import("./file-extensions").FileExtension;
|
|
80
|
+
};
|
|
81
|
+
"pcm-16": {
|
|
82
|
+
possible: import("./file-extensions").FileExtension[];
|
|
83
|
+
default: import("./file-extensions").FileExtension;
|
|
84
|
+
};
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
aac: {
|
|
88
|
+
default: import("./file-extensions").FileExtension;
|
|
89
|
+
forAudioCodec: {
|
|
90
|
+
aac: {
|
|
91
|
+
possible: import("./file-extensions").FileExtension[];
|
|
92
|
+
default: import("./file-extensions").FileExtension;
|
|
93
|
+
};
|
|
94
|
+
"pcm-16": {
|
|
95
|
+
possible: import("./file-extensions").FileExtension[];
|
|
96
|
+
default: import("./file-extensions").FileExtension;
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
wav: {
|
|
101
|
+
default: import("./file-extensions").FileExtension;
|
|
102
|
+
forAudioCodec: {
|
|
103
|
+
"pcm-16": {
|
|
104
|
+
possible: import("./file-extensions").FileExtension[];
|
|
105
|
+
default: import("./file-extensions").FileExtension;
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
prores: {
|
|
110
|
+
default: import("./file-extensions").FileExtension;
|
|
111
|
+
forAudioCodec: {
|
|
112
|
+
aac: {
|
|
113
|
+
possible: import("./file-extensions").FileExtension[];
|
|
114
|
+
default: import("./file-extensions").FileExtension;
|
|
115
|
+
};
|
|
116
|
+
"pcm-16": {
|
|
117
|
+
possible: import("./file-extensions").FileExtension[];
|
|
118
|
+
default: import("./file-extensions").FileExtension;
|
|
119
|
+
};
|
|
120
|
+
};
|
|
121
|
+
};
|
|
122
|
+
"h264-mkv": {
|
|
123
|
+
default: import("./file-extensions").FileExtension;
|
|
124
|
+
forAudioCodec: {
|
|
125
|
+
"pcm-16": {
|
|
126
|
+
possible: import("./file-extensions").FileExtension[];
|
|
127
|
+
default: import("./file-extensions").FileExtension;
|
|
128
|
+
};
|
|
129
|
+
};
|
|
130
|
+
};
|
|
131
|
+
gif: {
|
|
132
|
+
default: import("./file-extensions").FileExtension;
|
|
133
|
+
forAudioCodec: {};
|
|
134
|
+
};
|
|
135
|
+
};
|
|
136
|
+
defaultAudioCodecs: {
|
|
137
|
+
h264: {
|
|
138
|
+
compressed: "aac" | "pcm-16" | null;
|
|
139
|
+
lossless: "aac" | "pcm-16" | null;
|
|
140
|
+
};
|
|
141
|
+
h265: {
|
|
142
|
+
compressed: "aac" | "pcm-16" | null;
|
|
143
|
+
lossless: "aac" | "pcm-16" | null;
|
|
144
|
+
};
|
|
145
|
+
vp8: {
|
|
146
|
+
compressed: "pcm-16" | "opus" | null;
|
|
147
|
+
lossless: "pcm-16" | "opus" | null;
|
|
148
|
+
};
|
|
149
|
+
vp9: {
|
|
150
|
+
compressed: "pcm-16" | "opus" | null;
|
|
151
|
+
lossless: "pcm-16" | "opus" | null;
|
|
152
|
+
};
|
|
153
|
+
mp3: {
|
|
154
|
+
compressed: "mp3" | "pcm-16" | null;
|
|
155
|
+
lossless: "mp3" | "pcm-16" | null;
|
|
156
|
+
};
|
|
157
|
+
aac: {
|
|
158
|
+
compressed: "aac" | "pcm-16" | null;
|
|
159
|
+
lossless: "aac" | "pcm-16" | null;
|
|
160
|
+
};
|
|
161
|
+
wav: {
|
|
162
|
+
compressed: "pcm-16" | null;
|
|
163
|
+
lossless: "pcm-16" | null;
|
|
164
|
+
};
|
|
165
|
+
prores: {
|
|
166
|
+
compressed: "aac" | "pcm-16" | null;
|
|
167
|
+
lossless: "aac" | "pcm-16" | null;
|
|
168
|
+
};
|
|
169
|
+
"h264-mkv": {
|
|
170
|
+
compressed: "pcm-16" | null;
|
|
171
|
+
lossless: "pcm-16" | null;
|
|
172
|
+
};
|
|
173
|
+
gif: {
|
|
174
|
+
compressed: null;
|
|
175
|
+
lossless: null;
|
|
176
|
+
};
|
|
177
|
+
};
|
|
10
178
|
};
|
package/dist/client.js
CHANGED
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.BrowserSafeApis = void 0;
|
|
4
|
+
const audio_codec_1 = require("./audio-codec");
|
|
4
5
|
const codec_1 = require("./codec");
|
|
5
6
|
const crf_1 = require("./crf");
|
|
7
|
+
const file_extensions_1 = require("./file-extensions");
|
|
6
8
|
const get_extension_from_codec_1 = require("./get-extension-from-codec");
|
|
7
9
|
const is_audio_codec_1 = require("./is-audio-codec");
|
|
8
10
|
const pixel_format_1 = require("./pixel-format");
|
|
9
|
-
const prores_profile_1 = require("./prores-profile");
|
|
10
11
|
exports.BrowserSafeApis = {
|
|
11
12
|
getFileExtensionFromCodec: get_extension_from_codec_1.getFileExtensionFromCodec,
|
|
12
13
|
validCodecs: codec_1.validCodecs,
|
|
13
14
|
getDefaultCrfForCodec: crf_1.getDefaultCrfForCodec,
|
|
14
15
|
getValidCrfRanges: crf_1.getValidCrfRanges,
|
|
15
16
|
isAudioCodec: is_audio_codec_1.isAudioCodec,
|
|
16
|
-
proResProfileOptions: prores_profile_1.proResProfileOptions,
|
|
17
17
|
validPixelFormats: pixel_format_1.validPixelFormats,
|
|
18
18
|
DEFAULT_PIXEL_FORMAT: pixel_format_1.DEFAULT_PIXEL_FORMAT,
|
|
19
|
+
supportedAudioCodecs: file_extensions_1.supportedAudioCodecs,
|
|
20
|
+
defaultFileExtensionMap: file_extensions_1.defaultFileExtensionMap,
|
|
21
|
+
defaultAudioCodecs: audio_codec_1.defaultAudioCodecs,
|
|
19
22
|
};
|
package/dist/combine-videos.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { AudioCodec } from './audio-codec';
|
|
1
2
|
import type { Codec } from './codec';
|
|
2
3
|
import type { FfmpegExecutable } from './ffmpeg-executable';
|
|
3
4
|
declare type Options = {
|
|
@@ -11,6 +12,7 @@ declare type Options = {
|
|
|
11
12
|
numberOfGifLoops: number | null;
|
|
12
13
|
remotionRoot: string;
|
|
13
14
|
ffmpegExecutable: FfmpegExecutable;
|
|
15
|
+
audioCodec: AudioCodec | null;
|
|
14
16
|
};
|
|
15
17
|
export declare const combineVideos: (options: Options) => Promise<void>;
|
|
16
18
|
export {};
|
package/dist/combine-videos.js
CHANGED
|
@@ -8,17 +8,18 @@ exports.combineVideos = void 0;
|
|
|
8
8
|
const execa_1 = __importDefault(require("execa"));
|
|
9
9
|
const fs_1 = require("fs");
|
|
10
10
|
const path_1 = require("path");
|
|
11
|
+
const audio_codec_1 = require("./audio-codec");
|
|
11
12
|
const ffmpeg_flags_1 = require("./ffmpeg-flags");
|
|
12
|
-
const get_audio_codec_name_1 = require("./get-audio-codec-name");
|
|
13
13
|
const is_audio_codec_1 = require("./is-audio-codec");
|
|
14
14
|
const parse_ffmpeg_progress_1 = require("./parse-ffmpeg-progress");
|
|
15
15
|
const truthy_1 = require("./truthy");
|
|
16
16
|
const combineVideos = async (options) => {
|
|
17
17
|
var _a;
|
|
18
|
-
const { files, filelistDir, output, onProgress, numberOfFrames, codec, fps, numberOfGifLoops, ffmpegExecutable, remotionRoot, } = options;
|
|
18
|
+
const { files, filelistDir, output, onProgress, numberOfFrames, codec, fps, numberOfGifLoops, ffmpegExecutable, remotionRoot, audioCodec, } = options;
|
|
19
19
|
const fileList = files.map((p) => `file '${p}'`).join('\n');
|
|
20
20
|
const fileListTxt = (0, path_1.join)(filelistDir, 'files.txt');
|
|
21
21
|
(0, fs_1.writeFileSync)(fileListTxt, fileList);
|
|
22
|
+
const resolvedAudioCodec = audioCodec !== null && audioCodec !== void 0 ? audioCodec : (0, audio_codec_1.getDefaultAudioCodec)({ codec, preferLossless: false });
|
|
22
23
|
try {
|
|
23
24
|
const task = (0, execa_1.default)(await (0, ffmpeg_flags_1.getExecutableBinary)(ffmpegExecutable, remotionRoot, 'ffmpeg'), [
|
|
24
25
|
(0, is_audio_codec_1.isAudioCodec)(codec) ? null : '-r',
|
|
@@ -37,8 +38,10 @@ const combineVideos = async (options) => {
|
|
|
37
38
|
: '-1',
|
|
38
39
|
(0, is_audio_codec_1.isAudioCodec)(codec) ? null : '-c:v',
|
|
39
40
|
(0, is_audio_codec_1.isAudioCodec)(codec) ? null : codec === 'gif' ? 'gif' : 'copy',
|
|
40
|
-
'-c:a',
|
|
41
|
-
|
|
41
|
+
resolvedAudioCodec ? '-c:a' : null,
|
|
42
|
+
resolvedAudioCodec
|
|
43
|
+
? (0, audio_codec_1.mapAudioCodecToFfmpegAudioCodecName)(resolvedAudioCodec)
|
|
44
|
+
: null,
|
|
42
45
|
// Set max bitrate up to 512kbps, will choose lower if that's too much
|
|
43
46
|
'-b:a',
|
|
44
47
|
'512K',
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Codec } from './codec';
|
|
2
|
+
export declare const supportedAudioCodecs: {
|
|
3
|
+
readonly h264: readonly ["aac", "pcm-16"];
|
|
4
|
+
readonly 'h264-mkv': readonly ["pcm-16"];
|
|
5
|
+
readonly aac: readonly ["aac", "pcm-16"];
|
|
6
|
+
readonly gif: readonly [];
|
|
7
|
+
readonly h265: readonly ["aac", "pcm-16"];
|
|
8
|
+
readonly mp3: readonly ["mp3", "pcm-16"];
|
|
9
|
+
readonly prores: readonly ["pcm-16", "aac"];
|
|
10
|
+
readonly vp8: readonly ["opus", "pcm-16"];
|
|
11
|
+
readonly vp9: readonly ["opus", "pcm-16"];
|
|
12
|
+
readonly wav: readonly ["pcm-16"];
|
|
13
|
+
};
|
|
14
|
+
export declare type FileExtension = 'aac' | '3gp' | 'm4a' | 'm4b' | 'mpg' | 'mpeg' | 'mkv' | 'mp4' | 'gif' | 'hevc' | 'mp3' | 'mov' | 'mxf' | 'wav' | 'webm';
|
|
15
|
+
export declare const defaultFileExtensionMap: {
|
|
16
|
+
[key in Codec]: {
|
|
17
|
+
default: FileExtension;
|
|
18
|
+
forAudioCodec: {
|
|
19
|
+
[k in typeof supportedAudioCodecs[key][number]]: {
|
|
20
|
+
possible: FileExtension[];
|
|
21
|
+
default: FileExtension;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.defaultFileExtensionMap = exports.supportedAudioCodecs = void 0;
|
|
4
|
+
exports.supportedAudioCodecs = {
|
|
5
|
+
h264: ['aac', 'pcm-16'],
|
|
6
|
+
'h264-mkv': ['pcm-16'],
|
|
7
|
+
aac: ['aac', 'pcm-16'],
|
|
8
|
+
gif: [],
|
|
9
|
+
h265: ['aac', 'pcm-16'],
|
|
10
|
+
mp3: ['mp3', 'pcm-16'],
|
|
11
|
+
prores: ['pcm-16', 'aac'],
|
|
12
|
+
vp8: ['opus', 'pcm-16'],
|
|
13
|
+
vp9: ['opus', 'pcm-16'],
|
|
14
|
+
wav: ['pcm-16'],
|
|
15
|
+
};
|
|
16
|
+
exports.defaultFileExtensionMap = {
|
|
17
|
+
'h264-mkv': {
|
|
18
|
+
default: 'mkv',
|
|
19
|
+
forAudioCodec: {
|
|
20
|
+
'pcm-16': { possible: ['mkv'], default: 'mkv' },
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
aac: {
|
|
24
|
+
default: 'aac',
|
|
25
|
+
forAudioCodec: {
|
|
26
|
+
aac: {
|
|
27
|
+
possible: ['aac', '3gp', 'm4a', 'm4b', 'mpg', 'mpeg'],
|
|
28
|
+
default: 'aac',
|
|
29
|
+
},
|
|
30
|
+
'pcm-16': {
|
|
31
|
+
possible: ['wav'],
|
|
32
|
+
default: 'wav',
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
gif: {
|
|
37
|
+
default: 'gif',
|
|
38
|
+
forAudioCodec: {},
|
|
39
|
+
},
|
|
40
|
+
h264: {
|
|
41
|
+
default: 'mp4',
|
|
42
|
+
forAudioCodec: {
|
|
43
|
+
'pcm-16': { possible: ['mkv'], default: 'mkv' },
|
|
44
|
+
aac: { possible: ['mp4', 'mkv'], default: 'mp4' },
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
h265: {
|
|
48
|
+
default: 'mp4',
|
|
49
|
+
forAudioCodec: {
|
|
50
|
+
aac: { possible: ['mp4', 'mkv', 'hevc'], default: 'mp4' },
|
|
51
|
+
'pcm-16': { possible: ['mkv'], default: 'mkv' },
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
mp3: {
|
|
55
|
+
default: 'mp3',
|
|
56
|
+
forAudioCodec: {
|
|
57
|
+
mp3: { possible: ['mp3'], default: 'mp3' },
|
|
58
|
+
'pcm-16': { possible: ['wav'], default: 'wav' },
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
prores: {
|
|
62
|
+
default: 'mov',
|
|
63
|
+
forAudioCodec: {
|
|
64
|
+
aac: { possible: ['mov', 'mkv', 'mxf'], default: 'mov' },
|
|
65
|
+
'pcm-16': { possible: ['mov', 'mkv', 'mxf'], default: 'mov' },
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
vp8: {
|
|
69
|
+
default: 'webm',
|
|
70
|
+
forAudioCodec: {
|
|
71
|
+
'pcm-16': { possible: ['mkv'], default: 'mkv' },
|
|
72
|
+
opus: { possible: ['webm'], default: 'webm' },
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
vp9: {
|
|
76
|
+
default: 'webm',
|
|
77
|
+
forAudioCodec: {
|
|
78
|
+
'pcm-16': { possible: ['mkv'], default: 'mkv' },
|
|
79
|
+
opus: { possible: ['webm'], default: 'webm' },
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
wav: {
|
|
83
|
+
default: 'wav',
|
|
84
|
+
forAudioCodec: {
|
|
85
|
+
'pcm-16': { possible: ['wav'], default: 'wav' },
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
};
|
|
@@ -1,2 +1,6 @@
|
|
|
1
|
+
import type { AudioCodec } from './audio-codec';
|
|
1
2
|
import type { Codec } from './codec';
|
|
2
|
-
|
|
3
|
+
import type { FileExtension } from './file-extensions';
|
|
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
|
+
export declare const defaultCodecsForFileExtension: Record<FileExtension, Codec>;
|
|
@@ -1,35 +1,61 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getFileExtensionFromCodec = void 0;
|
|
3
|
+
exports.defaultCodecsForFileExtension = exports.makeFileExtensionMap = exports.getFileExtensionFromCodec = void 0;
|
|
4
4
|
const codec_1 = require("./codec");
|
|
5
|
-
const
|
|
5
|
+
const file_extensions_1 = require("./file-extensions");
|
|
6
|
+
const getFileExtensionFromCodec = (codec, audioCodec) => {
|
|
6
7
|
if (!codec_1.validCodecs.includes(codec)) {
|
|
7
8
|
throw new Error(`Codec must be one of the following: ${codec_1.validCodecs.join(', ')}, but got ${codec}`);
|
|
8
9
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
case 'h264':
|
|
13
|
-
return 'mp4';
|
|
14
|
-
// The chunks will be rendered as mkv, but the final output will still be MP4
|
|
15
|
-
case 'h264-mkv':
|
|
16
|
-
return 'mkv';
|
|
17
|
-
case 'h265':
|
|
18
|
-
return 'mp4';
|
|
19
|
-
case 'mp3':
|
|
20
|
-
return 'mp3';
|
|
21
|
-
case 'prores':
|
|
22
|
-
return 'mov';
|
|
23
|
-
case 'vp8':
|
|
24
|
-
return 'webm';
|
|
25
|
-
case 'vp9':
|
|
26
|
-
return 'webm';
|
|
27
|
-
case 'gif':
|
|
28
|
-
return 'gif';
|
|
29
|
-
case 'wav':
|
|
30
|
-
return 'wav';
|
|
31
|
-
default:
|
|
32
|
-
throw new Error("Don't know which file extension to use for codec " + codec);
|
|
10
|
+
const map = file_extensions_1.defaultFileExtensionMap[codec];
|
|
11
|
+
if (audioCodec === null) {
|
|
12
|
+
return map.default;
|
|
33
13
|
}
|
|
14
|
+
const typedAudioCodec = audioCodec;
|
|
15
|
+
if (!(typedAudioCodec in map.forAudioCodec)) {
|
|
16
|
+
throw new Error(`Audio codec ${typedAudioCodec} is not supported for codec ${codec}`);
|
|
17
|
+
}
|
|
18
|
+
return map.forAudioCodec[audioCodec]
|
|
19
|
+
.default;
|
|
34
20
|
};
|
|
35
21
|
exports.getFileExtensionFromCodec = getFileExtensionFromCodec;
|
|
22
|
+
const makeFileExtensionMap = () => {
|
|
23
|
+
const map = {};
|
|
24
|
+
Object.keys(file_extensions_1.defaultFileExtensionMap).forEach((_codec) => {
|
|
25
|
+
const codec = _codec;
|
|
26
|
+
const fileExtMap = file_extensions_1.defaultFileExtensionMap[codec];
|
|
27
|
+
const audioCodecs = Object.keys(fileExtMap.forAudioCodec);
|
|
28
|
+
const possibleExtensionsForAudioCodec = audioCodecs.map((audioCodec) => fileExtMap.forAudioCodec[audioCodec].possible);
|
|
29
|
+
const allPossibleExtensions = [
|
|
30
|
+
fileExtMap.default,
|
|
31
|
+
...possibleExtensionsForAudioCodec.flat(1),
|
|
32
|
+
];
|
|
33
|
+
for (const extension of allPossibleExtensions) {
|
|
34
|
+
if (!map[extension]) {
|
|
35
|
+
map[extension] = [];
|
|
36
|
+
}
|
|
37
|
+
if (!map[extension].includes(codec)) {
|
|
38
|
+
map[extension].push(codec);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
return map;
|
|
43
|
+
};
|
|
44
|
+
exports.makeFileExtensionMap = makeFileExtensionMap;
|
|
45
|
+
exports.defaultCodecsForFileExtension = {
|
|
46
|
+
'3gp': 'aac',
|
|
47
|
+
aac: 'aac',
|
|
48
|
+
gif: 'gif',
|
|
49
|
+
hevc: 'h265',
|
|
50
|
+
m4a: 'aac',
|
|
51
|
+
m4b: 'aac',
|
|
52
|
+
mkv: 'h264-mkv',
|
|
53
|
+
mov: 'prores',
|
|
54
|
+
mp3: 'mp3',
|
|
55
|
+
mp4: 'h264',
|
|
56
|
+
mpeg: 'aac',
|
|
57
|
+
mpg: 'aac',
|
|
58
|
+
mxf: 'prores',
|
|
59
|
+
wav: 'wav',
|
|
60
|
+
webm: 'vp8',
|
|
61
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { mimeContentType, mimeLookup } from './mime-types';
|
|
|
5
5
|
import * as perf from './perf';
|
|
6
6
|
export type { RenderMediaOnDownload } from './assets/download-and-map-assets-to-file';
|
|
7
7
|
export type { DownloadMap } from './assets/download-map';
|
|
8
|
+
export { AudioCodec } from './audio-codec';
|
|
8
9
|
export { Browser } from './browser';
|
|
9
10
|
export { BrowserExecutable } from './browser-executable';
|
|
10
11
|
export { BrowserLog } from './browser-log';
|
|
@@ -15,6 +16,7 @@ export { ErrorWithStackFrame } from './error-handling/handle-javascript-exceptio
|
|
|
15
16
|
export { FfmpegExecutable } from './ffmpeg-executable';
|
|
16
17
|
export { FfmpegVersion } from './ffmpeg-flags';
|
|
17
18
|
export type { FfmpegOverrideFn } from './ffmpeg-override';
|
|
19
|
+
export { FileExtension } from './file-extensions';
|
|
18
20
|
export { FrameRange } from './frame-range';
|
|
19
21
|
export { getCanExtractFramesFast } from './get-can-extract-frames-fast';
|
|
20
22
|
export { getCompositions } from './get-compositions';
|
|
@@ -60,7 +62,7 @@ export declare const RenderInternals: {
|
|
|
60
62
|
scale: number;
|
|
61
63
|
codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif";
|
|
62
64
|
}) => void;
|
|
63
|
-
getFileExtensionFromCodec:
|
|
65
|
+
getFileExtensionFromCodec: <T extends "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif">(codec: T, audioCodec: "mp3" | "aac" | "pcm-16" | "opus" | null) => import("./file-extensions").FileExtension;
|
|
64
66
|
tmpDir: (str: string) => string;
|
|
65
67
|
deleteDirectory: (directory: string) => Promise<void>;
|
|
66
68
|
isServeUrl: (potentialUrl: string) => boolean;
|
|
@@ -155,5 +157,140 @@ export declare const RenderInternals: {
|
|
|
155
157
|
numberOfGifLoops: number | null;
|
|
156
158
|
remotionRoot: string;
|
|
157
159
|
ffmpegExecutable: import("./ffmpeg-executable").FfmpegExecutable;
|
|
160
|
+
audioCodec: "mp3" | "aac" | "pcm-16" | "opus" | null;
|
|
158
161
|
}) => Promise<void>;
|
|
162
|
+
getDefaultAudioCodec: ({ codec, preferLossless, }: {
|
|
163
|
+
codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif";
|
|
164
|
+
preferLossless: boolean;
|
|
165
|
+
}) => "mp3" | "aac" | "pcm-16" | "opus" | null;
|
|
166
|
+
validAudioCodecs: readonly ["pcm-16", "aac", "mp3", "opus"];
|
|
167
|
+
defaultFileExtensionMap: {
|
|
168
|
+
h264: {
|
|
169
|
+
default: import("./file-extensions").FileExtension;
|
|
170
|
+
forAudioCodec: {
|
|
171
|
+
aac: {
|
|
172
|
+
possible: import("./file-extensions").FileExtension[];
|
|
173
|
+
default: import("./file-extensions").FileExtension;
|
|
174
|
+
};
|
|
175
|
+
"pcm-16": {
|
|
176
|
+
possible: import("./file-extensions").FileExtension[];
|
|
177
|
+
default: import("./file-extensions").FileExtension;
|
|
178
|
+
};
|
|
179
|
+
};
|
|
180
|
+
};
|
|
181
|
+
h265: {
|
|
182
|
+
default: import("./file-extensions").FileExtension;
|
|
183
|
+
forAudioCodec: {
|
|
184
|
+
aac: {
|
|
185
|
+
possible: import("./file-extensions").FileExtension[];
|
|
186
|
+
default: import("./file-extensions").FileExtension;
|
|
187
|
+
};
|
|
188
|
+
"pcm-16": {
|
|
189
|
+
possible: import("./file-extensions").FileExtension[];
|
|
190
|
+
default: import("./file-extensions").FileExtension;
|
|
191
|
+
};
|
|
192
|
+
};
|
|
193
|
+
};
|
|
194
|
+
vp8: {
|
|
195
|
+
default: import("./file-extensions").FileExtension;
|
|
196
|
+
forAudioCodec: {
|
|
197
|
+
"pcm-16": {
|
|
198
|
+
possible: import("./file-extensions").FileExtension[];
|
|
199
|
+
default: import("./file-extensions").FileExtension;
|
|
200
|
+
};
|
|
201
|
+
opus: {
|
|
202
|
+
possible: import("./file-extensions").FileExtension[];
|
|
203
|
+
default: import("./file-extensions").FileExtension;
|
|
204
|
+
};
|
|
205
|
+
};
|
|
206
|
+
};
|
|
207
|
+
vp9: {
|
|
208
|
+
default: import("./file-extensions").FileExtension;
|
|
209
|
+
forAudioCodec: {
|
|
210
|
+
"pcm-16": {
|
|
211
|
+
possible: import("./file-extensions").FileExtension[];
|
|
212
|
+
default: import("./file-extensions").FileExtension;
|
|
213
|
+
};
|
|
214
|
+
opus: {
|
|
215
|
+
possible: import("./file-extensions").FileExtension[];
|
|
216
|
+
default: import("./file-extensions").FileExtension;
|
|
217
|
+
};
|
|
218
|
+
};
|
|
219
|
+
};
|
|
220
|
+
mp3: {
|
|
221
|
+
default: import("./file-extensions").FileExtension;
|
|
222
|
+
forAudioCodec: {
|
|
223
|
+
mp3: {
|
|
224
|
+
possible: import("./file-extensions").FileExtension[];
|
|
225
|
+
default: import("./file-extensions").FileExtension;
|
|
226
|
+
};
|
|
227
|
+
"pcm-16": {
|
|
228
|
+
possible: import("./file-extensions").FileExtension[];
|
|
229
|
+
default: import("./file-extensions").FileExtension;
|
|
230
|
+
};
|
|
231
|
+
};
|
|
232
|
+
};
|
|
233
|
+
aac: {
|
|
234
|
+
default: import("./file-extensions").FileExtension;
|
|
235
|
+
forAudioCodec: {
|
|
236
|
+
aac: {
|
|
237
|
+
possible: import("./file-extensions").FileExtension[];
|
|
238
|
+
default: import("./file-extensions").FileExtension;
|
|
239
|
+
};
|
|
240
|
+
"pcm-16": {
|
|
241
|
+
possible: import("./file-extensions").FileExtension[];
|
|
242
|
+
default: import("./file-extensions").FileExtension;
|
|
243
|
+
};
|
|
244
|
+
};
|
|
245
|
+
};
|
|
246
|
+
wav: {
|
|
247
|
+
default: import("./file-extensions").FileExtension;
|
|
248
|
+
forAudioCodec: {
|
|
249
|
+
"pcm-16": {
|
|
250
|
+
possible: import("./file-extensions").FileExtension[];
|
|
251
|
+
default: import("./file-extensions").FileExtension;
|
|
252
|
+
};
|
|
253
|
+
};
|
|
254
|
+
};
|
|
255
|
+
prores: {
|
|
256
|
+
default: import("./file-extensions").FileExtension;
|
|
257
|
+
forAudioCodec: {
|
|
258
|
+
aac: {
|
|
259
|
+
possible: import("./file-extensions").FileExtension[];
|
|
260
|
+
default: import("./file-extensions").FileExtension;
|
|
261
|
+
};
|
|
262
|
+
"pcm-16": {
|
|
263
|
+
possible: import("./file-extensions").FileExtension[];
|
|
264
|
+
default: import("./file-extensions").FileExtension;
|
|
265
|
+
};
|
|
266
|
+
};
|
|
267
|
+
};
|
|
268
|
+
"h264-mkv": {
|
|
269
|
+
default: import("./file-extensions").FileExtension;
|
|
270
|
+
forAudioCodec: {
|
|
271
|
+
"pcm-16": {
|
|
272
|
+
possible: import("./file-extensions").FileExtension[];
|
|
273
|
+
default: import("./file-extensions").FileExtension;
|
|
274
|
+
};
|
|
275
|
+
};
|
|
276
|
+
};
|
|
277
|
+
gif: {
|
|
278
|
+
default: import("./file-extensions").FileExtension;
|
|
279
|
+
forAudioCodec: {};
|
|
280
|
+
};
|
|
281
|
+
};
|
|
282
|
+
supportedAudioCodecs: {
|
|
283
|
+
readonly h264: readonly ["aac", "pcm-16"];
|
|
284
|
+
readonly 'h264-mkv': readonly ["pcm-16"];
|
|
285
|
+
readonly aac: readonly ["aac", "pcm-16"];
|
|
286
|
+
readonly gif: readonly [];
|
|
287
|
+
readonly h265: readonly ["aac", "pcm-16"];
|
|
288
|
+
readonly mp3: readonly ["mp3", "pcm-16"];
|
|
289
|
+
readonly prores: readonly ["pcm-16", "aac"];
|
|
290
|
+
readonly vp8: readonly ["opus", "pcm-16"];
|
|
291
|
+
readonly vp9: readonly ["opus", "pcm-16"];
|
|
292
|
+
readonly wav: readonly ["pcm-16"];
|
|
293
|
+
};
|
|
294
|
+
makeFileExtensionMap: () => Record<string, ("h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif")[]>;
|
|
295
|
+
defaultCodecsForFileExtension: Record<import("./file-extensions").FileExtension, "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif">;
|
|
159
296
|
};
|
package/dist/index.js
CHANGED
|
@@ -30,6 +30,7 @@ exports.RenderInternals = exports.validateOutputFilename = exports.stitchFramesT
|
|
|
30
30
|
const execa_1 = __importDefault(require("execa"));
|
|
31
31
|
const download_file_1 = require("./assets/download-file");
|
|
32
32
|
const download_map_1 = require("./assets/download-map");
|
|
33
|
+
const audio_codec_1 = require("./audio-codec");
|
|
33
34
|
const browser_1 = require("./browser");
|
|
34
35
|
const TimeoutSettings_1 = require("./browser/TimeoutSettings");
|
|
35
36
|
const can_use_parallel_encoding_1 = require("./can-use-parallel-encoding");
|
|
@@ -42,6 +43,7 @@ const ensure_output_directory_1 = require("./ensure-output-directory");
|
|
|
42
43
|
const symbolicate_error_1 = require("./error-handling/symbolicate-error");
|
|
43
44
|
const symbolicateable_error_1 = require("./error-handling/symbolicateable-error");
|
|
44
45
|
const ffmpeg_flags_1 = require("./ffmpeg-flags");
|
|
46
|
+
const file_extensions_1 = require("./file-extensions");
|
|
45
47
|
const find_closest_package_json_1 = require("./find-closest-package-json");
|
|
46
48
|
const frame_range_1 = require("./frame-range");
|
|
47
49
|
const get_concurrency_1 = require("./get-concurrency");
|
|
@@ -153,6 +155,12 @@ exports.RenderInternals = {
|
|
|
153
155
|
validateBitrate: validate_videobitrate_1.validateBitrate,
|
|
154
156
|
getFfmpegVersion: ffmpeg_flags_1.getFfmpegVersion,
|
|
155
157
|
combineVideos: combine_videos_1.combineVideos,
|
|
158
|
+
getDefaultAudioCodec: audio_codec_1.getDefaultAudioCodec,
|
|
159
|
+
validAudioCodecs: audio_codec_1.validAudioCodecs,
|
|
160
|
+
defaultFileExtensionMap: file_extensions_1.defaultFileExtensionMap,
|
|
161
|
+
supportedAudioCodecs: file_extensions_1.supportedAudioCodecs,
|
|
162
|
+
makeFileExtensionMap: get_extension_from_codec_1.makeFileExtensionMap,
|
|
163
|
+
defaultCodecsForFileExtension: get_extension_from_codec_1.defaultCodecsForFileExtension,
|
|
156
164
|
};
|
|
157
165
|
// Warn of potential performance issues with Apple Silicon (M1 chip under Rosetta)
|
|
158
166
|
(0, check_apple_silicon_1.checkNodeVersionAndWarnAboutRosetta)();
|
package/dist/render-media.d.ts
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import type { SmallTCompMetadata } from 'remotion';
|
|
3
3
|
import type { RenderMediaOnDownload } from './assets/download-and-map-assets-to-file';
|
|
4
4
|
import type { DownloadMap } from './assets/download-map';
|
|
5
|
+
import type { AudioCodec } from './audio-codec';
|
|
5
6
|
import type { BrowserExecutable } from './browser-executable';
|
|
6
7
|
import type { BrowserLog } from './browser-log';
|
|
7
8
|
import type { Browser as PuppeteerBrowser } from './browser/Browser';
|
|
@@ -63,6 +64,10 @@ export declare type RenderMediaOptions = {
|
|
|
63
64
|
* @deprecated Only for Remotion internal usage
|
|
64
65
|
*/
|
|
65
66
|
downloadMap?: DownloadMap;
|
|
67
|
+
/**
|
|
68
|
+
* @deprecated Only for Remotion internal usage
|
|
69
|
+
*/
|
|
70
|
+
preferLossless?: boolean;
|
|
66
71
|
muted?: boolean;
|
|
67
72
|
enforceAudioTrack?: boolean;
|
|
68
73
|
ffmpegOverride?: FfmpegOverrideFn;
|
|
@@ -70,6 +75,7 @@ export declare type RenderMediaOptions = {
|
|
|
70
75
|
videoBitrate?: string | null;
|
|
71
76
|
onSlowestFrames?: OnSlowestFrames;
|
|
72
77
|
disallowParallelEncoding?: boolean;
|
|
78
|
+
audioCodec?: AudioCodec | null;
|
|
73
79
|
} & ServeUrlOrWebpackBundle & ConcurrencyOrParallelism;
|
|
74
80
|
declare type ConcurrencyOrParallelism = {
|
|
75
81
|
concurrency?: number | string | null;
|
|
@@ -84,5 +90,5 @@ declare type ConcurrencyOrParallelism = {
|
|
|
84
90
|
* @description Render a video from a composition
|
|
85
91
|
* @link https://www.remotion.dev/docs/renderer/render-media
|
|
86
92
|
*/
|
|
87
|
-
export declare const renderMedia: ({ proResProfile, crf, composition, ffmpegExecutable, ffprobeExecutable, inputProps, pixelFormat, codec, envVariables, frameRange, puppeteerInstance, outputLocation, onProgress, overwrite, onDownload, dumpBrowserLogs, onBrowserLog, onStart, timeoutInMilliseconds, chromiumOptions, scale, browserExecutable, port, cancelSignal, muted, enforceAudioTrack, ffmpegOverride, audioBitrate, videoBitrate, onSlowestFrames, ...options }: RenderMediaOptions) => Promise<Buffer | null>;
|
|
93
|
+
export declare const renderMedia: ({ proResProfile, crf, composition, ffmpegExecutable, ffprobeExecutable, inputProps, pixelFormat, codec, envVariables, frameRange, puppeteerInstance, outputLocation, onProgress, overwrite, onDownload, dumpBrowserLogs, onBrowserLog, onStart, timeoutInMilliseconds, chromiumOptions, scale, browserExecutable, port, cancelSignal, muted, enforceAudioTrack, ffmpegOverride, audioBitrate, videoBitrate, onSlowestFrames, audioCodec, ...options }: RenderMediaOptions) => Promise<Buffer | null>;
|
|
88
94
|
export {};
|
package/dist/render-media.js
CHANGED
|
@@ -55,8 +55,8 @@ const getConcurrency = (others) => {
|
|
|
55
55
|
* @description Render a video from a composition
|
|
56
56
|
* @link https://www.remotion.dev/docs/renderer/render-media
|
|
57
57
|
*/
|
|
58
|
-
const renderMedia = ({ proResProfile, crf, composition, ffmpegExecutable, ffprobeExecutable, inputProps, pixelFormat, codec, envVariables, frameRange, puppeteerInstance, outputLocation, onProgress, overwrite, onDownload, dumpBrowserLogs, onBrowserLog, onStart, timeoutInMilliseconds, chromiumOptions, scale, browserExecutable, port, cancelSignal, muted, enforceAudioTrack, ffmpegOverride, audioBitrate, videoBitrate, onSlowestFrames, ...options }) => {
|
|
59
|
-
var _a, _b, _c, _d;
|
|
58
|
+
const renderMedia = ({ proResProfile, crf, composition, ffmpegExecutable, ffprobeExecutable, inputProps, pixelFormat, codec, envVariables, frameRange, puppeteerInstance, outputLocation, onProgress, overwrite, onDownload, dumpBrowserLogs, onBrowserLog, onStart, timeoutInMilliseconds, chromiumOptions, scale, browserExecutable, port, cancelSignal, muted, enforceAudioTrack, ffmpegOverride, audioBitrate, videoBitrate, onSlowestFrames, audioCodec, ...options }) => {
|
|
59
|
+
var _a, _b, _c, _d, _e;
|
|
60
60
|
const remotionRoot = (0, find_closest_package_json_1.findRemotionRoot)();
|
|
61
61
|
(0, validate_ffmpeg_1.validateFfmpeg)(ffmpegExecutable !== null && ffmpegExecutable !== void 0 ? ffmpegExecutable : null, remotionRoot, 'ffmpeg');
|
|
62
62
|
(0, quality_1.validateQuality)(options.quality);
|
|
@@ -69,7 +69,12 @@ const renderMedia = ({ proResProfile, crf, composition, ffmpegExecutable, ffprob
|
|
|
69
69
|
});
|
|
70
70
|
(0, pixel_format_1.validateSelectedPixelFormatAndCodecCombination)(pixelFormat, codec);
|
|
71
71
|
if (outputLocation) {
|
|
72
|
-
(0, validate_output_filename_1.validateOutputFilename)(
|
|
72
|
+
(0, validate_output_filename_1.validateOutputFilename)({
|
|
73
|
+
codec,
|
|
74
|
+
audioCodec: audioCodec !== null && audioCodec !== void 0 ? audioCodec : null,
|
|
75
|
+
extension: (0, get_extension_of_filename_1.getExtensionOfFilename)(outputLocation),
|
|
76
|
+
preferLossless: (_a = options.preferLossless) !== null && _a !== void 0 ? _a : false,
|
|
77
|
+
});
|
|
73
78
|
}
|
|
74
79
|
const absoluteOutputLocation = outputLocation
|
|
75
80
|
? path_1.default.resolve(process.cwd(), outputLocation)
|
|
@@ -77,9 +82,9 @@ const renderMedia = ({ proResProfile, crf, composition, ffmpegExecutable, ffprob
|
|
|
77
82
|
(0, validate_scale_1.validateScale)(scale);
|
|
78
83
|
const concurrency = getConcurrency(options);
|
|
79
84
|
(0, validate_ffmpeg_override_1.validateFfmpegOverride)(ffmpegOverride);
|
|
80
|
-
const everyNthFrame = (
|
|
85
|
+
const everyNthFrame = (_b = options.everyNthFrame) !== null && _b !== void 0 ? _b : 1;
|
|
81
86
|
(0, validate_every_nth_frame_1.validateEveryNthFrame)(everyNthFrame, codec);
|
|
82
|
-
const numberOfGifLoops = (
|
|
87
|
+
const numberOfGifLoops = (_c = options.numberOfGifLoops) !== null && _c !== void 0 ? _c : null;
|
|
83
88
|
const serveUrl = (0, legacy_webpack_config_1.getServeUrlWithFallback)(options);
|
|
84
89
|
let stitchStage = 'encoding';
|
|
85
90
|
let stitcherFfmpeg;
|
|
@@ -90,7 +95,7 @@ const renderMedia = ({ proResProfile, crf, composition, ffmpegExecutable, ffprob
|
|
|
90
95
|
let encodedDoneIn = null;
|
|
91
96
|
let cancelled = false;
|
|
92
97
|
const renderStart = Date.now();
|
|
93
|
-
const downloadMap = (
|
|
98
|
+
const downloadMap = (_d = options.downloadMap) !== null && _d !== void 0 ? _d : (0, download_map_1.makeDownloadMap)();
|
|
94
99
|
const { estimatedUsage, freeMemory, hasEnoughMemory } = (0, prestitcher_memory_usage_1.shouldUseParallelEncoding)({
|
|
95
100
|
height: composition.height,
|
|
96
101
|
width: composition.width,
|
|
@@ -111,11 +116,11 @@ const renderMedia = ({ proResProfile, crf, composition, ffmpegExecutable, ffprob
|
|
|
111
116
|
}
|
|
112
117
|
const imageFormat = (0, is_audio_codec_1.isAudioCodec)(codec)
|
|
113
118
|
? 'none'
|
|
114
|
-
: (
|
|
119
|
+
: (_e = options.imageFormat) !== null && _e !== void 0 ? _e : 'jpeg';
|
|
115
120
|
const quality = imageFormat === 'jpeg' ? options.quality : undefined;
|
|
116
121
|
(0, image_format_1.validateSelectedPixelFormatAndImageFormatCombination)(pixelFormat, imageFormat);
|
|
117
122
|
const preEncodedFileLocation = parallelEncoding
|
|
118
|
-
? path_1.default.join(downloadMap.preEncode, 'pre-encode.' + (0, get_extension_from_codec_1.getFileExtensionFromCodec)(codec))
|
|
123
|
+
? path_1.default.join(downloadMap.preEncode, 'pre-encode.' + (0, get_extension_from_codec_1.getFileExtensionFromCodec)(codec, audioCodec !== null && audioCodec !== void 0 ? audioCodec : null))
|
|
119
124
|
: null;
|
|
120
125
|
const outputDir = parallelEncoding
|
|
121
126
|
? null
|
|
@@ -270,6 +275,7 @@ const renderMedia = ({ proResProfile, crf, composition, ffmpegExecutable, ffprob
|
|
|
270
275
|
return Promise.all([renderFramesReturn, waitForPrestitcherIfNecessary()]);
|
|
271
276
|
})
|
|
272
277
|
.then(([{ assetsInfo }]) => {
|
|
278
|
+
var _a;
|
|
273
279
|
renderedDoneIn = Date.now() - renderStart;
|
|
274
280
|
callUpdate();
|
|
275
281
|
if (absoluteOutputLocation) {
|
|
@@ -285,6 +291,7 @@ const renderMedia = ({ proResProfile, crf, composition, ffmpegExecutable, ffprob
|
|
|
285
291
|
internalOptions: {
|
|
286
292
|
preEncodedFileLocation,
|
|
287
293
|
imageFormat,
|
|
294
|
+
preferLossless: (_a = options.preferLossless) !== null && _a !== void 0 ? _a : false,
|
|
288
295
|
},
|
|
289
296
|
force: overwrite !== null && overwrite !== void 0 ? overwrite : overwrite_1.DEFAULT_OVERWRITE,
|
|
290
297
|
pixelFormat,
|
|
@@ -309,6 +316,7 @@ const renderMedia = ({ proResProfile, crf, composition, ffmpegExecutable, ffprob
|
|
|
309
316
|
ffmpegOverride,
|
|
310
317
|
audioBitrate,
|
|
311
318
|
videoBitrate,
|
|
319
|
+
audioCodec: audioCodec !== null && audioCodec !== void 0 ? audioCodec : null,
|
|
312
320
|
}),
|
|
313
321
|
stitchStart,
|
|
314
322
|
]);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import type { RenderMediaOnDownload } from './assets/download-and-map-assets-to-file';
|
|
3
3
|
import type { RenderAssetInfo } from './assets/download-map';
|
|
4
|
+
import type { AudioCodec } from './audio-codec';
|
|
4
5
|
import type { Codec } from './codec';
|
|
5
6
|
import type { FfmpegExecutable } from './ffmpeg-executable';
|
|
6
7
|
import type { FfmpegOverrideFn } from './ffmpeg-override';
|
|
@@ -20,6 +21,7 @@ export declare type StitcherOptions = {
|
|
|
20
21
|
pixelFormat?: PixelFormat;
|
|
21
22
|
numberOfGifLoops?: number | null;
|
|
22
23
|
codec?: Codec;
|
|
24
|
+
audioCodec?: AudioCodec | null;
|
|
23
25
|
crf?: number | null;
|
|
24
26
|
onProgress?: (progress: number) => void;
|
|
25
27
|
onDownload?: RenderMediaOnDownload;
|
|
@@ -32,6 +34,7 @@ export declare type StitcherOptions = {
|
|
|
32
34
|
internalOptions?: {
|
|
33
35
|
preEncodedFileLocation: string | null;
|
|
34
36
|
imageFormat: ImageFormat;
|
|
37
|
+
preferLossless: boolean;
|
|
35
38
|
};
|
|
36
39
|
muted?: boolean;
|
|
37
40
|
enforceAudioTrack?: boolean;
|
|
@@ -34,6 +34,7 @@ const remotion_1 = require("remotion");
|
|
|
34
34
|
const calculate_asset_positions_1 = require("./assets/calculate-asset-positions");
|
|
35
35
|
const convert_assets_to_file_urls_1 = require("./assets/convert-assets-to-file-urls");
|
|
36
36
|
const download_and_map_assets_to_file_1 = require("./assets/download-and-map-assets-to-file");
|
|
37
|
+
const audio_codec_1 = require("./audio-codec");
|
|
37
38
|
const codec_1 = require("./codec");
|
|
38
39
|
const codec_supports_media_1 = require("./codec-supports-media");
|
|
39
40
|
const convert_number_of_gif_loops_to_ffmpeg_1 = require("./convert-number-of-gif-loops-to-ffmpeg");
|
|
@@ -41,7 +42,6 @@ const crf_1 = require("./crf");
|
|
|
41
42
|
const delete_directory_1 = require("./delete-directory");
|
|
42
43
|
const ffmpeg_flags_1 = require("./ffmpeg-flags");
|
|
43
44
|
const find_closest_package_json_1 = require("./find-closest-package-json");
|
|
44
|
-
const get_audio_codec_name_1 = require("./get-audio-codec-name");
|
|
45
45
|
const get_codec_name_1 = require("./get-codec-name");
|
|
46
46
|
const get_extension_from_codec_1 = require("./get-extension-from-codec");
|
|
47
47
|
const get_prores_profile_name_1 = require("./get-prores-profile-name");
|
|
@@ -109,7 +109,7 @@ const getAssetsData = async ({ assets, onDownload, fps, expectedFrames, verbose,
|
|
|
109
109
|
return outName;
|
|
110
110
|
};
|
|
111
111
|
const spawnFfmpeg = async (options, remotionRoot) => {
|
|
112
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w;
|
|
112
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y;
|
|
113
113
|
remotion_1.Internals.validateDimension(options.height, 'height', 'passed to `stitchFramesToVideo()`');
|
|
114
114
|
remotion_1.Internals.validateDimension(options.width, 'width', 'passed to `stitchFramesToVideo()`');
|
|
115
115
|
const codec = (_a = options.codec) !== null && _a !== void 0 ? _a : codec_1.DEFAULT_CODEC;
|
|
@@ -129,12 +129,8 @@ const spawnFfmpeg = async (options, remotionRoot) => {
|
|
|
129
129
|
const pixelFormat = (_b = options.pixelFormat) !== null && _b !== void 0 ? _b : pixel_format_1.DEFAULT_PIXEL_FORMAT;
|
|
130
130
|
await (0, validate_ffmpeg_1.validateFfmpeg)((_c = options.ffmpegExecutable) !== null && _c !== void 0 ? _c : null, remotionRoot, 'ffmpeg');
|
|
131
131
|
const encoderName = (0, get_codec_name_1.getCodecName)(codec);
|
|
132
|
-
const audioCodecName = (0, get_audio_codec_name_1.getAudioCodecName)(codec);
|
|
133
132
|
const proResProfileName = (0, get_prores_profile_name_1.getProResProfileName)(codec, options.proResProfile);
|
|
134
133
|
const mediaSupport = (0, codec_supports_media_1.codecSupportsMedia)(codec);
|
|
135
|
-
const tempFile = options.outputLocation
|
|
136
|
-
? null
|
|
137
|
-
: path_1.default.join(options.assetsInfo.downloadMap.stitchFrames, `out.${(0, get_extension_from_codec_1.getFileExtensionFromCodec)(codec)}`);
|
|
138
134
|
const shouldRenderAudio = mediaSupport.audio &&
|
|
139
135
|
(options.assetsInfo.assets.flat(1).length > 0 ||
|
|
140
136
|
options.enforceAudioTrack) &&
|
|
@@ -143,10 +139,17 @@ const spawnFfmpeg = async (options, remotionRoot) => {
|
|
|
143
139
|
if (!shouldRenderAudio && !shouldRenderVideo) {
|
|
144
140
|
throw new Error('The output format has neither audio nor video. This can happen if you are rendering an audio codec and the output file has no audio or the muted flag was passed.');
|
|
145
141
|
}
|
|
142
|
+
// Explanation: https://github.com/remotion-dev/remotion/issues/1647
|
|
143
|
+
const resolvedAudioCodec = ((_d = options.internalOptions) === null || _d === void 0 ? void 0 : _d.preferLossless)
|
|
144
|
+
? (0, audio_codec_1.getDefaultAudioCodec)({ codec, preferLossless: true })
|
|
145
|
+
: (_e = options.audioCodec) !== null && _e !== void 0 ? _e : (0, audio_codec_1.getDefaultAudioCodec)({ codec, preferLossless: false });
|
|
146
|
+
const tempFile = options.outputLocation
|
|
147
|
+
? null
|
|
148
|
+
: path_1.default.join(options.assetsInfo.downloadMap.stitchFrames, `out.${(0, get_extension_from_codec_1.getFileExtensionFromCodec)(codec, resolvedAudioCodec)}`);
|
|
146
149
|
if (options.verbose) {
|
|
147
|
-
console.log('[verbose] ffmpeg', (
|
|
150
|
+
console.log('[verbose] ffmpeg', (_f = options.ffmpegExecutable) !== null && _f !== void 0 ? _f : 'ffmpeg in PATH');
|
|
148
151
|
console.log('[verbose] encoder', encoderName);
|
|
149
|
-
console.log('[verbose] audioCodec',
|
|
152
|
+
console.log('[verbose] audioCodec', resolvedAudioCodec);
|
|
150
153
|
console.log('[verbose] pixelFormat', pixelFormat);
|
|
151
154
|
if (options.ffmpegOverride) {
|
|
152
155
|
console.log('[verbose] ffmpegOverride', options.ffmpegOverride);
|
|
@@ -174,34 +177,34 @@ const spawnFfmpeg = async (options, remotionRoot) => {
|
|
|
174
177
|
onDownload: options.onDownload,
|
|
175
178
|
fps: options.fps,
|
|
176
179
|
expectedFrames,
|
|
177
|
-
verbose: (
|
|
178
|
-
ffmpegExecutable: (
|
|
179
|
-
ffprobeExecutable: (
|
|
180
|
+
verbose: (_g = options.verbose) !== null && _g !== void 0 ? _g : false,
|
|
181
|
+
ffmpegExecutable: (_h = options.ffmpegExecutable) !== null && _h !== void 0 ? _h : null,
|
|
182
|
+
ffprobeExecutable: (_j = options.ffprobeExecutable) !== null && _j !== void 0 ? _j : null,
|
|
180
183
|
onProgress: (prog) => updateProgress(prog, 0),
|
|
181
184
|
downloadMap: options.assetsInfo.downloadMap,
|
|
182
185
|
remotionRoot,
|
|
183
186
|
})
|
|
184
187
|
: null;
|
|
185
188
|
if (mediaSupport.audio && !mediaSupport.video) {
|
|
186
|
-
if (!
|
|
189
|
+
if (!resolvedAudioCodec) {
|
|
187
190
|
throw new TypeError('exporting audio but has no audio codec name. Report this in the Remotion repo.');
|
|
188
191
|
}
|
|
189
|
-
const ffmpegTask = (0, execa_1.default)(await (0, ffmpeg_flags_1.getExecutableBinary)((
|
|
192
|
+
const ffmpegTask = (0, execa_1.default)(await (0, ffmpeg_flags_1.getExecutableBinary)((_k = options.ffmpegExecutable) !== null && _k !== void 0 ? _k : null, remotionRoot, 'ffmpeg'), [
|
|
190
193
|
'-i',
|
|
191
194
|
audio,
|
|
192
195
|
'-c:a',
|
|
193
|
-
|
|
196
|
+
(0, audio_codec_1.mapAudioCodecToFfmpegAudioCodecName)(resolvedAudioCodec),
|
|
194
197
|
// Set bitrate up to 320k, for aac it might effectively be lower
|
|
195
198
|
'-b:a',
|
|
196
|
-
(
|
|
199
|
+
(_l = options.audioBitrate) !== null && _l !== void 0 ? _l : '320k',
|
|
197
200
|
options.force ? '-y' : null,
|
|
198
|
-
(
|
|
201
|
+
(_m = options.outputLocation) !== null && _m !== void 0 ? _m : tempFile,
|
|
199
202
|
].filter(remotion_1.Internals.truthy));
|
|
200
|
-
(
|
|
203
|
+
(_o = options.cancelSignal) === null || _o === void 0 ? void 0 : _o.call(options, () => {
|
|
201
204
|
ffmpegTask.kill();
|
|
202
205
|
});
|
|
203
206
|
await ffmpegTask;
|
|
204
|
-
(
|
|
207
|
+
(_p = options.onProgress) === null || _p === void 0 ? void 0 : _p.call(options, expectedFrames);
|
|
205
208
|
if (audio) {
|
|
206
209
|
await (0, delete_directory_1.deleteDirectory)(path_1.default.dirname(audio));
|
|
207
210
|
}
|
|
@@ -226,8 +229,8 @@ const spawnFfmpeg = async (options, remotionRoot) => {
|
|
|
226
229
|
}
|
|
227
230
|
const ffmpegArgs = [
|
|
228
231
|
['-r', String(options.fps)],
|
|
229
|
-
...(((
|
|
230
|
-
? [['-i', (
|
|
232
|
+
...(((_q = options.internalOptions) === null || _q === void 0 ? void 0 : _q.preEncodedFileLocation)
|
|
233
|
+
? [['-i', (_r = options.internalOptions) === null || _r === void 0 ? void 0 : _r.preEncodedFileLocation]]
|
|
231
234
|
: [
|
|
232
235
|
['-f', 'image2'],
|
|
233
236
|
['-s', `${options.width}x${options.height}`],
|
|
@@ -235,16 +238,16 @@ const spawnFfmpeg = async (options, remotionRoot) => {
|
|
|
235
238
|
['-i', options.assetsInfo.imageSequenceName],
|
|
236
239
|
]),
|
|
237
240
|
audio ? ['-i', audio] : null,
|
|
238
|
-
((
|
|
241
|
+
((_s = options.numberOfGifLoops) !== null && _s !== void 0 ? _s : null) === null
|
|
239
242
|
? null
|
|
240
243
|
: [
|
|
241
244
|
'-loop',
|
|
242
|
-
(0, convert_number_of_gif_loops_to_ffmpeg_1.convertNumberOfGifLoopsToFfmpegSyntax)((
|
|
245
|
+
(0, convert_number_of_gif_loops_to_ffmpeg_1.convertNumberOfGifLoopsToFfmpegSyntax)((_t = options.numberOfGifLoops) !== null && _t !== void 0 ? _t : null),
|
|
243
246
|
],
|
|
244
247
|
// -c:v is the same as -vcodec as -codec:video
|
|
245
248
|
// and specified the video codec.
|
|
246
249
|
['-c:v', encoderName],
|
|
247
|
-
...(((
|
|
250
|
+
...(((_u = options.internalOptions) === null || _u === void 0 ? void 0 : _u.preEncodedFileLocation)
|
|
248
251
|
? []
|
|
249
252
|
: [
|
|
250
253
|
proResProfileName ? ['-profile:v', proResProfileName] : null,
|
|
@@ -259,9 +262,11 @@ const spawnFfmpeg = async (options, remotionRoot) => {
|
|
|
259
262
|
}),
|
|
260
263
|
]),
|
|
261
264
|
codec === 'h264' ? ['-movflags', 'faststart'] : null,
|
|
262
|
-
|
|
265
|
+
resolvedAudioCodec
|
|
266
|
+
? ['-c:a', (0, audio_codec_1.mapAudioCodecToFfmpegAudioCodecName)(resolvedAudioCodec)]
|
|
267
|
+
: null,
|
|
263
268
|
// Set max bitrate up to 1024kbps, will choose lower if that's too much
|
|
264
|
-
|
|
269
|
+
resolvedAudioCodec ? ['-b:a', options.audioBitrate || '512K'] : null,
|
|
265
270
|
// Ignore metadata that may come from remote media
|
|
266
271
|
['-map_metadata', '-1'],
|
|
267
272
|
[
|
|
@@ -270,7 +275,7 @@ const spawnFfmpeg = async (options, remotionRoot) => {
|
|
|
270
275
|
[`Made with Remotion`, packageJson ? packageJson.version : null].join(' '),
|
|
271
276
|
],
|
|
272
277
|
options.force ? '-y' : null,
|
|
273
|
-
(
|
|
278
|
+
(_v = options.outputLocation) !== null && _v !== void 0 ? _v : tempFile,
|
|
274
279
|
];
|
|
275
280
|
if (options.verbose) {
|
|
276
281
|
console.log('Generated FFMPEG command:');
|
|
@@ -284,15 +289,15 @@ const spawnFfmpeg = async (options, remotionRoot) => {
|
|
|
284
289
|
console.log('Generated final FFMPEG command:');
|
|
285
290
|
console.log(finalFfmpegString);
|
|
286
291
|
}
|
|
287
|
-
const task = (0, execa_1.default)(await (0, ffmpeg_flags_1.getExecutableBinary)((
|
|
292
|
+
const task = (0, execa_1.default)(await (0, ffmpeg_flags_1.getExecutableBinary)((_w = options.ffmpegExecutable) !== null && _w !== void 0 ? _w : null, remotionRoot, 'ffmpeg'), finalFfmpegString, {
|
|
288
293
|
cwd: options.dir,
|
|
289
294
|
});
|
|
290
|
-
(
|
|
295
|
+
(_x = options.cancelSignal) === null || _x === void 0 ? void 0 : _x.call(options, () => {
|
|
291
296
|
task.kill();
|
|
292
297
|
});
|
|
293
298
|
let ffmpegOutput = '';
|
|
294
299
|
let isFinished = false;
|
|
295
|
-
(
|
|
300
|
+
(_y = task.stderr) === null || _y === void 0 ? void 0 : _y.on('data', (data) => {
|
|
296
301
|
var _a;
|
|
297
302
|
const str = data.toString();
|
|
298
303
|
ffmpegOutput += str;
|
|
@@ -1,2 +1,7 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare const validateOutputFilename: (codec
|
|
1
|
+
import type { AudioCodec } from './audio-codec';
|
|
2
|
+
export declare const validateOutputFilename: <T extends "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif">({ codec, audioCodec, extension, preferLossless, }: {
|
|
3
|
+
codec: T;
|
|
4
|
+
audioCodec: AudioCodec | null;
|
|
5
|
+
extension: string;
|
|
6
|
+
preferLossless: boolean;
|
|
7
|
+
}) => void;
|
|
@@ -1,57 +1,26 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.validateOutputFilename = void 0;
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
if (codec === 'prores') {
|
|
26
|
-
const allowedProResExtensions = ['mov', 'mkv', 'mxf'];
|
|
27
|
-
if (!extension || !allowedProResExtensions.includes(extension)) {
|
|
28
|
-
throw new TypeError(`When using the 'prores' codec, the output must end in one of those extensions: ${allowedProResExtensions
|
|
29
|
-
.map((a) => `.${a}`)
|
|
30
|
-
.join(', ')}`);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
if (codec === 'mp3') {
|
|
34
|
-
if (extension !== 'mp3') {
|
|
35
|
-
throw new TypeError("When using the 'mp3' codec, the output must end in .mp3");
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
if (codec === 'aac') {
|
|
39
|
-
const allowedAacExtensions = ['aac', '3gp', 'm4a', 'm4b', 'mpg', 'mpeg'];
|
|
40
|
-
if (!extension || !allowedAacExtensions.includes(extension)) {
|
|
41
|
-
throw new TypeError(`When using the 'aac' codec, the output must end in one of those extensions: ${allowedAacExtensions
|
|
42
|
-
.map((a) => `.${a}`)
|
|
43
|
-
.join(', ')}`);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
if (codec === 'wav') {
|
|
47
|
-
if (extension !== 'wav') {
|
|
48
|
-
throw new TypeError("When using the 'wav' codec, the output location must end in .wav.");
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
if (codec === 'gif') {
|
|
52
|
-
if (extension !== 'gif') {
|
|
53
|
-
throw new TypeError('When using the GIF codec, the output filename must end in .gif.');
|
|
54
|
-
}
|
|
4
|
+
const audio_codec_1 = require("./audio-codec");
|
|
5
|
+
const file_extensions_1 = require("./file-extensions");
|
|
6
|
+
const validateOutputFilename = ({ codec, audioCodec, extension, preferLossless, }) => {
|
|
7
|
+
if (!file_extensions_1.defaultFileExtensionMap[codec]) {
|
|
8
|
+
throw new TypeError(`The codec "${codec}" is not supported. Supported codecs are: ${Object.keys(file_extensions_1.defaultFileExtensionMap).join(', ')}`);
|
|
9
|
+
}
|
|
10
|
+
const map = file_extensions_1.defaultFileExtensionMap[codec];
|
|
11
|
+
const resolvedAudioCodec = audioCodec !== null && audioCodec !== void 0 ? audioCodec : (0, audio_codec_1.getDefaultAudioCodec)({ codec, preferLossless });
|
|
12
|
+
if (resolvedAudioCodec === null) {
|
|
13
|
+
if (extension !== map.default) {
|
|
14
|
+
throw new TypeError(`When using the ${codec} codec, the output filename must end in .${map.default}.`);
|
|
15
|
+
}
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (!(resolvedAudioCodec in map.forAudioCodec)) {
|
|
19
|
+
throw new Error(`Audio codec ${resolvedAudioCodec} is not supported for codec ${codec}`);
|
|
20
|
+
}
|
|
21
|
+
const acceptableExtensions = map.forAudioCodec[resolvedAudioCodec].possible;
|
|
22
|
+
if (!acceptableExtensions.includes(extension)) {
|
|
23
|
+
throw new TypeError(`When using the ${codec} codec with the ${resolvedAudioCodec} audio codec, the output filename must end in one of the following: ${acceptableExtensions.join(', ')}.`);
|
|
55
24
|
}
|
|
56
25
|
};
|
|
57
26
|
exports.validateOutputFilename = validateOutputFilename;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remotion/renderer",
|
|
3
|
-
"version": "3.3.
|
|
3
|
+
"version": "3.3.42",
|
|
4
4
|
"description": "Renderer for Remotion",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"execa": "5.1.1",
|
|
26
26
|
"extract-zip": "2.0.1",
|
|
27
|
-
"remotion": "3.3.
|
|
27
|
+
"remotion": "3.3.42",
|
|
28
28
|
"source-map": "^0.8.0-beta.0",
|
|
29
29
|
"ws": "8.7.0"
|
|
30
30
|
},
|
|
@@ -49,13 +49,13 @@
|
|
|
49
49
|
"vitest": "0.24.3"
|
|
50
50
|
},
|
|
51
51
|
"optionalDependencies": {
|
|
52
|
-
"@remotion/compositor-darwin-arm64": "3.3.
|
|
53
|
-
"@remotion/compositor-darwin-x64": "3.3.
|
|
54
|
-
"@remotion/compositor-linux-arm64-gnu": "3.3.
|
|
55
|
-
"@remotion/compositor-linux-arm64-musl": "3.3.
|
|
56
|
-
"@remotion/compositor-linux-x64-gnu": "3.3.
|
|
57
|
-
"@remotion/compositor-linux-x64-musl": "3.3.
|
|
58
|
-
"@remotion/compositor-win32-x64-msvc": "3.3.
|
|
52
|
+
"@remotion/compositor-darwin-arm64": "3.3.42",
|
|
53
|
+
"@remotion/compositor-darwin-x64": "3.3.42",
|
|
54
|
+
"@remotion/compositor-linux-arm64-gnu": "3.3.42",
|
|
55
|
+
"@remotion/compositor-linux-arm64-musl": "3.3.42",
|
|
56
|
+
"@remotion/compositor-linux-x64-gnu": "3.3.42",
|
|
57
|
+
"@remotion/compositor-linux-x64-musl": "3.3.42",
|
|
58
|
+
"@remotion/compositor-win32-x64-msvc": "3.3.42"
|
|
59
59
|
},
|
|
60
60
|
"keywords": [
|
|
61
61
|
"remotion",
|
|
@@ -67,5 +67,5 @@
|
|
|
67
67
|
"publishConfig": {
|
|
68
68
|
"access": "public"
|
|
69
69
|
},
|
|
70
|
-
"gitHead": "
|
|
70
|
+
"gitHead": "bfb8098300fb75d4c27220eead954c2dc8e5b4ce"
|
|
71
71
|
}
|