@remotion/webcodecs 4.0.252 → 4.0.254
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.d.ts +3 -2
- package/dist/audio-decoder.js +11 -9
- package/dist/audio-encoder.d.ts +4 -3
- package/dist/audio-encoder.js +10 -9
- package/dist/controller.d.ts +16 -0
- package/dist/controller.js +16 -0
- package/dist/convert-media.d.ts +3 -2
- package/dist/convert-media.js +47 -17
- package/dist/create/matroska/matroska-utils.d.ts +1 -1
- package/dist/emitter.d.ts +20 -0
- package/dist/emitter.js +29 -0
- package/dist/esm/index.mjs +208 -98
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -1
- package/dist/io-manager/io-synchronizer.d.ts +4 -3
- package/dist/io-manager/io-synchronizer.js +19 -14
- package/dist/io-manager/make-timeout-promise.d.ts +6 -1
- package/dist/io-manager/make-timeout-promise.js +23 -5
- package/dist/on-audio-track.d.ts +2 -2
- package/dist/on-audio-track.js +12 -16
- package/dist/on-video-track.d.ts +2 -2
- package/dist/on-video-track.js +10 -14
- package/dist/select-container-creator.d.ts +1 -1
- package/dist/throttled-state-update.d.ts +1 -1
- package/dist/throttled-state-update.js +2 -2
- package/dist/video-decoder.d.ts +3 -2
- package/dist/video-decoder.js +10 -8
- package/dist/video-encoder.d.ts +4 -3
- package/dist/video-encoder.js +9 -8
- package/dist/wav-audio-encoder.d.ts +1 -1
- package/dist/wav-audio-encoder.js +2 -2
- package/dist/webcodecs-controller.d.ts +16 -0
- package/dist/webcodecs-controller.js +16 -0
- package/package.json +5 -5
package/dist/index.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ export { ConvertMediaOnVideoTrackHandler, VideoOperation, } from './on-video-tra
|
|
|
17
17
|
export type { ResizeOperation } from './resizing/mode';
|
|
18
18
|
export { createVideoDecoder, WebCodecsVideoDecoder } from './video-decoder';
|
|
19
19
|
export { createVideoEncoder, WebCodecsVideoEncoder } from './video-encoder';
|
|
20
|
+
export { webcodecsController, WebCodecsController } from './webcodecs-controller';
|
|
20
21
|
export declare const WebCodecsInternals: {
|
|
21
22
|
rotateAndResizeVideoFrame: ({ frame, rotation, videoCodec, resizeOperation, }: {
|
|
22
23
|
frame: VideoFrame;
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
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;
|
|
3
|
+
exports.WebCodecsInternals = exports.webcodecsController = 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
4
|
const rotate_and_resize_video_frame_1 = require("./rotate-and-resize-video-frame");
|
|
5
5
|
const rotation_1 = require("./rotation");
|
|
6
6
|
const set_remotion_imported_1 = require("./set-remotion-imported");
|
|
@@ -36,6 +36,8 @@ var video_decoder_1 = require("./video-decoder");
|
|
|
36
36
|
Object.defineProperty(exports, "createVideoDecoder", { enumerable: true, get: function () { return video_decoder_1.createVideoDecoder; } });
|
|
37
37
|
var video_encoder_1 = require("./video-encoder");
|
|
38
38
|
Object.defineProperty(exports, "createVideoEncoder", { enumerable: true, get: function () { return video_encoder_1.createVideoEncoder; } });
|
|
39
|
+
var webcodecs_controller_1 = require("./webcodecs-controller");
|
|
40
|
+
Object.defineProperty(exports, "webcodecsController", { enumerable: true, get: function () { return webcodecs_controller_1.webcodecsController; } });
|
|
39
41
|
exports.WebCodecsInternals = {
|
|
40
42
|
rotateAndResizeVideoFrame: rotate_and_resize_video_frame_1.rotateAndResizeVideoFrame,
|
|
41
43
|
normalizeVideoRotation: rotate_and_resize_video_frame_1.normalizeVideoRotation,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ProgressTracker } from '../create/progress-tracker';
|
|
2
2
|
import type { LogLevel } from '../log';
|
|
3
|
+
import type { WebCodecsController } from '../webcodecs-controller';
|
|
3
4
|
export declare const makeIoSynchronizer: ({ logLevel, label, progress, }: {
|
|
4
5
|
logLevel: LogLevel;
|
|
5
6
|
label: string;
|
|
@@ -7,13 +8,13 @@ export declare const makeIoSynchronizer: ({ logLevel, label, progress, }: {
|
|
|
7
8
|
}) => {
|
|
8
9
|
inputItem: (timestamp: number, keyFrame: boolean) => void;
|
|
9
10
|
onOutput: (timestamp: number) => void;
|
|
10
|
-
waitFor: ({ unprocessed, unemitted, minimumProgress,
|
|
11
|
+
waitFor: ({ unprocessed, unemitted, minimumProgress, controller, }: {
|
|
11
12
|
unemitted: number;
|
|
12
13
|
unprocessed: number;
|
|
13
14
|
minimumProgress: number | null;
|
|
14
|
-
|
|
15
|
+
controller: WebCodecsController;
|
|
15
16
|
}) => Promise<void>;
|
|
16
|
-
waitForFinish: (
|
|
17
|
+
waitForFinish: (controller: WebCodecsController) => Promise<void>;
|
|
17
18
|
onProcessed: () => void;
|
|
18
19
|
getUnprocessed: () => number;
|
|
19
20
|
};
|
|
@@ -69,17 +69,22 @@ const makeIoSynchronizer = ({ logLevel, label, progress, }) => {
|
|
|
69
69
|
eventEmitter.addEventListener('processed', on);
|
|
70
70
|
return promise;
|
|
71
71
|
};
|
|
72
|
-
const waitFor = async ({ unprocessed, unemitted, minimumProgress,
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
72
|
+
const waitFor = async ({ unprocessed, unemitted, minimumProgress, controller, }) => {
|
|
73
|
+
await controller._internals.checkForAbortAndPause();
|
|
74
|
+
const { timeoutPromise, clear } = (0, make_timeout_promise_1.makeTimeoutPromise)({
|
|
75
|
+
label: () => [
|
|
76
|
+
`Waited too long for ${label} to finish:`,
|
|
77
|
+
`${getUnemittedItems()} unemitted items`,
|
|
78
|
+
`${getUnprocessed()} unprocessed items: ${JSON.stringify(_unprocessed)}`,
|
|
79
|
+
`smallest progress: ${progress.getSmallestProgress()}`,
|
|
80
|
+
`inputs: ${JSON.stringify(inputs)}`,
|
|
81
|
+
`last output: ${lastOutput}`,
|
|
82
|
+
`wanted: ${unemitted} unemitted items, ${unprocessed} unprocessed items, minimum progress ${minimumProgress}`,
|
|
83
|
+
].join('\n'),
|
|
84
|
+
ms: 10000,
|
|
85
|
+
controller,
|
|
86
|
+
});
|
|
87
|
+
controller._internals.signal.addEventListener('abort', clear);
|
|
83
88
|
await Promise.race([
|
|
84
89
|
timeoutPromise,
|
|
85
90
|
Promise.all([
|
|
@@ -102,14 +107,14 @@ const makeIoSynchronizer = ({ logLevel, label, progress, }) => {
|
|
|
102
107
|
})(),
|
|
103
108
|
]),
|
|
104
109
|
]).finally(() => clear());
|
|
105
|
-
signal.removeEventListener('abort', clear);
|
|
110
|
+
controller._internals.signal.removeEventListener('abort', clear);
|
|
106
111
|
};
|
|
107
|
-
const waitForFinish = async (
|
|
112
|
+
const waitForFinish = async (controller) => {
|
|
108
113
|
await waitFor({
|
|
109
114
|
unprocessed: 0,
|
|
110
115
|
unemitted: 0,
|
|
111
116
|
minimumProgress: null,
|
|
112
|
-
|
|
117
|
+
controller,
|
|
113
118
|
});
|
|
114
119
|
};
|
|
115
120
|
const onProcessed = () => {
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
import type { WebCodecsController } from '../webcodecs-controller';
|
|
2
|
+
export declare const makeTimeoutPromise: ({ label, ms, controller, }: {
|
|
3
|
+
label: () => string;
|
|
4
|
+
ms: number;
|
|
5
|
+
controller: WebCodecsController;
|
|
6
|
+
}) => {
|
|
2
7
|
timeoutPromise: Promise<void>;
|
|
3
8
|
clear: () => void;
|
|
4
9
|
};
|
|
@@ -2,16 +2,34 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.makeTimeoutPromise = void 0;
|
|
4
4
|
const with_resolvers_1 = require("../create/with-resolvers");
|
|
5
|
-
const makeTimeoutPromise = (label, ms) => {
|
|
5
|
+
const makeTimeoutPromise = ({ label, ms, controller, }) => {
|
|
6
6
|
const { promise, reject, resolve } = (0, with_resolvers_1.withResolvers)();
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
let timeout = null;
|
|
8
|
+
const set = () => {
|
|
9
|
+
timeout = setTimeout(() => {
|
|
10
|
+
reject(new Error(`${label()} (timed out after ${ms}ms)`));
|
|
11
|
+
}, ms);
|
|
12
|
+
};
|
|
13
|
+
set();
|
|
14
|
+
const onPause = () => {
|
|
15
|
+
if (timeout) {
|
|
16
|
+
clearTimeout(timeout);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
const onResume = () => {
|
|
20
|
+
set();
|
|
21
|
+
};
|
|
22
|
+
controller.addEventListener('pause', onPause);
|
|
23
|
+
controller.addEventListener('resume', onResume);
|
|
10
24
|
return {
|
|
11
25
|
timeoutPromise: promise,
|
|
12
26
|
clear: () => {
|
|
13
|
-
|
|
27
|
+
if (timeout) {
|
|
28
|
+
clearTimeout(timeout);
|
|
29
|
+
}
|
|
14
30
|
resolve();
|
|
31
|
+
controller.removeEventListener('pause', onPause);
|
|
32
|
+
controller.removeEventListener('resume', onResume);
|
|
15
33
|
},
|
|
16
34
|
};
|
|
17
35
|
};
|
package/dist/on-audio-track.d.ts
CHANGED
|
@@ -2,15 +2,15 @@ import { type LogLevel, type OnAudioTrack } from '@remotion/media-parser';
|
|
|
2
2
|
import type { ConvertMediaOnAudioData } from './convert-media';
|
|
3
3
|
import type { MediaFn } from './create/media-fn';
|
|
4
4
|
import type { ProgressTracker } from './create/progress-tracker';
|
|
5
|
-
import Error from './error-cause';
|
|
6
5
|
import type { ConvertMediaAudioCodec } from './get-available-audio-codecs';
|
|
7
6
|
import type { ConvertMediaContainer } from './get-available-containers';
|
|
8
7
|
import type { ConvertMediaOnAudioTrackHandler } from './on-audio-track-handler';
|
|
9
8
|
import type { ConvertMediaProgressFn } from './throttled-state-update';
|
|
9
|
+
import type { WebCodecsController } from './webcodecs-controller';
|
|
10
10
|
export declare const makeAudioTrackHandler: ({ state, defaultAudioCodec: audioCodec, controller, abortConversion, onMediaStateUpdate, onAudioTrack, logLevel, outputContainer, progressTracker, onAudioData, }: {
|
|
11
11
|
state: MediaFn;
|
|
12
12
|
defaultAudioCodec: ConvertMediaAudioCodec | null;
|
|
13
|
-
controller:
|
|
13
|
+
controller: WebCodecsController;
|
|
14
14
|
abortConversion: (errCause: Error) => void;
|
|
15
15
|
onMediaStateUpdate: null | ConvertMediaProgressFn;
|
|
16
16
|
onAudioTrack: ConvertMediaOnAudioTrackHandler | null;
|
package/dist/on-audio-track.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.makeAudioTrackHandler = void 0;
|
|
7
4
|
const media_parser_1 = require("@remotion/media-parser");
|
|
@@ -12,7 +9,6 @@ const audio_encoder_config_1 = require("./audio-encoder-config");
|
|
|
12
9
|
const can_copy_audio_track_1 = require("./can-copy-audio-track");
|
|
13
10
|
const convert_encoded_chunk_1 = require("./convert-encoded-chunk");
|
|
14
11
|
const default_on_audio_track_handler_1 = require("./default-on-audio-track-handler");
|
|
15
|
-
const error_cause_1 = __importDefault(require("./error-cause"));
|
|
16
12
|
const get_default_audio_codec_1 = require("./get-default-audio-codec");
|
|
17
13
|
const log_1 = require("./log");
|
|
18
14
|
const makeAudioTrackHandler = ({ state, defaultAudioCodec: audioCodec, controller, abortConversion, onMediaStateUpdate, onAudioTrack, logLevel, outputContainer, progressTracker, onAudioData, }) => async ({ track, container: inputContainer }) => {
|
|
@@ -33,7 +29,7 @@ const makeAudioTrackHandler = ({ state, defaultAudioCodec: audioCodec, controlle
|
|
|
33
29
|
return null;
|
|
34
30
|
}
|
|
35
31
|
if (audioOperation.type === 'fail') {
|
|
36
|
-
throw new
|
|
32
|
+
throw new Error(`Audio track with ID ${track.trackId} resolved with {"type": "fail"}. This could mean that this audio track could neither be copied to the output container or re-encoded. You have the option to drop the track instead of failing it: https://remotion.dev/docs/webcodecs/track-transformation`);
|
|
37
33
|
}
|
|
38
34
|
if (audioOperation.type === 'copy') {
|
|
39
35
|
const addedTrack = await state.addTrack({
|
|
@@ -73,11 +69,11 @@ const makeAudioTrackHandler = ({ state, defaultAudioCodec: audioCodec, controlle
|
|
|
73
69
|
description: track.description,
|
|
74
70
|
});
|
|
75
71
|
if (!audioEncoderConfig) {
|
|
76
|
-
abortConversion(new
|
|
72
|
+
abortConversion(new Error(`Could not configure audio encoder of track ${track.trackId}`));
|
|
77
73
|
return null;
|
|
78
74
|
}
|
|
79
75
|
if (!audioDecoderConfig) {
|
|
80
|
-
abortConversion(new
|
|
76
|
+
abortConversion(new Error(`Could not configure audio decoder of track ${track.trackId}`));
|
|
81
77
|
return null;
|
|
82
78
|
}
|
|
83
79
|
const codecPrivate = audioOperation.audioCodec === 'aac'
|
|
@@ -121,12 +117,12 @@ const makeAudioTrackHandler = ({ state, defaultAudioCodec: audioCodec, controlle
|
|
|
121
117
|
});
|
|
122
118
|
},
|
|
123
119
|
onError: (err) => {
|
|
124
|
-
abortConversion(new
|
|
120
|
+
abortConversion(new Error(`Audio encoder of ${track.trackId} failed (see .cause of this error)`, {
|
|
125
121
|
cause: err,
|
|
126
122
|
}));
|
|
127
123
|
},
|
|
128
124
|
codec: audioOperation.audioCodec,
|
|
129
|
-
|
|
125
|
+
controller,
|
|
130
126
|
config: audioEncoderConfig,
|
|
131
127
|
logLevel,
|
|
132
128
|
progressTracker,
|
|
@@ -138,19 +134,19 @@ const makeAudioTrackHandler = ({ state, defaultAudioCodec: audioCodec, controlle
|
|
|
138
134
|
: audioData;
|
|
139
135
|
if (newAudioData !== audioData) {
|
|
140
136
|
if (newAudioData.duration !== audioData.duration) {
|
|
141
|
-
throw new
|
|
137
|
+
throw new Error(`onAudioData returned a different duration than the input audio data. Original duration: ${audioData.duration}, new duration: ${newAudioData.duration}`);
|
|
142
138
|
}
|
|
143
139
|
if (newAudioData.numberOfChannels !== audioData.numberOfChannels) {
|
|
144
|
-
throw new
|
|
140
|
+
throw new Error(`onAudioData returned a different number of channels than the input audio data. Original channels: ${audioData.numberOfChannels}, new channels: ${newAudioData.numberOfChannels}`);
|
|
145
141
|
}
|
|
146
142
|
if (newAudioData.sampleRate !== audioData.sampleRate) {
|
|
147
|
-
throw new
|
|
143
|
+
throw new Error(`onAudioData returned a different sample rate than the input audio data. Original sample rate: ${audioData.sampleRate}, new sample rate: ${newAudioData.sampleRate}`);
|
|
148
144
|
}
|
|
149
145
|
if (newAudioData.format !== audioData.format) {
|
|
150
|
-
throw new
|
|
146
|
+
throw new Error(`onAudioData returned a different format than the input audio data. Original format: ${audioData.format}, new format: ${newAudioData.format}`);
|
|
151
147
|
}
|
|
152
148
|
if (newAudioData.timestamp !== audioData.timestamp) {
|
|
153
|
-
throw new
|
|
149
|
+
throw new Error(`onAudioData returned a different timestamp than the input audio data. Original timestamp: ${audioData.timestamp}, new timestamp: ${newAudioData.timestamp}`);
|
|
154
150
|
}
|
|
155
151
|
audioData.close();
|
|
156
152
|
}
|
|
@@ -164,11 +160,11 @@ const makeAudioTrackHandler = ({ state, defaultAudioCodec: audioCodec, controlle
|
|
|
164
160
|
newAudioData.close();
|
|
165
161
|
},
|
|
166
162
|
onError(error) {
|
|
167
|
-
abortConversion(new
|
|
163
|
+
abortConversion(new Error(`Audio decoder of track ${track.trackId} failed. Config: ${JSON.stringify(audioDecoderConfig)} (see .cause of this error)`, {
|
|
168
164
|
cause: error,
|
|
169
165
|
}));
|
|
170
166
|
},
|
|
171
|
-
|
|
167
|
+
controller,
|
|
172
168
|
config: audioDecoderConfig,
|
|
173
169
|
logLevel,
|
|
174
170
|
track,
|
package/dist/on-video-track.d.ts
CHANGED
|
@@ -2,18 +2,18 @@ import type { LogLevel, OnVideoTrack } from '@remotion/media-parser';
|
|
|
2
2
|
import type { ConvertMediaOnVideoFrame } from './convert-media';
|
|
3
3
|
import type { MediaFn } from './create/media-fn';
|
|
4
4
|
import type { ProgressTracker } from './create/progress-tracker';
|
|
5
|
-
import Error from './error-cause';
|
|
6
5
|
import type { ConvertMediaContainer } from './get-available-containers';
|
|
7
6
|
import type { ConvertMediaVideoCodec } from './get-available-video-codecs';
|
|
8
7
|
import type { ConvertMediaOnVideoTrackHandler } from './on-video-track-handler';
|
|
9
8
|
import type { ResizeOperation } from './resizing/mode';
|
|
10
9
|
import type { ConvertMediaProgressFn } from './throttled-state-update';
|
|
10
|
+
import type { WebCodecsController } from './webcodecs-controller';
|
|
11
11
|
export declare const makeVideoTrackHandler: ({ state, onVideoFrame, onMediaStateUpdate, abortConversion, controller, defaultVideoCodec, onVideoTrack, logLevel, outputContainer, rotate, progress, resizeOperation, }: {
|
|
12
12
|
state: MediaFn;
|
|
13
13
|
onVideoFrame: null | ConvertMediaOnVideoFrame;
|
|
14
14
|
onMediaStateUpdate: null | ConvertMediaProgressFn;
|
|
15
15
|
abortConversion: (errCause: Error) => void;
|
|
16
|
-
controller:
|
|
16
|
+
controller: WebCodecsController;
|
|
17
17
|
defaultVideoCodec: ConvertMediaVideoCodec | null;
|
|
18
18
|
onVideoTrack: ConvertMediaOnVideoTrackHandler | null;
|
|
19
19
|
logLevel: LogLevel;
|
package/dist/on-video-track.js
CHANGED
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.makeVideoTrackHandler = void 0;
|
|
7
4
|
const arraybuffer_to_uint8_array_1 = require("./arraybuffer-to-uint8-array");
|
|
8
5
|
const can_copy_video_track_1 = require("./can-copy-video-track");
|
|
9
6
|
const convert_encoded_chunk_1 = require("./convert-encoded-chunk");
|
|
10
7
|
const default_on_video_track_handler_1 = require("./default-on-video-track-handler");
|
|
11
|
-
const error_cause_1 = __importDefault(require("./error-cause"));
|
|
12
8
|
const get_default_video_codec_1 = require("./get-default-video-codec");
|
|
13
9
|
const log_1 = require("./log");
|
|
14
10
|
const on_frame_1 = require("./on-frame");
|
|
@@ -19,8 +15,8 @@ const video_encoder_1 = require("./video-encoder");
|
|
|
19
15
|
const video_encoder_config_1 = require("./video-encoder-config");
|
|
20
16
|
const makeVideoTrackHandler = ({ state, onVideoFrame, onMediaStateUpdate, abortConversion, controller, defaultVideoCodec, onVideoTrack, logLevel, outputContainer, rotate, progress, resizeOperation, }) => async ({ track, container: inputContainer }) => {
|
|
21
17
|
var _a, _b;
|
|
22
|
-
if (controller.signal.aborted) {
|
|
23
|
-
throw new
|
|
18
|
+
if (controller._internals.signal.aborted) {
|
|
19
|
+
throw new Error('Aborted');
|
|
24
20
|
}
|
|
25
21
|
const canCopyTrack = (0, can_copy_video_track_1.canCopyVideoTrack)({
|
|
26
22
|
inputContainer,
|
|
@@ -43,7 +39,7 @@ const makeVideoTrackHandler = ({ state, onVideoFrame, onMediaStateUpdate, abortC
|
|
|
43
39
|
return null;
|
|
44
40
|
}
|
|
45
41
|
if (videoOperation.type === 'fail') {
|
|
46
|
-
throw new
|
|
42
|
+
throw new Error(`Video track with ID ${track.trackId} resolved with {"type": "fail"}. This could mean that this video track could neither be copied to the output container or re-encoded. You have the option to drop the track instead of failing it: https://remotion.dev/docs/webcodecs/track-transformation`);
|
|
47
43
|
}
|
|
48
44
|
if (videoOperation.type === 'copy') {
|
|
49
45
|
log_1.Log.verbose(logLevel, `Copying video track with codec ${track.codec} and timescale ${track.timescale}`);
|
|
@@ -72,7 +68,7 @@ const makeVideoTrackHandler = ({ state, onVideoFrame, onMediaStateUpdate, abortC
|
|
|
72
68
|
};
|
|
73
69
|
}
|
|
74
70
|
if (videoOperation.type !== 'reencode') {
|
|
75
|
-
throw new
|
|
71
|
+
throw new Error(`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"`);
|
|
76
72
|
}
|
|
77
73
|
const rotation = ((_a = videoOperation.rotate) !== null && _a !== void 0 ? _a : rotate) - track.rotation;
|
|
78
74
|
const { height: newHeight, width: newWidth } = (0, rotation_1.calculateNewDimensionsFromRotateAndScale)({
|
|
@@ -90,11 +86,11 @@ const makeVideoTrackHandler = ({ state, onVideoFrame, onMediaStateUpdate, abortC
|
|
|
90
86
|
});
|
|
91
87
|
const videoDecoderConfig = await (0, video_decoder_config_1.getVideoDecoderConfigWithHardwareAcceleration)(track);
|
|
92
88
|
if (videoEncoderConfig === null) {
|
|
93
|
-
abortConversion(new
|
|
89
|
+
abortConversion(new Error(`Could not configure video encoder of track ${track.trackId}`));
|
|
94
90
|
return null;
|
|
95
91
|
}
|
|
96
92
|
if (videoDecoderConfig === null) {
|
|
97
|
-
abortConversion(new
|
|
93
|
+
abortConversion(new Error(`Could not configure video decoder of track ${track.trackId}`));
|
|
98
94
|
return null;
|
|
99
95
|
}
|
|
100
96
|
const { trackNumber } = await state.addTrack({
|
|
@@ -124,11 +120,11 @@ const makeVideoTrackHandler = ({ state, onVideoFrame, onMediaStateUpdate, abortC
|
|
|
124
120
|
});
|
|
125
121
|
},
|
|
126
122
|
onError: (err) => {
|
|
127
|
-
abortConversion(new
|
|
123
|
+
abortConversion(new Error(`Video encoder of track ${track.trackId} failed (see .cause of this error)`, {
|
|
128
124
|
cause: err,
|
|
129
125
|
}));
|
|
130
126
|
},
|
|
131
|
-
|
|
127
|
+
controller,
|
|
132
128
|
config: videoEncoderConfig,
|
|
133
129
|
logLevel,
|
|
134
130
|
outputCodec: videoOperation.videoCodec,
|
|
@@ -149,11 +145,11 @@ const makeVideoTrackHandler = ({ state, onVideoFrame, onMediaStateUpdate, abortC
|
|
|
149
145
|
});
|
|
150
146
|
},
|
|
151
147
|
onError: (err) => {
|
|
152
|
-
abortConversion(new
|
|
148
|
+
abortConversion(new Error(`Video decoder of track ${track.trackId} failed (see .cause of this error)`, {
|
|
153
149
|
cause: err,
|
|
154
150
|
}));
|
|
155
151
|
},
|
|
156
|
-
|
|
152
|
+
controller,
|
|
157
153
|
logLevel,
|
|
158
154
|
progress,
|
|
159
155
|
});
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { ConvertMediaContainer } from './get-available-containers';
|
|
2
|
-
export declare const selectContainerCreator: (container: ConvertMediaContainer) => ({
|
|
2
|
+
export declare const selectContainerCreator: (container: ConvertMediaContainer) => ({ writer, onBytesProgress, onMillisecondsProgress, logLevel, filename, progressTracker, }: import("./create/media-fn").MediaFnGeneratorInput) => Promise<import("./create/media-fn").MediaFn>;
|
|
@@ -8,6 +8,6 @@ type ReturnType = {
|
|
|
8
8
|
export declare const throttledStateUpdate: ({ updateFn, everyMilliseconds, signal, }: {
|
|
9
9
|
updateFn: ConvertMediaOnProgress | null;
|
|
10
10
|
everyMilliseconds: number;
|
|
11
|
-
signal: AbortSignal;
|
|
11
|
+
signal: AbortSignal | null;
|
|
12
12
|
}) => ReturnType;
|
|
13
13
|
export {};
|
|
@@ -33,7 +33,7 @@ const throttledStateUpdate = ({ updateFn, everyMilliseconds, signal, }) => {
|
|
|
33
33
|
const onAbort = () => {
|
|
34
34
|
clearInterval(interval);
|
|
35
35
|
};
|
|
36
|
-
signal.addEventListener('abort', onAbort, { once: true });
|
|
36
|
+
signal === null || signal === void 0 ? void 0 : signal.addEventListener('abort', onAbort, { once: true });
|
|
37
37
|
return {
|
|
38
38
|
get: () => currentState,
|
|
39
39
|
update: (fn) => {
|
|
@@ -41,7 +41,7 @@ const throttledStateUpdate = ({ updateFn, everyMilliseconds, signal, }) => {
|
|
|
41
41
|
},
|
|
42
42
|
stopAndGetLastProgress: () => {
|
|
43
43
|
clearInterval(interval);
|
|
44
|
-
signal.removeEventListener('abort', onAbort);
|
|
44
|
+
signal === null || signal === void 0 ? void 0 : signal.removeEventListener('abort', onAbort);
|
|
45
45
|
return currentState;
|
|
46
46
|
},
|
|
47
47
|
};
|
package/dist/video-decoder.d.ts
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import type { AudioOrVideoSample, LogLevel } from '@remotion/media-parser';
|
|
2
2
|
import type { ProgressTracker } from './create/progress-tracker';
|
|
3
|
+
import type { WebCodecsController } from './webcodecs-controller';
|
|
3
4
|
export type WebCodecsVideoDecoder = {
|
|
4
5
|
processSample: (videoSample: AudioOrVideoSample) => Promise<void>;
|
|
5
6
|
waitForFinish: () => Promise<void>;
|
|
6
7
|
close: () => void;
|
|
7
8
|
flush: () => Promise<void>;
|
|
8
9
|
};
|
|
9
|
-
export declare const createVideoDecoder: ({ onFrame, onError,
|
|
10
|
+
export declare const createVideoDecoder: ({ onFrame, onError, controller, config, logLevel, progress, }: {
|
|
10
11
|
onFrame: (frame: VideoFrame) => Promise<void>;
|
|
11
12
|
onError: (error: DOMException) => void;
|
|
12
|
-
|
|
13
|
+
controller: WebCodecsController;
|
|
13
14
|
config: VideoDecoderConfig;
|
|
14
15
|
logLevel: LogLevel;
|
|
15
16
|
progress: ProgressTracker;
|
package/dist/video-decoder.js
CHANGED
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.createVideoDecoder = void 0;
|
|
4
4
|
const io_synchronizer_1 = require("./io-manager/io-synchronizer");
|
|
5
5
|
const log_1 = require("./log");
|
|
6
|
-
const createVideoDecoder = ({ onFrame, onError,
|
|
6
|
+
const createVideoDecoder = ({ onFrame, onError, controller, config, logLevel, progress, }) => {
|
|
7
7
|
const ioSynchronizer = (0, io_synchronizer_1.makeIoSynchronizer)({
|
|
8
8
|
logLevel,
|
|
9
9
|
label: 'Video decoder',
|
|
@@ -16,17 +16,19 @@ const createVideoDecoder = ({ onFrame, onError, signal, config, logLevel, progre
|
|
|
16
16
|
const abortHandler = () => {
|
|
17
17
|
inputFrame.close();
|
|
18
18
|
};
|
|
19
|
-
signal.addEventListener('abort', abortHandler, {
|
|
19
|
+
controller._internals.signal.addEventListener('abort', abortHandler, {
|
|
20
|
+
once: true,
|
|
21
|
+
});
|
|
20
22
|
outputQueue = outputQueue
|
|
21
23
|
.then(() => {
|
|
22
|
-
if (signal.aborted) {
|
|
24
|
+
if (controller._internals.signal.aborted) {
|
|
23
25
|
return;
|
|
24
26
|
}
|
|
25
27
|
return onFrame(inputFrame);
|
|
26
28
|
})
|
|
27
29
|
.then(() => {
|
|
28
30
|
ioSynchronizer.onProcessed();
|
|
29
|
-
signal.removeEventListener('abort', abortHandler);
|
|
31
|
+
controller._internals.signal.removeEventListener('abort', abortHandler);
|
|
30
32
|
return Promise.resolve();
|
|
31
33
|
})
|
|
32
34
|
.catch((err) => {
|
|
@@ -40,7 +42,7 @@ const createVideoDecoder = ({ onFrame, onError, signal, config, logLevel, progre
|
|
|
40
42
|
});
|
|
41
43
|
const close = () => {
|
|
42
44
|
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
43
|
-
signal.removeEventListener('abort', onAbort);
|
|
45
|
+
controller._internals.signal.removeEventListener('abort', onAbort);
|
|
44
46
|
if (videoDecoder.state === 'closed') {
|
|
45
47
|
return;
|
|
46
48
|
}
|
|
@@ -49,7 +51,7 @@ const createVideoDecoder = ({ onFrame, onError, signal, config, logLevel, progre
|
|
|
49
51
|
const onAbort = () => {
|
|
50
52
|
close();
|
|
51
53
|
};
|
|
52
|
-
signal.addEventListener('abort', onAbort);
|
|
54
|
+
controller._internals.signal.addEventListener('abort', onAbort);
|
|
53
55
|
videoDecoder.configure(config);
|
|
54
56
|
const processSample = async (sample) => {
|
|
55
57
|
var _a, _b;
|
|
@@ -65,7 +67,7 @@ const createVideoDecoder = ({ onFrame, onError, signal, config, logLevel, progre
|
|
|
65
67
|
unemitted: 20,
|
|
66
68
|
unprocessed: 2,
|
|
67
69
|
minimumProgress: sample.timestamp - 10000000,
|
|
68
|
-
|
|
70
|
+
controller,
|
|
69
71
|
});
|
|
70
72
|
if (sample.type === 'key') {
|
|
71
73
|
await videoDecoder.flush();
|
|
@@ -82,7 +84,7 @@ const createVideoDecoder = ({ onFrame, onError, signal, config, logLevel, progre
|
|
|
82
84
|
waitForFinish: async () => {
|
|
83
85
|
await videoDecoder.flush();
|
|
84
86
|
log_1.Log.verbose(logLevel, 'Flushed video decoder');
|
|
85
|
-
await ioSynchronizer.waitForFinish(
|
|
87
|
+
await ioSynchronizer.waitForFinish(controller);
|
|
86
88
|
log_1.Log.verbose(logLevel, 'IO synchro finished');
|
|
87
89
|
await outputQueue;
|
|
88
90
|
log_1.Log.verbose(logLevel, 'Output queue finished');
|
package/dist/video-encoder.d.ts
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type LogLevel } from '@remotion/media-parser';
|
|
2
2
|
import type { ProgressTracker } from './create/progress-tracker';
|
|
3
3
|
import type { ConvertMediaVideoCodec } from './get-available-video-codecs';
|
|
4
|
+
import type { WebCodecsController } from './webcodecs-controller';
|
|
4
5
|
export type WebCodecsVideoEncoder = {
|
|
5
6
|
encodeFrame: (videoFrame: VideoFrame, timestamp: number) => Promise<void>;
|
|
6
7
|
waitForFinish: () => Promise<void>;
|
|
7
8
|
close: () => void;
|
|
8
9
|
flush: () => Promise<void>;
|
|
9
10
|
};
|
|
10
|
-
export declare const createVideoEncoder: ({ onChunk, onError,
|
|
11
|
+
export declare const createVideoEncoder: ({ onChunk, onError, controller, config, logLevel, outputCodec, progress, }: {
|
|
11
12
|
onChunk: (chunk: EncodedVideoChunk, metadata: EncodedVideoChunkMetadata | null) => Promise<void>;
|
|
12
13
|
onError: (error: DOMException) => void;
|
|
13
|
-
|
|
14
|
+
controller: WebCodecsController;
|
|
14
15
|
config: VideoEncoderConfig;
|
|
15
16
|
logLevel: LogLevel;
|
|
16
17
|
outputCodec: ConvertMediaVideoCodec;
|
package/dist/video-encoder.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createVideoEncoder = void 0;
|
|
4
|
+
const media_parser_1 = require("@remotion/media-parser");
|
|
4
5
|
const convert_to_correct_videoframe_1 = require("./convert-to-correct-videoframe");
|
|
5
6
|
const io_synchronizer_1 = require("./io-manager/io-synchronizer");
|
|
6
7
|
const log_1 = require("./log");
|
|
7
|
-
const createVideoEncoder = ({ onChunk, onError,
|
|
8
|
-
if (signal.aborted) {
|
|
9
|
-
throw new
|
|
8
|
+
const createVideoEncoder = ({ onChunk, onError, controller, config, logLevel, outputCodec, progress, }) => {
|
|
9
|
+
if (controller._internals.signal.aborted) {
|
|
10
|
+
throw new media_parser_1.MediaParserAbortError('Not creating video encoder, already aborted');
|
|
10
11
|
}
|
|
11
12
|
const ioSynchronizer = (0, io_synchronizer_1.makeIoSynchronizer)({
|
|
12
13
|
logLevel,
|
|
@@ -24,7 +25,7 @@ const createVideoEncoder = ({ onChunk, onError, signal, config, logLevel, output
|
|
|
24
25
|
ioSynchronizer.onOutput(timestamp);
|
|
25
26
|
outputQueue = outputQueue
|
|
26
27
|
.then(() => {
|
|
27
|
-
if (signal.aborted) {
|
|
28
|
+
if (controller._internals.signal.aborted) {
|
|
28
29
|
return;
|
|
29
30
|
}
|
|
30
31
|
return onChunk(chunk, metadata !== null && metadata !== void 0 ? metadata : null);
|
|
@@ -40,7 +41,7 @@ const createVideoEncoder = ({ onChunk, onError, signal, config, logLevel, output
|
|
|
40
41
|
});
|
|
41
42
|
const close = () => {
|
|
42
43
|
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
43
|
-
signal.removeEventListener('abort', onAbort);
|
|
44
|
+
controller._internals.signal.removeEventListener('abort', onAbort);
|
|
44
45
|
if (encoder.state === 'closed') {
|
|
45
46
|
return;
|
|
46
47
|
}
|
|
@@ -49,7 +50,7 @@ const createVideoEncoder = ({ onChunk, onError, signal, config, logLevel, output
|
|
|
49
50
|
const onAbort = () => {
|
|
50
51
|
close();
|
|
51
52
|
};
|
|
52
|
-
signal.addEventListener('abort', onAbort);
|
|
53
|
+
controller._internals.signal.addEventListener('abort', onAbort);
|
|
53
54
|
log_1.Log.verbose(logLevel, 'Configuring video encoder', config);
|
|
54
55
|
encoder.configure(config);
|
|
55
56
|
let framesProcessed = 0;
|
|
@@ -63,7 +64,7 @@ const createVideoEncoder = ({ onChunk, onError, signal, config, logLevel, output
|
|
|
63
64
|
unemitted: 10,
|
|
64
65
|
unprocessed: 10,
|
|
65
66
|
minimumProgress: frame.timestamp - 10000000,
|
|
66
|
-
|
|
67
|
+
controller,
|
|
67
68
|
});
|
|
68
69
|
// @ts-expect-error - can have changed in the meanwhile
|
|
69
70
|
if (encoder.state === 'closed') {
|
|
@@ -89,7 +90,7 @@ const createVideoEncoder = ({ onChunk, onError, signal, config, logLevel, output
|
|
|
89
90
|
waitForFinish: async () => {
|
|
90
91
|
await encoder.flush();
|
|
91
92
|
await outputQueue;
|
|
92
|
-
await ioSynchronizer.waitForFinish(
|
|
93
|
+
await ioSynchronizer.waitForFinish(controller);
|
|
93
94
|
},
|
|
94
95
|
close,
|
|
95
96
|
flush: async () => {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { AudioEncoderInit, WebCodecsAudioEncoder } from './audio-encoder';
|
|
2
|
-
export declare const getWaveAudioEncoder: ({ onChunk,
|
|
2
|
+
export declare const getWaveAudioEncoder: ({ onChunk, controller, }: Pick<AudioEncoderInit, "onChunk" | "controller">) => WebCodecsAudioEncoder;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getWaveAudioEncoder = void 0;
|
|
4
|
-
const getWaveAudioEncoder = ({ onChunk,
|
|
4
|
+
const getWaveAudioEncoder = ({ onChunk, controller, }) => {
|
|
5
5
|
return {
|
|
6
6
|
close: () => {
|
|
7
7
|
return Promise.resolve();
|
|
8
8
|
},
|
|
9
9
|
encodeFrame: (audioData) => {
|
|
10
|
-
if (signal.aborted) {
|
|
10
|
+
if (controller._internals.signal.aborted) {
|
|
11
11
|
return Promise.resolve();
|
|
12
12
|
}
|
|
13
13
|
const chunk = {
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { MediaParserController } from '@remotion/media-parser';
|
|
2
|
+
export type WebCodecsController = {
|
|
3
|
+
abort: (reason?: any) => void;
|
|
4
|
+
pause: MediaParserController['pause'];
|
|
5
|
+
resume: MediaParserController['resume'];
|
|
6
|
+
addEventListener: MediaParserController['addEventListener'];
|
|
7
|
+
removeEventListener: MediaParserController['removeEventListener'];
|
|
8
|
+
/**
|
|
9
|
+
* @deprecated Not public API
|
|
10
|
+
*/
|
|
11
|
+
_internals: {
|
|
12
|
+
signal: AbortSignal;
|
|
13
|
+
checkForAbortAndPause: MediaParserController['_internals']['checkForAbortAndPause'];
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
export declare const webcodecsController: () => WebCodecsController;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.webcodecsController = void 0;
|
|
4
|
+
const media_parser_1 = require("@remotion/media-parser");
|
|
5
|
+
const webcodecsController = () => {
|
|
6
|
+
const controller = (0, media_parser_1.mediaParserController)();
|
|
7
|
+
return {
|
|
8
|
+
abort: controller.abort,
|
|
9
|
+
pause: controller.pause,
|
|
10
|
+
resume: controller.resume,
|
|
11
|
+
addEventListener: controller.addEventListener,
|
|
12
|
+
removeEventListener: controller.removeEventListener,
|
|
13
|
+
_internals: controller._internals,
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
exports.webcodecsController = webcodecsController;
|