@remotion/media-parser 4.0.229 → 4.0.231

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 (182) hide show
  1. package/dist/boxes/iso-base-media/esds/decoder-specific-config.d.ts +3 -2
  2. package/dist/boxes/iso-base-media/esds/decoder-specific-config.js +7 -8
  3. package/dist/boxes/iso-base-media/esds/esds-descriptors.d.ts +4 -2
  4. package/dist/boxes/iso-base-media/esds/esds-descriptors.js +5 -4
  5. package/dist/boxes/iso-base-media/esds/esds.d.ts +3 -1
  6. package/dist/boxes/iso-base-media/esds/esds.js +2 -2
  7. package/dist/boxes/iso-base-media/make-track.js +2 -1
  8. package/dist/boxes/iso-base-media/mdat/mdat.js +13 -7
  9. package/dist/boxes/iso-base-media/moov/moov.d.ts +3 -1
  10. package/dist/boxes/iso-base-media/moov/moov.js +2 -2
  11. package/dist/boxes/iso-base-media/mvhd.js +11 -9
  12. package/dist/boxes/iso-base-media/parse-icc-profile.d.ts +36 -0
  13. package/dist/boxes/iso-base-media/parse-icc-profile.js +115 -0
  14. package/dist/boxes/iso-base-media/process-box.d.ts +5 -4
  15. package/dist/boxes/iso-base-media/process-box.js +17 -14
  16. package/dist/boxes/iso-base-media/stsd/colr.d.ts +14 -4
  17. package/dist/boxes/iso-base-media/stsd/colr.js +13 -1
  18. package/dist/boxes/iso-base-media/stsd/mebx.d.ts +1 -2
  19. package/dist/boxes/iso-base-media/stsd/mebx.js +2 -2
  20. package/dist/boxes/iso-base-media/stsd/samples.d.ts +5 -2
  21. package/dist/boxes/iso-base-media/stsd/samples.js +7 -6
  22. package/dist/boxes/iso-base-media/stsd/stsd.js +1 -0
  23. package/dist/boxes/iso-base-media/to-date.d.ts +1 -0
  24. package/dist/boxes/iso-base-media/to-date.js +9 -1
  25. package/dist/boxes/iso-base-media/trak/trak.d.ts +3 -1
  26. package/dist/boxes/iso-base-media/trak/trak.js +2 -2
  27. package/dist/boxes/webm/av1-codec-private.js +1 -1
  28. package/dist/boxes/webm/ebml.d.ts +1 -1
  29. package/dist/boxes/webm/get-sample-from-block.d.ts +4 -4
  30. package/dist/boxes/webm/get-sample-from-block.js +4 -2
  31. package/dist/boxes/webm/make-track.js +1 -0
  32. package/dist/boxes/webm/parse-webm-header.js +23 -4
  33. package/dist/boxes/webm/segments/parse-children.d.ts +12 -7
  34. package/dist/boxes/webm/segments/parse-children.js +67 -57
  35. package/dist/boxes/webm/segments.d.ts +8 -3
  36. package/dist/boxes/webm/segments.js +70 -39
  37. package/dist/buffer-iterator.d.ts +1 -1
  38. package/dist/buffer-iterator.js +1 -8
  39. package/dist/create/iso-base-media/codec-specific/avc1.d.ts +2 -0
  40. package/dist/create/iso-base-media/codec-specific/avc1.js +48 -0
  41. package/dist/create/iso-base-media/codec-specific/create-codec-specific-data.d.ts +22 -0
  42. package/dist/create/iso-base-media/codec-specific/create-codec-specific-data.js +36 -0
  43. package/dist/create/iso-base-media/codec-specific/mp4a.d.ts +2 -0
  44. package/dist/create/iso-base-media/codec-specific/mp4a.js +90 -0
  45. package/dist/create/iso-base-media/create-colr.d.ts +6 -0
  46. package/dist/create/iso-base-media/create-colr.js +26 -0
  47. package/dist/create/iso-base-media/create-ftyp.d.ts +10 -0
  48. package/dist/create/iso-base-media/create-ftyp.js +22 -0
  49. package/dist/create/iso-base-media/create-ilst.d.ts +1 -0
  50. package/dist/create/iso-base-media/create-ilst.js +14 -0
  51. package/dist/create/iso-base-media/create-iso-base-media.d.ts +2 -0
  52. package/dist/create/iso-base-media/create-iso-base-media.js +167 -0
  53. package/dist/create/iso-base-media/create-mdia.d.ts +5 -0
  54. package/dist/create/iso-base-media/create-mdia.js +18 -0
  55. package/dist/create/iso-base-media/create-moov.d.ts +5 -0
  56. package/dist/create/iso-base-media/create-moov.js +18 -0
  57. package/dist/create/iso-base-media/create-mvhd.d.ts +10 -0
  58. package/dist/create/iso-base-media/create-mvhd.js +48 -0
  59. package/dist/create/iso-base-media/create-trak.d.ts +4 -0
  60. package/dist/create/iso-base-media/create-trak.js +17 -0
  61. package/dist/create/iso-base-media/create-udta.d.ts +1 -0
  62. package/dist/create/iso-base-media/create-udta.js +14 -0
  63. package/dist/create/iso-base-media/create-url.d.ts +1 -0
  64. package/dist/create/iso-base-media/create-url.js +16 -0
  65. package/dist/create/iso-base-media/example-stts.d.ts +3 -0
  66. package/dist/create/iso-base-media/example-stts.js +2797 -0
  67. package/dist/create/iso-base-media/ilst/create-cmt.d.ts +1 -0
  68. package/dist/create/iso-base-media/ilst/create-cmt.js +26 -0
  69. package/dist/create/iso-base-media/ilst/create-too.d.ts +1 -0
  70. package/dist/create/iso-base-media/ilst/create-too.js +27 -0
  71. package/dist/create/iso-base-media/mdia/create-mdhd.d.ts +6 -0
  72. package/dist/create/iso-base-media/mdia/create-mdhd.js +33 -0
  73. package/dist/create/iso-base-media/mp4-header.d.ts +6 -0
  74. package/dist/create/iso-base-media/mp4-header.js +47 -0
  75. package/dist/create/iso-base-media/primitives.d.ts +15 -0
  76. package/dist/create/iso-base-media/primitives.js +133 -0
  77. package/dist/create/iso-base-media/serialize-track.d.ts +9 -0
  78. package/dist/create/iso-base-media/serialize-track.js +63 -0
  79. package/dist/create/iso-base-media/trak/create-tkhd.d.ts +27 -0
  80. package/dist/create/iso-base-media/trak/create-tkhd.js +97 -0
  81. package/dist/create/iso-base-media/trak/mdia/create-minf.d.ts +4 -0
  82. package/dist/create/iso-base-media/trak/mdia/create-minf.js +19 -0
  83. package/dist/create/iso-base-media/trak/mdia/minf/create-dinf.d.ts +1 -0
  84. package/dist/create/iso-base-media/trak/mdia/minf/create-dinf.js +22 -0
  85. package/dist/create/iso-base-media/trak/mdia/minf/create-smhd.d.ts +1 -0
  86. package/dist/create/iso-base-media/trak/mdia/minf/create-smhd.js +20 -0
  87. package/dist/create/iso-base-media/trak/mdia/minf/create-stbl.d.ts +6 -0
  88. package/dist/create/iso-base-media/trak/mdia/minf/create-stbl.js +35 -0
  89. package/dist/create/iso-base-media/trak/mdia/minf/create-vmhd.d.ts +1 -0
  90. package/dist/create/iso-base-media/trak/mdia/minf/create-vmhd.js +20 -0
  91. package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-ctts.d.ts +2 -0
  92. package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-ctts.js +45 -0
  93. package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-stco.d.ts +2 -0
  94. package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-stco.js +28 -0
  95. package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-stsc.d.ts +2 -0
  96. package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-stsc.js +56 -0
  97. package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-stss.d.ts +2 -0
  98. package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-stss.js +23 -0
  99. package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-stsz.d.ts +2 -0
  100. package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-stsz.js +25 -0
  101. package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-stts.d.ts +2 -0
  102. package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-stts.js +48 -0
  103. package/dist/create/iso-base-media/trak/mdia/minf/stbl/stsd/create-avc1.d.ts +1 -0
  104. package/dist/create/iso-base-media/trak/mdia/minf/stbl/stsd/create-avc1.js +20 -0
  105. package/dist/create/iso-base-media/trak/mdia/minf/stbl/stsd/create-avcc.d.ts +1 -0
  106. package/dist/create/iso-base-media/trak/mdia/minf/stbl/stsd/create-avcc.js +16 -0
  107. package/dist/create/iso-base-media/trak/mdia/minf/stbl/stsd/create-pasp.d.ts +1 -0
  108. package/dist/create/iso-base-media/trak/mdia/minf/stbl/stsd/create-pasp.js +13 -0
  109. package/dist/create/iso-base-media/udta/create-meta.d.ts +4 -0
  110. package/dist/create/iso-base-media/udta/create-meta.js +20 -0
  111. package/dist/create/iso-base-media/udta/meta/create-hdlr.d.ts +1 -0
  112. package/dist/create/iso-base-media/udta/meta/create-hdlr.js +32 -0
  113. package/dist/create/make-track-info.d.ts +20 -0
  114. package/dist/create/make-track-info.js +2 -0
  115. package/dist/create/{cluster-segment.d.ts → matroska/cluster-segment.d.ts} +1 -1
  116. package/dist/create/{cluster-segment.js → matroska/cluster-segment.js} +2 -2
  117. package/dist/create/{cluster.d.ts → matroska/cluster.d.ts} +12 -5
  118. package/dist/create/{cluster.js → matroska/cluster.js} +23 -20
  119. package/dist/create/matroska/create-matroska-media.d.ts +2 -0
  120. package/dist/create/{create-media.js → matroska/create-matroska-media.js} +49 -25
  121. package/dist/create/matroska/make-duration-with-padding.d.ts +1 -0
  122. package/dist/create/{make-duration-with-padding.js → matroska/make-duration-with-padding.js} +1 -1
  123. package/dist/create/{matroska-cues.d.ts → matroska/matroska-cues.d.ts} +1 -1
  124. package/dist/create/{matroska-cues.js → matroska/matroska-cues.js} +1 -1
  125. package/dist/create/matroska/matroska-header.d.ts +1 -0
  126. package/dist/create/{matroska-header.js → matroska/matroska-header.js} +1 -1
  127. package/dist/create/{matroska-info.d.ts → matroska/matroska-info.d.ts} +1 -1
  128. package/dist/create/{matroska-info.js → matroska/matroska-info.js} +1 -1
  129. package/dist/create/matroska/matroska-seek.d.ts +6 -0
  130. package/dist/create/{matroska-seek.js → matroska/matroska-seek.js} +1 -1
  131. package/dist/create/{matroska-segment.d.ts → matroska/matroska-segment.d.ts} +1 -1
  132. package/dist/create/{matroska-segment.js → matroska/matroska-segment.js} +1 -1
  133. package/dist/create/matroska/matroska-trackentry.d.ts +10 -0
  134. package/dist/create/{matroska-trackentry.js → matroska/matroska-trackentry.js} +9 -3
  135. package/dist/create/{create-media.d.ts → media-fn.d.ts} +17 -4
  136. package/dist/create/media-fn.js +2 -0
  137. package/dist/create/timescale.d.ts +1 -1
  138. package/dist/create/timescale.js +2 -2
  139. package/dist/emit-available-info.d.ts +1 -1
  140. package/dist/emit-available-info.js +23 -10
  141. package/dist/esm/buffer.mjs +3 -3
  142. package/dist/esm/index.mjs +2104 -735
  143. package/dist/esm/web-fs.mjs +2 -2
  144. package/dist/get-audio-codec.d.ts +2 -1
  145. package/dist/get-audio-codec.js +29 -10
  146. package/dist/get-duration.d.ts +5 -0
  147. package/dist/get-duration.js +7 -3
  148. package/dist/get-fps.d.ts +1 -0
  149. package/dist/get-fps.js +24 -13
  150. package/dist/get-sample-positions.d.ts +1 -0
  151. package/dist/get-sample-positions.js +1 -0
  152. package/dist/get-tracks.d.ts +1 -0
  153. package/dist/get-video-codec.d.ts +2 -2
  154. package/dist/get-video-codec.js +6 -6
  155. package/dist/has-all-info.d.ts +1 -1
  156. package/dist/has-all-info.js +8 -8
  157. package/dist/index.d.ts +6 -8
  158. package/dist/index.js +7 -3
  159. package/dist/options.d.ts +10 -1
  160. package/dist/parse-media.js +42 -14
  161. package/dist/parse-result.d.ts +15 -0
  162. package/dist/parse-video.d.ts +3 -1
  163. package/dist/parse-video.js +6 -14
  164. package/dist/parser-state.d.ts +3 -3
  165. package/dist/readers/reader.d.ts +2 -2
  166. package/dist/samples-from-moof.js +1 -0
  167. package/dist/version.d.ts +1 -0
  168. package/dist/version.js +5 -0
  169. package/dist/webcodec-sample-types.d.ts +7 -20
  170. package/dist/writers/buffer-implementation/writer.d.ts +2 -2
  171. package/dist/writers/buffer-implementation/writer.js +3 -3
  172. package/dist/writers/web-fs.js +2 -3
  173. package/dist/writers/writer.d.ts +5 -3
  174. package/package.json +3 -3
  175. package/dist/create/make-duration-with-padding.d.ts +0 -1
  176. package/dist/create/matroska-header.d.ts +0 -1
  177. package/dist/create/matroska-seek.d.ts +0 -6
  178. package/dist/create/matroska-trackentry.d.ts +0 -27
  179. package/dist/create/polyfill-audio-sample.d.ts +0 -3
  180. package/dist/create/polyfill-audio-sample.js +0 -15
  181. package/dist/writers/buffer-implementation/multi-buffer.d.ts +0 -0
  182. package/dist/writers/buffer-implementation/multi-buffer.js +0 -1
@@ -1021,7 +1021,1111 @@ var combineUint8Arrays = (arrays) => {
1021
1021
  return result;
1022
1022
  };
1023
1023
 
1024
- // src/create/cluster-segment.ts
1024
+ // src/log.ts
1025
+ var logLevels = ["trace", "verbose", "info", "warn", "error"];
1026
+ var getNumberForLogLevel = (level) => {
1027
+ return logLevels.indexOf(level);
1028
+ };
1029
+ var isEqualOrBelowLogLevel = (currentLevel, level) => {
1030
+ return getNumberForLogLevel(currentLevel) <= getNumberForLogLevel(level);
1031
+ };
1032
+ var Log = {
1033
+ trace: (logLevel, ...args) => {
1034
+ if (isEqualOrBelowLogLevel(logLevel, "trace")) {
1035
+ return console.log(...args);
1036
+ }
1037
+ },
1038
+ verbose: (logLevel, ...args) => {
1039
+ if (isEqualOrBelowLogLevel(logLevel, "verbose")) {
1040
+ return console.log(...args);
1041
+ }
1042
+ },
1043
+ info: (logLevel, ...args) => {
1044
+ if (isEqualOrBelowLogLevel(logLevel, "info")) {
1045
+ return console.log(...args);
1046
+ }
1047
+ },
1048
+ warn: (logLevel, ...args) => {
1049
+ if (isEqualOrBelowLogLevel(logLevel, "warn")) {
1050
+ return console.warn(...args);
1051
+ }
1052
+ },
1053
+ error: (...args) => {
1054
+ return console.error(...args);
1055
+ }
1056
+ };
1057
+
1058
+ // src/create/iso-base-media/primitives.ts
1059
+ var stringsToUint8Array = (str) => {
1060
+ return new TextEncoder().encode(str);
1061
+ };
1062
+ var numberTo32BitUIntOrInt = (num) => {
1063
+ return new Uint8Array([
1064
+ num >> 24 & 255,
1065
+ num >> 16 & 255,
1066
+ num >> 8 & 255,
1067
+ num & 255
1068
+ ]);
1069
+ };
1070
+ var numberTo32BitUIntOrIntLeading128 = (num) => {
1071
+ const arr = [
1072
+ num >> 24 & 255,
1073
+ num >> 16 & 255,
1074
+ num >> 8 & 255,
1075
+ num & 255
1076
+ ];
1077
+ for (const i in arr) {
1078
+ if (arr[i] === 0) {
1079
+ arr[i] = 128;
1080
+ } else {
1081
+ break;
1082
+ }
1083
+ }
1084
+ return new Uint8Array(arr);
1085
+ };
1086
+ var numberTo16BitUIntOrInt = (num) => {
1087
+ return new Uint8Array([num >> 8 & 255, num & 255]);
1088
+ };
1089
+ var setFixedPointSignedOrUnsigned1616Number = (num) => {
1090
+ const val = Math.round(num * 2 ** 16);
1091
+ return numberTo32BitUIntOrInt(val);
1092
+ };
1093
+ var setFixedPointSigned230Number = (num) => {
1094
+ const val = Math.round(num * 2 ** 30);
1095
+ return numberTo32BitUIntOrInt(val);
1096
+ };
1097
+ var addSize = (arr) => {
1098
+ return combineUint8Arrays([numberTo32BitUIntOrInt(arr.length + 4), arr]);
1099
+ };
1100
+ var addLeading128Size = (arr) => {
1101
+ return combineUint8Arrays([
1102
+ numberTo32BitUIntOrIntLeading128(arr.length),
1103
+ arr
1104
+ ]);
1105
+ };
1106
+ var floatTo16Point1632Bit = (number) => {
1107
+ const fixedNumber = Number(number.toFixed(2));
1108
+ const result = new Uint8Array(4);
1109
+ const tens = Math.floor(fixedNumber / 10);
1110
+ const ones = Math.floor(fixedNumber % 10);
1111
+ const tenths = Math.floor(fixedNumber * 10 % 10);
1112
+ const hundredths = Math.floor(fixedNumber * 100 % 10);
1113
+ result[0] = tens;
1114
+ result[1] = ones;
1115
+ result[2] = tenths;
1116
+ result[3] = hundredths;
1117
+ return result;
1118
+ };
1119
+ var floatTo16Point16_16Bit = (number) => {
1120
+ const fixedNumber = Number(number.toFixed(2));
1121
+ const result = new Uint8Array(2);
1122
+ const ones = Math.floor(fixedNumber % 10);
1123
+ const tenths = Math.floor(fixedNumber * 10 % 10);
1124
+ result[0] = ones;
1125
+ result[1] = tenths;
1126
+ return result;
1127
+ };
1128
+ var serializeMatrix = (matrix) => {
1129
+ return combineUint8Arrays([
1130
+ setFixedPointSignedOrUnsigned1616Number(matrix[0]),
1131
+ setFixedPointSignedOrUnsigned1616Number(matrix[1]),
1132
+ setFixedPointSigned230Number(matrix[2]),
1133
+ setFixedPointSignedOrUnsigned1616Number(matrix[3]),
1134
+ setFixedPointSignedOrUnsigned1616Number(matrix[4]),
1135
+ setFixedPointSigned230Number(matrix[5]),
1136
+ setFixedPointSignedOrUnsigned1616Number(matrix[6]),
1137
+ setFixedPointSignedOrUnsigned1616Number(matrix[7]),
1138
+ setFixedPointSigned230Number(matrix[8])
1139
+ ]);
1140
+ };
1141
+ var stringToPascalString = (str) => {
1142
+ const buffer = new Uint8Array(32);
1143
+ for (let i = 0;i < Math.min(str.length, 32); i++) {
1144
+ buffer[i] = str.charCodeAt(i);
1145
+ }
1146
+ return buffer;
1147
+ };
1148
+ var padIsoBaseMediaBytes = (data, totalLength) => {
1149
+ if (data.length - 8 > totalLength) {
1150
+ throw new Error(`Data is longer than the total length: ${data.length - 8} > ${totalLength}`);
1151
+ }
1152
+ if (data.length - 8 === totalLength) {
1153
+ return data;
1154
+ }
1155
+ return combineUint8Arrays([
1156
+ data,
1157
+ addSize(combineUint8Arrays([
1158
+ stringsToUint8Array("free"),
1159
+ new Uint8Array(totalLength - (data.length - 8))
1160
+ ]))
1161
+ ]);
1162
+ };
1163
+ var IDENTITY_MATRIX = [1, 0, 0, 0, 1, 0, 0, 0, 1];
1164
+
1165
+ // src/create/iso-base-media/create-ftyp.ts
1166
+ var createFtyp = ({
1167
+ majorBrand,
1168
+ minorBrand,
1169
+ compatibleBrands
1170
+ }) => {
1171
+ const type = stringsToUint8Array("ftyp");
1172
+ const majorBrandArr = stringsToUint8Array(majorBrand);
1173
+ const minorBrandArr = numberTo32BitUIntOrInt(minorBrand);
1174
+ const compatibleBrandsArr = combineUint8Arrays(compatibleBrands.map((b) => stringsToUint8Array(b)));
1175
+ return addSize(combineUint8Arrays([
1176
+ type,
1177
+ majorBrandArr,
1178
+ minorBrandArr,
1179
+ compatibleBrandsArr
1180
+ ]));
1181
+ };
1182
+ var createIsoBaseMediaFtyp = ({
1183
+ majorBrand,
1184
+ minorBrand,
1185
+ compatibleBrands
1186
+ }) => {
1187
+ return createFtyp({ compatibleBrands, majorBrand, minorBrand });
1188
+ };
1189
+
1190
+ // src/create/iso-base-media/create-ilst.ts
1191
+ var createIlst = (items) => {
1192
+ return addSize(combineUint8Arrays([
1193
+ stringsToUint8Array("ilst"),
1194
+ ...items
1195
+ ]));
1196
+ };
1197
+
1198
+ // src/create/iso-base-media/create-moov.ts
1199
+ var createMoov = ({
1200
+ mvhd,
1201
+ traks,
1202
+ udta
1203
+ }) => {
1204
+ return addSize(combineUint8Arrays([
1205
+ stringsToUint8Array("moov"),
1206
+ mvhd,
1207
+ ...traks,
1208
+ udta
1209
+ ]));
1210
+ };
1211
+
1212
+ // src/boxes/iso-base-media/to-date.ts
1213
+ var toUnixTimestamp = (value) => {
1214
+ if (value === 0) {
1215
+ return null;
1216
+ }
1217
+ const baseDate = new Date("1904-01-01T00:00:00Z");
1218
+ return Math.floor(value + baseDate.getTime() / 1000) * 1000;
1219
+ };
1220
+ var fromUnixTimestamp = (value) => {
1221
+ if (value === null) {
1222
+ return 0;
1223
+ }
1224
+ const baseDate = new Date("1904-01-01T00:00:00Z");
1225
+ return Math.floor(value / 1000 - baseDate.getTime() / 1000);
1226
+ };
1227
+
1228
+ // src/create/iso-base-media/create-mvhd.ts
1229
+ var createMvhd = ({
1230
+ timescale,
1231
+ durationInUnits,
1232
+ rate,
1233
+ volume,
1234
+ nextTrackId,
1235
+ matrix,
1236
+ creationTime,
1237
+ modificationTime
1238
+ }) => {
1239
+ if (matrix.length !== 9) {
1240
+ throw new Error("Matrix must be 9 elements long");
1241
+ }
1242
+ const content = combineUint8Arrays([
1243
+ stringsToUint8Array("mvhd"),
1244
+ new Uint8Array([0]),
1245
+ new Uint8Array([0, 0, 0]),
1246
+ creationTime === null ? numberTo32BitUIntOrInt(0) : numberTo32BitUIntOrInt(fromUnixTimestamp(creationTime)),
1247
+ modificationTime === null ? numberTo32BitUIntOrInt(0) : numberTo32BitUIntOrInt(fromUnixTimestamp(modificationTime)),
1248
+ numberTo32BitUIntOrInt(timescale),
1249
+ numberTo32BitUIntOrInt(durationInUnits),
1250
+ floatTo16Point1632Bit(rate),
1251
+ floatTo16Point16_16Bit(volume),
1252
+ new Uint8Array([0, 0]),
1253
+ new Uint8Array([0, 0, 0, 0]),
1254
+ new Uint8Array([0, 0, 0, 0]),
1255
+ serializeMatrix(matrix),
1256
+ combineUint8Arrays(new Array(6).fill(new Uint8Array([0, 0, 0, 0]))),
1257
+ numberTo32BitUIntOrInt(nextTrackId)
1258
+ ]);
1259
+ return addSize(content);
1260
+ };
1261
+
1262
+ // src/create/iso-base-media/create-udta.ts
1263
+ var createUdta = (children) => {
1264
+ return addSize(combineUint8Arrays([
1265
+ stringsToUint8Array("udta"),
1266
+ children
1267
+ ]));
1268
+ };
1269
+
1270
+ // src/create/iso-base-media/ilst/create-cmt.ts
1271
+ var createCmt = (comment) => {
1272
+ return addSize(combineUint8Arrays([
1273
+ new Uint8Array([169, 99, 109, 116]),
1274
+ addSize(combineUint8Arrays([
1275
+ stringsToUint8Array("data"),
1276
+ new Uint8Array([0, 0]),
1277
+ new Uint8Array([0, 1]),
1278
+ new Uint8Array([0, 0]),
1279
+ new Uint8Array([0, 0]),
1280
+ stringsToUint8Array(comment)
1281
+ ]))
1282
+ ]));
1283
+ };
1284
+
1285
+ // src/create/iso-base-media/ilst/create-too.ts
1286
+ var createToo = (value) => {
1287
+ return addSize(combineUint8Arrays([
1288
+ new Uint8Array([169, 116, 111, 111]),
1289
+ addSize(combineUint8Arrays([
1290
+ new Uint8Array([100, 97, 116, 97]),
1291
+ new Uint8Array([0, 0]),
1292
+ new Uint8Array([0, 1]),
1293
+ new Uint8Array([0, 0]),
1294
+ new Uint8Array([0, 0]),
1295
+ stringsToUint8Array(value)
1296
+ ]))
1297
+ ]));
1298
+ };
1299
+
1300
+ // src/create/iso-base-media/trak/mdia/minf/stbl/stsd/create-avcc.ts
1301
+ var createAvccBox = (privateData) => {
1302
+ if (!privateData) {
1303
+ throw new Error("privateData is required");
1304
+ }
1305
+ return addSize(combineUint8Arrays([
1306
+ stringsToUint8Array("avcC"),
1307
+ privateData
1308
+ ]));
1309
+ };
1310
+
1311
+ // src/create/iso-base-media/trak/mdia/minf/stbl/stsd/create-pasp.ts
1312
+ var createPasp = (x, y) => {
1313
+ return addSize(combineUint8Arrays([
1314
+ stringsToUint8Array("pasp"),
1315
+ numberTo32BitUIntOrInt(x),
1316
+ numberTo32BitUIntOrInt(y)
1317
+ ]));
1318
+ };
1319
+
1320
+ // src/create/iso-base-media/codec-specific/avc1.ts
1321
+ var createAvc1Data = ({
1322
+ avccBox,
1323
+ pasp,
1324
+ width,
1325
+ height,
1326
+ horizontalResolution,
1327
+ verticalResolution,
1328
+ compressorName,
1329
+ depth
1330
+ }) => {
1331
+ return addSize(combineUint8Arrays([
1332
+ stringsToUint8Array("avc1"),
1333
+ new Uint8Array([0, 0, 0, 0, 0, 0]),
1334
+ new Uint8Array([0, 1]),
1335
+ new Uint8Array([0, 0]),
1336
+ new Uint8Array([0, 0]),
1337
+ new Uint8Array([0, 0, 0, 0]),
1338
+ new Uint8Array([0, 0, 0, 0]),
1339
+ new Uint8Array([0, 0, 0, 0]),
1340
+ numberTo16BitUIntOrInt(width),
1341
+ numberTo16BitUIntOrInt(height),
1342
+ setFixedPointSignedOrUnsigned1616Number(horizontalResolution),
1343
+ setFixedPointSignedOrUnsigned1616Number(verticalResolution),
1344
+ new Uint8Array([0, 0, 0, 0]),
1345
+ numberTo16BitUIntOrInt(1),
1346
+ stringToPascalString(compressorName),
1347
+ numberTo16BitUIntOrInt(depth),
1348
+ numberTo16BitUIntOrInt(-1),
1349
+ avccBox,
1350
+ pasp
1351
+ ]));
1352
+ };
1353
+
1354
+ // src/create/iso-base-media/codec-specific/mp4a.ts
1355
+ var createMp4a = ({
1356
+ sampleRate,
1357
+ channelCount,
1358
+ avgBitrate,
1359
+ maxBitrate,
1360
+ codecPrivate: codecPrivate2
1361
+ }) => {
1362
+ if (!codecPrivate2) {
1363
+ throw new Error("Need codecPrivate for mp4a");
1364
+ }
1365
+ const esdsAtom = addSize(combineUint8Arrays([
1366
+ stringsToUint8Array("esds"),
1367
+ new Uint8Array([0]),
1368
+ new Uint8Array([0, 0, 0]),
1369
+ new Uint8Array([3]),
1370
+ addLeading128Size(combineUint8Arrays([
1371
+ numberTo16BitUIntOrInt(2),
1372
+ new Uint8Array([0]),
1373
+ new Uint8Array([4]),
1374
+ addLeading128Size(combineUint8Arrays([
1375
+ new Uint8Array([64]),
1376
+ new Uint8Array([21]),
1377
+ new Uint8Array([0, 0, 0]),
1378
+ numberTo32BitUIntOrInt(maxBitrate),
1379
+ numberTo32BitUIntOrInt(avgBitrate),
1380
+ new Uint8Array([5]),
1381
+ addLeading128Size(codecPrivate2)
1382
+ ])),
1383
+ new Uint8Array([6]),
1384
+ addLeading128Size(new Uint8Array([2]))
1385
+ ]))
1386
+ ]));
1387
+ return addSize(combineUint8Arrays([
1388
+ stringsToUint8Array("mp4a"),
1389
+ new Uint8Array([0, 0, 0, 0, 0, 0]),
1390
+ numberTo16BitUIntOrInt(1),
1391
+ numberTo16BitUIntOrInt(0),
1392
+ numberTo16BitUIntOrInt(0),
1393
+ new Uint8Array([0, 0, 0, 0]),
1394
+ numberTo16BitUIntOrInt(channelCount),
1395
+ numberTo16BitUIntOrInt(16),
1396
+ numberTo16BitUIntOrInt(0),
1397
+ numberTo16BitUIntOrInt(0),
1398
+ setFixedPointSignedOrUnsigned1616Number(sampleRate),
1399
+ esdsAtom
1400
+ ]));
1401
+ };
1402
+
1403
+ // src/create/iso-base-media/codec-specific/create-codec-specific-data.ts
1404
+ var createCodecSpecificData = (track) => {
1405
+ if (track.type === "video") {
1406
+ return createAvc1Data({
1407
+ avccBox: createAvccBox(track.codecPrivate),
1408
+ compressorName: "WebCodecs",
1409
+ depth: 24,
1410
+ horizontalResolution: 72,
1411
+ verticalResolution: 72,
1412
+ height: track.height,
1413
+ width: track.width,
1414
+ pasp: createPasp(1, 1),
1415
+ type: "avc1-data"
1416
+ });
1417
+ }
1418
+ if (track.type === "audio") {
1419
+ return createMp4a({
1420
+ type: "mp4a-data",
1421
+ avgBitrate: 128 * 1024,
1422
+ maxBitrate: 128 * 1024,
1423
+ channelCount: track.numberOfChannels,
1424
+ sampleRate: track.sampleRate,
1425
+ codecPrivate: track.codecPrivate
1426
+ });
1427
+ }
1428
+ throw new Error("Unsupported codec specific data " + track);
1429
+ };
1430
+
1431
+ // src/create/iso-base-media/create-mdia.ts
1432
+ var createMdia = ({
1433
+ mdhd,
1434
+ hdlr,
1435
+ minf
1436
+ }) => {
1437
+ return addSize(combineUint8Arrays([
1438
+ stringsToUint8Array("mdia"),
1439
+ mdhd,
1440
+ hdlr,
1441
+ minf
1442
+ ]));
1443
+ };
1444
+
1445
+ // src/truthy.ts
1446
+ function truthy(value) {
1447
+ return Boolean(value);
1448
+ }
1449
+
1450
+ // src/create/iso-base-media/create-trak.ts
1451
+ var createTrak = ({
1452
+ tkhd,
1453
+ mdia
1454
+ }) => {
1455
+ return addSize(combineUint8Arrays([
1456
+ stringsToUint8Array("trak"),
1457
+ tkhd,
1458
+ mdia
1459
+ ].filter(truthy)));
1460
+ };
1461
+
1462
+ // src/create/iso-base-media/mdia/create-mdhd.ts
1463
+ var createMdhd = ({
1464
+ creationTime,
1465
+ modificationTime,
1466
+ timescale,
1467
+ duration: duration2
1468
+ }) => {
1469
+ return addSize(combineUint8Arrays([
1470
+ stringsToUint8Array("mdhd"),
1471
+ new Uint8Array([0]),
1472
+ new Uint8Array([0, 0, 0]),
1473
+ creationTime === null ? numberTo32BitUIntOrInt(0) : numberTo32BitUIntOrInt(fromUnixTimestamp(creationTime)),
1474
+ modificationTime === null ? numberTo32BitUIntOrInt(0) : numberTo32BitUIntOrInt(fromUnixTimestamp(modificationTime)),
1475
+ numberTo32BitUIntOrInt(timescale),
1476
+ numberTo32BitUIntOrInt(Math.round(duration2 / 1000 * timescale)),
1477
+ new Uint8Array([85, 196]),
1478
+ new Uint8Array([0, 0])
1479
+ ]));
1480
+ };
1481
+
1482
+ // src/create/iso-base-media/trak/create-tkhd.ts
1483
+ var TKHD_FLAGS = {
1484
+ TRACK_ENABLED: 1,
1485
+ TRACK_IN_MOVIE: 2,
1486
+ TRACK_IN_PREVIEW: 4,
1487
+ TRACK_IN_POSTER: 8
1488
+ };
1489
+ var createTkhdForAudio = ({
1490
+ creationTime,
1491
+ modificationTime,
1492
+ flags,
1493
+ trackId,
1494
+ duration: duration2,
1495
+ volume,
1496
+ timescale
1497
+ }) => {
1498
+ return addSize(combineUint8Arrays([
1499
+ stringsToUint8Array("tkhd"),
1500
+ new Uint8Array([0]),
1501
+ new Uint8Array([0, 0, flags]),
1502
+ creationTime === null ? numberTo32BitUIntOrInt(0) : numberTo32BitUIntOrInt(fromUnixTimestamp(creationTime)),
1503
+ modificationTime === null ? numberTo32BitUIntOrInt(0) : numberTo32BitUIntOrInt(fromUnixTimestamp(modificationTime)),
1504
+ numberTo32BitUIntOrInt(trackId),
1505
+ new Uint8Array([0, 0, 0, 0]),
1506
+ numberTo32BitUIntOrInt(Math.round(duration2 / 1000 * timescale)),
1507
+ new Uint8Array([0, 0, 0, 0]),
1508
+ new Uint8Array([0, 0, 0, 0]),
1509
+ new Uint8Array([0, 0]),
1510
+ new Uint8Array([0, 1]),
1511
+ floatTo16Point16_16Bit(volume),
1512
+ new Uint8Array([0, 0]),
1513
+ serializeMatrix(IDENTITY_MATRIX),
1514
+ setFixedPointSignedOrUnsigned1616Number(0),
1515
+ setFixedPointSignedOrUnsigned1616Number(0)
1516
+ ]));
1517
+ };
1518
+ var createTkhdForVideo = ({
1519
+ creationTime,
1520
+ modificationTime,
1521
+ duration: duration2,
1522
+ trackId,
1523
+ volume,
1524
+ matrix,
1525
+ width,
1526
+ height,
1527
+ flags,
1528
+ timescale
1529
+ }) => {
1530
+ const content = combineUint8Arrays([
1531
+ stringsToUint8Array("tkhd"),
1532
+ new Uint8Array([0]),
1533
+ new Uint8Array([0, 0, flags]),
1534
+ creationTime === null ? numberTo32BitUIntOrInt(0) : numberTo32BitUIntOrInt(fromUnixTimestamp(creationTime)),
1535
+ modificationTime === null ? numberTo32BitUIntOrInt(0) : numberTo32BitUIntOrInt(fromUnixTimestamp(modificationTime)),
1536
+ numberTo32BitUIntOrInt(trackId),
1537
+ new Uint8Array([0, 0, 0, 0]),
1538
+ numberTo32BitUIntOrInt(duration2 / 1000 * timescale),
1539
+ new Uint8Array([0, 0, 0, 0]),
1540
+ new Uint8Array([0, 0, 0, 0]),
1541
+ new Uint8Array([0, 0]),
1542
+ new Uint8Array([0, 0]),
1543
+ floatTo16Point16_16Bit(volume),
1544
+ new Uint8Array([0, 0]),
1545
+ serializeMatrix(matrix),
1546
+ setFixedPointSignedOrUnsigned1616Number(width),
1547
+ setFixedPointSignedOrUnsigned1616Number(height)
1548
+ ]);
1549
+ return addSize(content);
1550
+ };
1551
+
1552
+ // src/create/iso-base-media/trak/mdia/minf/create-dinf.ts
1553
+ var createDinf = () => {
1554
+ return addSize(combineUint8Arrays([
1555
+ stringsToUint8Array("dinf"),
1556
+ addSize(combineUint8Arrays([
1557
+ stringsToUint8Array("dref"),
1558
+ new Uint8Array([0]),
1559
+ new Uint8Array([0, 0, 0]),
1560
+ new Uint8Array([0, 0, 0, 1]),
1561
+ addSize(combineUint8Arrays([
1562
+ stringsToUint8Array("url "),
1563
+ new Uint8Array([0]),
1564
+ new Uint8Array([0, 0, 1])
1565
+ ]))
1566
+ ]))
1567
+ ]));
1568
+ };
1569
+
1570
+ // src/create/iso-base-media/trak/mdia/create-minf.ts
1571
+ var createMinf = ({
1572
+ vmhdAtom,
1573
+ stblAtom
1574
+ }) => {
1575
+ return addSize(combineUint8Arrays([
1576
+ stringsToUint8Array("minf"),
1577
+ vmhdAtom,
1578
+ createDinf(),
1579
+ stblAtom
1580
+ ]));
1581
+ };
1582
+
1583
+ // src/create/iso-base-media/trak/mdia/minf/create-smhd.ts
1584
+ var createSmhd = () => {
1585
+ return addSize(combineUint8Arrays([
1586
+ stringsToUint8Array("smhd"),
1587
+ new Uint8Array([0]),
1588
+ new Uint8Array([0, 0, 0]),
1589
+ new Uint8Array([0, 0]),
1590
+ new Uint8Array([0, 0])
1591
+ ]));
1592
+ };
1593
+
1594
+ // src/create/iso-base-media/trak/mdia/minf/stbl/create-ctts.ts
1595
+ var makeEntry = (entry) => {
1596
+ return combineUint8Arrays([
1597
+ numberTo32BitUIntOrInt(entry.sampleCount),
1598
+ numberTo32BitUIntOrInt(entry.sampleOffset)
1599
+ ]);
1600
+ };
1601
+ var createCttsBox = (samplePositions) => {
1602
+ const offsets = samplePositions.map((s) => s.cts - s.dts);
1603
+ const entries = [];
1604
+ let lastOffset = null;
1605
+ for (const offset of offsets) {
1606
+ if (lastOffset === offset) {
1607
+ entries[entries.length - 1].sampleCount++;
1608
+ } else {
1609
+ entries.push({
1610
+ sampleCount: 1,
1611
+ sampleOffset: offset
1612
+ });
1613
+ }
1614
+ lastOffset = offset;
1615
+ }
1616
+ const needsCtts = entries.length > 0 && entries.some((e) => e.sampleOffset !== 0);
1617
+ if (!needsCtts) {
1618
+ return null;
1619
+ }
1620
+ return addSize(combineUint8Arrays([
1621
+ stringsToUint8Array("ctts"),
1622
+ new Uint8Array([0]),
1623
+ new Uint8Array([0, 0, 0]),
1624
+ numberTo32BitUIntOrInt(entries.length),
1625
+ ...entries.map((e) => makeEntry(e))
1626
+ ]));
1627
+ };
1628
+
1629
+ // src/create/iso-base-media/trak/mdia/minf/stbl/create-stco.ts
1630
+ var createStcoAtom = (samplePositions) => {
1631
+ const chunkOffsets = [];
1632
+ let lastChunk;
1633
+ for (const sample of samplePositions) {
1634
+ if (lastChunk !== sample.chunk) {
1635
+ chunkOffsets.push(sample.offset);
1636
+ }
1637
+ lastChunk = sample.chunk;
1638
+ }
1639
+ return addSize(combineUint8Arrays([
1640
+ stringsToUint8Array("stco"),
1641
+ new Uint8Array([0]),
1642
+ new Uint8Array([0, 0, 0]),
1643
+ numberTo32BitUIntOrInt(chunkOffsets.length),
1644
+ ...chunkOffsets.map((offset) => numberTo32BitUIntOrInt(offset))
1645
+ ]));
1646
+ };
1647
+
1648
+ // src/create/iso-base-media/trak/mdia/minf/stbl/create-stsc.ts
1649
+ var createEntry = (entry) => {
1650
+ return combineUint8Arrays([
1651
+ numberTo32BitUIntOrInt(entry.firstChunk),
1652
+ numberTo32BitUIntOrInt(entry.samplesPerChunk),
1653
+ numberTo32BitUIntOrInt(entry.sampleDescriptionIndex)
1654
+ ]);
1655
+ };
1656
+ var createStsc = (samplePositions) => {
1657
+ const entries = [];
1658
+ const deduplicateLastEntry = () => {
1659
+ const lastEntry = entries[entries.length - 1];
1660
+ const secondToLastEntry = entries[entries.length - 2];
1661
+ if (lastEntry && secondToLastEntry && lastEntry.samplesPerChunk === secondToLastEntry.samplesPerChunk && lastEntry.sampleDescriptionIndex === secondToLastEntry.sampleDescriptionIndex) {
1662
+ const lastIndex = entries.length - 1;
1663
+ entries.length = lastIndex;
1664
+ }
1665
+ };
1666
+ let lastChunk;
1667
+ for (const samplePosition of samplePositions) {
1668
+ if (samplePosition.chunk === lastChunk) {
1669
+ entries[entries.length - 1].samplesPerChunk++;
1670
+ } else {
1671
+ deduplicateLastEntry();
1672
+ entries.push({
1673
+ firstChunk: samplePosition.chunk,
1674
+ samplesPerChunk: 1,
1675
+ sampleDescriptionIndex: 1
1676
+ });
1677
+ lastChunk = samplePosition.chunk;
1678
+ }
1679
+ }
1680
+ deduplicateLastEntry();
1681
+ return addSize(combineUint8Arrays([
1682
+ stringsToUint8Array("stsc"),
1683
+ new Uint8Array([0]),
1684
+ new Uint8Array([0, 0, 0]),
1685
+ numberTo32BitUIntOrInt(entries.length),
1686
+ ...entries.map((e) => createEntry(e))
1687
+ ]));
1688
+ };
1689
+
1690
+ // src/create/iso-base-media/trak/mdia/minf/stbl/create-stss.ts
1691
+ var createStss = (samplePositions) => {
1692
+ const samples = samplePositions.map((sample, i) => [sample.isKeyframe, i]).filter((s) => s[0]).map((s) => s[1] + 1);
1693
+ return addSize(combineUint8Arrays([
1694
+ stringsToUint8Array("stss"),
1695
+ new Uint8Array([0]),
1696
+ new Uint8Array([0, 0, 0]),
1697
+ numberTo32BitUIntOrInt(samples.length),
1698
+ ...samples.map((sample) => numberTo32BitUIntOrInt(sample))
1699
+ ]));
1700
+ };
1701
+
1702
+ // src/create/iso-base-media/trak/mdia/minf/stbl/create-stsz.ts
1703
+ var createStsz = (samplePositions) => {
1704
+ const sampleSizes = samplePositions.map((samplePosition) => samplePosition.size);
1705
+ return addSize(combineUint8Arrays([
1706
+ stringsToUint8Array("stsz"),
1707
+ new Uint8Array([0]),
1708
+ new Uint8Array([0, 0, 0]),
1709
+ numberTo32BitUIntOrInt(0),
1710
+ numberTo32BitUIntOrInt(sampleSizes.length),
1711
+ ...sampleSizes.map((size) => numberTo32BitUIntOrInt(size))
1712
+ ]));
1713
+ };
1714
+
1715
+ // src/create/iso-base-media/trak/mdia/minf/stbl/create-stts.ts
1716
+ var makeEntry2 = (entry) => {
1717
+ return combineUint8Arrays([
1718
+ numberTo32BitUIntOrInt(entry.sampleCount),
1719
+ numberTo32BitUIntOrInt(entry.sampleOffset)
1720
+ ]);
1721
+ };
1722
+ var createSttsAtom = (samplePositions) => {
1723
+ let lastDuration = null;
1724
+ const durations = samplePositions.map((_, i, a) => {
1725
+ if (a[i].duration === undefined || a[i].duration === 0) {
1726
+ return (a[i + 1]?.dts ?? a[i].dts) - a[i].dts;
1727
+ }
1728
+ return a[i].duration;
1729
+ });
1730
+ const entries = [];
1731
+ for (const duration2 of durations) {
1732
+ if (duration2 === lastDuration) {
1733
+ entries[entries.length - 1].sampleCount++;
1734
+ } else {
1735
+ entries.push({
1736
+ sampleCount: 1,
1737
+ sampleOffset: duration2
1738
+ });
1739
+ }
1740
+ lastDuration = duration2;
1741
+ }
1742
+ return addSize(combineUint8Arrays([
1743
+ stringsToUint8Array("stts"),
1744
+ new Uint8Array([0]),
1745
+ new Uint8Array([0, 0, 0]),
1746
+ numberTo32BitUIntOrInt(entries.length),
1747
+ ...entries.map((e) => makeEntry2(e))
1748
+ ]));
1749
+ };
1750
+
1751
+ // src/create/iso-base-media/trak/mdia/minf/stbl/stsd/create-avc1.ts
1752
+ var createStsdData = (codecSpecificData) => {
1753
+ return addSize(combineUint8Arrays([
1754
+ stringsToUint8Array("stsd"),
1755
+ new Uint8Array([0]),
1756
+ new Uint8Array([0, 0, 0]),
1757
+ new Uint8Array([0, 0, 0, 1]),
1758
+ codecSpecificData
1759
+ ]));
1760
+ };
1761
+
1762
+ // src/create/iso-base-media/trak/mdia/minf/create-stbl.ts
1763
+ var createStbl = ({
1764
+ samplePositions,
1765
+ codecSpecificData,
1766
+ isVideo
1767
+ }) => {
1768
+ return addSize(combineUint8Arrays([
1769
+ stringsToUint8Array("stbl"),
1770
+ createStsdData(codecSpecificData),
1771
+ createSttsAtom(samplePositions),
1772
+ isVideo ? createStss(samplePositions) : null,
1773
+ createCttsBox(samplePositions),
1774
+ createStsc(samplePositions),
1775
+ createStsz(samplePositions),
1776
+ createStcoAtom(samplePositions),
1777
+ isVideo ? null : new Uint8Array([
1778
+ 0,
1779
+ 0,
1780
+ 0,
1781
+ 26,
1782
+ 115,
1783
+ 103,
1784
+ 112,
1785
+ 100,
1786
+ 1,
1787
+ 0,
1788
+ 0,
1789
+ 0,
1790
+ 114,
1791
+ 111,
1792
+ 108,
1793
+ 108,
1794
+ 0,
1795
+ 0,
1796
+ 0,
1797
+ 2,
1798
+ 0,
1799
+ 0,
1800
+ 0,
1801
+ 1,
1802
+ 255,
1803
+ 255,
1804
+ 0,
1805
+ 0,
1806
+ 0,
1807
+ 28,
1808
+ 115,
1809
+ 98,
1810
+ 103,
1811
+ 112,
1812
+ 0,
1813
+ 0,
1814
+ 0,
1815
+ 0,
1816
+ 114,
1817
+ 111,
1818
+ 108,
1819
+ 108,
1820
+ 0,
1821
+ 0,
1822
+ 0,
1823
+ 1,
1824
+ 0,
1825
+ 0,
1826
+ 10,
1827
+ 25,
1828
+ 0,
1829
+ 0,
1830
+ 0,
1831
+ 1
1832
+ ])
1833
+ ].filter(truthy)));
1834
+ };
1835
+
1836
+ // src/create/iso-base-media/trak/mdia/minf/create-vmhd.ts
1837
+ var createVmhd = () => {
1838
+ return addSize(combineUint8Arrays([
1839
+ stringsToUint8Array("vmhd"),
1840
+ new Uint8Array([0]),
1841
+ new Uint8Array([0, 0, 1]),
1842
+ new Uint8Array([0, 0]),
1843
+ new Uint8Array([0, 0, 0, 0, 0, 0])
1844
+ ]));
1845
+ };
1846
+
1847
+ // src/create/iso-base-media/udta/meta/create-hdlr.ts
1848
+ var createHdlr = (type) => {
1849
+ return addSize(combineUint8Arrays([
1850
+ stringsToUint8Array("hdlr"),
1851
+ new Uint8Array([0]),
1852
+ new Uint8Array([0, 0, 0]),
1853
+ new Uint8Array([0, 0, 0, 0]),
1854
+ stringsToUint8Array(type === "mdir" ? "mdir" : type === "video" ? "vide" : "soun"),
1855
+ type === "mdir" ? numberTo32BitUIntOrInt(1634758764) : new Uint8Array([0, 0, 0, 0]),
1856
+ new Uint8Array([0, 0, 0, 0]),
1857
+ new Uint8Array([0, 0, 0, 0]),
1858
+ stringsToUint8Array(type === "mdir" ? "\0" : type === "video" ? "VideoHandler\0" : "SoundHandler\0")
1859
+ ]));
1860
+ };
1861
+
1862
+ // src/create/iso-base-media/serialize-track.ts
1863
+ var serializeTrack = ({
1864
+ track,
1865
+ durationInUnits,
1866
+ samplePositions,
1867
+ timescale
1868
+ }) => {
1869
+ if (track.codec !== "h264" && track.codec !== "aac") {
1870
+ throw new Error("Currently only H.264 and AAC is supported");
1871
+ }
1872
+ return createTrak({
1873
+ tkhd: track.codec === "aac" ? createTkhdForAudio({
1874
+ creationTime: Date.now(),
1875
+ flags: TKHD_FLAGS.TRACK_ENABLED | TKHD_FLAGS.TRACK_IN_MOVIE,
1876
+ modificationTime: Date.now(),
1877
+ duration: durationInUnits,
1878
+ trackId: track.trackNumber,
1879
+ volume: 1,
1880
+ timescale
1881
+ }) : track.type === "video" ? createTkhdForVideo({
1882
+ creationTime: Date.now(),
1883
+ modificationTime: Date.now(),
1884
+ duration: durationInUnits,
1885
+ flags: TKHD_FLAGS.TRACK_ENABLED | TKHD_FLAGS.TRACK_IN_MOVIE,
1886
+ height: track.height,
1887
+ width: track.width,
1888
+ matrix: IDENTITY_MATRIX,
1889
+ trackId: track.trackNumber,
1890
+ volume: 0,
1891
+ timescale
1892
+ }) : new Uint8Array(stringsToUint8Array("wrong")),
1893
+ mdia: createMdia({
1894
+ mdhd: createMdhd({
1895
+ creationTime: null,
1896
+ modificationTime: null,
1897
+ duration: durationInUnits,
1898
+ timescale: track.timescale
1899
+ }),
1900
+ hdlr: track.type === "video" ? createHdlr("video") : createHdlr("audio"),
1901
+ minf: createMinf({
1902
+ stblAtom: createStbl({
1903
+ samplePositions,
1904
+ isVideo: track.type === "video",
1905
+ codecSpecificData: createCodecSpecificData(track)
1906
+ }),
1907
+ vmhdAtom: track.type === "audio" ? createSmhd() : createVmhd()
1908
+ })
1909
+ })
1910
+ });
1911
+ };
1912
+
1913
+ // src/create/iso-base-media/udta/create-meta.ts
1914
+ var createMeta = ({
1915
+ hdlr,
1916
+ ilst
1917
+ }) => {
1918
+ return addSize(combineUint8Arrays([
1919
+ stringsToUint8Array("meta"),
1920
+ new Uint8Array([0]),
1921
+ new Uint8Array([0, 0, 0]),
1922
+ hdlr,
1923
+ ilst
1924
+ ]));
1925
+ };
1926
+
1927
+ // src/create/iso-base-media/mp4-header.ts
1928
+ var HEADER_LENGTH = 1024000;
1929
+ var createPaddedMoovAtom = ({
1930
+ durationInUnits,
1931
+ trackInfo,
1932
+ timescale
1933
+ }) => {
1934
+ return padIsoBaseMediaBytes(createMoov({
1935
+ mvhd: createMvhd({
1936
+ timescale,
1937
+ durationInUnits,
1938
+ matrix: IDENTITY_MATRIX,
1939
+ nextTrackId: trackInfo.map((t) => t.track.trackNumber).reduce((a, b) => Math.max(a, b), 0) + 1,
1940
+ rate: 1,
1941
+ volume: 1,
1942
+ creationTime: Date.now(),
1943
+ modificationTime: Date.now()
1944
+ }),
1945
+ traks: trackInfo.map((track) => {
1946
+ return serializeTrack({
1947
+ timescale,
1948
+ track: track.track,
1949
+ durationInUnits,
1950
+ samplePositions: track.samplePositions
1951
+ });
1952
+ }),
1953
+ udta: createUdta(createMeta({
1954
+ hdlr: createHdlr("mdir"),
1955
+ ilst: createIlst([
1956
+ createToo("WebCodecs"),
1957
+ createCmt("Made with @remotion/webcodecs")
1958
+ ])
1959
+ }))
1960
+ }), HEADER_LENGTH);
1961
+ };
1962
+
1963
+ // src/create/iso-base-media/create-iso-base-media.ts
1964
+ var createIsoBaseMedia = async ({
1965
+ writer,
1966
+ onBytesProgress,
1967
+ onMillisecondsProgress,
1968
+ logLevel,
1969
+ filename
1970
+ }) => {
1971
+ const header = createIsoBaseMediaFtyp({
1972
+ compatibleBrands: ["isom", "iso2", "avc1", "mp42"],
1973
+ majorBrand: "isom",
1974
+ minorBrand: 512
1975
+ });
1976
+ const w = await writer.createContent({ filename, mimeType: "video/mp4" });
1977
+ await w.write(header);
1978
+ let durationInUnits = 0;
1979
+ const currentTracks = [];
1980
+ const samplePositions = [];
1981
+ const sampleChunkIndices = [];
1982
+ const moovOffset = w.getWrittenByteCount();
1983
+ const getPaddedMoovAtom = () => {
1984
+ return createPaddedMoovAtom({
1985
+ durationInUnits,
1986
+ trackInfo: currentTracks.map((track) => {
1987
+ return {
1988
+ track,
1989
+ durationInUnits,
1990
+ samplePositions: samplePositions[track.trackNumber] ?? [],
1991
+ timescale: track.timescale
1992
+ };
1993
+ }),
1994
+ timescale: 1000
1995
+ });
1996
+ };
1997
+ await w.write(getPaddedMoovAtom());
1998
+ let mdatSize = 8;
1999
+ const mdatSizeOffset = w.getWrittenByteCount();
2000
+ await w.write(combineUint8Arrays([
2001
+ numberTo32BitUIntOrInt(mdatSize),
2002
+ stringsToUint8Array("mdat")
2003
+ ]));
2004
+ const updateMdatSize = async () => {
2005
+ await w.updateDataAt(mdatSizeOffset, numberTo32BitUIntOrInt(mdatSize));
2006
+ onBytesProgress(w.getWrittenByteCount());
2007
+ };
2008
+ const operationProm = { current: Promise.resolve() };
2009
+ const updateMoov = async () => {
2010
+ await w.updateDataAt(moovOffset, getPaddedMoovAtom());
2011
+ onBytesProgress(w.getWrittenByteCount());
2012
+ };
2013
+ const updateDuration = (newDuration) => {
2014
+ durationInUnits = newDuration;
2015
+ onMillisecondsProgress(newDuration);
2016
+ };
2017
+ const addCodecPrivateToTrack = ({
2018
+ trackNumber: trackNumber2,
2019
+ codecPrivate: codecPrivate2
2020
+ }) => {
2021
+ currentTracks.forEach((track) => {
2022
+ if (track.trackNumber === trackNumber2) {
2023
+ track.codecPrivate = codecPrivate2;
2024
+ }
2025
+ });
2026
+ };
2027
+ let lastChunkWasVideo = false;
2028
+ const addSample = async ({
2029
+ chunk,
2030
+ trackNumber: trackNumber2,
2031
+ isVideo,
2032
+ timescale,
2033
+ codecPrivate: codecPrivate2
2034
+ }) => {
2035
+ const position = w.getWrittenByteCount();
2036
+ await w.write(chunk.data);
2037
+ mdatSize += chunk.data.length;
2038
+ onBytesProgress(w.getWrittenByteCount());
2039
+ if (codecPrivate2) {
2040
+ addCodecPrivateToTrack({ trackNumber: trackNumber2, codecPrivate: codecPrivate2 });
2041
+ }
2042
+ const newDuration = Math.round((chunk.timestamp + (chunk.duration ?? 0)) / 1000);
2043
+ updateDuration(newDuration);
2044
+ if (!samplePositions[trackNumber2]) {
2045
+ samplePositions[trackNumber2] = [];
2046
+ }
2047
+ if (typeof sampleChunkIndices[trackNumber2] === "undefined") {
2048
+ sampleChunkIndices[trackNumber2] = 0;
2049
+ }
2050
+ if (isVideo && chunk.type === "key") {
2051
+ sampleChunkIndices[trackNumber2]++;
2052
+ } else if (!isVideo && samplePositions[trackNumber2].length % 22 === 0) {
2053
+ sampleChunkIndices[trackNumber2]++;
2054
+ } else if (lastChunkWasVideo !== isVideo) {
2055
+ sampleChunkIndices[trackNumber2]++;
2056
+ }
2057
+ const samplePositionToAdd = {
2058
+ isKeyframe: chunk.type === "key",
2059
+ offset: position,
2060
+ chunk: sampleChunkIndices[trackNumber2],
2061
+ cts: Math.round(chunk.cts / (1e6 / timescale)),
2062
+ dts: Math.round(chunk.dts / (1e6 / timescale)),
2063
+ duration: Math.round((chunk.duration ?? 0) / (1e6 / timescale)),
2064
+ size: chunk.data.length
2065
+ };
2066
+ lastChunkWasVideo = isVideo;
2067
+ samplePositions[trackNumber2].push(samplePositionToAdd);
2068
+ };
2069
+ const addTrack = (track) => {
2070
+ const trackNumber2 = currentTracks.length + 1;
2071
+ currentTracks.push({ ...track, trackNumber: trackNumber2 });
2072
+ return Promise.resolve({ trackNumber: trackNumber2 });
2073
+ };
2074
+ const waitForFinishPromises = [];
2075
+ return {
2076
+ save: () => {
2077
+ return w.save();
2078
+ },
2079
+ remove: async () => {
2080
+ await w.remove();
2081
+ },
2082
+ addSample: ({ chunk, trackNumber: trackNumber2, isVideo, timescale, codecPrivate: codecPrivate2 }) => {
2083
+ operationProm.current = operationProm.current.then(() => {
2084
+ return addSample({
2085
+ chunk,
2086
+ trackNumber: trackNumber2,
2087
+ isVideo,
2088
+ timescale,
2089
+ codecPrivate: codecPrivate2
2090
+ });
2091
+ });
2092
+ return operationProm.current;
2093
+ },
2094
+ addTrack: (track) => {
2095
+ operationProm.current = operationProm.current.then(() => addTrack(track));
2096
+ return operationProm.current;
2097
+ },
2098
+ updateTrackSampleRate: ({ sampleRate, trackNumber: trackNumber2 }) => {
2099
+ currentTracks.forEach((track) => {
2100
+ if (track.trackNumber === trackNumber2) {
2101
+ if (track.type !== "audio") {
2102
+ throw new Error(`Tried to update sample rate of track ${trackNumber2}, but it's not an audio track`);
2103
+ }
2104
+ track.sampleRate = sampleRate;
2105
+ }
2106
+ });
2107
+ },
2108
+ addWaitForFinishPromise: (promise) => {
2109
+ waitForFinishPromises.push(promise);
2110
+ },
2111
+ async waitForFinish() {
2112
+ Log.verbose(logLevel, "All write operations queued. Waiting for finish...");
2113
+ await Promise.all(waitForFinishPromises.map((p) => p()));
2114
+ Log.verbose(logLevel, "Cleanup tasks executed");
2115
+ await operationProm.current;
2116
+ await updateMoov();
2117
+ await updateMdatSize();
2118
+ Log.verbose(logLevel, "All write operations done. Waiting for finish...");
2119
+ await w.waitForFinish();
2120
+ },
2121
+ updateDuration: (duration2) => {
2122
+ operationProm.current = operationProm.current.then(() => updateDuration(duration2));
2123
+ return operationProm.current;
2124
+ }
2125
+ };
2126
+ };
2127
+
2128
+ // src/create/matroska/cluster-segment.ts
1025
2129
  var CLUSTER_MIN_VINT_WIDTH = 8;
1026
2130
  var createClusterSegment = (timestamp) => {
1027
2131
  return makeMatroskaBytes({
@@ -1062,32 +2166,36 @@ var makeSimpleBlock = ({
1062
2166
  ]);
1063
2167
  };
1064
2168
 
1065
- // src/create/timescale.ts
1066
- var CREATE_TIME_SCALE = 1e6;
1067
-
1068
- // src/create/cluster.ts
2169
+ // src/create/matroska/cluster.ts
1069
2170
  var maxClusterTimestamp = 2 ** 15;
1070
- var timestampToClusterTimestamp = (timestamp) => {
1071
- return Math.round(timestamp / CREATE_TIME_SCALE * 1000);
2171
+ var timestampToClusterTimestamp = (timestamp, timescale) => {
2172
+ return Math.round(timestamp / timescale * 1000);
1072
2173
  };
1073
2174
  var canFitInCluster = ({
1074
2175
  clusterStartTimestamp,
1075
- chunk
2176
+ chunk,
2177
+ timescale
1076
2178
  }) => {
1077
- const timecodeRelativeToCluster = timestampToClusterTimestamp(chunk.timestamp) - timestampToClusterTimestamp(clusterStartTimestamp);
2179
+ const timecodeRelativeToCluster = timestampToClusterTimestamp(chunk.timestamp, timescale) - timestampToClusterTimestamp(clusterStartTimestamp, timescale);
1078
2180
  if (timecodeRelativeToCluster < 0) {
1079
2181
  throw new Error(`timecodeRelativeToCluster is negative`);
1080
2182
  }
1081
2183
  return timecodeRelativeToCluster <= maxClusterTimestamp;
1082
2184
  };
1083
- var makeCluster = async (w, clusterStartTimestamp) => {
1084
- const cluster = createClusterSegment(timestampToClusterTimestamp(clusterStartTimestamp));
1085
- const clusterVIntPosition = w.getWrittenByteCount() + cluster.offsets.offset + matroskaToHex(matroskaElements.Cluster).byteLength;
2185
+ var makeCluster = async ({
2186
+ writer,
2187
+ clusterStartTimestamp,
2188
+ timescale,
2189
+ logLevel
2190
+ }) => {
2191
+ Log.verbose(logLevel, `Making new Matroska cluster with timestamp ${clusterStartTimestamp}`);
2192
+ const cluster = createClusterSegment(timestampToClusterTimestamp(clusterStartTimestamp, timescale));
2193
+ const clusterVIntPosition = writer.getWrittenByteCount() + cluster.offsets.offset + matroskaToHex(matroskaElements.Cluster).byteLength;
1086
2194
  let clusterSize = cluster.bytes.byteLength - matroskaToHex(matroskaElements.Cluster).byteLength - CLUSTER_MIN_VINT_WIDTH;
1087
- await w.write(cluster.bytes);
2195
+ await writer.write(cluster.bytes);
1088
2196
  const addSample = async (chunk, trackNumber2) => {
1089
- const timecodeRelativeToCluster = timestampToClusterTimestamp(chunk.timestamp) - timestampToClusterTimestamp(clusterStartTimestamp);
1090
- if (!canFitInCluster({ clusterStartTimestamp, chunk })) {
2197
+ const timecodeRelativeToCluster = timestampToClusterTimestamp(chunk.timestamp, timescale) - timestampToClusterTimestamp(clusterStartTimestamp, timescale);
2198
+ if (!canFitInCluster({ clusterStartTimestamp, chunk, timescale })) {
1091
2199
  throw new Error(`timecodeRelativeToCluster is too big: ${timecodeRelativeToCluster} > ${maxClusterTimestamp}`);
1092
2200
  }
1093
2201
  const keyframe = chunk.type === "key";
@@ -1100,8 +2208,8 @@ var makeCluster = async (w, clusterStartTimestamp) => {
1100
2208
  timecodeRelativeToCluster
1101
2209
  });
1102
2210
  clusterSize += simpleBlock2.byteLength;
1103
- await w.updateDataAt(clusterVIntPosition, getVariableInt(clusterSize, CLUSTER_MIN_VINT_WIDTH));
1104
- await w.write(simpleBlock2);
2211
+ await writer.updateDataAt(clusterVIntPosition, getVariableInt(clusterSize, CLUSTER_MIN_VINT_WIDTH));
2212
+ await writer.write(simpleBlock2);
1105
2213
  return { timecodeRelativeToCluster };
1106
2214
  };
1107
2215
  const shouldMakeNewCluster = ({
@@ -1109,13 +2217,15 @@ var makeCluster = async (w, clusterStartTimestamp) => {
1109
2217
  chunk,
1110
2218
  newT
1111
2219
  }) => {
1112
- const newTimestamp = timestampToClusterTimestamp(newT);
1113
- const oldTimestamp = timestampToClusterTimestamp(clusterStartTimestamp);
2220
+ const newTimestamp = timestampToClusterTimestamp(newT, timescale);
2221
+ const oldTimestamp = timestampToClusterTimestamp(clusterStartTimestamp, timescale);
1114
2222
  const canFit = canFitInCluster({
1115
2223
  chunk,
1116
- clusterStartTimestamp
2224
+ clusterStartTimestamp,
2225
+ timescale
1117
2226
  });
1118
2227
  if (!canFit) {
2228
+ Log.verbose(logLevel, `Cannot fit ${chunk.timestamp} in cluster ${clusterStartTimestamp}. Creating new cluster`);
1119
2229
  return true;
1120
2230
  }
1121
2231
  const keyframe = chunk.type === "key";
@@ -1128,7 +2238,7 @@ var makeCluster = async (w, clusterStartTimestamp) => {
1128
2238
  };
1129
2239
  };
1130
2240
 
1131
- // src/create/make-duration-with-padding.ts
2241
+ // src/create/matroska/make-duration-with-padding.ts
1132
2242
  var makeDurationWithPadding = (newDuration) => {
1133
2243
  return makeMatroskaBytes({
1134
2244
  type: "Duration",
@@ -1140,7 +2250,7 @@ var makeDurationWithPadding = (newDuration) => {
1140
2250
  });
1141
2251
  };
1142
2252
 
1143
- // src/create/matroska-cues.ts
2253
+ // src/create/matroska/matroska-cues.ts
1144
2254
  var createMatroskaCues = (cues) => {
1145
2255
  return makeMatroskaBytes({
1146
2256
  type: "Cues",
@@ -1186,7 +2296,7 @@ var createMatroskaCues = (cues) => {
1186
2296
  });
1187
2297
  };
1188
2298
 
1189
- // src/create/matroska-header.ts
2299
+ // src/create/matroska/matroska-header.ts
1190
2300
  var makeMatroskaHeader = () => {
1191
2301
  return makeMatroskaBytes({
1192
2302
  type: "Header",
@@ -1249,7 +2359,7 @@ var makeMatroskaHeader = () => {
1249
2359
  });
1250
2360
  };
1251
2361
 
1252
- // src/create/matroska-info.ts
2362
+ // src/create/matroska/matroska-info.ts
1253
2363
  var makeMatroskaInfo = ({ timescale }) => {
1254
2364
  return makeMatroskaBytes({
1255
2365
  type: "Info",
@@ -1278,7 +2388,7 @@ var makeMatroskaInfo = ({ timescale }) => {
1278
2388
  });
1279
2389
  };
1280
2390
 
1281
- // src/create/matroska-seek.ts
2391
+ // src/create/matroska/matroska-seek.ts
1282
2392
  var createMatroskaSeekHead = (seeks) => {
1283
2393
  return padMatroskaBytes(makeMatroskaBytes({
1284
2394
  type: "SeekHead",
@@ -1307,7 +2417,7 @@ var createMatroskaSeekHead = (seeks) => {
1307
2417
  }), 200);
1308
2418
  };
1309
2419
 
1310
- // src/create/matroska-segment.ts
2420
+ // src/create/matroska/matroska-segment.ts
1311
2421
  var MATROSKA_SEGMENT_MIN_VINT_WIDTH = 8;
1312
2422
  var createMatroskaSegment = (children) => {
1313
2423
  return makeMatroskaBytes({
@@ -1317,11 +2427,6 @@ var createMatroskaSegment = (children) => {
1317
2427
  });
1318
2428
  };
1319
2429
 
1320
- // src/truthy.ts
1321
- function truthy(value) {
1322
- return Boolean(value);
1323
- }
1324
-
1325
2430
  // src/boxes/webm/traversal.ts
1326
2431
  var getMainSegment = (segments) => {
1327
2432
  return segments.find((s) => s.type === "Segment");
@@ -1584,7 +2689,7 @@ var makeMatroskaColorBytes = ({
1584
2689
  });
1585
2690
  };
1586
2691
 
1587
- // src/create/matroska-trackentry.ts
2692
+ // src/create/matroska/matroska-trackentry.ts
1588
2693
  var makeMatroskaVideoBytes = ({
1589
2694
  color: color2,
1590
2695
  width,
@@ -1824,24 +2929,31 @@ var makeMatroskaVideoTrackEntryBytes = ({
1824
2929
  });
1825
2930
  };
1826
2931
  var makeMatroskaTracks = (tracks2) => {
2932
+ const bytesArr = tracks2.map((t) => {
2933
+ const bytes = t.type === "video" ? makeMatroskaVideoTrackEntryBytes(t) : makeMatroskaAudioTrackEntryBytes(t);
2934
+ return bytes;
2935
+ });
1827
2936
  return padMatroskaBytes(makeMatroskaBytes({
1828
2937
  type: "Tracks",
1829
- value: tracks2,
2938
+ value: bytesArr,
1830
2939
  minVintWidth: null
1831
2940
  }), 500);
1832
2941
  };
1833
2942
 
1834
- // src/create/create-media.ts
1835
- var createMedia = async ({
2943
+ // src/create/matroska/create-matroska-media.ts
2944
+ var timescale = 1e6;
2945
+ var createMatroskaMedia = async ({
1836
2946
  writer,
1837
2947
  onBytesProgress,
1838
- onMillisecondsProgress
2948
+ onMillisecondsProgress,
2949
+ filename,
2950
+ logLevel
1839
2951
  }) => {
1840
2952
  const header = makeMatroskaHeader();
1841
- const w = await writer.createContent();
2953
+ const w = await writer.createContent({ filename, mimeType: "video/webm" });
1842
2954
  await w.write(header.bytes);
1843
2955
  const matroskaInfo = makeMatroskaInfo({
1844
- timescale: CREATE_TIME_SCALE
2956
+ timescale
1845
2957
  });
1846
2958
  const currentTracks = [];
1847
2959
  const seeks = [];
@@ -1890,7 +3002,12 @@ var createMedia = async ({
1890
3002
  };
1891
3003
  await w.write(matroskaSegment.bytes);
1892
3004
  const clusterOffset = w.getWrittenByteCount();
1893
- let currentCluster = await makeCluster(w, 0);
3005
+ let currentCluster = await makeCluster({
3006
+ writer: w,
3007
+ clusterStartTimestamp: 0,
3008
+ timescale,
3009
+ logLevel
3010
+ });
1894
3011
  seeks.push({
1895
3012
  hexString: matroskaElements.Cluster,
1896
3013
  byte: clusterOffset - seekHeadOffset
@@ -1898,9 +3015,14 @@ var createMedia = async ({
1898
3015
  const trackNumberProgresses = {};
1899
3016
  const getClusterOrMakeNew = async ({
1900
3017
  chunk,
1901
- isVideo
3018
+ isVideo,
3019
+ trackNumber: trackNumber2
1902
3020
  }) => {
1903
- const smallestProgress = Math.min(...Object.values(trackNumberProgresses));
3021
+ const trackProgressValues = Object.values(trackNumberProgresses);
3022
+ const smallestProgress = trackProgressValues.length === 0 ? 0 : Math.min(...trackProgressValues);
3023
+ if (chunk.type === "key") {
3024
+ trackNumberProgresses[trackNumber2] = chunk.timestamp;
3025
+ }
1904
3026
  if (!currentCluster.shouldMakeNewCluster({
1905
3027
  newT: smallestProgress,
1906
3028
  isVideo,
@@ -1908,7 +3030,12 @@ var createMedia = async ({
1908
3030
  })) {
1909
3031
  return { cluster: currentCluster, isNew: false, smallestProgress };
1910
3032
  }
1911
- currentCluster = await makeCluster(w, smallestProgress);
3033
+ currentCluster = await makeCluster({
3034
+ writer: w,
3035
+ clusterStartTimestamp: smallestProgress,
3036
+ timescale,
3037
+ logLevel
3038
+ });
1912
3039
  return { cluster: currentCluster, isNew: true, smallestProgress };
1913
3040
  };
1914
3041
  const updateDuration = async (newDuration) => {
@@ -1916,11 +3043,15 @@ var createMedia = async ({
1916
3043
  await w.updateDataAt(durationOffset, blocks.bytes);
1917
3044
  onBytesProgress(w.getWrittenByteCount());
1918
3045
  };
1919
- const addSample = async (chunk, trackNumber2, isVideo) => {
1920
- trackNumberProgresses[trackNumber2] = chunk.timestamp;
3046
+ const addSample = async ({
3047
+ chunk,
3048
+ trackNumber: trackNumber2,
3049
+ isVideo
3050
+ }) => {
1921
3051
  const { cluster, isNew, smallestProgress } = await getClusterOrMakeNew({
1922
3052
  chunk,
1923
- isVideo
3053
+ isVideo,
3054
+ trackNumber: trackNumber2
1924
3055
  });
1925
3056
  const newDuration = Math.round((chunk.timestamp + (chunk.duration ?? 0)) / 1000);
1926
3057
  await updateDuration(newDuration);
@@ -1928,7 +3059,7 @@ var createMedia = async ({
1928
3059
  if (isNew) {
1929
3060
  const newCluster = w.getWrittenByteCount();
1930
3061
  cues.push({
1931
- time: timestampToClusterTimestamp(smallestProgress) + timecodeRelativeToCluster,
3062
+ time: timestampToClusterTimestamp(smallestProgress, timescale) + timecodeRelativeToCluster,
1932
3063
  clusterPosition: newCluster - seekHeadOffset,
1933
3064
  trackNumber: trackNumber2
1934
3065
  });
@@ -1944,79 +3075,53 @@ var createMedia = async ({
1944
3075
  const operationProm = { current: Promise.resolve() };
1945
3076
  const waitForFinishPromises = [];
1946
3077
  return {
1947
- save: async () => {
1948
- const file = await w.save();
1949
- return file;
3078
+ updateTrackSampleRate: ({ sampleRate, trackNumber: trackNumber2 }) => {
3079
+ currentTracks.forEach((track) => {
3080
+ if (track.trackNumber === trackNumber2) {
3081
+ if (track.type !== "audio") {
3082
+ throw new Error("track is not audio");
3083
+ }
3084
+ track.sampleRate = sampleRate;
3085
+ }
3086
+ });
3087
+ },
3088
+ save: () => {
3089
+ return w.save();
1950
3090
  },
1951
3091
  remove: async () => {
1952
3092
  await w.remove();
1953
3093
  },
1954
- addSample: (chunk, trackNumber2, isVideo) => {
1955
- operationProm.current = operationProm.current.then(() => addSample(chunk, trackNumber2, isVideo));
3094
+ addSample: ({ chunk, trackNumber: trackNumber2, isVideo }) => {
3095
+ operationProm.current = operationProm.current.then(() => addSample({ chunk, trackNumber: trackNumber2, isVideo }));
1956
3096
  return operationProm.current;
1957
3097
  },
1958
3098
  updateDuration: (duration2) => {
1959
3099
  operationProm.current = operationProm.current.then(() => updateDuration(duration2));
1960
3100
  return operationProm.current;
1961
- },
1962
- addTrack: (track) => {
1963
- const trackNumber2 = currentTracks.length + 1;
1964
- const bytes = track.type === "video" ? makeMatroskaVideoTrackEntryBytes({ ...track, trackNumber: trackNumber2 }) : makeMatroskaAudioTrackEntryBytes({ ...track, trackNumber: trackNumber2 });
1965
- operationProm.current = operationProm.current.then(() => addTrack(bytes));
1966
- trackNumbers.push(trackNumber2);
1967
- return operationProm.current.then(() => ({ trackNumber: trackNumber2 }));
1968
- },
1969
- addWaitForFinishPromise: (promise) => {
1970
- waitForFinishPromises.push(promise);
1971
- },
1972
- async waitForFinish() {
1973
- await Promise.all(waitForFinishPromises.map((p) => p()));
1974
- await operationProm.current;
1975
- seeks.push({
1976
- hexString: matroskaElements.Cues,
1977
- byte: w.getWrittenByteCount() - seekHeadOffset
1978
- });
1979
- await updateSeekWrite();
1980
- await w.write(createMatroskaCues(cues).bytes);
1981
- await w.waitForFinish();
1982
- const segmentSize = w.getWrittenByteCount() - segmentOffset - matroskaToHex(matroskaElements.Segment).byteLength - MATROSKA_SEGMENT_MIN_VINT_WIDTH;
1983
- await updateSegmentSize(segmentSize);
1984
- }
1985
- };
1986
- };
1987
-
1988
- // src/log.ts
1989
- var logLevels = ["trace", "verbose", "info", "warn", "error"];
1990
- var getNumberForLogLevel = (level) => {
1991
- return logLevels.indexOf(level);
1992
- };
1993
- var isEqualOrBelowLogLevel = (currentLevel, level) => {
1994
- return getNumberForLogLevel(currentLevel) <= getNumberForLogLevel(level);
1995
- };
1996
- var Log = {
1997
- trace: (logLevel, ...args) => {
1998
- if (isEqualOrBelowLogLevel(logLevel, "trace")) {
1999
- return console.log(...args);
2000
- }
2001
- },
2002
- verbose: (logLevel, ...args) => {
2003
- if (isEqualOrBelowLogLevel(logLevel, "verbose")) {
2004
- return console.log(...args);
2005
- }
2006
- },
2007
- info: (logLevel, ...args) => {
2008
- if (isEqualOrBelowLogLevel(logLevel, "info")) {
2009
- return console.log(...args);
2010
- }
2011
- },
2012
- warn: (logLevel, ...args) => {
2013
- if (isEqualOrBelowLogLevel(logLevel, "warn")) {
2014
- return console.warn(...args);
3101
+ },
3102
+ addTrack: (track) => {
3103
+ const trackNumber2 = currentTracks.length + 1;
3104
+ operationProm.current = operationProm.current.then(() => addTrack({ ...track, trackNumber: trackNumber2 }));
3105
+ trackNumbers.push(trackNumber2);
3106
+ return operationProm.current.then(() => ({ trackNumber: trackNumber2 }));
3107
+ },
3108
+ addWaitForFinishPromise: (promise) => {
3109
+ waitForFinishPromises.push(promise);
3110
+ },
3111
+ async waitForFinish() {
3112
+ await Promise.all(waitForFinishPromises.map((p) => p()));
3113
+ await operationProm.current;
3114
+ seeks.push({
3115
+ hexString: matroskaElements.Cues,
3116
+ byte: w.getWrittenByteCount() - seekHeadOffset
3117
+ });
3118
+ await updateSeekWrite();
3119
+ await w.write(createMatroskaCues(cues).bytes);
3120
+ await w.waitForFinish();
3121
+ const segmentSize = w.getWrittenByteCount() - segmentOffset - matroskaToHex(matroskaElements.Segment).byteLength - MATROSKA_SEGMENT_MIN_VINT_WIDTH;
3122
+ await updateSegmentSize(segmentSize);
2015
3123
  }
2016
- },
2017
- error: (...args) => {
2018
- return console.error(...args);
2019
- }
3124
+ };
2020
3125
  };
2021
3126
 
2022
3127
  // src/boxes/iso-base-media/traversal.ts
@@ -2053,135 +3158,373 @@ var getMdiaBox = (trakBox) => {
2053
3158
  if (!mdiaBox || mdiaBox.type !== "regular-box") {
2054
3159
  return null;
2055
3160
  }
2056
- return mdiaBox;
3161
+ return mdiaBox;
3162
+ };
3163
+ var getMdhdBox = (trakBox) => {
3164
+ const mdiaBox = getMdiaBox(trakBox);
3165
+ if (!mdiaBox) {
3166
+ return null;
3167
+ }
3168
+ const mdhdBox = mdiaBox.children.find((c) => c.type === "mdhd-box");
3169
+ return mdhdBox;
3170
+ };
3171
+ var getStblBox = (trakBox) => {
3172
+ const mdiaBox = getMdiaBox(trakBox);
3173
+ if (!mdiaBox) {
3174
+ return null;
3175
+ }
3176
+ const minfBox = mdiaBox.children.find((s) => s.type === "regular-box" && s.boxType === "minf");
3177
+ if (!minfBox || minfBox.type !== "regular-box") {
3178
+ return null;
3179
+ }
3180
+ const stblBox = minfBox.children.find((s) => s.type === "regular-box" && s.boxType === "stbl");
3181
+ if (!stblBox || stblBox.type !== "regular-box") {
3182
+ return null;
3183
+ }
3184
+ return stblBox;
3185
+ };
3186
+ var getStsdBox = (trakBox) => {
3187
+ const stblBox = getStblBox(trakBox);
3188
+ if (!stblBox || stblBox.type !== "regular-box") {
3189
+ return null;
3190
+ }
3191
+ const stsdBox = stblBox.children.find((s) => s.type === "stsd-box");
3192
+ return stsdBox;
3193
+ };
3194
+ var getVideoDescriptors = (trakBox) => {
3195
+ const stsdBox = getStsdBox(trakBox);
3196
+ if (!stsdBox) {
3197
+ return null;
3198
+ }
3199
+ const descriptors = stsdBox.samples.map((s) => {
3200
+ return s.type === "video" ? s.descriptors.map((d) => {
3201
+ return d.type === "avcc-box" ? d.privateData : d.type === "hvcc-box" ? d.privateData : null;
3202
+ }) : [];
3203
+ });
3204
+ return descriptors.flat(1).filter(Boolean)[0] ?? null;
3205
+ };
3206
+ var getStcoBox = (trakBox) => {
3207
+ const stblBox = getStblBox(trakBox);
3208
+ if (!stblBox || stblBox.type !== "regular-box") {
3209
+ return null;
3210
+ }
3211
+ const stcoBox = stblBox.children.find((s) => s.type === "stco-box");
3212
+ return stcoBox;
3213
+ };
3214
+ var getSttsBox = (trakBox) => {
3215
+ const stblBox = getStblBox(trakBox);
3216
+ if (!stblBox || stblBox.type !== "regular-box") {
3217
+ return null;
3218
+ }
3219
+ const sttsBox = stblBox.children.find((s) => s.type === "stts-box");
3220
+ return sttsBox;
3221
+ };
3222
+ var getCttsBox = (trakBox) => {
3223
+ const stblBox = getStblBox(trakBox);
3224
+ if (!stblBox || stblBox.type !== "regular-box") {
3225
+ return null;
3226
+ }
3227
+ const cttsBox = stblBox.children.find((s) => s.type === "ctts-box");
3228
+ return cttsBox;
3229
+ };
3230
+ var getStszBox = (trakBox) => {
3231
+ const stblBox = getStblBox(trakBox);
3232
+ if (!stblBox || stblBox.type !== "regular-box") {
3233
+ return null;
3234
+ }
3235
+ const stszBox = stblBox.children.find((s) => s.type === "stsz-box");
3236
+ return stszBox;
3237
+ };
3238
+ var getStscBox = (trakBox) => {
3239
+ const stblBox = getStblBox(trakBox);
3240
+ if (!stblBox || stblBox.type !== "regular-box") {
3241
+ return null;
3242
+ }
3243
+ const stcoBox = stblBox.children.find((b) => b.type === "stsc-box");
3244
+ return stcoBox;
3245
+ };
3246
+ var getStssBox = (trakBox) => {
3247
+ const stblBox = getStblBox(trakBox);
3248
+ if (!stblBox || stblBox.type !== "regular-box") {
3249
+ return null;
3250
+ }
3251
+ const stssBox = stblBox.children.find((b) => b.type === "stss-box");
3252
+ return stssBox;
3253
+ };
3254
+ var getTfdtBox = (segment) => {
3255
+ if (segment.type !== "regular-box" || segment.boxType !== "traf") {
3256
+ throw new Error("Expected traf-box");
3257
+ }
3258
+ const tfhdBox = segment.children.find((c) => c.type === "tfdt-box");
3259
+ if (!tfhdBox || tfhdBox.type !== "tfdt-box") {
3260
+ throw new Error("Expected tfhd-box");
3261
+ }
3262
+ return tfhdBox;
3263
+ };
3264
+ var getTfhdBox = (segment) => {
3265
+ if (segment.type !== "regular-box" || segment.boxType !== "traf") {
3266
+ throw new Error("Expected traf-box");
3267
+ }
3268
+ const tfhdBox = segment.children.find((c) => c.type === "tfhd-box");
3269
+ if (!tfhdBox || tfhdBox.type !== "tfhd-box") {
3270
+ throw new Error("Expected tfhd-box");
3271
+ }
3272
+ return tfhdBox;
3273
+ };
3274
+ var getTrunBoxes = (segment) => {
3275
+ if (segment.type !== "regular-box" || segment.boxType !== "traf") {
3276
+ throw new Error("Expected traf-box");
3277
+ }
3278
+ const trunBoxes = segment.children.filter((c) => c.type === "trun-box");
3279
+ return trunBoxes;
3280
+ };
3281
+ var getMdatBox = (anySegment) => {
3282
+ const mdat = anySegment.find((b) => b.type === "mdat-box");
3283
+ if (!mdat) {
3284
+ return null;
3285
+ }
3286
+ if (mdat.type !== "mdat-box") {
3287
+ throw new Error("Expected mdat-box");
3288
+ }
3289
+ return mdat;
3290
+ };
3291
+
3292
+ // src/get-sample-positions.ts
3293
+ var getSamplePositions = ({
3294
+ stcoBox,
3295
+ stszBox,
3296
+ stscBox,
3297
+ stssBox,
3298
+ sttsBox,
3299
+ cttsBox
3300
+ }) => {
3301
+ const sttsDeltas = [];
3302
+ for (const distribution of sttsBox.sampleDistribution) {
3303
+ for (let i = 0;i < distribution.sampleCount; i++) {
3304
+ sttsDeltas.push(distribution.sampleDelta);
3305
+ }
3306
+ }
3307
+ const cttsEntries = [];
3308
+ for (const entry of cttsBox?.entries ?? [
3309
+ { sampleCount: sttsDeltas.length, sampleOffset: 0 }
3310
+ ]) {
3311
+ for (let i = 0;i < entry.sampleCount; i++) {
3312
+ cttsEntries.push(entry.sampleOffset);
3313
+ }
3314
+ }
3315
+ let dts = 0;
3316
+ const chunks = stcoBox.entries;
3317
+ const samples = [];
3318
+ let samplesPerChunk = 1;
3319
+ for (let i = 0;i < chunks.length; i++) {
3320
+ const hasEntry = stscBox.entries.find((entry) => entry.firstChunk === i + 1);
3321
+ if (hasEntry) {
3322
+ samplesPerChunk = hasEntry.samplesPerChunk;
3323
+ }
3324
+ let offsetInThisChunk = 0;
3325
+ for (let j = 0;j < samplesPerChunk; j++) {
3326
+ const size = stszBox.countType === "fixed" ? stszBox.sampleSize : stszBox.entries[samples.length];
3327
+ const isKeyframe = stssBox ? stssBox.sampleNumber.includes(samples.length + 1) : true;
3328
+ const delta = sttsDeltas[samples.length];
3329
+ const ctsOffset = cttsEntries[samples.length];
3330
+ const cts = dts + ctsOffset;
3331
+ samples.push({
3332
+ offset: Number(chunks[i]) + offsetInThisChunk,
3333
+ size,
3334
+ isKeyframe,
3335
+ dts,
3336
+ cts,
3337
+ duration: delta,
3338
+ chunk: i
3339
+ });
3340
+ dts += delta;
3341
+ offsetInThisChunk += size;
3342
+ }
3343
+ }
3344
+ return samples;
3345
+ };
3346
+
3347
+ // src/samples-from-moof.ts
3348
+ var getSamplesFromTraf = (trafSegment, moofOffset) => {
3349
+ if (trafSegment.type !== "regular-box" || trafSegment.boxType !== "traf") {
3350
+ throw new Error("Expected traf-box");
3351
+ }
3352
+ const tfhdBox = getTfhdBox(trafSegment);
3353
+ const defaultSampleDuration = tfhdBox?.defaultSampleDuration ?? null;
3354
+ const defaultSampleSize = tfhdBox?.defaultSampleSize ?? null;
3355
+ const defaultSampleFlags = tfhdBox?.defaultSampleFlags ?? null;
3356
+ const tfdtBox = getTfdtBox(trafSegment);
3357
+ const trunBoxes = getTrunBoxes(trafSegment);
3358
+ let time = 0;
3359
+ let offset = 0;
3360
+ let dataOffset = 0;
3361
+ const samples = [];
3362
+ for (const trunBox of trunBoxes) {
3363
+ let i = -1;
3364
+ if (trunBox.dataOffset) {
3365
+ dataOffset = trunBox.dataOffset;
3366
+ offset = 0;
3367
+ }
3368
+ for (const sample of trunBox.samples) {
3369
+ i++;
3370
+ const duration2 = sample.sampleDuration ?? defaultSampleDuration;
3371
+ if (duration2 === null) {
3372
+ throw new Error("Expected duration");
3373
+ }
3374
+ const size = sample.sampleSize ?? defaultSampleSize;
3375
+ if (size === null) {
3376
+ throw new Error("Expected size");
3377
+ }
3378
+ const isFirstSample = i === 0;
3379
+ const sampleFlags = sample.sampleFlags ? sample.sampleFlags : isFirstSample && trunBox.firstSampleFlags !== null ? trunBox.firstSampleFlags : defaultSampleFlags;
3380
+ if (sampleFlags === null) {
3381
+ throw new Error("Expected sample flags");
3382
+ }
3383
+ const keyframe = !(sampleFlags >> 16 & 1);
3384
+ const dts = time + (tfdtBox?.baseMediaDecodeTime ?? 0);
3385
+ const samplePosition = {
3386
+ offset: offset + (moofOffset ?? 0) + (dataOffset ?? 0),
3387
+ dts,
3388
+ cts: dts,
3389
+ duration: duration2,
3390
+ isKeyframe: keyframe,
3391
+ size,
3392
+ chunk: 0
3393
+ };
3394
+ samples.push(samplePosition);
3395
+ offset += size;
3396
+ time += duration2;
3397
+ }
3398
+ }
3399
+ return samples;
2057
3400
  };
2058
- var getMdhdBox = (trakBox) => {
2059
- const mdiaBox = getMdiaBox(trakBox);
2060
- if (!mdiaBox) {
2061
- return null;
3401
+ var getSamplesFromMoof = ({
3402
+ moofBox,
3403
+ trackId
3404
+ }) => {
3405
+ if (moofBox.type !== "regular-box") {
3406
+ throw new Error("Expected moof-box");
2062
3407
  }
2063
- const mdhdBox = mdiaBox.children.find((c) => c.type === "mdhd-box");
2064
- return mdhdBox;
3408
+ const trafs = moofBox.children.filter((c) => c.type === "regular-box" && c.boxType === "traf");
3409
+ const mapped = trafs.map((traf) => {
3410
+ const tfhdBox = getTfhdBox(traf);
3411
+ return tfhdBox?.trackId === trackId ? getSamplesFromTraf(traf, moofBox.offset) : [];
3412
+ });
3413
+ return mapped.flat(1);
2065
3414
  };
2066
- var getStblBox = (trakBox) => {
2067
- const mdiaBox = getMdiaBox(trakBox);
2068
- if (!mdiaBox) {
2069
- return null;
3415
+
3416
+ // src/boxes/iso-base-media/get-sample-positions-from-track.ts
3417
+ var getSamplePositionsFromTrack = (trakBox, moofBox) => {
3418
+ const stszBox = getStszBox(trakBox);
3419
+ const stcoBox = getStcoBox(trakBox);
3420
+ const stscBox = getStscBox(trakBox);
3421
+ const stssBox = getStssBox(trakBox);
3422
+ const sttsBox = getSttsBox(trakBox);
3423
+ const tkhdBox = getTkhdBox(trakBox);
3424
+ const cttsBox = getCttsBox(trakBox);
3425
+ const timescaleAndDuration = getTimescaleAndDuration(trakBox);
3426
+ if (!tkhdBox) {
3427
+ throw new Error("Expected tkhd box in trak box");
2070
3428
  }
2071
- const minfBox = mdiaBox.children.find((s) => s.type === "regular-box" && s.boxType === "minf");
2072
- if (!minfBox || minfBox.type !== "regular-box") {
2073
- return null;
3429
+ if (!stszBox) {
3430
+ throw new Error("Expected stsz box in trak box");
2074
3431
  }
2075
- const stblBox = minfBox.children.find((s) => s.type === "regular-box" && s.boxType === "stbl");
2076
- if (!stblBox || stblBox.type !== "regular-box") {
2077
- return null;
3432
+ if (!stcoBox) {
3433
+ throw new Error("Expected stco box in trak box");
2078
3434
  }
2079
- return stblBox;
2080
- };
2081
- var getStsdBox = (trakBox) => {
2082
- const stblBox = getStblBox(trakBox);
2083
- if (!stblBox || stblBox.type !== "regular-box") {
2084
- return null;
3435
+ if (!stscBox) {
3436
+ throw new Error("Expected stsc box in trak box");
2085
3437
  }
2086
- const stsdBox = stblBox.children.find((s) => s.type === "stsd-box");
2087
- return stsdBox;
2088
- };
2089
- var getVideoDescriptors = (trakBox) => {
2090
- const stsdBox = getStsdBox(trakBox);
2091
- if (!stsdBox) {
2092
- return null;
3438
+ if (!sttsBox) {
3439
+ throw new Error("Expected stts box in trak box");
2093
3440
  }
2094
- const descriptors = stsdBox.samples.map((s) => {
2095
- return s.type === "video" ? s.descriptors.map((d) => {
2096
- return d.type === "avcc-box" ? d.privateData : d.type === "hvcc-box" ? d.privateData : null;
2097
- }) : [];
3441
+ if (!timescaleAndDuration) {
3442
+ throw new Error("Expected timescale and duration in trak box");
3443
+ }
3444
+ let samplePositions = getSamplePositions({
3445
+ stcoBox,
3446
+ stscBox,
3447
+ stszBox,
3448
+ stssBox,
3449
+ sttsBox,
3450
+ cttsBox
2098
3451
  });
2099
- return descriptors.flat(1).filter(Boolean)[0] ?? null;
2100
- };
2101
- var getStcoBox = (trakBox) => {
2102
- const stblBox = getStblBox(trakBox);
2103
- if (!stblBox || stblBox.type !== "regular-box") {
2104
- return null;
3452
+ if (samplePositions.length === 0 && moofBox) {
3453
+ samplePositions = getSamplesFromMoof({ moofBox, trackId: tkhdBox.trackId });
2105
3454
  }
2106
- const stcoBox = stblBox.children.find((s) => s.type === "stco-box");
2107
- return stcoBox;
3455
+ return samplePositions;
2108
3456
  };
2109
- var getSttsBox = (trakBox) => {
2110
- const stblBox = getStblBox(trakBox);
2111
- if (!stblBox || stblBox.type !== "regular-box") {
3457
+
3458
+ // src/get-duration.ts
3459
+ var getDurationFromMatroska = (segments) => {
3460
+ const mainSegment = segments.find((s) => s.type === "Segment");
3461
+ if (!mainSegment || mainSegment.type !== "Segment") {
2112
3462
  return null;
2113
3463
  }
2114
- const sttsBox = stblBox.children.find((s) => s.type === "stts-box");
2115
- return sttsBox;
2116
- };
2117
- var getCttsBox = (trakBox) => {
2118
- const stblBox = getStblBox(trakBox);
2119
- if (!stblBox || stblBox.type !== "regular-box") {
3464
+ const { value: children } = mainSegment;
3465
+ if (!children) {
2120
3466
  return null;
2121
3467
  }
2122
- const cttsBox = stblBox.children.find((s) => s.type === "ctts-box");
2123
- return cttsBox;
2124
- };
2125
- var getStszBox = (trakBox) => {
2126
- const stblBox = getStblBox(trakBox);
2127
- if (!stblBox || stblBox.type !== "regular-box") {
3468
+ const infoSegment = children.find((s) => s.type === "Info");
3469
+ const relevantBoxes = [
3470
+ ...mainSegment.value,
3471
+ ...infoSegment && infoSegment.type === "Info" ? infoSegment.value : []
3472
+ ];
3473
+ const timestampScale2 = relevantBoxes.find((s) => s.type === "TimestampScale");
3474
+ if (!timestampScale2 || timestampScale2.type !== "TimestampScale") {
2128
3475
  return null;
2129
3476
  }
2130
- const stszBox = stblBox.children.find((s) => s.type === "stsz-box");
2131
- return stszBox;
2132
- };
2133
- var getStscBox = (trakBox) => {
2134
- const stblBox = getStblBox(trakBox);
2135
- if (!stblBox || stblBox.type !== "regular-box") {
3477
+ const duration2 = relevantBoxes.find((s) => s.type === "Duration");
3478
+ if (!duration2 || duration2.type !== "Duration") {
2136
3479
  return null;
2137
3480
  }
2138
- const stcoBox = stblBox.children.find((b) => b.type === "stsc-box");
2139
- return stcoBox;
3481
+ return duration2.value.value / timestampScale2.value.value * 1000;
2140
3482
  };
2141
- var getStssBox = (trakBox) => {
2142
- const stblBox = getStblBox(trakBox);
2143
- if (!stblBox || stblBox.type !== "regular-box") {
2144
- return null;
2145
- }
2146
- const stssBox = stblBox.children.find((b) => b.type === "stss-box");
2147
- return stssBox;
3483
+ var isMatroska = (boxes) => {
3484
+ const matroskaBox = boxes.find((b) => b.type === "Segment");
3485
+ return matroskaBox;
2148
3486
  };
2149
- var getTfdtBox = (segment) => {
2150
- if (segment.type !== "regular-box" || segment.boxType !== "traf") {
2151
- throw new Error("Expected traf-box");
3487
+ var getDuration = (boxes, parserState) => {
3488
+ if (isMatroska(boxes)) {
3489
+ return getDurationFromMatroska(boxes);
2152
3490
  }
2153
- const tfhdBox = segment.children.find((c) => c.type === "tfdt-box");
2154
- if (!tfhdBox || tfhdBox.type !== "tfdt-box") {
2155
- throw new Error("Expected tfhd-box");
3491
+ const moovBox = getMoovBox(boxes);
3492
+ if (!moovBox) {
3493
+ return null;
2156
3494
  }
2157
- return tfhdBox;
2158
- };
2159
- var getTfhdBox = (segment) => {
2160
- if (segment.type !== "regular-box" || segment.boxType !== "traf") {
2161
- throw new Error("Expected traf-box");
3495
+ const moofBox = getMoofBox(boxes);
3496
+ const mvhdBox = getMvhdBox(moovBox);
3497
+ if (!mvhdBox) {
3498
+ return null;
2162
3499
  }
2163
- const tfhdBox = segment.children.find((c) => c.type === "tfhd-box");
2164
- if (!tfhdBox || tfhdBox.type !== "tfhd-box") {
2165
- throw new Error("Expected tfhd-box");
3500
+ if (mvhdBox.type !== "mvhd-box") {
3501
+ throw new Error("Expected mvhd-box");
2166
3502
  }
2167
- return tfhdBox;
2168
- };
2169
- var getTrunBoxes = (segment) => {
2170
- if (segment.type !== "regular-box" || segment.boxType !== "traf") {
2171
- throw new Error("Expected traf-box");
3503
+ if (mvhdBox.durationInSeconds > 0) {
3504
+ return mvhdBox.durationInSeconds;
2172
3505
  }
2173
- const trunBoxes = segment.children.filter((c) => c.type === "trun-box");
2174
- return trunBoxes;
3506
+ const tracks2 = getTracks(boxes, parserState);
3507
+ const allTracks = [
3508
+ ...tracks2.videoTracks,
3509
+ ...tracks2.audioTracks,
3510
+ ...tracks2.otherTracks
3511
+ ];
3512
+ const allSamples = allTracks.map((t) => {
3513
+ const { timescale: ts } = t;
3514
+ const samplePositions = getSamplePositionsFromTrack(t.trakBox, moofBox);
3515
+ const highest = samplePositions?.map((sp) => (sp.cts + sp.duration) / ts).reduce((a, b) => Math.max(a, b), 0);
3516
+ return highest ?? 0;
3517
+ });
3518
+ const highestTimestamp = Math.max(...allSamples);
3519
+ return highestTimestamp;
2175
3520
  };
2176
- var getMdatBox = (anySegment) => {
2177
- const mdat = anySegment.find((b) => b.type === "mdat-box");
2178
- if (!mdat) {
2179
- return null;
2180
- }
2181
- if (mdat.type !== "mdat-box") {
2182
- throw new Error("Expected mdat-box");
3521
+ var hasDuration = (boxes, parserState) => {
3522
+ try {
3523
+ const duration2 = getDuration(boxes, parserState);
3524
+ return getDuration(boxes, parserState) !== null && duration2 !== 0;
3525
+ } catch {
3526
+ return false;
2183
3527
  }
2184
- return mdat;
2185
3528
  };
2186
3529
 
2187
3530
  // src/get-fps.ts
@@ -2227,21 +3570,12 @@ var getTimescaleAndDuration = (trakBox) => {
2227
3570
  }
2228
3571
  return null;
2229
3572
  };
2230
- var getFps = (segments) => {
2231
- const moovBox = getMoovBox(segments);
2232
- if (!moovBox) {
2233
- return null;
2234
- }
2235
- const trackBoxes = getTraks(moovBox);
2236
- const trackBox = trackBoxes.find(trakBoxContainsVideo);
2237
- if (!trackBox) {
2238
- return null;
2239
- }
2240
- const timescaleAndDuration = getTimescaleAndDuration(trackBox);
3573
+ var getFpsFromMp4TrakBox = (trakBox) => {
3574
+ const timescaleAndDuration = getTimescaleAndDuration(trakBox);
2241
3575
  if (!timescaleAndDuration) {
2242
3576
  return null;
2243
3577
  }
2244
- const sttsBox = getSttsBox(trackBox);
3578
+ const sttsBox = getSttsBox(trakBox);
2245
3579
  if (!sttsBox) {
2246
3580
  return null;
2247
3581
  }
@@ -2251,8 +3585,23 @@ var getFps = (segments) => {
2251
3585
  durationInSamples: timescaleAndDuration.duration
2252
3586
  });
2253
3587
  };
3588
+ var getFps = (segments) => {
3589
+ const moovBox = getMoovBox(segments);
3590
+ if (!moovBox) {
3591
+ return null;
3592
+ }
3593
+ const trackBoxes = getTraks(moovBox);
3594
+ const trackBox = trackBoxes.find(trakBoxContainsVideo);
3595
+ if (!trackBox) {
3596
+ return null;
3597
+ }
3598
+ return getFpsFromMp4TrakBox(trackBox);
3599
+ };
2254
3600
  var hasFps = (boxes) => {
2255
3601
  try {
3602
+ if (isMatroska(boxes)) {
3603
+ return true;
3604
+ }
2256
3605
  return getFps(boxes) !== null;
2257
3606
  } catch {
2258
3607
  return false;
@@ -2275,12 +3624,8 @@ var getAudioCodec = (boxes, parserState) => {
2275
3624
  }
2276
3625
  return null;
2277
3626
  };
2278
- var hasAudioCodec = (boxes, state) => {
2279
- try {
2280
- return getAudioCodec(boxes, state) !== null;
2281
- } catch {
2282
- return false;
2283
- }
3627
+ var hasAudioCodec = (boxes) => {
3628
+ return hasTracks(boxes);
2284
3629
  };
2285
3630
  var getCodecSpecificatorFromEsdsBox = ({
2286
3631
  child
@@ -2300,9 +3645,9 @@ var getCodecSpecificatorFromEsdsBox = ({
2300
3645
  };
2301
3646
  }
2302
3647
  const audioSpecificConfig = descriptor.decoderSpecificConfigs.find((d) => {
2303
- return d.type === "audio-specific-config" ? d : null;
3648
+ return d.type === "mp4a-specific-config" ? d : null;
2304
3649
  });
2305
- if (!audioSpecificConfig || audioSpecificConfig.type !== "audio-specific-config") {
3650
+ if (!audioSpecificConfig || audioSpecificConfig.type !== "mp4a-specific-config") {
2306
3651
  throw new Error("No audio-specific-config");
2307
3652
  }
2308
3653
  return {
@@ -2311,6 +3656,29 @@ var getCodecSpecificatorFromEsdsBox = ({
2311
3656
  description: audioSpecificConfig.asBytes
2312
3657
  };
2313
3658
  };
3659
+ var getCodecPrivateFromTrak = (trakBox) => {
3660
+ const stsdBox = getStsdBox(trakBox);
3661
+ if (!stsdBox) {
3662
+ return null;
3663
+ }
3664
+ const audioSample = stsdBox.samples.find((s) => s.type === "audio");
3665
+ if (!audioSample || audioSample.type !== "audio") {
3666
+ return null;
3667
+ }
3668
+ const esds = audioSample.children.find((b) => b.type === "esds-box");
3669
+ if (!esds || esds.type !== "esds-box") {
3670
+ return null;
3671
+ }
3672
+ const decoderConfigDescriptor = esds.descriptors.find((d) => d.type === "decoder-config-descriptor");
3673
+ if (!decoderConfigDescriptor) {
3674
+ return null;
3675
+ }
3676
+ const mp4a = decoderConfigDescriptor.decoderSpecificConfigs.find((d) => d.type === "mp4a-specific-config");
3677
+ if (!mp4a) {
3678
+ return null;
3679
+ }
3680
+ return mp4a.asBytes;
3681
+ };
2314
3682
  var onSample = (sample, children) => {
2315
3683
  const child = children.find((c) => c.type === "esds-box");
2316
3684
  if (child && child.type === "esds-box") {
@@ -2651,18 +4019,11 @@ var getArrayBufferIterator = (initialData, maxBytes) => {
2651
4019
  getUint8(),
2652
4020
  getUint8(),
2653
4021
  getUint8(),
2654
- getUint8()
2655
- ]);
2656
- return Number(bigInt);
2657
- };
2658
- const getFourByteNumber = (littleEndian = false) => {
2659
- if (littleEndian) {
2660
- const one = getUint8();
2661
- const two = getUint8();
2662
- const three = getUint8();
2663
- const four = getUint8();
2664
- return four << 24 | three << 16 | two << 8 | one;
2665
- }
4022
+ getUint8()
4023
+ ]);
4024
+ return Number(bigInt);
4025
+ };
4026
+ const getFourByteNumber = () => {
2666
4027
  return getUint8() << 24 | getUint8() << 16 | getUint8() << 8 | getUint8();
2667
4028
  };
2668
4029
  const getPaddedFourByteNumber = () => {
@@ -3016,7 +4377,7 @@ var parseAv1PrivateData = (data, colrAtom) => {
3016
4377
  const chroma_sample_position = iterator.getBits(2);
3017
4378
  str += subsampling_x && subsampling_y ? chroma_sample_position === 1 ? "1" : "0" : "0";
3018
4379
  str += ".";
3019
- if (colrAtom) {
4380
+ if (colrAtom && colrAtom.colorType === "transfer-characteristics") {
3020
4381
  str += colrAtom.primaries.toString().padStart(2, "0");
3021
4382
  str += ".";
3022
4383
  str += colrAtom.transfer.toString().padStart(2, "0");
@@ -3125,11 +4486,7 @@ var getVideoCodec = (boxes) => {
3125
4486
  return null;
3126
4487
  };
3127
4488
  var hasVideoCodec = (boxes) => {
3128
- try {
3129
- return getVideoCodec(boxes) !== null;
3130
- } catch {
3131
- return false;
3132
- }
4489
+ return hasTracks(boxes);
3133
4490
  };
3134
4491
  var getVideoPrivateData = (trakBox) => {
3135
4492
  const videoSample = getStsdVideoConfig(trakBox);
@@ -3159,6 +4516,9 @@ var getIsoBmColrConfig = (trakBox) => {
3159
4516
  if (!colrAtom) {
3160
4517
  return null;
3161
4518
  }
4519
+ if (colrAtom.colorType !== "transfer-characteristics") {
4520
+ return null;
4521
+ }
3162
4522
  return {
3163
4523
  fullRange: colrAtom.fullRangeFlag,
3164
4524
  matrixCoefficients: colrAtom.matrixIndex === 1 ? "bt709" : colrAtom.matrixIndex === 5 ? "bt470bg" : colrAtom.matrixIndex === 6 ? "smpte170m" : null,
@@ -3217,7 +4577,7 @@ var makeBaseMediaTrack = (trakBox) => {
3217
4577
  sampleRate,
3218
4578
  description,
3219
4579
  trakBox,
3220
- codecPrivate: null,
4580
+ codecPrivate: getCodecPrivateFromTrak(trakBox),
3221
4581
  codecWithoutConfig: getAudioCodecFromTrack(trakBox)
3222
4582
  };
3223
4583
  }
@@ -3270,7 +4630,8 @@ var makeBaseMediaTrack = (trakBox) => {
3270
4630
  primaries: null,
3271
4631
  transferCharacteristics: null
3272
4632
  },
3273
- codecWithoutConfig: getVideoCodecFromIsoTrak(trakBox)
4633
+ codecWithoutConfig: getVideoCodecFromIsoTrak(trakBox),
4634
+ fps: getFpsFromMp4TrakBox(trakBox)
3274
4635
  };
3275
4636
  return track;
3276
4637
  };
@@ -3534,7 +4895,7 @@ var getMatroskaAudioCodecString = (track) => {
3534
4895
  throw new Error(`Unknown codec: ${codec.value}`);
3535
4896
  };
3536
4897
  var getTrack = ({
3537
- timescale,
4898
+ timescale: timescale2,
3538
4899
  track
3539
4900
  }) => {
3540
4901
  const trackType2 = getTrackTypeSegment(track);
@@ -3577,7 +4938,7 @@ var getTrack = ({
3577
4938
  numerator: 1,
3578
4939
  denominator: 1
3579
4940
  },
3580
- timescale,
4941
+ timescale: timescale2,
3581
4942
  codedHeight: height.value.value,
3582
4943
  codedWidth: width.value.value,
3583
4944
  displayAspectHeight: displayHeight2 ? displayHeight2.value.value : height.value.value,
@@ -3593,7 +4954,8 @@ var getTrack = ({
3593
4954
  },
3594
4955
  codecWithoutConfig: getMatroskaVideoCodecWithoutConfigString({
3595
4956
  codecSegment: codec
3596
- })
4957
+ }),
4958
+ fps: null
3597
4959
  };
3598
4960
  }
3599
4961
  if (trackTypeToString(trackType2.value.value) === "audio") {
@@ -3607,7 +4969,7 @@ var getTrack = ({
3607
4969
  type: "audio",
3608
4970
  trackId,
3609
4971
  codec: getMatroskaAudioCodecString(track),
3610
- timescale,
4972
+ timescale: timescale2,
3611
4973
  numberOfChannels,
3612
4974
  sampleRate,
3613
4975
  description: getAudioDescription(track),
@@ -3622,7 +4984,7 @@ var getTrack = ({
3622
4984
  };
3623
4985
 
3624
4986
  // src/boxes/webm/get-ready-tracks.ts
3625
- var getTracksFromMatroska = (segment, timescale) => {
4987
+ var getTracksFromMatroska = (segment, timescale2) => {
3626
4988
  const tracksSegment = getTracksSegment(segment);
3627
4989
  if (!tracksSegment) {
3628
4990
  throw new Error("No tracks segment");
@@ -3637,7 +4999,7 @@ var getTracksFromMatroska = (segment, timescale) => {
3637
4999
  }
3638
5000
  const track = getTrack({
3639
5001
  track: trackEntrySegment,
3640
- timescale
5002
+ timescale: timescale2
3641
5003
  });
3642
5004
  if (track) {
3643
5005
  tracks2.push(track);
@@ -3761,239 +5123,6 @@ var hasDimensions = (boxes, state) => {
3761
5123
  }
3762
5124
  };
3763
5125
 
3764
- // src/get-sample-positions.ts
3765
- var getSamplePositions = ({
3766
- stcoBox,
3767
- stszBox,
3768
- stscBox,
3769
- stssBox,
3770
- sttsBox,
3771
- cttsBox
3772
- }) => {
3773
- const sttsDeltas = [];
3774
- for (const distribution of sttsBox.sampleDistribution) {
3775
- for (let i = 0;i < distribution.sampleCount; i++) {
3776
- sttsDeltas.push(distribution.sampleDelta);
3777
- }
3778
- }
3779
- const cttsEntries = [];
3780
- for (const entry of cttsBox?.entries ?? [
3781
- { sampleCount: sttsDeltas.length, sampleOffset: 0 }
3782
- ]) {
3783
- for (let i = 0;i < entry.sampleCount; i++) {
3784
- cttsEntries.push(entry.sampleOffset);
3785
- }
3786
- }
3787
- let dts = 0;
3788
- const chunks = stcoBox.entries;
3789
- const samples = [];
3790
- let samplesPerChunk = 1;
3791
- for (let i = 0;i < chunks.length; i++) {
3792
- const hasEntry = stscBox.entries.find((entry) => entry.firstChunk === i + 1);
3793
- if (hasEntry) {
3794
- samplesPerChunk = hasEntry.samplesPerChunk;
3795
- }
3796
- let offsetInThisChunk = 0;
3797
- for (let j = 0;j < samplesPerChunk; j++) {
3798
- const size = stszBox.countType === "fixed" ? stszBox.sampleSize : stszBox.entries[samples.length];
3799
- const isKeyframe = stssBox ? stssBox.sampleNumber.includes(samples.length + 1) : true;
3800
- const delta = sttsDeltas[samples.length];
3801
- const ctsOffset = cttsEntries[samples.length];
3802
- const cts = dts + ctsOffset;
3803
- samples.push({
3804
- offset: Number(chunks[i]) + offsetInThisChunk,
3805
- size,
3806
- isKeyframe,
3807
- dts,
3808
- cts,
3809
- duration: delta
3810
- });
3811
- dts += delta;
3812
- offsetInThisChunk += size;
3813
- }
3814
- }
3815
- return samples;
3816
- };
3817
-
3818
- // src/samples-from-moof.ts
3819
- var getSamplesFromTraf = (trafSegment, moofOffset) => {
3820
- if (trafSegment.type !== "regular-box" || trafSegment.boxType !== "traf") {
3821
- throw new Error("Expected traf-box");
3822
- }
3823
- const tfhdBox = getTfhdBox(trafSegment);
3824
- const defaultSampleDuration = tfhdBox?.defaultSampleDuration ?? null;
3825
- const defaultSampleSize = tfhdBox?.defaultSampleSize ?? null;
3826
- const defaultSampleFlags = tfhdBox?.defaultSampleFlags ?? null;
3827
- const tfdtBox = getTfdtBox(trafSegment);
3828
- const trunBoxes = getTrunBoxes(trafSegment);
3829
- let time = 0;
3830
- let offset = 0;
3831
- let dataOffset = 0;
3832
- const samples = [];
3833
- for (const trunBox of trunBoxes) {
3834
- let i = -1;
3835
- if (trunBox.dataOffset) {
3836
- dataOffset = trunBox.dataOffset;
3837
- offset = 0;
3838
- }
3839
- for (const sample of trunBox.samples) {
3840
- i++;
3841
- const duration2 = sample.sampleDuration ?? defaultSampleDuration;
3842
- if (duration2 === null) {
3843
- throw new Error("Expected duration");
3844
- }
3845
- const size = sample.sampleSize ?? defaultSampleSize;
3846
- if (size === null) {
3847
- throw new Error("Expected size");
3848
- }
3849
- const isFirstSample = i === 0;
3850
- const sampleFlags = sample.sampleFlags ? sample.sampleFlags : isFirstSample && trunBox.firstSampleFlags !== null ? trunBox.firstSampleFlags : defaultSampleFlags;
3851
- if (sampleFlags === null) {
3852
- throw new Error("Expected sample flags");
3853
- }
3854
- const keyframe = !(sampleFlags >> 16 & 1);
3855
- const dts = time + (tfdtBox?.baseMediaDecodeTime ?? 0);
3856
- const samplePosition = {
3857
- offset: offset + (moofOffset ?? 0) + (dataOffset ?? 0),
3858
- dts,
3859
- cts: dts,
3860
- duration: duration2,
3861
- isKeyframe: keyframe,
3862
- size
3863
- };
3864
- samples.push(samplePosition);
3865
- offset += size;
3866
- time += duration2;
3867
- }
3868
- }
3869
- return samples;
3870
- };
3871
- var getSamplesFromMoof = ({
3872
- moofBox,
3873
- trackId
3874
- }) => {
3875
- if (moofBox.type !== "regular-box") {
3876
- throw new Error("Expected moof-box");
3877
- }
3878
- const trafs = moofBox.children.filter((c) => c.type === "regular-box" && c.boxType === "traf");
3879
- const mapped = trafs.map((traf) => {
3880
- const tfhdBox = getTfhdBox(traf);
3881
- return tfhdBox?.trackId === trackId ? getSamplesFromTraf(traf, moofBox.offset) : [];
3882
- });
3883
- return mapped.flat(1);
3884
- };
3885
-
3886
- // src/boxes/iso-base-media/get-sample-positions-from-track.ts
3887
- var getSamplePositionsFromTrack = (trakBox, moofBox) => {
3888
- const stszBox = getStszBox(trakBox);
3889
- const stcoBox = getStcoBox(trakBox);
3890
- const stscBox = getStscBox(trakBox);
3891
- const stssBox = getStssBox(trakBox);
3892
- const sttsBox = getSttsBox(trakBox);
3893
- const tkhdBox = getTkhdBox(trakBox);
3894
- const cttsBox = getCttsBox(trakBox);
3895
- const timescaleAndDuration = getTimescaleAndDuration(trakBox);
3896
- if (!tkhdBox) {
3897
- throw new Error("Expected tkhd box in trak box");
3898
- }
3899
- if (!stszBox) {
3900
- throw new Error("Expected stsz box in trak box");
3901
- }
3902
- if (!stcoBox) {
3903
- throw new Error("Expected stco box in trak box");
3904
- }
3905
- if (!stscBox) {
3906
- throw new Error("Expected stsc box in trak box");
3907
- }
3908
- if (!sttsBox) {
3909
- throw new Error("Expected stts box in trak box");
3910
- }
3911
- if (!timescaleAndDuration) {
3912
- throw new Error("Expected timescale and duration in trak box");
3913
- }
3914
- let samplePositions = getSamplePositions({
3915
- stcoBox,
3916
- stscBox,
3917
- stszBox,
3918
- stssBox,
3919
- sttsBox,
3920
- cttsBox
3921
- });
3922
- if (samplePositions.length === 0 && moofBox) {
3923
- samplePositions = getSamplesFromMoof({ moofBox, trackId: tkhdBox.trackId });
3924
- }
3925
- return samplePositions;
3926
- };
3927
-
3928
- // src/get-duration.ts
3929
- var getDurationFromMatroska = (segments) => {
3930
- const mainSegment = segments.find((s) => s.type === "Segment");
3931
- if (!mainSegment || mainSegment.type !== "Segment") {
3932
- return null;
3933
- }
3934
- const { value: children } = mainSegment;
3935
- if (!children) {
3936
- return null;
3937
- }
3938
- const infoSegment = children.find((s) => s.type === "Info");
3939
- const relevantBoxes = [
3940
- ...mainSegment.value,
3941
- ...infoSegment && infoSegment.type === "Info" ? infoSegment.value : []
3942
- ];
3943
- const timestampScale2 = relevantBoxes.find((s) => s.type === "TimestampScale");
3944
- if (!timestampScale2 || timestampScale2.type !== "TimestampScale") {
3945
- return null;
3946
- }
3947
- const duration2 = relevantBoxes.find((s) => s.type === "Duration");
3948
- if (!duration2 || duration2.type !== "Duration") {
3949
- return null;
3950
- }
3951
- return duration2.value.value / timestampScale2.value.value * 1000;
3952
- };
3953
- var getDuration = (boxes, parserState) => {
3954
- const matroskaBox = boxes.find((b) => b.type === "Segment");
3955
- if (matroskaBox) {
3956
- return getDurationFromMatroska(boxes);
3957
- }
3958
- const moovBox = getMoovBox(boxes);
3959
- if (!moovBox) {
3960
- return null;
3961
- }
3962
- const moofBox = getMoofBox(boxes);
3963
- const mvhdBox = getMvhdBox(moovBox);
3964
- if (!mvhdBox) {
3965
- return null;
3966
- }
3967
- if (mvhdBox.type !== "mvhd-box") {
3968
- throw new Error("Expected mvhd-box");
3969
- }
3970
- if (mvhdBox.durationInSeconds > 0) {
3971
- return mvhdBox.durationInSeconds;
3972
- }
3973
- const tracks2 = getTracks(boxes, parserState);
3974
- const allTracks = [
3975
- ...tracks2.videoTracks,
3976
- ...tracks2.audioTracks,
3977
- ...tracks2.otherTracks
3978
- ];
3979
- const allSamples = allTracks.map((t) => {
3980
- const { timescale: ts } = t;
3981
- const samplePositions = getSamplePositionsFromTrack(t.trakBox, moofBox);
3982
- const highest = samplePositions?.map((sp) => (sp.cts + sp.duration) / ts).reduce((a, b) => Math.max(a, b), 0);
3983
- return highest ?? 0;
3984
- });
3985
- const highestTimestamp = Math.max(...allSamples);
3986
- return highestTimestamp;
3987
- };
3988
- var hasDuration = (boxes, parserState) => {
3989
- try {
3990
- const duration2 = getDuration(boxes, parserState);
3991
- return getDuration(boxes, parserState) !== null && duration2 !== 0;
3992
- } catch {
3993
- return false;
3994
- }
3995
- };
3996
-
3997
5126
  // src/emit-available-info.ts
3998
5127
  var emitAvailableInfo = ({
3999
5128
  hasInfo,
@@ -4007,14 +5136,14 @@ var emitAvailableInfo = ({
4007
5136
  const keys = Object.keys(hasInfo);
4008
5137
  for (const key of keys) {
4009
5138
  if (key === "boxes") {
4010
- if (hasInfo.boxes && returnValue.boxes === undefined) {
5139
+ if (parseResult && hasInfo.boxes && returnValue.boxes === undefined) {
4011
5140
  moreFields.onBoxes?.(parseResult.segments);
4012
5141
  returnValue.boxes = parseResult.segments;
4013
5142
  }
4014
5143
  continue;
4015
5144
  }
4016
5145
  if (key === "durationInSeconds") {
4017
- if (hasInfo.durationInSeconds && returnValue.durationInSeconds === undefined) {
5146
+ if (hasInfo.durationInSeconds && returnValue.durationInSeconds === undefined && parseResult) {
4018
5147
  const durationInSeconds = getDuration(parseResult.segments, state);
4019
5148
  moreFields.onDurationInSeconds?.(durationInSeconds);
4020
5149
  returnValue.durationInSeconds = durationInSeconds;
@@ -4022,7 +5151,7 @@ var emitAvailableInfo = ({
4022
5151
  continue;
4023
5152
  }
4024
5153
  if (key === "dimensions") {
4025
- if (hasInfo.dimensions && returnValue.dimensions === undefined) {
5154
+ if (hasInfo.dimensions && returnValue.dimensions === undefined && parseResult) {
4026
5155
  const dimensionsQueried = getDimensions(parseResult.segments, state);
4027
5156
  const dimensions = {
4028
5157
  height: dimensionsQueried.height,
@@ -4034,7 +5163,7 @@ var emitAvailableInfo = ({
4034
5163
  continue;
4035
5164
  }
4036
5165
  if (key === "unrotatedDimensions") {
4037
- if (returnValue.unrotatedDimensions === undefined && hasInfo.unrotatedDimensions) {
5166
+ if (returnValue.unrotatedDimensions === undefined && hasInfo.unrotatedDimensions && parseResult) {
4038
5167
  const dimensionsQueried = getDimensions(parseResult.segments, state);
4039
5168
  const unrotatedDimensions = {
4040
5169
  height: dimensionsQueried.unrotatedHeight,
@@ -4046,7 +5175,7 @@ var emitAvailableInfo = ({
4046
5175
  continue;
4047
5176
  }
4048
5177
  if (key === "rotation") {
4049
- if (returnValue.rotation === undefined && hasInfo.rotation) {
5178
+ if (returnValue.rotation === undefined && hasInfo.rotation && parseResult) {
4050
5179
  const dimensionsQueried = getDimensions(parseResult.segments, state);
4051
5180
  const { rotation } = dimensionsQueried;
4052
5181
  moreFields.onRotation?.(rotation);
@@ -4055,7 +5184,7 @@ var emitAvailableInfo = ({
4055
5184
  continue;
4056
5185
  }
4057
5186
  if (key === "fps") {
4058
- if (returnValue.fps === undefined && hasInfo.fps) {
5187
+ if (returnValue.fps === undefined && hasInfo.fps && parseResult) {
4059
5188
  const fps = getFps(parseResult.segments);
4060
5189
  moreFields.onFps?.(fps);
4061
5190
  returnValue.fps = fps;
@@ -4063,7 +5192,7 @@ var emitAvailableInfo = ({
4063
5192
  continue;
4064
5193
  }
4065
5194
  if (key === "videoCodec") {
4066
- if (returnValue.videoCodec === undefined && hasInfo.videoCodec) {
5195
+ if (returnValue.videoCodec === undefined && hasInfo.videoCodec && parseResult) {
4067
5196
  const videoCodec = getVideoCodec(parseResult.segments);
4068
5197
  moreFields.onVideoCodec?.(videoCodec);
4069
5198
  returnValue.videoCodec = videoCodec;
@@ -4071,7 +5200,7 @@ var emitAvailableInfo = ({
4071
5200
  continue;
4072
5201
  }
4073
5202
  if (key === "audioCodec") {
4074
- if (returnValue.audioCodec === undefined && hasInfo.audioCodec) {
5203
+ if (returnValue.audioCodec === undefined && hasInfo.audioCodec && parseResult) {
4075
5204
  const audioCodec = getAudioCodec(parseResult.segments, state);
4076
5205
  moreFields.onAudioCodec?.(audioCodec);
4077
5206
  returnValue.audioCodec = audioCodec;
@@ -4079,7 +5208,7 @@ var emitAvailableInfo = ({
4079
5208
  continue;
4080
5209
  }
4081
5210
  if (key === "tracks") {
4082
- if (hasInfo.tracks && returnValue.videoTracks === undefined && returnValue.audioTracks === undefined) {
5211
+ if (hasInfo.tracks && returnValue.videoTracks === undefined && returnValue.audioTracks === undefined && parseResult) {
4083
5212
  const { videoTracks, audioTracks } = getTracks(parseResult.segments, state);
4084
5213
  moreFields.onTracks?.({ videoTracks, audioTracks });
4085
5214
  returnValue.videoTracks = videoTracks;
@@ -4110,7 +5239,7 @@ var emitAvailableInfo = ({
4110
5239
  continue;
4111
5240
  }
4112
5241
  if (key === "container") {
4113
- if (returnValue.container === undefined && hasInfo.container) {
5242
+ if (returnValue.container === undefined && hasInfo.container && parseResult) {
4114
5243
  const container = getContainer(parseResult.segments);
4115
5244
  moreFields.onContainer?.(container);
4116
5245
  returnValue.container = container;
@@ -4126,25 +5255,25 @@ var getAvailableInfo = (options, parseResult, state) => {
4126
5255
  const keys = Object.entries(options).filter(([, value]) => value);
4127
5256
  const infos = keys.map(([key]) => {
4128
5257
  if (key === "boxes") {
4129
- return parseResult.status === "done";
5258
+ return Boolean(parseResult && parseResult.status === "done");
4130
5259
  }
4131
5260
  if (key === "durationInSeconds") {
4132
- return hasDuration(parseResult.segments, state);
5261
+ return Boolean(parseResult && hasDuration(parseResult.segments, state));
4133
5262
  }
4134
5263
  if (key === "dimensions" || key === "rotation" || key === "unrotatedDimensions") {
4135
- return hasDimensions(parseResult.segments, state);
5264
+ return Boolean(parseResult && hasDimensions(parseResult.segments, state));
4136
5265
  }
4137
5266
  if (key === "fps") {
4138
- return hasFps(parseResult.segments);
5267
+ return Boolean(parseResult && hasFps(parseResult.segments));
4139
5268
  }
4140
5269
  if (key === "videoCodec") {
4141
- return hasVideoCodec(parseResult.segments);
5270
+ return Boolean(parseResult && hasVideoCodec(parseResult.segments));
4142
5271
  }
4143
5272
  if (key === "audioCodec") {
4144
- return hasAudioCodec(parseResult.segments, state);
5273
+ return Boolean(parseResult && hasAudioCodec(parseResult.segments));
4145
5274
  }
4146
5275
  if (key === "tracks") {
4147
- return hasTracks(parseResult.segments);
5276
+ return Boolean(parseResult && hasTracks(parseResult.segments));
4148
5277
  }
4149
5278
  if (key === "internalStats") {
4150
5279
  return false;
@@ -4156,7 +5285,7 @@ var getAvailableInfo = (options, parseResult, state) => {
4156
5285
  return true;
4157
5286
  }
4158
5287
  if (key === "container") {
4159
- return hasContainer(parseResult.segments);
5288
+ return Boolean(parseResult && hasContainer(parseResult.segments));
4160
5289
  }
4161
5290
  throw new Error(`Unknown key: ${key}`);
4162
5291
  });
@@ -4169,7 +5298,7 @@ var getAvailableInfo = (options, parseResult, state) => {
4169
5298
  };
4170
5299
 
4171
5300
  // src/boxes/iso-base-media/esds/decoder-specific-config.ts
4172
- var parseDecoderSpecificConfig = (iterator) => {
5301
+ var parseDecoderSpecificConfig = (iterator, logLevel) => {
4173
5302
  const layerTag = iterator.getUint8();
4174
5303
  const layerSize = iterator.getPaddedFourByteNumber();
4175
5304
  const start = iterator.counter.getOffset();
@@ -4193,13 +5322,15 @@ var parseDecoderSpecificConfig = (iterator) => {
4193
5322
  if (read < layerSize) {
4194
5323
  iterator.discard(layerSize - read);
4195
5324
  }
4196
- const patchedAsBytes = bytes.byteLength === 2 && bytes[0] === 17 && bytes[1] === 136 ? new Uint8Array([17, 144]) : bytes;
5325
+ if (bytes.byteLength === 2 && bytes[0] === 17 && bytes[1] === 136) {
5326
+ 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");
5327
+ }
4197
5328
  return {
4198
- type: "audio-specific-config",
5329
+ type: "mp4a-specific-config",
4199
5330
  audioObjectType,
4200
5331
  samplingFrequencyIndex,
4201
5332
  channelConfiguration,
4202
- asBytes: patchedAsBytes
5333
+ asBytes: bytes
4203
5334
  };
4204
5335
  };
4205
5336
 
@@ -4214,7 +5345,8 @@ var mapToObjectAudioIndicator = (num) => {
4214
5345
  return "unknown";
4215
5346
  };
4216
5347
  var processDescriptor = ({
4217
- iterator
5348
+ iterator,
5349
+ logLevel
4218
5350
  }) => {
4219
5351
  const tag = iterator.getUint8();
4220
5352
  if (tag === 4) {
@@ -4230,8 +5362,8 @@ var processDescriptor = ({
4230
5362
  const maxBitrate = iterator.getUint32();
4231
5363
  const avgBitrate = iterator.getUint32();
4232
5364
  const decoderSpecificConfigs = [];
4233
- while (size - (iterator.counter.getOffset() - initialOffset) >= 0) {
4234
- const decoderSpecificConfig = parseDecoderSpecificConfig(iterator);
5365
+ while (size - (iterator.counter.getOffset() - initialOffset) > 0) {
5366
+ const decoderSpecificConfig = parseDecoderSpecificConfig(iterator, logLevel);
4235
5367
  decoderSpecificConfigs.push(decoderSpecificConfig);
4236
5368
  }
4237
5369
  return {
@@ -4261,12 +5393,13 @@ var processDescriptor = ({
4261
5393
  descriptor: null
4262
5394
  };
4263
5395
  };
4264
- var parseDescriptors = (iterator, maxBytes) => {
5396
+ var parseDescriptors = (iterator, maxBytes, logLevel) => {
4265
5397
  const descriptors = [];
4266
5398
  const initialOffset = iterator.counter.getOffset();
4267
5399
  while (iterator.bytesRemaining() > 0 && iterator.counter.getOffset() - initialOffset < maxBytes) {
4268
5400
  const { descriptor } = processDescriptor({
4269
- iterator
5401
+ iterator,
5402
+ logLevel
4270
5403
  });
4271
5404
  if (descriptor) {
4272
5405
  descriptors.push(descriptor);
@@ -4281,7 +5414,8 @@ var parseDescriptors = (iterator, maxBytes) => {
4281
5414
  var parseEsds = ({
4282
5415
  data,
4283
5416
  size,
4284
- fileOffset
5417
+ fileOffset,
5418
+ logLevel
4285
5419
  }) => {
4286
5420
  const version = data.getUint8();
4287
5421
  data.discard(3);
@@ -4290,7 +5424,7 @@ var parseEsds = ({
4290
5424
  const esId = data.getUint16();
4291
5425
  data.discard(1);
4292
5426
  const remaining = size - (data.counter.getOffset() - fileOffset);
4293
- const descriptors = parseDescriptors(data, remaining);
5427
+ const descriptors = parseDescriptors(data, remaining, logLevel);
4294
5428
  const remainingNow = size - (data.counter.getOffset() - fileOffset);
4295
5429
  data.discard(remainingNow);
4296
5430
  return {
@@ -4397,15 +5531,19 @@ var parseMdat = async ({
4397
5531
  break;
4398
5532
  }
4399
5533
  const bytes = data.getSlice(samplesWithIndex.samplePosition.size);
4400
- const timestamp = Math.floor(samplesWithIndex.samplePosition.cts * 1e6 / samplesWithIndex.track.timescale);
4401
- const duration2 = Math.floor(samplesWithIndex.samplePosition.duration * 1e6 / samplesWithIndex.track.timescale);
5534
+ const timestamp = samplesWithIndex.samplePosition.cts * 1e6 / samplesWithIndex.track.timescale;
5535
+ const duration2 = samplesWithIndex.samplePosition.duration * 1e6 / samplesWithIndex.track.timescale;
5536
+ const cts = samplesWithIndex.samplePosition.cts * 1e6 / samplesWithIndex.track.timescale;
5537
+ const dts = samplesWithIndex.samplePosition.dts * 1e6 / samplesWithIndex.track.timescale;
4402
5538
  if (samplesWithIndex.track.type === "audio") {
4403
5539
  await options.parserState.onAudioSample(samplesWithIndex.track.trackId, {
4404
5540
  data: bytes,
4405
5541
  timestamp,
5542
+ duration: duration2,
5543
+ cts,
5544
+ dts,
4406
5545
  trackId: samplesWithIndex.track.trackId,
4407
- type: samplesWithIndex.samplePosition.isKeyframe ? "key" : "delta",
4408
- duration: duration2
5546
+ type: samplesWithIndex.samplePosition.isKeyframe ? "key" : "delta"
4409
5547
  });
4410
5548
  }
4411
5549
  if (samplesWithIndex.track.type === "video") {
@@ -4413,8 +5551,8 @@ var parseMdat = async ({
4413
5551
  data: bytes,
4414
5552
  timestamp,
4415
5553
  duration: duration2,
4416
- cts: samplesWithIndex.samplePosition.cts,
4417
- dts: samplesWithIndex.samplePosition.dts,
5554
+ cts,
5555
+ dts,
4418
5556
  trackId: samplesWithIndex.track.trackId,
4419
5557
  type: samplesWithIndex.samplePosition.isKeyframe ? "key" : "delta"
4420
5558
  });
@@ -4443,7 +5581,7 @@ var parseMdhd = ({
4443
5581
  data.discard(3);
4444
5582
  const creationTime = version === 1 ? Number(data.getUint64()) : data.getUint32();
4445
5583
  const modificationTime = version === 1 ? Number(data.getUint64()) : data.getUint32();
4446
- const timescale = data.getUint32();
5584
+ const timescale2 = data.getUint32();
4447
5585
  const duration2 = version === 1 ? data.getUint64() : data.getUint32();
4448
5586
  const language2 = data.getUint16();
4449
5587
  const quality = data.getUint16();
@@ -4454,7 +5592,7 @@ var parseMdhd = ({
4454
5592
  return {
4455
5593
  type: "mdhd-box",
4456
5594
  duration: Number(duration2),
4457
- timescale,
5595
+ timescale: timescale2,
4458
5596
  version,
4459
5597
  language: language2,
4460
5598
  quality,
@@ -4469,7 +5607,8 @@ var parseMoov = async ({
4469
5607
  offset,
4470
5608
  size,
4471
5609
  options,
4472
- signal
5610
+ signal,
5611
+ logLevel
4473
5612
  }) => {
4474
5613
  const children = await parseBoxes({
4475
5614
  iterator,
@@ -4478,8 +5617,8 @@ var parseMoov = async ({
4478
5617
  initialBoxes: [],
4479
5618
  options,
4480
5619
  continueMdat: false,
4481
- littleEndian: false,
4482
- signal
5620
+ signal,
5621
+ logLevel
4483
5622
  });
4484
5623
  if (children.status === "incomplete") {
4485
5624
  throw new Error("Incomplete boxes are not allowed");
@@ -4492,15 +5631,6 @@ var parseMoov = async ({
4492
5631
  };
4493
5632
  };
4494
5633
 
4495
- // src/boxes/iso-base-media/to-date.ts
4496
- var toUnixTimestamp = (value) => {
4497
- if (value === 0) {
4498
- return null;
4499
- }
4500
- const baseDate = new Date("1904-01-01T00:00:00Z");
4501
- return Math.floor(value + baseDate.getTime() / 1000) * 1000;
4502
- };
4503
-
4504
5634
  // src/boxes/iso-base-media/mvhd.ts
4505
5635
  var parseMvhd = ({
4506
5636
  iterator,
@@ -4523,14 +5653,17 @@ var parseMvhd = ({
4523
5653
  iterator.discard(2);
4524
5654
  iterator.discard(4);
4525
5655
  iterator.discard(4);
4526
- const matrix = [];
4527
- for (let i = 0;i < 9; i++) {
4528
- if (i % 3 === 2) {
4529
- matrix.push(iterator.getFixedPointSigned230Number());
4530
- } else {
4531
- matrix.push(iterator.getFixedPointSigned1616Number());
4532
- }
4533
- }
5656
+ const matrix = [
5657
+ iterator.getFixedPointSigned1616Number(),
5658
+ iterator.getFixedPointSigned1616Number(),
5659
+ iterator.getFixedPointSigned230Number(),
5660
+ iterator.getFixedPointSigned1616Number(),
5661
+ iterator.getFixedPointSigned1616Number(),
5662
+ iterator.getFixedPointSigned230Number(),
5663
+ iterator.getFixedPointSigned1616Number(),
5664
+ iterator.getFixedPointSigned1616Number(),
5665
+ iterator.getFixedPointSigned230Number()
5666
+ ];
4534
5667
  iterator.discard(4 * 6);
4535
5668
  const nextTrackId = iterator.getUint32();
4536
5669
  volumeView.destroy();
@@ -4587,9 +5720,115 @@ var parseAvcc = ({
4587
5720
  };
4588
5721
  };
4589
5722
 
5723
+ // src/boxes/iso-base-media/parse-icc-profile.ts
5724
+ var parseIccProfile = (data) => {
5725
+ const iterator = getArrayBufferIterator(data, Infinity);
5726
+ const size = iterator.getUint32();
5727
+ if (size !== data.length) {
5728
+ throw new Error("Invalid ICC profile size");
5729
+ }
5730
+ const preferredCMMType = iterator.getByteString(4);
5731
+ const profileVersion = iterator.getByteString(4);
5732
+ const profileDeviceClass = iterator.getByteString(4);
5733
+ const colorSpace = iterator.getByteString(4);
5734
+ const pcs = iterator.getByteString(4);
5735
+ const dateTime = iterator.getSlice(12);
5736
+ const signature = iterator.getByteString(4);
5737
+ if (signature !== "acsp") {
5738
+ throw new Error("Invalid ICC profile signature");
5739
+ }
5740
+ const primaryPlatform = iterator.getByteString(4);
5741
+ const profileFlags = iterator.getUint32();
5742
+ const deviceManufacturer = iterator.getByteString(4);
5743
+ const deviceModel = iterator.getByteString(4);
5744
+ const deviceAttributes = iterator.getUint64();
5745
+ const renderingIntent = iterator.getUint32();
5746
+ const pcsIlluminant1 = iterator.getUint32();
5747
+ const pcsIlluminant2 = iterator.getUint32();
5748
+ const pcsIlluminant3 = iterator.getUint32();
5749
+ const profileCreator = iterator.getByteString(4);
5750
+ const profileId = iterator.getByteString(16);
5751
+ iterator.discard(28);
5752
+ const tagCount = iterator.getUint32();
5753
+ const entries = [];
5754
+ for (let i = 0;i < tagCount; i++) {
5755
+ const entry = {
5756
+ tag: iterator.getByteString(4),
5757
+ offset: iterator.getUint32(),
5758
+ size: iterator.getUint32()
5759
+ };
5760
+ entries.push(entry);
5761
+ }
5762
+ let lastOffset = -1;
5763
+ let rXYZ = null;
5764
+ let gXYZ = null;
5765
+ let bXYZ = null;
5766
+ let whitePoint = null;
5767
+ for (const entry of entries) {
5768
+ const found = data.slice(entry.offset, entry.offset + entry.size);
5769
+ if (entry.tag === "rXYZ" || entry.tag === "gXYZ" || entry.tag === "bXYZ" || entry.tag === "wtpt") {
5770
+ const it = getArrayBufferIterator(found, Infinity);
5771
+ it.discard(4);
5772
+ const x = it.getInt32() / 65536;
5773
+ const y = it.getInt32() / 65536;
5774
+ const z = it.getInt32() / 65536;
5775
+ it.destroy();
5776
+ const point = { x, y, z };
5777
+ if (entry.tag === "rXYZ") {
5778
+ rXYZ = point;
5779
+ } else if (entry.tag === "gXYZ") {
5780
+ gXYZ = point;
5781
+ } else if (entry.tag === "bXYZ") {
5782
+ bXYZ = point;
5783
+ } else if (entry.tag === "wtpt") {
5784
+ whitePoint = point;
5785
+ }
5786
+ }
5787
+ if (lastOffset !== -1) {
5788
+ const bytesToAdvance = entry.offset - lastOffset;
5789
+ const bytesToGoBackwards = entry.size - bytesToAdvance;
5790
+ if (bytesToGoBackwards > 0) {
5791
+ iterator.counter.decrement(bytesToGoBackwards);
5792
+ }
5793
+ }
5794
+ lastOffset = entry.offset;
5795
+ }
5796
+ const profile = {
5797
+ size,
5798
+ preferredCMMType,
5799
+ profileVersion,
5800
+ profileDeviceClass,
5801
+ colorSpace,
5802
+ pcs,
5803
+ dateTime,
5804
+ signature,
5805
+ primaryPlatform,
5806
+ profileFlags,
5807
+ deviceManufacturer,
5808
+ deviceModel,
5809
+ deviceAttributes,
5810
+ renderingIntent,
5811
+ pcsIlluminant: [
5812
+ pcsIlluminant1 / 65536,
5813
+ pcsIlluminant2 / 65536,
5814
+ pcsIlluminant3 / 65536
5815
+ ],
5816
+ profileCreator,
5817
+ profileId,
5818
+ entries,
5819
+ bXYZ,
5820
+ gXYZ,
5821
+ rXYZ,
5822
+ whitePoint
5823
+ };
5824
+ iterator.destroy();
5825
+ return profile;
5826
+ };
5827
+
4590
5828
  // src/boxes/iso-base-media/stsd/colr.ts
4591
5829
  var parseColorParameterBox = ({
4592
- iterator
5830
+ iterator,
5831
+ size
4593
5832
  }) => {
4594
5833
  const byteString = iterator.getByteString(4);
4595
5834
  if (byteString === "nclx") {
@@ -4601,6 +5840,7 @@ var parseColorParameterBox = ({
4601
5840
  iterator.stopReadingBits();
4602
5841
  return {
4603
5842
  type: "colr-box",
5843
+ colorType: "transfer-characteristics",
4604
5844
  fullRangeFlag,
4605
5845
  matrixIndex,
4606
5846
  primaries: primaries2,
@@ -4613,12 +5853,22 @@ var parseColorParameterBox = ({
4613
5853
  const matrixIndex = iterator.getUint16();
4614
5854
  return {
4615
5855
  type: "colr-box",
5856
+ colorType: "transfer-characteristics",
4616
5857
  fullRangeFlag: false,
4617
5858
  matrixIndex,
4618
5859
  primaries: primaries2,
4619
5860
  transfer
4620
5861
  };
4621
5862
  }
5863
+ if (byteString === "prof") {
5864
+ const profile = iterator.getSlice(size - 12);
5865
+ return {
5866
+ type: "colr-box",
5867
+ colorType: "icc-profile",
5868
+ profile,
5869
+ parsed: parseIccProfile(profile)
5870
+ };
5871
+ }
4622
5872
  throw new Error("Unexpected box type " + byteString);
4623
5873
  };
4624
5874
 
@@ -4678,7 +5928,6 @@ var parseMebx = async ({
4678
5928
  offset,
4679
5929
  size,
4680
5930
  options,
4681
- littleEndian,
4682
5931
  signal
4683
5932
  }) => {
4684
5933
  iterator.discard(6);
@@ -4690,8 +5939,8 @@ var parseMebx = async ({
4690
5939
  initialBoxes: [],
4691
5940
  options,
4692
5941
  continueMdat: false,
4693
- littleEndian,
4694
- signal
5942
+ signal,
5943
+ logLevel: "info"
4695
5944
  });
4696
5945
  if (children.status === "incomplete") {
4697
5946
  throw new Error("Incomplete boxes are not allowed");
@@ -4855,7 +6104,8 @@ var audioTags = [
4855
6104
  var processSample = async ({
4856
6105
  iterator,
4857
6106
  options,
4858
- signal
6107
+ signal,
6108
+ logLevel
4859
6109
  }) => {
4860
6110
  const fileOffset = iterator.counter.getOffset();
4861
6111
  const bytesRemaining = iterator.bytesRemaining();
@@ -4899,8 +6149,8 @@ var processSample = async ({
4899
6149
  initialBoxes: [],
4900
6150
  options,
4901
6151
  continueMdat: false,
4902
- littleEndian: false,
4903
- signal
6152
+ signal,
6153
+ logLevel
4904
6154
  });
4905
6155
  if (children.status === "incomplete") {
4906
6156
  throw new Error("Incomplete boxes are not allowed");
@@ -4946,8 +6196,8 @@ var processSample = async ({
4946
6196
  initialBoxes: [],
4947
6197
  options,
4948
6198
  continueMdat: false,
4949
- littleEndian: false,
4950
- signal
6199
+ signal,
6200
+ logLevel
4951
6201
  });
4952
6202
  if (children.status === "incomplete") {
4953
6203
  throw new Error("Incomplete boxes are not allowed");
@@ -4997,8 +6247,8 @@ var processSample = async ({
4997
6247
  initialBoxes: [],
4998
6248
  options,
4999
6249
  continueMdat: false,
5000
- littleEndian: false,
5001
- signal
6250
+ signal,
6251
+ logLevel
5002
6252
  });
5003
6253
  if (children.status === "incomplete") {
5004
6254
  throw new Error("Incomplete boxes are not allowed");
@@ -5051,8 +6301,8 @@ var processSample = async ({
5051
6301
  initialBoxes: [],
5052
6302
  options,
5053
6303
  continueMdat: false,
5054
- littleEndian: false,
5055
- signal
6304
+ signal,
6305
+ logLevel
5056
6306
  }) : (iterator.discard(bytesRemainingInBox), { status: "done", segments: [] });
5057
6307
  if (children.status === "incomplete") {
5058
6308
  throw new Error("Incomplete boxes are not allowed");
@@ -5088,7 +6338,8 @@ var parseSamples = async ({
5088
6338
  iterator,
5089
6339
  maxBytes,
5090
6340
  options,
5091
- signal
6341
+ signal,
6342
+ logLevel
5092
6343
  }) => {
5093
6344
  const samples = [];
5094
6345
  const initialOffset = iterator.counter.getOffset();
@@ -5096,7 +6347,8 @@ var parseSamples = async ({
5096
6347
  const { sample } = await processSample({
5097
6348
  iterator,
5098
6349
  options,
5099
- signal
6350
+ signal,
6351
+ logLevel
5100
6352
  });
5101
6353
  if (sample) {
5102
6354
  samples.push(sample);
@@ -5124,7 +6376,8 @@ var parseStsd = async ({
5124
6376
  iterator,
5125
6377
  maxBytes: bytesRemainingInBox,
5126
6378
  options,
5127
- signal
6379
+ signal,
6380
+ logLevel: "info"
5128
6381
  });
5129
6382
  if (boxes.length !== numberOfEntries) {
5130
6383
  throw new Error(`Expected ${numberOfEntries} sample descriptions, got ${boxes.length}`);
@@ -5394,7 +6647,8 @@ var parseTrak = async ({
5394
6647
  size,
5395
6648
  offsetAtStart,
5396
6649
  options,
5397
- signal
6650
+ signal,
6651
+ logLevel
5398
6652
  }) => {
5399
6653
  const children = await parseBoxes({
5400
6654
  iterator: data,
@@ -5403,8 +6657,8 @@ var parseTrak = async ({
5403
6657
  initialBoxes: [],
5404
6658
  options,
5405
6659
  continueMdat: false,
5406
- littleEndian: false,
5407
- signal
6660
+ signal,
6661
+ logLevel
5408
6662
  });
5409
6663
  if (children.status === "incomplete") {
5410
6664
  throw new Error("Incomplete boxes are not allowed");
@@ -5465,8 +6719,8 @@ var getChildren = async ({
5465
6719
  iterator,
5466
6720
  bytesRemainingInBox,
5467
6721
  options,
5468
- littleEndian,
5469
- signal
6722
+ signal,
6723
+ logLevel
5470
6724
  }) => {
5471
6725
  const parseChildren = boxType === "mdia" || boxType === "minf" || boxType === "stbl" || boxType === "moof" || boxType === "dims" || boxType === "wave" || boxType === "traf" || boxType === "stsb";
5472
6726
  if (parseChildren) {
@@ -5477,8 +6731,8 @@ var getChildren = async ({
5477
6731
  initialBoxes: [],
5478
6732
  options,
5479
6733
  continueMdat: false,
5480
- littleEndian,
5481
- signal
6734
+ signal,
6735
+ logLevel
5482
6736
  });
5483
6737
  if (parsed.status === "incomplete") {
5484
6738
  throw new Error("Incomplete boxes are not allowed");
@@ -5527,12 +6781,12 @@ var processBox = async ({
5527
6781
  allowIncompleteBoxes,
5528
6782
  parsedBoxes,
5529
6783
  options,
5530
- littleEndian,
5531
- signal
6784
+ signal,
6785
+ logLevel
5532
6786
  }) => {
5533
6787
  const fileOffset = iterator.counter.getOffset();
5534
6788
  const bytesRemaining = iterator.bytesRemaining();
5535
- const boxSizeRaw = iterator.getFourByteNumber(littleEndian);
6789
+ const boxSizeRaw = iterator.getFourByteNumber();
5536
6790
  if (boxSizeRaw === 1 && iterator.bytesRemaining() < 12 || iterator.bytesRemaining() < 4) {
5537
6791
  iterator.counter.decrement(iterator.counter.getOffset() - fileOffset);
5538
6792
  if (allowIncompleteBoxes) {
@@ -5554,7 +6808,7 @@ var processBox = async ({
5554
6808
  };
5555
6809
  }
5556
6810
  const boxType = iterator.getByteString(4);
5557
- const boxSize = boxSizeRaw === 1 ? iterator.getEightByteNumber(littleEndian) : boxSizeRaw;
6811
+ const boxSize = boxSizeRaw === 1 ? iterator.getEightByteNumber() : boxSizeRaw;
5558
6812
  if (bytesRemaining < boxSize) {
5559
6813
  if (boxType === "mdat") {
5560
6814
  const shouldSkip = (options.canSkipVideoData || !hasTracks(parsedBoxes)) && options.supportsContentRange;
@@ -5604,7 +6858,8 @@ var processBox = async ({
5604
6858
  }
5605
6859
  if (boxType === "colr") {
5606
6860
  const box = parseColorParameterBox({
5607
- iterator
6861
+ iterator,
6862
+ size: boxSize
5608
6863
  });
5609
6864
  return {
5610
6865
  type: "complete",
@@ -5749,7 +7004,6 @@ var processBox = async ({
5749
7004
  offset: fileOffset,
5750
7005
  size: boxSize,
5751
7006
  options,
5752
- littleEndian,
5753
7007
  signal
5754
7008
  });
5755
7009
  return {
@@ -5765,7 +7019,8 @@ var processBox = async ({
5765
7019
  offset: fileOffset,
5766
7020
  size: boxSize,
5767
7021
  options,
5768
- signal
7022
+ signal,
7023
+ logLevel
5769
7024
  });
5770
7025
  return {
5771
7026
  type: "complete",
@@ -5780,7 +7035,8 @@ var processBox = async ({
5780
7035
  size: boxSize,
5781
7036
  offsetAtStart: fileOffset,
5782
7037
  options,
5783
- signal
7038
+ signal,
7039
+ logLevel
5784
7040
  });
5785
7041
  const transformedTrack = makeBaseMediaTrack(box);
5786
7042
  if (transformedTrack) {
@@ -5880,7 +7136,8 @@ var processBox = async ({
5880
7136
  const box = parseEsds({
5881
7137
  data: iterator,
5882
7138
  size: boxSize,
5883
- fileOffset
7139
+ fileOffset,
7140
+ logLevel
5884
7141
  });
5885
7142
  return {
5886
7143
  type: "complete",
@@ -5915,8 +7172,8 @@ var processBox = async ({
5915
7172
  iterator,
5916
7173
  bytesRemainingInBox,
5917
7174
  options,
5918
- littleEndian,
5919
- signal
7175
+ signal,
7176
+ logLevel
5920
7177
  });
5921
7178
  return {
5922
7179
  type: "complete",
@@ -5938,8 +7195,8 @@ var parseBoxes = async ({
5938
7195
  initialBoxes,
5939
7196
  options,
5940
7197
  continueMdat,
5941
- littleEndian,
5942
- signal
7198
+ signal,
7199
+ logLevel
5943
7200
  }) => {
5944
7201
  let boxes = initialBoxes;
5945
7202
  const initialOffset = iterator.counter.getOffset();
@@ -5957,8 +7214,8 @@ var parseBoxes = async ({
5957
7214
  allowIncompleteBoxes,
5958
7215
  parsedBoxes: initialBoxes,
5959
7216
  options,
5960
- littleEndian,
5961
- signal
7217
+ signal,
7218
+ logLevel
5962
7219
  });
5963
7220
  if (result.type === "incomplete") {
5964
7221
  if (Number.isFinite(maxBytes)) {
@@ -5975,8 +7232,8 @@ var parseBoxes = async ({
5975
7232
  initialBoxes: boxes,
5976
7233
  options,
5977
7234
  continueMdat: false,
5978
- littleEndian,
5979
- signal
7235
+ signal,
7236
+ logLevel
5980
7237
  });
5981
7238
  },
5982
7239
  skipTo: null
@@ -5994,8 +7251,8 @@ var parseBoxes = async ({
5994
7251
  initialBoxes: boxes,
5995
7252
  options,
5996
7253
  continueMdat: result,
5997
- littleEndian,
5998
- signal
7254
+ signal,
7255
+ logLevel
5999
7256
  }));
6000
7257
  },
6001
7258
  skipTo: null
@@ -6027,8 +7284,8 @@ var parseBoxes = async ({
6027
7284
  initialBoxes: boxes,
6028
7285
  options,
6029
7286
  continueMdat: false,
6030
- littleEndian,
6031
- signal
7287
+ signal,
7288
+ logLevel
6032
7289
  });
6033
7290
  },
6034
7291
  skipTo: result.skipTo
@@ -6046,8 +7303,8 @@ var parseBoxes = async ({
6046
7303
  initialBoxes: boxes,
6047
7304
  options,
6048
7305
  continueMdat: false,
6049
- littleEndian,
6050
- signal
7306
+ signal,
7307
+ logLevel
6051
7308
  });
6052
7309
  },
6053
7310
  skipTo: null
@@ -6073,8 +7330,8 @@ var parseBoxes = async ({
6073
7330
  initialBoxes: boxes,
6074
7331
  options,
6075
7332
  continueMdat: false,
6076
- littleEndian,
6077
- signal
7333
+ signal,
7334
+ logLevel
6078
7335
  });
6079
7336
  },
6080
7337
  skipTo: skipped ? mdatState.fileOffset : null
@@ -6145,11 +7402,11 @@ var getSampleFromBlock = (ebml, parserContext, offset) => {
6145
7402
  const { keyframe } = parseBlockFlags(iterator, ebml.type === "SimpleBlock" ? matroskaElements.SimpleBlock : matroskaElements.Block);
6146
7403
  const { codec, trackTimescale } = parserContext.parserState.getTrackInfoByNumber(trackNumber2);
6147
7404
  const clusterOffset = parserContext.parserState.getTimestampOffsetForByteOffset(offset);
6148
- const timescale = parserContext.parserState.getTimescale();
7405
+ const timescale2 = parserContext.parserState.getTimescale();
6149
7406
  if (clusterOffset === undefined) {
6150
7407
  throw new Error("Could not find offset for byte offset " + offset);
6151
7408
  }
6152
- const timecodeInNanoSeconds = (timecodeRelativeToCluster + clusterOffset) * timescale * (trackTimescale ?? 1);
7409
+ const timecodeInNanoSeconds = (timecodeRelativeToCluster + clusterOffset) * timescale2 * (trackTimescale ?? 1);
6153
7410
  const timecodeInMicroseconds = timecodeInNanoSeconds / 1000;
6154
7411
  if (!codec) {
6155
7412
  throw new Error(`Could not find codec for track ${trackNumber2}`);
@@ -6158,8 +7415,8 @@ var getSampleFromBlock = (ebml, parserContext, offset) => {
6158
7415
  if (codec.startsWith("V_")) {
6159
7416
  const partialVideoSample = {
6160
7417
  data: iterator.getSlice(remainingNow),
6161
- cts: null,
6162
- dts: null,
7418
+ cts: timecodeInMicroseconds,
7419
+ dts: timecodeInMicroseconds,
6163
7420
  duration: undefined,
6164
7421
  trackId: trackNumber2,
6165
7422
  timestamp: timecodeInMicroseconds
@@ -6187,7 +7444,9 @@ var getSampleFromBlock = (ebml, parserContext, offset) => {
6187
7444
  trackId: trackNumber2,
6188
7445
  timestamp: timecodeInMicroseconds,
6189
7446
  type: "key",
6190
- duration: undefined
7447
+ duration: undefined,
7448
+ cts: timecodeInMicroseconds,
7449
+ dts: timecodeInMicroseconds
6191
7450
  };
6192
7451
  iterator.destroy();
6193
7452
  return {
@@ -6367,32 +7626,54 @@ var postprocessEbml = async ({
6367
7626
  };
6368
7627
 
6369
7628
  // src/boxes/webm/segments.ts
6370
- var parseSegment = async ({
6371
- segmentId,
7629
+ var continueAfterMatroskaParseResult = async ({
7630
+ result,
6372
7631
  iterator,
6373
- length,
6374
7632
  parserContext,
6375
- headerReadSoFar
7633
+ segment
6376
7634
  }) => {
6377
- if (length < 0) {
6378
- throw new Error(`Expected length of ${segmentId} to be greater or equal 0`);
7635
+ if (result.status === "done") {
7636
+ throw new Error("Should not continue after done");
6379
7637
  }
6380
- iterator.counter.decrement(headerReadSoFar);
6381
- const offset = iterator.counter.getOffset();
6382
- const ebml = await parseEbml(iterator, parserContext);
6383
- const remapped = await postprocessEbml({ offset, ebml, parserContext });
6384
- return remapped;
7638
+ const proceeded = await result.continueParsing();
7639
+ if (proceeded.status === "done") {
7640
+ return {
7641
+ status: "done",
7642
+ segment
7643
+ };
7644
+ }
7645
+ return {
7646
+ continueParsing() {
7647
+ return continueAfterMatroskaParseResult({
7648
+ result: proceeded,
7649
+ iterator,
7650
+ parserContext,
7651
+ segment
7652
+ });
7653
+ },
7654
+ segment: null,
7655
+ status: "incomplete"
7656
+ };
6385
7657
  };
6386
- var expectSegment = async (iterator, parserContext) => {
6387
- const offset = iterator.counter.getOffset();
7658
+ var expectSegment = async ({
7659
+ iterator,
7660
+ parserContext,
7661
+ offset,
7662
+ children
7663
+ }) => {
7664
+ iterator.counter.decrement(iterator.counter.getOffset() - offset);
6388
7665
  if (iterator.bytesRemaining() === 0) {
6389
7666
  return {
6390
7667
  status: "incomplete",
6391
- segments: [],
6392
7668
  continueParsing: () => {
6393
- return Promise.resolve(expectSegment(iterator, parserContext));
7669
+ return expectAndProcessSegment({
7670
+ iterator,
7671
+ parserContext,
7672
+ offset,
7673
+ children
7674
+ });
6394
7675
  },
6395
- skipTo: null
7676
+ segment: null
6396
7677
  };
6397
7678
  }
6398
7679
  const segmentId = iterator.getMatroskaSegmentId();
@@ -6400,11 +7681,15 @@ var expectSegment = async (iterator, parserContext) => {
6400
7681
  iterator.counter.decrement(iterator.counter.getOffset() - offset);
6401
7682
  return {
6402
7683
  status: "incomplete",
6403
- segments: [],
6404
7684
  continueParsing: () => {
6405
- return Promise.resolve(expectSegment(iterator, parserContext));
7685
+ return expectAndProcessSegment({
7686
+ iterator,
7687
+ parserContext,
7688
+ offset,
7689
+ children
7690
+ });
6406
7691
  },
6407
- skipTo: null
7692
+ segment: null
6408
7693
  };
6409
7694
  }
6410
7695
  const offsetBeforeVInt = iterator.counter.getOffset();
@@ -6414,41 +7699,43 @@ var expectSegment = async (iterator, parserContext) => {
6414
7699
  iterator.counter.decrement(iterator.counter.getOffset() - offset);
6415
7700
  return {
6416
7701
  status: "incomplete",
6417
- segments: [],
6418
7702
  continueParsing: () => {
6419
- return Promise.resolve(expectSegment(iterator, parserContext));
7703
+ return expectSegment({ iterator, parserContext, offset, children });
6420
7704
  },
6421
- skipTo: null
7705
+ segment: null
6422
7706
  };
6423
7707
  }
6424
7708
  const bytesRemainingNow = iterator.byteLength() - iterator.counter.getOffset();
6425
7709
  if (segmentId === "0x18538067" || segmentId === "0x1f43b675") {
7710
+ const newSegment = {
7711
+ type: segmentId === "0x18538067" ? "Segment" : "Cluster",
7712
+ minVintWidth: offsetAfterVInt - offsetBeforeVInt,
7713
+ value: []
7714
+ };
6426
7715
  const main = await expectChildren({
6427
7716
  iterator,
6428
7717
  length,
6429
- initialChildren: [],
6430
- wrap: segmentId === "0x18538067" ? (s) => ({
6431
- type: "Segment",
6432
- value: s,
6433
- minVintWidth: offsetAfterVInt - offsetBeforeVInt
6434
- }) : (s) => ({
6435
- type: "Cluster",
6436
- value: s,
6437
- minVintWidth: offsetAfterVInt - offsetBeforeVInt
6438
- }),
6439
- parserContext
7718
+ children: newSegment.value,
7719
+ parserContext,
7720
+ startOffset: iterator.counter.getOffset()
6440
7721
  });
6441
7722
  if (main.status === "incomplete") {
6442
7723
  return {
6443
7724
  status: "incomplete",
6444
- segments: main.segments,
6445
- skipTo: null,
6446
- continueParsing: main.continueParsing
7725
+ continueParsing: () => {
7726
+ return continueAfterMatroskaParseResult({
7727
+ iterator,
7728
+ parserContext,
7729
+ result: main,
7730
+ segment: newSegment
7731
+ });
7732
+ },
7733
+ segment: newSegment
6447
7734
  };
6448
7735
  }
6449
7736
  return {
6450
7737
  status: "done",
6451
- segments: main.segments
7738
+ segment: newSegment
6452
7739
  };
6453
7740
  }
6454
7741
  if (bytesRemainingNow < length) {
@@ -6456,11 +7743,10 @@ var expectSegment = async (iterator, parserContext) => {
6456
7743
  iterator.counter.decrement(bytesRead);
6457
7744
  return {
6458
7745
  status: "incomplete",
6459
- segments: [],
7746
+ segment: null,
6460
7747
  continueParsing: () => {
6461
- return Promise.resolve(expectSegment(iterator, parserContext));
6462
- },
6463
- skipTo: null
7748
+ return expectSegment({ iterator, parserContext, offset, children });
7749
+ }
6464
7750
  };
6465
7751
  }
6466
7752
  const segment = await parseSegment({
@@ -6472,138 +7758,187 @@ var expectSegment = async (iterator, parserContext) => {
6472
7758
  });
6473
7759
  return {
6474
7760
  status: "done",
6475
- segments: [segment]
7761
+ segment
6476
7762
  };
6477
7763
  };
7764
+ var parseSegment = async ({
7765
+ segmentId,
7766
+ iterator,
7767
+ length,
7768
+ parserContext,
7769
+ headerReadSoFar
7770
+ }) => {
7771
+ if (length < 0) {
7772
+ throw new Error(`Expected length of ${segmentId} to be greater or equal 0`);
7773
+ }
7774
+ iterator.counter.decrement(headerReadSoFar);
7775
+ const offset = iterator.counter.getOffset();
7776
+ const ebml = await parseEbml(iterator, parserContext);
7777
+ const remapped = await postprocessEbml({ offset, ebml, parserContext });
7778
+ return remapped;
7779
+ };
6478
7780
 
6479
7781
  // src/boxes/webm/segments/parse-children.ts
6480
7782
  var processParseResult = ({
6481
7783
  parseResult,
6482
- children,
6483
- wrap
7784
+ children
6484
7785
  }) => {
7786
+ if (parseResult.segment && !children.includes(parseResult.segment)) {
7787
+ children.push(parseResult.segment);
7788
+ }
6485
7789
  if (parseResult.status === "incomplete") {
6486
7790
  return {
6487
7791
  status: "incomplete",
6488
- segments: [],
7792
+ segment: parseResult.segment,
6489
7793
  continueParsing: async () => {
6490
7794
  const newParseResult = await parseResult.continueParsing();
6491
7795
  return processParseResult({
6492
7796
  children,
6493
- parseResult: newParseResult,
6494
- wrap
7797
+ parseResult: newParseResult
6495
7798
  });
6496
- },
6497
- skipTo: null
7799
+ }
6498
7800
  };
6499
7801
  }
6500
- for (const segment of parseResult.segments) {
6501
- children.push(segment);
6502
- }
6503
7802
  return {
6504
7803
  status: "done",
6505
- segments: wrap ? [wrap(children)] : children
7804
+ segment: parseResult.segment
6506
7805
  };
6507
7806
  };
6508
- var continueParsingfunction = ({
6509
- result,
7807
+ var expectAndProcessSegment = async ({
6510
7808
  iterator,
7809
+ parserContext,
7810
+ offset,
7811
+ children
7812
+ }) => {
7813
+ const segment = await expectSegment({
7814
+ iterator,
7815
+ parserContext,
7816
+ offset,
7817
+ children
7818
+ });
7819
+ return processParseResult({
7820
+ children,
7821
+ parseResult: segment
7822
+ });
7823
+ };
7824
+ var continueAfterSegmentResult = async ({
7825
+ result,
7826
+ length,
6511
7827
  children,
6512
- wrap,
6513
7828
  parserContext,
6514
- length
6515
- }) => async () => {
6516
- if (result.status !== "incomplete") {
6517
- throw new Error("expected incomplete");
7829
+ iterator,
7830
+ startOffset
7831
+ }) => {
7832
+ if (result.status === "done") {
7833
+ throw new Error("Should not continue after done");
6518
7834
  }
6519
- const offset = iterator.counter.getOffset();
6520
- const continued = await result.continueParsing();
6521
- if (continued.status === "incomplete") {
6522
- if (!parserContext.supportsContentRange) {
6523
- throw new Error("Content-Range header is not supported by the reader, but was asked to seek");
6524
- }
7835
+ const segmentResult = await result.continueParsing();
7836
+ if (segmentResult.status === "done") {
6525
7837
  return {
6526
7838
  status: "incomplete",
6527
- continueParsing: continueParsingfunction({
6528
- result: continued,
6529
- iterator,
6530
- children,
6531
- wrap,
6532
- parserContext,
6533
- length: length - (iterator.counter.getOffset() - offset)
6534
- }),
6535
- skipTo: continued.skipTo,
6536
- segments: wrap ? [wrap(children)] : children
7839
+ continueParsing: () => {
7840
+ return expectChildren({
7841
+ children,
7842
+ iterator,
7843
+ length,
7844
+ parserContext,
7845
+ startOffset
7846
+ });
7847
+ },
7848
+ skipTo: null
6537
7849
  };
6538
7850
  }
6539
- return expectChildren({
6540
- iterator,
6541
- length: length - (iterator.counter.getOffset() - offset),
6542
- initialChildren: children,
6543
- wrap,
6544
- parserContext
6545
- });
7851
+ return {
7852
+ status: "incomplete",
7853
+ continueParsing: () => {
7854
+ return continueAfterSegmentResult({
7855
+ result: segmentResult,
7856
+ children,
7857
+ iterator,
7858
+ length,
7859
+ parserContext,
7860
+ startOffset
7861
+ });
7862
+ },
7863
+ skipTo: null
7864
+ };
6546
7865
  };
6547
7866
  var expectChildren = async ({
6548
7867
  iterator,
6549
7868
  length,
6550
- initialChildren,
6551
- wrap,
6552
- parserContext
7869
+ children,
7870
+ parserContext,
7871
+ startOffset
6553
7872
  }) => {
6554
- const children = [...initialChildren];
6555
- const startOffset = iterator.counter.getOffset();
6556
7873
  while (iterator.counter.getOffset() < startOffset + length) {
6557
7874
  if (iterator.bytesRemaining() === 0) {
6558
7875
  break;
6559
7876
  }
6560
- const parseResult = await expectSegment(iterator, parserContext);
6561
- const child = processParseResult({
6562
- children,
6563
- parseResult,
6564
- wrap
7877
+ const currentOffset = iterator.counter.getOffset();
7878
+ const child = await expectAndProcessSegment({
7879
+ iterator,
7880
+ parserContext,
7881
+ offset: currentOffset,
7882
+ children
6565
7883
  });
6566
7884
  if (child.status === "incomplete") {
6567
- if (!parserContext.supportsContentRange) {
6568
- throw new Error("Content-Range header is not supported by the reader, but was asked to seek");
6569
- }
6570
7885
  return {
6571
7886
  status: "incomplete",
6572
- continueParsing: continueParsingfunction({
6573
- result: child,
6574
- iterator,
6575
- children,
6576
- wrap,
6577
- parserContext,
6578
- length: length - (iterator.counter.getOffset() - startOffset)
6579
- }),
6580
- skipTo: child.skipTo,
6581
- segments: wrap ? [wrap(children)] : children
7887
+ continueParsing: () => {
7888
+ return continueAfterSegmentResult({
7889
+ result: child,
7890
+ children,
7891
+ iterator,
7892
+ length: length - (currentOffset - startOffset),
7893
+ parserContext,
7894
+ startOffset: currentOffset
7895
+ });
7896
+ },
7897
+ skipTo: null
6582
7898
  };
6583
7899
  }
6584
7900
  }
6585
7901
  return {
6586
- status: "done",
6587
- segments: wrap ? [wrap(children)] : children
7902
+ status: "done"
6588
7903
  };
6589
7904
  };
6590
7905
 
6591
7906
  // src/boxes/webm/parse-webm-header.ts
6592
- var parseWebm = (counter, parserContext) => {
6593
- return expectChildren({
7907
+ var continueAfterMatroskaResult = (result, children) => {
7908
+ if (result.status === "done") {
7909
+ return {
7910
+ status: "done",
7911
+ segments: children
7912
+ };
7913
+ }
7914
+ return {
7915
+ status: "incomplete",
7916
+ segments: children,
7917
+ continueParsing: async () => {
7918
+ const newResult = await result.continueParsing();
7919
+ return continueAfterMatroskaResult(newResult, children);
7920
+ },
7921
+ skipTo: null
7922
+ };
7923
+ };
7924
+ var parseWebm = async (counter, parserContext) => {
7925
+ const children = [];
7926
+ const results = await expectChildren({
6594
7927
  iterator: counter,
6595
7928
  length: Infinity,
6596
- initialChildren: [],
6597
- wrap: null,
6598
- parserContext
7929
+ children,
7930
+ parserContext,
7931
+ startOffset: counter.counter.getOffset()
6599
7932
  });
7933
+ return continueAfterMatroskaResult(results, children);
6600
7934
  };
6601
7935
 
6602
7936
  // src/parse-video.ts
6603
7937
  var parseVideo = ({
6604
7938
  iterator,
6605
7939
  options,
6606
- signal
7940
+ signal,
7941
+ logLevel
6607
7942
  }) => {
6608
7943
  if (iterator.bytesRemaining() === 0) {
6609
7944
  return Promise.resolve({
@@ -6613,7 +7948,8 @@ var parseVideo = ({
6613
7948
  return parseVideo({
6614
7949
  iterator,
6615
7950
  options,
6616
- signal
7951
+ signal,
7952
+ logLevel
6617
7953
  });
6618
7954
  },
6619
7955
  skipTo: null
@@ -6623,6 +7959,7 @@ var parseVideo = ({
6623
7959
  throw new Error("AVI files are not yet supported");
6624
7960
  }
6625
7961
  if (iterator.isIsoBaseMedia()) {
7962
+ Log.verbose(logLevel, "Detected ISO Base Media container");
6626
7963
  return parseBoxes({
6627
7964
  iterator,
6628
7965
  maxBytes: Infinity,
@@ -6630,11 +7967,12 @@ var parseVideo = ({
6630
7967
  initialBoxes: [],
6631
7968
  options,
6632
7969
  continueMdat: false,
6633
- littleEndian: false,
6634
- signal
7970
+ signal,
7971
+ logLevel
6635
7972
  });
6636
7973
  }
6637
7974
  if (iterator.isWebm()) {
7975
+ Log.verbose(logLevel, "Detected Matroska container");
6638
7976
  return Promise.resolve(parseWebm(iterator, options));
6639
7977
  }
6640
7978
  if (iterator.isMp3()) {
@@ -6673,15 +8011,15 @@ var makeParserState = ({
6673
8011
  const queuedAudioSamples = {};
6674
8012
  const queuedVideoSamples = {};
6675
8013
  const declinedTrackNumbers = [];
6676
- let timescale = null;
8014
+ let timescale2 = null;
6677
8015
  const getTimescale = () => {
6678
- if (timescale === null) {
8016
+ if (timescale2 === null) {
6679
8017
  return 1e6;
6680
8018
  }
6681
- return timescale;
8019
+ return timescale2;
6682
8020
  };
6683
8021
  const setTimescale = (newTimescale) => {
6684
- timescale = newTimescale;
8022
+ timescale2 = newTimescale;
6685
8023
  };
6686
8024
  const timestampMap = new Map;
6687
8025
  const setTimestampOffset = (byteOffset, timestamp) => {
@@ -6775,6 +8113,8 @@ var parseMedia = async ({
6775
8113
  onAudioTrack,
6776
8114
  onVideoTrack,
6777
8115
  signal,
8116
+ logLevel = "info",
8117
+ onParseProgress,
6778
8118
  ...more
6779
8119
  }) => {
6780
8120
  const state = makeParserState({
@@ -6794,14 +8134,40 @@ var parseMedia = async ({
6794
8134
  const moreFields = more;
6795
8135
  let iterator = null;
6796
8136
  let parseResult = null;
8137
+ const canSkipVideoData = !onVideoTrack && !onAudioTrack;
8138
+ if (canSkipVideoData) {
8139
+ Log.verbose(logLevel, "Only parsing metadata, because no onVideoTrack and onAudioTrack callbacks were passed.");
8140
+ } else {
8141
+ Log.verbose(logLevel, "Parsing video data, because onVideoTrack/onAudioTrack callbacks were passed.");
8142
+ }
6797
8143
  const options = {
6798
- canSkipVideoData: !(onAudioTrack || onVideoTrack),
8144
+ canSkipVideoData,
6799
8145
  onAudioTrack: onAudioTrack ?? null,
6800
8146
  onVideoTrack: onVideoTrack ?? null,
6801
8147
  parserState: state,
6802
8148
  nullifySamples: !(typeof process !== "undefined" && typeof process.env !== "undefined" && process.env.KEEP_SAMPLES === "true"),
6803
8149
  supportsContentRange
6804
8150
  };
8151
+ const hasAllInfo = () => {
8152
+ if (parseResult === null) {
8153
+ return false;
8154
+ }
8155
+ const availableInfo = getAvailableInfo(fields ?? {}, parseResult, state);
8156
+ return Object.values(availableInfo).every(Boolean);
8157
+ };
8158
+ const triggerInfoEmit = () => {
8159
+ const availableInfo = getAvailableInfo(fields ?? {}, parseResult, state);
8160
+ emitAvailableInfo({
8161
+ hasInfo: availableInfo,
8162
+ moreFields,
8163
+ parseResult,
8164
+ state,
8165
+ returnValue,
8166
+ contentLength,
8167
+ name
8168
+ });
8169
+ };
8170
+ triggerInfoEmit();
6805
8171
  while (parseResult === null || parseResult.status === "incomplete") {
6806
8172
  if (signal?.aborted) {
6807
8173
  throw new Error("Aborted");
@@ -6828,27 +8194,24 @@ var parseMedia = async ({
6828
8194
  if (!iterator) {
6829
8195
  throw new Error("Unexpected null");
6830
8196
  }
8197
+ await onParseProgress?.({
8198
+ bytes: iterator.counter.getOffset(),
8199
+ percentage: contentLength ? iterator.counter.getOffset() / contentLength : null,
8200
+ totalBytes: contentLength
8201
+ });
8202
+ triggerInfoEmit();
6831
8203
  if (parseResult && parseResult.status === "incomplete") {
8204
+ Log.verbose(logLevel, "Continuing parsing of file, currently at position", iterator.counter.getOffset(), getAvailableInfo(fields ?? {}, parseResult, state));
6832
8205
  parseResult = await parseResult.continueParsing();
6833
8206
  } else {
6834
8207
  parseResult = await parseVideo({
6835
8208
  iterator,
6836
8209
  options,
6837
- signal: signal ?? null
8210
+ signal: signal ?? null,
8211
+ logLevel
6838
8212
  });
6839
8213
  }
6840
- const availableInfo = getAvailableInfo(fields ?? {}, parseResult, state);
6841
- const hasAllInfo = Object.values(availableInfo).every(Boolean);
6842
- emitAvailableInfo({
6843
- hasInfo: availableInfo,
6844
- moreFields,
6845
- parseResult,
6846
- state,
6847
- returnValue,
6848
- contentLength,
6849
- name
6850
- });
6851
- if (hasAllInfo && !onVideoTrack && !onAudioTrack) {
8214
+ if (hasAllInfo() && !onVideoTrack && !onAudioTrack) {
6852
8215
  break;
6853
8216
  }
6854
8217
  if (parseResult && parseResult.status === "incomplete" && parseResult.skipTo !== null) {
@@ -6861,6 +8224,7 @@ var parseMedia = async ({
6861
8224
  iterator.skipTo(parseResult.skipTo, true);
6862
8225
  }
6863
8226
  }
8227
+ Log.verbose(logLevel, "Finished parsing file");
6864
8228
  emitAvailableInfo({
6865
8229
  hasInfo: Object.keys(fields ?? {}).reduce((acc, key) => {
6866
8230
  acc[key] = true;
@@ -6877,12 +8241,17 @@ var parseMedia = async ({
6877
8241
  iterator?.destroy();
6878
8242
  return returnValue;
6879
8243
  };
8244
+ // src/version.ts
8245
+ var VERSION = "4.0.231";
8246
+
6880
8247
  // src/index.ts
6881
8248
  var MediaParserInternals = {
6882
- createMedia,
8249
+ createMatroskaMedia,
8250
+ createIsoBaseMedia,
6883
8251
  Log
6884
8252
  };
6885
8253
  export {
6886
8254
  parseMedia,
8255
+ VERSION,
6887
8256
  MediaParserInternals
6888
8257
  };