@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.
Files changed (41) hide show
  1. package/dist/boxes/iso-base-media/esds/decoder-specific-config.d.ts +1 -2
  2. package/dist/boxes/iso-base-media/esds/decoder-specific-config.js +1 -5
  3. package/dist/boxes/iso-base-media/esds/esds-descriptors.d.ts +2 -4
  4. package/dist/boxes/iso-base-media/esds/esds-descriptors.js +3 -4
  5. package/dist/boxes/iso-base-media/esds/esds.d.ts +1 -3
  6. package/dist/boxes/iso-base-media/esds/esds.js +2 -2
  7. package/dist/boxes/iso-base-media/get-sample-positions-from-track.js +7 -1
  8. package/dist/boxes/iso-base-media/process-box.js +0 -1
  9. package/dist/boxes/iso-base-media/stsd/samples.js +6 -5
  10. package/dist/create/event-emitter.d.ts +31 -0
  11. package/dist/create/event-emitter.js +25 -0
  12. package/dist/create/iso-base-media/create-iso-base-media.d.ts +1 -1
  13. package/dist/create/iso-base-media/create-iso-base-media.js +3 -1
  14. package/dist/create/matroska/cluster.js +1 -1
  15. package/dist/create/matroska/create-matroska-media.d.ts +1 -1
  16. package/dist/create/matroska/create-matroska-media.js +7 -10
  17. package/dist/create/media-fn.d.ts +2 -0
  18. package/dist/create/progress-tracker.d.ts +7 -0
  19. package/dist/create/progress-tracker.js +43 -0
  20. package/dist/create/wav/create-wav.d.ts +1 -1
  21. package/dist/create/wav/create-wav.js +3 -1
  22. package/dist/create/with-resolvers.d.ts +10 -0
  23. package/dist/create/with-resolvers.js +28 -0
  24. package/dist/emit-available-info.js +11 -2
  25. package/dist/esm/index.mjs +235 -68
  26. package/dist/get-audio-codec.d.ts +1 -0
  27. package/dist/get-audio-codec.js +15 -1
  28. package/dist/get-is-hdr.d.ts +4 -0
  29. package/dist/get-is-hdr.js +18 -0
  30. package/dist/get-sample-positions-from-lpcm.d.ts +3 -0
  31. package/dist/get-sample-positions-from-lpcm.js +46 -0
  32. package/dist/get-tracks.d.ts +3 -3
  33. package/dist/get-video-codec.js +9 -3
  34. package/dist/has-all-info.js +6 -1
  35. package/dist/index.d.ts +23 -4
  36. package/dist/index.js +7 -0
  37. package/dist/options.d.ts +7 -0
  38. package/dist/parse-media.js +1 -1
  39. package/dist/version.d.ts +1 -1
  40. package/dist/version.js +1 -1
  41. 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, logLevel: LogLevel) => DecoderSpecificConfig;
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 log_1 = require("../../../log");
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, logLevel, }: {
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, logLevel: LogLevel) => Descriptor[];
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, logLevel, }) => {
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, logLevel);
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, logLevel) => {
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, logLevel, }: {
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, logLevel, }) => {
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, logLevel);
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
  }
@@ -444,7 +444,6 @@ const processBox = async ({ iterator, allowIncompleteBoxes, parsedBoxes, options
444
444
  data: iterator,
445
445
  size: boxSize,
446
446
  fileOffset,
447
- logLevel,
448
447
  });
449
448
  return {
450
449
  type: 'complete',
@@ -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
- const numberOfChannels = iterator.getUint16();
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 bitsPerCodedSample = iterator.getUint32();
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: bitsPerCodedSample,
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 trackNumberProgresses = {};
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
- // Also doing this AFTER smallestProgress is calculated
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
- (_o = moreFields.onContainer) === null || _o === void 0 ? void 0 : _o.call(moreFields, container);
149
+ (_p = moreFields.onContainer) === null || _p === void 0 ? void 0 : _p.call(moreFields, container);
141
150
  returnValue.container = container;
142
151
  }
143
152
  continue;