@remotion/media-parser 4.0.194 → 4.0.196

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 (275) hide show
  1. package/dist/add-new-matroska-tracks.d.ts +8 -0
  2. package/dist/add-new-matroska-tracks.js +14 -0
  3. package/dist/av1-codec-string.d.ts +3 -0
  4. package/dist/av1-codec-string.js +91 -0
  5. package/dist/boxes/iso-base-media/esds/decoder-specific-config.d.ts +14 -0
  6. package/dist/boxes/iso-base-media/esds/decoder-specific-config.js +38 -0
  7. package/dist/boxes/iso-base-media/esds/esds-descriptors.d.ts +8 -0
  8. package/dist/boxes/iso-base-media/esds/esds-descriptors.js +22 -2
  9. package/dist/boxes/iso-base-media/ftype.d.ts +9 -0
  10. package/dist/boxes/iso-base-media/ftype.js +31 -0
  11. package/dist/boxes/iso-base-media/make-track.d.ts +3 -0
  12. package/dist/boxes/iso-base-media/make-track.js +112 -0
  13. package/dist/boxes/iso-base-media/mdat/mdat.d.ts +6 -2
  14. package/dist/boxes/iso-base-media/mdat/mdat.js +90 -6
  15. package/dist/boxes/iso-base-media/moov/moov.d.ts +4 -2
  16. package/dist/boxes/iso-base-media/moov/moov.js +4 -2
  17. package/dist/boxes/iso-base-media/mvhd.js +7 -1
  18. package/dist/boxes/iso-base-media/process-box.d.ts +20 -3
  19. package/dist/boxes/iso-base-media/process-box.js +322 -34
  20. package/dist/boxes/iso-base-media/stsd/av1c.d.ts +9 -0
  21. package/dist/boxes/iso-base-media/stsd/av1c.js +10 -0
  22. package/dist/boxes/iso-base-media/stsd/avcc-hvcc.d.ts +20 -0
  23. package/dist/boxes/iso-base-media/stsd/avcc-hvcc.js +73 -0
  24. package/dist/boxes/iso-base-media/stsd/avcc.d.ts +10 -0
  25. package/dist/boxes/iso-base-media/stsd/avcc.js +21 -0
  26. package/dist/boxes/iso-base-media/stsd/colr.d.ts +11 -0
  27. package/dist/boxes/iso-base-media/stsd/colr.js +35 -0
  28. package/dist/boxes/iso-base-media/stsd/ctts.d.ts +19 -0
  29. package/dist/boxes/iso-base-media/stsd/ctts.js +30 -0
  30. package/dist/boxes/iso-base-media/stsd/hvcc.d.ts +11 -0
  31. package/dist/boxes/iso-base-media/stsd/hvcc.js +17 -0
  32. package/dist/boxes/iso-base-media/stsd/keys.js +1 -0
  33. package/dist/boxes/iso-base-media/stsd/mebx.d.ts +4 -2
  34. package/dist/boxes/iso-base-media/stsd/mebx.js +4 -2
  35. package/dist/boxes/iso-base-media/stsd/pasp.d.ts +12 -0
  36. package/dist/boxes/iso-base-media/stsd/pasp.js +17 -0
  37. package/dist/boxes/iso-base-media/stsd/samples.d.ts +12 -5
  38. package/dist/boxes/iso-base-media/stsd/samples.js +27 -10
  39. package/dist/boxes/iso-base-media/stsd/stsd.d.ts +4 -2
  40. package/dist/boxes/iso-base-media/stsd/stsd.js +6 -2
  41. package/dist/boxes/iso-base-media/stsd/stss.d.ts +13 -0
  42. package/dist/boxes/iso-base-media/stsd/stss.js +28 -0
  43. package/dist/boxes/iso-base-media/stsd/stsz.d.ts +9 -3
  44. package/dist/boxes/iso-base-media/stsd/stsz.js +14 -2
  45. package/dist/boxes/iso-base-media/stsd/stts.d.ts +15 -0
  46. package/dist/boxes/iso-base-media/stsd/stts.js +35 -0
  47. package/dist/boxes/iso-base-media/tkhd.d.ts +3 -0
  48. package/dist/boxes/iso-base-media/tkhd.js +41 -14
  49. package/dist/boxes/iso-base-media/trak/trak.d.ts +4 -2
  50. package/dist/boxes/iso-base-media/trak/trak.js +4 -2
  51. package/dist/boxes/iso-base-media/void-box.d.ts +4 -0
  52. package/dist/boxes/iso-base-media/void-box.js +2 -0
  53. package/dist/boxes/webm/allowed-partial-segments.d.ts +1 -0
  54. package/dist/boxes/webm/allowed-partial-segments.js +4 -0
  55. package/dist/boxes/webm/av1-codec-private.d.ts +2 -0
  56. package/dist/boxes/webm/av1-codec-private.js +95 -0
  57. package/dist/boxes/webm/bitstream/av1/bitstream-frame-header.d.ts +14 -0
  58. package/dist/boxes/webm/bitstream/av1/bitstream-frame-header.js +67 -0
  59. package/dist/boxes/webm/bitstream/av1/bitstream-frame.d.ts +11 -0
  60. package/dist/boxes/webm/bitstream/av1/bitstream-frame.js +14 -0
  61. package/dist/boxes/webm/bitstream/av1/chroma-sample-position.d.ts +6 -0
  62. package/dist/boxes/webm/bitstream/av1/chroma-sample-position.js +9 -0
  63. package/dist/boxes/webm/bitstream/av1/color-config.d.ts +16 -0
  64. package/dist/boxes/webm/bitstream/av1/color-config.js +103 -0
  65. package/dist/boxes/webm/bitstream/av1/color-primaries.d.ts +14 -0
  66. package/dist/boxes/webm/bitstream/av1/color-primaries.js +17 -0
  67. package/dist/boxes/webm/bitstream/av1/decoder-model-info.d.ts +9 -0
  68. package/dist/boxes/webm/bitstream/av1/decoder-model-info.js +17 -0
  69. package/dist/boxes/webm/bitstream/av1/header-segment.d.ts +51 -0
  70. package/dist/boxes/webm/bitstream/av1/header-segment.js +183 -0
  71. package/dist/boxes/webm/bitstream/av1/matrix-coefficients.d.ts +17 -0
  72. package/dist/boxes/webm/bitstream/av1/matrix-coefficients.js +20 -0
  73. package/dist/boxes/webm/bitstream/av1/operating-parameters-info.d.ts +10 -0
  74. package/dist/boxes/webm/bitstream/av1/operating-parameters-info.js +15 -0
  75. package/dist/boxes/webm/bitstream/av1/temporal-point-info.d.ts +5 -0
  76. package/dist/boxes/webm/bitstream/av1/temporal-point-info.js +8 -0
  77. package/dist/boxes/webm/bitstream/av1/timing-info.d.ts +8 -0
  78. package/dist/boxes/webm/bitstream/av1/timing-info.js +20 -0
  79. package/dist/boxes/webm/bitstream/av1/transfer-characteristics.d.ts +21 -0
  80. package/dist/boxes/webm/bitstream/av1/transfer-characteristics.js +24 -0
  81. package/dist/boxes/webm/bitstream/av1/uvlc.d.ts +2 -0
  82. package/dist/boxes/webm/bitstream/av1/uvlc.js +20 -0
  83. package/dist/boxes/webm/bitstream/av1.d.ts +20 -0
  84. package/dist/boxes/webm/bitstream/av1.js +118 -0
  85. package/dist/boxes/webm/bitstream/h264/get-h264-descriptor.d.ts +0 -0
  86. package/dist/boxes/webm/bitstream/h264/get-h264-descriptor.js +1 -0
  87. package/dist/boxes/webm/description.d.ts +2 -0
  88. package/dist/boxes/webm/description.js +83 -0
  89. package/dist/boxes/webm/get-ready-tracks.d.ts +3 -0
  90. package/dist/boxes/webm/get-ready-tracks.js +29 -0
  91. package/dist/boxes/webm/get-track.d.ts +6 -0
  92. package/dist/boxes/webm/get-track.js +183 -0
  93. package/dist/boxes/webm/parse-webm-header.d.ts +2 -1
  94. package/dist/boxes/webm/parse-webm-header.js +2 -2
  95. package/dist/boxes/webm/segments/all-segments.d.ts +269 -0
  96. package/dist/boxes/webm/segments/all-segments.js +277 -0
  97. package/dist/boxes/webm/segments/duration.d.ts +1 -1
  98. package/dist/boxes/webm/segments/duration.js +13 -9
  99. package/dist/boxes/webm/segments/info.d.ts +2 -1
  100. package/dist/boxes/webm/segments/info.js +12 -4
  101. package/dist/boxes/webm/segments/main.d.ts +0 -2
  102. package/dist/boxes/webm/segments/main.js +0 -11
  103. package/dist/boxes/webm/segments/muxing.d.ts +1 -1
  104. package/dist/boxes/webm/segments/muxing.js +1 -2
  105. package/dist/boxes/webm/segments/parse-children.d.ts +11 -1
  106. package/dist/boxes/webm/segments/parse-children.js +82 -6
  107. package/dist/boxes/webm/segments/seek-head.d.ts +2 -1
  108. package/dist/boxes/webm/segments/seek-head.js +12 -3
  109. package/dist/boxes/webm/segments/seek-position.d.ts +1 -1
  110. package/dist/boxes/webm/segments/seek-position.js +1 -2
  111. package/dist/boxes/webm/segments/seek.d.ts +7 -2
  112. package/dist/boxes/webm/segments/seek.js +22 -9
  113. package/dist/boxes/webm/segments/track-entry.d.ts +102 -22
  114. package/dist/boxes/webm/segments/track-entry.js +269 -57
  115. package/dist/boxes/webm/segments/tracks.d.ts +2 -1
  116. package/dist/boxes/webm/segments/tracks.js +12 -4
  117. package/dist/boxes/webm/segments/void.d.ts +1 -1
  118. package/dist/boxes/webm/segments/void.js +1 -2
  119. package/dist/boxes/webm/segments/writing.d.ts +1 -1
  120. package/dist/boxes/webm/segments/writing.js +1 -2
  121. package/dist/boxes/webm/segments.d.ts +8 -4
  122. package/dist/boxes/webm/segments.js +176 -40
  123. package/dist/boxes/webm/traversal.d.ts +7 -0
  124. package/dist/boxes/webm/traversal.js +25 -0
  125. package/dist/buffer-iterator.d.ts +15 -1
  126. package/dist/buffer-iterator.js +115 -46
  127. package/dist/combine-uint8array.d.ts +1 -0
  128. package/dist/combine-uint8array.js +13 -0
  129. package/dist/from-fetch.d.ts +2 -0
  130. package/dist/from-fetch.js +54 -0
  131. package/dist/from-node.js +6 -0
  132. package/dist/from-web-file.d.ts +2 -0
  133. package/dist/from-web-file.js +34 -0
  134. package/dist/from-web.js +6 -9
  135. package/dist/get-audio-codec.d.ts +19 -0
  136. package/dist/get-audio-codec.js +153 -60
  137. package/dist/get-dimensions.d.ts +8 -2
  138. package/dist/get-dimensions.js +13 -91
  139. package/dist/get-duration.js +4 -7
  140. package/dist/get-fps.d.ts +4 -3
  141. package/dist/get-fps.js +17 -116
  142. package/dist/get-sample-aspect-ratio.d.ts +37 -0
  143. package/dist/get-sample-aspect-ratio.js +137 -0
  144. package/dist/get-sample-positions.d.ts +11 -1
  145. package/dist/get-sample-positions.js +31 -2
  146. package/dist/get-tracks.d.ts +44 -5
  147. package/dist/get-tracks.js +66 -48
  148. package/dist/get-video-codec.d.ts +2 -0
  149. package/dist/get-video-codec.js +47 -31
  150. package/dist/get-video-metadata.d.ts +2 -0
  151. package/dist/get-video-metadata.js +44 -0
  152. package/dist/has-all-info.d.ts +2 -1
  153. package/dist/has-all-info.js +14 -5
  154. package/dist/index.d.ts +1 -0
  155. package/dist/make-hvc1-codec-strings.d.ts +2 -0
  156. package/dist/make-hvc1-codec-strings.js +47 -0
  157. package/dist/options.d.ts +26 -4
  158. package/dist/parse-media.js +62 -17
  159. package/dist/parse-result.d.ts +16 -5
  160. package/dist/parse-video.d.ts +11 -2
  161. package/dist/parse-video.js +14 -6
  162. package/dist/parser-context.d.ts +8 -0
  163. package/dist/parser-context.js +2 -0
  164. package/dist/parser-state.d.ts +23 -0
  165. package/dist/parser-state.js +112 -0
  166. package/dist/read-and-increment-offset.d.ts +28 -0
  167. package/dist/read-and-increment-offset.js +177 -0
  168. package/dist/reader.d.ts +2 -2
  169. package/dist/traversal.d.ts +37 -0
  170. package/dist/traversal.js +244 -1
  171. package/dist/understand-vorbis.d.ts +1 -0
  172. package/dist/understand-vorbis.js +12 -0
  173. package/dist/webcodec-sample-types.d.ts +21 -0
  174. package/dist/webcodec-sample-types.js +2 -0
  175. package/package.json +10 -2
  176. package/src/add-new-matroska-tracks.ts +23 -0
  177. package/src/boxes/iso-base-media/esds/decoder-specific-config.ts +61 -0
  178. package/src/boxes/iso-base-media/esds/esds-descriptors.ts +33 -2
  179. package/src/boxes/iso-base-media/make-track.ts +157 -0
  180. package/src/boxes/iso-base-media/mdat/mdat.ts +131 -0
  181. package/src/boxes/iso-base-media/moov/moov.ts +8 -3
  182. package/src/boxes/iso-base-media/mvhd.ts +7 -1
  183. package/src/boxes/iso-base-media/process-box.ts +388 -38
  184. package/src/boxes/iso-base-media/stsd/av1c.ts +19 -0
  185. package/src/boxes/iso-base-media/stsd/avcc.ts +36 -0
  186. package/src/boxes/iso-base-media/stsd/colr.ts +49 -0
  187. package/src/boxes/iso-base-media/stsd/ctts.ts +55 -0
  188. package/src/boxes/iso-base-media/stsd/hvcc.ts +32 -0
  189. package/src/boxes/iso-base-media/stsd/keys.ts +2 -0
  190. package/src/boxes/iso-base-media/stsd/mebx.ts +8 -3
  191. package/src/boxes/iso-base-media/stsd/pasp.ts +32 -0
  192. package/src/boxes/iso-base-media/stsd/samples.ts +43 -16
  193. package/src/boxes/iso-base-media/stsd/stco.ts +50 -0
  194. package/src/boxes/iso-base-media/stsd/stsc.ts +61 -0
  195. package/src/boxes/iso-base-media/stsd/stsd.ts +10 -3
  196. package/src/boxes/iso-base-media/stsd/stss.ts +47 -0
  197. package/src/boxes/iso-base-media/stsd/stsz.ts +75 -0
  198. package/src/boxes/iso-base-media/tkhd.ts +63 -16
  199. package/src/boxes/iso-base-media/trak/trak.ts +8 -3
  200. package/src/boxes/iso-base-media/void-box.ts +4 -0
  201. package/src/boxes/webm/allowed-partial-segments.ts +1 -0
  202. package/src/boxes/webm/av1-codec-private.ts +113 -0
  203. package/src/boxes/webm/description.ts +101 -0
  204. package/src/boxes/webm/get-ready-tracks.ts +36 -0
  205. package/src/boxes/webm/get-track.ts +250 -0
  206. package/src/boxes/webm/parse-webm-header.ts +6 -2
  207. package/src/boxes/webm/segments/all-segments.ts +285 -0
  208. package/src/boxes/webm/segments/duration.ts +15 -8
  209. package/src/boxes/webm/segments/info.ts +18 -4
  210. package/src/boxes/webm/segments/main.ts +0 -13
  211. package/src/boxes/webm/segments/muxing.ts +1 -1
  212. package/src/boxes/webm/segments/parse-children.ts +132 -9
  213. package/src/boxes/webm/segments/seek-head.ts +17 -4
  214. package/src/boxes/webm/segments/seek-position.ts +1 -2
  215. package/src/boxes/webm/segments/seek.ts +31 -9
  216. package/src/boxes/webm/segments/track-entry.ts +475 -65
  217. package/src/boxes/webm/segments/tracks.ts +17 -7
  218. package/src/boxes/webm/segments/void.ts +4 -2
  219. package/src/boxes/webm/segments/writing.ts +1 -1
  220. package/src/boxes/webm/segments.ts +266 -42
  221. package/src/boxes/webm/traversal.ts +32 -0
  222. package/src/buffer-iterator.ts +140 -45
  223. package/src/combine-uint8array.ts +13 -0
  224. package/src/{from-web.ts → from-fetch.ts} +9 -1
  225. package/src/from-node.ts +8 -0
  226. package/src/from-web-file.ts +39 -0
  227. package/src/get-audio-codec.ts +213 -84
  228. package/src/get-dimensions.ts +25 -132
  229. package/src/get-duration.ts +4 -8
  230. package/src/get-fps.ts +27 -172
  231. package/src/get-sample-aspect-ratio.ts +204 -0
  232. package/src/get-sample-positions.ts +93 -0
  233. package/src/get-tracks.ts +147 -0
  234. package/src/get-video-codec.ts +62 -47
  235. package/src/has-all-info.ts +35 -5
  236. package/src/index.ts +8 -0
  237. package/src/make-hvc1-codec-strings.ts +55 -0
  238. package/src/options.ts +48 -9
  239. package/src/parse-media.ts +90 -21
  240. package/src/parse-result.ts +28 -4
  241. package/src/parse-video.ts +30 -7
  242. package/src/parser-context.ts +9 -0
  243. package/src/parser-state.ts +151 -0
  244. package/src/reader.ts +2 -2
  245. package/src/test/aspect-ratio.test.ts +42 -0
  246. package/src/test/av1.test.ts +108 -0
  247. package/src/test/duration.test.ts +5 -21
  248. package/src/test/matroska.test.ts +350 -31
  249. package/src/test/mvhd.test.ts +6 -1
  250. package/src/test/parse-esds.test.ts +29 -6
  251. package/src/test/parse-stco.test.ts +59 -0
  252. package/src/test/parse-stsc.test.ts +104 -0
  253. package/src/test/parse-stsz.test.ts +57 -0
  254. package/src/test/parse-stts.test.ts +1 -1
  255. package/src/test/parse-video.test.ts +23 -35
  256. package/src/test/parse-webm.test.ts +5 -5
  257. package/src/test/stream-local.test.ts +542 -46
  258. package/src/test/stream-remote.test.ts +15 -13
  259. package/src/test/stream-samples.test.ts +259 -0
  260. package/src/test/stsd.test.ts +60 -8
  261. package/src/test/tkhd.test.ts +4 -1
  262. package/src/traversal.ts +496 -0
  263. package/src/webcodec-sample-types.ts +30 -0
  264. package/tsconfig.json +5 -1
  265. package/tsconfig.tsbuildinfo +1 -1
  266. package/boxes.json +0 -1
  267. package/dist/boxes/iso-base-media/esds-descriptors.d.ts +0 -21
  268. package/dist/boxes/iso-base-media/esds-descriptors.js +0 -62
  269. package/dist/boxes/iso-base-media/esds.d.ts +0 -15
  270. package/dist/boxes/iso-base-media/esds.js +0 -27
  271. package/dist/get-codec.d.ts +0 -4
  272. package/dist/get-codec.js +0 -22
  273. /package/dist/{get-samples.d.ts → boxes/webm/bitstream/av1/frame.d.ts} +0 -0
  274. /package/dist/{get-samples.js → boxes/webm/bitstream/av1/frame.js} +0 -0
  275. /package/src/boxes/iso-base-media/{stts → stsd}/stts.ts +0 -0
package/src/get-fps.ts CHANGED
@@ -1,5 +1,13 @@
1
- import type {SttsBox} from './boxes/iso-base-media/stts/stts';
1
+ import type {SttsBox} from './boxes/iso-base-media/stsd/stts';
2
+ import type {TrakBox} from './boxes/iso-base-media/trak/trak';
2
3
  import type {AnySegment} from './parse-result';
4
+ import {
5
+ getMdhdBox,
6
+ getMoovBox,
7
+ getStsdBox,
8
+ getSttsBox,
9
+ getTraks,
10
+ } from './traversal';
3
11
 
4
12
  const calculateFps = ({
5
13
  sttsBox,
@@ -27,43 +35,9 @@ type TimescaleAndDuration = {
27
35
  duration: number;
28
36
  };
29
37
 
30
- export const trakBoxContainsAudio = (trakBox: AnySegment): boolean => {
31
- if (trakBox.type !== 'trak-box') {
32
- return false;
33
- }
34
-
35
- const {children} = trakBox;
36
- const mediaBoxes = children.filter(
37
- (c) => c.type === 'regular-box' && c.boxType === 'mdia',
38
- );
39
- if (!mediaBoxes || mediaBoxes.length === 0) {
40
- return false;
41
- }
42
-
43
- const firstMediaBox = mediaBoxes[0];
44
- if (
45
- firstMediaBox.type !== 'regular-box' ||
46
- firstMediaBox.boxType !== 'mdia'
47
- ) {
48
- return false;
49
- }
50
-
51
- const minf = firstMediaBox.children.find(
52
- (c) => c.type === 'regular-box' && c.boxType === 'minf',
53
- );
54
- if (!minf || minf.type !== 'regular-box' || minf.boxType !== 'minf') {
55
- return false;
56
- }
57
-
58
- const stbl = minf.children.find(
59
- (c) => c.type === 'regular-box' && c.boxType === 'stbl',
60
- );
61
- if (!stbl || stbl.type !== 'regular-box' || stbl.boxType !== 'stbl') {
62
- return false;
63
- }
64
-
65
- const stsd = stbl.children.find((c) => c.type === 'stsd-box');
66
- if (!stsd || stsd.type !== 'stsd-box') {
38
+ export const trakBoxContainsAudio = (trakBox: TrakBox): boolean => {
39
+ const stsd = getStsdBox(trakBox);
40
+ if (!stsd) {
67
41
  return false;
68
42
  }
69
43
 
@@ -75,43 +49,9 @@ export const trakBoxContainsAudio = (trakBox: AnySegment): boolean => {
75
49
  return true;
76
50
  };
77
51
 
78
- export const trakBoxContainsVideo = (trakBox: AnySegment): boolean => {
79
- if (trakBox.type !== 'trak-box') {
80
- return false;
81
- }
82
-
83
- const {children} = trakBox;
84
- const mediaBoxes = children.filter(
85
- (c) => c.type === 'regular-box' && c.boxType === 'mdia',
86
- );
87
- if (!mediaBoxes || mediaBoxes.length === 0) {
88
- return false;
89
- }
90
-
91
- const firstMediaBox = mediaBoxes[0];
92
- if (
93
- firstMediaBox.type !== 'regular-box' ||
94
- firstMediaBox.boxType !== 'mdia'
95
- ) {
96
- return false;
97
- }
98
-
99
- const minf = firstMediaBox.children.find(
100
- (c) => c.type === 'regular-box' && c.boxType === 'minf',
101
- );
102
- if (!minf || minf.type !== 'regular-box' || minf.boxType !== 'minf') {
103
- return false;
104
- }
105
-
106
- const stbl = minf.children.find(
107
- (c) => c.type === 'regular-box' && c.boxType === 'stbl',
108
- );
109
- if (!stbl || stbl.type !== 'regular-box' || stbl.boxType !== 'stbl') {
110
- return false;
111
- }
112
-
113
- const stsd = stbl.children.find((c) => c.type === 'stsd-box');
114
- if (!stsd || stsd.type !== 'stsd-box') {
52
+ export const trakBoxContainsVideo = (trakBox: TrakBox): boolean => {
53
+ const stsd = getStsdBox(trakBox);
54
+ if (!stsd) {
115
55
  return false;
116
56
  }
117
57
 
@@ -124,121 +64,36 @@ export const trakBoxContainsVideo = (trakBox: AnySegment): boolean => {
124
64
  };
125
65
 
126
66
  export const getTimescaleAndDuration = (
127
- boxes: AnySegment[],
67
+ trakBox: TrakBox,
128
68
  ): TimescaleAndDuration | null => {
129
- const moovBox = boxes.find((s) => s.type === 'moov-box');
130
- if (!moovBox || moovBox.type !== 'moov-box') {
131
- return null;
132
- }
133
-
134
- const {children} = moovBox;
135
- const trackBoxes = children.filter((c) => c.type === 'trak-box');
136
- if (!trackBoxes || trackBoxes.length === 0) {
137
- return null;
138
- }
139
-
140
- const trackBox = trackBoxes.find(trakBoxContainsVideo);
141
- if (!trackBox || trackBox.type !== 'trak-box') {
142
- return null;
143
- }
144
-
145
- const trackBoxChildren = trackBox.children;
146
- if (!trackBoxChildren || trackBoxChildren.length === 0) {
147
- return null;
148
- }
149
-
150
- const mdiaBox = trackBoxChildren.find(
151
- (c) => c.type === 'regular-box' && c.boxType === 'mdia',
152
- );
153
- if (
154
- !mdiaBox ||
155
- mdiaBox.type !== 'regular-box' ||
156
- mdiaBox.boxType !== 'mdia'
157
- ) {
158
- return null;
159
- }
160
-
161
- const mdhdBox = mdiaBox?.children.find((c) => c.type === 'mdhd-box');
162
- if (mdhdBox && mdhdBox.type === 'mdhd-box') {
69
+ const mdhdBox = getMdhdBox(trakBox);
70
+ if (mdhdBox) {
163
71
  return {timescale: mdhdBox.timescale, duration: mdhdBox.duration};
164
72
  }
165
73
 
166
- const mvhdBox = moovBox.children.find((c) => c.type === 'mvhd-box');
167
- if (!mvhdBox || mvhdBox.type !== 'mvhd-box') {
168
- return null;
169
- }
170
-
171
- const {timeScale, durationInUnits} = mvhdBox;
172
- return {timescale: timeScale, duration: durationInUnits};
74
+ return null;
173
75
  };
174
76
 
175
77
  export const getFps = (segments: AnySegment[]) => {
176
- const timescaleAndDuration = getTimescaleAndDuration(segments);
177
- if (!timescaleAndDuration) {
178
- return null;
179
- }
180
-
181
- const moovBox = segments.find((s) => s.type === 'moov-box');
182
- if (!moovBox || moovBox.type !== 'moov-box') {
78
+ const moovBox = getMoovBox(segments);
79
+ if (!moovBox) {
183
80
  return null;
184
81
  }
185
82
 
186
- const mvhdBox = moovBox.children.find((c) => c.type === 'mvhd-box');
187
- if (!mvhdBox || mvhdBox.type !== 'mvhd-box') {
188
- return null;
189
- }
190
-
191
- const {children} = moovBox;
192
- const trackBoxes = children.filter((c) => c.type === 'trak-box');
193
- if (!trackBoxes || trackBoxes.length === 0) {
194
- return null;
195
- }
83
+ const trackBoxes = getTraks(moovBox);
196
84
 
197
85
  const trackBox = trackBoxes.find(trakBoxContainsVideo);
198
- if (!trackBox || trackBox.type !== 'trak-box') {
86
+ if (!trackBox) {
199
87
  return null;
200
88
  }
201
89
 
202
- const trackBoxChildren = trackBox.children;
203
- if (!trackBoxChildren || trackBoxChildren.length === 0) {
204
- return null;
205
- }
206
-
207
- const mdiaBox = trackBoxChildren.find(
208
- (c) => c.type === 'regular-box' && c.boxType === 'mdia',
209
- );
210
- if (
211
- !mdiaBox ||
212
- mdiaBox.type !== 'regular-box' ||
213
- mdiaBox.boxType !== 'mdia'
214
- ) {
215
- return null;
216
- }
217
-
218
- const minfBox = mdiaBox.children.find(
219
- (c) => c.type === 'regular-box' && c.boxType === 'minf',
220
- );
221
- if (
222
- !minfBox ||
223
- minfBox.type !== 'regular-box' ||
224
- minfBox.boxType !== 'minf'
225
- ) {
226
- return null;
227
- }
228
-
229
- const stblBox = minfBox.children.find(
230
- (c) => c.type === 'regular-box' && c.boxType === 'stbl',
231
- );
232
- if (
233
- !stblBox ||
234
- stblBox.type !== 'regular-box' ||
235
- stblBox.boxType !== 'stbl'
236
- ) {
90
+ const timescaleAndDuration = getTimescaleAndDuration(trackBox);
91
+ if (!timescaleAndDuration) {
237
92
  return null;
238
93
  }
239
94
 
240
- const sttsBox = stblBox.children.find((c) => c.type === 'stts-box');
241
- if (!sttsBox || sttsBox.type !== 'stts-box') {
95
+ const sttsBox = getSttsBox(trackBox);
96
+ if (!sttsBox) {
242
97
  return null;
243
98
  }
244
99
 
@@ -0,0 +1,204 @@
1
+ import type {Av1CBox} from './boxes/iso-base-media/stsd/av1c';
2
+ import type {AvccBox} from './boxes/iso-base-media/stsd/avcc';
3
+ import type {ColorParameterBox} from './boxes/iso-base-media/stsd/colr';
4
+ import type {HvccBox} from './boxes/iso-base-media/stsd/hvcc';
5
+ import type {PaspBox} from './boxes/iso-base-media/stsd/pasp';
6
+ import type {VideoSample} from './boxes/iso-base-media/stsd/samples';
7
+ import type {TkhdBox} from './boxes/iso-base-media/tkhd';
8
+ import type {TrakBox} from './boxes/iso-base-media/trak/trak';
9
+ import type {Dimensions} from './get-dimensions';
10
+ import {getStsdBox} from './traversal';
11
+
12
+ type AspectRatio = {
13
+ numerator: number;
14
+ denominator: number;
15
+ };
16
+
17
+ export const getVideoSample = (trakBox: TrakBox): VideoSample | null => {
18
+ const stsdBox = getStsdBox(trakBox);
19
+
20
+ if (!stsdBox) {
21
+ return null;
22
+ }
23
+
24
+ const videoSample = stsdBox.samples.find((s) => s.type === 'video');
25
+ if (!videoSample || videoSample.type !== 'video') {
26
+ return null;
27
+ }
28
+
29
+ return videoSample;
30
+ };
31
+
32
+ export const getAvccBox = (trakBox: TrakBox): AvccBox | null => {
33
+ const videoSample = getVideoSample(trakBox);
34
+ if (!videoSample) {
35
+ return null;
36
+ }
37
+
38
+ const avccBox = videoSample.descriptors.find((c) => c.type === 'avcc-box');
39
+
40
+ if (!avccBox || avccBox.type !== 'avcc-box') {
41
+ return null;
42
+ }
43
+
44
+ return avccBox;
45
+ };
46
+
47
+ export const getAv1CBox = (trakBox: TrakBox): Av1CBox | null => {
48
+ const videoSample = getVideoSample(trakBox);
49
+ if (!videoSample) {
50
+ return null;
51
+ }
52
+
53
+ const av1cBox = videoSample.descriptors.find((c) => c.type === 'av1C-box');
54
+
55
+ if (!av1cBox || av1cBox.type !== 'av1C-box') {
56
+ return null;
57
+ }
58
+
59
+ return av1cBox;
60
+ };
61
+
62
+ export const getPaspBox = (trakBox: TrakBox): PaspBox | null => {
63
+ const videoSample = getVideoSample(trakBox);
64
+ if (!videoSample) {
65
+ return null;
66
+ }
67
+
68
+ const paspBox = videoSample.descriptors.find((c) => c.type === 'pasp-box');
69
+
70
+ if (!paspBox || paspBox.type !== 'pasp-box') {
71
+ return null;
72
+ }
73
+
74
+ return paspBox;
75
+ };
76
+
77
+ export const getHvccBox = (trakBox: TrakBox): HvccBox | null => {
78
+ const videoSample = getVideoSample(trakBox);
79
+ if (!videoSample) {
80
+ return null;
81
+ }
82
+
83
+ const hvccBox = videoSample.descriptors.find((c) => c.type === 'hvcc-box');
84
+
85
+ if (!hvccBox || hvccBox.type !== 'hvcc-box') {
86
+ return null;
87
+ }
88
+
89
+ return hvccBox;
90
+ };
91
+
92
+ export const getSampleAspectRatio = (trakBox: TrakBox): AspectRatio => {
93
+ const paspBox = getPaspBox(trakBox);
94
+ if (!paspBox) {
95
+ return {
96
+ numerator: 1,
97
+ denominator: 1,
98
+ };
99
+ }
100
+
101
+ return {
102
+ numerator: paspBox.hSpacing,
103
+ denominator: paspBox.vSpacing,
104
+ };
105
+ };
106
+
107
+ export const getColrBox = (
108
+ videoSample: VideoSample,
109
+ ): ColorParameterBox | null => {
110
+ const colrBox = videoSample.descriptors.find((c) => c.type === 'colr-box');
111
+
112
+ if (!colrBox || colrBox.type !== 'colr-box') {
113
+ return null;
114
+ }
115
+
116
+ return colrBox;
117
+ };
118
+
119
+ export const applyTkhdBox = (
120
+ aspectRatioApplied: Dimensions,
121
+ tkhdBox: TkhdBox,
122
+ ): {
123
+ displayAspectWidth: number;
124
+ displayAspectHeight: number;
125
+ width: number;
126
+ height: number;
127
+ rotation: number;
128
+ } => {
129
+ if (tkhdBox === null || tkhdBox.rotation === 0) {
130
+ return {
131
+ displayAspectWidth: aspectRatioApplied.width,
132
+ displayAspectHeight: aspectRatioApplied.height,
133
+ width: aspectRatioApplied.width,
134
+ height: aspectRatioApplied.height,
135
+ rotation: 0,
136
+ };
137
+ }
138
+
139
+ return {
140
+ width: tkhdBox.width,
141
+ height: tkhdBox.height,
142
+ rotation: tkhdBox.rotation,
143
+ displayAspectWidth: aspectRatioApplied.width,
144
+ displayAspectHeight: aspectRatioApplied.height,
145
+ };
146
+ };
147
+
148
+ export const applyAspectRatios = ({
149
+ dimensions,
150
+ sampleAspectRatio,
151
+ displayAspectRatio,
152
+ }: {
153
+ dimensions: Dimensions;
154
+ sampleAspectRatio: AspectRatio;
155
+ displayAspectRatio: AspectRatio;
156
+ }): Dimensions => {
157
+ if (displayAspectRatio.numerator === 0) {
158
+ return dimensions;
159
+ }
160
+
161
+ if (displayAspectRatio.denominator === 0) {
162
+ return dimensions;
163
+ }
164
+
165
+ const newWidth = Math.round(
166
+ (dimensions.width * sampleAspectRatio.numerator) /
167
+ sampleAspectRatio.denominator,
168
+ );
169
+ const newHeight = Math.floor(
170
+ newWidth / (displayAspectRatio.numerator / displayAspectRatio.denominator),
171
+ );
172
+
173
+ return {
174
+ width: Math.floor(newWidth),
175
+ height: newHeight,
176
+ };
177
+ };
178
+
179
+ function gcd(a: number, b: number): number {
180
+ return b === 0 ? a : gcd(b, a % b);
181
+ }
182
+
183
+ function reduceFraction(numerator: number, denominator: number) {
184
+ const greatestCommonDivisor = gcd(Math.abs(numerator), Math.abs(denominator));
185
+ return {
186
+ numerator: numerator / greatestCommonDivisor,
187
+ denominator: denominator / greatestCommonDivisor,
188
+ };
189
+ }
190
+
191
+ export const getDisplayAspectRatio = ({
192
+ sampleAspectRatio,
193
+ nativeDimensions,
194
+ }: {
195
+ sampleAspectRatio: AspectRatio;
196
+ nativeDimensions: Dimensions;
197
+ }): AspectRatio => {
198
+ const num = Math.round(nativeDimensions.width * sampleAspectRatio.numerator);
199
+ const den = Math.round(
200
+ nativeDimensions.height * sampleAspectRatio.denominator,
201
+ );
202
+
203
+ return reduceFraction(num, den);
204
+ };
@@ -0,0 +1,93 @@
1
+ import type {CttsBox} from './boxes/iso-base-media/stsd/ctts';
2
+ import type {StcoBox} from './boxes/iso-base-media/stsd/stco';
3
+ import type {StscBox} from './boxes/iso-base-media/stsd/stsc';
4
+ import type {StssBox} from './boxes/iso-base-media/stsd/stss';
5
+ import type {StszBox} from './boxes/iso-base-media/stsd/stsz';
6
+ import type {SttsBox} from './boxes/iso-base-media/stsd/stts';
7
+
8
+ export type SamplePosition = {
9
+ offset: number;
10
+ size: number;
11
+ isKeyframe: boolean;
12
+ dts: number;
13
+ cts: number;
14
+ duration: number;
15
+ };
16
+
17
+ export const getSamplePositions = ({
18
+ stcoBox,
19
+ stszBox,
20
+ stscBox,
21
+ stssBox,
22
+ sttsBox,
23
+ cttsBox,
24
+ }: {
25
+ stcoBox: StcoBox;
26
+ stszBox: StszBox;
27
+ stscBox: StscBox;
28
+ stssBox: StssBox | null;
29
+ sttsBox: SttsBox;
30
+ cttsBox: CttsBox | null;
31
+ }) => {
32
+ const sttsDeltas: number[] = [];
33
+ for (const distribution of sttsBox.sampleDistribution) {
34
+ for (let i = 0; i < distribution.sampleCount; i++) {
35
+ sttsDeltas.push(distribution.sampleDelta);
36
+ }
37
+ }
38
+
39
+ const cttsEntries: number[] = [];
40
+ for (const entry of cttsBox?.entries ?? [
41
+ {sampleCount: sttsDeltas.length, sampleOffset: 0},
42
+ ]) {
43
+ for (let i = 0; i < entry.sampleCount; i++) {
44
+ cttsEntries.push(entry.sampleOffset);
45
+ }
46
+ }
47
+
48
+ let dts = 0;
49
+
50
+ const chunks = stcoBox.entries;
51
+ const samples: SamplePosition[] = [];
52
+
53
+ let samplesPerChunk = 1;
54
+
55
+ for (let i = 0; i < chunks.length; i++) {
56
+ const hasEntry = stscBox.entries.find(
57
+ (entry) => entry.firstChunk === i + 1,
58
+ );
59
+ if (hasEntry) {
60
+ samplesPerChunk = hasEntry.samplesPerChunk;
61
+ }
62
+
63
+ let offsetInThisChunk = 0;
64
+
65
+ for (let j = 0; j < samplesPerChunk; j++) {
66
+ const size =
67
+ stszBox.countType === 'fixed'
68
+ ? stszBox.sampleSize
69
+ : stszBox.entries[samples.length];
70
+
71
+ const isKeyframe = stssBox
72
+ ? stssBox.sampleNumber.includes(samples.length + 1)
73
+ : true;
74
+
75
+ const delta = sttsDeltas[samples.length];
76
+ const ctsOffset = cttsEntries[samples.length];
77
+ const cts = dts + ctsOffset;
78
+
79
+ samples.push({
80
+ offset: chunks[i] + offsetInThisChunk,
81
+ size,
82
+ isKeyframe,
83
+ dts,
84
+ cts,
85
+ duration: delta,
86
+ });
87
+ dts += delta;
88
+ offsetInThisChunk += size;
89
+ }
90
+ }
91
+
92
+ return samples;
93
+ };
@@ -0,0 +1,147 @@
1
+ import {makeBaseMediaTrack} from './boxes/iso-base-media/make-track';
2
+ import type {MoovBox} from './boxes/iso-base-media/moov/moov';
3
+ import {getTracksFromMatroska} from './boxes/webm/get-ready-tracks';
4
+ import {getMainSegment} from './boxes/webm/traversal';
5
+ import type {SamplePosition} from './get-sample-positions';
6
+ import type {AnySegment} from './parse-result';
7
+ import type {ParserState} from './parser-state';
8
+ import {getMoovBox, getMvhdBox, getTracksSegment, getTraks} from './traversal';
9
+
10
+ type SampleAspectRatio = {
11
+ numerator: number;
12
+ denominator: number;
13
+ };
14
+
15
+ export type VideoTrack = {
16
+ type: 'video';
17
+ samplePositions: SamplePosition[] | null;
18
+ trackId: number;
19
+ description: Uint8Array | undefined;
20
+ timescale: number;
21
+ codec: string;
22
+ sampleAspectRatio: SampleAspectRatio;
23
+ width: number;
24
+ height: number;
25
+ displayAspectWidth: number;
26
+ displayAspectHeight: number;
27
+ codedWidth: number;
28
+ codedHeight: number;
29
+ rotation: number;
30
+ };
31
+
32
+ export type AudioTrack = {
33
+ type: 'audio';
34
+ samplePositions: SamplePosition[] | null;
35
+ trackId: number;
36
+ timescale: number;
37
+ codec: string;
38
+ numberOfChannels: number;
39
+ sampleRate: number;
40
+ description: Uint8Array | undefined;
41
+ };
42
+
43
+ export type OtherTrack = {
44
+ type: 'other';
45
+ samplePositions: SamplePosition[] | null;
46
+ trackId: number;
47
+ timescale: number;
48
+ };
49
+
50
+ export type Track = VideoTrack | AudioTrack | OtherTrack;
51
+
52
+ export const getNumberOfTracks = (moovBox: MoovBox): number => {
53
+ const mvHdBox = getMvhdBox(moovBox);
54
+ if (!mvHdBox) {
55
+ return 0;
56
+ }
57
+
58
+ return mvHdBox.nextTrackId - 1;
59
+ };
60
+
61
+ export const hasTracks = (segments: AnySegment[]): boolean => {
62
+ const mainSegment = getMainSegment(segments);
63
+
64
+ if (mainSegment) {
65
+ return getTracksSegment(mainSegment) !== null;
66
+ }
67
+
68
+ const moovBox = getMoovBox(segments);
69
+
70
+ if (!moovBox) {
71
+ return false;
72
+ }
73
+
74
+ const numberOfTracks = getNumberOfTracks(moovBox);
75
+ const tracks = getTraks(moovBox);
76
+
77
+ return tracks.length === numberOfTracks;
78
+ };
79
+
80
+ export const getTracks = (
81
+ segments: AnySegment[],
82
+ state: ParserState,
83
+ ): {
84
+ videoTracks: VideoTrack[];
85
+ audioTracks: AudioTrack[];
86
+ otherTracks: OtherTrack[];
87
+ } => {
88
+ const videoTracks: VideoTrack[] = [];
89
+ const audioTracks: AudioTrack[] = [];
90
+ const otherTracks: OtherTrack[] = [];
91
+
92
+ const mainSegment = segments.find((s) => s.type === 'main-segment');
93
+ if (mainSegment && mainSegment.type === 'main-segment') {
94
+ const matroskaTracks = getTracksFromMatroska(
95
+ mainSegment,
96
+ state.getTimescale(),
97
+ );
98
+
99
+ for (const track of matroskaTracks) {
100
+ if (track.type === 'video') {
101
+ videoTracks.push(track);
102
+ } else if (track.type === 'audio') {
103
+ audioTracks.push(track);
104
+ } else if (track.type === 'other') {
105
+ otherTracks.push(track);
106
+ }
107
+ }
108
+
109
+ return {
110
+ videoTracks,
111
+ audioTracks,
112
+ otherTracks,
113
+ };
114
+ }
115
+
116
+ const moovBox = getMoovBox(segments);
117
+ if (!moovBox) {
118
+ return {
119
+ videoTracks,
120
+ audioTracks,
121
+ otherTracks,
122
+ };
123
+ }
124
+
125
+ const tracks = getTraks(moovBox);
126
+
127
+ for (const trakBox of tracks) {
128
+ const track = makeBaseMediaTrack(trakBox);
129
+ if (!track) {
130
+ continue;
131
+ }
132
+
133
+ if (track.type === 'video') {
134
+ videoTracks.push(track);
135
+ } else if (track.type === 'audio') {
136
+ audioTracks.push(track);
137
+ } else if (track.type === 'other') {
138
+ otherTracks.push(track);
139
+ }
140
+ }
141
+
142
+ return {
143
+ videoTracks,
144
+ audioTracks,
145
+ otherTracks,
146
+ };
147
+ };