@remotion/webcodecs 4.0.305 → 4.0.306
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 +15 -10
- package/dist/audio-decoder.js +49 -52
- package/dist/audio-encoder.d.ts +5 -5
- package/dist/audio-encoder.js +20 -42
- package/dist/convert-media.js +2 -2
- package/dist/copy-audio-track.d.ts +11 -0
- package/dist/copy-audio-track.js +31 -0
- package/dist/copy-video-track.d.ts +11 -0
- package/dist/copy-video-track.js +32 -0
- package/dist/create/event-emitter.d.ts +0 -1
- package/dist/create/progress-tracker.d.ts +0 -2
- package/dist/create/progress-tracker.js +3 -20
- package/dist/esm/index.mjs +560 -470
- package/dist/get-wave-audio-decoder.d.ts +6 -1
- package/dist/get-wave-audio-decoder.js +16 -11
- package/dist/io-manager/io-synchronizer.d.ts +6 -13
- package/dist/io-manager/io-synchronizer.js +31 -72
- package/dist/io-manager/make-timeout-promise.d.ts +1 -1
- package/dist/io-manager/make-timeout-promise.js +8 -4
- package/dist/on-audio-track.d.ts +2 -2
- package/dist/on-audio-track.js +15 -150
- package/dist/on-frame.d.ts +2 -4
- package/dist/on-frame.js +8 -9
- package/dist/on-video-track.d.ts +2 -2
- package/dist/on-video-track.js +18 -129
- package/dist/processing-queue.d.ts +19 -0
- package/dist/processing-queue.js +47 -0
- package/dist/reencode-audio-track.d.ts +18 -0
- package/dist/reencode-audio-track.js +164 -0
- package/dist/reencode-video-track.d.ts +19 -0
- package/dist/reencode-video-track.js +151 -0
- package/dist/sort-video-frames.d.ts +4 -3
- package/dist/sort-video-frames.js +7 -3
- package/dist/video-decoder.d.ts +14 -8
- package/dist/video-decoder.js +37 -72
- package/dist/video-encoder.d.ts +6 -5
- package/dist/video-encoder.js +16 -40
- package/dist/wav-audio-encoder.d.ts +4 -1
- package/dist/wav-audio-encoder.js +3 -2
- package/package.json +5 -5
package/dist/audio-decoder.d.ts
CHANGED
|
@@ -1,19 +1,24 @@
|
|
|
1
|
-
import type { MediaParserAudioSample,
|
|
2
|
-
import type { ProgressTracker } from './create/progress-tracker';
|
|
1
|
+
import type { MediaParserAudioSample, MediaParserLogLevel } from '@remotion/media-parser';
|
|
3
2
|
import type { WebCodecsController } from './webcodecs-controller';
|
|
4
3
|
export type WebCodecsAudioDecoder = {
|
|
5
|
-
|
|
6
|
-
waitForFinish: () => Promise<void>;
|
|
4
|
+
decode: (audioSample: MediaParserAudioSample) => void;
|
|
7
5
|
close: () => void;
|
|
8
6
|
flush: () => Promise<void>;
|
|
7
|
+
waitForFinish: () => Promise<void>;
|
|
8
|
+
waitForQueueToBeLessThan: (items: number) => Promise<void>;
|
|
9
9
|
};
|
|
10
10
|
export type CreateAudioDecoderInit = {
|
|
11
|
-
onFrame: (frame: AudioData) => Promise<void
|
|
12
|
-
onError: (error:
|
|
13
|
-
controller: WebCodecsController;
|
|
11
|
+
onFrame: (frame: AudioData) => Promise<void> | void;
|
|
12
|
+
onError: (error: Error) => void;
|
|
13
|
+
controller: WebCodecsController | null;
|
|
14
14
|
config: AudioDecoderConfig;
|
|
15
15
|
logLevel: MediaParserLogLevel;
|
|
16
|
-
track: MediaParserAudioTrack;
|
|
17
|
-
progressTracker: ProgressTracker;
|
|
18
16
|
};
|
|
19
|
-
export declare const
|
|
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 | EncodedAudioChunk) => Promise<void> | void;
|
|
21
|
+
onError: (error: Error) => void;
|
|
22
|
+
controller?: WebCodecsController | null;
|
|
23
|
+
logLevel?: MediaParserLogLevel;
|
|
24
|
+
}) => WebCodecsAudioDecoder;
|
package/dist/audio-decoder.js
CHANGED
|
@@ -1,56 +1,49 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createAudioDecoder = void 0;
|
|
3
|
+
exports.createAudioDecoder = exports.internalCreateAudioDecoder = void 0;
|
|
4
4
|
const get_wave_audio_decoder_1 = require("./get-wave-audio-decoder");
|
|
5
5
|
const io_synchronizer_1 = require("./io-manager/io-synchronizer");
|
|
6
|
-
const
|
|
7
|
-
if (controller
|
|
6
|
+
const internalCreateAudioDecoder = ({ onFrame, onError, controller, config, logLevel, }) => {
|
|
7
|
+
if (controller &&
|
|
8
|
+
controller._internals._mediaParserController._internals.signal.aborted) {
|
|
8
9
|
throw new Error('Not creating audio decoder, already aborted');
|
|
9
10
|
}
|
|
10
|
-
if (config.codec === 'pcm-s16') {
|
|
11
|
-
return (0, get_wave_audio_decoder_1.getWaveAudioDecoder)({ onFrame, track, sampleFormat: 's16' });
|
|
12
|
-
}
|
|
13
11
|
const ioSynchronizer = (0, io_synchronizer_1.makeIoSynchronizer)({
|
|
14
12
|
logLevel,
|
|
15
13
|
label: 'Audio decoder',
|
|
16
|
-
|
|
14
|
+
controller,
|
|
17
15
|
});
|
|
18
|
-
|
|
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
|
+
}
|
|
19
26
|
const audioDecoder = new AudioDecoder({
|
|
20
|
-
output(frame) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
controller._internals._mediaParserController._internals.signal.addEventListener('abort', abortHandler, {
|
|
26
|
-
once: true,
|
|
27
|
-
});
|
|
28
|
-
outputQueue = outputQueue
|
|
29
|
-
.then(() => {
|
|
30
|
-
if (controller._internals._mediaParserController._internals.signal
|
|
31
|
-
.aborted) {
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
return onFrame(frame);
|
|
35
|
-
})
|
|
36
|
-
.then(() => {
|
|
37
|
-
ioSynchronizer.onProcessed();
|
|
38
|
-
controller._internals._mediaParserController._internals.signal.removeEventListener('abort', abortHandler);
|
|
39
|
-
return Promise.resolve();
|
|
40
|
-
})
|
|
41
|
-
.catch((err) => {
|
|
27
|
+
async output(frame) {
|
|
28
|
+
try {
|
|
29
|
+
await onFrame(frame);
|
|
30
|
+
}
|
|
31
|
+
catch (err) {
|
|
42
32
|
frame.close();
|
|
43
33
|
onError(err);
|
|
44
|
-
}
|
|
34
|
+
}
|
|
35
|
+
ioSynchronizer.onOutput(frame.timestamp + (frame.duration ?? 0));
|
|
45
36
|
},
|
|
46
37
|
error(error) {
|
|
47
38
|
onError(error);
|
|
48
39
|
},
|
|
49
40
|
});
|
|
50
41
|
const close = () => {
|
|
51
|
-
controller
|
|
52
|
-
|
|
53
|
-
|
|
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
|
+
}
|
|
54
47
|
if (audioDecoder.state === 'closed') {
|
|
55
48
|
return;
|
|
56
49
|
}
|
|
@@ -59,21 +52,18 @@ const createAudioDecoder = ({ onFrame, onError, controller, config, logLevel, tr
|
|
|
59
52
|
const onAbort = () => {
|
|
60
53
|
close();
|
|
61
54
|
};
|
|
62
|
-
controller
|
|
55
|
+
if (controller) {
|
|
56
|
+
controller._internals._mediaParserController._internals.signal.addEventListener('abort', onAbort);
|
|
57
|
+
}
|
|
63
58
|
audioDecoder.configure(config);
|
|
64
|
-
const processSample =
|
|
59
|
+
const processSample = (audioSample) => {
|
|
65
60
|
if (audioDecoder.state === 'closed') {
|
|
66
61
|
return;
|
|
67
62
|
}
|
|
68
|
-
progressTracker.setPossibleLowestTimestamp(Math.min(audioSample.timestamp, audioSample.decodingTimestamp ?? Infinity));
|
|
69
|
-
await ioSynchronizer.waitFor({
|
|
70
|
-
unemitted: 20,
|
|
71
|
-
unprocessed: 20,
|
|
72
|
-
minimumProgress: audioSample.timestamp - 10000000,
|
|
73
|
-
controller,
|
|
74
|
-
});
|
|
75
63
|
// Don't flush, it messes up the audio
|
|
76
|
-
const chunk =
|
|
64
|
+
const chunk = audioSample instanceof EncodedAudioChunk
|
|
65
|
+
? audioSample
|
|
66
|
+
: new EncodedAudioChunk(audioSample);
|
|
77
67
|
audioDecoder.decode(chunk);
|
|
78
68
|
// https://test-streams.mux.dev/x36xhzz/url_0/url_525/193039199_mp4_h264_aac_hd_7.ts
|
|
79
69
|
// has a 16 byte audio sample at the end which chrome does not decode
|
|
@@ -81,14 +71,12 @@ const createAudioDecoder = ({ onFrame, onError, controller, config, logLevel, tr
|
|
|
81
71
|
// For now only reporting chunks that are bigger than that
|
|
82
72
|
// 16 was chosen arbitrarily, can be improved
|
|
83
73
|
if (chunk.byteLength > 16) {
|
|
84
|
-
ioSynchronizer.inputItem(chunk.timestamp
|
|
74
|
+
ioSynchronizer.inputItem(chunk.timestamp);
|
|
85
75
|
}
|
|
86
76
|
};
|
|
87
|
-
let queue = Promise.resolve();
|
|
88
77
|
return {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
return queue;
|
|
78
|
+
decode: (sample) => {
|
|
79
|
+
processSample(sample);
|
|
92
80
|
},
|
|
93
81
|
waitForFinish: async () => {
|
|
94
82
|
// Firefox might throw "Needs to be configured first"
|
|
@@ -96,14 +84,23 @@ const createAudioDecoder = ({ onFrame, onError, controller, config, logLevel, tr
|
|
|
96
84
|
await audioDecoder.flush();
|
|
97
85
|
}
|
|
98
86
|
catch { }
|
|
99
|
-
await
|
|
100
|
-
await ioSynchronizer.waitForFinish(controller);
|
|
101
|
-
await outputQueue;
|
|
87
|
+
await ioSynchronizer.waitForFinish();
|
|
102
88
|
},
|
|
103
89
|
close,
|
|
104
90
|
flush: async () => {
|
|
105
91
|
await audioDecoder.flush();
|
|
106
92
|
},
|
|
93
|
+
waitForQueueToBeLessThan: ioSynchronizer.waitForQueueSize,
|
|
107
94
|
};
|
|
108
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
|
+
};
|
|
109
106
|
exports.createAudioDecoder = createAudioDecoder;
|
package/dist/audio-encoder.d.ts
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
import { type MediaParserLogLevel } from '@remotion/media-parser';
|
|
2
|
-
import type { ProgressTracker } from './create/progress-tracker';
|
|
3
2
|
import type { ConvertMediaAudioCodec } from './get-available-audio-codecs';
|
|
3
|
+
import type { IoSynchronizer } from './io-manager/io-synchronizer';
|
|
4
4
|
import type { WebCodecsController } from './webcodecs-controller';
|
|
5
5
|
export type WebCodecsAudioEncoder = {
|
|
6
|
-
|
|
6
|
+
encode: (audioData: AudioData) => void;
|
|
7
7
|
waitForFinish: () => Promise<void>;
|
|
8
8
|
close: () => void;
|
|
9
9
|
flush: () => Promise<void>;
|
|
10
|
+
ioSynchronizer: IoSynchronizer;
|
|
10
11
|
};
|
|
11
12
|
export type AudioEncoderInit = {
|
|
12
13
|
onChunk: (chunk: EncodedAudioChunk) => Promise<void>;
|
|
13
|
-
onError: (error:
|
|
14
|
+
onError: (error: Error) => void;
|
|
14
15
|
codec: ConvertMediaAudioCodec;
|
|
15
16
|
controller: WebCodecsController;
|
|
16
17
|
config: AudioEncoderConfig;
|
|
17
18
|
logLevel: MediaParserLogLevel;
|
|
18
19
|
onNewAudioSampleRate: (sampleRate: number) => void;
|
|
19
|
-
progressTracker: ProgressTracker;
|
|
20
20
|
};
|
|
21
|
-
export declare const createAudioEncoder: ({ onChunk, onError, codec, controller, config: audioEncoderConfig, logLevel, onNewAudioSampleRate,
|
|
21
|
+
export declare const createAudioEncoder: ({ onChunk, onError, codec, controller, config: audioEncoderConfig, logLevel, onNewAudioSampleRate, }: AudioEncoderInit) => WebCodecsAudioEncoder;
|
package/dist/audio-encoder.js
CHANGED
|
@@ -4,41 +4,32 @@ exports.createAudioEncoder = void 0;
|
|
|
4
4
|
const media_parser_1 = require("@remotion/media-parser");
|
|
5
5
|
const io_synchronizer_1 = require("./io-manager/io-synchronizer");
|
|
6
6
|
const wav_audio_encoder_1 = require("./wav-audio-encoder");
|
|
7
|
-
const createAudioEncoder = ({ onChunk, onError, codec, controller, config: audioEncoderConfig, logLevel, onNewAudioSampleRate,
|
|
7
|
+
const createAudioEncoder = ({ onChunk, onError, codec, controller, config: audioEncoderConfig, logLevel, onNewAudioSampleRate, }) => {
|
|
8
8
|
if (controller._internals._mediaParserController._internals.signal.aborted) {
|
|
9
9
|
throw new media_parser_1.MediaParserAbortError('Not creating audio encoder, already aborted');
|
|
10
10
|
}
|
|
11
|
+
const ioSynchronizer = (0, io_synchronizer_1.makeIoSynchronizer)({
|
|
12
|
+
logLevel,
|
|
13
|
+
label: 'Audio encoder',
|
|
14
|
+
controller,
|
|
15
|
+
});
|
|
11
16
|
if (codec === 'wav') {
|
|
12
17
|
return (0, wav_audio_encoder_1.getWaveAudioEncoder)({
|
|
13
18
|
onChunk,
|
|
14
19
|
controller,
|
|
15
20
|
config: audioEncoderConfig,
|
|
21
|
+
ioSynchronizer,
|
|
16
22
|
});
|
|
17
23
|
}
|
|
18
|
-
const ioSynchronizer = (0, io_synchronizer_1.makeIoSynchronizer)({
|
|
19
|
-
logLevel,
|
|
20
|
-
label: 'Audio encoder',
|
|
21
|
-
progress: progressTracker,
|
|
22
|
-
});
|
|
23
|
-
let prom = Promise.resolve();
|
|
24
24
|
const encoder = new AudioEncoder({
|
|
25
|
-
output: (chunk) => {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
.aborted) {
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
return onChunk(chunk);
|
|
34
|
-
})
|
|
35
|
-
.then(() => {
|
|
36
|
-
ioSynchronizer.onProcessed();
|
|
37
|
-
return Promise.resolve();
|
|
38
|
-
})
|
|
39
|
-
.catch((err) => {
|
|
25
|
+
output: async (chunk) => {
|
|
26
|
+
try {
|
|
27
|
+
await onChunk(chunk);
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
40
30
|
onError(err);
|
|
41
|
-
}
|
|
31
|
+
}
|
|
32
|
+
ioSynchronizer.onOutput(chunk.timestamp);
|
|
42
33
|
},
|
|
43
34
|
error(error) {
|
|
44
35
|
onError(error);
|
|
@@ -61,18 +52,7 @@ const createAudioEncoder = ({ onChunk, onError, codec, controller, config: audio
|
|
|
61
52
|
throw new Error('Only `codec: "opus"` and `codec: "aac"` is supported currently');
|
|
62
53
|
}
|
|
63
54
|
const wantedSampleRate = audioEncoderConfig.sampleRate;
|
|
64
|
-
const encodeFrame =
|
|
65
|
-
if (encoder.state === 'closed') {
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
progressTracker.setPossibleLowestTimestamp(audioData.timestamp);
|
|
69
|
-
await ioSynchronizer.waitFor({
|
|
70
|
-
unemitted: 20,
|
|
71
|
-
unprocessed: 20,
|
|
72
|
-
minimumProgress: audioData.timestamp - 10000000,
|
|
73
|
-
controller,
|
|
74
|
-
});
|
|
75
|
-
// @ts-expect-error - can have changed in the meanwhile
|
|
55
|
+
const encodeFrame = (audioData) => {
|
|
76
56
|
if (encoder.state === 'closed') {
|
|
77
57
|
return;
|
|
78
58
|
}
|
|
@@ -89,23 +69,21 @@ const createAudioEncoder = ({ onChunk, onError, codec, controller, config: audio
|
|
|
89
69
|
}
|
|
90
70
|
}
|
|
91
71
|
encoder.encode(audioData);
|
|
92
|
-
ioSynchronizer.inputItem(audioData.timestamp
|
|
72
|
+
ioSynchronizer.inputItem(audioData.timestamp);
|
|
93
73
|
};
|
|
94
|
-
let queue = Promise.resolve();
|
|
95
74
|
return {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
return queue;
|
|
75
|
+
encode: (audioData) => {
|
|
76
|
+
encodeFrame(audioData);
|
|
99
77
|
},
|
|
100
78
|
waitForFinish: async () => {
|
|
101
79
|
await encoder.flush();
|
|
102
|
-
await ioSynchronizer.waitForFinish(
|
|
103
|
-
await prom;
|
|
80
|
+
await ioSynchronizer.waitForFinish();
|
|
104
81
|
},
|
|
105
82
|
close,
|
|
106
83
|
flush: async () => {
|
|
107
84
|
await encoder.flush();
|
|
108
85
|
},
|
|
86
|
+
ioSynchronizer,
|
|
109
87
|
};
|
|
110
88
|
};
|
|
111
89
|
exports.createAudioEncoder = createAudioEncoder;
|
package/dist/convert-media.js
CHANGED
|
@@ -81,6 +81,7 @@ const convertMedia = async function ({ src, onVideoFrame, onAudioData, onProgres
|
|
|
81
81
|
expectedFrameRate: expectedFrameRate ?? null,
|
|
82
82
|
});
|
|
83
83
|
const onVideoTrack = (0, on_video_track_1.makeVideoTrackHandler)({
|
|
84
|
+
progressTracker,
|
|
84
85
|
state,
|
|
85
86
|
onVideoFrame: onVideoFrame ?? null,
|
|
86
87
|
onMediaStateUpdate: throttledState.update ?? null,
|
|
@@ -91,10 +92,10 @@ const convertMedia = async function ({ src, onVideoFrame, onAudioData, onProgres
|
|
|
91
92
|
logLevel,
|
|
92
93
|
outputContainer: container,
|
|
93
94
|
rotate: rotate ?? 0,
|
|
94
|
-
progress: progressTracker,
|
|
95
95
|
resizeOperation: resize ?? null,
|
|
96
96
|
});
|
|
97
97
|
const onAudioTrack = (0, on_audio_track_1.makeAudioTrackHandler)({
|
|
98
|
+
progressTracker,
|
|
98
99
|
abortConversion,
|
|
99
100
|
defaultAudioCodec: audioCodec ?? null,
|
|
100
101
|
controller,
|
|
@@ -103,7 +104,6 @@ const convertMedia = async function ({ src, onVideoFrame, onAudioData, onProgres
|
|
|
103
104
|
onAudioTrack: userAudioResolver ?? null,
|
|
104
105
|
logLevel,
|
|
105
106
|
outputContainer: container,
|
|
106
|
-
progressTracker,
|
|
107
107
|
onAudioData: onAudioData ?? null,
|
|
108
108
|
});
|
|
109
109
|
media_parser_1.MediaParserInternals.internalParseMedia({
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { MediaParserAudioTrack, MediaParserLogLevel, MediaParserOnAudioSample } from '@remotion/media-parser';
|
|
2
|
+
import type { MediaFn } from './create/media-fn';
|
|
3
|
+
import type { ProgressTracker } from './create/progress-tracker';
|
|
4
|
+
import type { ConvertMediaProgressFn } from './throttled-state-update';
|
|
5
|
+
export declare const copyAudioTrack: ({ state, track, logLevel, onMediaStateUpdate, progressTracker, }: {
|
|
6
|
+
state: MediaFn;
|
|
7
|
+
track: MediaParserAudioTrack;
|
|
8
|
+
logLevel: MediaParserLogLevel;
|
|
9
|
+
onMediaStateUpdate: ConvertMediaProgressFn | null;
|
|
10
|
+
progressTracker: ProgressTracker;
|
|
11
|
+
}) => Promise<MediaParserOnAudioSample>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.copyAudioTrack = void 0;
|
|
4
|
+
const log_1 = require("./log");
|
|
5
|
+
const copyAudioTrack = async ({ state, track, logLevel, onMediaStateUpdate, progressTracker, }) => {
|
|
6
|
+
const addedTrack = await state.addTrack({
|
|
7
|
+
type: 'audio',
|
|
8
|
+
codec: track.codecEnum,
|
|
9
|
+
numberOfChannels: track.numberOfChannels,
|
|
10
|
+
sampleRate: track.sampleRate,
|
|
11
|
+
codecPrivate: track.codecData?.data ?? null,
|
|
12
|
+
timescale: track.originalTimescale,
|
|
13
|
+
});
|
|
14
|
+
log_1.Log.verbose(logLevel, `Copying audio track ${track.trackId} as track ${addedTrack.trackNumber}. Timescale = ${track.originalTimescale}, codec = ${track.codecEnum} (${track.codec}) `);
|
|
15
|
+
return async (audioSample) => {
|
|
16
|
+
progressTracker.setPossibleLowestTimestamp(Math.min(audioSample.timestamp, audioSample.decodingTimestamp ?? Infinity));
|
|
17
|
+
await state.addSample({
|
|
18
|
+
chunk: audioSample,
|
|
19
|
+
trackNumber: addedTrack.trackNumber,
|
|
20
|
+
isVideo: false,
|
|
21
|
+
codecPrivate: track.codecData?.data ?? null,
|
|
22
|
+
});
|
|
23
|
+
onMediaStateUpdate?.((prevState) => {
|
|
24
|
+
return {
|
|
25
|
+
...prevState,
|
|
26
|
+
encodedAudioFrames: prevState.encodedAudioFrames + 1,
|
|
27
|
+
};
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
exports.copyAudioTrack = copyAudioTrack;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { MediaParserLogLevel, MediaParserOnVideoSample, MediaParserVideoTrack } from '@remotion/media-parser';
|
|
2
|
+
import type { MediaFn } from './create/media-fn';
|
|
3
|
+
import type { ProgressTracker } from './create/progress-tracker';
|
|
4
|
+
import type { ConvertMediaProgressFn } from './throttled-state-update';
|
|
5
|
+
export declare const copyVideoTrack: ({ logLevel, state, track, onMediaStateUpdate, progressTracker, }: {
|
|
6
|
+
logLevel: MediaParserLogLevel;
|
|
7
|
+
state: MediaFn;
|
|
8
|
+
track: MediaParserVideoTrack;
|
|
9
|
+
onMediaStateUpdate: null | ConvertMediaProgressFn;
|
|
10
|
+
progressTracker: ProgressTracker;
|
|
11
|
+
}) => Promise<MediaParserOnVideoSample>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.copyVideoTrack = void 0;
|
|
4
|
+
const log_1 = require("./log");
|
|
5
|
+
const copyVideoTrack = async ({ logLevel, state, track, onMediaStateUpdate, progressTracker, }) => {
|
|
6
|
+
log_1.Log.verbose(logLevel, `Copying video track with codec ${track.codec} and timescale ${track.originalTimescale}`);
|
|
7
|
+
const videoTrack = await state.addTrack({
|
|
8
|
+
type: 'video',
|
|
9
|
+
color: track.advancedColor,
|
|
10
|
+
width: track.codedWidth,
|
|
11
|
+
height: track.codedHeight,
|
|
12
|
+
codec: track.codecEnum,
|
|
13
|
+
codecPrivate: track.codecData?.data ?? null,
|
|
14
|
+
timescale: track.originalTimescale,
|
|
15
|
+
});
|
|
16
|
+
return async (sample) => {
|
|
17
|
+
progressTracker.setPossibleLowestTimestamp(Math.min(sample.timestamp, sample.decodingTimestamp ?? Infinity));
|
|
18
|
+
await state.addSample({
|
|
19
|
+
chunk: sample,
|
|
20
|
+
trackNumber: videoTrack.trackNumber,
|
|
21
|
+
isVideo: true,
|
|
22
|
+
codecPrivate: track.codecData?.data ?? null,
|
|
23
|
+
});
|
|
24
|
+
onMediaStateUpdate?.((prevState) => {
|
|
25
|
+
return {
|
|
26
|
+
...prevState,
|
|
27
|
+
decodedVideoFrames: prevState.decodedVideoFrames + 1,
|
|
28
|
+
};
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
exports.copyVideoTrack = copyVideoTrack;
|
|
@@ -2,8 +2,6 @@ export declare const makeProgressTracker: () => {
|
|
|
2
2
|
registerTrack: (trackNumber: number) => void;
|
|
3
3
|
getSmallestProgress: () => number;
|
|
4
4
|
updateTrackProgress: (trackNumber: number, progress: number) => void;
|
|
5
|
-
waitForProgress: () => Promise<void>;
|
|
6
|
-
getStartingTimestamp: () => number;
|
|
7
5
|
setPossibleLowestTimestamp: (timestamp: number) => void;
|
|
8
6
|
};
|
|
9
7
|
export type ProgressTracker = ReturnType<typeof makeProgressTracker>;
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.makeProgressTracker = void 0;
|
|
4
4
|
const event_emitter_1 = require("./event-emitter");
|
|
5
|
-
const with_resolvers_1 = require("./with-resolvers");
|
|
6
5
|
// Make sure to distinguish null and undefined here
|
|
7
6
|
const makeProgressTracker = () => {
|
|
8
7
|
const trackNumberProgresses = {};
|
|
@@ -16,13 +15,7 @@ const makeProgressTracker = () => {
|
|
|
16
15
|
startingTimestamp = Math.min(startingTimestamp, timestamp);
|
|
17
16
|
}
|
|
18
17
|
};
|
|
19
|
-
const
|
|
20
|
-
if (startingTimestamp === null) {
|
|
21
|
-
throw new Error('No starting timestamp');
|
|
22
|
-
}
|
|
23
|
-
return startingTimestamp;
|
|
24
|
-
};
|
|
25
|
-
const calculateSmallestProgress = () => {
|
|
18
|
+
const getSmallestProgress = () => {
|
|
26
19
|
const progressValues = Object.values(trackNumberProgresses).map((p) => {
|
|
27
20
|
if (p !== null) {
|
|
28
21
|
return p;
|
|
@@ -41,26 +34,16 @@ const makeProgressTracker = () => {
|
|
|
41
34
|
registerTrack: (trackNumber) => {
|
|
42
35
|
trackNumberProgresses[trackNumber] = null;
|
|
43
36
|
},
|
|
44
|
-
getSmallestProgress
|
|
37
|
+
getSmallestProgress,
|
|
45
38
|
updateTrackProgress: (trackNumber, progress) => {
|
|
46
39
|
if (trackNumberProgresses[trackNumber] === undefined) {
|
|
47
40
|
throw new Error(`Tried to update progress for a track that was not registered: ${trackNumber}`);
|
|
48
41
|
}
|
|
49
42
|
trackNumberProgresses[trackNumber] = progress;
|
|
50
43
|
eventEmitter.dispatchEvent('progress', {
|
|
51
|
-
smallestProgress:
|
|
44
|
+
smallestProgress: getSmallestProgress(),
|
|
52
45
|
});
|
|
53
46
|
},
|
|
54
|
-
waitForProgress: () => {
|
|
55
|
-
const { promise, resolve } = (0, with_resolvers_1.withResolvers)();
|
|
56
|
-
const on = () => {
|
|
57
|
-
eventEmitter.removeEventListener('progress', on);
|
|
58
|
-
resolve();
|
|
59
|
-
};
|
|
60
|
-
eventEmitter.addEventListener('progress', on);
|
|
61
|
-
return promise;
|
|
62
|
-
},
|
|
63
|
-
getStartingTimestamp,
|
|
64
47
|
setPossibleLowestTimestamp,
|
|
65
48
|
};
|
|
66
49
|
};
|