@remotion/media-parser 4.0.232 → 4.0.234
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/boxes/iso-base-media/esds/decoder-specific-config.d.ts +1 -2
- package/dist/boxes/iso-base-media/esds/decoder-specific-config.js +1 -5
- package/dist/boxes/iso-base-media/esds/esds-descriptors.d.ts +2 -4
- package/dist/boxes/iso-base-media/esds/esds-descriptors.js +3 -4
- package/dist/boxes/iso-base-media/esds/esds.d.ts +1 -3
- package/dist/boxes/iso-base-media/esds/esds.js +2 -2
- package/dist/boxes/iso-base-media/get-sample-positions-from-track.js +7 -1
- package/dist/boxes/iso-base-media/process-box.js +0 -1
- package/dist/boxes/iso-base-media/stsd/samples.js +6 -5
- package/dist/create/event-emitter.d.ts +31 -0
- package/dist/create/event-emitter.js +25 -0
- package/dist/create/iso-base-media/create-iso-base-media.d.ts +1 -1
- package/dist/create/iso-base-media/create-iso-base-media.js +3 -1
- package/dist/create/matroska/cluster.js +1 -1
- package/dist/create/matroska/create-matroska-media.d.ts +1 -1
- package/dist/create/matroska/create-matroska-media.js +7 -10
- package/dist/create/media-fn.d.ts +2 -0
- package/dist/create/progress-tracker.d.ts +7 -0
- package/dist/create/progress-tracker.js +43 -0
- package/dist/create/wav/create-wav.d.ts +1 -1
- package/dist/create/wav/create-wav.js +3 -1
- package/dist/create/with-resolvers.d.ts +10 -0
- package/dist/create/with-resolvers.js +28 -0
- package/dist/emit-available-info.js +11 -2
- package/dist/esm/index.mjs +235 -68
- package/dist/get-audio-codec.d.ts +1 -0
- package/dist/get-audio-codec.js +15 -1
- package/dist/get-is-hdr.d.ts +4 -0
- package/dist/get-is-hdr.js +18 -0
- package/dist/get-sample-positions-from-lpcm.d.ts +3 -0
- package/dist/get-sample-positions-from-lpcm.js +46 -0
- package/dist/get-tracks.d.ts +3 -3
- package/dist/get-video-codec.js +9 -3
- package/dist/has-all-info.js +6 -1
- package/dist/index.d.ts +23 -4
- package/dist/index.js +7 -0
- package/dist/options.d.ts +7 -0
- package/dist/parse-media.js +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -3
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { BufferIterator } from '../../../buffer-iterator';
|
|
2
|
-
import type { LogLevel } from '../../../log';
|
|
3
2
|
type UnknownDecoderSpecificConfig = {
|
|
4
3
|
type: 'unknown-decoder-specific-config';
|
|
5
4
|
};
|
|
@@ -11,5 +10,5 @@ type AudioSpecificConfig = {
|
|
|
11
10
|
asBytes: Uint8Array;
|
|
12
11
|
};
|
|
13
12
|
export type DecoderSpecificConfig = UnknownDecoderSpecificConfig | AudioSpecificConfig;
|
|
14
|
-
export declare const parseDecoderSpecificConfig: (iterator: BufferIterator
|
|
13
|
+
export declare const parseDecoderSpecificConfig: (iterator: BufferIterator) => DecoderSpecificConfig;
|
|
15
14
|
export {};
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.parseDecoderSpecificConfig = void 0;
|
|
4
|
-
const
|
|
5
|
-
const parseDecoderSpecificConfig = (iterator, logLevel) => {
|
|
4
|
+
const parseDecoderSpecificConfig = (iterator) => {
|
|
6
5
|
const layerTag = iterator.getUint8();
|
|
7
6
|
const layerSize = iterator.getPaddedFourByteNumber();
|
|
8
7
|
const start = iterator.counter.getOffset();
|
|
@@ -28,9 +27,6 @@ const parseDecoderSpecificConfig = (iterator, logLevel) => {
|
|
|
28
27
|
if (read < layerSize) {
|
|
29
28
|
iterator.discard(layerSize - read);
|
|
30
29
|
}
|
|
31
|
-
if (bytes.byteLength === 2 && bytes[0] === 17 && bytes[1] === 136) {
|
|
32
|
-
log_1.Log.warn(logLevel, 'Chrome has a bug and might not be able to decode this audio. It will be fixed, see: https://issues.chromium.org/issues/360083330');
|
|
33
|
-
}
|
|
34
30
|
return {
|
|
35
31
|
type: 'mp4a-specific-config',
|
|
36
32
|
audioObjectType,
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { BufferIterator } from '../../../buffer-iterator';
|
|
2
|
-
import type { LogLevel } from '../../../log';
|
|
3
2
|
import type { DecoderSpecificConfig } from './decoder-specific-config';
|
|
4
3
|
type AudioObjectType = 'aac' | 'mp3' | 'unknown';
|
|
5
4
|
type DecoderConfigDescriptor = {
|
|
@@ -23,9 +22,8 @@ export type Descriptor = DecoderConfigDescriptor | SlConfigDescriptor | UnknownD
|
|
|
23
22
|
type DescriptorAndNext = {
|
|
24
23
|
descriptor: Descriptor | null;
|
|
25
24
|
};
|
|
26
|
-
export declare const processDescriptor: ({ iterator,
|
|
25
|
+
export declare const processDescriptor: ({ iterator, }: {
|
|
27
26
|
iterator: BufferIterator;
|
|
28
|
-
logLevel: LogLevel;
|
|
29
27
|
}) => DescriptorAndNext;
|
|
30
|
-
export declare const parseDescriptors: (iterator: BufferIterator, maxBytes: number
|
|
28
|
+
export declare const parseDescriptors: (iterator: BufferIterator, maxBytes: number) => Descriptor[];
|
|
31
29
|
export {};
|
|
@@ -14,7 +14,7 @@ const mapToObjectAudioIndicator = (num) => {
|
|
|
14
14
|
}
|
|
15
15
|
return 'unknown';
|
|
16
16
|
};
|
|
17
|
-
const processDescriptor = ({ iterator,
|
|
17
|
+
const processDescriptor = ({ iterator, }) => {
|
|
18
18
|
const tag = iterator.getUint8();
|
|
19
19
|
if (tag === 4) {
|
|
20
20
|
const size = iterator.getPaddedFourByteNumber();
|
|
@@ -31,7 +31,7 @@ const processDescriptor = ({ iterator, logLevel, }) => {
|
|
|
31
31
|
const avgBitrate = iterator.getUint32();
|
|
32
32
|
const decoderSpecificConfigs = [];
|
|
33
33
|
while (size - (iterator.counter.getOffset() - initialOffset) > 0) {
|
|
34
|
-
const decoderSpecificConfig = (0, decoder_specific_config_1.parseDecoderSpecificConfig)(iterator
|
|
34
|
+
const decoderSpecificConfig = (0, decoder_specific_config_1.parseDecoderSpecificConfig)(iterator);
|
|
35
35
|
decoderSpecificConfigs.push(decoderSpecificConfig);
|
|
36
36
|
}
|
|
37
37
|
return {
|
|
@@ -62,14 +62,13 @@ const processDescriptor = ({ iterator, logLevel, }) => {
|
|
|
62
62
|
};
|
|
63
63
|
};
|
|
64
64
|
exports.processDescriptor = processDescriptor;
|
|
65
|
-
const parseDescriptors = (iterator, maxBytes
|
|
65
|
+
const parseDescriptors = (iterator, maxBytes) => {
|
|
66
66
|
const descriptors = [];
|
|
67
67
|
const initialOffset = iterator.counter.getOffset();
|
|
68
68
|
while (iterator.bytesRemaining() > 0 &&
|
|
69
69
|
iterator.counter.getOffset() - initialOffset < maxBytes) {
|
|
70
70
|
const { descriptor } = (0, exports.processDescriptor)({
|
|
71
71
|
iterator,
|
|
72
|
-
logLevel,
|
|
73
72
|
});
|
|
74
73
|
if (descriptor) {
|
|
75
74
|
descriptors.push(descriptor);
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { BufferIterator } from '../../../buffer-iterator';
|
|
2
|
-
import type { LogLevel } from '../../../log';
|
|
3
2
|
import type { Descriptor } from './esds-descriptors';
|
|
4
3
|
export interface EsdsBox {
|
|
5
4
|
type: 'esds-box';
|
|
@@ -9,9 +8,8 @@ export interface EsdsBox {
|
|
|
9
8
|
esId: number;
|
|
10
9
|
descriptors: Descriptor[];
|
|
11
10
|
}
|
|
12
|
-
export declare const parseEsds: ({ data, size, fileOffset,
|
|
11
|
+
export declare const parseEsds: ({ data, size, fileOffset, }: {
|
|
13
12
|
data: BufferIterator;
|
|
14
13
|
size: number;
|
|
15
14
|
fileOffset: number;
|
|
16
|
-
logLevel: LogLevel;
|
|
17
15
|
}) => EsdsBox;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.parseEsds = void 0;
|
|
4
4
|
const esds_descriptors_1 = require("./esds-descriptors");
|
|
5
|
-
const parseEsds = ({ data, size, fileOffset,
|
|
5
|
+
const parseEsds = ({ data, size, fileOffset, }) => {
|
|
6
6
|
const version = data.getUint8();
|
|
7
7
|
// Flags, we discard them
|
|
8
8
|
data.discard(3);
|
|
@@ -12,7 +12,7 @@ const parseEsds = ({ data, size, fileOffset, logLevel, }) => {
|
|
|
12
12
|
// disard 1 byte, currently unknown
|
|
13
13
|
data.discard(1);
|
|
14
14
|
const remaining = size - (data.counter.getOffset() - fileOffset);
|
|
15
|
-
const descriptors = (0, esds_descriptors_1.parseDescriptors)(data, remaining
|
|
15
|
+
const descriptors = (0, esds_descriptors_1.parseDescriptors)(data, remaining);
|
|
16
16
|
const remainingNow = size - (data.counter.getOffset() - fileOffset);
|
|
17
17
|
data.discard(remainingNow);
|
|
18
18
|
return {
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getSamplePositionsFromTrack = void 0;
|
|
4
|
+
const get_audio_codec_1 = require("../../get-audio-codec");
|
|
4
5
|
const get_fps_1 = require("../../get-fps");
|
|
5
6
|
const get_sample_positions_1 = require("../../get-sample-positions");
|
|
7
|
+
const get_sample_positions_from_lpcm_1 = require("../../get-sample-positions-from-lpcm");
|
|
6
8
|
const samples_from_moof_1 = require("../../samples-from-moof");
|
|
7
9
|
const traversal_1 = require("./traversal");
|
|
8
10
|
const getSamplePositionsFromTrack = (trakBox, moofBox) => {
|
|
11
|
+
const isLpcm = (0, get_audio_codec_1.isLpcmAudioCodec)(trakBox);
|
|
12
|
+
const timescaleAndDuration = (0, get_fps_1.getTimescaleAndDuration)(trakBox);
|
|
13
|
+
if (isLpcm) {
|
|
14
|
+
return (0, get_sample_positions_from_lpcm_1.getSamplePositionsFromLpcm)(trakBox);
|
|
15
|
+
}
|
|
9
16
|
const stszBox = (0, traversal_1.getStszBox)(trakBox);
|
|
10
17
|
const stcoBox = (0, traversal_1.getStcoBox)(trakBox);
|
|
11
18
|
const stscBox = (0, traversal_1.getStscBox)(trakBox);
|
|
@@ -13,7 +20,6 @@ const getSamplePositionsFromTrack = (trakBox, moofBox) => {
|
|
|
13
20
|
const sttsBox = (0, traversal_1.getSttsBox)(trakBox);
|
|
14
21
|
const tkhdBox = (0, traversal_1.getTkhdBox)(trakBox);
|
|
15
22
|
const cttsBox = (0, traversal_1.getCttsBox)(trakBox);
|
|
16
|
-
const timescaleAndDuration = (0, get_fps_1.getTimescaleAndDuration)(trakBox);
|
|
17
23
|
if (!tkhdBox) {
|
|
18
24
|
throw new Error('Expected tkhd box in trak box');
|
|
19
25
|
}
|
|
@@ -45,6 +45,7 @@ const audioTags = [
|
|
|
45
45
|
'MAC6 ',
|
|
46
46
|
'ima4',
|
|
47
47
|
'fl32',
|
|
48
|
+
'lpcm',
|
|
48
49
|
'fl64',
|
|
49
50
|
'in24',
|
|
50
51
|
'in32',
|
|
@@ -182,16 +183,16 @@ const processSample = async ({ iterator, options, signal, logLevel, }) => {
|
|
|
182
183
|
};
|
|
183
184
|
}
|
|
184
185
|
if (version === 2) {
|
|
185
|
-
|
|
186
|
+
iterator.getUint16(); // always 3
|
|
186
187
|
const sampleSize = iterator.getUint16();
|
|
187
188
|
const compressionId = iterator.getUint16();
|
|
188
189
|
const packetSize = iterator.getUint16();
|
|
189
190
|
iterator.getFixedPointUnsigned1616Number(); // LQ sample rate;
|
|
190
191
|
iterator.getUint32(); // ignore
|
|
191
192
|
const higherSampleRate = iterator.getFloat64();
|
|
192
|
-
iterator.getUint32(); // ignore;
|
|
193
|
+
const numAudioChannel = iterator.getUint32(); // ignore;
|
|
193
194
|
iterator.getUint32(); // ignore, always 0x7F000000?
|
|
194
|
-
const
|
|
195
|
+
const bitsPerChannel = iterator.getUint32();
|
|
195
196
|
iterator.getUint32(); // ignore;
|
|
196
197
|
const bytesPerFrame = iterator.getUint32();
|
|
197
198
|
const samplesPerPacket = iterator.getUint32();
|
|
@@ -219,7 +220,7 @@ const processSample = async ({ iterator, options, signal, logLevel, }) => {
|
|
|
219
220
|
vendor: [...Array.from(new Uint8Array(vendor))],
|
|
220
221
|
size: boxSize,
|
|
221
222
|
type: 'audio',
|
|
222
|
-
numberOfChannels,
|
|
223
|
+
numberOfChannels: numAudioChannel,
|
|
223
224
|
sampleSize,
|
|
224
225
|
compressionId,
|
|
225
226
|
packetSize,
|
|
@@ -227,7 +228,7 @@ const processSample = async ({ iterator, options, signal, logLevel, }) => {
|
|
|
227
228
|
samplesPerPacket,
|
|
228
229
|
bytesPerPacket: null,
|
|
229
230
|
bytesPerFrame,
|
|
230
|
-
bitsPerSample:
|
|
231
|
+
bitsPerSample: bitsPerChannel,
|
|
231
232
|
children: children.segments.boxes,
|
|
232
233
|
},
|
|
233
234
|
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
type Input = {
|
|
2
|
+
timestamp: number;
|
|
3
|
+
keyFrame: boolean;
|
|
4
|
+
};
|
|
5
|
+
type Output = {
|
|
6
|
+
timestamp: number;
|
|
7
|
+
};
|
|
8
|
+
type Processed = {};
|
|
9
|
+
type Progress = {
|
|
10
|
+
smallestProgress: number;
|
|
11
|
+
};
|
|
12
|
+
type IoEventMap = {
|
|
13
|
+
input: Input;
|
|
14
|
+
output: Output;
|
|
15
|
+
processed: Processed;
|
|
16
|
+
progress: Progress;
|
|
17
|
+
};
|
|
18
|
+
export type IoEventTypes = keyof IoEventMap;
|
|
19
|
+
export type CallbackListener<T extends IoEventTypes> = (data: {
|
|
20
|
+
detail: IoEventMap[T];
|
|
21
|
+
}) => void;
|
|
22
|
+
type IoListeners = {
|
|
23
|
+
[EventType in IoEventTypes]: CallbackListener<EventType>[];
|
|
24
|
+
};
|
|
25
|
+
export declare class IoEventEmitter {
|
|
26
|
+
listeners: IoListeners;
|
|
27
|
+
addEventListener<Q extends IoEventTypes>(name: Q, callback: CallbackListener<Q>): void;
|
|
28
|
+
removeEventListener<Q extends IoEventTypes>(name: Q, callback: CallbackListener<Q>): void;
|
|
29
|
+
dispatchEvent<T extends IoEventTypes>(dispatchName: T, context: IoEventMap[T]): void;
|
|
30
|
+
}
|
|
31
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.IoEventEmitter = void 0;
|
|
4
|
+
class IoEventEmitter {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.listeners = {
|
|
7
|
+
input: [],
|
|
8
|
+
output: [],
|
|
9
|
+
processed: [],
|
|
10
|
+
progress: [],
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
addEventListener(name, callback) {
|
|
14
|
+
this.listeners[name].push(callback);
|
|
15
|
+
}
|
|
16
|
+
removeEventListener(name, callback) {
|
|
17
|
+
this.listeners[name] = this.listeners[name].filter((l) => l !== callback);
|
|
18
|
+
}
|
|
19
|
+
dispatchEvent(dispatchName, context) {
|
|
20
|
+
this.listeners[dispatchName].forEach((callback) => {
|
|
21
|
+
callback({ detail: context });
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
exports.IoEventEmitter = IoEventEmitter;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { MediaFn, MediaFnGeneratorInput } from '../media-fn';
|
|
2
|
-
export declare const createIsoBaseMedia: ({ writer, onBytesProgress, onMillisecondsProgress, logLevel, filename, }: MediaFnGeneratorInput) => Promise<MediaFn>;
|
|
2
|
+
export declare const createIsoBaseMedia: ({ writer, onBytesProgress, onMillisecondsProgress, logLevel, filename, progressTracker, }: MediaFnGeneratorInput) => Promise<MediaFn>;
|
|
@@ -6,7 +6,7 @@ const log_1 = require("../../log");
|
|
|
6
6
|
const create_ftyp_1 = require("./create-ftyp");
|
|
7
7
|
const mp4_header_1 = require("./mp4-header");
|
|
8
8
|
const primitives_1 = require("./primitives");
|
|
9
|
-
const createIsoBaseMedia = async ({ writer, onBytesProgress, onMillisecondsProgress, logLevel, filename, }) => {
|
|
9
|
+
const createIsoBaseMedia = async ({ writer, onBytesProgress, onMillisecondsProgress, logLevel, filename, progressTracker, }) => {
|
|
10
10
|
const header = (0, create_ftyp_1.createIsoBaseMediaFtyp)({
|
|
11
11
|
compatibleBrands: ['isom', 'iso2', 'avc1', 'mp42'],
|
|
12
12
|
majorBrand: 'isom',
|
|
@@ -70,6 +70,7 @@ const createIsoBaseMedia = async ({ writer, onBytesProgress, onMillisecondsProgr
|
|
|
70
70
|
await w.write(chunk.data);
|
|
71
71
|
mdatSize += chunk.data.length;
|
|
72
72
|
onBytesProgress(w.getWrittenByteCount());
|
|
73
|
+
progressTracker.updateTrackProgress(trackNumber, chunk.timestamp);
|
|
73
74
|
if (codecPrivate) {
|
|
74
75
|
addCodecPrivateToTrack({ trackNumber, codecPrivate });
|
|
75
76
|
}
|
|
@@ -109,6 +110,7 @@ const createIsoBaseMedia = async ({ writer, onBytesProgress, onMillisecondsProgr
|
|
|
109
110
|
const addTrack = (track) => {
|
|
110
111
|
const trackNumber = currentTracks.length + 1;
|
|
111
112
|
currentTracks.push({ ...track, trackNumber });
|
|
113
|
+
progressTracker.registerTrack(trackNumber);
|
|
112
114
|
return Promise.resolve({ trackNumber });
|
|
113
115
|
};
|
|
114
116
|
const waitForFinishPromises = [];
|
|
@@ -15,7 +15,7 @@ const canFitInCluster = ({ clusterStartTimestamp, chunk, timescale, }) => {
|
|
|
15
15
|
const timecodeRelativeToCluster = (0, exports.timestampToClusterTimestamp)(chunk.timestamp, timescale) -
|
|
16
16
|
(0, exports.timestampToClusterTimestamp)(clusterStartTimestamp, timescale);
|
|
17
17
|
if (timecodeRelativeToCluster < 0) {
|
|
18
|
-
throw new Error(`timecodeRelativeToCluster is negative`);
|
|
18
|
+
throw new Error(`timecodeRelativeToCluster is negative, tried to add ${chunk.timestamp} to ${clusterStartTimestamp}`);
|
|
19
19
|
}
|
|
20
20
|
return timecodeRelativeToCluster <= maxClusterTimestamp;
|
|
21
21
|
};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { MediaFn, MediaFnGeneratorInput } from '../media-fn';
|
|
2
|
-
export declare const createMatroskaMedia: ({ writer, onBytesProgress, onMillisecondsProgress, filename, logLevel, }: MediaFnGeneratorInput) => Promise<MediaFn>;
|
|
2
|
+
export declare const createMatroskaMedia: ({ writer, onBytesProgress, onMillisecondsProgress, filename, logLevel, progressTracker, }: MediaFnGeneratorInput) => Promise<MediaFn>;
|
|
@@ -13,7 +13,7 @@ const matroska_seek_1 = require("./matroska-seek");
|
|
|
13
13
|
const matroska_segment_1 = require("./matroska-segment");
|
|
14
14
|
const matroska_trackentry_1 = require("./matroska-trackentry");
|
|
15
15
|
const timescale = 1000000;
|
|
16
|
-
const createMatroskaMedia = async ({ writer, onBytesProgress, onMillisecondsProgress, filename, logLevel, }) => {
|
|
16
|
+
const createMatroskaMedia = async ({ writer, onBytesProgress, onMillisecondsProgress, filename, logLevel, progressTracker, }) => {
|
|
17
17
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
18
18
|
const header = (0, matroska_header_1.makeMatroskaHeader)();
|
|
19
19
|
const w = await writer.createContent({ filename, mimeType: 'video/webm' });
|
|
@@ -79,17 +79,11 @@ const createMatroskaMedia = async ({ writer, onBytesProgress, onMillisecondsProg
|
|
|
79
79
|
hexString: all_segments_1.matroskaElements.Cluster,
|
|
80
80
|
byte: clusterOffset - seekHeadOffset,
|
|
81
81
|
});
|
|
82
|
-
const
|
|
83
|
-
const getClusterOrMakeNew = async ({ chunk, isVideo, trackNumber, }) => {
|
|
84
|
-
const trackProgressValues = Object.values(trackNumberProgresses);
|
|
85
|
-
const smallestProgress = trackProgressValues.length === 0 ? 0 : Math.min(...trackProgressValues);
|
|
82
|
+
const getClusterOrMakeNew = async ({ chunk, isVideo, }) => {
|
|
86
83
|
// In Safari, samples can arrive out of order, e.g public/bigbuckbunny.mp4
|
|
87
84
|
// Therefore, only updating track number progress if it is a keyframe
|
|
88
85
|
// to allow for timestamps to be lower than the previous one
|
|
89
|
-
|
|
90
|
-
if (chunk.type === 'key') {
|
|
91
|
-
trackNumberProgresses[trackNumber] = chunk.timestamp;
|
|
92
|
-
}
|
|
86
|
+
const smallestProgress = progressTracker.getSmallestProgress();
|
|
93
87
|
if (!currentCluster.shouldMakeNewCluster({
|
|
94
88
|
newT: smallestProgress,
|
|
95
89
|
isVideo,
|
|
@@ -115,7 +109,6 @@ const createMatroskaMedia = async ({ writer, onBytesProgress, onMillisecondsProg
|
|
|
115
109
|
const { cluster, isNew, smallestProgress } = await getClusterOrMakeNew({
|
|
116
110
|
chunk,
|
|
117
111
|
isVideo,
|
|
118
|
-
trackNumber,
|
|
119
112
|
});
|
|
120
113
|
const newDuration = Math.round((chunk.timestamp + ((_a = chunk.duration) !== null && _a !== void 0 ? _a : 0)) / 1000);
|
|
121
114
|
await updateDuration(newDuration);
|
|
@@ -129,12 +122,16 @@ const createMatroskaMedia = async ({ writer, onBytesProgress, onMillisecondsProg
|
|
|
129
122
|
trackNumber,
|
|
130
123
|
});
|
|
131
124
|
}
|
|
125
|
+
if (chunk.type === 'key') {
|
|
126
|
+
progressTracker.updateTrackProgress(trackNumber, chunk.timestamp);
|
|
127
|
+
}
|
|
132
128
|
onBytesProgress(w.getWrittenByteCount());
|
|
133
129
|
onMillisecondsProgress(newDuration);
|
|
134
130
|
};
|
|
135
131
|
const addTrack = async (track) => {
|
|
136
132
|
currentTracks.push(track);
|
|
137
133
|
const newTracks = (0, matroska_trackentry_1.makeMatroskaTracks)(currentTracks);
|
|
134
|
+
progressTracker.registerTrack(track.trackNumber);
|
|
138
135
|
await w.updateDataAt(tracksOffset, (0, make_header_1.combineUint8Arrays)(newTracks.map((b) => b.bytes)));
|
|
139
136
|
};
|
|
140
137
|
const operationProm = { current: Promise.resolve() };
|
|
@@ -2,6 +2,7 @@ import type { LogLevel } from '../log';
|
|
|
2
2
|
import type { AudioOrVideoSample } from '../webcodec-sample-types';
|
|
3
3
|
import type { WriterInterface } from '../writers/writer';
|
|
4
4
|
import type { MakeTrackAudio, MakeTrackVideo } from './make-track-info';
|
|
5
|
+
import type { ProgressTracker } from './progress-tracker';
|
|
5
6
|
export type MediaFn = {
|
|
6
7
|
save: () => Promise<Blob>;
|
|
7
8
|
remove: () => Promise<void>;
|
|
@@ -28,4 +29,5 @@ export type MediaFnGeneratorInput = {
|
|
|
28
29
|
onMillisecondsProgress: (totalMilliseconds: number) => void;
|
|
29
30
|
logLevel: LogLevel;
|
|
30
31
|
filename: string;
|
|
32
|
+
progressTracker: ProgressTracker;
|
|
31
33
|
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const makeProgressTracker: () => {
|
|
2
|
+
registerTrack: (trackNumber: number) => void;
|
|
3
|
+
getSmallestProgress: () => number;
|
|
4
|
+
updateTrackProgress: (trackNumber: number, progress: number) => void;
|
|
5
|
+
waitForProgress: () => Promise<void>;
|
|
6
|
+
};
|
|
7
|
+
export type ProgressTracker = ReturnType<typeof makeProgressTracker>;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.makeProgressTracker = void 0;
|
|
4
|
+
const event_emitter_1 = require("./event-emitter");
|
|
5
|
+
const with_resolvers_1 = require("./with-resolvers");
|
|
6
|
+
const makeProgressTracker = () => {
|
|
7
|
+
const trackNumberProgresses = {};
|
|
8
|
+
const eventEmitter = new event_emitter_1.IoEventEmitter();
|
|
9
|
+
const calculateSmallestProgress = () => {
|
|
10
|
+
const progressValues = Object.values(trackNumberProgresses);
|
|
11
|
+
if (progressValues.length === 0) {
|
|
12
|
+
return 0;
|
|
13
|
+
}
|
|
14
|
+
return Math.min(...progressValues);
|
|
15
|
+
};
|
|
16
|
+
return {
|
|
17
|
+
registerTrack: (trackNumber) => {
|
|
18
|
+
trackNumberProgresses[trackNumber] = 0;
|
|
19
|
+
},
|
|
20
|
+
getSmallestProgress: () => {
|
|
21
|
+
return calculateSmallestProgress();
|
|
22
|
+
},
|
|
23
|
+
updateTrackProgress: (trackNumber, progress) => {
|
|
24
|
+
if (trackNumberProgresses[trackNumber] === undefined) {
|
|
25
|
+
throw new Error(`Tried to update progress for a track that was not registered: ${trackNumber}`);
|
|
26
|
+
}
|
|
27
|
+
trackNumberProgresses[trackNumber] = progress;
|
|
28
|
+
eventEmitter.dispatchEvent('progress', {
|
|
29
|
+
smallestProgress: calculateSmallestProgress(),
|
|
30
|
+
});
|
|
31
|
+
},
|
|
32
|
+
waitForProgress: () => {
|
|
33
|
+
const { promise, resolve } = (0, with_resolvers_1.withResolvers)();
|
|
34
|
+
const on = () => {
|
|
35
|
+
eventEmitter.removeEventListener('processed', on);
|
|
36
|
+
resolve();
|
|
37
|
+
};
|
|
38
|
+
eventEmitter.addEventListener('processed', on);
|
|
39
|
+
return promise;
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
exports.makeProgressTracker = makeProgressTracker;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { MediaFn, MediaFnGeneratorInput } from '../media-fn';
|
|
2
|
-
export declare const createWav: ({ filename, logLevel, onBytesProgress, onMillisecondsProgress, writer, }: MediaFnGeneratorInput) => Promise<MediaFn>;
|
|
2
|
+
export declare const createWav: ({ filename, logLevel, onBytesProgress, onMillisecondsProgress, writer, progressTracker, }: MediaFnGeneratorInput) => Promise<MediaFn>;
|
|
@@ -15,7 +15,7 @@ const numberTo16BitLittleEndian = (num) => {
|
|
|
15
15
|
};
|
|
16
16
|
const BIT_DEPTH = 16;
|
|
17
17
|
const BYTES_PER_SAMPLE = BIT_DEPTH / 8;
|
|
18
|
-
const createWav = async ({ filename, logLevel, onBytesProgress, onMillisecondsProgress, writer, }) => {
|
|
18
|
+
const createWav = async ({ filename, logLevel, onBytesProgress, onMillisecondsProgress, writer, progressTracker, }) => {
|
|
19
19
|
const w = await writer.createContent({ filename, mimeType: 'audio/wav' });
|
|
20
20
|
await w.write(new Uint8Array([0x52, 0x49, 0x46, 0x46])); // "RIFF"
|
|
21
21
|
const sizePosition = w.getWrittenByteCount();
|
|
@@ -75,6 +75,7 @@ const createWav = async ({ filename, logLevel, onBytesProgress, onMillisecondsPr
|
|
|
75
75
|
throw new Error('Only one track supported for WAV');
|
|
76
76
|
}
|
|
77
77
|
operationProm.current = operationProm.current.then(() => addSample(chunk));
|
|
78
|
+
progressTracker.updateTrackProgress(trackNumber, chunk.timestamp);
|
|
78
79
|
return operationProm.current;
|
|
79
80
|
},
|
|
80
81
|
updateTrackSampleRate: () => {
|
|
@@ -101,6 +102,7 @@ const createWav = async ({ filename, logLevel, onBytesProgress, onMillisecondsPr
|
|
|
101
102
|
numberOfChannels: track.numberOfChannels,
|
|
102
103
|
});
|
|
103
104
|
await updateBlockAlign(track.numberOfChannels);
|
|
105
|
+
progressTracker.registerTrack(1);
|
|
104
106
|
return Promise.resolve({ trackNumber: 1 });
|
|
105
107
|
},
|
|
106
108
|
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const withResolvers: <T>() => {
|
|
2
|
+
promise: Promise<T>;
|
|
3
|
+
resolve: (value: T | PromiseLike<T>) => void;
|
|
4
|
+
reject: (reason?: any) => void;
|
|
5
|
+
};
|
|
6
|
+
export declare const withResolversAndWaitForReturn: <T>() => {
|
|
7
|
+
getPromiseToImmediatelyReturn: () => Promise<T>;
|
|
8
|
+
reject: (reason: unknown) => void;
|
|
9
|
+
resolve: (value: T | PromiseLike<T>) => void;
|
|
10
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.withResolversAndWaitForReturn = exports.withResolvers = void 0;
|
|
4
|
+
const withResolvers = function () {
|
|
5
|
+
let resolve;
|
|
6
|
+
let reject;
|
|
7
|
+
const promise = new Promise((res, rej) => {
|
|
8
|
+
resolve = res;
|
|
9
|
+
reject = rej;
|
|
10
|
+
});
|
|
11
|
+
return { promise, resolve: resolve, reject: reject };
|
|
12
|
+
};
|
|
13
|
+
exports.withResolvers = withResolvers;
|
|
14
|
+
const withResolversAndWaitForReturn = () => {
|
|
15
|
+
const { promise, reject, resolve } = (0, exports.withResolvers)();
|
|
16
|
+
const { promise: returnPromise, resolve: resolveReturn } = (0, exports.withResolvers)();
|
|
17
|
+
return {
|
|
18
|
+
getPromiseToImmediatelyReturn: () => {
|
|
19
|
+
resolveReturn(undefined);
|
|
20
|
+
return promise;
|
|
21
|
+
},
|
|
22
|
+
reject: (reason) => {
|
|
23
|
+
returnPromise.then(() => reject(reason));
|
|
24
|
+
},
|
|
25
|
+
resolve,
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
exports.withResolversAndWaitForReturn = withResolversAndWaitForReturn;
|
|
@@ -6,10 +6,11 @@ const get_container_1 = require("./get-container");
|
|
|
6
6
|
const get_dimensions_1 = require("./get-dimensions");
|
|
7
7
|
const get_duration_1 = require("./get-duration");
|
|
8
8
|
const get_fps_1 = require("./get-fps");
|
|
9
|
+
const get_is_hdr_1 = require("./get-is-hdr");
|
|
9
10
|
const get_tracks_1 = require("./get-tracks");
|
|
10
11
|
const get_video_codec_1 = require("./get-video-codec");
|
|
11
12
|
const emitAvailableInfo = ({ hasInfo, parseResult, moreFields, state, returnValue, contentLength, name, }) => {
|
|
12
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
13
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
|
|
13
14
|
const keys = Object.keys(hasInfo);
|
|
14
15
|
for (const key of keys) {
|
|
15
16
|
if (key === 'structure') {
|
|
@@ -132,12 +133,20 @@ const emitAvailableInfo = ({ hasInfo, parseResult, moreFields, state, returnValu
|
|
|
132
133
|
}
|
|
133
134
|
continue;
|
|
134
135
|
}
|
|
136
|
+
if (key === 'isHdr') {
|
|
137
|
+
if (returnValue.isHdr === undefined && hasInfo.isHdr && parseResult) {
|
|
138
|
+
const isHdr = (0, get_is_hdr_1.getIsHdr)(parseResult.segments, state);
|
|
139
|
+
(_o = moreFields.onIsHdr) === null || _o === void 0 ? void 0 : _o.call(moreFields, isHdr);
|
|
140
|
+
returnValue.isHdr = isHdr;
|
|
141
|
+
}
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
135
144
|
if (key === 'container') {
|
|
136
145
|
if (returnValue.container === undefined &&
|
|
137
146
|
hasInfo.container &&
|
|
138
147
|
parseResult) {
|
|
139
148
|
const container = (0, get_container_1.getContainer)(parseResult.segments);
|
|
140
|
-
(
|
|
149
|
+
(_p = moreFields.onContainer) === null || _p === void 0 ? void 0 : _p.call(moreFields, container);
|
|
141
150
|
returnValue.container = container;
|
|
142
151
|
}
|
|
143
152
|
continue;
|