From 87ed3a1934edc03f194fc727c3c187220199e966 Mon Sep 17 00:00:00 2001 From: Vanilagy <1696106+Vanilagy@users.noreply.github.com> Date: Thu, 12 Mar 2026 21:43:14 +0100 Subject: [PATCH 1/3] Fix faulty MPEG-2 detection (fixes #322) --- src/input-format.ts | 2 +- src/mpeg-ts/mpeg-ts-demuxer.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/input-format.ts b/src/input-format.ts index ed09428..5506af8 100644 --- a/src/input-format.ts +++ b/src/input-format.ts @@ -530,7 +530,7 @@ export class MpegTsInputFormat extends InputFormat { } else if (bytes[0] === 0x47 && bytes[TS_PACKET_SIZE + 16] === 0x47) { // MPEG-TS with Forward Error Correction return true; - } else if (bytes[4] === 0x47 && bytes[4 + TS_PACKET_SIZE] === 0x47) { + } else if (bytes[4] === 0x47 && bytes[4 + TS_PACKET_SIZE + 4] === 0x47) { // MPEG-2-TS (DVHS) return true; } diff --git a/src/mpeg-ts/mpeg-ts-demuxer.ts b/src/mpeg-ts/mpeg-ts-demuxer.ts index 253e8de..be61c08 100644 --- a/src/mpeg-ts/mpeg-ts-demuxer.ts +++ b/src/mpeg-ts/mpeg-ts-demuxer.ts @@ -161,10 +161,10 @@ export class MpegTsDemuxer extends Demuxer { // MPEG-TS with Forward Error Correction this.packetOffset = 0; this.packetStride = TS_PACKET_SIZE + 16; - } else if (startingBytes[4] === 0x47 && startingBytes[4 + TS_PACKET_SIZE] === 0x47) { + } else if (startingBytes[4] === 0x47 && startingBytes[4 + TS_PACKET_SIZE + 4] === 0x47) { // MPEG-2-TS (DVHS) this.packetOffset = 4; - this.packetStride = TS_PACKET_SIZE; + this.packetStride = TS_PACKET_SIZE + 4; } else { throw new Error('Unreachable.'); } From 35e16ca23e0af9d3927f2edaa8b396b4b3a29f20 Mon Sep 17 00:00:00 2001 From: Vanilagy <1696106+Vanilagy@users.noreply.github.com> Date: Fri, 13 Mar 2026 10:45:34 +0100 Subject: [PATCH 2/3] Fix incorrect GOP timestamp verification logic for first GOP (fixes #321) --- dev/convert.html | 2 +- dev/demux.html | 6 +++++- src/muxer.ts | 39 +++++++++++++++++++++------------------ 3 files changed, 27 insertions(+), 20 deletions(-) diff --git a/dev/convert.html b/dev/convert.html index 9f18bfd..658b6b4 100644 --- a/dev/convert.html +++ b/dev/convert.html @@ -189,7 +189,7 @@ }, trim: { //start: 0, - //end: 10 + end: 10 }, }); console.log(conversion); diff --git a/dev/demux.html b/dev/demux.html index baa5541..3b87013 100644 --- a/dev/demux.html +++ b/dev/demux.html @@ -21,7 +21,11 @@ const sink = new Mediabunny.EncodedPacketSink(videoTrack); for await (const packet of sink.packets()) { - console.log(packet.timestamp); + console.log(packet.type, packet.timestamp); + + if (packet.timestamp >= 5) { + break; + } } /* diff --git a/src/muxer.ts b/src/muxer.ts index ee0e7bd..83def00 100644 --- a/src/muxer.ts +++ b/src/muxer.ts @@ -46,12 +46,16 @@ export abstract class Muxer { private trackTimestampInfo = new WeakMap(); protected validateAndNormalizeTimestamp(track: OutputTrack, timestampInSeconds: number, isKeyPacket: boolean) { timestampInSeconds += track.source._timestampOffset; + if (timestampInSeconds < 0) { + throw new Error(`Timestamps must be non-negative (got ${timestampInSeconds}s).`); + } + let timestampInfo = this.trackTimestampInfo.get(track); if (!timestampInfo) { if (!isKeyPacket) { @@ -60,29 +64,28 @@ export abstract class Muxer { timestampInfo = { maxTimestamp: timestampInSeconds, - maxTimestampBeforeLastKeyPacket: timestampInSeconds, + maxTimestampBeforeLastKeyPacket: null, }; this.trackTimestampInfo.set(track, timestampInfo); - } + } else { + if (isKeyPacket) { + timestampInfo.maxTimestampBeforeLastKeyPacket = timestampInfo.maxTimestamp; + } - if (timestampInSeconds < 0) { - throw new Error(`Timestamps must be non-negative (got ${timestampInSeconds}s).`); - } + if ( + timestampInfo.maxTimestampBeforeLastKeyPacket !== null + && timestampInSeconds < timestampInfo.maxTimestampBeforeLastKeyPacket + ) { + throw new Error( + `Timestamps cannot be smaller than the largest timestamp of the previous GOP (a GOP begins with a` + + ` key packet and ends right before the next key packet). Got ${timestampInSeconds}s, but largest` + + ` timestamp is ${timestampInfo.maxTimestampBeforeLastKeyPacket}s.`, + ); + } - if (isKeyPacket) { - timestampInfo.maxTimestampBeforeLastKeyPacket = timestampInfo.maxTimestamp; + timestampInfo.maxTimestamp = Math.max(timestampInfo.maxTimestamp, timestampInSeconds); } - if (timestampInSeconds < timestampInfo.maxTimestampBeforeLastKeyPacket) { - throw new Error( - `Timestamps cannot be smaller than the largest timestamp of the previous GOP (a GOP begins with a key` - + ` packet and ends right before the next key packet). Got ${timestampInSeconds}s, but largest` - + ` timestamp is ${timestampInfo.maxTimestampBeforeLastKeyPacket}s.`, - ); - } - - timestampInfo.maxTimestamp = Math.max(timestampInfo.maxTimestamp, timestampInSeconds); - return timestampInSeconds; } } From 92ea645df41f6858a35a004233b6c9d6d25c0420 Mon Sep 17 00:00:00 2001 From: Vanilagy <1696106+Vanilagy@users.noreply.github.com> Date: Fri, 13 Mar 2026 11:03:57 +0100 Subject: [PATCH 3/3] Bump patch --- package-lock.json | 18 +++++++++--------- package.json | 2 +- packages/aac-encoder/package.json | 2 +- packages/ac3/package.json | 2 +- packages/flac-encoder/package.json | 2 +- packages/mp3-encoder/package.json | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/package-lock.json b/package-lock.json index fc5f586..f003e96 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediabunny", - "version": "1.39.1", + "version": "1.39.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "mediabunny", - "version": "1.39.1", + "version": "1.39.2", "license": "MPL-2.0", "workspaces": [ "packages/*" @@ -7751,9 +7751,9 @@ } }, "node_modules/mediabunny": { - "version": "1.39.0", - "resolved": "https://registry.npmjs.org/mediabunny/-/mediabunny-1.39.0.tgz", - "integrity": "sha512-NDeht2Sf7kYfrUu7b/9AhVK4KdQhy6UeTF/EPNXW+PdpIYvSv36ZQ/SRBoFAJN2LRl6XrGb8JYY4MCnhsGQ2yg==", + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/mediabunny/-/mediabunny-1.39.1.tgz", + "integrity": "sha512-gaQKDWtfLhgSN9tRj37lgznHf9MOvey7sbT6GdQA7mWl1kaE5R+P1lfl9CDsgtzongx12IG9X/y2vgZmTHzGDg==", "license": "MPL-2.0", "peer": true, "workspaces": [ @@ -12077,7 +12077,7 @@ }, "packages/aac-encoder": { "name": "@mediabunny/aac-encoder", - "version": "1.39.1", + "version": "1.39.2", "license": "MPL-2.0", "devDependencies": { "@types/emscripten": "^1.40.1" @@ -12092,7 +12092,7 @@ }, "packages/ac3": { "name": "@mediabunny/ac3", - "version": "1.39.1", + "version": "1.39.2", "license": "MPL-2.0", "devDependencies": { "@types/emscripten": "^1.40.1" @@ -12107,7 +12107,7 @@ }, "packages/flac-encoder": { "name": "@mediabunny/flac-encoder", - "version": "1.39.1", + "version": "1.39.2", "license": "MPL-2.0", "devDependencies": { "@types/emscripten": "^1.40.1" @@ -12122,7 +12122,7 @@ }, "packages/mp3-encoder": { "name": "@mediabunny/mp3-encoder", - "version": "1.39.1", + "version": "1.39.2", "license": "MPL-2.0", "devDependencies": { "@types/emscripten": "^1.40.1" diff --git a/package.json b/package.json index bd6102e..4fb193f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mediabunny", "author": "Vanilagy", - "version": "1.39.1", + "version": "1.39.2", "description": "Pure TypeScript media toolkit for reading, writing, and converting media files, directly in the browser.", "type": "module", "workspaces": [ diff --git a/packages/aac-encoder/package.json b/packages/aac-encoder/package.json index 0bec4d0..faa9753 100644 --- a/packages/aac-encoder/package.json +++ b/packages/aac-encoder/package.json @@ -1,7 +1,7 @@ { "name": "@mediabunny/aac-encoder", "author": "Vanilagy", - "version": "1.39.1", + "version": "1.39.2", "description": "AAC encoder extension for Mediabunny, based on FFmpeg.", "main": "./dist/bundles/mediabunny-aac-encoder.mjs", "module": "./dist/bundles/mediabunny-aac-encoder.mjs", diff --git a/packages/ac3/package.json b/packages/ac3/package.json index 659bc06..bd5b58c 100644 --- a/packages/ac3/package.json +++ b/packages/ac3/package.json @@ -1,7 +1,7 @@ { "name": "@mediabunny/ac3", "author": "Vanilagy", - "version": "1.39.1", + "version": "1.39.2", "description": "AC-3 and E-AC-3 (Dolby Digital) decoder and encoder extension for Mediabunny, based on FFmpeg.", "main": "./dist/bundles/mediabunny-ac3.mjs", "module": "./dist/bundles/mediabunny-ac3.mjs", diff --git a/packages/flac-encoder/package.json b/packages/flac-encoder/package.json index 2a09cca..fe3aac3 100644 --- a/packages/flac-encoder/package.json +++ b/packages/flac-encoder/package.json @@ -1,7 +1,7 @@ { "name": "@mediabunny/flac-encoder", "author": "Vanilagy", - "version": "1.39.1", + "version": "1.39.2", "description": "FLAC encoder extension for Mediabunny, based on libFLAC.", "main": "./dist/bundles/mediabunny-flac-encoder.mjs", "module": "./dist/bundles/mediabunny-flac-encoder.mjs", diff --git a/packages/mp3-encoder/package.json b/packages/mp3-encoder/package.json index 531f3f0..522f6a3 100644 --- a/packages/mp3-encoder/package.json +++ b/packages/mp3-encoder/package.json @@ -1,7 +1,7 @@ { "name": "@mediabunny/mp3-encoder", "author": "Vanilagy", - "version": "1.39.1", + "version": "1.39.2", "description": "MP3 encoder extension for Mediabunny, based on LAME.", "main": "./dist/bundles/mediabunny-mp3-encoder.mjs", "module": "./dist/bundles/mediabunny-mp3-encoder.mjs",