@remotion/media-parser 4.0.202 → 4.0.205

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 (106) hide show
  1. package/dist/av1-codec-string.d.ts +0 -5
  2. package/dist/av1-codec-string.js +1 -18
  3. package/dist/boxes/iso-base-media/esds/decoder-specific-config.js +6 -1
  4. package/dist/boxes/iso-base-media/ftype.d.ts +9 -0
  5. package/dist/boxes/iso-base-media/ftype.js +31 -0
  6. package/dist/boxes/iso-base-media/get-sample-positions-from-track.d.ts +4 -0
  7. package/dist/boxes/iso-base-media/get-sample-positions-from-track.js +48 -0
  8. package/dist/boxes/iso-base-media/make-track.js +3 -30
  9. package/dist/boxes/iso-base-media/mdat/mdat.js +25 -22
  10. package/dist/boxes/iso-base-media/mdhd.d.ts +2 -0
  11. package/dist/boxes/iso-base-media/mdhd.js +6 -7
  12. package/dist/boxes/iso-base-media/mvhd.js +11 -13
  13. package/dist/boxes/iso-base-media/process-box.js +36 -0
  14. package/dist/boxes/iso-base-media/tfdt.d.ts +12 -0
  15. package/dist/boxes/iso-base-media/tfdt.js +20 -0
  16. package/dist/boxes/iso-base-media/tfhd.d.ts +16 -0
  17. package/dist/boxes/iso-base-media/tfhd.js +41 -0
  18. package/dist/boxes/iso-base-media/tkhd.js +9 -12
  19. package/dist/boxes/iso-base-media/trun.d.ts +21 -0
  20. package/dist/boxes/iso-base-media/trun.js +44 -0
  21. package/dist/boxes/webm/bitstream/av1.js +1 -10
  22. package/dist/boxes/webm/ebml.d.ts +1 -1
  23. package/dist/boxes/webm/get-track.js +2 -2
  24. package/dist/boxes/webm/segments/seek-position.js +1 -1
  25. package/dist/boxes/webm/segments/seek.d.ts +1 -1
  26. package/dist/boxes/webm/segments/seek.js +8 -2
  27. package/dist/boxes/webm/segments/timestamp-scale.js +1 -1
  28. package/dist/boxes/webm/tracks.d.ts +8 -0
  29. package/dist/boxes/webm/tracks.js +21 -0
  30. package/dist/buffer-iterator.d.ts +1 -0
  31. package/dist/buffer-iterator.js +3 -2
  32. package/dist/create/cluster-segment.d.ts +10 -0
  33. package/dist/create/cluster-segment.js +41 -0
  34. package/dist/create/create-media.d.ts +6 -1
  35. package/dist/create/create-media.js +58 -4
  36. package/dist/create/matroska-header.d.ts +1 -1
  37. package/dist/create/matroska-info.d.ts +1 -1
  38. package/dist/create/matroska-info.js +2 -2
  39. package/dist/create/matroska-segment.d.ts +2 -1
  40. package/dist/create/matroska-trackentry.d.ts +5 -4
  41. package/dist/from-web.js +6 -15
  42. package/dist/get-duration.d.ts +3 -2
  43. package/dist/get-duration.js +24 -4
  44. package/dist/get-tracks.d.ts +4 -4
  45. package/dist/get-video-metadata.d.ts +2 -0
  46. package/dist/get-video-metadata.js +44 -0
  47. package/dist/has-all-info.js +1 -1
  48. package/dist/parse-media.js +1 -1
  49. package/dist/parse-result.d.ts +4 -1
  50. package/dist/read-and-increment-offset.d.ts +28 -0
  51. package/dist/read-and-increment-offset.js +177 -0
  52. package/dist/samples-from-moof.d.ts +6 -0
  53. package/dist/samples-from-moof.js +75 -0
  54. package/dist/traversal.d.ts +8 -1
  55. package/dist/traversal.js +39 -1
  56. package/dist/understand-vorbis.d.ts +1 -0
  57. package/dist/understand-vorbis.js +12 -0
  58. package/dist/writers/web-fs.js +21 -5
  59. package/dist/writers/writer.d.ts +3 -1
  60. package/package.json +2 -2
  61. package/src/boxes/iso-base-media/esds/decoder-specific-config.ts +8 -1
  62. package/src/boxes/iso-base-media/get-sample-positions-from-track.ts +69 -0
  63. package/src/boxes/iso-base-media/make-track.ts +4 -45
  64. package/src/boxes/iso-base-media/mdat/mdat.ts +33 -24
  65. package/src/boxes/iso-base-media/mdhd.ts +10 -7
  66. package/src/boxes/iso-base-media/mvhd.ts +15 -14
  67. package/src/boxes/iso-base-media/process-box.ts +42 -0
  68. package/src/boxes/iso-base-media/tfdt.ts +37 -0
  69. package/src/boxes/iso-base-media/tfhd.ts +66 -0
  70. package/src/boxes/iso-base-media/tkhd.ts +11 -13
  71. package/src/boxes/iso-base-media/trun.ts +74 -0
  72. package/src/boxes/webm/get-track.ts +2 -2
  73. package/src/buffer-iterator.ts +3 -2
  74. package/src/get-duration.ts +40 -5
  75. package/src/get-tracks.ts +4 -4
  76. package/src/has-all-info.ts +1 -1
  77. package/src/parse-media.ts +1 -1
  78. package/src/parse-result.ts +7 -1
  79. package/src/samples-from-moof.ts +102 -0
  80. package/src/test/samples-from-moof.test.ts +2496 -0
  81. package/src/test/stream-local.test.ts +28 -30
  82. package/src/test/stream-samples.test.ts +153 -231
  83. package/src/traversal.ts +56 -1
  84. package/tsconfig.tsbuildinfo +1 -1
  85. package/dist/bitstream/av1.d.ts +0 -2
  86. package/dist/bitstream/av1.js +0 -12
  87. package/dist/boxes/iso-base-media/avcc-hvcc.d.ts +0 -20
  88. package/dist/boxes/iso-base-media/avcc-hvcc.js +0 -73
  89. package/dist/boxes/iso-base-media/avcc.d.ts +0 -18
  90. package/dist/boxes/iso-base-media/avcc.js +0 -27
  91. package/dist/boxes/iso-base-media/esds-descriptors.d.ts +0 -21
  92. package/dist/boxes/iso-base-media/esds-descriptors.js +0 -62
  93. package/dist/boxes/iso-base-media/esds.d.ts +0 -15
  94. package/dist/boxes/iso-base-media/esds.js +0 -27
  95. package/dist/create-media.d.ts +0 -1
  96. package/dist/create-media.js +0 -78
  97. package/dist/from-input-type-file.d.ts +0 -2
  98. package/dist/from-input-type-file.js +0 -37
  99. package/dist/get-codec.d.ts +0 -4
  100. package/dist/get-codec.js +0 -22
  101. package/dist/web-file.d.ts +0 -2
  102. package/dist/web-file.js +0 -37
  103. /package/dist/{get-samples.d.ts → boxes/webm/bitstream/av1/frame.d.ts} +0 -0
  104. /package/dist/{get-samples.js → boxes/webm/bitstream/av1/frame.js} +0 -0
  105. /package/dist/{sample-aspect-ratio.d.ts → boxes/webm/bitstream/h264/get-h264-descriptor.d.ts} +0 -0
  106. /package/dist/{sample-aspect-ratio.js → boxes/webm/bitstream/h264/get-h264-descriptor.js} +0 -0
@@ -1,6 +1,10 @@
1
+ import {getSamplePositionsFromTrack} from './boxes/iso-base-media/get-sample-positions-from-track';
2
+ import type {TrakBox} from './boxes/iso-base-media/trak/trak';
1
3
  import type {DurationSegment} from './boxes/webm/segments/all-segments';
4
+ import {getTracks} from './get-tracks';
2
5
  import type {AnySegment} from './parse-result';
3
- import {getMoovBox, getMvhdBox} from './traversal';
6
+ import type {ParserState} from './parser-state';
7
+ import {getMoofBox, getMoovBox, getMvhdBox} from './traversal';
4
8
 
5
9
  const getDurationFromMatroska = (segments: AnySegment[]): number | null => {
6
10
  const mainSegment = segments.find((s) => s.type === 'Segment');
@@ -35,7 +39,10 @@ const getDurationFromMatroska = (segments: AnySegment[]): number | null => {
35
39
  return (duration.value.value / timestampScale.value.value) * 1000;
36
40
  };
37
41
 
38
- export const getDuration = (boxes: AnySegment[]): number | null => {
42
+ export const getDuration = (
43
+ boxes: AnySegment[],
44
+ parserState: ParserState,
45
+ ): number | null => {
39
46
  const matroskaBox = boxes.find((b) => b.type === 'Segment');
40
47
  if (matroskaBox) {
41
48
  return getDurationFromMatroska(boxes);
@@ -46,6 +53,7 @@ export const getDuration = (boxes: AnySegment[]): number | null => {
46
53
  return null;
47
54
  }
48
55
 
56
+ const moofBox = getMoofBox(boxes);
49
57
  const mvhdBox = getMvhdBox(moovBox);
50
58
 
51
59
  if (!mvhdBox) {
@@ -56,12 +64,39 @@ export const getDuration = (boxes: AnySegment[]): number | null => {
56
64
  throw new Error('Expected mvhd-box');
57
65
  }
58
66
 
59
- return mvhdBox.durationInSeconds;
67
+ if (mvhdBox.durationInSeconds > 0) {
68
+ return mvhdBox.durationInSeconds;
69
+ }
70
+
71
+ const tracks = getTracks(boxes, parserState);
72
+ const allTracks = [
73
+ ...tracks.videoTracks,
74
+ ...tracks.audioTracks,
75
+ ...tracks.otherTracks,
76
+ ];
77
+ const allSamples = allTracks.map((t) => {
78
+ const {timescale: ts} = t;
79
+ const samplePositions = getSamplePositionsFromTrack(
80
+ t.trakBox as TrakBox,
81
+ moofBox,
82
+ );
83
+
84
+ const highest = samplePositions
85
+ ?.map((sp) => (sp.cts + sp.duration) / ts)
86
+ .reduce((a, b) => Math.max(a, b), 0);
87
+ return highest ?? 0;
88
+ });
89
+ const highestTimestamp = Math.max(...allSamples);
90
+ return highestTimestamp;
60
91
  };
61
92
 
62
- export const hasDuration = (boxes: AnySegment[]): boolean => {
93
+ export const hasDuration = (
94
+ boxes: AnySegment[],
95
+ parserState: ParserState,
96
+ ): boolean => {
63
97
  try {
64
- return getDuration(boxes) !== null;
98
+ const duration = getDuration(boxes, parserState);
99
+ return getDuration(boxes, parserState) !== null && duration !== 0;
65
100
  } catch (err) {
66
101
  return false;
67
102
  }
package/src/get-tracks.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import {makeBaseMediaTrack} from './boxes/iso-base-media/make-track';
2
2
  import type {MoovBox} from './boxes/iso-base-media/moov/moov';
3
+ import type {TrakBox} from './boxes/iso-base-media/trak/trak';
3
4
  import {getTracksFromMatroska} from './boxes/webm/get-ready-tracks';
4
5
  import {getMainSegment} from './boxes/webm/traversal';
5
- import type {SamplePosition} from './get-sample-positions';
6
6
  import type {AnySegment} from './parse-result';
7
7
  import type {ParserState} from './parser-state';
8
8
  import {getMoovBox, getMvhdBox, getTracksSegment, getTraks} from './traversal';
@@ -14,7 +14,6 @@ type SampleAspectRatio = {
14
14
 
15
15
  export type VideoTrack = {
16
16
  type: 'video';
17
- samplePositions: SamplePosition[] | null;
18
17
  trackId: number;
19
18
  description: Uint8Array | undefined;
20
19
  timescale: number;
@@ -27,24 +26,25 @@ export type VideoTrack = {
27
26
  codedWidth: number;
28
27
  codedHeight: number;
29
28
  rotation: number;
29
+ trakBox: TrakBox | null;
30
30
  };
31
31
 
32
32
  export type AudioTrack = {
33
33
  type: 'audio';
34
- samplePositions: SamplePosition[] | null;
35
34
  trackId: number;
36
35
  timescale: number;
37
36
  codec: string;
38
37
  numberOfChannels: number;
39
38
  sampleRate: number;
40
39
  description: Uint8Array | undefined;
40
+ trakBox: TrakBox | null;
41
41
  };
42
42
 
43
43
  export type OtherTrack = {
44
44
  type: 'other';
45
- samplePositions: SamplePosition[] | null;
46
45
  trackId: number;
47
46
  timescale: number;
47
+ trakBox: TrakBox | null;
48
48
  };
49
49
 
50
50
  export type Track = VideoTrack | AudioTrack | OtherTrack;
@@ -45,7 +45,7 @@ export const hasAllInfo = (
45
45
  }
46
46
 
47
47
  if (key === 'durationInSeconds') {
48
- return hasDuration(parseResult.segments);
48
+ return hasDuration(parseResult.segments, state);
49
49
  }
50
50
 
51
51
  if (
@@ -149,7 +149,7 @@ export const parseMedia: ParseMedia = async ({
149
149
  }
150
150
 
151
151
  if (fields?.durationInSeconds) {
152
- returnValue.durationInSeconds = getDuration(parseResult.segments);
152
+ returnValue.durationInSeconds = getDuration(parseResult.segments, state);
153
153
  }
154
154
 
155
155
  if (fields?.fps) {
@@ -19,8 +19,11 @@ import type {StsdBox} from './boxes/iso-base-media/stsd/stsd';
19
19
  import type {StssBox} from './boxes/iso-base-media/stsd/stss';
20
20
  import type {StszBox} from './boxes/iso-base-media/stsd/stsz';
21
21
  import type {SttsBox} from './boxes/iso-base-media/stsd/stts';
22
+ import type {TfdtBox} from './boxes/iso-base-media/tfdt';
23
+ import type {TfhdBox} from './boxes/iso-base-media/tfhd';
22
24
  import type {TkhdBox} from './boxes/iso-base-media/tkhd';
23
25
  import type {TrakBox} from './boxes/iso-base-media/trak/trak';
26
+ import type {TrunBox} from './boxes/iso-base-media/trun';
24
27
  import type {VoidBox} from './boxes/iso-base-media/void-box';
25
28
  import type {MatroskaSegment} from './boxes/webm/segments';
26
29
 
@@ -56,7 +59,10 @@ export type IsoBaseMediaBox =
56
59
  | PaspBox
57
60
  | CttsBox
58
61
  | Av1CBox
59
- | ColorParameterBox;
62
+ | TrunBox
63
+ | ColorParameterBox
64
+ | TfdtBox
65
+ | TfhdBox;
60
66
 
61
67
  export type AnySegment = MatroskaSegment | IsoBaseMediaBox;
62
68
 
@@ -0,0 +1,102 @@
1
+ import type {SamplePosition} from './get-sample-positions';
2
+ import type {AnySegment, IsoBaseMediaBox} from './parse-result';
3
+ import {getTfdtBox, getTfhdBox, getTrunBoxes} from './traversal';
4
+
5
+ const getSamplesFromTraf = (
6
+ trafSegment: IsoBaseMediaBox,
7
+ moofOffset: number,
8
+ ): SamplePosition[] => {
9
+ if (trafSegment.type !== 'regular-box' || trafSegment.boxType !== 'traf') {
10
+ throw new Error('Expected traf-box');
11
+ }
12
+
13
+ const tfhdBox = getTfhdBox(trafSegment);
14
+ const defaultSampleDuration = tfhdBox?.defaultSampleDuration ?? null;
15
+ const defaultSampleSize = tfhdBox?.defaultSampleSize ?? null;
16
+ const defaultSampleFlags = tfhdBox?.defaultSampleFlags ?? null;
17
+
18
+ const tfdtBox = getTfdtBox(trafSegment);
19
+ const trunBoxes = getTrunBoxes(trafSegment);
20
+
21
+ let time = 0;
22
+ let offset = 0;
23
+
24
+ let dataOffset = 0;
25
+
26
+ const samples: SamplePosition[] = [];
27
+
28
+ for (const trunBox of trunBoxes) {
29
+ let i = -1;
30
+
31
+ if (trunBox.dataOffset) {
32
+ dataOffset = trunBox.dataOffset;
33
+ offset = 0;
34
+ }
35
+
36
+ for (const sample of trunBox.samples) {
37
+ i++;
38
+ const duration = sample.sampleDuration ?? defaultSampleDuration;
39
+ if (duration === null) {
40
+ throw new Error('Expected duration');
41
+ }
42
+
43
+ const size = sample.sampleSize ?? defaultSampleSize;
44
+ if (size === null) {
45
+ throw new Error('Expected size');
46
+ }
47
+
48
+ const isFirstSample = i === 0;
49
+ const sampleFlags = sample.sampleFlags
50
+ ? sample.sampleFlags
51
+ : isFirstSample && trunBox.firstSampleFlags !== null
52
+ ? trunBox.firstSampleFlags
53
+ : defaultSampleFlags;
54
+ if (sampleFlags === null) {
55
+ throw new Error('Expected sample flags');
56
+ }
57
+
58
+ const keyframe = !((sampleFlags >> 16) & 0x1);
59
+
60
+ const dts = time + (tfdtBox?.baseMediaDecodeTime ?? 0);
61
+
62
+ const samplePosition: SamplePosition = {
63
+ offset: offset + (moofOffset ?? 0) + (dataOffset ?? 0),
64
+ dts,
65
+ cts: dts,
66
+ duration,
67
+ isKeyframe: keyframe,
68
+ size,
69
+ };
70
+ samples.push(samplePosition);
71
+ offset += size;
72
+ time += duration;
73
+ }
74
+ }
75
+
76
+ return samples;
77
+ };
78
+
79
+ export const getSamplesFromMoof = ({
80
+ moofBox,
81
+ trackId,
82
+ }: {
83
+ moofBox: AnySegment;
84
+ trackId: number;
85
+ }) => {
86
+ if (moofBox.type !== 'regular-box') {
87
+ throw new Error('Expected moof-box');
88
+ }
89
+
90
+ const trafs = moofBox.children.filter(
91
+ (c) => c.type === 'regular-box' && c.boxType === 'traf',
92
+ ) as IsoBaseMediaBox[];
93
+
94
+ const mapped = trafs.map((traf) => {
95
+ const tfhdBox = getTfhdBox(traf);
96
+
97
+ return tfhdBox?.trackId === trackId
98
+ ? getSamplesFromTraf(traf, moofBox.offset)
99
+ : [];
100
+ });
101
+ return mapped.flat(1);
102
+ };