Add special top-level Cluster logic for Matroska demuxer

This commit is contained in:
Vanilagy
2025-07-28 12:03:19 +02:00
parent 72ed933bf4
commit 95091cce9c
3 changed files with 27 additions and 4 deletions
+2 -2
View File
@@ -1,12 +1,12 @@
{ {
"name": "mediabunny", "name": "mediabunny",
"version": "1.4.2", "version": "1.4.3",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "mediabunny", "name": "mediabunny",
"version": "1.4.2", "version": "1.4.3",
"license": "MPL-2.0", "license": "MPL-2.0",
"dependencies": { "dependencies": {
"@types/dom-mediacapture-transform": "^0.1.11", "@types/dom-mediacapture-transform": "^0.1.11",
+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"name": "mediabunny", "name": "mediabunny",
"author": "Vanilagy", "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.", "description": "Pure TypeScript media toolkit for reading, writing, and converting media files, directly in the browser.",
"type": "module", "type": "module",
"main": "./dist/bundles/mediabunny.cjs", "main": "./dist/bundles/mediabunny.cjs",
+24 -1
View File
@@ -220,13 +220,16 @@ export class MatroskaDemuxer extends Demuxer {
const fileSize = await this.input.source.getSize(); const fileSize = await this.input.source.getSize();
// Loop over all top-level elements in the file
while (this.metadataReader.pos <= fileSize - MIN_HEADER_SIZE) { while (this.metadataReader.pos <= fileSize - MIN_HEADER_SIZE) {
await this.metadataReader.reader.loadRange( await this.metadataReader.reader.loadRange(
this.metadataReader.pos, this.metadataReader.pos,
this.metadataReader.pos + MAX_HEADER_SIZE, 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; const startPos = this.metadataReader.pos;
if (id === EBMLId.EBML) { if (id === EBMLId.EBML) {
@@ -242,6 +245,26 @@ export class MatroskaDemuxer extends Demuxer {
// and only segment // and only segment
break; 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); assertDefinedSize(size);