@remotion/webcodecs 4.0.227 → 4.0.229
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-config.js +3 -0
- package/dist/audio-decoder.d.ts +3 -3
- package/dist/audio-decoder.js +23 -29
- package/dist/audio-encoder.d.ts +3 -2
- package/dist/audio-encoder.js +17 -29
- package/dist/auto-select-writer.d.ts +3 -0
- package/dist/auto-select-writer.js +20 -0
- package/dist/calculate-progress.d.ts +4 -0
- package/dist/calculate-progress.js +10 -0
- package/dist/can-copy-audio-track.d.ts +8 -0
- package/dist/can-copy-audio-track.js +10 -0
- package/dist/can-copy-video-track.d.ts +8 -0
- package/dist/can-copy-video-track.js +13 -0
- package/dist/can-reencode-audio-track.d.ts +7 -0
- package/dist/can-reencode-audio-track.js +21 -0
- package/dist/can-reencode-audio.d.ts +7 -0
- package/dist/can-reencode-audio.js +21 -0
- package/dist/can-reencode-video-track.d.ts +6 -0
- package/dist/can-reencode-video-track.js +15 -0
- package/dist/can-reencode-video.d.ts +6 -0
- package/dist/can-reencode-video.js +15 -0
- package/dist/codec-id.d.ts +7 -2
- package/dist/codec-id.js +7 -0
- package/dist/convert-encoded-chunk.d.ts +2 -0
- package/dist/convert-encoded-chunk.js +15 -0
- package/dist/convert-media.d.ts +25 -9
- package/dist/convert-media.js +69 -15
- package/dist/esm/index.mjs +602 -297
- package/dist/event-emitter.d.ts +25 -0
- package/dist/event-emitter.js +23 -0
- package/dist/index.d.ts +8 -1
- package/dist/index.js +12 -1
- package/dist/io-manager/event-emitter.d.ts +27 -0
- package/dist/io-manager/event-emitter.js +24 -0
- package/dist/io-manager/io-synchronizer.d.ts +12 -0
- package/dist/io-manager/io-synchronizer.js +95 -0
- package/dist/log.d.ts +10 -0
- package/dist/log.js +6 -0
- package/dist/on-audio-track.d.ts +6 -5
- package/dist/on-audio-track.js +23 -21
- package/dist/on-frame.d.ts +11 -0
- package/dist/on-frame.js +32 -0
- package/dist/on-video-track.d.ts +8 -6
- package/dist/on-video-track.js +30 -21
- package/dist/polyfill-encoded-audio-chunk.d.ts +3 -0
- package/dist/polyfill-encoded-audio-chunk.js +5 -0
- package/dist/resolve-audio-action.d.ts +15 -11
- package/dist/resolve-audio-action.js +23 -21
- package/dist/resolve-video-action.d.ts +14 -11
- package/dist/resolve-video-action.js +17 -24
- package/dist/video-decoder.d.ts +3 -3
- package/dist/video-decoder.js +23 -28
- package/dist/video-encoder-config.d.ts +6 -1
- package/dist/video-encoder-config.js +6 -1
- package/dist/video-encoder.d.ts +4 -3
- package/dist/video-encoder.js +26 -29
- package/dist/wait-until-return.d.ts +4 -0
- package/dist/wait-until-return.js +14 -0
- package/dist/with-resolvers.d.ts +5 -0
- package/dist/with-resolvers.js +16 -1
- package/package.json +4 -4
|
@@ -5,6 +5,9 @@ const getAudioDecoderConfig = async (config) => {
|
|
|
5
5
|
if (typeof AudioDecoder === 'undefined') {
|
|
6
6
|
return null;
|
|
7
7
|
}
|
|
8
|
+
if (typeof EncodedAudioChunk === 'undefined') {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
8
11
|
if ((await AudioDecoder.isConfigSupported(config)).supported) {
|
|
9
12
|
return config;
|
|
10
13
|
}
|
package/dist/audio-decoder.d.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import type { AudioSample } from '@remotion/media-parser';
|
|
1
|
+
import type { AudioSample, LogLevel } from '@remotion/media-parser';
|
|
2
2
|
export type WebCodecsAudioDecoder = {
|
|
3
3
|
processSample: (audioSample: AudioSample) => Promise<void>;
|
|
4
4
|
waitForFinish: () => Promise<void>;
|
|
5
5
|
close: () => void;
|
|
6
|
-
getQueueSize: () => number;
|
|
7
6
|
flush: () => Promise<void>;
|
|
8
7
|
};
|
|
9
|
-
export declare const createAudioDecoder: ({ onFrame, onError, signal, config, }: {
|
|
8
|
+
export declare const createAudioDecoder: ({ onFrame, onError, signal, config, logLevel, }: {
|
|
10
9
|
onFrame: (frame: AudioData) => Promise<void>;
|
|
11
10
|
onError: (error: DOMException) => void;
|
|
12
11
|
signal: AbortSignal;
|
|
13
12
|
config: AudioDecoderConfig;
|
|
13
|
+
logLevel: LogLevel;
|
|
14
14
|
}) => WebCodecsAudioDecoder;
|
package/dist/audio-decoder.js
CHANGED
|
@@ -1,22 +1,35 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createAudioDecoder = void 0;
|
|
4
|
-
const
|
|
4
|
+
const io_synchronizer_1 = require("./io-manager/io-synchronizer");
|
|
5
|
+
const createAudioDecoder = ({ onFrame, onError, signal, config, logLevel, }) => {
|
|
5
6
|
if (signal.aborted) {
|
|
6
7
|
throw new Error('Not creating audio decoder, already aborted');
|
|
7
8
|
}
|
|
9
|
+
const ioSynchronizer = (0, io_synchronizer_1.makeIoSynchronizer)(logLevel, 'Audio decoder');
|
|
8
10
|
let outputQueue = Promise.resolve();
|
|
9
|
-
let outputQueueSize = 0;
|
|
10
|
-
let dequeueResolver = () => { };
|
|
11
11
|
const audioDecoder = new AudioDecoder({
|
|
12
12
|
output(inputFrame) {
|
|
13
|
-
|
|
13
|
+
ioSynchronizer.onOutput(inputFrame.timestamp);
|
|
14
|
+
const abortHandler = () => {
|
|
15
|
+
inputFrame.close();
|
|
16
|
+
};
|
|
17
|
+
signal.addEventListener('abort', abortHandler, { once: true });
|
|
14
18
|
outputQueue = outputQueue
|
|
15
|
-
.then(() => onFrame(inputFrame))
|
|
16
19
|
.then(() => {
|
|
17
|
-
|
|
18
|
-
|
|
20
|
+
if (signal.aborted) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
return onFrame(inputFrame);
|
|
24
|
+
})
|
|
25
|
+
.then(() => {
|
|
26
|
+
ioSynchronizer.onProcessed();
|
|
27
|
+
signal.removeEventListener('abort', abortHandler);
|
|
19
28
|
return Promise.resolve();
|
|
29
|
+
})
|
|
30
|
+
.catch((err) => {
|
|
31
|
+
inputFrame.close();
|
|
32
|
+
onError(err);
|
|
20
33
|
});
|
|
21
34
|
},
|
|
22
35
|
error(error) {
|
|
@@ -35,34 +48,16 @@ const createAudioDecoder = ({ onFrame, onError, signal, config, }) => {
|
|
|
35
48
|
close();
|
|
36
49
|
};
|
|
37
50
|
signal.addEventListener('abort', onAbort);
|
|
38
|
-
const getQueueSize = () => {
|
|
39
|
-
return audioDecoder.decodeQueueSize + outputQueueSize;
|
|
40
|
-
};
|
|
41
51
|
audioDecoder.configure(config);
|
|
42
|
-
const waitForDequeue = async () => {
|
|
43
|
-
await new Promise((r) => {
|
|
44
|
-
dequeueResolver = r;
|
|
45
|
-
// @ts-expect-error exists
|
|
46
|
-
audioDecoder.addEventListener('dequeue', () => r(), {
|
|
47
|
-
once: true,
|
|
48
|
-
});
|
|
49
|
-
});
|
|
50
|
-
};
|
|
51
|
-
const waitForFinish = async () => {
|
|
52
|
-
while (getQueueSize() > 0) {
|
|
53
|
-
await waitForDequeue();
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
52
|
const processSample = async (audioSample) => {
|
|
57
53
|
if (audioDecoder.state === 'closed') {
|
|
58
54
|
return;
|
|
59
55
|
}
|
|
60
|
-
|
|
61
|
-
await waitForDequeue();
|
|
62
|
-
}
|
|
56
|
+
await ioSynchronizer.waitFor({ unemitted: 100, _unprocessed: 2 });
|
|
63
57
|
// Don't flush, it messes up the audio
|
|
64
58
|
const chunk = new EncodedAudioChunk(audioSample);
|
|
65
59
|
audioDecoder.decode(chunk);
|
|
60
|
+
ioSynchronizer.inputItem(chunk.timestamp, audioSample.type === 'key');
|
|
66
61
|
};
|
|
67
62
|
let queue = Promise.resolve();
|
|
68
63
|
return {
|
|
@@ -72,11 +67,10 @@ const createAudioDecoder = ({ onFrame, onError, signal, config, }) => {
|
|
|
72
67
|
},
|
|
73
68
|
waitForFinish: async () => {
|
|
74
69
|
await audioDecoder.flush();
|
|
75
|
-
await waitForFinish();
|
|
70
|
+
await ioSynchronizer.waitForFinish();
|
|
76
71
|
await outputQueue;
|
|
77
72
|
},
|
|
78
73
|
close,
|
|
79
|
-
getQueueSize,
|
|
80
74
|
flush: async () => {
|
|
81
75
|
await audioDecoder.flush();
|
|
82
76
|
},
|
package/dist/audio-encoder.d.ts
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
|
+
import type { LogLevel } from '@remotion/media-parser';
|
|
1
2
|
import type { ConvertMediaAudioCodec } from './codec-id';
|
|
2
3
|
export type WebCodecsAudioEncoder = {
|
|
3
4
|
encodeFrame: (audioData: AudioData) => Promise<void>;
|
|
4
5
|
waitForFinish: () => Promise<void>;
|
|
5
6
|
close: () => void;
|
|
6
|
-
getQueueSize: () => number;
|
|
7
7
|
flush: () => Promise<void>;
|
|
8
8
|
};
|
|
9
|
-
export declare const createAudioEncoder: ({ onChunk, onError, codec, signal, config: audioEncoderConfig, }: {
|
|
9
|
+
export declare const createAudioEncoder: ({ onChunk, onError, codec, signal, config: audioEncoderConfig, logLevel, }: {
|
|
10
10
|
onChunk: (chunk: EncodedAudioChunk) => Promise<void>;
|
|
11
11
|
onError: (error: DOMException) => void;
|
|
12
12
|
codec: ConvertMediaAudioCodec;
|
|
13
13
|
signal: AbortSignal;
|
|
14
14
|
config: AudioEncoderConfig;
|
|
15
|
+
logLevel: LogLevel;
|
|
15
16
|
}) => WebCodecsAudioEncoder;
|
package/dist/audio-encoder.js
CHANGED
|
@@ -1,22 +1,29 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createAudioEncoder = void 0;
|
|
4
|
-
const
|
|
4
|
+
const io_synchronizer_1 = require("./io-manager/io-synchronizer");
|
|
5
|
+
const createAudioEncoder = ({ onChunk, onError, codec, signal, config: audioEncoderConfig, logLevel, }) => {
|
|
5
6
|
if (signal.aborted) {
|
|
6
7
|
throw new Error('Not creating audio encoder, already aborted');
|
|
7
8
|
}
|
|
9
|
+
const ioSynchronizer = (0, io_synchronizer_1.makeIoSynchronizer)(logLevel, 'Audio encoder');
|
|
8
10
|
let prom = Promise.resolve();
|
|
9
|
-
let outputQueue = 0;
|
|
10
|
-
let dequeueResolver = () => { };
|
|
11
11
|
const encoder = new AudioEncoder({
|
|
12
12
|
output: (chunk) => {
|
|
13
|
-
|
|
13
|
+
ioSynchronizer.onOutput(chunk.timestamp);
|
|
14
14
|
prom = prom
|
|
15
|
-
.then(() => onChunk(chunk))
|
|
16
15
|
.then(() => {
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
if (signal.aborted) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
return onChunk(chunk);
|
|
20
|
+
})
|
|
21
|
+
.then(() => {
|
|
22
|
+
ioSynchronizer.onProcessed();
|
|
19
23
|
return Promise.resolve();
|
|
24
|
+
})
|
|
25
|
+
.catch((err) => {
|
|
26
|
+
onError(err);
|
|
20
27
|
});
|
|
21
28
|
},
|
|
22
29
|
error(error) {
|
|
@@ -38,36 +45,18 @@ const createAudioEncoder = ({ onChunk, onError, codec, signal, config: audioEnco
|
|
|
38
45
|
if (codec !== 'opus') {
|
|
39
46
|
throw new Error('Only `codec: "opus"` is supported currently');
|
|
40
47
|
}
|
|
41
|
-
const getQueueSize = () => {
|
|
42
|
-
return encoder.encodeQueueSize + outputQueue;
|
|
43
|
-
};
|
|
44
48
|
encoder.configure(audioEncoderConfig);
|
|
45
|
-
const waitForDequeue = async () => {
|
|
46
|
-
await new Promise((r) => {
|
|
47
|
-
dequeueResolver = r;
|
|
48
|
-
// @ts-expect-error exists
|
|
49
|
-
encoder.addEventListener('dequeue', () => r(), {
|
|
50
|
-
once: true,
|
|
51
|
-
});
|
|
52
|
-
});
|
|
53
|
-
};
|
|
54
|
-
const waitForFinish = async () => {
|
|
55
|
-
while (getQueueSize() > 0) {
|
|
56
|
-
await waitForDequeue();
|
|
57
|
-
}
|
|
58
|
-
};
|
|
59
49
|
const encodeFrame = async (audioData) => {
|
|
60
50
|
if (encoder.state === 'closed') {
|
|
61
51
|
return;
|
|
62
52
|
}
|
|
63
|
-
|
|
64
|
-
await waitForDequeue();
|
|
65
|
-
}
|
|
53
|
+
await ioSynchronizer.waitFor({ unemitted: 2, _unprocessed: 2 });
|
|
66
54
|
// @ts-expect-error - can have changed in the meanwhile
|
|
67
55
|
if (encoder.state === 'closed') {
|
|
68
56
|
return;
|
|
69
57
|
}
|
|
70
58
|
encoder.encode(audioData);
|
|
59
|
+
ioSynchronizer.inputItem(audioData.timestamp, true);
|
|
71
60
|
};
|
|
72
61
|
let queue = Promise.resolve();
|
|
73
62
|
return {
|
|
@@ -77,11 +66,10 @@ const createAudioEncoder = ({ onChunk, onError, codec, signal, config: audioEnco
|
|
|
77
66
|
},
|
|
78
67
|
waitForFinish: async () => {
|
|
79
68
|
await encoder.flush();
|
|
80
|
-
await waitForFinish();
|
|
69
|
+
await ioSynchronizer.waitForFinish();
|
|
81
70
|
await prom;
|
|
82
71
|
},
|
|
83
72
|
close,
|
|
84
|
-
getQueueSize,
|
|
85
73
|
flush: async () => {
|
|
86
74
|
await encoder.flush();
|
|
87
75
|
},
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.autoSelectWriter = void 0;
|
|
4
|
+
const buffer_1 = require("@remotion/media-parser/buffer");
|
|
5
|
+
const web_fs_1 = require("@remotion/media-parser/web-fs");
|
|
6
|
+
const log_1 = require("./log");
|
|
7
|
+
const autoSelectWriter = async (writer, logLevel) => {
|
|
8
|
+
if (writer) {
|
|
9
|
+
log_1.Log.verbose(logLevel, 'Using writer provided by user');
|
|
10
|
+
return writer;
|
|
11
|
+
}
|
|
12
|
+
log_1.Log.verbose(logLevel, 'Determining best writer');
|
|
13
|
+
if (await (0, web_fs_1.canUseWebFsWriter)()) {
|
|
14
|
+
log_1.Log.verbose(logLevel, 'Using WebFS writer because it is supported');
|
|
15
|
+
return web_fs_1.webFsWriter;
|
|
16
|
+
}
|
|
17
|
+
log_1.Log.verbose(logLevel, 'Using buffer writer because WebFS writer is not supported');
|
|
18
|
+
return buffer_1.bufferWriter;
|
|
19
|
+
};
|
|
20
|
+
exports.autoSelectWriter = autoSelectWriter;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.calculateProgress = void 0;
|
|
4
|
+
const calculateProgress = ({ millisecondsWritten, expectedOutputDurationInMs, }) => {
|
|
5
|
+
if (expectedOutputDurationInMs === null) {
|
|
6
|
+
return null;
|
|
7
|
+
}
|
|
8
|
+
return millisecondsWritten / expectedOutputDurationInMs;
|
|
9
|
+
};
|
|
10
|
+
exports.calculateProgress = calculateProgress;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { MediaParserAudioCodec } from '@remotion/media-parser';
|
|
2
|
+
import type { ConvertMediaAudioCodec } from './codec-id';
|
|
3
|
+
import type { ConvertMediaContainer } from './convert-media';
|
|
4
|
+
export declare const canCopyAudioTrack: ({ inputCodec, outputCodec, container, }: {
|
|
5
|
+
inputCodec: MediaParserAudioCodec;
|
|
6
|
+
outputCodec: ConvertMediaAudioCodec;
|
|
7
|
+
container: ConvertMediaContainer;
|
|
8
|
+
}) => boolean;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.canCopyAudioTrack = void 0;
|
|
4
|
+
const canCopyAudioTrack = ({ inputCodec, outputCodec, container, }) => {
|
|
5
|
+
if (outputCodec === 'opus') {
|
|
6
|
+
return inputCodec === 'opus' && container === 'webm';
|
|
7
|
+
}
|
|
8
|
+
throw new Error(`Unhandled codec: ${outputCodec}`);
|
|
9
|
+
};
|
|
10
|
+
exports.canCopyAudioTrack = canCopyAudioTrack;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { MediaParserVideoCodec } from '@remotion/media-parser';
|
|
2
|
+
import type { ConvertMediaVideoCodec } from './codec-id';
|
|
3
|
+
import type { ConvertMediaContainer } from './convert-media';
|
|
4
|
+
export declare const canCopyVideoTrack: ({ inputCodec, outputCodec, container, }: {
|
|
5
|
+
inputCodec: MediaParserVideoCodec;
|
|
6
|
+
outputCodec: ConvertMediaVideoCodec;
|
|
7
|
+
container: ConvertMediaContainer;
|
|
8
|
+
}) => boolean;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.canCopyVideoTrack = void 0;
|
|
4
|
+
const canCopyVideoTrack = ({ inputCodec, outputCodec, container, }) => {
|
|
5
|
+
if (outputCodec === 'vp8') {
|
|
6
|
+
return inputCodec === 'vp8' && container === 'webm';
|
|
7
|
+
}
|
|
8
|
+
if (outputCodec === 'vp9') {
|
|
9
|
+
return inputCodec === 'vp9' && container === 'webm';
|
|
10
|
+
}
|
|
11
|
+
throw new Error(`Unhandled codec: ${outputCodec}`);
|
|
12
|
+
};
|
|
13
|
+
exports.canCopyVideoTrack = canCopyVideoTrack;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { AudioTrack } from '@remotion/media-parser';
|
|
2
|
+
import type { ConvertMediaAudioCodec } from './codec-id';
|
|
3
|
+
export declare const canReencodeAudioTrack: ({ track, audioCodec, bitrate, }: {
|
|
4
|
+
track: AudioTrack;
|
|
5
|
+
audioCodec: ConvertMediaAudioCodec;
|
|
6
|
+
bitrate: number;
|
|
7
|
+
}) => Promise<boolean>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.canReencodeAudioTrack = void 0;
|
|
4
|
+
const audio_decoder_config_1 = require("./audio-decoder-config");
|
|
5
|
+
const audio_encoder_config_1 = require("./audio-encoder-config");
|
|
6
|
+
const canReencodeAudioTrack = async ({ track, audioCodec, bitrate, }) => {
|
|
7
|
+
const audioDecoderConfig = await (0, audio_decoder_config_1.getAudioDecoderConfig)({
|
|
8
|
+
codec: track.codec,
|
|
9
|
+
numberOfChannels: track.numberOfChannels,
|
|
10
|
+
sampleRate: track.sampleRate,
|
|
11
|
+
description: track.description,
|
|
12
|
+
});
|
|
13
|
+
const audioEncoderConfig = await (0, audio_encoder_config_1.getAudioEncoderConfig)({
|
|
14
|
+
codec: audioCodec,
|
|
15
|
+
numberOfChannels: track.numberOfChannels,
|
|
16
|
+
sampleRate: track.sampleRate,
|
|
17
|
+
bitrate,
|
|
18
|
+
});
|
|
19
|
+
return Boolean(audioDecoderConfig && audioEncoderConfig);
|
|
20
|
+
};
|
|
21
|
+
exports.canReencodeAudioTrack = canReencodeAudioTrack;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { AudioTrack } from '@remotion/media-parser';
|
|
2
|
+
import type { ConvertMediaAudioCodec } from './codec-id';
|
|
3
|
+
export declare const canReencodeAudioTrack: ({ track, audioCodec, bitrate, }: {
|
|
4
|
+
track: AudioTrack;
|
|
5
|
+
audioCodec: ConvertMediaAudioCodec;
|
|
6
|
+
bitrate: number;
|
|
7
|
+
}) => Promise<boolean>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.canReencodeAudioTrack = void 0;
|
|
4
|
+
const audio_decoder_config_1 = require("./audio-decoder-config");
|
|
5
|
+
const audio_encoder_config_1 = require("./audio-encoder-config");
|
|
6
|
+
const canReencodeAudioTrack = async ({ track, audioCodec, bitrate, }) => {
|
|
7
|
+
const audioDecoderConfig = await (0, audio_decoder_config_1.getAudioDecoderConfig)({
|
|
8
|
+
codec: track.codec,
|
|
9
|
+
numberOfChannels: track.numberOfChannels,
|
|
10
|
+
sampleRate: track.sampleRate,
|
|
11
|
+
description: track.description,
|
|
12
|
+
});
|
|
13
|
+
const audioEncoderConfig = await (0, audio_encoder_config_1.getAudioEncoderConfig)({
|
|
14
|
+
codec: audioCodec,
|
|
15
|
+
numberOfChannels: track.numberOfChannels,
|
|
16
|
+
sampleRate: track.sampleRate,
|
|
17
|
+
bitrate,
|
|
18
|
+
});
|
|
19
|
+
return Boolean(audioDecoderConfig && audioEncoderConfig);
|
|
20
|
+
};
|
|
21
|
+
exports.canReencodeAudioTrack = canReencodeAudioTrack;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { VideoTrack } from '@remotion/media-parser';
|
|
2
|
+
import type { ConvertMediaVideoCodec } from './codec-id';
|
|
3
|
+
export declare const canReencodeVideoTrack: ({ videoCodec, track, }: {
|
|
4
|
+
videoCodec: ConvertMediaVideoCodec;
|
|
5
|
+
track: VideoTrack;
|
|
6
|
+
}) => Promise<boolean>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.canReencodeVideoTrack = void 0;
|
|
4
|
+
const video_decoder_config_1 = require("./video-decoder-config");
|
|
5
|
+
const video_encoder_config_1 = require("./video-encoder-config");
|
|
6
|
+
const canReencodeVideoTrack = async ({ videoCodec, track, }) => {
|
|
7
|
+
const videoEncoderConfig = await (0, video_encoder_config_1.getVideoEncoderConfig)({
|
|
8
|
+
codec: videoCodec,
|
|
9
|
+
height: track.displayAspectHeight,
|
|
10
|
+
width: track.displayAspectWidth,
|
|
11
|
+
});
|
|
12
|
+
const videoDecoderConfig = await (0, video_decoder_config_1.getVideoDecoderConfigWithHardwareAcceleration)(track);
|
|
13
|
+
return Boolean(videoDecoderConfig && videoEncoderConfig);
|
|
14
|
+
};
|
|
15
|
+
exports.canReencodeVideoTrack = canReencodeVideoTrack;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { VideoTrack } from '@remotion/media-parser';
|
|
2
|
+
import type { ConvertMediaVideoCodec } from './codec-id';
|
|
3
|
+
export declare const canReencodeVideoTrack: ({ videoCodec, track, }: {
|
|
4
|
+
videoCodec: ConvertMediaVideoCodec;
|
|
5
|
+
track: VideoTrack;
|
|
6
|
+
}) => Promise<boolean>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.canReencodeVideoTrack = void 0;
|
|
4
|
+
const video_decoder_config_1 = require("./video-decoder-config");
|
|
5
|
+
const video_encoder_config_1 = require("./video-encoder-config");
|
|
6
|
+
const canReencodeVideoTrack = async ({ videoCodec, track, }) => {
|
|
7
|
+
const videoEncoderConfig = await (0, video_encoder_config_1.getVideoEncoderConfig)({
|
|
8
|
+
codec: videoCodec,
|
|
9
|
+
height: track.displayAspectHeight,
|
|
10
|
+
width: track.displayAspectWidth,
|
|
11
|
+
});
|
|
12
|
+
const videoDecoderConfig = await (0, video_decoder_config_1.getVideoDecoderConfigWithHardwareAcceleration)(track);
|
|
13
|
+
return Boolean(videoDecoderConfig && videoEncoderConfig);
|
|
14
|
+
};
|
|
15
|
+
exports.canReencodeVideoTrack = canReencodeVideoTrack;
|
package/dist/codec-id.d.ts
CHANGED
|
@@ -1,2 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
1
|
+
declare const availableVideoCodecs: readonly ["vp8", "vp9"];
|
|
2
|
+
export declare const getAvailableVideoCodecs: () => readonly ["vp8", "vp9"];
|
|
3
|
+
export type ConvertMediaVideoCodec = (typeof availableVideoCodecs)[number];
|
|
4
|
+
declare const availableAudioCodecs: readonly ["opus"];
|
|
5
|
+
export declare const getAvailableAudioCodecs: () => readonly ["opus"];
|
|
6
|
+
export type ConvertMediaAudioCodec = (typeof availableAudioCodecs)[number];
|
|
7
|
+
export {};
|
package/dist/codec-id.js
CHANGED
|
@@ -1,2 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getAvailableAudioCodecs = exports.getAvailableVideoCodecs = void 0;
|
|
4
|
+
const availableVideoCodecs = ['vp8', 'vp9'];
|
|
5
|
+
const getAvailableVideoCodecs = () => availableVideoCodecs;
|
|
6
|
+
exports.getAvailableVideoCodecs = getAvailableVideoCodecs;
|
|
7
|
+
const availableAudioCodecs = ['opus'];
|
|
8
|
+
const getAvailableAudioCodecs = () => availableAudioCodecs;
|
|
9
|
+
exports.getAvailableAudioCodecs = getAvailableAudioCodecs;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.convertEncodedChunk = void 0;
|
|
4
|
+
const convertEncodedChunk = (chunk) => {
|
|
5
|
+
var _a;
|
|
6
|
+
const arr = new Uint8Array(chunk.byteLength);
|
|
7
|
+
chunk.copyTo(arr);
|
|
8
|
+
return {
|
|
9
|
+
data: arr,
|
|
10
|
+
duration: (_a = chunk.duration) !== null && _a !== void 0 ? _a : undefined,
|
|
11
|
+
timestamp: chunk.timestamp,
|
|
12
|
+
type: chunk.type,
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
exports.convertEncodedChunk = convertEncodedChunk;
|
package/dist/convert-media.d.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2024 Remotion AG
|
|
3
|
+
* For licensing, see: https://remotion.dev/docs/webcodecs#license
|
|
4
|
+
*/
|
|
5
|
+
import type { LogLevel, Options, ParseMediaDynamicOptions, ParseMediaFields, ParseMediaOptions, VideoTrack, WriterInterface } from '@remotion/media-parser';
|
|
2
6
|
import type { ConvertMediaAudioCodec, ConvertMediaVideoCodec } from './codec-id';
|
|
3
7
|
import { type ResolveAudioActionFn } from './resolve-audio-action';
|
|
4
8
|
import { type ResolveVideoActionFn } from './resolve-video-action';
|
|
@@ -7,20 +11,32 @@ export type ConvertMediaState = {
|
|
|
7
11
|
decodedAudioFrames: number;
|
|
8
12
|
encodedVideoFrames: number;
|
|
9
13
|
encodedAudioFrames: number;
|
|
14
|
+
bytesWritten: number;
|
|
15
|
+
millisecondsWritten: number;
|
|
16
|
+
expectedOutputDurationInMs: number | null;
|
|
17
|
+
overallProgress: number | null;
|
|
10
18
|
};
|
|
11
|
-
export type
|
|
19
|
+
export type ConvertMediaContainer = 'webm';
|
|
12
20
|
export type ConvertMediaResult = {
|
|
13
|
-
save: () => Promise<
|
|
21
|
+
save: () => Promise<Blob>;
|
|
14
22
|
remove: () => Promise<void>;
|
|
15
23
|
};
|
|
16
|
-
export
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
24
|
+
export type ConvertMediaOnMediaStateUpdate = (state: ConvertMediaState) => void;
|
|
25
|
+
export type ConvertMediaOnVideoFrame = (options: {
|
|
26
|
+
frame: VideoFrame;
|
|
27
|
+
track: VideoTrack;
|
|
28
|
+
}) => Promise<VideoFrame> | VideoFrame;
|
|
29
|
+
export declare const convertMedia: <F extends Options<ParseMediaFields>>({ src, onVideoFrame, onMediaStateUpdate: onMediaStateDoNoCallDirectly, audioCodec, container, videoCodec, signal: userPassedAbortSignal, onAudioTrack: userAudioResolver, onVideoTrack: userVideoResolver, reader, fields, logLevel, writer, ...more }: {
|
|
30
|
+
src: ParseMediaOptions<F>["src"];
|
|
31
|
+
container: ConvertMediaContainer;
|
|
32
|
+
onVideoFrame?: ConvertMediaOnVideoFrame;
|
|
33
|
+
onMediaStateUpdate?: ConvertMediaOnMediaStateUpdate;
|
|
21
34
|
videoCodec: ConvertMediaVideoCodec;
|
|
22
35
|
audioCodec: ConvertMediaAudioCodec;
|
|
23
36
|
signal?: AbortSignal;
|
|
24
37
|
onAudioTrack?: ResolveAudioActionFn;
|
|
25
38
|
onVideoTrack?: ResolveVideoActionFn;
|
|
26
|
-
|
|
39
|
+
reader?: ParseMediaOptions<F>["reader"];
|
|
40
|
+
logLevel?: LogLevel;
|
|
41
|
+
writer?: WriterInterface;
|
|
42
|
+
} & ParseMediaDynamicOptions<F>) => Promise<ConvertMediaResult>;
|