@remotion/webcodecs 4.0.231 → 4.0.233

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 (72) hide show
  1. package/README.md +2 -2
  2. package/dist/audio-decoder-config.d.ts +2 -1
  3. package/dist/audio-decoder-config.js +44 -3
  4. package/dist/audio-decoder.d.ts +6 -3
  5. package/dist/audio-decoder.js +26 -4
  6. package/dist/audio-encoder-config.d.ts +4 -1
  7. package/dist/audio-encoder-config.js +6 -0
  8. package/dist/audio-encoder.d.ts +6 -4
  9. package/dist/audio-encoder.js +15 -3
  10. package/dist/browser-quirks.d.ts +1 -0
  11. package/dist/browser-quirks.js +5 -1
  12. package/dist/can-copy-audio-track.d.ts +1 -1
  13. package/dist/can-copy-audio-track.js +3 -0
  14. package/dist/can-copy-video-track.d.ts +4 -2
  15. package/dist/can-copy-video-track.js +10 -2
  16. package/dist/can-reencode-audio-track.d.ts +4 -3
  17. package/dist/can-reencode-audio-track.js +5 -2
  18. package/dist/can-reencode-video-track.d.ts +1 -1
  19. package/dist/codec-id.d.ts +2 -2
  20. package/dist/codec-id.js +8 -2
  21. package/dist/convert-media.d.ts +5 -2
  22. package/dist/convert-media.js +11 -8
  23. package/dist/convert-to-correct-videoframe.d.ts +1 -1
  24. package/dist/convert-to-correct-videoframe.js +8 -0
  25. package/dist/default-on-video-track-handler.js +12 -2
  26. package/dist/esm/index.mjs +463 -160
  27. package/dist/generate-output-filename.d.ts +1 -1
  28. package/dist/get-available-audio-codecs.d.ts +7 -0
  29. package/dist/get-available-audio-codecs.js +18 -0
  30. package/dist/get-available-containers.d.ts +4 -0
  31. package/dist/get-available-containers.js +8 -0
  32. package/dist/get-available-video-codecs.d.ts +7 -0
  33. package/dist/get-available-video-codecs.js +18 -0
  34. package/dist/get-default-audio-codec.d.ts +2 -1
  35. package/dist/get-default-audio-codec.js +3 -0
  36. package/dist/get-default-video-codec.d.ts +3 -2
  37. package/dist/get-default-video-codec.js +7 -1
  38. package/dist/get-wave-audio-decoder.d.ts +2 -0
  39. package/dist/get-wave-audio-decoder.js +29 -0
  40. package/dist/index.d.ts +10 -1
  41. package/dist/index.js +12 -5
  42. package/dist/io-manager/event-emitter.d.ts +4 -0
  43. package/dist/io-manager/event-emitter.js +1 -0
  44. package/dist/io-manager/io-synchronizer.d.ts +8 -2
  45. package/dist/io-manager/io-synchronizer.js +31 -14
  46. package/dist/io-manager/make-timeout-promise.d.ts +4 -0
  47. package/dist/io-manager/make-timeout-promise.js +18 -0
  48. package/dist/on-audio-track-handler.d.ts +2 -1
  49. package/dist/on-audio-track.d.ts +5 -3
  50. package/dist/on-audio-track.js +9 -4
  51. package/dist/on-frame.d.ts +3 -2
  52. package/dist/on-frame.js +24 -19
  53. package/dist/on-video-track-handler.d.ts +4 -1
  54. package/dist/on-video-track.d.ts +6 -3
  55. package/dist/on-video-track.js +20 -5
  56. package/dist/rotate-video-frame.d.ts +5 -0
  57. package/dist/rotate-video-frame.js +48 -0
  58. package/dist/rotate-video.d.ts +4 -0
  59. package/dist/rotate-video.js +43 -0
  60. package/dist/rotation.d.ts +8 -0
  61. package/dist/rotation.js +10 -0
  62. package/dist/select-container-creator.d.ts +2 -0
  63. package/dist/select-container-creator.js +17 -0
  64. package/dist/test/avi-to-mp4.test.js +15 -0
  65. package/dist/video-decoder.d.ts +3 -2
  66. package/dist/video-decoder.js +11 -3
  67. package/dist/video-encoder-config.d.ts +1 -1
  68. package/dist/video-encoder.d.ts +4 -3
  69. package/dist/video-encoder.js +7 -2
  70. package/dist/wav-audio-encoder.d.ts +2 -0
  71. package/dist/wav-audio-encoder.js +26 -0
  72. package/package.json +5 -3
@@ -1,2 +1,2 @@
1
- import type { ConvertMediaContainer } from './codec-id';
1
+ import type { ConvertMediaContainer } from './get-available-containers';
2
2
  export declare const generateOutputFilename: (source: string | Blob, container: ConvertMediaContainer) => string;
@@ -0,0 +1,7 @@
1
+ import type { ConvertMediaContainer } from './get-available-containers';
2
+ declare const availableAudioCodecs: readonly ["opus", "aac", "wav"];
3
+ export declare const getAvailableAudioCodecs: ({ container, }: {
4
+ container: ConvertMediaContainer;
5
+ }) => ConvertMediaAudioCodec[];
6
+ export type ConvertMediaAudioCodec = (typeof availableAudioCodecs)[number];
7
+ export {};
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getAvailableAudioCodecs = void 0;
4
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
5
+ const availableAudioCodecs = ['opus', 'aac', 'wav'];
6
+ const getAvailableAudioCodecs = ({ container, }) => {
7
+ if (container === 'mp4') {
8
+ return ['aac'];
9
+ }
10
+ if (container === 'webm') {
11
+ return ['opus'];
12
+ }
13
+ if (container === 'wav') {
14
+ return ['wav'];
15
+ }
16
+ throw new Error(`Unsupported container: ${container}`);
17
+ };
18
+ exports.getAvailableAudioCodecs = getAvailableAudioCodecs;
@@ -0,0 +1,4 @@
1
+ declare const availableContainers: readonly ["webm", "mp4", "wav"];
2
+ export type ConvertMediaContainer = (typeof availableContainers)[number];
3
+ export declare const getAvailableContainers: () => readonly ConvertMediaContainer[];
4
+ export {};
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getAvailableContainers = void 0;
4
+ const availableContainers = ['webm', 'mp4', 'wav'];
5
+ const getAvailableContainers = () => {
6
+ return availableContainers;
7
+ };
8
+ exports.getAvailableContainers = getAvailableContainers;
@@ -0,0 +1,7 @@
1
+ import type { ConvertMediaContainer } from './get-available-containers';
2
+ declare const availableVideoCodecs: readonly ["vp8", "vp9", "h264"];
3
+ export type ConvertMediaVideoCodec = (typeof availableVideoCodecs)[number];
4
+ export declare const getAvailableVideoCodecs: ({ container, }: {
5
+ container: ConvertMediaContainer;
6
+ }) => ConvertMediaVideoCodec[];
7
+ export {};
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getAvailableVideoCodecs = void 0;
4
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
5
+ const availableVideoCodecs = ['vp8', 'vp9', 'h264'];
6
+ const getAvailableVideoCodecs = ({ container, }) => {
7
+ if (container === 'mp4') {
8
+ return ['h264'];
9
+ }
10
+ if (container === 'webm') {
11
+ return ['vp8', 'vp9'];
12
+ }
13
+ if (container === 'wav') {
14
+ return [];
15
+ }
16
+ throw new Error(`Unsupported container: ${container}`);
17
+ };
18
+ exports.getAvailableVideoCodecs = getAvailableVideoCodecs;
@@ -1,4 +1,5 @@
1
- import type { ConvertMediaAudioCodec, ConvertMediaContainer } from './codec-id';
1
+ import type { ConvertMediaAudioCodec } from './get-available-audio-codecs';
2
+ import type { ConvertMediaContainer } from './get-available-containers';
2
3
  export declare const getDefaultAudioCodec: ({ container, }: {
3
4
  container: ConvertMediaContainer;
4
5
  }) => ConvertMediaAudioCodec;
@@ -8,6 +8,9 @@ const getDefaultAudioCodec = ({ container, }) => {
8
8
  if (container === 'mp4') {
9
9
  return 'aac';
10
10
  }
11
+ if (container === 'wav') {
12
+ return 'wav';
13
+ }
11
14
  throw new Error(`Unhandled container: ${container}`);
12
15
  };
13
16
  exports.getDefaultAudioCodec = getDefaultAudioCodec;
@@ -1,4 +1,5 @@
1
- import type { ConvertMediaContainer, ConvertMediaVideoCodec } from './codec-id';
1
+ import type { ConvertMediaContainer } from './get-available-containers';
2
+ import type { ConvertMediaVideoCodec } from './get-available-video-codecs';
2
3
  export declare const getDefaultVideoCodec: ({ container, }: {
3
4
  container: ConvertMediaContainer;
4
- }) => ConvertMediaVideoCodec;
5
+ }) => ConvertMediaVideoCodec | null;
@@ -5,6 +5,12 @@ const getDefaultVideoCodec = ({ container, }) => {
5
5
  if (container === 'webm') {
6
6
  return 'vp8';
7
7
  }
8
- throw new Error(`Unhandled container: ${container} satisfies never`);
8
+ if (container === 'mp4') {
9
+ return 'h264';
10
+ }
11
+ if (container === 'wav') {
12
+ return null;
13
+ }
14
+ throw new Error(`Unhandled container: ${container}`);
9
15
  };
10
16
  exports.getDefaultVideoCodec = getDefaultVideoCodec;
@@ -0,0 +1,2 @@
1
+ import type { CreateAudioDecoderInit, WebCodecsAudioDecoder } from './audio-decoder';
2
+ export declare const getWaveAudioDecoder: ({ onFrame, track, }: Pick<CreateAudioDecoderInit, "onFrame" | "track">) => WebCodecsAudioDecoder;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getWaveAudioDecoder = void 0;
4
+ // TODO: Should also be subject to throttling
5
+ const getWaveAudioDecoder = ({ onFrame, track, }) => {
6
+ let queue = Promise.resolve();
7
+ const processSample = async (audioSample) => {
8
+ await onFrame(new AudioData({
9
+ data: audioSample.data,
10
+ format: 's16',
11
+ numberOfChannels: track.numberOfChannels,
12
+ numberOfFrames: audioSample.data.byteLength / 2,
13
+ sampleRate: track.sampleRate,
14
+ timestamp: audioSample.timestamp,
15
+ }));
16
+ };
17
+ return {
18
+ close() {
19
+ return Promise.resolve();
20
+ },
21
+ processSample(audioSample) {
22
+ queue = queue.then(() => processSample(audioSample));
23
+ return queue;
24
+ },
25
+ flush: () => Promise.resolve(),
26
+ waitForFinish: () => Promise.resolve(),
27
+ };
28
+ };
29
+ exports.getWaveAudioDecoder = getWaveAudioDecoder;
package/dist/index.d.ts CHANGED
@@ -4,13 +4,22 @@ export { canCopyAudioTrack } from './can-copy-audio-track';
4
4
  export { canCopyVideoTrack } from './can-copy-video-track';
5
5
  export { canReencodeAudioTrack } from './can-reencode-audio-track';
6
6
  export { canReencodeVideoTrack } from './can-reencode-video-track';
7
- export { ConvertMediaAudioCodec, ConvertMediaContainer, ConvertMediaVideoCodec, getAvailableAudioCodecs, getAvailableContainers, getAvailableVideoCodecs, } from './codec-id';
8
7
  export { convertMedia, ConvertMediaOnProgress, ConvertMediaOnVideoFrame, ConvertMediaProgress, ConvertMediaResult, } from './convert-media';
9
8
  export { defaultOnAudioTrackHandler } from './default-on-audio-track-handler';
10
9
  export { defaultOnVideoTrackHandler } from './default-on-video-track-handler';
10
+ export { ConvertMediaAudioCodec, getAvailableAudioCodecs, } from './get-available-audio-codecs';
11
+ export { ConvertMediaContainer, getAvailableContainers, } from './get-available-containers';
12
+ export { ConvertMediaVideoCodec, getAvailableVideoCodecs, } from './get-available-video-codecs';
11
13
  export { getDefaultAudioCodec } from './get-default-audio-codec';
12
14
  export { getDefaultVideoCodec } from './get-default-video-codec';
13
15
  export { AudioOperation, ConvertMediaOnAudioTrackHandler, } from './on-audio-track-handler';
14
16
  export { ConvertMediaOnVideoTrackHandler, VideoOperation, } from './on-video-track-handler';
15
17
  export { createVideoDecoder, WebCodecsVideoDecoder } from './video-decoder';
16
18
  export { createVideoEncoder, WebCodecsVideoEncoder } from './video-encoder';
19
+ export declare const WebCodecsInternals: {
20
+ rotateVideoFrame: ({ frame, rotation, }: {
21
+ frame: VideoFrame;
22
+ rotation: number;
23
+ }) => VideoFrame;
24
+ normalizeVideoRotation: (rotation: number) => number;
25
+ };
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createVideoEncoder = exports.createVideoDecoder = exports.getDefaultVideoCodec = exports.getDefaultAudioCodec = exports.defaultOnVideoTrackHandler = exports.defaultOnAudioTrackHandler = exports.convertMedia = exports.getAvailableVideoCodecs = exports.getAvailableContainers = exports.getAvailableAudioCodecs = exports.canReencodeVideoTrack = exports.canReencodeAudioTrack = exports.canCopyVideoTrack = exports.canCopyAudioTrack = exports.createAudioEncoder = exports.createAudioDecoder = void 0;
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 rotate_video_frame_1 = require("./rotate-video-frame");
4
5
  const set_remotion_imported_1 = require("./set-remotion-imported");
5
6
  var audio_decoder_1 = require("./audio-decoder");
6
7
  Object.defineProperty(exports, "createAudioDecoder", { enumerable: true, get: function () { return audio_decoder_1.createAudioDecoder; } });
@@ -14,16 +15,18 @@ var can_reencode_audio_track_1 = require("./can-reencode-audio-track");
14
15
  Object.defineProperty(exports, "canReencodeAudioTrack", { enumerable: true, get: function () { return can_reencode_audio_track_1.canReencodeAudioTrack; } });
15
16
  var can_reencode_video_track_1 = require("./can-reencode-video-track");
16
17
  Object.defineProperty(exports, "canReencodeVideoTrack", { enumerable: true, get: function () { return can_reencode_video_track_1.canReencodeVideoTrack; } });
17
- var codec_id_1 = require("./codec-id");
18
- Object.defineProperty(exports, "getAvailableAudioCodecs", { enumerable: true, get: function () { return codec_id_1.getAvailableAudioCodecs; } });
19
- Object.defineProperty(exports, "getAvailableContainers", { enumerable: true, get: function () { return codec_id_1.getAvailableContainers; } });
20
- Object.defineProperty(exports, "getAvailableVideoCodecs", { enumerable: true, get: function () { return codec_id_1.getAvailableVideoCodecs; } });
21
18
  var convert_media_1 = require("./convert-media");
22
19
  Object.defineProperty(exports, "convertMedia", { enumerable: true, get: function () { return convert_media_1.convertMedia; } });
23
20
  var default_on_audio_track_handler_1 = require("./default-on-audio-track-handler");
24
21
  Object.defineProperty(exports, "defaultOnAudioTrackHandler", { enumerable: true, get: function () { return default_on_audio_track_handler_1.defaultOnAudioTrackHandler; } });
25
22
  var default_on_video_track_handler_1 = require("./default-on-video-track-handler");
26
23
  Object.defineProperty(exports, "defaultOnVideoTrackHandler", { enumerable: true, get: function () { return default_on_video_track_handler_1.defaultOnVideoTrackHandler; } });
24
+ var get_available_audio_codecs_1 = require("./get-available-audio-codecs");
25
+ Object.defineProperty(exports, "getAvailableAudioCodecs", { enumerable: true, get: function () { return get_available_audio_codecs_1.getAvailableAudioCodecs; } });
26
+ var get_available_containers_1 = require("./get-available-containers");
27
+ Object.defineProperty(exports, "getAvailableContainers", { enumerable: true, get: function () { return get_available_containers_1.getAvailableContainers; } });
28
+ var get_available_video_codecs_1 = require("./get-available-video-codecs");
29
+ Object.defineProperty(exports, "getAvailableVideoCodecs", { enumerable: true, get: function () { return get_available_video_codecs_1.getAvailableVideoCodecs; } });
27
30
  var get_default_audio_codec_1 = require("./get-default-audio-codec");
28
31
  Object.defineProperty(exports, "getDefaultAudioCodec", { enumerable: true, get: function () { return get_default_audio_codec_1.getDefaultAudioCodec; } });
29
32
  var get_default_video_codec_1 = require("./get-default-video-codec");
@@ -32,4 +35,8 @@ var video_decoder_1 = require("./video-decoder");
32
35
  Object.defineProperty(exports, "createVideoDecoder", { enumerable: true, get: function () { return video_decoder_1.createVideoDecoder; } });
33
36
  var video_encoder_1 = require("./video-encoder");
34
37
  Object.defineProperty(exports, "createVideoEncoder", { enumerable: true, get: function () { return video_encoder_1.createVideoEncoder; } });
38
+ exports.WebCodecsInternals = {
39
+ rotateVideoFrame: rotate_video_frame_1.rotateVideoFrame,
40
+ normalizeVideoRotation: rotate_video_frame_1.normalizeVideoRotation,
41
+ };
35
42
  (0, set_remotion_imported_1.setRemotionImported)();
@@ -6,10 +6,14 @@ type Output = {
6
6
  timestamp: number;
7
7
  };
8
8
  type Processed = {};
9
+ type Progress = {
10
+ smallestProgress: number;
11
+ };
9
12
  type IoEventMap = {
10
13
  input: Input;
11
14
  output: Output;
12
15
  processed: Processed;
16
+ progress: Progress;
13
17
  };
14
18
  export type IoEventTypes = keyof IoEventMap;
15
19
  export type CallbackListener<T extends IoEventTypes> = (data: {
@@ -7,6 +7,7 @@ class IoEventEmitter {
7
7
  input: [],
8
8
  output: [],
9
9
  processed: [],
10
+ progress: [],
10
11
  };
11
12
  }
12
13
  addEventListener(name, callback) {
@@ -1,10 +1,16 @@
1
+ import type { ProgressTracker } from '@remotion/media-parser';
1
2
  import type { LogLevel } from '../log';
2
- export declare const makeIoSynchronizer: (logLevel: LogLevel, label: string) => {
3
+ export declare const makeIoSynchronizer: ({ logLevel, label, progress, }: {
4
+ logLevel: LogLevel;
5
+ label: string;
6
+ progress: ProgressTracker;
7
+ }) => {
3
8
  inputItem: (timestamp: number, keyFrame: boolean) => void;
4
9
  onOutput: (timestamp: number) => void;
5
- waitFor: ({ _unprocessed, unemitted, }: {
10
+ waitFor: ({ _unprocessed, unemitted, minimumProgress, }: {
6
11
  unemitted: number;
7
12
  _unprocessed: number;
13
+ minimumProgress: number | null;
8
14
  }) => Promise<void>;
9
15
  waitForFinish: () => Promise<void>;
10
16
  onProcessed: () => void;
@@ -1,11 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.makeIoSynchronizer = void 0;
4
+ const media_parser_1 = require("@remotion/media-parser");
4
5
  const log_1 = require("../log");
5
- const with_resolvers_1 = require("../with-resolvers");
6
- const event_emitter_1 = require("./event-emitter");
7
- const makeIoSynchronizer = (logLevel, label) => {
8
- const eventEmitter = new event_emitter_1.IoEventEmitter();
6
+ const make_timeout_promise_1 = require("./make-timeout-promise");
7
+ const makeIoSynchronizer = ({ logLevel, label, progress, }) => {
8
+ const eventEmitter = new media_parser_1.MediaParserInternals.IoEventEmitter();
9
9
  let lastInput = 0;
10
10
  let lastInputKeyframe = 0;
11
11
  let lastOutput = 0;
@@ -51,7 +51,7 @@ const makeIoSynchronizer = (logLevel, label) => {
51
51
  printState('Got output');
52
52
  };
53
53
  const waitForOutput = () => {
54
- const { promise, resolve } = (0, with_resolvers_1.withResolvers)();
54
+ const { promise, resolve } = media_parser_1.MediaParserInternals.withResolvers();
55
55
  const on = () => {
56
56
  eventEmitter.removeEventListener('output', on);
57
57
  resolve();
@@ -60,7 +60,7 @@ const makeIoSynchronizer = (logLevel, label) => {
60
60
  return promise;
61
61
  };
62
62
  const waitForProcessed = () => {
63
- const { promise, resolve } = (0, with_resolvers_1.withResolvers)();
63
+ const { promise, resolve } = media_parser_1.MediaParserInternals.withResolvers();
64
64
  const on = () => {
65
65
  eventEmitter.removeEventListener('processed', on);
66
66
  resolve();
@@ -68,16 +68,33 @@ const makeIoSynchronizer = (logLevel, label) => {
68
68
  eventEmitter.addEventListener('processed', on);
69
69
  return promise;
70
70
  };
71
- const waitFor = async ({ _unprocessed, unemitted, }) => {
72
- while (getUnemittedItems() > unemitted) {
73
- await waitForOutput();
74
- }
75
- while (getUnprocessed() > _unprocessed) {
76
- await waitForProcessed();
77
- }
71
+ const waitFor = async ({ _unprocessed, unemitted, minimumProgress, }) => {
72
+ const { timeoutPromise, clear } = (0, make_timeout_promise_1.makeTimeoutPromise)(`Waited too long for ${label}`, 10000);
73
+ await Promise.race([
74
+ timeoutPromise,
75
+ Promise.all([
76
+ (async () => {
77
+ while (getUnemittedItems() > unemitted) {
78
+ await waitForOutput();
79
+ }
80
+ })(),
81
+ (async () => {
82
+ while (getUnprocessed() > _unprocessed) {
83
+ await waitForProcessed();
84
+ }
85
+ })(),
86
+ minimumProgress === null
87
+ ? Promise.resolve()
88
+ : (async () => {
89
+ while (progress.getSmallestProgress() < minimumProgress) {
90
+ await progress.waitForProgress();
91
+ }
92
+ })(),
93
+ ]),
94
+ ]).finally(() => clear());
78
95
  };
79
96
  const waitForFinish = async () => {
80
- await waitFor({ _unprocessed: 0, unemitted: 0 });
97
+ await waitFor({ _unprocessed: 0, unemitted: 0, minimumProgress: null });
81
98
  };
82
99
  const onProcessed = () => {
83
100
  eventEmitter.dispatchEvent('processed', {});
@@ -0,0 +1,4 @@
1
+ export declare const makeTimeoutPromise: (label: string, ms: number) => {
2
+ timeoutPromise: Promise<void>;
3
+ clear: () => void;
4
+ };
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.makeTimeoutPromise = void 0;
4
+ const media_parser_1 = require("@remotion/media-parser");
5
+ const makeTimeoutPromise = (label, ms) => {
6
+ const { promise, reject, resolve } = media_parser_1.MediaParserInternals.withResolvers();
7
+ const timeout = setTimeout(() => {
8
+ reject(new Error(`${label} (timed out after ${ms}ms)`));
9
+ }, ms);
10
+ return {
11
+ timeoutPromise: promise,
12
+ clear: () => {
13
+ clearTimeout(timeout);
14
+ resolve();
15
+ },
16
+ };
17
+ };
18
+ exports.makeTimeoutPromise = makeTimeoutPromise;
@@ -1,5 +1,6 @@
1
1
  import type { AudioTrack, LogLevel } from '@remotion/media-parser';
2
- import type { ConvertMediaAudioCodec, ConvertMediaContainer } from './codec-id';
2
+ import type { ConvertMediaAudioCodec } from './get-available-audio-codecs';
3
+ import type { ConvertMediaContainer } from './get-available-containers';
3
4
  export type AudioOperation = {
4
5
  type: 'reencode';
5
6
  bitrate: number;
@@ -1,9 +1,10 @@
1
- import type { LogLevel, MediaFn, OnAudioTrack } from '@remotion/media-parser';
2
- import type { ConvertMediaAudioCodec, ConvertMediaContainer } from './codec-id';
1
+ import type { LogLevel, MediaFn, OnAudioTrack, ProgressTracker } from '@remotion/media-parser';
3
2
  import Error from './error-cause';
3
+ import type { ConvertMediaAudioCodec } from './get-available-audio-codecs';
4
+ import type { ConvertMediaContainer } from './get-available-containers';
4
5
  import type { ConvertMediaOnAudioTrackHandler } from './on-audio-track-handler';
5
6
  import type { ConvertMediaProgressFn } from './throttled-state-update';
6
- export declare const makeAudioTrackHandler: ({ state, defaultAudioCodec: audioCodec, controller, abortConversion, onMediaStateUpdate, onAudioTrack, logLevel, container, }: {
7
+ export declare const makeAudioTrackHandler: ({ state, defaultAudioCodec: audioCodec, controller, abortConversion, onMediaStateUpdate, onAudioTrack, logLevel, container, progressTracker, }: {
7
8
  state: MediaFn;
8
9
  defaultAudioCodec: ConvertMediaAudioCodec | null;
9
10
  controller: AbortController;
@@ -12,4 +13,5 @@ export declare const makeAudioTrackHandler: ({ state, defaultAudioCodec: audioCo
12
13
  onAudioTrack: ConvertMediaOnAudioTrackHandler | null;
13
14
  logLevel: LogLevel;
14
15
  container: ConvertMediaContainer;
16
+ progressTracker: ProgressTracker;
15
17
  }) => OnAudioTrack;
@@ -12,7 +12,7 @@ const convert_encoded_chunk_1 = require("./convert-encoded-chunk");
12
12
  const default_on_audio_track_handler_1 = require("./default-on-audio-track-handler");
13
13
  const error_cause_1 = __importDefault(require("./error-cause"));
14
14
  const log_1 = require("./log");
15
- const makeAudioTrackHandler = ({ state, defaultAudioCodec: audioCodec, controller, abortConversion, onMediaStateUpdate, onAudioTrack, logLevel, container, }) => async (track) => {
15
+ const makeAudioTrackHandler = ({ state, defaultAudioCodec: audioCodec, controller, abortConversion, onMediaStateUpdate, onAudioTrack, logLevel, container, progressTracker, }) => async (track) => {
16
16
  const audioOperation = await (onAudioTrack !== null && onAudioTrack !== void 0 ? onAudioTrack : default_on_audio_track_handler_1.defaultOnAudioTrackHandler)({
17
17
  defaultAudioCodec: audioCodec,
18
18
  track,
@@ -62,7 +62,7 @@ const makeAudioTrackHandler = ({ state, defaultAudioCodec: audioCodec, controlle
62
62
  numberOfChannels: track.numberOfChannels,
63
63
  sampleRate: track.sampleRate,
64
64
  description: track.description,
65
- });
65
+ }, logLevel);
66
66
  if (!audioEncoderConfig) {
67
67
  abortConversion(new error_cause_1.default(`Could not configure audio encoder of track ${track.trackId}`));
68
68
  return null;
@@ -74,7 +74,9 @@ const makeAudioTrackHandler = ({ state, defaultAudioCodec: audioCodec, controlle
74
74
  const codecPrivate = audioOperation.audioCodec === 'aac' ? new Uint8Array([17, 144]) : null;
75
75
  const { trackNumber } = await state.addTrack({
76
76
  type: 'audio',
77
- codec: audioOperation.audioCodec,
77
+ codec: audioOperation.audioCodec === 'wav'
78
+ ? 'pcm-s16'
79
+ : audioOperation.audioCodec,
78
80
  numberOfChannels: track.numberOfChannels,
79
81
  sampleRate: track.sampleRate,
80
82
  codecPrivate,
@@ -112,6 +114,7 @@ const makeAudioTrackHandler = ({ state, defaultAudioCodec: audioCodec, controlle
112
114
  signal: controller.signal,
113
115
  config: audioEncoderConfig,
114
116
  logLevel,
117
+ progressTracker,
115
118
  });
116
119
  const audioDecoder = (0, audio_decoder_1.createAudioDecoder)({
117
120
  onFrame: async (frame) => {
@@ -125,13 +128,15 @@ const makeAudioTrackHandler = ({ state, defaultAudioCodec: audioCodec, controlle
125
128
  frame.close();
126
129
  },
127
130
  onError(error) {
128
- abortConversion(new error_cause_1.default(`Audio decoder of track ${track.trackId} failed (see .cause of this error)`, {
131
+ abortConversion(new error_cause_1.default(`Audio decoder of track ${track.trackId} failed. Config: ${JSON.stringify(audioDecoderConfig)} (see .cause of this error)`, {
129
132
  cause: error,
130
133
  }));
131
134
  },
132
135
  signal: controller.signal,
133
136
  config: audioDecoderConfig,
134
137
  logLevel,
138
+ track,
139
+ progressTracker,
135
140
  });
136
141
  state.addWaitForFinishPromise(async () => {
137
142
  await audioDecoder.waitForFinish();
@@ -1,11 +1,12 @@
1
1
  import type { VideoTrack } from '@remotion/media-parser';
2
- import type { ConvertMediaVideoCodec } from './codec-id';
3
2
  import type { ConvertMediaOnVideoFrame } from './convert-media';
3
+ import type { ConvertMediaVideoCodec } from './get-available-video-codecs';
4
4
  import type { WebCodecsVideoEncoder } from './video-encoder';
5
- export declare const onFrame: ({ frame, onVideoFrame, videoEncoder, track, outputCodec, }: {
5
+ export declare const onFrame: ({ frame: unrotatedFrame, onVideoFrame, videoEncoder, track, outputCodec, rotation, }: {
6
6
  frame: VideoFrame;
7
7
  onVideoFrame: ConvertMediaOnVideoFrame | null;
8
8
  videoEncoder: WebCodecsVideoEncoder;
9
9
  track: VideoTrack;
10
10
  outputCodec: ConvertMediaVideoCodec;
11
+ rotation: number;
11
12
  }) => Promise<void>;
package/dist/on-frame.js CHANGED
@@ -2,36 +2,41 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.onFrame = void 0;
4
4
  const convert_to_correct_videoframe_1 = require("./convert-to-correct-videoframe");
5
- const onFrame = async ({ frame, onVideoFrame, videoEncoder, track, outputCodec, }) => {
6
- const newFrame = onVideoFrame ? await onVideoFrame({ frame, track }) : frame;
7
- if (newFrame.codedHeight !== frame.displayHeight) {
8
- throw new Error(`Returned VideoFrame of track ${track.trackId} has different codedHeight (${newFrame.codedHeight}) than the input frame displayHeight (${frame.displayHeight})`);
9
- }
10
- if (newFrame.codedWidth !== frame.displayWidth) {
11
- throw new Error(`Returned VideoFrame of track ${track.trackId} has different codedWidth (${newFrame.codedWidth}) than the input frame displayWidth (${frame.displayWidth})`);
5
+ const rotate_video_frame_1 = require("./rotate-video-frame");
6
+ const onFrame = async ({ frame: unrotatedFrame, onVideoFrame, videoEncoder, track, outputCodec, rotation, }) => {
7
+ var _a, _b;
8
+ const rotated = (0, rotate_video_frame_1.rotateVideoFrame)({
9
+ rotation,
10
+ frame: unrotatedFrame,
11
+ });
12
+ if (unrotatedFrame !== rotated) {
13
+ unrotatedFrame.close();
12
14
  }
13
- if (newFrame.displayWidth !== frame.displayWidth) {
14
- throw new Error(`Returned VideoFrame of track ${track.trackId} has different displayWidth (${newFrame.displayWidth}) than the input frame (${newFrame.displayHeight})`);
15
+ const userProcessedFrame = onVideoFrame
16
+ ? await onVideoFrame({ frame: rotated, track })
17
+ : rotated;
18
+ if (userProcessedFrame.displayWidth !== rotated.displayWidth) {
19
+ throw new Error(`Returned VideoFrame of track ${track.trackId} has different displayWidth (${userProcessedFrame.displayWidth}) than the input frame (${userProcessedFrame.displayHeight})`);
15
20
  }
16
- if (newFrame.displayHeight !== frame.displayHeight) {
17
- throw new Error(`Returned VideoFrame of track ${track.trackId} has different displayHeight (${newFrame.displayHeight}) than the input frame (${newFrame.displayHeight})`);
21
+ if (userProcessedFrame.displayHeight !== rotated.displayHeight) {
22
+ throw new Error(`Returned VideoFrame of track ${track.trackId} has different displayHeight (${userProcessedFrame.displayHeight}) than the input frame (${userProcessedFrame.displayHeight})`);
18
23
  }
19
- if (newFrame.timestamp !== frame.timestamp) {
20
- throw new Error(`Returned VideoFrame of track ${track.trackId} has different timestamp (${newFrame.timestamp}) than the input frame (${newFrame.timestamp}). When calling new VideoFrame(), pass {timestamp: frame.timestamp} as second argument`);
24
+ if (userProcessedFrame.timestamp !== rotated.timestamp) {
25
+ throw new Error(`Returned VideoFrame of track ${track.trackId} has different timestamp (${userProcessedFrame.timestamp}) than the input frame (${rotated.timestamp}). When calling new VideoFrame(), pass {timestamp: frame.timestamp} as second argument`);
21
26
  }
22
- if (newFrame.duration !== frame.duration) {
23
- throw new Error(`Returned VideoFrame of track ${track.trackId} has different duration (${newFrame.duration}) than the input frame (${newFrame.duration}). When calling new VideoFrame(), pass {duration: frame.duration} as second argument`);
27
+ if (((_a = userProcessedFrame.duration) !== null && _a !== void 0 ? _a : 0) !== ((_b = rotated.duration) !== null && _b !== void 0 ? _b : 0)) {
28
+ throw new Error(`Returned VideoFrame of track ${track.trackId} has different duration (${userProcessedFrame.duration}) than the input frame (${rotated.duration}). When calling new VideoFrame(), pass {duration: frame.duration} as second argument`);
24
29
  }
25
30
  const fixedFrame = (0, convert_to_correct_videoframe_1.convertToCorrectVideoFrame)({
26
- videoFrame: newFrame,
31
+ videoFrame: userProcessedFrame,
27
32
  outputCodec,
28
33
  });
29
34
  await videoEncoder.encodeFrame(fixedFrame, fixedFrame.timestamp);
30
35
  fixedFrame.close();
31
- if (frame !== newFrame) {
32
- frame.close();
36
+ if (rotated !== userProcessedFrame) {
37
+ rotated.close();
33
38
  }
34
- if (fixedFrame !== newFrame) {
39
+ if (fixedFrame !== userProcessedFrame) {
35
40
  fixedFrame.close();
36
41
  }
37
42
  };
@@ -1,8 +1,10 @@
1
1
  import type { LogLevel, VideoTrack } from '@remotion/media-parser';
2
- import type { ConvertMediaContainer, ConvertMediaVideoCodec } from './codec-id';
2
+ import type { ConvertMediaContainer } from './get-available-containers';
3
+ import type { ConvertMediaVideoCodec } from './get-available-video-codecs';
3
4
  export type VideoOperation = {
4
5
  type: 'reencode';
5
6
  videoCodec: ConvertMediaVideoCodec;
7
+ rotate?: number;
6
8
  } | {
7
9
  type: 'copy';
8
10
  } | {
@@ -15,4 +17,5 @@ export type ConvertMediaOnVideoTrackHandler = (options: {
15
17
  track: VideoTrack;
16
18
  logLevel: LogLevel;
17
19
  container: ConvertMediaContainer;
20
+ rotate: number;
18
21
  }) => VideoOperation | Promise<VideoOperation>;
@@ -1,10 +1,11 @@
1
- import type { LogLevel, MediaFn, OnVideoTrack } from '@remotion/media-parser';
2
- import type { ConvertMediaContainer, ConvertMediaVideoCodec } from './codec-id';
1
+ import type { LogLevel, MediaFn, OnVideoTrack, ProgressTracker } from '@remotion/media-parser';
3
2
  import type { ConvertMediaOnVideoFrame } from './convert-media';
4
3
  import Error from './error-cause';
4
+ import type { ConvertMediaContainer } from './get-available-containers';
5
+ import type { ConvertMediaVideoCodec } from './get-available-video-codecs';
5
6
  import type { ConvertMediaOnVideoTrackHandler } from './on-video-track-handler';
6
7
  import type { ConvertMediaProgressFn } from './throttled-state-update';
7
- export declare const makeVideoTrackHandler: ({ state, onVideoFrame, onMediaStateUpdate, abortConversion, controller, defaultVideoCodec, onVideoTrack, logLevel, container, }: {
8
+ export declare const makeVideoTrackHandler: ({ state, onVideoFrame, onMediaStateUpdate, abortConversion, controller, defaultVideoCodec, onVideoTrack, logLevel, container, rotate, progress, }: {
8
9
  state: MediaFn;
9
10
  onVideoFrame: null | ConvertMediaOnVideoFrame;
10
11
  onMediaStateUpdate: null | ConvertMediaProgressFn;
@@ -14,4 +15,6 @@ export declare const makeVideoTrackHandler: ({ state, onVideoFrame, onMediaState
14
15
  onVideoTrack: ConvertMediaOnVideoTrackHandler | null;
15
16
  logLevel: LogLevel;
16
17
  container: ConvertMediaContainer;
18
+ rotate: number;
19
+ progress: ProgressTracker;
17
20
  }) => OnVideoTrack;