Skip to content

Commit fd1b51b

Browse files
committed
Merge branch 'main' into pr/1800
2 parents 418a634 + f03427b commit fd1b51b

File tree

81 files changed

+1043
-322
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

81 files changed

+1043
-322
lines changed
+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import type {AudioCodec} from '@remotion/renderer';
2+
import {RenderInternals} from '@remotion/renderer';
3+
4+
let _audioCodec: AudioCodec | null = null;
5+
6+
export const setAudioCodec = (audioCodec: AudioCodec | null) => {
7+
if (audioCodec === null) {
8+
_audioCodec = null;
9+
return;
10+
}
11+
12+
if (!RenderInternals.validAudioCodecs.includes(audioCodec)) {
13+
throw new Error(
14+
`Audio codec must be one of the following: ${RenderInternals.validAudioCodecs.join(
15+
', '
16+
)}, but got ${audioCodec}`
17+
);
18+
}
19+
20+
_audioCodec = audioCodec;
21+
};
22+
23+
export const getAudioCodec = () => {
24+
return _audioCodec;
25+
};

packages/cli/src/config/index.ts

+4
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import {getWebpackCaching} from './webpack-caching';
3838
import type {WebpackConfiguration} from '@remotion/bundler';
3939
// eslint-disable-next-line no-restricted-imports
4040
import type {ConfigType} from 'remotion';
41+
import {getAudioCodec, setAudioCodec} from './audio-codec';
4142
import {
4243
getAudioBitrate,
4344
getVideoBitrate,
@@ -175,6 +176,8 @@ export const Config: ConfigType = {
175176
Puppeteer,
176177
Rendering,
177178
Output,
179+
// Options added after migration
180+
setAudioCodec,
178181
} as ConfigType;
179182

180183
export type {Concurrency, WebpackConfiguration, WebpackOverrideFn};
@@ -199,6 +202,7 @@ export const ConfigInternals = {
199202
getConcurrency,
200203
getCurrentPuppeteerTimeout,
201204
getQuality,
205+
getAudioCodec,
202206
getStillFrame,
203207
getShouldOutputImageSequence,
204208
getDotEnvLocation,

packages/cli/src/get-audio-codec.ts

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import type {AudioCodec} from '@remotion/renderer';
2+
import {ConfigInternals} from './config';
3+
import {parsedCli} from './parse-command-line';
4+
5+
export const getResolvedAudioCodec = (): AudioCodec | null => {
6+
return parsedCli['audio-codec'] ?? ConfigInternals.getAudioCodec();
7+
};

packages/cli/src/get-filename.ts

+6-28
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,26 @@
1-
import type {Codec} from '@remotion/renderer';
21
import {RenderInternals} from '@remotion/renderer';
32
import {Log} from './log';
43
import {getOutputLocation} from './user-passed-output-location';
54

65
export const getOutputFilename = ({
7-
codec,
86
imageSequence,
97
compositionName,
108
defaultExtension,
119
args,
1210
}: {
13-
codec: Codec;
1411
imageSequence: boolean;
1512
compositionName: string;
1613
defaultExtension: string;
1714
args: string[];
1815
}): string => {
19-
let filename = getOutputLocation({
16+
const filename = getOutputLocation({
2017
compositionId: compositionName,
2118
defaultExtension,
2219
args,
2320
type: imageSequence ? 'sequence' : 'asset',
2421
});
2522

26-
let extension = RenderInternals.getExtensionOfFilename(filename);
23+
const extension = RenderInternals.getExtensionOfFilename(filename);
2724
if (imageSequence) {
2825
if (extension !== null) {
2926
Log.error(
@@ -37,29 +34,10 @@ export const getOutputFilename = ({
3734
}
3835

3936
if (extension === null && !imageSequence) {
40-
if (codec === 'h264' || codec === 'h265') {
41-
Log.warn('No file extension specified, adding .mp4 automatically.');
42-
filename += '.mp4';
43-
extension = 'mp4';
44-
}
45-
46-
if (codec === 'h264-mkv') {
47-
Log.warn('No file extension specified, adding .mkv automatically.');
48-
filename += '.mkv';
49-
extension = 'mkv';
50-
}
51-
52-
if (codec === 'vp8' || codec === 'vp9') {
53-
Log.warn('No file extension specified, adding .webm automatically.');
54-
filename += '.webm';
55-
extension = 'webm';
56-
}
57-
58-
if (codec === 'prores') {
59-
Log.warn('No file extension specified, adding .mov automatically.');
60-
filename += '.mov';
61-
extension = 'mov';
62-
}
37+
Log.warn(
38+
`No file extension specified, adding ${defaultExtension} automatically.`
39+
);
40+
return `${filename}.${defaultExtension}`;
6341
}
6442

6543
return filename;

packages/cli/src/get-final-output-codec.ts

+31-34
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,23 @@
1-
import type {Codec, CodecOrUndefined} from '@remotion/renderer';
1+
import type {Codec, CodecOrUndefined, FileExtension} from '@remotion/renderer';
22
import {RenderInternals} from '@remotion/renderer';
33

4-
const fileExtensions: Record<string, Codec[]> = {
5-
webm: ['vp8', 'vp9'],
6-
hevc: ['h265'],
7-
mp3: ['mp3'],
8-
mov: ['prores'],
9-
wav: ['wav'],
10-
aac: ['aac'],
11-
mkv: ['h264-mkv'],
12-
gif: ['gif'],
13-
mp4: ['h264'],
14-
m4a: ['aac'],
15-
};
16-
17-
const deriveExtensionFromFilename = (extension: string | null) => {
4+
const deriveCodecsFromFilename = (
5+
extension: string | null
6+
): {
7+
possible: Codec[];
8+
default: Codec | null;
9+
} => {
1810
if (extension === null) {
19-
return [];
11+
return {possible: [], default: null};
2012
}
2113

22-
return fileExtensions[extension] ?? [];
14+
return {
15+
default:
16+
RenderInternals.defaultCodecsForFileExtension[
17+
extension as FileExtension
18+
] ?? null,
19+
possible: RenderInternals.makeFileExtensionMap()[extension] ?? [],
20+
};
2321
};
2422

2523
export const getFinalOutputCodec = ({
@@ -37,15 +35,14 @@ export const getFinalOutputCodec = ({
3735
RenderInternals.getExtensionOfFilename(downloadName);
3836
const outNameExtension = RenderInternals.getExtensionOfFilename(outName);
3937

40-
const derivedDownloadCodecs = deriveExtensionFromFilename(
41-
downloadNameExtension
42-
);
43-
const derivedOutNameCodecs = deriveExtensionFromFilename(outNameExtension);
38+
const derivedDownloadCodecs = deriveCodecsFromFilename(downloadNameExtension);
39+
const derivedOutNameCodecs = deriveCodecsFromFilename(outNameExtension);
4440

4541
if (
46-
derivedDownloadCodecs.length > 0 &&
47-
derivedOutNameCodecs.length > 0 &&
48-
derivedDownloadCodecs.join('') !== derivedOutNameCodecs.join('')
42+
derivedDownloadCodecs.possible.length > 0 &&
43+
derivedOutNameCodecs.possible.length > 0 &&
44+
derivedDownloadCodecs.possible.join('') !==
45+
derivedOutNameCodecs.possible.join('')
4946
) {
5047
throw new TypeError(
5148
`The download name is ${downloadName} but the output name is ${outName}. The file extensions must match`
@@ -54,22 +51,22 @@ export const getFinalOutputCodec = ({
5451

5552
if (cliFlag) {
5653
if (
57-
derivedDownloadCodecs.length > 0 &&
58-
derivedDownloadCodecs.indexOf(cliFlag) === -1
54+
derivedDownloadCodecs.possible.length > 0 &&
55+
derivedDownloadCodecs.possible.indexOf(cliFlag) === -1
5956
) {
6057
throw new TypeError(
61-
`The download name is ${downloadName} but --codec=${cliFlag} was passed. The download name implies a codec of ${derivedDownloadCodecs.join(
58+
`The download name is ${downloadName} but --codec=${cliFlag} was passed. The download name implies a codec of ${derivedDownloadCodecs.possible.join(
6259
' or '
6360
)} which does not align with the --codec flag.`
6461
);
6562
}
6663

6764
if (
68-
derivedOutNameCodecs.length > 0 &&
69-
derivedOutNameCodecs.indexOf(cliFlag) === -1
65+
derivedOutNameCodecs.possible.length > 0 &&
66+
derivedOutNameCodecs.possible.indexOf(cliFlag) === -1
7067
) {
7168
throw new TypeError(
72-
`The out name is ${outName} but --codec=${cliFlag} was passed. The out name implies a codec of ${derivedOutNameCodecs.join(
69+
`The out name is ${outName} but --codec=${cliFlag} was passed. The out name implies a codec of ${derivedOutNameCodecs.possible.join(
7370
' or '
7471
)} which does not align with the --codec flag.`
7572
);
@@ -78,16 +75,16 @@ export const getFinalOutputCodec = ({
7875
return {codec: cliFlag, reason: 'from --codec flag'};
7976
}
8077

81-
if (derivedDownloadCodecs.length > 0) {
78+
if (derivedDownloadCodecs.possible.length > 0) {
8279
return {
83-
codec: derivedDownloadCodecs[0],
80+
codec: derivedDownloadCodecs.default as Codec,
8481
reason: 'derived from download name',
8582
};
8683
}
8784

88-
if (derivedOutNameCodecs.length > 0) {
85+
if (derivedOutNameCodecs.possible.length > 0) {
8986
return {
90-
codec: derivedOutNameCodecs[0],
87+
codec: derivedOutNameCodecs.default as Codec,
9188
reason: 'derived from out name',
9289
};
9390
}

packages/cli/src/get-render-media-options.ts

+3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type {Codec, RenderMediaOptions} from '@remotion/renderer';
22
import {RenderInternals} from '@remotion/renderer';
33
import {ConfigInternals} from './config';
4+
import {getResolvedAudioCodec} from './get-audio-codec';
45
import {getCliOptions} from './get-cli-options';
56
import {getImageFormat} from './image-formats';
67

@@ -49,6 +50,7 @@ export const getRenderMediaOptions = async ({
4950
});
5051

5152
const imageFormat = getImageFormat(codec);
53+
const audioCodec = getResolvedAudioCodec();
5254

5355
return {
5456
outputLocation,
@@ -91,5 +93,6 @@ export const getRenderMediaOptions = async ({
9193
codec,
9294
audioBitrate,
9395
videoBitrate,
96+
audioCodec,
9497
};
9598
};

packages/cli/src/parse-command-line.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type {
2+
AudioCodec,
23
BrowserExecutable,
34
Codec,
45
FfmpegExecutable,
@@ -35,6 +36,7 @@ export type CommandLineOptions = {
3536
['public-dir']: string;
3637
['audio-bitrate']: string;
3738
['video-bitrate']: string;
39+
['audio-codec']: AudioCodec;
3840
crf: number;
3941
force: boolean;
4042
overwrite: boolean;

packages/cli/src/render.tsx

+7-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {Internals} from 'remotion';
1414
import {chalk} from './chalk';
1515
import {ConfigInternals} from './config';
1616
import {findEntryPoint} from './entry-point';
17+
import {getResolvedAudioCodec} from './get-audio-codec';
1718
import {
1819
getAndValidateAbsoluteOutputFile,
1920
getCliOptions,
@@ -177,11 +178,15 @@ export const render = async (remotionRoot: string, args: string[]) => {
177178
scale,
178179
});
179180

181+
const audioCodec = getResolvedAudioCodec();
182+
180183
const relativeOutputLocation = getOutputFilename({
181-
codec,
182184
imageSequence: shouldOutputImageSequence,
183185
compositionName: compositionId,
184-
defaultExtension: RenderInternals.getFileExtensionFromCodec(codec),
186+
defaultExtension: RenderInternals.getFileExtensionFromCodec(
187+
codec,
188+
audioCodec
189+
),
185190
args: argsAfterComposition,
186191
});
187192

packages/core/src/audio/AudioForRendering.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ const AudioForRenderingRefForwardingFunction: React.ForwardRefRenderFunction<
5151
volume: volumeProp,
5252
playbackRate,
5353
allowAmplificationDuringRender,
54+
onDuration,
5455
...nativeProps
5556
} = props;
5657

@@ -112,7 +113,7 @@ const AudioForRenderingRefForwardingFunction: React.ForwardRefRenderFunction<
112113
allowAmplificationDuringRender,
113114
]);
114115

115-
const {src, onDuration} = props;
116+
const {src} = props;
116117

117118
// If audio source switches, make new handle
118119
if (environment === 'rendering') {

packages/core/src/config.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,14 @@ type FlatConfig = ObjectConfig['Bundling'] &
3333
ObjectConfig['Preview'] &
3434
ObjectConfig['Puppeteer'] &
3535
ObjectConfig['Output'] &
36-
ObjectConfig['Rendering'];
36+
ObjectConfig['Rendering'] & {
37+
/**
38+
* Set the audio codec to use for the output video.
39+
* See the Encoding guide in the docs for defaults and available options.
40+
*/
41+
setAudioCodec: (codec: 'pcm-16' | 'aac' | 'mp3' | 'opus') => void;
42+
};
43+
3744
// Legacy config format: New options to not need to be added here.
3845
type ObjectConfig = {
3946
/**

0 commit comments

Comments
 (0)