@remotion/webcodecs 4.0.397 → 4.0.399
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/convert-media.d.ts +1 -2
- package/dist/convert-media.js +2 -11
- package/dist/create/iso-base-media/primitives.d.ts +1 -1
- package/dist/esm/index.mjs +3 -92
- package/dist/index.js +0 -2
- package/package.json +4 -5
- package/dist/audio-decoder.d.ts +0 -24
- package/dist/audio-decoder.js +0 -106
- package/dist/can-use-webfs-target.d.ts +0 -1
- package/dist/can-use-webfs-target.js +0 -23
- package/dist/create-frames.d.ts +0 -8
- package/dist/create-frames.js +0 -69
- package/dist/video-decoder.d.ts +0 -23
- package/dist/video-decoder.js +0 -80
package/dist/convert-media.d.ts
CHANGED
|
@@ -34,7 +34,7 @@ export type ConvertMediaOnAudioData = (options: {
|
|
|
34
34
|
audioData: AudioData;
|
|
35
35
|
track: MediaParserAudioTrack;
|
|
36
36
|
}) => Promise<AudioData> | AudioData;
|
|
37
|
-
export declare const convertMedia: <F extends Options<ParseMediaFields>>({ src, onVideoFrame, onAudioData, onProgress: onProgressDoNotCallDirectly, audioCodec, container, videoCodec, controller, onAudioTrack: userAudioResolver, onVideoTrack: userVideoResolver, reader, fields, logLevel, writer, progressIntervalInMs, rotate,
|
|
37
|
+
export declare const convertMedia: <F extends Options<ParseMediaFields>>({ src, onVideoFrame, onAudioData, onProgress: onProgressDoNotCallDirectly, audioCodec, container, videoCodec, controller, onAudioTrack: userAudioResolver, onVideoTrack: userVideoResolver, reader, fields, logLevel, writer, progressIntervalInMs, rotate, resize, onAudioCodec, onContainer, onDimensions, onDurationInSeconds, onFps, onImages, onInternalStats, onIsHdr, onKeyframes, onLocation, onMetadata, onMimeType, onName, onNumberOfAudioChannels, onRotation, onSampleRate, onSize, onSlowAudioBitrate, onSlowDurationInSeconds, onSlowFps, onSlowKeyframes, onSlowNumberOfFrames, onSlowVideoBitrate, onSlowStructure, onTracks, onUnrotatedDimensions, onVideoCodec, onM3uStreams, selectM3uStream, selectM3uAssociatedPlaylists, expectedDurationInSeconds, expectedFrameRate, seekingHints, ...more }: {
|
|
38
38
|
src: ParseMediaOptions<F>["src"];
|
|
39
39
|
container: ConvertMediaContainer;
|
|
40
40
|
onVideoFrame?: ConvertMediaOnVideoFrame;
|
|
@@ -55,7 +55,6 @@ export declare const convertMedia: <F extends Options<ParseMediaFields>>({ src,
|
|
|
55
55
|
progressIntervalInMs?: number;
|
|
56
56
|
rotate?: number;
|
|
57
57
|
resize?: ResizeOperation;
|
|
58
|
-
apiKey?: string | null;
|
|
59
58
|
fields?: F;
|
|
60
59
|
seekingHints?: ParseMediaOptions<F>["seekingHints"];
|
|
61
60
|
} & MediaParserInternalTypes["ParseMediaCallbacks"]) => Promise<ConvertMediaResult>;
|
package/dist/convert-media.js
CHANGED
|
@@ -15,13 +15,11 @@ const with_resolvers_1 = require("./create/with-resolvers");
|
|
|
15
15
|
const generate_output_filename_1 = require("./generate-output-filename");
|
|
16
16
|
const get_available_containers_1 = require("./get-available-containers");
|
|
17
17
|
const get_available_video_codecs_1 = require("./get-available-video-codecs");
|
|
18
|
-
const log_1 = require("./log");
|
|
19
18
|
const on_audio_track_1 = require("./on-audio-track");
|
|
20
19
|
const on_video_track_1 = require("./on-video-track");
|
|
21
|
-
const send_telemetry_event_1 = require("./send-telemetry-event");
|
|
22
20
|
const throttled_state_update_1 = require("./throttled-state-update");
|
|
23
21
|
const webcodecs_controller_1 = require("./webcodecs-controller");
|
|
24
|
-
const convertMedia = async function ({ src, onVideoFrame, onAudioData, onProgress: onProgressDoNotCallDirectly, audioCodec, container, videoCodec, controller = (0, webcodecs_controller_1.webcodecsController)(), onAudioTrack: userAudioResolver, onVideoTrack: userVideoResolver, reader, fields, logLevel = 'info', writer, progressIntervalInMs, rotate,
|
|
22
|
+
const convertMedia = async function ({ src, onVideoFrame, onAudioData, onProgress: onProgressDoNotCallDirectly, audioCodec, container, videoCodec, controller = (0, webcodecs_controller_1.webcodecsController)(), onAudioTrack: userAudioResolver, onVideoTrack: userVideoResolver, reader, fields, logLevel = 'info', writer, progressIntervalInMs, rotate, resize, onAudioCodec, onContainer, onDimensions, onDurationInSeconds, onFps, onImages, onInternalStats, onIsHdr, onKeyframes, onLocation, onMetadata, onMimeType, onName, onNumberOfAudioChannels, onRotation, onSampleRate, onSize, onSlowAudioBitrate, onSlowDurationInSeconds, onSlowFps, onSlowKeyframes, onSlowNumberOfFrames, onSlowVideoBitrate, onSlowStructure, onTracks, onUnrotatedDimensions, onVideoCodec, onM3uStreams, selectM3uStream, selectM3uAssociatedPlaylists, expectedDurationInSeconds, expectedFrameRate, seekingHints, ...more }) {
|
|
25
23
|
if (controller._internals._mediaParserController._internals.signal.aborted) {
|
|
26
24
|
return Promise.reject(new media_parser_1.MediaParserAbortError('Aborted'));
|
|
27
25
|
}
|
|
@@ -188,15 +186,8 @@ const convertMedia = async function ({ src, onVideoFrame, onAudioData, onProgres
|
|
|
188
186
|
finalState: throttledState.get(),
|
|
189
187
|
});
|
|
190
188
|
})
|
|
191
|
-
.then(() => {
|
|
192
|
-
(0, send_telemetry_event_1.sendUsageEvent)({ succeeded: true, apiKey: apiKey ?? null }).catch((err) => {
|
|
193
|
-
log_1.Log.error('Failed to send usage event', err);
|
|
194
|
-
});
|
|
195
|
-
})
|
|
189
|
+
.then(() => { })
|
|
196
190
|
.catch((err) => {
|
|
197
|
-
(0, send_telemetry_event_1.sendUsageEvent)({ succeeded: false, apiKey: apiKey ?? null }).catch((err2) => {
|
|
198
|
-
log_1.Log.error('Failed to send usage event', err2);
|
|
199
|
-
});
|
|
200
191
|
reject(err);
|
|
201
192
|
})
|
|
202
193
|
.finally(() => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const stringsToUint8Array: (str: string) => Uint8Array<
|
|
1
|
+
export declare const stringsToUint8Array: (str: string) => Uint8Array<ArrayBuffer>;
|
|
2
2
|
export declare const numberTo32BitUIntOrInt: (num: number) => Uint8Array<ArrayBuffer>;
|
|
3
3
|
export declare const numberTo64BitUIntOrInt: (num: number | bigint) => Uint8Array<ArrayBuffer>;
|
|
4
4
|
export declare const numberTo32BitUIntOrIntLeading128: (num: number) => Uint8Array<ArrayBuffer>;
|
package/dist/esm/index.mjs
CHANGED
|
@@ -331,21 +331,6 @@ var rotateAndResizeVideoFrame = ({
|
|
|
331
331
|
});
|
|
332
332
|
};
|
|
333
333
|
|
|
334
|
-
// src/set-remotion-imported.ts
|
|
335
|
-
import { VERSION } from "@remotion/media-parser";
|
|
336
|
-
var setRemotionImported = () => {
|
|
337
|
-
if (typeof globalThis === "undefined") {
|
|
338
|
-
return;
|
|
339
|
-
}
|
|
340
|
-
if (globalThis.remotion_imported) {
|
|
341
|
-
return;
|
|
342
|
-
}
|
|
343
|
-
globalThis.remotion_imported = VERSION;
|
|
344
|
-
if (typeof window !== "undefined") {
|
|
345
|
-
window.remotion_imported = `${VERSION}-webcodecs`;
|
|
346
|
-
}
|
|
347
|
-
};
|
|
348
|
-
|
|
349
334
|
// src/audio-encoder.ts
|
|
350
335
|
import {
|
|
351
336
|
MediaParserAbortError
|
|
@@ -1830,7 +1815,7 @@ var createIsoBaseMediaFtyp = ({
|
|
|
1830
1815
|
};
|
|
1831
1816
|
|
|
1832
1817
|
// src/create/iso-base-media/mp4-header.ts
|
|
1833
|
-
import { VERSION
|
|
1818
|
+
import { VERSION } from "@remotion/media-parser";
|
|
1834
1819
|
|
|
1835
1820
|
// src/create/iso-base-media/create-ilst.ts
|
|
1836
1821
|
var createIlst = (items) => {
|
|
@@ -2697,7 +2682,7 @@ var createPaddedMoovAtom = ({
|
|
|
2697
2682
|
hdlr: createHdlr("mdir"),
|
|
2698
2683
|
ilst: createIlst([
|
|
2699
2684
|
createToo("WebCodecs"),
|
|
2700
|
-
createCmt(`Made with @remotion/webcodecs ${
|
|
2685
|
+
createCmt(`Made with @remotion/webcodecs ${VERSION}`)
|
|
2701
2686
|
])
|
|
2702
2687
|
}))
|
|
2703
2688
|
}), headerLength);
|
|
@@ -5245,71 +5230,6 @@ var makeVideoTrackHandler = ({
|
|
|
5245
5230
|
});
|
|
5246
5231
|
};
|
|
5247
5232
|
|
|
5248
|
-
// ../licensing/dist/esm/index.mjs
|
|
5249
|
-
var HOST = "https://www.remotion.pro";
|
|
5250
|
-
var registerUsageEvent = async ({
|
|
5251
|
-
apiKey,
|
|
5252
|
-
host,
|
|
5253
|
-
succeeded,
|
|
5254
|
-
event
|
|
5255
|
-
}) => {
|
|
5256
|
-
const abortController = new AbortController;
|
|
5257
|
-
const timeout = setTimeout(() => {
|
|
5258
|
-
abortController.abort();
|
|
5259
|
-
}, 1e4);
|
|
5260
|
-
try {
|
|
5261
|
-
const res = await fetch(`${HOST}/api/track/register-usage-point`, {
|
|
5262
|
-
method: "POST",
|
|
5263
|
-
body: JSON.stringify({
|
|
5264
|
-
event,
|
|
5265
|
-
apiKey,
|
|
5266
|
-
host,
|
|
5267
|
-
succeeded
|
|
5268
|
-
}),
|
|
5269
|
-
headers: {
|
|
5270
|
-
"Content-Type": "application/json"
|
|
5271
|
-
},
|
|
5272
|
-
signal: abortController.signal
|
|
5273
|
-
});
|
|
5274
|
-
clearTimeout(timeout);
|
|
5275
|
-
const json = await res.json();
|
|
5276
|
-
if (json.success) {
|
|
5277
|
-
return {
|
|
5278
|
-
billable: json.billable,
|
|
5279
|
-
classification: json.classification
|
|
5280
|
-
};
|
|
5281
|
-
}
|
|
5282
|
-
if (!res.ok) {
|
|
5283
|
-
throw new Error(json.error);
|
|
5284
|
-
}
|
|
5285
|
-
const read = await res.json();
|
|
5286
|
-
return read;
|
|
5287
|
-
} catch (err) {
|
|
5288
|
-
clearTimeout(timeout);
|
|
5289
|
-
if (err instanceof Error && err.name === "AbortError") {
|
|
5290
|
-
throw new Error("Request timed out after 10 seconds");
|
|
5291
|
-
}
|
|
5292
|
-
throw err;
|
|
5293
|
-
}
|
|
5294
|
-
};
|
|
5295
|
-
|
|
5296
|
-
// src/send-telemetry-event.ts
|
|
5297
|
-
var sendUsageEvent = async ({
|
|
5298
|
-
apiKey,
|
|
5299
|
-
succeeded
|
|
5300
|
-
}) => {
|
|
5301
|
-
const host = typeof window === "undefined" ? null : typeof window.location === "undefined" ? null : window.location.origin ?? null;
|
|
5302
|
-
if (host === null) {
|
|
5303
|
-
return;
|
|
5304
|
-
}
|
|
5305
|
-
await registerUsageEvent({
|
|
5306
|
-
apiKey,
|
|
5307
|
-
event: "webcodec-conversion",
|
|
5308
|
-
host,
|
|
5309
|
-
succeeded
|
|
5310
|
-
});
|
|
5311
|
-
};
|
|
5312
|
-
|
|
5313
5233
|
// src/throttled-state-update.ts
|
|
5314
5234
|
var throttledStateUpdate = ({
|
|
5315
5235
|
updateFn,
|
|
@@ -5393,7 +5313,6 @@ var convertMedia = async function({
|
|
|
5393
5313
|
writer,
|
|
5394
5314
|
progressIntervalInMs,
|
|
5395
5315
|
rotate,
|
|
5396
|
-
apiKey,
|
|
5397
5316
|
resize,
|
|
5398
5317
|
onAudioCodec,
|
|
5399
5318
|
onContainer,
|
|
@@ -5593,14 +5512,7 @@ var convertMedia = async function({
|
|
|
5593
5512
|
remove: state.remove,
|
|
5594
5513
|
finalState: throttledState.get()
|
|
5595
5514
|
});
|
|
5596
|
-
}).then(() => {
|
|
5597
|
-
sendUsageEvent({ succeeded: true, apiKey: apiKey ?? null }).catch((err) => {
|
|
5598
|
-
Log.error("Failed to send usage event", err);
|
|
5599
|
-
});
|
|
5600
|
-
}).catch((err) => {
|
|
5601
|
-
sendUsageEvent({ succeeded: false, apiKey: apiKey ?? null }).catch((err2) => {
|
|
5602
|
-
Log.error("Failed to send usage event", err2);
|
|
5603
|
-
});
|
|
5515
|
+
}).then(() => {}).catch((err) => {
|
|
5604
5516
|
reject(err);
|
|
5605
5517
|
}).finally(() => {
|
|
5606
5518
|
throttledState.stopAndGetLastProgress();
|
|
@@ -5937,7 +5849,6 @@ var WebCodecsInternals = {
|
|
|
5937
5849
|
rotateAndResizeVideoFrame,
|
|
5938
5850
|
normalizeVideoRotation
|
|
5939
5851
|
};
|
|
5940
|
-
setRemotionImported();
|
|
5941
5852
|
export {
|
|
5942
5853
|
webcodecsController,
|
|
5943
5854
|
rotateAndResizeVideoFrame,
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.WebCodecsInternals = exports.webcodecsController = exports.createVideoEncoder = exports.VideoUndecodableError = exports.AudioUndecodableError = exports.rotateAndResizeVideoFrame = exports.getPartialAudioData = exports.getDefaultVideoCodec = exports.getDefaultAudioCodec = exports.getAvailableVideoCodecs = exports.getAvailableContainers = exports.getAvailableAudioCodecs = exports.extractFrames = exports.defaultOnVideoTrackHandler = exports.defaultOnAudioTrackHandler = exports.createVideoDecoder = exports.createAudioDecoder = exports.convertMedia = exports.convertAudioData = exports.canReencodeVideoTrack = exports.canReencodeAudioTrack = exports.canCopyVideoTrack = exports.canCopyAudioTrack = exports.createAudioEncoder = void 0;
|
|
4
4
|
const rotate_and_resize_video_frame_1 = require("./rotate-and-resize-video-frame");
|
|
5
|
-
const set_remotion_imported_1 = require("./set-remotion-imported");
|
|
6
5
|
var audio_encoder_1 = require("./audio-encoder");
|
|
7
6
|
Object.defineProperty(exports, "createAudioEncoder", { enumerable: true, get: function () { return audio_encoder_1.createAudioEncoder; } });
|
|
8
7
|
var can_copy_audio_track_1 = require("./can-copy-audio-track");
|
|
@@ -52,4 +51,3 @@ exports.WebCodecsInternals = {
|
|
|
52
51
|
rotateAndResizeVideoFrame: rotate_and_resize_video_frame_1.rotateAndResizeVideoFrame,
|
|
53
52
|
normalizeVideoRotation: rotate_and_resize_video_frame_1.normalizeVideoRotation,
|
|
54
53
|
};
|
|
55
|
-
(0, set_remotion_imported_1.setRemotionImported)();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remotion/webcodecs",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.399",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"module": "dist/esm/index.mjs",
|
|
@@ -27,14 +27,13 @@
|
|
|
27
27
|
"author": "Jonny Burger <jonny@remotion.dev>",
|
|
28
28
|
"license": "Remotion License (See https://remotion.dev/docs/webcodecs#license)",
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@remotion/media-parser": "4.0.
|
|
31
|
-
"@remotion/licensing": "4.0.397"
|
|
30
|
+
"@remotion/media-parser": "4.0.399"
|
|
32
31
|
},
|
|
33
32
|
"peerDependencies": {},
|
|
34
33
|
"devDependencies": {
|
|
35
34
|
"@types/dom-webcodecs": "0.1.11",
|
|
36
|
-
"@remotion/example-videos": "4.0.
|
|
37
|
-
"@remotion/eslint-config-internal": "4.0.
|
|
35
|
+
"@remotion/example-videos": "4.0.399",
|
|
36
|
+
"@remotion/eslint-config-internal": "4.0.399",
|
|
38
37
|
"playwright": "1.55.1",
|
|
39
38
|
"vite": "5.4.21",
|
|
40
39
|
"@playwright/test": "1.55.1",
|
package/dist/audio-decoder.d.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import type { MediaParserLogLevel } from '@remotion/media-parser';
|
|
2
|
-
import type { WebCodecsController } from './webcodecs-controller';
|
|
3
|
-
export type WebCodecsAudioDecoder = {
|
|
4
|
-
decode: (audioSample: EncodedAudioChunkInit | EncodedAudioChunk) => void;
|
|
5
|
-
close: () => void;
|
|
6
|
-
flush: () => Promise<void>;
|
|
7
|
-
waitForFinish: () => Promise<void>;
|
|
8
|
-
waitForQueueToBeLessThan: (items: number) => Promise<void>;
|
|
9
|
-
};
|
|
10
|
-
export type CreateAudioDecoderInit = {
|
|
11
|
-
onFrame: (frame: AudioData) => Promise<void> | void;
|
|
12
|
-
onError: (error: Error) => void;
|
|
13
|
-
controller: WebCodecsController | null;
|
|
14
|
-
config: AudioDecoderConfig;
|
|
15
|
-
logLevel: MediaParserLogLevel;
|
|
16
|
-
};
|
|
17
|
-
export declare const internalCreateAudioDecoder: ({ onFrame, onError, controller, config, logLevel, }: CreateAudioDecoderInit) => WebCodecsAudioDecoder;
|
|
18
|
-
export declare const createAudioDecoder: ({ onFrame, onError, controller, track, logLevel, }: {
|
|
19
|
-
track: AudioDecoderConfig;
|
|
20
|
-
onFrame: (frame: AudioData) => Promise<void> | void;
|
|
21
|
-
onError: (error: Error) => void;
|
|
22
|
-
controller?: WebCodecsController | null;
|
|
23
|
-
logLevel?: MediaParserLogLevel;
|
|
24
|
-
}) => WebCodecsAudioDecoder;
|
package/dist/audio-decoder.js
DELETED
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createAudioDecoder = exports.internalCreateAudioDecoder = void 0;
|
|
4
|
-
const get_wave_audio_decoder_1 = require("./get-wave-audio-decoder");
|
|
5
|
-
const io_synchronizer_1 = require("./io-manager/io-synchronizer");
|
|
6
|
-
const internalCreateAudioDecoder = ({ onFrame, onError, controller, config, logLevel, }) => {
|
|
7
|
-
if (controller &&
|
|
8
|
-
controller._internals._mediaParserController._internals.signal.aborted) {
|
|
9
|
-
throw new Error('Not creating audio decoder, already aborted');
|
|
10
|
-
}
|
|
11
|
-
const ioSynchronizer = (0, io_synchronizer_1.makeIoSynchronizer)({
|
|
12
|
-
logLevel,
|
|
13
|
-
label: 'Audio decoder',
|
|
14
|
-
controller,
|
|
15
|
-
});
|
|
16
|
-
if (config.codec === 'pcm-s16') {
|
|
17
|
-
return (0, get_wave_audio_decoder_1.getWaveAudioDecoder)({
|
|
18
|
-
onFrame,
|
|
19
|
-
config,
|
|
20
|
-
sampleFormat: 's16',
|
|
21
|
-
logLevel,
|
|
22
|
-
ioSynchronizer,
|
|
23
|
-
onError,
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
const audioDecoder = new AudioDecoder({
|
|
27
|
-
async output(frame) {
|
|
28
|
-
try {
|
|
29
|
-
await onFrame(frame);
|
|
30
|
-
}
|
|
31
|
-
catch (err) {
|
|
32
|
-
frame.close();
|
|
33
|
-
onError(err);
|
|
34
|
-
}
|
|
35
|
-
ioSynchronizer.onOutput(frame.timestamp + (frame.duration ?? 0));
|
|
36
|
-
},
|
|
37
|
-
error(error) {
|
|
38
|
-
onError(error);
|
|
39
|
-
},
|
|
40
|
-
});
|
|
41
|
-
const close = () => {
|
|
42
|
-
if (controller) {
|
|
43
|
-
controller._internals._mediaParserController._internals.signal.removeEventListener('abort',
|
|
44
|
-
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
45
|
-
onAbort);
|
|
46
|
-
}
|
|
47
|
-
if (audioDecoder.state === 'closed') {
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
audioDecoder.close();
|
|
51
|
-
};
|
|
52
|
-
const onAbort = () => {
|
|
53
|
-
close();
|
|
54
|
-
};
|
|
55
|
-
if (controller) {
|
|
56
|
-
controller._internals._mediaParserController._internals.signal.addEventListener('abort', onAbort);
|
|
57
|
-
}
|
|
58
|
-
audioDecoder.configure(config);
|
|
59
|
-
const processSample = (audioSample) => {
|
|
60
|
-
if (audioDecoder.state === 'closed') {
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
// Don't flush, it messes up the audio
|
|
64
|
-
const chunk = audioSample instanceof EncodedAudioChunk
|
|
65
|
-
? audioSample
|
|
66
|
-
: new EncodedAudioChunk(audioSample);
|
|
67
|
-
audioDecoder.decode(chunk);
|
|
68
|
-
// https://test-streams.mux.dev/x36xhzz/url_0/url_525/193039199_mp4_h264_aac_hd_7.ts
|
|
69
|
-
// has a 16 byte audio sample at the end which chrome does not decode
|
|
70
|
-
// Might be empty audio
|
|
71
|
-
// For now only reporting chunks that are bigger than that
|
|
72
|
-
// 16 was chosen arbitrarily, can be improved
|
|
73
|
-
if (chunk.byteLength > 16) {
|
|
74
|
-
ioSynchronizer.inputItem(chunk.timestamp);
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
|
-
return {
|
|
78
|
-
decode: (sample) => {
|
|
79
|
-
processSample(sample);
|
|
80
|
-
},
|
|
81
|
-
waitForFinish: async () => {
|
|
82
|
-
// Firefox might throw "Needs to be configured first"
|
|
83
|
-
try {
|
|
84
|
-
await audioDecoder.flush();
|
|
85
|
-
}
|
|
86
|
-
catch { }
|
|
87
|
-
await ioSynchronizer.waitForFinish();
|
|
88
|
-
},
|
|
89
|
-
close,
|
|
90
|
-
flush: async () => {
|
|
91
|
-
await audioDecoder.flush();
|
|
92
|
-
},
|
|
93
|
-
waitForQueueToBeLessThan: ioSynchronizer.waitForQueueSize,
|
|
94
|
-
};
|
|
95
|
-
};
|
|
96
|
-
exports.internalCreateAudioDecoder = internalCreateAudioDecoder;
|
|
97
|
-
const createAudioDecoder = ({ onFrame, onError, controller, track, logLevel, }) => {
|
|
98
|
-
return (0, exports.internalCreateAudioDecoder)({
|
|
99
|
-
onFrame,
|
|
100
|
-
onError,
|
|
101
|
-
controller: controller ?? null,
|
|
102
|
-
config: track,
|
|
103
|
-
logLevel: logLevel ?? 'error',
|
|
104
|
-
});
|
|
105
|
-
};
|
|
106
|
-
exports.createAudioDecoder = createAudioDecoder;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const canUseWebFsWriter: () => Promise<boolean>;
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.canUseWebFsWriter = void 0;
|
|
4
|
-
const canUseWebFsWriter = async () => {
|
|
5
|
-
if (!('storage' in navigator)) {
|
|
6
|
-
return false;
|
|
7
|
-
}
|
|
8
|
-
if (!('getDirectory' in navigator.storage)) {
|
|
9
|
-
return false;
|
|
10
|
-
}
|
|
11
|
-
try {
|
|
12
|
-
const directoryHandle = await navigator.storage.getDirectory();
|
|
13
|
-
const fileHandle = await directoryHandle.getFileHandle('remotion-probe-web-fs-support', {
|
|
14
|
-
create: true,
|
|
15
|
-
});
|
|
16
|
-
const canUse = fileHandle.createWritable !== undefined;
|
|
17
|
-
return canUse;
|
|
18
|
-
}
|
|
19
|
-
catch {
|
|
20
|
-
return false;
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
exports.canUseWebFsWriter = canUseWebFsWriter;
|
package/dist/create-frames.d.ts
DELETED
package/dist/create-frames.js
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.extractFrames = void 0;
|
|
4
|
-
const media_parser_1 = require("@remotion/media-parser");
|
|
5
|
-
const worker_1 = require("@remotion/media-parser/worker");
|
|
6
|
-
const create_video_decoder_1 = require("./create-video-decoder");
|
|
7
|
-
const extractFrames = async ({ fromSeconds, toSeconds, width, height, src, onFrame, }) => {
|
|
8
|
-
const controller = (0, media_parser_1.mediaParserController)();
|
|
9
|
-
controller.seek(fromSeconds);
|
|
10
|
-
const segmentDuration = toSeconds - fromSeconds;
|
|
11
|
-
const expectedFrames = [];
|
|
12
|
-
try {
|
|
13
|
-
await (0, worker_1.parseMediaOnWebWorker)({
|
|
14
|
-
src: new URL(src, window.location.href).toString(),
|
|
15
|
-
acknowledgeRemotionLicense: true,
|
|
16
|
-
controller,
|
|
17
|
-
onVideoTrack: ({ track }) => {
|
|
18
|
-
const aspectRatio = track.width / track.height;
|
|
19
|
-
const framesFitInWidth = Math.ceil(width / (height * aspectRatio));
|
|
20
|
-
const timestampTargets = [];
|
|
21
|
-
for (let i = 0; i < framesFitInWidth; i++) {
|
|
22
|
-
timestampTargets.push(fromSeconds +
|
|
23
|
-
((segmentDuration * media_parser_1.WEBCODECS_TIMESCALE) / framesFitInWidth) *
|
|
24
|
-
(i + 0.5));
|
|
25
|
-
}
|
|
26
|
-
const decoder = (0, create_video_decoder_1.createVideoDecoder)({
|
|
27
|
-
onFrame: (frame) => {
|
|
28
|
-
if (frame.timestamp >= expectedFrames[0] - 1) {
|
|
29
|
-
expectedFrames.shift();
|
|
30
|
-
onFrame(frame);
|
|
31
|
-
}
|
|
32
|
-
frame.close();
|
|
33
|
-
},
|
|
34
|
-
onError: console.error,
|
|
35
|
-
track,
|
|
36
|
-
});
|
|
37
|
-
const queued = [];
|
|
38
|
-
return async (sample) => {
|
|
39
|
-
const nextTimestampWeWant = timestampTargets[0];
|
|
40
|
-
if (nextTimestampWeWant === undefined) {
|
|
41
|
-
throw new Error('this should not happen');
|
|
42
|
-
}
|
|
43
|
-
if (sample.type === 'key') {
|
|
44
|
-
queued.length = 0;
|
|
45
|
-
}
|
|
46
|
-
queued.push(sample);
|
|
47
|
-
if (sample.timestamp > nextTimestampWeWant) {
|
|
48
|
-
expectedFrames.push(timestampTargets.shift());
|
|
49
|
-
while (queued.length > 0) {
|
|
50
|
-
const sam = queued.shift();
|
|
51
|
-
await decoder.waitForQueueToBeLessThan(10);
|
|
52
|
-
await decoder.decode(sam);
|
|
53
|
-
}
|
|
54
|
-
if (timestampTargets.length === 0) {
|
|
55
|
-
await decoder.flush();
|
|
56
|
-
controller.abort();
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
};
|
|
60
|
-
},
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
catch (e) {
|
|
64
|
-
if (!(0, media_parser_1.hasBeenAborted)(e)) {
|
|
65
|
-
throw e;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
};
|
|
69
|
-
exports.extractFrames = extractFrames;
|
package/dist/video-decoder.d.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import type { MediaParserLogLevel, MediaParserVideoSample } from '@remotion/media-parser';
|
|
2
|
-
import type { WebCodecsController } from './webcodecs-controller';
|
|
3
|
-
export type WebCodecsVideoDecoder = {
|
|
4
|
-
decode: (videoSample: MediaParserVideoSample | EncodedVideoChunk) => void;
|
|
5
|
-
close: () => void;
|
|
6
|
-
flush: () => Promise<void>;
|
|
7
|
-
waitForFinish: () => Promise<void>;
|
|
8
|
-
waitForQueueToBeLessThan: (items: number) => Promise<void>;
|
|
9
|
-
};
|
|
10
|
-
export declare const internalCreateVideoDecoder: ({ onFrame, onError, controller, config, logLevel, }: {
|
|
11
|
-
onFrame: (frame: VideoFrame) => Promise<void> | void;
|
|
12
|
-
onError: (error: Error) => void;
|
|
13
|
-
controller: WebCodecsController | null;
|
|
14
|
-
config: VideoDecoderConfig;
|
|
15
|
-
logLevel: MediaParserLogLevel;
|
|
16
|
-
}) => WebCodecsVideoDecoder;
|
|
17
|
-
export declare const createVideoDecoder: ({ onFrame, onError, controller, track, logLevel, }: {
|
|
18
|
-
track: VideoDecoderConfig;
|
|
19
|
-
onFrame: (frame: VideoFrame) => Promise<void> | void;
|
|
20
|
-
onError: (error: Error) => void;
|
|
21
|
-
controller?: WebCodecsController;
|
|
22
|
-
logLevel?: MediaParserLogLevel;
|
|
23
|
-
}) => WebCodecsVideoDecoder;
|
package/dist/video-decoder.js
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createVideoDecoder = exports.internalCreateVideoDecoder = void 0;
|
|
4
|
-
const io_synchronizer_1 = require("./io-manager/io-synchronizer");
|
|
5
|
-
const log_1 = require("./log");
|
|
6
|
-
const internalCreateVideoDecoder = ({ onFrame, onError, controller, config, logLevel, }) => {
|
|
7
|
-
const ioSynchronizer = (0, io_synchronizer_1.makeIoSynchronizer)({
|
|
8
|
-
logLevel,
|
|
9
|
-
label: 'Video decoder',
|
|
10
|
-
controller,
|
|
11
|
-
});
|
|
12
|
-
const videoDecoder = new VideoDecoder({
|
|
13
|
-
async output(frame) {
|
|
14
|
-
try {
|
|
15
|
-
await onFrame(frame);
|
|
16
|
-
}
|
|
17
|
-
catch (err) {
|
|
18
|
-
onError(err);
|
|
19
|
-
frame.close();
|
|
20
|
-
}
|
|
21
|
-
ioSynchronizer.onOutput(frame.timestamp);
|
|
22
|
-
},
|
|
23
|
-
error(error) {
|
|
24
|
-
onError(error);
|
|
25
|
-
},
|
|
26
|
-
});
|
|
27
|
-
const close = () => {
|
|
28
|
-
if (controller) {
|
|
29
|
-
controller._internals._mediaParserController._internals.signal.removeEventListener('abort',
|
|
30
|
-
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
31
|
-
onAbort);
|
|
32
|
-
}
|
|
33
|
-
if (videoDecoder.state === 'closed') {
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
videoDecoder.close();
|
|
37
|
-
};
|
|
38
|
-
const onAbort = () => {
|
|
39
|
-
close();
|
|
40
|
-
};
|
|
41
|
-
if (controller) {
|
|
42
|
-
controller._internals._mediaParserController._internals.signal.addEventListener('abort', onAbort);
|
|
43
|
-
}
|
|
44
|
-
videoDecoder.configure(config);
|
|
45
|
-
const decode = (sample) => {
|
|
46
|
-
if (videoDecoder.state === 'closed') {
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
49
|
-
const encodedChunk = sample instanceof EncodedVideoChunk
|
|
50
|
-
? sample
|
|
51
|
-
: new EncodedVideoChunk(sample);
|
|
52
|
-
videoDecoder.decode(encodedChunk);
|
|
53
|
-
ioSynchronizer.inputItem(sample.timestamp);
|
|
54
|
-
};
|
|
55
|
-
return {
|
|
56
|
-
decode,
|
|
57
|
-
waitForFinish: async () => {
|
|
58
|
-
await videoDecoder.flush();
|
|
59
|
-
log_1.Log.verbose(logLevel, 'Flushed video decoder');
|
|
60
|
-
await ioSynchronizer.waitForFinish();
|
|
61
|
-
log_1.Log.verbose(logLevel, 'IO synchro finished');
|
|
62
|
-
},
|
|
63
|
-
close,
|
|
64
|
-
flush: async () => {
|
|
65
|
-
await videoDecoder.flush();
|
|
66
|
-
},
|
|
67
|
-
waitForQueueToBeLessThan: ioSynchronizer.waitForQueueSize,
|
|
68
|
-
};
|
|
69
|
-
};
|
|
70
|
-
exports.internalCreateVideoDecoder = internalCreateVideoDecoder;
|
|
71
|
-
const createVideoDecoder = ({ onFrame, onError, controller, track, logLevel, }) => {
|
|
72
|
-
return (0, exports.internalCreateVideoDecoder)({
|
|
73
|
-
onFrame,
|
|
74
|
-
onError,
|
|
75
|
-
controller: controller ?? null,
|
|
76
|
-
config: track,
|
|
77
|
-
logLevel: logLevel ?? 'info',
|
|
78
|
-
});
|
|
79
|
-
};
|
|
80
|
-
exports.createVideoDecoder = createVideoDecoder;
|