@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.
Files changed (37) hide show
  1. package/dist/audio-decoder.js +0 -5
  2. package/dist/can-copy-video-track.d.ts +5 -4
  3. package/dist/can-copy-video-track.js +19 -6
  4. package/dist/convert-encoded-chunk.js +2 -0
  5. package/dist/convert-media.d.ts +4 -1
  6. package/dist/convert-media.js +12 -1
  7. package/dist/default-on-video-track-handler.js +3 -2
  8. package/dist/esm/index.mjs +318 -43
  9. package/dist/index.d.ts +11 -1
  10. package/dist/index.js +5 -3
  11. package/dist/io-manager/io-synchronizer.js +4 -4
  12. package/dist/io-manager/make-timeout-promise.d.ts +1 -1
  13. package/dist/io-manager/make-timeout-promise.js +1 -1
  14. package/dist/on-frame.d.ts +3 -1
  15. package/dist/on-frame.js +5 -3
  16. package/dist/on-video-track-handler.d.ts +3 -0
  17. package/dist/on-video-track.d.ts +3 -1
  18. package/dist/on-video-track.js +10 -5
  19. package/dist/resizing/calculate-new-size.d.ts +8 -0
  20. package/dist/resizing/calculate-new-size.js +89 -0
  21. package/dist/resizing/mode.d.ts +24 -0
  22. package/dist/resizing/mode.js +2 -0
  23. package/dist/resizing/resizing.d.ts +13 -0
  24. package/dist/resizing/resizing.js +2 -0
  25. package/dist/resizing.d.ts +13 -0
  26. package/dist/resizing.js +2 -0
  27. package/dist/rotate-and-resize-video-frame.d.ts +9 -0
  28. package/dist/rotate-and-resize-video-frame.js +67 -0
  29. package/dist/rotate-video-frame.d.ts +5 -1
  30. package/dist/rotate-video-frame.js +9 -4
  31. package/dist/rotation.d.ts +11 -3
  32. package/dist/rotation.js +24 -5
  33. package/dist/scaling.d.ts +13 -0
  34. package/dist/scaling.js +2 -0
  35. package/dist/send-telemetry-event.d.ts +4 -0
  36. package/dist/send-telemetry-event.js +22 -0
  37. package/package.json +5 -4
@@ -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 { MediaParserVideoCodec, ParseMediaContainer } from '@remotion/media-parser';
1
+ import type { ParseMediaContainer, VideoTrack } from '@remotion/media-parser';
2
2
  import type { ConvertMediaContainer } from './get-available-containers';
3
- export declare const canCopyVideoTrack: ({ inputCodec, outputContainer, inputRotation, rotationToApply, inputContainer, }: {
3
+ import type { ResizeOperation } from './resizing/mode';
4
+ export declare const canCopyVideoTrack: ({ outputContainer, rotationToApply, inputContainer, resizeOperation, inputTrack, }: {
4
5
  inputContainer: ParseMediaContainer;
5
- inputCodec: MediaParserVideoCodec;
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 rotate_video_frame_1 = require("./rotate-video-frame");
5
- const canCopyVideoTrack = ({ inputCodec, outputContainer, inputRotation, rotationToApply, inputContainer, }) => {
6
- if ((0, rotate_video_frame_1.normalizeVideoRotation)(inputRotation) !==
7
- (0, rotate_video_frame_1.normalizeVideoRotation)(rotationToApply)) {
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 inputCodec === 'vp8' || inputCodec === 'vp9';
23
+ return (inputTrack.codecWithoutConfig === 'vp8' ||
24
+ inputTrack.codecWithoutConfig === 'vp9');
12
25
  }
13
26
  if (outputContainer === 'mp4') {
14
- return (inputCodec === 'h264' &&
27
+ return (inputTrack.codecWithoutConfig === 'h264' &&
15
28
  (inputContainer === 'mp4' || inputContainer === 'avi'));
16
29
  }
17
30
  if (outputContainer === 'wav') {
@@ -33,6 +33,8 @@ const convertEncodedChunk = (chunk, trackId) => {
33
33
  cts: chunk.timestamp,
34
34
  dts: chunk.timestamp,
35
35
  trackId,
36
+ offset: 0,
37
+ timescale: 1000000,
36
38
  };
37
39
  };
38
40
  exports.convertEncodedChunk = convertEncodedChunk;
@@ -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>;
@@ -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
- rotation: rotate - track.rotation,
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`);
@@ -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 calculateNewDimensionsFromDimensions = ({
3
- width,
190
+ var calculateNewDimensionsFromRotate = ({
4
191
  height,
192
+ width,
5
193
  rotation
6
194
  }) => {
7
- const switchDimensions = rotation % 90 === 0 && rotation % 180 !== 0;
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 { height: newHeight, width: newWidth };
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 rotateVideoFrame = ({
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 % 360 === 0) {
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 } = calculateNewDimensionsFromDimensions({
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
- ctx.rotate(normalized * (Math.PI / 180));
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(inputRotation) !== normalizeVideoRotation(rotationToApply)) {
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 inputCodec === "vp8" || inputCodec === "vp9";
742
+ return inputTrack.codecWithoutConfig === "vp8" || inputTrack.codecWithoutConfig === "vp9";
509
743
  }
510
744
  if (outputContainer === "mp4") {
511
- return inputCodec === "h264" && (inputContainer === "mp4" || inputContainer === "avi");
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
- rotation: rotate - track.rotation
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 = rotateVideoFrame({
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 } = calculateNewDimensionsFromDimensions({
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
- rotateVideoFrame,
1717
- normalizeVideoRotation
1990
+ rotateAndResizeVideoFrame,
1991
+ normalizeVideoRotation,
1992
+ calculateNewDimensionsFromDimensions: calculateNewDimensionsFromRotateAndScale
1718
1993
  };
1719
1994
  setRemotionImported();
1720
1995
  export {