diff --git a/package-lock.json b/package-lock.json index 51bdd32..f2a5af9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediabunny", - "version": "1.4.2", + "version": "1.4.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "mediabunny", - "version": "1.4.2", + "version": "1.4.3", "license": "MPL-2.0", "dependencies": { "@types/dom-mediacapture-transform": "^0.1.11", diff --git a/package.json b/package.json index 1694167..6d9d8d3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mediabunny", "author": "Vanilagy", - "version": "1.4.2", + "version": "1.4.3", "description": "Pure TypeScript media toolkit for reading, writing, and converting media files, directly in the browser.", "type": "module", "main": "./dist/bundles/mediabunny.cjs", diff --git a/src/matroska/matroska-demuxer.ts b/src/matroska/matroska-demuxer.ts index da84f42..95392a6 100644 --- a/src/matroska/matroska-demuxer.ts +++ b/src/matroska/matroska-demuxer.ts @@ -220,13 +220,16 @@ export class MatroskaDemuxer extends Demuxer { const fileSize = await this.input.source.getSize(); + // Loop over all top-level elements in the file while (this.metadataReader.pos <= fileSize - MIN_HEADER_SIZE) { await this.metadataReader.reader.loadRange( this.metadataReader.pos, this.metadataReader.pos + MAX_HEADER_SIZE, ); - const { id, size } = this.metadataReader.readElementHeader(); + const header = this.metadataReader.readElementHeader(); + const id = header.id; + let size = header.size; const startPos = this.metadataReader.pos; if (id === EBMLId.EBML) { @@ -242,6 +245,26 @@ export class MatroskaDemuxer extends Demuxer { // and only segment break; } + } else if (id === EBMLId.Cluster) { + // Clusters are not a top-level element in Matroska, but some files contain a Segment whose size + // doesn't contain any of the clusters that follow it. In the case, we apply the following logic: if + // we find a top-level cluster, attribute it to the previous segment. + + if (size === null) { + // Just in case this is one of those weird sizeless clusters, let's do our best and still try to + // determine its size. + const nextElementPos = await this.clusterReader.searchForNextElementId( + LEVEL_0_AND_1_EBML_IDS, + fileSize, + ); + size = (nextElementPos ?? fileSize) - startPos; + } + + const lastSegment = last(this.segments); + if (lastSegment) { + // Extend the previous segment's size + lastSegment.elementEndPos = startPos + size; + } } assertDefinedSize(size);