@remotion/media-parser 4.0.210 → 4.0.211

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 (113) hide show
  1. package/dist/boxes/iso-base-media/mdat/mdat.d.ts +12 -4
  2. package/dist/boxes/iso-base-media/mdat/mdat.js +13 -3
  3. package/dist/boxes/iso-base-media/process-box.js +46 -7
  4. package/dist/boxes/iso-base-media/traversal.d.ts +2 -7
  5. package/dist/boxes/iso-base-media/traversal.js +5 -15
  6. package/dist/boxes/webm/color.js +29 -22
  7. package/dist/boxes/webm/ebml.d.ts +1 -1
  8. package/dist/boxes/webm/get-track.js +1 -16
  9. package/dist/boxes/webm/segments/parse-children.js +6 -0
  10. package/dist/buffer-iterator.d.ts +4 -1
  11. package/dist/buffer-iterator.js +31 -5
  12. package/dist/create/cluster.d.ts +8 -2
  13. package/dist/create/cluster.js +3 -2
  14. package/dist/create/create-media.d.ts +1 -1
  15. package/dist/create/create-media.js +44 -27
  16. package/dist/create/matroska-cues.d.ts +1 -1
  17. package/dist/create/matroska-cues.js +4 -5
  18. package/dist/create/matroska-trackentry.js +0 -8
  19. package/dist/esm/from-fetch.mjs +41 -6
  20. package/dist/esm/from-node.mjs +2 -1
  21. package/dist/esm/from-web-file.mjs +2 -1
  22. package/dist/esm/index.mjs +239 -106
  23. package/dist/get-audio-codec.d.ts +1 -1
  24. package/dist/get-audio-codec.js +4 -1
  25. package/dist/index.d.ts +1 -0
  26. package/dist/parse-media.js +34 -25
  27. package/dist/parser-context.d.ts +1 -0
  28. package/dist/readers/from-fetch.d.ts +12 -0
  29. package/dist/readers/from-fetch.js +59 -13
  30. package/dist/readers/from-node.js +1 -0
  31. package/dist/readers/from-web-file.js +1 -0
  32. package/dist/readers/reader.d.ts +1 -0
  33. package/dist/traversal.d.ts +21 -0
  34. package/dist/traversal.js +158 -1
  35. package/package.json +2 -2
  36. package/dist/av1-codec-string.d.ts +0 -3
  37. package/dist/av1-codec-string.js +0 -91
  38. package/dist/boxes/iso-base-media/ftype.d.ts +0 -9
  39. package/dist/boxes/iso-base-media/ftype.js +0 -31
  40. package/dist/boxes/iso-base-media/stsd/avcc-hvcc.d.ts +0 -20
  41. package/dist/boxes/iso-base-media/stsd/avcc-hvcc.js +0 -73
  42. package/dist/boxes/iso-base-media/stts/stts.d.ts +0 -15
  43. package/dist/boxes/iso-base-media/stts/stts.js +0 -35
  44. package/dist/boxes/webm/bitstream/av1/bitstream-frame-header.d.ts +0 -14
  45. package/dist/boxes/webm/bitstream/av1/bitstream-frame-header.js +0 -67
  46. package/dist/boxes/webm/bitstream/av1/bitstream-frame.d.ts +0 -11
  47. package/dist/boxes/webm/bitstream/av1/bitstream-frame.js +0 -14
  48. package/dist/boxes/webm/bitstream/av1/chroma-sample-position.d.ts +0 -6
  49. package/dist/boxes/webm/bitstream/av1/chroma-sample-position.js +0 -9
  50. package/dist/boxes/webm/bitstream/av1/color-config.d.ts +0 -16
  51. package/dist/boxes/webm/bitstream/av1/color-config.js +0 -103
  52. package/dist/boxes/webm/bitstream/av1/color-primaries.d.ts +0 -14
  53. package/dist/boxes/webm/bitstream/av1/color-primaries.js +0 -17
  54. package/dist/boxes/webm/bitstream/av1/decoder-model-info.d.ts +0 -9
  55. package/dist/boxes/webm/bitstream/av1/decoder-model-info.js +0 -17
  56. package/dist/boxes/webm/bitstream/av1/frame.d.ts +0 -0
  57. package/dist/boxes/webm/bitstream/av1/frame.js +0 -1
  58. package/dist/boxes/webm/bitstream/av1/header-segment.d.ts +0 -51
  59. package/dist/boxes/webm/bitstream/av1/header-segment.js +0 -183
  60. package/dist/boxes/webm/bitstream/av1/matrix-coefficients.d.ts +0 -17
  61. package/dist/boxes/webm/bitstream/av1/matrix-coefficients.js +0 -20
  62. package/dist/boxes/webm/bitstream/av1/operating-parameters-info.d.ts +0 -10
  63. package/dist/boxes/webm/bitstream/av1/operating-parameters-info.js +0 -15
  64. package/dist/boxes/webm/bitstream/av1/temporal-point-info.d.ts +0 -5
  65. package/dist/boxes/webm/bitstream/av1/temporal-point-info.js +0 -8
  66. package/dist/boxes/webm/bitstream/av1/timing-info.d.ts +0 -8
  67. package/dist/boxes/webm/bitstream/av1/timing-info.js +0 -20
  68. package/dist/boxes/webm/bitstream/av1/transfer-characteristics.d.ts +0 -21
  69. package/dist/boxes/webm/bitstream/av1/transfer-characteristics.js +0 -24
  70. package/dist/boxes/webm/bitstream/av1/uvlc.d.ts +0 -2
  71. package/dist/boxes/webm/bitstream/av1/uvlc.js +0 -20
  72. package/dist/boxes/webm/bitstream/av1.d.ts +0 -20
  73. package/dist/boxes/webm/bitstream/av1.js +0 -118
  74. package/dist/boxes/webm/bitstream/h264/get-h264-descriptor.d.ts +0 -0
  75. package/dist/boxes/webm/bitstream/h264/get-h264-descriptor.js +0 -1
  76. package/dist/boxes/webm/segments/duration.d.ts +0 -6
  77. package/dist/boxes/webm/segments/duration.js +0 -19
  78. package/dist/boxes/webm/segments/info.d.ts +0 -9
  79. package/dist/boxes/webm/segments/info.js +0 -22
  80. package/dist/boxes/webm/segments/main.d.ts +0 -5
  81. package/dist/boxes/webm/segments/main.js +0 -2
  82. package/dist/boxes/webm/segments/muxing.d.ts +0 -6
  83. package/dist/boxes/webm/segments/muxing.js +0 -11
  84. package/dist/boxes/webm/segments/seek-head.d.ts +0 -9
  85. package/dist/boxes/webm/segments/seek-head.js +0 -22
  86. package/dist/boxes/webm/segments/seek-position.d.ts +0 -6
  87. package/dist/boxes/webm/segments/seek-position.js +0 -11
  88. package/dist/boxes/webm/segments/seek.d.ts +0 -13
  89. package/dist/boxes/webm/segments/seek.js +0 -35
  90. package/dist/boxes/webm/segments/timestamp-scale.d.ts +0 -6
  91. package/dist/boxes/webm/segments/timestamp-scale.js +0 -11
  92. package/dist/boxes/webm/segments/tracks.d.ts +0 -8
  93. package/dist/boxes/webm/segments/tracks.js +0 -21
  94. package/dist/boxes/webm/segments/unknown.d.ts +0 -6
  95. package/dist/boxes/webm/segments/unknown.js +0 -11
  96. package/dist/boxes/webm/segments/void.d.ts +0 -6
  97. package/dist/boxes/webm/segments/void.js +0 -11
  98. package/dist/boxes/webm/segments/writing.d.ts +0 -6
  99. package/dist/boxes/webm/segments/writing.js +0 -11
  100. package/dist/boxes/webm/tracks.d.ts +0 -8
  101. package/dist/boxes/webm/tracks.js +0 -21
  102. package/dist/combine-uint8array.d.ts +0 -1
  103. package/dist/combine-uint8array.js +0 -13
  104. package/dist/create/cues.d.ts +0 -0
  105. package/dist/create/cues.js +0 -1
  106. package/dist/from-web.d.ts +0 -2
  107. package/dist/from-web.js +0 -45
  108. package/dist/get-video-metadata.d.ts +0 -2
  109. package/dist/get-video-metadata.js +0 -44
  110. package/dist/read-and-increment-offset.d.ts +0 -28
  111. package/dist/read-and-increment-offset.js +0 -177
  112. package/dist/understand-vorbis.d.ts +0 -1
  113. package/dist/understand-vorbis.js +0 -12
@@ -14,7 +14,7 @@ const matroska_segment_1 = require("./matroska-segment");
14
14
  const matroska_trackentry_1 = require("./matroska-trackentry");
15
15
  const timescale_1 = require("./timescale");
16
16
  const createMedia = async (writer) => {
17
- var _a, _b, _c, _d, _e, _f;
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();
20
20
  await w.write(header.bytes);
@@ -26,13 +26,16 @@ const createMedia = async (writer) => {
26
26
  const cues = [];
27
27
  const trackNumbers = [];
28
28
  const matroskaSegment = (0, matroska_segment_1.createMatroskaSegment)([
29
- matroskaInfo,
30
29
  ...(0, matroska_seek_1.createMatroskaSeekHead)(seeks),
30
+ matroskaInfo,
31
31
  ...(0, matroska_trackentry_1.makeMatroskaTracks)(currentTracks),
32
32
  ]);
33
- const durationOffset = ((_b = (_a = matroskaSegment.offsets.children[0].children.find((c) => c.field === 'Duration')) === null || _a === void 0 ? void 0 : _a.offset) !== null && _b !== void 0 ? _b : 0) + w.getWrittenByteCount();
33
+ const infoSegment = matroskaSegment.offsets.children.find((o) => o.field === 'Info');
34
+ const durationOffset = ((_b = (_a = infoSegment === null || infoSegment === void 0 ? void 0 : infoSegment.children.find((c) => c.field === 'Duration')) === null || _a === void 0 ? void 0 : _a.offset) !== null && _b !== void 0 ? _b : 0) +
35
+ w.getWrittenByteCount();
34
36
  const tracksOffset = ((_d = (_c = matroskaSegment.offsets.children.find((o) => o.field === 'Tracks')) === null || _c === void 0 ? void 0 : _c.offset) !== null && _d !== void 0 ? _d : 0) + w.getWrittenByteCount();
35
37
  const seekHeadOffset = ((_f = (_e = matroskaSegment.offsets.children.find((o) => o.field === 'SeekHead')) === null || _e === void 0 ? void 0 : _e.offset) !== null && _f !== void 0 ? _f : 0) + w.getWrittenByteCount();
38
+ const infoOffset = ((_g = infoSegment === null || infoSegment === void 0 ? void 0 : infoSegment.offset) !== null && _g !== void 0 ? _g : 0) + w.getWrittenByteCount();
36
39
  if (!seekHeadOffset) {
37
40
  throw new Error('could not get seek offset');
38
41
  }
@@ -42,6 +45,13 @@ const createMedia = async (writer) => {
42
45
  if (!tracksOffset) {
43
46
  throw new Error('could not get tracks offset');
44
47
  }
48
+ if (!infoOffset) {
49
+ throw new Error('could not get tracks offset');
50
+ }
51
+ seeks.push({
52
+ hexString: all_segments_1.matroskaElements.Info,
53
+ byte: infoOffset - seekHeadOffset,
54
+ });
45
55
  seeks.push({
46
56
  hexString: all_segments_1.matroskaElements.Tracks,
47
57
  byte: tracksOffset - seekHeadOffset,
@@ -50,11 +60,10 @@ const createMedia = async (writer) => {
50
60
  const updatedSeek = (0, matroska_seek_1.createMatroskaSeekHead)(seeks);
51
61
  await w.updateDataAt(seekHeadOffset, (0, make_header_1.combineUint8Arrays)(updatedSeek.map((b) => b.bytes)));
52
62
  };
53
- const segmentOffset = w.getWrittenByteCount() +
54
- (0, make_header_1.matroskaToHex)(all_segments_1.matroskaElements.Segment).byteLength;
63
+ const segmentOffset = w.getWrittenByteCount();
55
64
  const updateSegmentSize = async (size) => {
56
65
  const data = (0, ebml_1.getVariableInt)(size, matroska_segment_1.MATROSKA_SEGMENT_MIN_VINT_WIDTH);
57
- await w.updateDataAt(segmentOffset, data);
66
+ await w.updateDataAt(segmentOffset + (0, make_header_1.matroskaToHex)(all_segments_1.matroskaElements.Segment).byteLength, data);
58
67
  };
59
68
  await w.write(matroskaSegment.bytes);
60
69
  const clusterOffset = w.getWrittenByteCount();
@@ -63,33 +72,38 @@ const createMedia = async (writer) => {
63
72
  hexString: all_segments_1.matroskaElements.Cluster,
64
73
  byte: clusterOffset - seekHeadOffset,
65
74
  });
66
- cues.push({
67
- time: 0,
68
- clusterPosition: clusterOffset - seekHeadOffset,
69
- trackNumbers,
70
- });
71
75
  const trackNumberProgresses = {};
72
- const getClusterOrMakeNew = async (chunk) => {
76
+ const getClusterOrMakeNew = async ({ chunk, isVideo, }) => {
73
77
  const smallestProgress = Math.min(...Object.values(trackNumberProgresses));
74
- if (!currentCluster.shouldMakeNewCluster(smallestProgress, chunk.type === 'key')) {
75
- return currentCluster;
78
+ if (!currentCluster.shouldMakeNewCluster({
79
+ newT: smallestProgress,
80
+ keyframe: chunk.type === 'key',
81
+ isVideo,
82
+ })) {
83
+ return { cluster: currentCluster, isNew: false, smallestProgress };
76
84
  }
77
- const newCluster = w.getWrittenByteCount();
78
- cues.push({
79
- time: smallestProgress,
80
- clusterPosition: newCluster - seekHeadOffset,
81
- trackNumbers,
82
- });
83
85
  currentCluster = await (0, cluster_1.makeCluster)(w, smallestProgress);
84
- return currentCluster;
86
+ return { cluster: currentCluster, isNew: true, smallestProgress };
85
87
  };
86
- const addSample = async (chunk, trackNumber) => {
88
+ const addSample = async (chunk, trackNumber, isVideo) => {
87
89
  var _a;
88
90
  trackNumberProgresses[trackNumber] = chunk.timestamp;
89
- const cluster = await getClusterOrMakeNew(chunk);
91
+ const { cluster, isNew, smallestProgress } = await getClusterOrMakeNew({
92
+ chunk,
93
+ isVideo,
94
+ });
90
95
  const newDuration = Math.round((chunk.timestamp + ((_a = chunk.duration) !== null && _a !== void 0 ? _a : 0)) / 1000);
91
96
  await updateDuration(newDuration);
92
- return cluster.addSample(chunk, trackNumber);
97
+ const { timecodeRelativeToCluster } = await cluster.addSample(chunk, trackNumber);
98
+ if (isNew) {
99
+ const newCluster = w.getWrittenByteCount();
100
+ cues.push({
101
+ time: (0, cluster_1.timestampToClusterTimestamp)(smallestProgress) +
102
+ timecodeRelativeToCluster,
103
+ clusterPosition: newCluster - seekHeadOffset,
104
+ trackNumber,
105
+ });
106
+ }
93
107
  };
94
108
  const updateDuration = async (newDuration) => {
95
109
  const blocks = (0, make_duration_with_padding_1.makeDurationWithPadding)(newDuration);
@@ -110,8 +124,8 @@ const createMedia = async (writer) => {
110
124
  remove: async () => {
111
125
  await w.remove();
112
126
  },
113
- addSample: (chunk, trackNumber) => {
114
- operationProm.current = operationProm.current.then(() => addSample(chunk, trackNumber));
127
+ addSample: (chunk, trackNumber, isVideo) => {
128
+ operationProm.current = operationProm.current.then(() => addSample(chunk, trackNumber, isVideo));
115
129
  return operationProm.current;
116
130
  },
117
131
  updateDuration: (duration) => {
@@ -139,8 +153,11 @@ const createMedia = async (writer) => {
139
153
  });
140
154
  await updateSeekWrite();
141
155
  await w.write((0, matroska_cues_1.createMatroskaCues)(cues).bytes);
142
- const segmentSize = w.getWrittenByteCount() - segmentOffset;
143
156
  await w.waitForFinish();
157
+ const segmentSize = w.getWrittenByteCount() -
158
+ segmentOffset -
159
+ (0, make_header_1.matroskaToHex)(all_segments_1.matroskaElements.Segment).byteLength -
160
+ matroska_segment_1.MATROSKA_SEGMENT_MIN_VINT_WIDTH;
144
161
  await updateSegmentSize(segmentSize);
145
162
  },
146
163
  };
@@ -1,6 +1,6 @@
1
1
  export type Cue = {
2
2
  time: number;
3
3
  clusterPosition: number;
4
- trackNumbers: number[];
4
+ trackNumber: number;
5
5
  };
6
6
  export declare const createMatroskaCues: (cues: Cue[]) => import("../boxes/webm/segments/all-segments").BytesAndOffset;
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createMatroskaCues = void 0;
4
4
  const make_header_1 = require("../boxes/webm/make-header");
5
- const cluster_1 = require("./cluster");
6
5
  const createMatroskaCues = (cues) => {
7
6
  return (0, make_header_1.makeMatroskaBytes)({
8
7
  type: 'Cues',
@@ -15,18 +14,18 @@ const createMatroskaCues = (cues) => {
15
14
  type: 'CueTime',
16
15
  minVintWidth: null,
17
16
  value: {
18
- value: (0, cluster_1.timestampToClusterTimestamp)(cue.time),
17
+ value: cue.time,
19
18
  byteLength: null,
20
19
  },
21
20
  },
22
- ...cue.trackNumbers.map((trackNumber) => ({
21
+ {
23
22
  type: 'CueTrackPositions',
24
23
  value: [
25
24
  {
26
25
  type: 'CueTrack',
27
26
  minVintWidth: null,
28
27
  value: {
29
- value: trackNumber,
28
+ value: cue.trackNumber,
30
29
  byteLength: null,
31
30
  },
32
31
  },
@@ -40,7 +39,7 @@ const createMatroskaCues = (cues) => {
40
39
  },
41
40
  ],
42
41
  minVintWidth: null,
43
- })),
42
+ },
44
43
  ],
45
44
  minVintWidth: null,
46
45
  };
@@ -119,14 +119,6 @@ const makeMatroskaAudioTrackEntryBytes = ({ trackNumber, codec, numberOfChannels
119
119
  },
120
120
  minVintWidth: null,
121
121
  },
122
- {
123
- type: 'TrackTimestampScale',
124
- value: {
125
- value: 1,
126
- size: '64',
127
- },
128
- minVintWidth: null,
129
- },
130
122
  {
131
123
  type: 'CodecID',
132
124
  value: makeAudioCodecId(codec),
@@ -1,4 +1,32 @@
1
1
  // src/readers/from-fetch.ts
2
+ function parseContentRange(input) {
3
+ const matches = input.match(/^(\w+) ((\d+)-(\d+)|\*)\/(\d+|\*)$/);
4
+ if (!matches)
5
+ return null;
6
+ const [, unit, , start, end, size] = matches;
7
+ const range = {
8
+ unit,
9
+ start: start != null ? Number(start) : null,
10
+ end: end != null ? Number(end) : null,
11
+ size: size === "*" ? null : Number(size)
12
+ };
13
+ if (range.start === null && range.end === null && range.size === null) {
14
+ return null;
15
+ }
16
+ return range;
17
+ }
18
+ var validateContentRangeAndDetectIfSupported = (actualRange, parsedContentRange) => {
19
+ if (typeof actualRange === "number" && parsedContentRange?.start !== actualRange) {
20
+ if (actualRange === 0) {
21
+ return { supportsContentRange: false };
22
+ }
23
+ throw new Error(`Range header (${actualRange}) does not match content-range header (${parsedContentRange?.start})`);
24
+ }
25
+ if (actualRange !== null && typeof actualRange !== "number" && (parsedContentRange?.start !== actualRange[0] || parsedContentRange?.end !== actualRange[1])) {
26
+ throw new Error(`Range header (${actualRange}) does not match content-range header (${parsedContentRange?.start})`);
27
+ }
28
+ return { supportsContentRange: true };
29
+ };
2
30
  var fetchReader = {
3
31
  read: async (src, range, signal) => {
4
32
  if (typeof src !== "string") {
@@ -9,20 +37,25 @@ var fetchReader = {
9
37
  return Promise.reject(new Error(resolvedUrl + " is not a URL - needs to start with http:// or https:// or blob:. If you want to read a local file, pass `reader: nodeReader` to parseMedia()."));
10
38
  }
11
39
  const controller = new AbortController;
40
+ const cache = typeof navigator !== "undefined" && navigator.userAgent.includes("Cloudflare-Workers") ? undefined : "no-store";
41
+ const actualRange = range === null ? 0 : range;
12
42
  const res = await fetch(resolvedUrl, {
13
- headers: range === null ? {} : typeof range === "number" ? {
14
- Range: `bytes=${range}`
43
+ headers: typeof actualRange === "number" ? {
44
+ Range: `bytes=${actualRange}-`
15
45
  } : {
16
- Range: `bytes=${`${range[0]}-${range[1]}`}`
46
+ Range: `bytes=${`${actualRange[0]}-${actualRange[1]}`}`
17
47
  },
18
48
  signal: controller.signal,
19
- cache: "no-store"
49
+ cache
20
50
  });
51
+ const contentRange = res.headers.get("content-range");
52
+ const parsedContentRange = contentRange ? parseContentRange(contentRange) : null;
53
+ const { supportsContentRange } = validateContentRangeAndDetectIfSupported(actualRange, parsedContentRange);
21
54
  signal?.addEventListener("abort", () => {
22
55
  controller.abort();
23
56
  }, { once: true });
24
57
  if (res.status.toString().startsWith("4") || res.status.toString().startsWith("5")) {
25
- throw new Error(`Server returned status code ${res.status} for ${src}`);
58
+ throw new Error(`Server returned status code ${res.status} for ${src} and range ${actualRange}`);
26
59
  }
27
60
  if (!res.body) {
28
61
  throw new Error("No body");
@@ -47,7 +80,8 @@ var fetchReader = {
47
80
  }
48
81
  },
49
82
  contentLength,
50
- name: name ?? fallbackName
83
+ name: name ?? fallbackName,
84
+ supportsContentRange
51
85
  };
52
86
  },
53
87
  getLength: async (src) => {
@@ -68,5 +102,6 @@ var fetchReader = {
68
102
  }
69
103
  };
70
104
  export {
105
+ parseContentRange,
71
106
  fetchReader
72
107
  };
@@ -32,7 +32,8 @@ var nodeReader = {
32
32
  }
33
33
  },
34
34
  contentLength: stats.size,
35
- name: src.split("/").pop()
35
+ name: src.split("/").pop(),
36
+ supportsContentRange: true
36
37
  };
37
38
  },
38
39
  getLength: async (src) => {
@@ -28,7 +28,8 @@ var webFileReader = {
28
28
  }
29
29
  },
30
30
  contentLength: file.size,
31
- name: file.name
31
+ name: file.name,
32
+ supportsContentRange: true
32
33
  });
33
34
  };
34
35
  reader.onerror = (error) => {