@remotion/webcodecs 4.0.240 → 4.0.242
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/audio-decoder.js +0 -5
- package/dist/can-copy-video-track.d.ts +5 -4
- package/dist/can-copy-video-track.js +19 -6
- package/dist/convert-encoded-chunk.js +2 -0
- package/dist/convert-media.d.ts +4 -1
- package/dist/convert-media.js +12 -1
- package/dist/default-on-video-track-handler.js +3 -2
- package/dist/esm/index.mjs +318 -43
- package/dist/index.d.ts +11 -1
- package/dist/index.js +5 -3
- package/dist/io-manager/io-synchronizer.js +4 -4
- package/dist/io-manager/make-timeout-promise.d.ts +1 -1
- package/dist/io-manager/make-timeout-promise.js +1 -1
- package/dist/on-frame.d.ts +3 -1
- package/dist/on-frame.js +5 -3
- package/dist/on-video-track-handler.d.ts +3 -0
- package/dist/on-video-track.d.ts +3 -1
- package/dist/on-video-track.js +10 -5
- package/dist/resizing/calculate-new-size.d.ts +8 -0
- package/dist/resizing/calculate-new-size.js +89 -0
- package/dist/resizing/mode.d.ts +24 -0
- package/dist/resizing/mode.js +2 -0
- package/dist/resizing/resizing.d.ts +13 -0
- package/dist/resizing/resizing.js +2 -0
- package/dist/resizing.d.ts +13 -0
- package/dist/resizing.js +2 -0
- package/dist/rotate-and-resize-video-frame.d.ts +9 -0
- package/dist/rotate-and-resize-video-frame.js +67 -0
- package/dist/rotate-video-frame.d.ts +5 -1
- package/dist/rotate-video-frame.js +9 -4
- package/dist/rotation.d.ts +11 -3
- package/dist/rotation.js +24 -5
- package/dist/scaling.d.ts +13 -0
- package/dist/scaling.js +2 -0
- package/dist/send-telemetry-event.d.ts +4 -0
- package/dist/send-telemetry-event.js +22 -0
- package/package.json +5 -4
package/dist/index.d.ts
CHANGED
|
@@ -14,12 +14,22 @@ export { getDefaultAudioCodec } from './get-default-audio-codec';
|
|
|
14
14
|
export { getDefaultVideoCodec } from './get-default-video-codec';
|
|
15
15
|
export { AudioOperation, ConvertMediaOnAudioTrackHandler, } from './on-audio-track-handler';
|
|
16
16
|
export { ConvertMediaOnVideoTrackHandler, VideoOperation, } from './on-video-track-handler';
|
|
17
|
+
export type { ResizeOperation } from './resizing/mode';
|
|
17
18
|
export { createVideoDecoder, WebCodecsVideoDecoder } from './video-decoder';
|
|
18
19
|
export { createVideoEncoder, WebCodecsVideoEncoder } from './video-encoder';
|
|
19
20
|
export declare const WebCodecsInternals: {
|
|
20
|
-
|
|
21
|
+
rotateAndResizeVideoFrame: ({ frame, rotation, videoCodec, resizeOperation, }: {
|
|
21
22
|
frame: VideoFrame;
|
|
22
23
|
rotation: number;
|
|
24
|
+
videoCodec: import("./get-available-video-codecs").ConvertMediaVideoCodec;
|
|
25
|
+
resizeOperation: import("./resizing/mode").ResizeOperation | null;
|
|
23
26
|
}) => VideoFrame;
|
|
24
27
|
normalizeVideoRotation: (rotation: number) => number;
|
|
28
|
+
calculateNewDimensionsFromDimensions: ({ width, height, rotation, resizeOperation, videoCodec, }: {
|
|
29
|
+
width: number;
|
|
30
|
+
height: number;
|
|
31
|
+
rotation: number;
|
|
32
|
+
resizeOperation: import("./resizing/mode").ResizeOperation | null;
|
|
33
|
+
videoCodec: import("./get-available-video-codecs").ConvertMediaVideoCodec | import("@remotion/media-parser").MediaParserVideoCodec;
|
|
34
|
+
}) => import("./resizing/mode").Dimensions;
|
|
25
35
|
};
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.WebCodecsInternals = exports.createVideoEncoder = exports.createVideoDecoder = exports.getDefaultVideoCodec = exports.getDefaultAudioCodec = exports.getAvailableVideoCodecs = exports.getAvailableContainers = exports.getAvailableAudioCodecs = exports.defaultOnVideoTrackHandler = exports.defaultOnAudioTrackHandler = exports.convertMedia = exports.canReencodeVideoTrack = exports.canReencodeAudioTrack = exports.canCopyVideoTrack = exports.canCopyAudioTrack = exports.createAudioEncoder = exports.createAudioDecoder = void 0;
|
|
4
|
-
const
|
|
4
|
+
const rotate_and_resize_video_frame_1 = require("./rotate-and-resize-video-frame");
|
|
5
|
+
const rotation_1 = require("./rotation");
|
|
5
6
|
const set_remotion_imported_1 = require("./set-remotion-imported");
|
|
6
7
|
var audio_decoder_1 = require("./audio-decoder");
|
|
7
8
|
Object.defineProperty(exports, "createAudioDecoder", { enumerable: true, get: function () { return audio_decoder_1.createAudioDecoder; } });
|
|
@@ -36,7 +37,8 @@ Object.defineProperty(exports, "createVideoDecoder", { enumerable: true, get: fu
|
|
|
36
37
|
var video_encoder_1 = require("./video-encoder");
|
|
37
38
|
Object.defineProperty(exports, "createVideoEncoder", { enumerable: true, get: function () { return video_encoder_1.createVideoEncoder; } });
|
|
38
39
|
exports.WebCodecsInternals = {
|
|
39
|
-
|
|
40
|
-
normalizeVideoRotation:
|
|
40
|
+
rotateAndResizeVideoFrame: rotate_and_resize_video_frame_1.rotateAndResizeVideoFrame,
|
|
41
|
+
normalizeVideoRotation: rotate_and_resize_video_frame_1.normalizeVideoRotation,
|
|
42
|
+
calculateNewDimensionsFromDimensions: rotation_1.calculateNewDimensionsFromRotateAndScale,
|
|
41
43
|
};
|
|
42
44
|
(0, set_remotion_imported_1.setRemotionImported)();
|
|
@@ -69,14 +69,14 @@ const makeIoSynchronizer = ({ logLevel, label, progress, }) => {
|
|
|
69
69
|
return promise;
|
|
70
70
|
};
|
|
71
71
|
const waitFor = async ({ unprocessed, unemitted, minimumProgress, signal, }) => {
|
|
72
|
-
const { timeoutPromise, clear } = (0, make_timeout_promise_1.makeTimeoutPromise)([
|
|
73
|
-
`Waited too long for ${label}:`,
|
|
72
|
+
const { timeoutPromise, clear } = (0, make_timeout_promise_1.makeTimeoutPromise)(() => [
|
|
73
|
+
`Waited too long for ${label} to finish:`,
|
|
74
74
|
`${getUnemittedItems()} unemitted items`,
|
|
75
|
-
`${getUnprocessed()} unprocessed items`,
|
|
76
|
-
`minimum progress ${minimumProgress}`,
|
|
75
|
+
`${getUnprocessed()} unprocessed items: ${JSON.stringify(_unprocessed)}`,
|
|
77
76
|
`smallest progress: ${progress.getSmallestProgress()}`,
|
|
78
77
|
`inputs: ${JSON.stringify(inputs)}`,
|
|
79
78
|
`last output: ${lastOutput}`,
|
|
79
|
+
`wanted: ${unemitted} unemitted items, ${unprocessed} unprocessed items, minimum progress ${minimumProgress}`,
|
|
80
80
|
].join('\n'), 10000);
|
|
81
81
|
signal.addEventListener('abort', clear);
|
|
82
82
|
await Promise.race([
|
|
@@ -5,7 +5,7 @@ const media_parser_1 = require("@remotion/media-parser");
|
|
|
5
5
|
const makeTimeoutPromise = (label, ms) => {
|
|
6
6
|
const { promise, reject, resolve } = media_parser_1.MediaParserInternals.withResolvers();
|
|
7
7
|
const timeout = setTimeout(() => {
|
|
8
|
-
reject(new Error(`${label} (timed out after ${ms}ms)`));
|
|
8
|
+
reject(new Error(`${label()} (timed out after ${ms}ms)`));
|
|
9
9
|
}, ms);
|
|
10
10
|
return {
|
|
11
11
|
timeoutPromise: promise,
|
package/dist/on-frame.d.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import type { VideoTrack } from '@remotion/media-parser';
|
|
2
2
|
import type { ConvertMediaOnVideoFrame } from './convert-media';
|
|
3
3
|
import type { ConvertMediaVideoCodec } from './get-available-video-codecs';
|
|
4
|
+
import type { ResizeOperation } from './resizing/mode';
|
|
4
5
|
import type { WebCodecsVideoEncoder } from './video-encoder';
|
|
5
|
-
export declare const onFrame: ({ frame: unrotatedFrame, onVideoFrame, videoEncoder, track, outputCodec, rotation, }: {
|
|
6
|
+
export declare const onFrame: ({ frame: unrotatedFrame, onVideoFrame, videoEncoder, track, outputCodec, rotation, resizeOperation, }: {
|
|
6
7
|
frame: VideoFrame;
|
|
7
8
|
onVideoFrame: ConvertMediaOnVideoFrame | null;
|
|
8
9
|
videoEncoder: WebCodecsVideoEncoder;
|
|
9
10
|
track: VideoTrack;
|
|
10
11
|
outputCodec: ConvertMediaVideoCodec;
|
|
11
12
|
rotation: number;
|
|
13
|
+
resizeOperation: ResizeOperation | null;
|
|
12
14
|
}) => Promise<void>;
|
package/dist/on-frame.js
CHANGED
|
@@ -3,12 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.onFrame = void 0;
|
|
4
4
|
const browser_quirks_1 = require("./browser-quirks");
|
|
5
5
|
const convert_to_correct_videoframe_1 = require("./convert-to-correct-videoframe");
|
|
6
|
-
const
|
|
7
|
-
const onFrame = async ({ frame: unrotatedFrame, onVideoFrame, videoEncoder, track, outputCodec, rotation, }) => {
|
|
6
|
+
const rotate_and_resize_video_frame_1 = require("./rotate-and-resize-video-frame");
|
|
7
|
+
const onFrame = async ({ frame: unrotatedFrame, onVideoFrame, videoEncoder, track, outputCodec, rotation, resizeOperation, }) => {
|
|
8
8
|
var _a, _b;
|
|
9
|
-
const rotated = (0,
|
|
9
|
+
const rotated = (0, rotate_and_resize_video_frame_1.rotateAndResizeVideoFrame)({
|
|
10
10
|
rotation,
|
|
11
11
|
frame: unrotatedFrame,
|
|
12
|
+
resizeOperation,
|
|
13
|
+
videoCodec: outputCodec,
|
|
12
14
|
});
|
|
13
15
|
if (unrotatedFrame !== rotated) {
|
|
14
16
|
unrotatedFrame.close();
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import type { LogLevel, ParseMediaContainer, VideoTrack } from '@remotion/media-parser';
|
|
2
2
|
import type { ConvertMediaContainer } from './get-available-containers';
|
|
3
3
|
import type { ConvertMediaVideoCodec } from './get-available-video-codecs';
|
|
4
|
+
import type { ResizeOperation } from './resizing/mode';
|
|
4
5
|
export type VideoOperation = {
|
|
5
6
|
type: 'reencode';
|
|
6
7
|
videoCodec: ConvertMediaVideoCodec;
|
|
7
8
|
rotate?: number;
|
|
9
|
+
resize?: ResizeOperation | null;
|
|
8
10
|
} | {
|
|
9
11
|
type: 'copy';
|
|
10
12
|
} | {
|
|
@@ -18,6 +20,7 @@ export type ConvertMediaOnVideoTrackHandler = (options: {
|
|
|
18
20
|
logLevel: LogLevel;
|
|
19
21
|
outputContainer: ConvertMediaContainer;
|
|
20
22
|
rotate: number;
|
|
23
|
+
resizeOperation: ResizeOperation | null;
|
|
21
24
|
inputContainer: ParseMediaContainer;
|
|
22
25
|
canCopyTrack: boolean;
|
|
23
26
|
}) => VideoOperation | Promise<VideoOperation>;
|
package/dist/on-video-track.d.ts
CHANGED
|
@@ -4,8 +4,9 @@ import Error from './error-cause';
|
|
|
4
4
|
import type { ConvertMediaContainer } from './get-available-containers';
|
|
5
5
|
import type { ConvertMediaVideoCodec } from './get-available-video-codecs';
|
|
6
6
|
import type { ConvertMediaOnVideoTrackHandler } from './on-video-track-handler';
|
|
7
|
+
import type { ResizeOperation } from './resizing/mode';
|
|
7
8
|
import type { ConvertMediaProgressFn } from './throttled-state-update';
|
|
8
|
-
export declare const makeVideoTrackHandler: ({ state, onVideoFrame, onMediaStateUpdate, abortConversion, controller, defaultVideoCodec, onVideoTrack, logLevel, outputContainer, rotate, progress, }: {
|
|
9
|
+
export declare const makeVideoTrackHandler: ({ state, onVideoFrame, onMediaStateUpdate, abortConversion, controller, defaultVideoCodec, onVideoTrack, logLevel, outputContainer, rotate, progress, resizeOperation, }: {
|
|
9
10
|
state: MediaFn;
|
|
10
11
|
onVideoFrame: null | ConvertMediaOnVideoFrame;
|
|
11
12
|
onMediaStateUpdate: null | ConvertMediaProgressFn;
|
|
@@ -17,4 +18,5 @@ export declare const makeVideoTrackHandler: ({ state, onVideoFrame, onMediaState
|
|
|
17
18
|
outputContainer: ConvertMediaContainer;
|
|
18
19
|
rotate: number;
|
|
19
20
|
progress: ProgressTracker;
|
|
21
|
+
resizeOperation: ResizeOperation | null;
|
|
20
22
|
}) => OnVideoTrack;
|
package/dist/on-video-track.js
CHANGED
|
@@ -17,17 +17,17 @@ const video_decoder_1 = require("./video-decoder");
|
|
|
17
17
|
const video_decoder_config_1 = require("./video-decoder-config");
|
|
18
18
|
const video_encoder_1 = require("./video-encoder");
|
|
19
19
|
const video_encoder_config_1 = require("./video-encoder-config");
|
|
20
|
-
const makeVideoTrackHandler = ({ state, onVideoFrame, onMediaStateUpdate, abortConversion, controller, defaultVideoCodec, onVideoTrack, logLevel, outputContainer, rotate, progress, }) => async ({ track, container: inputContainer }) => {
|
|
21
|
-
var _a;
|
|
20
|
+
const makeVideoTrackHandler = ({ state, onVideoFrame, onMediaStateUpdate, abortConversion, controller, defaultVideoCodec, onVideoTrack, logLevel, outputContainer, rotate, progress, resizeOperation, }) => async ({ track, container: inputContainer }) => {
|
|
21
|
+
var _a, _b;
|
|
22
22
|
if (controller.signal.aborted) {
|
|
23
23
|
throw new error_cause_1.default('Aborted');
|
|
24
24
|
}
|
|
25
25
|
const canCopyTrack = (0, can_copy_video_track_1.canCopyVideoTrack)({
|
|
26
|
-
inputCodec: track.codecWithoutConfig,
|
|
27
26
|
inputContainer,
|
|
28
|
-
inputRotation: track.rotation,
|
|
29
27
|
outputContainer,
|
|
30
28
|
rotationToApply: rotate,
|
|
29
|
+
inputTrack: track,
|
|
30
|
+
resizeOperation,
|
|
31
31
|
});
|
|
32
32
|
const videoOperation = await (onVideoTrack !== null && onVideoTrack !== void 0 ? onVideoTrack : default_on_video_track_handler_1.defaultOnVideoTrackHandler)({
|
|
33
33
|
track,
|
|
@@ -37,6 +37,7 @@ const makeVideoTrackHandler = ({ state, onVideoFrame, onMediaStateUpdate, abortC
|
|
|
37
37
|
rotate,
|
|
38
38
|
inputContainer,
|
|
39
39
|
canCopyTrack,
|
|
40
|
+
resizeOperation,
|
|
40
41
|
});
|
|
41
42
|
if (videoOperation.type === 'drop') {
|
|
42
43
|
return null;
|
|
@@ -74,10 +75,12 @@ const makeVideoTrackHandler = ({ state, onVideoFrame, onMediaStateUpdate, abortC
|
|
|
74
75
|
throw new error_cause_1.default(`Video track with ID ${track.trackId} could not be resolved with a valid operation. Received ${JSON.stringify(videoOperation)}, but must be either "copy", "reencode", "drop" or "fail"`);
|
|
75
76
|
}
|
|
76
77
|
const rotation = ((_a = videoOperation.rotate) !== null && _a !== void 0 ? _a : rotate) - track.rotation;
|
|
77
|
-
const { height: newHeight, width: newWidth } = (0, rotation_1.
|
|
78
|
+
const { height: newHeight, width: newWidth } = (0, rotation_1.calculateNewDimensionsFromRotateAndScale)({
|
|
78
79
|
width: track.codedWidth,
|
|
79
80
|
height: track.codedHeight,
|
|
80
81
|
rotation,
|
|
82
|
+
videoCodec: videoOperation.videoCodec,
|
|
83
|
+
resizeOperation: (_b = videoOperation.resize) !== null && _b !== void 0 ? _b : null,
|
|
81
84
|
});
|
|
82
85
|
const videoEncoderConfig = await (0, video_encoder_config_1.getVideoEncoderConfig)({
|
|
83
86
|
codec: videoOperation.videoCodec,
|
|
@@ -134,6 +137,7 @@ const makeVideoTrackHandler = ({ state, onVideoFrame, onMediaStateUpdate, abortC
|
|
|
134
137
|
const videoDecoder = (0, video_decoder_1.createVideoDecoder)({
|
|
135
138
|
config: videoDecoderConfig,
|
|
136
139
|
onFrame: async (frame) => {
|
|
140
|
+
var _a;
|
|
137
141
|
await (0, on_frame_1.onFrame)({
|
|
138
142
|
frame,
|
|
139
143
|
track,
|
|
@@ -141,6 +145,7 @@ const makeVideoTrackHandler = ({ state, onVideoFrame, onMediaStateUpdate, abortC
|
|
|
141
145
|
onVideoFrame,
|
|
142
146
|
outputCodec: videoOperation.videoCodec,
|
|
143
147
|
rotation,
|
|
148
|
+
resizeOperation: (_a = videoOperation.resize) !== null && _a !== void 0 ? _a : null,
|
|
144
149
|
});
|
|
145
150
|
},
|
|
146
151
|
onError: (err) => {
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { MediaParserVideoCodec } from '@remotion/media-parser';
|
|
2
|
+
import type { ConvertMediaVideoCodec } from '../get-available-video-codecs';
|
|
3
|
+
import type { Dimensions, ResizeOperation } from './mode';
|
|
4
|
+
export declare const calculateNewSizeAfterResizing: ({ dimensions, resizeOperation, videoCodec, }: {
|
|
5
|
+
dimensions: Dimensions;
|
|
6
|
+
resizeOperation: ResizeOperation | null;
|
|
7
|
+
videoCodec: ConvertMediaVideoCodec | MediaParserVideoCodec;
|
|
8
|
+
}) => Dimensions;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.calculateNewSizeAfterResizing = void 0;
|
|
4
|
+
const ensureMultipleOfTwo = ({ dimensions, needsToBeMultipleOfTwo, }) => {
|
|
5
|
+
if (!needsToBeMultipleOfTwo) {
|
|
6
|
+
return dimensions;
|
|
7
|
+
}
|
|
8
|
+
return {
|
|
9
|
+
width: Math.floor(dimensions.width / 2) * 2,
|
|
10
|
+
height: Math.floor(dimensions.height / 2) * 2,
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
const calculateNewSizeAfterResizing = ({ dimensions, resizeOperation, videoCodec, }) => {
|
|
14
|
+
const needsToBeMultipleOfTwo = videoCodec === 'h264';
|
|
15
|
+
if (resizeOperation === null) {
|
|
16
|
+
return ensureMultipleOfTwo({
|
|
17
|
+
dimensions,
|
|
18
|
+
needsToBeMultipleOfTwo,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
if (resizeOperation.mode === 'width') {
|
|
22
|
+
return ensureMultipleOfTwo({
|
|
23
|
+
dimensions: {
|
|
24
|
+
width: resizeOperation.width,
|
|
25
|
+
height: Math.round((resizeOperation.width / dimensions.width) * dimensions.height),
|
|
26
|
+
},
|
|
27
|
+
needsToBeMultipleOfTwo,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
if (resizeOperation.mode === 'height') {
|
|
31
|
+
return ensureMultipleOfTwo({
|
|
32
|
+
dimensions: {
|
|
33
|
+
width: Math.round((resizeOperation.height / dimensions.height) * dimensions.width),
|
|
34
|
+
height: resizeOperation.height,
|
|
35
|
+
},
|
|
36
|
+
needsToBeMultipleOfTwo,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
if (resizeOperation.mode === 'max-height') {
|
|
40
|
+
const height = Math.min(dimensions.height, resizeOperation.maxHeight);
|
|
41
|
+
return ensureMultipleOfTwo({
|
|
42
|
+
dimensions: {
|
|
43
|
+
width: Math.round((height / dimensions.height) * dimensions.width),
|
|
44
|
+
height,
|
|
45
|
+
},
|
|
46
|
+
needsToBeMultipleOfTwo,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
if (resizeOperation.mode === 'max-width') {
|
|
50
|
+
const width = Math.min(dimensions.width, resizeOperation.maxWidth);
|
|
51
|
+
return ensureMultipleOfTwo({
|
|
52
|
+
dimensions: {
|
|
53
|
+
width,
|
|
54
|
+
height: Math.round((width / dimensions.width) * dimensions.height),
|
|
55
|
+
},
|
|
56
|
+
needsToBeMultipleOfTwo,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
if (resizeOperation.mode === 'max-height-width') {
|
|
60
|
+
const height = Math.min(dimensions.height, resizeOperation.maxHeight);
|
|
61
|
+
const width = Math.min(dimensions.width, resizeOperation.maxWidth);
|
|
62
|
+
const scale = Math.min(width / dimensions.width, height / dimensions.height);
|
|
63
|
+
const actualWidth = Math.round(dimensions.width * scale);
|
|
64
|
+
const actualHeight = Math.round(dimensions.height * scale);
|
|
65
|
+
return ensureMultipleOfTwo({
|
|
66
|
+
dimensions: {
|
|
67
|
+
height: actualHeight,
|
|
68
|
+
width: actualWidth,
|
|
69
|
+
},
|
|
70
|
+
needsToBeMultipleOfTwo,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
if (resizeOperation.mode === 'scale') {
|
|
74
|
+
if (resizeOperation.scale <= 0) {
|
|
75
|
+
throw new Error('Scale must be greater than 0');
|
|
76
|
+
}
|
|
77
|
+
const width = Math.round(dimensions.width * resizeOperation.scale);
|
|
78
|
+
const height = Math.round(dimensions.height * resizeOperation.scale);
|
|
79
|
+
return ensureMultipleOfTwo({
|
|
80
|
+
dimensions: {
|
|
81
|
+
width,
|
|
82
|
+
height,
|
|
83
|
+
},
|
|
84
|
+
needsToBeMultipleOfTwo,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
throw new Error('Invalid resizing mode ' + resizeOperation);
|
|
88
|
+
};
|
|
89
|
+
exports.calculateNewSizeAfterResizing = calculateNewSizeAfterResizing;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export type Dimensions = {
|
|
2
|
+
width: number;
|
|
3
|
+
height: number;
|
|
4
|
+
};
|
|
5
|
+
export type ResizeOperation = {
|
|
6
|
+
mode: 'width';
|
|
7
|
+
width: number;
|
|
8
|
+
} | {
|
|
9
|
+
mode: 'height';
|
|
10
|
+
height: number;
|
|
11
|
+
} | {
|
|
12
|
+
mode: 'max-height';
|
|
13
|
+
maxHeight: number;
|
|
14
|
+
} | {
|
|
15
|
+
mode: 'max-width';
|
|
16
|
+
maxWidth: number;
|
|
17
|
+
} | {
|
|
18
|
+
mode: 'max-height-width';
|
|
19
|
+
maxHeight: number;
|
|
20
|
+
maxWidth: number;
|
|
21
|
+
} | {
|
|
22
|
+
mode: 'scale';
|
|
23
|
+
scale: number;
|
|
24
|
+
};
|
package/dist/resizing.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ConvertMediaVideoCodec } from './get-available-video-codecs';
|
|
2
|
+
import type { ResizeOperation } from './resizing/mode';
|
|
3
|
+
export declare const normalizeVideoRotation: (rotation: number) => number;
|
|
4
|
+
export declare const rotateAndResizeVideoFrame: ({ frame, rotation, videoCodec, resizeOperation, }: {
|
|
5
|
+
frame: VideoFrame;
|
|
6
|
+
rotation: number;
|
|
7
|
+
videoCodec: ConvertMediaVideoCodec;
|
|
8
|
+
resizeOperation: ResizeOperation | null;
|
|
9
|
+
}) => VideoFrame;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.rotateAndResizeVideoFrame = exports.normalizeVideoRotation = void 0;
|
|
4
|
+
const rotation_1 = require("./rotation");
|
|
5
|
+
const normalizeVideoRotation = (rotation) => {
|
|
6
|
+
return ((rotation % 360) + 360) % 360;
|
|
7
|
+
};
|
|
8
|
+
exports.normalizeVideoRotation = normalizeVideoRotation;
|
|
9
|
+
const rotateAndResizeVideoFrame = ({ frame, rotation, videoCodec, resizeOperation, }) => {
|
|
10
|
+
var _a;
|
|
11
|
+
const normalized = ((rotation % 360) + 360) % 360;
|
|
12
|
+
// No resize, no rotation
|
|
13
|
+
if (normalized === 0 && resizeOperation === null) {
|
|
14
|
+
return frame;
|
|
15
|
+
}
|
|
16
|
+
if (normalized % 90 !== 0) {
|
|
17
|
+
throw new Error('Only 90 degree rotations are supported');
|
|
18
|
+
}
|
|
19
|
+
const { height, width } = (0, rotation_1.calculateNewDimensionsFromRotateAndScale)({
|
|
20
|
+
height: frame.displayHeight,
|
|
21
|
+
width: frame.displayWidth,
|
|
22
|
+
rotation,
|
|
23
|
+
videoCodec,
|
|
24
|
+
resizeOperation,
|
|
25
|
+
});
|
|
26
|
+
// No rotation, and resize turned out to be same dimensions
|
|
27
|
+
if (normalized === 0 &&
|
|
28
|
+
height === frame.displayHeight &&
|
|
29
|
+
width === frame.displayWidth) {
|
|
30
|
+
return frame;
|
|
31
|
+
}
|
|
32
|
+
const canvas = new OffscreenCanvas(width, height);
|
|
33
|
+
const ctx = canvas.getContext('2d');
|
|
34
|
+
if (!ctx) {
|
|
35
|
+
throw new Error('Could not get 2d context');
|
|
36
|
+
}
|
|
37
|
+
canvas.width = width;
|
|
38
|
+
canvas.height = height;
|
|
39
|
+
if (normalized === 90) {
|
|
40
|
+
ctx.translate(width, 0);
|
|
41
|
+
}
|
|
42
|
+
else if (normalized === 180) {
|
|
43
|
+
ctx.translate(width, height);
|
|
44
|
+
}
|
|
45
|
+
else if (normalized === 270) {
|
|
46
|
+
ctx.translate(0, height);
|
|
47
|
+
}
|
|
48
|
+
if (normalized !== 0) {
|
|
49
|
+
ctx.rotate(normalized * (Math.PI / 180));
|
|
50
|
+
}
|
|
51
|
+
if (frame.displayHeight !== height || frame.displayWidth !== width) {
|
|
52
|
+
const dimensionsAfterRotate = (0, rotation_1.calculateNewDimensionsFromRotate)({
|
|
53
|
+
height: frame.displayHeight,
|
|
54
|
+
rotation,
|
|
55
|
+
width: frame.displayWidth,
|
|
56
|
+
});
|
|
57
|
+
ctx.scale(width / dimensionsAfterRotate.width, height / dimensionsAfterRotate.height);
|
|
58
|
+
}
|
|
59
|
+
ctx.drawImage(frame, 0, 0);
|
|
60
|
+
return new VideoFrame(canvas, {
|
|
61
|
+
displayHeight: height,
|
|
62
|
+
displayWidth: width,
|
|
63
|
+
duration: (_a = frame.duration) !== null && _a !== void 0 ? _a : undefined,
|
|
64
|
+
timestamp: frame.timestamp,
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
exports.rotateAndResizeVideoFrame = rotateAndResizeVideoFrame;
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
import type { ConvertMediaVideoCodec } from './get-available-video-codecs';
|
|
2
|
+
import type { ResizingMode } from './resizing/mode';
|
|
1
3
|
export declare const normalizeVideoRotation: (rotation: number) => number;
|
|
2
|
-
export declare const
|
|
4
|
+
export declare const rotateAndResizeVideoFrame: ({ frame, rotation, videoCodec, resizingMode, }: {
|
|
3
5
|
frame: VideoFrame;
|
|
4
6
|
rotation: number;
|
|
7
|
+
videoCodec: ConvertMediaVideoCodec;
|
|
8
|
+
resizingMode: ResizingMode | null;
|
|
5
9
|
}) => VideoFrame;
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.rotateAndResizeVideoFrame = exports.normalizeVideoRotation = void 0;
|
|
4
4
|
const rotation_1 = require("./rotation");
|
|
5
5
|
const normalizeVideoRotation = (rotation) => {
|
|
6
6
|
return ((rotation % 360) + 360) % 360;
|
|
7
7
|
};
|
|
8
8
|
exports.normalizeVideoRotation = normalizeVideoRotation;
|
|
9
|
-
const
|
|
9
|
+
const rotateAndResizeVideoFrame = ({ frame, rotation, videoCodec, resizingMode, }) => {
|
|
10
10
|
var _a;
|
|
11
11
|
const normalized = ((rotation % 360) + 360) % 360;
|
|
12
|
-
if (normalized % 360 === 0) {
|
|
12
|
+
if (normalized % 360 === 0 && resizingMode === null) {
|
|
13
13
|
return frame;
|
|
14
14
|
}
|
|
15
15
|
if (normalized % 90 !== 0) {
|
|
@@ -19,6 +19,8 @@ const rotateVideoFrame = ({ frame, rotation, }) => {
|
|
|
19
19
|
height: frame.displayHeight,
|
|
20
20
|
width: frame.displayWidth,
|
|
21
21
|
rotation,
|
|
22
|
+
videoCodec,
|
|
23
|
+
resizingMode,
|
|
22
24
|
});
|
|
23
25
|
const canvas = new OffscreenCanvas(width, height);
|
|
24
26
|
const ctx = canvas.getContext('2d');
|
|
@@ -37,6 +39,9 @@ const rotateVideoFrame = ({ frame, rotation, }) => {
|
|
|
37
39
|
ctx.translate(0, height);
|
|
38
40
|
}
|
|
39
41
|
ctx.rotate(normalized * (Math.PI / 180));
|
|
42
|
+
if (frame.displayHeight !== height || frame.displayWidth !== width) {
|
|
43
|
+
ctx.scale(width / frame.displayWidth, height / frame.displayHeight);
|
|
44
|
+
}
|
|
40
45
|
ctx.drawImage(frame, 0, 0);
|
|
41
46
|
return new VideoFrame(canvas, {
|
|
42
47
|
displayHeight: height,
|
|
@@ -45,4 +50,4 @@ const rotateVideoFrame = ({ frame, rotation, }) => {
|
|
|
45
50
|
timestamp: frame.timestamp,
|
|
46
51
|
});
|
|
47
52
|
};
|
|
48
|
-
exports.
|
|
53
|
+
exports.rotateAndResizeVideoFrame = rotateAndResizeVideoFrame;
|
package/dist/rotation.d.ts
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import type { Dimensions, MediaParserVideoCodec } from '@remotion/media-parser';
|
|
2
|
+
import type { ConvertMediaVideoCodec } from './get-available-video-codecs';
|
|
3
|
+
import type { ResizeOperation } from './resizing/mode';
|
|
4
|
+
export declare const calculateNewDimensionsFromRotate: ({ height, width, rotation, }: Dimensions & {
|
|
4
5
|
rotation: number;
|
|
5
6
|
}) => {
|
|
6
7
|
height: number;
|
|
7
8
|
width: number;
|
|
8
9
|
};
|
|
10
|
+
export declare const calculateNewDimensionsFromRotateAndScale: ({ width, height, rotation, resizeOperation, videoCodec, }: {
|
|
11
|
+
width: number;
|
|
12
|
+
height: number;
|
|
13
|
+
rotation: number;
|
|
14
|
+
resizeOperation: ResizeOperation | null;
|
|
15
|
+
videoCodec: ConvertMediaVideoCodec | MediaParserVideoCodec;
|
|
16
|
+
}) => import("./resizing/mode").Dimensions;
|
package/dist/rotation.js
CHANGED
|
@@ -1,10 +1,29 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
const
|
|
5
|
-
|
|
3
|
+
exports.calculateNewDimensionsFromRotateAndScale = exports.calculateNewDimensionsFromRotate = void 0;
|
|
4
|
+
const calculate_new_size_1 = require("./resizing/calculate-new-size");
|
|
5
|
+
const rotate_and_resize_video_frame_1 = require("./rotate-and-resize-video-frame");
|
|
6
|
+
const calculateNewDimensionsFromRotate = ({ height, width, rotation, }) => {
|
|
7
|
+
const normalized = (0, rotate_and_resize_video_frame_1.normalizeVideoRotation)(rotation);
|
|
8
|
+
const switchDimensions = normalized % 90 === 0 && normalized % 180 !== 0;
|
|
6
9
|
const newHeight = switchDimensions ? width : height;
|
|
7
10
|
const newWidth = switchDimensions ? height : width;
|
|
8
|
-
return {
|
|
11
|
+
return {
|
|
12
|
+
height: newHeight,
|
|
13
|
+
width: newWidth,
|
|
14
|
+
};
|
|
9
15
|
};
|
|
10
|
-
exports.
|
|
16
|
+
exports.calculateNewDimensionsFromRotate = calculateNewDimensionsFromRotate;
|
|
17
|
+
const calculateNewDimensionsFromRotateAndScale = ({ width, height, rotation, resizeOperation, videoCodec, }) => {
|
|
18
|
+
const { height: newHeight, width: newWidth } = (0, exports.calculateNewDimensionsFromRotate)({
|
|
19
|
+
height,
|
|
20
|
+
rotation,
|
|
21
|
+
width,
|
|
22
|
+
});
|
|
23
|
+
return (0, calculate_new_size_1.calculateNewSizeAfterResizing)({
|
|
24
|
+
dimensions: { height: newHeight, width: newWidth },
|
|
25
|
+
resizeOperation,
|
|
26
|
+
videoCodec,
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
exports.calculateNewDimensionsFromRotateAndScale = calculateNewDimensionsFromRotateAndScale;
|
package/dist/scaling.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.sendUsageEvent = void 0;
|
|
4
|
+
const licensing_1 = require("@remotion/licensing");
|
|
5
|
+
const sendUsageEvent = async ({ apiKey, succeeded, }) => {
|
|
6
|
+
var _a;
|
|
7
|
+
const host = typeof window === 'undefined'
|
|
8
|
+
? null
|
|
9
|
+
: typeof window.location === 'undefined'
|
|
10
|
+
? null
|
|
11
|
+
: ((_a = window.location.origin) !== null && _a !== void 0 ? _a : null);
|
|
12
|
+
if (host === null) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
await (0, licensing_1.registerUsageEvent)({
|
|
16
|
+
apiKey,
|
|
17
|
+
event: 'webcodec-conversion',
|
|
18
|
+
host,
|
|
19
|
+
succeeded,
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
exports.sendUsageEvent = sendUsageEvent;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remotion/webcodecs",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.242",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"module": "dist/esm/index.mjs",
|
|
@@ -17,14 +17,15 @@
|
|
|
17
17
|
"author": "Jonny Burger <jonny@remotion.dev>",
|
|
18
18
|
"license": "Remotion License (See https://remotion.dev/docs/webcodecs#license)",
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@remotion/
|
|
20
|
+
"@remotion/licensing": "4.0.242",
|
|
21
|
+
"@remotion/media-parser": "4.0.242"
|
|
21
22
|
},
|
|
22
23
|
"peerDependencies": {},
|
|
23
24
|
"devDependencies": {
|
|
24
25
|
"@types/dom-webcodecs": "0.1.11",
|
|
25
26
|
"eslint": "9.14.0",
|
|
26
|
-
"@remotion/example-videos": "4.0.
|
|
27
|
-
"@remotion/eslint-config-internal": "4.0.
|
|
27
|
+
"@remotion/example-videos": "4.0.242",
|
|
28
|
+
"@remotion/eslint-config-internal": "4.0.242"
|
|
28
29
|
},
|
|
29
30
|
"keywords": [],
|
|
30
31
|
"publishConfig": {
|