Skip to content

Commit fb431b9

Browse files
committed
fix: correctly detect fragmented files
- Display total fragment duration on the demo closes #504
1 parent 8cae9af commit fb431b9

File tree

5 files changed

+37
-7
lines changed

5 files changed

+37
-7
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ The `info` argument is an object with the following structure.
156156
- **duration**: Number, providing the duration of the movie (unfragmented part) in timescale units,
157157
- **isProgressive**: boolean, indicating if the file can be played progressively,
158158
- **isFragmented**: boolean, indicating if the file is already fragmented,
159-
- **fragment_duration**: Number, giving the duration of the fragmented part of the file, in timescale units,
159+
- **fragment_duration**: Fraction, giving the duration of the fragmented part of the file along with the timescale (in the form `{ num: Number, den: Number }`)
160160
- **hasIOD**: boolean, indicating if the file contains an MPEG-4 Initial Object Descriptor
161161
- **tracks**: Array of track information objects
162162

demo/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,7 @@ function load() {
551551
Log.info('Application', 'Movie information received');
552552
movieInfo = info;
553553
if (info.isFragmented) {
554-
ms.duration = info.fragment_duration / info.timescale;
554+
ms.duration = info.fragment_duration.num / info.fragment_duration.den;
555555
} else {
556556
ms.duration = info.duration / info.timescale;
557557
}

demo/movieInfoDisplay.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -294,9 +294,9 @@ function displayMovieInfo(info, div, _displaySourceBuffer) {
294294
if (info.isFragmented) {
295295
html +=
296296
'<tr><th>Fragmented duration</th><td>' +
297-
info.fragment_duration +
297+
info.fragment_duration.num +
298298
(info.fragment_duration
299-
? ' - ' + Log.getDurationString(info.fragment_duration, info.timescale)
299+
? ' - ' + Log.getDurationString(info.fragment_duration.num, info.fragment_duration.den)
300300
: '') +
301301
'</td></tr>';
302302
}

entries/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ export interface Movie {
196196
brands: Array<string>;
197197
created: Date;
198198
duration: number;
199-
fragment_duration?: number;
199+
fragment_duration?: { num: number; den: number };
200200
hasIOD: boolean;
201201
hintTracks: Array<Track>;
202202
isFragmented: boolean;

src/isofile.ts

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,36 @@ export class ISOFile<TSegmentUser = unknown, TSampleUser = unknown> {
577577
return nextFileStart;
578578
}
579579

580+
getFragmentDuration() {
581+
const mvex = this.getBox('mvex');
582+
if (!mvex) return;
583+
584+
// Use mehd if available
585+
if (mvex.mehd) {
586+
return {
587+
num: mvex.mehd.fragment_duration,
588+
den: this.moov.mvhd.timescale,
589+
};
590+
}
591+
592+
// Find the longest track
593+
const traks = this.getBoxes('trak', false);
594+
let maximum = { num: 0, den: 1 };
595+
596+
for (const trak of traks) {
597+
const duration = trak.samples_duration;
598+
const timescale = trak.mdia.mdhd.timescale;
599+
if (duration && timescale) {
600+
const ratio = duration / timescale;
601+
if (ratio > maximum.num / maximum.den) {
602+
maximum = { num: duration, den: timescale };
603+
}
604+
}
605+
}
606+
607+
return maximum;
608+
}
609+
580610
getInfo(): Movie {
581611
if (!this.moov) {
582612
return {
@@ -586,14 +616,14 @@ export class ISOFile<TSegmentUser = unknown, TSampleUser = unknown> {
586616
}
587617

588618
const _1904 = new Date('1904-01-01T00:00:00Z').getTime();
589-
const isFragmented = this.moov.mvex?.mehd !== undefined;
619+
const isFragmented = this.getBox('mvex') !== undefined;
590620

591621
const movie: Movie = {
592622
hasMoov: true,
593623
duration: this.moov.mvhd.duration,
594624
timescale: this.moov.mvhd.timescale,
595625
isFragmented,
596-
fragment_duration: isFragmented ? this.moov.mvex.mehd.fragment_duration : undefined,
626+
fragment_duration: this.getFragmentDuration(),
597627
isProgressive: this.isProgressive,
598628
hasIOD: this.moov.iods !== undefined,
599629
brands: [this.ftyp.major_brand].concat(this.ftyp.compatible_brands),

0 commit comments

Comments
 (0)