@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/audio-decoder.js
CHANGED
|
@@ -78,11 +78,6 @@ const createAudioDecoder = ({ onFrame, onError, signal, config, logLevel, track,
|
|
|
78
78
|
let queue = Promise.resolve();
|
|
79
79
|
return {
|
|
80
80
|
processSample: (sample) => {
|
|
81
|
-
// In example.avi, we have samples with 0 data
|
|
82
|
-
// Chrome fails on these
|
|
83
|
-
if (sample.data.length === 0) {
|
|
84
|
-
return queue;
|
|
85
|
-
}
|
|
86
81
|
queue = queue.then(() => processSample(sample));
|
|
87
82
|
return queue;
|
|
88
83
|
},
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ParseMediaContainer, VideoTrack } from '@remotion/media-parser';
|
|
2
2
|
import type { ConvertMediaContainer } from './get-available-containers';
|
|
3
|
-
|
|
3
|
+
import type { ResizeOperation } from './resizing/mode';
|
|
4
|
+
export declare const canCopyVideoTrack: ({ outputContainer, rotationToApply, inputContainer, resizeOperation, inputTrack, }: {
|
|
4
5
|
inputContainer: ParseMediaContainer;
|
|
5
|
-
|
|
6
|
-
inputRotation: number;
|
|
6
|
+
inputTrack: VideoTrack;
|
|
7
7
|
rotationToApply: number;
|
|
8
8
|
outputContainer: ConvertMediaContainer;
|
|
9
|
+
resizeOperation: ResizeOperation | null;
|
|
9
10
|
}) => boolean;
|
|
@@ -1,17 +1,30 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.canCopyVideoTrack = void 0;
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
const rotate_and_resize_video_frame_1 = require("./rotate-and-resize-video-frame");
|
|
5
|
+
const rotation_1 = require("./rotation");
|
|
6
|
+
const canCopyVideoTrack = ({ outputContainer, rotationToApply, inputContainer, resizeOperation, inputTrack, }) => {
|
|
7
|
+
if ((0, rotate_and_resize_video_frame_1.normalizeVideoRotation)(inputTrack.rotation) !==
|
|
8
|
+
(0, rotate_and_resize_video_frame_1.normalizeVideoRotation)(rotationToApply)) {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
const newDimensions = (0, rotation_1.calculateNewDimensionsFromRotateAndScale)({
|
|
12
|
+
height: inputTrack.height,
|
|
13
|
+
resizeOperation,
|
|
14
|
+
rotation: rotationToApply,
|
|
15
|
+
videoCodec: inputTrack.codecWithoutConfig,
|
|
16
|
+
width: inputTrack.width,
|
|
17
|
+
});
|
|
18
|
+
if (newDimensions.height !== inputTrack.height ||
|
|
19
|
+
newDimensions.width !== inputTrack.width) {
|
|
8
20
|
return false;
|
|
9
21
|
}
|
|
10
22
|
if (outputContainer === 'webm') {
|
|
11
|
-
return
|
|
23
|
+
return (inputTrack.codecWithoutConfig === 'vp8' ||
|
|
24
|
+
inputTrack.codecWithoutConfig === 'vp9');
|
|
12
25
|
}
|
|
13
26
|
if (outputContainer === 'mp4') {
|
|
14
|
-
return (
|
|
27
|
+
return (inputTrack.codecWithoutConfig === 'h264' &&
|
|
15
28
|
(inputContainer === 'mp4' || inputContainer === 'avi'));
|
|
16
29
|
}
|
|
17
30
|
if (outputContainer === 'wav') {
|
package/dist/convert-media.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ import type { ConvertMediaContainer } from './get-available-containers';
|
|
|
8
8
|
import type { ConvertMediaVideoCodec } from './get-available-video-codecs';
|
|
9
9
|
import { type ConvertMediaOnAudioTrackHandler } from './on-audio-track-handler';
|
|
10
10
|
import { type ConvertMediaOnVideoTrackHandler } from './on-video-track-handler';
|
|
11
|
+
import type { ResizeOperation } from './resizing/mode';
|
|
11
12
|
export type ConvertMediaProgress = {
|
|
12
13
|
decodedVideoFrames: number;
|
|
13
14
|
decodedAudioFrames: number;
|
|
@@ -28,7 +29,7 @@ export type ConvertMediaOnVideoFrame = (options: {
|
|
|
28
29
|
frame: VideoFrame;
|
|
29
30
|
track: VideoTrack;
|
|
30
31
|
}) => Promise<VideoFrame> | VideoFrame;
|
|
31
|
-
export declare const convertMedia: <F extends Options<ParseMediaFields>>({ src, onVideoFrame, onProgress: onProgressDoNotCallDirectly, audioCodec, container, videoCodec, signal: userPassedAbortSignal, onAudioTrack: userAudioResolver, onVideoTrack: userVideoResolver, reader, fields, logLevel, writer, progressIntervalInMs, rotate, ...more }: {
|
|
32
|
+
export declare const convertMedia: <F extends Options<ParseMediaFields>>({ src, onVideoFrame, onProgress: onProgressDoNotCallDirectly, audioCodec, container, videoCodec, signal: userPassedAbortSignal, onAudioTrack: userAudioResolver, onVideoTrack: userVideoResolver, reader, fields, logLevel, writer, progressIntervalInMs, rotate, apiKey, resize, ...more }: {
|
|
32
33
|
src: ParseMediaOptions<F>["src"];
|
|
33
34
|
container: ConvertMediaContainer;
|
|
34
35
|
onVideoFrame?: ConvertMediaOnVideoFrame;
|
|
@@ -43,4 +44,6 @@ export declare const convertMedia: <F extends Options<ParseMediaFields>>({ src,
|
|
|
43
44
|
writer?: WriterInterface;
|
|
44
45
|
progressIntervalInMs?: number;
|
|
45
46
|
rotate?: number;
|
|
47
|
+
resize?: ResizeOperation;
|
|
48
|
+
apiKey?: string | null;
|
|
46
49
|
} & ParseMediaDynamicOptions<F>) => Promise<ConvertMediaResult>;
|
package/dist/convert-media.js
CHANGED
|
@@ -13,11 +13,13 @@ const auto_select_writer_1 = require("./auto-select-writer");
|
|
|
13
13
|
const calculate_progress_1 = require("./calculate-progress");
|
|
14
14
|
const error_cause_1 = __importDefault(require("./error-cause"));
|
|
15
15
|
const generate_output_filename_1 = require("./generate-output-filename");
|
|
16
|
+
const log_1 = require("./log");
|
|
16
17
|
const on_audio_track_1 = require("./on-audio-track");
|
|
17
18
|
const on_video_track_1 = require("./on-video-track");
|
|
18
19
|
const select_container_creator_1 = require("./select-container-creator");
|
|
20
|
+
const send_telemetry_event_1 = require("./send-telemetry-event");
|
|
19
21
|
const throttled_state_update_1 = require("./throttled-state-update");
|
|
20
|
-
const convertMedia = async function ({ src, onVideoFrame, onProgress: onProgressDoNotCallDirectly, audioCodec, container, videoCodec, signal: userPassedAbortSignal, onAudioTrack: userAudioResolver, onVideoTrack: userVideoResolver, reader, fields, logLevel = 'info', writer, progressIntervalInMs, rotate, ...more }) {
|
|
22
|
+
const convertMedia = async function ({ src, onVideoFrame, onProgress: onProgressDoNotCallDirectly, audioCodec, container, videoCodec, signal: userPassedAbortSignal, onAudioTrack: userAudioResolver, onVideoTrack: userVideoResolver, reader, fields, logLevel = 'info', writer, progressIntervalInMs, rotate, apiKey, resize, ...more }) {
|
|
21
23
|
var _a, _b;
|
|
22
24
|
if (userPassedAbortSignal === null || userPassedAbortSignal === void 0 ? void 0 : userPassedAbortSignal.aborted) {
|
|
23
25
|
return Promise.reject(new error_cause_1.default('Aborted'));
|
|
@@ -90,6 +92,7 @@ const convertMedia = async function ({ src, onVideoFrame, onProgress: onProgress
|
|
|
90
92
|
outputContainer: container,
|
|
91
93
|
rotate: rotate !== null && rotate !== void 0 ? rotate : 0,
|
|
92
94
|
progress: progressTracker,
|
|
95
|
+
resizeOperation: resize !== null && resize !== void 0 ? resize : null,
|
|
93
96
|
});
|
|
94
97
|
const onAudioTrack = (0, on_audio_track_1.makeAudioTrackHandler)({
|
|
95
98
|
abortConversion,
|
|
@@ -145,8 +148,16 @@ const convertMedia = async function ({ src, onVideoFrame, onProgress: onProgress
|
|
|
145
148
|
remove: state.remove,
|
|
146
149
|
finalState: throttledState.get(),
|
|
147
150
|
});
|
|
151
|
+
})
|
|
152
|
+
.then(() => {
|
|
153
|
+
(0, send_telemetry_event_1.sendUsageEvent)({ succeeded: true, apiKey: apiKey !== null && apiKey !== void 0 ? apiKey : null }).catch((err) => {
|
|
154
|
+
log_1.Log.error('Failed to send usage event', err);
|
|
155
|
+
});
|
|
148
156
|
})
|
|
149
157
|
.catch((err) => {
|
|
158
|
+
(0, send_telemetry_event_1.sendUsageEvent)({ succeeded: false, apiKey: apiKey !== null && apiKey !== void 0 ? apiKey : null }).catch((err2) => {
|
|
159
|
+
log_1.Log.error('Failed to send usage event hmm', err2);
|
|
160
|
+
});
|
|
150
161
|
reject(err);
|
|
151
162
|
})
|
|
152
163
|
.finally(() => {
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.defaultOnVideoTrackHandler = void 0;
|
|
4
4
|
const media_parser_1 = require("@remotion/media-parser");
|
|
5
5
|
const can_reencode_video_track_1 = require("./can-reencode-video-track");
|
|
6
|
-
const defaultOnVideoTrackHandler = async ({ track, defaultVideoCodec, logLevel, rotate, canCopyTrack, }) => {
|
|
6
|
+
const defaultOnVideoTrackHandler = async ({ track, defaultVideoCodec, logLevel, rotate, canCopyTrack, resizeOperation, }) => {
|
|
7
7
|
if (canCopyTrack) {
|
|
8
8
|
media_parser_1.MediaParserInternals.Log.verbose(logLevel, `Track ${track.trackId} (video): Can copy, therefore copying`);
|
|
9
9
|
return Promise.resolve({ type: 'copy' });
|
|
@@ -21,7 +21,8 @@ const defaultOnVideoTrackHandler = async ({ track, defaultVideoCodec, logLevel,
|
|
|
21
21
|
return Promise.resolve({
|
|
22
22
|
type: 'reencode',
|
|
23
23
|
videoCodec: defaultVideoCodec,
|
|
24
|
-
|
|
24
|
+
rotate: rotate - track.rotation,
|
|
25
|
+
resize: resizeOperation,
|
|
25
26
|
});
|
|
26
27
|
}
|
|
27
28
|
media_parser_1.MediaParserInternals.Log.verbose(logLevel, `Track ${track.trackId} (video): Can neither copy nor re-encode, therefore failing`);
|
package/dist/esm/index.mjs
CHANGED
|
@@ -1,35 +1,252 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __toESM = (mod, isNodeMode, target) => {
|
|
7
|
+
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
8
|
+
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
9
|
+
for (let key of __getOwnPropNames(mod))
|
|
10
|
+
if (!__hasOwnProp.call(to, key))
|
|
11
|
+
__defProp(to, key, {
|
|
12
|
+
get: () => mod[key],
|
|
13
|
+
enumerable: true
|
|
14
|
+
});
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
18
|
+
|
|
19
|
+
// ../licensing/dist/register-usage-point.js
|
|
20
|
+
var require_register_usage_point = __commonJS((exports) => {
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.registerUsageEvent = exports.HOST = undefined;
|
|
23
|
+
exports.HOST = "https://www.remotion.pro";
|
|
24
|
+
var registerUsageEvent = async ({ apiKey, host, succeeded, event }) => {
|
|
25
|
+
const res = await fetch(`${exports.HOST}/api/track/register-usage-point`, {
|
|
26
|
+
method: "POST",
|
|
27
|
+
body: JSON.stringify({
|
|
28
|
+
event,
|
|
29
|
+
apiKey,
|
|
30
|
+
host,
|
|
31
|
+
succeeded
|
|
32
|
+
}),
|
|
33
|
+
headers: {
|
|
34
|
+
"Content-Type": "application/json"
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
const json = await res.json();
|
|
38
|
+
if (json.success) {
|
|
39
|
+
return {
|
|
40
|
+
billable: json.billable,
|
|
41
|
+
classification: json.classification
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
if (!res.ok) {
|
|
45
|
+
throw new Error(json.error);
|
|
46
|
+
}
|
|
47
|
+
const read = await res.json();
|
|
48
|
+
return read;
|
|
49
|
+
};
|
|
50
|
+
exports.registerUsageEvent = registerUsageEvent;
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// ../licensing/dist/get-usage.js
|
|
54
|
+
var require_get_usage = __commonJS((exports) => {
|
|
55
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
56
|
+
exports.getUsage = undefined;
|
|
57
|
+
var register_usage_point_1 = require_register_usage_point();
|
|
58
|
+
var getUsage = async ({ apiKey, since }) => {
|
|
59
|
+
const res = await fetch(`${register_usage_point_1.HOST}/api/track/get-usage`, {
|
|
60
|
+
method: "POST",
|
|
61
|
+
body: JSON.stringify({
|
|
62
|
+
apiKey,
|
|
63
|
+
since: since !== null && since !== undefined ? since : null
|
|
64
|
+
}),
|
|
65
|
+
headers: {
|
|
66
|
+
"Content-Type": "application/json"
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
const json = await res.json();
|
|
70
|
+
if (json.success) {
|
|
71
|
+
return {
|
|
72
|
+
cloudRenders: json.cloudRenders,
|
|
73
|
+
webcodecConversions: json.webcodecConversions
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
throw new Error(json.error);
|
|
77
|
+
};
|
|
78
|
+
exports.getUsage = getUsage;
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// ../licensing/dist/index.js
|
|
82
|
+
var require_dist = __commonJS((exports) => {
|
|
83
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
84
|
+
exports.getUsage = exports.registerUsageEvent = undefined;
|
|
85
|
+
var register_usage_point_1 = require_register_usage_point();
|
|
86
|
+
Object.defineProperty(exports, "registerUsageEvent", { enumerable: true, get: function() {
|
|
87
|
+
return register_usage_point_1.registerUsageEvent;
|
|
88
|
+
} });
|
|
89
|
+
var get_usage_1 = require_get_usage();
|
|
90
|
+
Object.defineProperty(exports, "getUsage", { enumerable: true, get: function() {
|
|
91
|
+
return get_usage_1.getUsage;
|
|
92
|
+
} });
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// src/resizing/calculate-new-size.ts
|
|
96
|
+
var ensureMultipleOfTwo = ({
|
|
97
|
+
dimensions,
|
|
98
|
+
needsToBeMultipleOfTwo
|
|
99
|
+
}) => {
|
|
100
|
+
if (!needsToBeMultipleOfTwo) {
|
|
101
|
+
return dimensions;
|
|
102
|
+
}
|
|
103
|
+
return {
|
|
104
|
+
width: Math.floor(dimensions.width / 2) * 2,
|
|
105
|
+
height: Math.floor(dimensions.height / 2) * 2
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
var calculateNewSizeAfterResizing = ({
|
|
109
|
+
dimensions,
|
|
110
|
+
resizeOperation,
|
|
111
|
+
videoCodec
|
|
112
|
+
}) => {
|
|
113
|
+
const needsToBeMultipleOfTwo = videoCodec === "h264";
|
|
114
|
+
if (resizeOperation === null) {
|
|
115
|
+
return ensureMultipleOfTwo({
|
|
116
|
+
dimensions,
|
|
117
|
+
needsToBeMultipleOfTwo
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
if (resizeOperation.mode === "width") {
|
|
121
|
+
return ensureMultipleOfTwo({
|
|
122
|
+
dimensions: {
|
|
123
|
+
width: resizeOperation.width,
|
|
124
|
+
height: Math.round(resizeOperation.width / dimensions.width * dimensions.height)
|
|
125
|
+
},
|
|
126
|
+
needsToBeMultipleOfTwo
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
if (resizeOperation.mode === "height") {
|
|
130
|
+
return ensureMultipleOfTwo({
|
|
131
|
+
dimensions: {
|
|
132
|
+
width: Math.round(resizeOperation.height / dimensions.height * dimensions.width),
|
|
133
|
+
height: resizeOperation.height
|
|
134
|
+
},
|
|
135
|
+
needsToBeMultipleOfTwo
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
if (resizeOperation.mode === "max-height") {
|
|
139
|
+
const height = Math.min(dimensions.height, resizeOperation.maxHeight);
|
|
140
|
+
return ensureMultipleOfTwo({
|
|
141
|
+
dimensions: {
|
|
142
|
+
width: Math.round(height / dimensions.height * dimensions.width),
|
|
143
|
+
height
|
|
144
|
+
},
|
|
145
|
+
needsToBeMultipleOfTwo
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
if (resizeOperation.mode === "max-width") {
|
|
149
|
+
const width = Math.min(dimensions.width, resizeOperation.maxWidth);
|
|
150
|
+
return ensureMultipleOfTwo({
|
|
151
|
+
dimensions: {
|
|
152
|
+
width,
|
|
153
|
+
height: Math.round(width / dimensions.width * dimensions.height)
|
|
154
|
+
},
|
|
155
|
+
needsToBeMultipleOfTwo
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
if (resizeOperation.mode === "max-height-width") {
|
|
159
|
+
const height = Math.min(dimensions.height, resizeOperation.maxHeight);
|
|
160
|
+
const width = Math.min(dimensions.width, resizeOperation.maxWidth);
|
|
161
|
+
const scale = Math.min(width / dimensions.width, height / dimensions.height);
|
|
162
|
+
const actualWidth = Math.round(dimensions.width * scale);
|
|
163
|
+
const actualHeight = Math.round(dimensions.height * scale);
|
|
164
|
+
return ensureMultipleOfTwo({
|
|
165
|
+
dimensions: {
|
|
166
|
+
height: actualHeight,
|
|
167
|
+
width: actualWidth
|
|
168
|
+
},
|
|
169
|
+
needsToBeMultipleOfTwo
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
if (resizeOperation.mode === "scale") {
|
|
173
|
+
if (resizeOperation.scale <= 0) {
|
|
174
|
+
throw new Error("Scale must be greater than 0");
|
|
175
|
+
}
|
|
176
|
+
const width = Math.round(dimensions.width * resizeOperation.scale);
|
|
177
|
+
const height = Math.round(dimensions.height * resizeOperation.scale);
|
|
178
|
+
return ensureMultipleOfTwo({
|
|
179
|
+
dimensions: {
|
|
180
|
+
width,
|
|
181
|
+
height
|
|
182
|
+
},
|
|
183
|
+
needsToBeMultipleOfTwo
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
throw new Error("Invalid resizing mode " + resizeOperation);
|
|
187
|
+
};
|
|
188
|
+
|
|
1
189
|
// src/rotation.ts
|
|
2
|
-
var
|
|
3
|
-
width,
|
|
190
|
+
var calculateNewDimensionsFromRotate = ({
|
|
4
191
|
height,
|
|
192
|
+
width,
|
|
5
193
|
rotation
|
|
6
194
|
}) => {
|
|
7
|
-
const
|
|
195
|
+
const normalized = normalizeVideoRotation(rotation);
|
|
196
|
+
const switchDimensions = normalized % 90 === 0 && normalized % 180 !== 0;
|
|
8
197
|
const newHeight = switchDimensions ? width : height;
|
|
9
198
|
const newWidth = switchDimensions ? height : width;
|
|
10
|
-
return {
|
|
199
|
+
return {
|
|
200
|
+
height: newHeight,
|
|
201
|
+
width: newWidth
|
|
202
|
+
};
|
|
203
|
+
};
|
|
204
|
+
var calculateNewDimensionsFromRotateAndScale = ({
|
|
205
|
+
width,
|
|
206
|
+
height,
|
|
207
|
+
rotation,
|
|
208
|
+
resizeOperation,
|
|
209
|
+
videoCodec
|
|
210
|
+
}) => {
|
|
211
|
+
const { height: newHeight, width: newWidth } = calculateNewDimensionsFromRotate({
|
|
212
|
+
height,
|
|
213
|
+
rotation,
|
|
214
|
+
width
|
|
215
|
+
});
|
|
216
|
+
return calculateNewSizeAfterResizing({
|
|
217
|
+
dimensions: { height: newHeight, width: newWidth },
|
|
218
|
+
resizeOperation,
|
|
219
|
+
videoCodec
|
|
220
|
+
});
|
|
11
221
|
};
|
|
12
222
|
|
|
13
|
-
// src/rotate-video-frame.ts
|
|
223
|
+
// src/rotate-and-resize-video-frame.ts
|
|
14
224
|
var normalizeVideoRotation = (rotation) => {
|
|
15
225
|
return (rotation % 360 + 360) % 360;
|
|
16
226
|
};
|
|
17
|
-
var
|
|
227
|
+
var rotateAndResizeVideoFrame = ({
|
|
18
228
|
frame,
|
|
19
|
-
rotation
|
|
229
|
+
rotation,
|
|
230
|
+
videoCodec,
|
|
231
|
+
resizeOperation
|
|
20
232
|
}) => {
|
|
21
233
|
const normalized = (rotation % 360 + 360) % 360;
|
|
22
|
-
if (normalized
|
|
234
|
+
if (normalized === 0 && resizeOperation === null) {
|
|
23
235
|
return frame;
|
|
24
236
|
}
|
|
25
237
|
if (normalized % 90 !== 0) {
|
|
26
238
|
throw new Error("Only 90 degree rotations are supported");
|
|
27
239
|
}
|
|
28
|
-
const { height, width } =
|
|
240
|
+
const { height, width } = calculateNewDimensionsFromRotateAndScale({
|
|
29
241
|
height: frame.displayHeight,
|
|
30
242
|
width: frame.displayWidth,
|
|
31
|
-
rotation
|
|
243
|
+
rotation,
|
|
244
|
+
videoCodec,
|
|
245
|
+
resizeOperation
|
|
32
246
|
});
|
|
247
|
+
if (normalized === 0 && height === frame.displayHeight && width === frame.displayWidth) {
|
|
248
|
+
return frame;
|
|
249
|
+
}
|
|
33
250
|
const canvas = new OffscreenCanvas(width, height);
|
|
34
251
|
const ctx = canvas.getContext("2d");
|
|
35
252
|
if (!ctx) {
|
|
@@ -44,7 +261,17 @@ var rotateVideoFrame = ({
|
|
|
44
261
|
} else if (normalized === 270) {
|
|
45
262
|
ctx.translate(0, height);
|
|
46
263
|
}
|
|
47
|
-
|
|
264
|
+
if (normalized !== 0) {
|
|
265
|
+
ctx.rotate(normalized * (Math.PI / 180));
|
|
266
|
+
}
|
|
267
|
+
if (frame.displayHeight !== height || frame.displayWidth !== width) {
|
|
268
|
+
const dimensionsAfterRotate = calculateNewDimensionsFromRotate({
|
|
269
|
+
height: frame.displayHeight,
|
|
270
|
+
rotation,
|
|
271
|
+
width: frame.displayWidth
|
|
272
|
+
});
|
|
273
|
+
ctx.scale(width / dimensionsAfterRotate.width, height / dimensionsAfterRotate.height);
|
|
274
|
+
}
|
|
48
275
|
ctx.drawImage(frame, 0, 0);
|
|
49
276
|
return new VideoFrame(canvas, {
|
|
50
277
|
displayHeight: height,
|
|
@@ -110,7 +337,7 @@ import { MediaParserInternals as MediaParserInternals2 } from "@remotion/media-p
|
|
|
110
337
|
var makeTimeoutPromise = (label, ms) => {
|
|
111
338
|
const { promise, reject, resolve } = MediaParserInternals2.withResolvers();
|
|
112
339
|
const timeout = setTimeout(() => {
|
|
113
|
-
reject(new Error(`${label} (timed out after ${ms}ms)`));
|
|
340
|
+
reject(new Error(`${label()} (timed out after ${ms}ms)`));
|
|
114
341
|
}, ms);
|
|
115
342
|
return {
|
|
116
343
|
timeoutPromise: promise,
|
|
@@ -194,14 +421,14 @@ var makeIoSynchronizer = ({
|
|
|
194
421
|
minimumProgress,
|
|
195
422
|
signal
|
|
196
423
|
}) => {
|
|
197
|
-
const { timeoutPromise, clear } = makeTimeoutPromise([
|
|
198
|
-
`Waited too long for ${label}:`,
|
|
424
|
+
const { timeoutPromise, clear } = makeTimeoutPromise(() => [
|
|
425
|
+
`Waited too long for ${label} to finish:`,
|
|
199
426
|
`${getUnemittedItems()} unemitted items`,
|
|
200
|
-
`${getUnprocessed()} unprocessed items`,
|
|
201
|
-
`minimum progress ${minimumProgress}`,
|
|
427
|
+
`${getUnprocessed()} unprocessed items: ${JSON.stringify(_unprocessed)}`,
|
|
202
428
|
`smallest progress: ${progress.getSmallestProgress()}`,
|
|
203
429
|
`inputs: ${JSON.stringify(inputs)}`,
|
|
204
|
-
`last output: ${lastOutput}
|
|
430
|
+
`last output: ${lastOutput}`,
|
|
431
|
+
`wanted: ${unemitted} unemitted items, ${unprocessed} unprocessed items, minimum progress ${minimumProgress}`
|
|
205
432
|
].join(`
|
|
206
433
|
`), 1e4);
|
|
207
434
|
signal.addEventListener("abort", clear);
|
|
@@ -326,9 +553,6 @@ var createAudioDecoder = ({
|
|
|
326
553
|
let queue = Promise.resolve();
|
|
327
554
|
return {
|
|
328
555
|
processSample: (sample) => {
|
|
329
|
-
if (sample.data.length === 0) {
|
|
330
|
-
return queue;
|
|
331
|
-
}
|
|
332
556
|
queue = queue.then(() => processSample(sample));
|
|
333
557
|
return queue;
|
|
334
558
|
},
|
|
@@ -495,20 +719,30 @@ var canCopyAudioTrack = ({
|
|
|
495
719
|
};
|
|
496
720
|
// src/can-copy-video-track.ts
|
|
497
721
|
var canCopyVideoTrack = ({
|
|
498
|
-
inputCodec,
|
|
499
722
|
outputContainer,
|
|
500
|
-
inputRotation,
|
|
501
723
|
rotationToApply,
|
|
502
|
-
inputContainer
|
|
724
|
+
inputContainer,
|
|
725
|
+
resizeOperation,
|
|
726
|
+
inputTrack
|
|
503
727
|
}) => {
|
|
504
|
-
if (normalizeVideoRotation(
|
|
728
|
+
if (normalizeVideoRotation(inputTrack.rotation) !== normalizeVideoRotation(rotationToApply)) {
|
|
729
|
+
return false;
|
|
730
|
+
}
|
|
731
|
+
const newDimensions = calculateNewDimensionsFromRotateAndScale({
|
|
732
|
+
height: inputTrack.height,
|
|
733
|
+
resizeOperation,
|
|
734
|
+
rotation: rotationToApply,
|
|
735
|
+
videoCodec: inputTrack.codecWithoutConfig,
|
|
736
|
+
width: inputTrack.width
|
|
737
|
+
});
|
|
738
|
+
if (newDimensions.height !== inputTrack.height || newDimensions.width !== inputTrack.width) {
|
|
505
739
|
return false;
|
|
506
740
|
}
|
|
507
741
|
if (outputContainer === "webm") {
|
|
508
|
-
return
|
|
742
|
+
return inputTrack.codecWithoutConfig === "vp8" || inputTrack.codecWithoutConfig === "vp9";
|
|
509
743
|
}
|
|
510
744
|
if (outputContainer === "mp4") {
|
|
511
|
-
return
|
|
745
|
+
return inputTrack.codecWithoutConfig === "h264" && (inputContainer === "mp4" || inputContainer === "avi");
|
|
512
746
|
}
|
|
513
747
|
if (outputContainer === "wav") {
|
|
514
748
|
return false;
|
|
@@ -774,7 +1008,9 @@ var convertEncodedChunk = (chunk, trackId) => {
|
|
|
774
1008
|
type: chunk.type,
|
|
775
1009
|
cts: chunk.timestamp,
|
|
776
1010
|
dts: chunk.timestamp,
|
|
777
|
-
trackId
|
|
1011
|
+
trackId,
|
|
1012
|
+
offset: 0,
|
|
1013
|
+
timescale: 1e6
|
|
778
1014
|
};
|
|
779
1015
|
};
|
|
780
1016
|
|
|
@@ -992,7 +1228,8 @@ var defaultOnVideoTrackHandler = async ({
|
|
|
992
1228
|
defaultVideoCodec,
|
|
993
1229
|
logLevel,
|
|
994
1230
|
rotate,
|
|
995
|
-
canCopyTrack
|
|
1231
|
+
canCopyTrack,
|
|
1232
|
+
resizeOperation
|
|
996
1233
|
}) => {
|
|
997
1234
|
if (canCopyTrack) {
|
|
998
1235
|
MediaParserInternals7.Log.verbose(logLevel, `Track ${track.trackId} (video): Can copy, therefore copying`);
|
|
@@ -1011,7 +1248,8 @@ var defaultOnVideoTrackHandler = async ({
|
|
|
1011
1248
|
return Promise.resolve({
|
|
1012
1249
|
type: "reencode",
|
|
1013
1250
|
videoCodec: defaultVideoCodec,
|
|
1014
|
-
|
|
1251
|
+
rotate: rotate - track.rotation,
|
|
1252
|
+
resize: resizeOperation
|
|
1015
1253
|
});
|
|
1016
1254
|
}
|
|
1017
1255
|
MediaParserInternals7.Log.verbose(logLevel, `Track ${track.trackId} (video): Can neither copy nor re-encode, therefore failing`);
|
|
@@ -1077,11 +1315,14 @@ var onFrame = async ({
|
|
|
1077
1315
|
videoEncoder,
|
|
1078
1316
|
track,
|
|
1079
1317
|
outputCodec,
|
|
1080
|
-
rotation
|
|
1318
|
+
rotation,
|
|
1319
|
+
resizeOperation
|
|
1081
1320
|
}) => {
|
|
1082
|
-
const rotated =
|
|
1321
|
+
const rotated = rotateAndResizeVideoFrame({
|
|
1083
1322
|
rotation,
|
|
1084
|
-
frame: unrotatedFrame
|
|
1323
|
+
frame: unrotatedFrame,
|
|
1324
|
+
resizeOperation,
|
|
1325
|
+
videoCodec: outputCodec
|
|
1085
1326
|
});
|
|
1086
1327
|
if (unrotatedFrame !== rotated) {
|
|
1087
1328
|
unrotatedFrame.close();
|
|
@@ -1312,17 +1553,18 @@ var makeVideoTrackHandler = ({
|
|
|
1312
1553
|
logLevel,
|
|
1313
1554
|
outputContainer,
|
|
1314
1555
|
rotate,
|
|
1315
|
-
progress
|
|
1556
|
+
progress,
|
|
1557
|
+
resizeOperation
|
|
1316
1558
|
}) => async ({ track, container: inputContainer }) => {
|
|
1317
1559
|
if (controller.signal.aborted) {
|
|
1318
1560
|
throw new error_cause_default("Aborted");
|
|
1319
1561
|
}
|
|
1320
1562
|
const canCopyTrack = canCopyVideoTrack({
|
|
1321
|
-
inputCodec: track.codecWithoutConfig,
|
|
1322
1563
|
inputContainer,
|
|
1323
|
-
inputRotation: track.rotation,
|
|
1324
1564
|
outputContainer,
|
|
1325
|
-
rotationToApply: rotate
|
|
1565
|
+
rotationToApply: rotate,
|
|
1566
|
+
inputTrack: track,
|
|
1567
|
+
resizeOperation
|
|
1326
1568
|
});
|
|
1327
1569
|
const videoOperation = await (onVideoTrack ?? defaultOnVideoTrackHandler)({
|
|
1328
1570
|
track,
|
|
@@ -1331,7 +1573,8 @@ var makeVideoTrackHandler = ({
|
|
|
1331
1573
|
outputContainer,
|
|
1332
1574
|
rotate,
|
|
1333
1575
|
inputContainer,
|
|
1334
|
-
canCopyTrack
|
|
1576
|
+
canCopyTrack,
|
|
1577
|
+
resizeOperation
|
|
1335
1578
|
});
|
|
1336
1579
|
if (videoOperation.type === "drop") {
|
|
1337
1580
|
return null;
|
|
@@ -1369,10 +1612,12 @@ var makeVideoTrackHandler = ({
|
|
|
1369
1612
|
throw new error_cause_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"`);
|
|
1370
1613
|
}
|
|
1371
1614
|
const rotation = (videoOperation.rotate ?? rotate) - track.rotation;
|
|
1372
|
-
const { height: newHeight, width: newWidth } =
|
|
1615
|
+
const { height: newHeight, width: newWidth } = calculateNewDimensionsFromRotateAndScale({
|
|
1373
1616
|
width: track.codedWidth,
|
|
1374
1617
|
height: track.codedHeight,
|
|
1375
|
-
rotation
|
|
1618
|
+
rotation,
|
|
1619
|
+
videoCodec: videoOperation.videoCodec,
|
|
1620
|
+
resizeOperation: videoOperation.resize ?? null
|
|
1376
1621
|
});
|
|
1377
1622
|
const videoEncoderConfig = await getVideoEncoderConfig({
|
|
1378
1623
|
codec: videoOperation.videoCodec,
|
|
@@ -1434,7 +1679,8 @@ var makeVideoTrackHandler = ({
|
|
|
1434
1679
|
videoEncoder,
|
|
1435
1680
|
onVideoFrame,
|
|
1436
1681
|
outputCodec: videoOperation.videoCodec,
|
|
1437
|
-
rotation
|
|
1682
|
+
rotation,
|
|
1683
|
+
resizeOperation: videoOperation.resize ?? null
|
|
1438
1684
|
});
|
|
1439
1685
|
},
|
|
1440
1686
|
onError: (err) => {
|
|
@@ -1475,6 +1721,24 @@ var selectContainerCreator = (container) => {
|
|
|
1475
1721
|
throw new Error(`Unsupported container: ${container}`);
|
|
1476
1722
|
};
|
|
1477
1723
|
|
|
1724
|
+
// src/send-telemetry-event.ts
|
|
1725
|
+
var import_licensing = __toESM(require_dist(), 1);
|
|
1726
|
+
var sendUsageEvent = async ({
|
|
1727
|
+
apiKey,
|
|
1728
|
+
succeeded
|
|
1729
|
+
}) => {
|
|
1730
|
+
const host = typeof window === "undefined" ? null : typeof window.location === "undefined" ? null : window.location.origin ?? null;
|
|
1731
|
+
if (host === null) {
|
|
1732
|
+
return;
|
|
1733
|
+
}
|
|
1734
|
+
await import_licensing.registerUsageEvent({
|
|
1735
|
+
apiKey,
|
|
1736
|
+
event: "webcodec-conversion",
|
|
1737
|
+
host,
|
|
1738
|
+
succeeded
|
|
1739
|
+
});
|
|
1740
|
+
};
|
|
1741
|
+
|
|
1478
1742
|
// src/throttled-state-update.ts
|
|
1479
1743
|
var throttledStateUpdate = ({
|
|
1480
1744
|
updateFn,
|
|
@@ -1544,6 +1808,8 @@ var convertMedia = async function({
|
|
|
1544
1808
|
writer,
|
|
1545
1809
|
progressIntervalInMs,
|
|
1546
1810
|
rotate,
|
|
1811
|
+
apiKey,
|
|
1812
|
+
resize,
|
|
1547
1813
|
...more
|
|
1548
1814
|
}) {
|
|
1549
1815
|
if (userPassedAbortSignal?.aborted) {
|
|
@@ -1614,7 +1880,8 @@ var convertMedia = async function({
|
|
|
1614
1880
|
logLevel,
|
|
1615
1881
|
outputContainer: container,
|
|
1616
1882
|
rotate: rotate ?? 0,
|
|
1617
|
-
progress: progressTracker
|
|
1883
|
+
progress: progressTracker,
|
|
1884
|
+
resizeOperation: resize ?? null
|
|
1618
1885
|
});
|
|
1619
1886
|
const onAudioTrack = makeAudioTrackHandler({
|
|
1620
1887
|
abortConversion,
|
|
@@ -1667,7 +1934,14 @@ var convertMedia = async function({
|
|
|
1667
1934
|
remove: state.remove,
|
|
1668
1935
|
finalState: throttledState.get()
|
|
1669
1936
|
});
|
|
1937
|
+
}).then(() => {
|
|
1938
|
+
sendUsageEvent({ succeeded: true, apiKey: apiKey ?? null }).catch((err) => {
|
|
1939
|
+
Log.error("Failed to send usage event", err);
|
|
1940
|
+
});
|
|
1670
1941
|
}).catch((err) => {
|
|
1942
|
+
sendUsageEvent({ succeeded: false, apiKey: apiKey ?? null }).catch((err2) => {
|
|
1943
|
+
Log.error("Failed to send usage event hmm", err2);
|
|
1944
|
+
});
|
|
1671
1945
|
reject(err);
|
|
1672
1946
|
}).finally(() => {
|
|
1673
1947
|
throttledState.stopAndGetLastProgress();
|
|
@@ -1713,8 +1987,9 @@ var getAvailableVideoCodecs = ({
|
|
|
1713
1987
|
};
|
|
1714
1988
|
// src/index.ts
|
|
1715
1989
|
var WebCodecsInternals = {
|
|
1716
|
-
|
|
1717
|
-
normalizeVideoRotation
|
|
1990
|
+
rotateAndResizeVideoFrame,
|
|
1991
|
+
normalizeVideoRotation,
|
|
1992
|
+
calculateNewDimensionsFromDimensions: calculateNewDimensionsFromRotateAndScale
|
|
1718
1993
|
};
|
|
1719
1994
|
setRemotionImported();
|
|
1720
1995
|
export {
|