Skip to content

Commit a54df3b

Browse files
authored
Merge pull request #5316 from remotion-dev/dont-copy-if-videocodec-is-explicit
2 parents 81d7719 + 938c5dc commit a54df3b

File tree

8 files changed

+108
-0
lines changed

8 files changed

+108
-0
lines changed

packages/convert/app/components/get-supported-configs.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ export const getSupportedConfigs = async ({
113113
rotationToApply: userRotation,
114114
inputContainer,
115115
resizeOperation,
116+
outputVideoCodec: null,
116117
});
117118
if (canCopy && prioritizeCopyOverReencode) {
118119
options.push({
@@ -161,6 +162,7 @@ export const getSupportedConfigs = async ({
161162
inputCodec: track.codecEnum,
162163
outputContainer: container,
163164
inputContainer,
165+
outputAudioCodec: null,
164166
});
165167

166168
if (canCopy) {

packages/docs/docs/webcodecs/can-copy-audio-track.mdx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ for (const track of audioTracks) {
3737
inputCodec: track.codecEnum,
3838
outputContainer: 'webm',
3939
inputContainer: container,
40+
outputAudioCodec: null
4041
}); // bool
4142
}
4243
```
@@ -86,6 +87,12 @@ _string_ <TsType type="ConvertMediaContainer" source="@remotion/webcodecs" />
8687

8788
The container format of the output media.
8889

90+
### `outputAudioCodec`
91+
92+
_string | null_ <TsType type="ConvertMediaAudioCodec" source="@remotion/webcodecs" />
93+
94+
The desired audio codec of the output media. If `null`, it means you don't care about the audio codec as long as it can be copied.
95+
8996
## Return value
9097

9198
Returns a `boolean`.

packages/docs/docs/webcodecs/can-copy-video-track.mdx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ for (const track of videoTracks) {
4242
inputContainer: container,
4343
rotationToApply: 0,
4444
resizeOperation: null,
45+
outputVideoCodec: null
4546
}); // boolean
4647
}
4748
```
@@ -105,6 +106,12 @@ _string_ <TsType type="ResizeOperation" source="@remotion/webcodecs" />
105106

106107
The [resize operation](/docs/webcodecs/resize-a-video) to apply to the video track.
107108

109+
### `outputVideoCodec`
110+
111+
_string | null_ <TsType type="ConvertMediaVideoCodec" source="@remotion/webcodecs" />
112+
113+
The desired video codec of the output media. If `null`, it means you don't care about the video codec as long as it can be copied.
114+
108115
## Rotation behavior
109116

110117
Any `rotationToApply` is in addition to an auto-rotation that is applied by default to fix the orientation of the video track.

packages/webcodecs/src/can-copy-audio-track.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,32 @@ import type {
22
MediaParserAudioCodec,
33
MediaParserContainer,
44
} from '@remotion/media-parser';
5+
import type {ConvertMediaAudioCodec} from './get-available-audio-codecs';
56
import type {ConvertMediaContainer} from './get-available-containers';
7+
import {isSameAudioCodec} from './is-different-video-codec';
68

79
export const canCopyAudioTrack = ({
810
inputCodec,
911
outputContainer,
1012
inputContainer,
13+
outputAudioCodec,
1114
}: {
1215
inputCodec: MediaParserAudioCodec;
1316
outputContainer: ConvertMediaContainer;
1417
inputContainer: MediaParserContainer;
18+
outputAudioCodec: ConvertMediaAudioCodec | null;
1519
}) => {
20+
if (outputAudioCodec) {
21+
if (
22+
!isSameAudioCodec({
23+
inputAudioCodec: inputCodec,
24+
outputCodec: outputAudioCodec,
25+
})
26+
) {
27+
return false;
28+
}
29+
}
30+
1631
if (outputContainer === 'webm') {
1732
return inputCodec === 'opus';
1833
}

packages/webcodecs/src/can-copy-video-track.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import type {
33
MediaParserVideoTrack,
44
} from '@remotion/media-parser';
55
import type {ConvertMediaContainer} from './get-available-containers';
6+
import type {ConvertMediaVideoCodec} from './get-available-video-codecs';
7+
import {isSameVideoCodec} from './is-different-video-codec';
68
import type {ResizeOperation} from './resizing/mode';
79
import {normalizeVideoRotation} from './rotate-and-resize-video-frame';
810
import {calculateNewDimensionsFromRotateAndScale} from './rotation';
@@ -13,11 +15,13 @@ export const canCopyVideoTrack = ({
1315
inputContainer,
1416
resizeOperation,
1517
inputTrack,
18+
outputVideoCodec,
1619
}: {
1720
inputContainer: MediaParserContainer;
1821
inputTrack: MediaParserVideoTrack;
1922
rotationToApply: number;
2023
outputContainer: ConvertMediaContainer;
24+
outputVideoCodec: ConvertMediaVideoCodec | null;
2125
resizeOperation: ResizeOperation | null;
2226
}) => {
2327
if (
@@ -27,6 +31,17 @@ export const canCopyVideoTrack = ({
2731
return false;
2832
}
2933

34+
if (outputVideoCodec) {
35+
if (
36+
!isSameVideoCodec({
37+
inputVideoCodec: inputTrack.codecEnum,
38+
outputCodec: outputVideoCodec,
39+
})
40+
) {
41+
return false;
42+
}
43+
}
44+
3045
const newDimensions = calculateNewDimensionsFromRotateAndScale({
3146
height: inputTrack.height,
3247
resizeOperation,
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import type {
2+
MediaParserAudioCodec,
3+
MediaParserVideoCodec,
4+
} from '@remotion/media-parser';
5+
import type {ConvertMediaAudioCodec} from './get-available-audio-codecs';
6+
import type {ConvertMediaVideoCodec} from './get-available-video-codecs';
7+
8+
export const isSameVideoCodec = ({
9+
inputVideoCodec,
10+
outputCodec,
11+
}: {
12+
inputVideoCodec: MediaParserVideoCodec;
13+
outputCodec: ConvertMediaVideoCodec;
14+
}) => {
15+
if (outputCodec === 'h264') {
16+
return inputVideoCodec === 'h264';
17+
}
18+
19+
if (outputCodec === 'h265') {
20+
return inputVideoCodec === 'h265';
21+
}
22+
23+
if (outputCodec === 'vp8') {
24+
return inputVideoCodec === 'vp8';
25+
}
26+
27+
if (outputCodec === 'vp9') {
28+
return inputVideoCodec === 'vp9';
29+
}
30+
31+
throw new Error(`Unsupported output codec: ${outputCodec satisfies never}`);
32+
};
33+
34+
export const isSameAudioCodec = ({
35+
inputAudioCodec,
36+
outputCodec,
37+
}: {
38+
inputAudioCodec: MediaParserAudioCodec;
39+
outputCodec: ConvertMediaAudioCodec;
40+
}) => {
41+
if (outputCodec === 'aac') {
42+
return inputAudioCodec === 'aac';
43+
}
44+
45+
if (outputCodec === 'opus') {
46+
return inputAudioCodec === 'opus';
47+
}
48+
49+
if (outputCodec === 'wav') {
50+
return (
51+
inputAudioCodec === 'pcm-f32' ||
52+
inputAudioCodec === 'pcm-s16' ||
53+
inputAudioCodec === 'pcm-s24' ||
54+
inputAudioCodec === 'pcm-s32' ||
55+
inputAudioCodec === 'pcm-u8'
56+
);
57+
}
58+
59+
throw new Error(`Unsupported output codec: ${outputCodec satisfies never}`);
60+
};

packages/webcodecs/src/on-audio-track.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ export const makeAudioTrackHandler =
4545
inputCodec: track.codecEnum,
4646
outputContainer,
4747
inputContainer,
48+
outputAudioCodec: audioCodec,
4849
});
4950

5051
const audioOperation = await (onAudioTrack ?? defaultOnAudioTrackHandler)({

packages/webcodecs/src/on-video-track.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ export const makeVideoTrackHandler =
5858
rotationToApply: rotate,
5959
inputTrack: track,
6060
resizeOperation,
61+
outputVideoCodec: defaultVideoCodec,
6162
});
6263

6364
const videoOperation = await (onVideoTrack ?? defaultOnVideoTrackHandler)({

0 commit comments

Comments
 (0)