From ae0266df52b1930320a4f04824c757a689746107 Mon Sep 17 00:00:00 2001 From: Vanilagy <1696106+Vanilagy@users.noreply.github.com> Date: Mon, 11 Aug 2025 18:41:15 +0200 Subject: [PATCH 1/4] Clarify decode order thing for encoded packet sources --- src/media-source.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/media-source.ts b/src/media-source.ts index 2ae14db..3860552 100644 --- a/src/media-source.ts +++ b/src/media-source.ts @@ -158,7 +158,8 @@ export class EncodedVideoPacketSource extends VideoSource { } /** - * Adds an encoded packet to the output video track. + * Adds an encoded packet to the output video track. Packets must be added in *decode order*, while a packet's + * timestamp must be its *presentation timestamp*. B-frames are handled automatically. * * @param meta - Additional metadata from the encoder. You should pass this for the first call, including a valid * decoder config. @@ -788,7 +789,7 @@ export class EncodedAudioPacketSource extends AudioSource { } /** - * Adds an encoded packet to the output audio track. + * Adds an encoded packet to the output audio track. Packets must be added in *decode order*. * * @param meta - Additional metadata from the encoder. You should pass this for the first call, including a valid * decoder config. From c9dcebed6f28a5195cc4cc3c2c4f15520d4fe454 Mon Sep 17 00:00:00 2001 From: Vanilagy <1696106+Vanilagy@users.noreply.github.com> Date: Tue, 12 Aug 2025 08:53:25 +0200 Subject: [PATCH 2/4] Skip zero-length AudioSamples --- src/media-sink.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/media-sink.ts b/src/media-sink.ts index aec70e7..6c4de94 100644 --- a/src/media-sink.ts +++ b/src/media-sink.ts @@ -1248,9 +1248,15 @@ class AudioDecoderWrapper extends DecoderWrapper { super(onSample, onError); const sampleHandler = (sample: AudioSample) => { - const sampleRate = decoderConfig.sampleRate; + if (sample.numberOfFrames === 0) { + // We skip zero-data (empty) AudioSamples. These are sometimes emitted, for example, by Firefox when it + // decodes Vorbis (at the start). + sample.close(); + return; + } // Round the timestamp to the sample rate + const sampleRate = decoderConfig.sampleRate; sample.setTimestamp(Math.round(sample.timestamp * sampleRate) / sampleRate); onSample(sample); From e0a4169bf888bdb9b331d98403f0edb3c1027262 Mon Sep 17 00:00:00 2001 From: Vanilagy <1696106+Vanilagy@users.noreply.github.com> Date: Tue, 12 Aug 2025 09:29:57 +0200 Subject: [PATCH 3/4] Handle missing starting key sample in ISOBMFF --- dev/demux.html | 18 +++++++++--------- src/isobmff/isobmff-demuxer.ts | 6 ++++++ 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/dev/demux.html b/dev/demux.html index c9c5fd5..04d1e43 100644 --- a/dev/demux.html +++ b/dev/demux.html @@ -8,15 +8,6 @@ document.body.append(fileInput); fileInput.addEventListener('change', async () => { - const videoUrl = "https://upload.wikimedia.org/wikipedia/commons/5/53/1941._%D0%9A%D0%BE%D0%BD%D1%91%D0%BA-%D0%B3%D0%BE%D1%80%D0%B1%D1%83%D0%BD%D0%BE%D0%BA.webm" - const source = new Mediabunny.UrlSource(videoUrl) - const input = new Mediabunny.Input({ formats: Mediabunny.ALL_FORMATS, source }); - - const videoTrack = await input.getPrimaryVideoTrack(); - - console.log(videoTrack); - - /* const file = fileInput.files[0]; const source = new Mediabunny.BlobSource(file); @@ -25,6 +16,15 @@ source }); + const videoTrack = await input.getPrimaryVideoTrack(); + const sink = new Mediabunny.EncodedPacketSink(videoTrack); + + for await (const packet of sink.packets(undefined, undefined, { verifyKeyPackets: false })) { + console.log(packet); + if (packet.timestamp >= 2.4) break; + } + + /* const audioTrack = await input.getPrimaryAudioTrack(); const sink = new Mediabunny.EncodedPacketSink(audioTrack); diff --git a/src/isobmff/isobmff-demuxer.ts b/src/isobmff/isobmff-demuxer.ts index 20bcf42..80c1dc2 100644 --- a/src/isobmff/isobmff-demuxer.ts +++ b/src/isobmff/isobmff-demuxer.ts @@ -1459,6 +1459,12 @@ export class IsobmffDemuxer extends Demuxer { const sampleIndex = this.metadataReader.readU32() - 1; // Convert to 0-indexed track.sampleTable.keySampleIndices.push(sampleIndex); } + + if (track.sampleTable.keySampleIndices[0] !== 0) { + // Some files don't mark the first sample a key sample, which is basically almost always incorrect. + // Here, we correct for that mistake: + track.sampleTable.keySampleIndices.unshift(0); + } }; break; case 'stsc': { From 7e89511ca6466e0d79ef3fe27542e028f491fa3e Mon Sep 17 00:00:00 2001 From: Vanilagy <1696106+Vanilagy@users.noreply.github.com> Date: Tue, 12 Aug 2025 10:09:34 +0200 Subject: [PATCH 4/4] Bump patch --- package-lock.json | 12 ++++++------ package.json | 2 +- packages/mp3-encoder/package.json | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7ea184f..0655037 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediabunny", - "version": "1.7.1", + "version": "1.7.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "mediabunny", - "version": "1.7.1", + "version": "1.7.2", "license": "MPL-2.0", "workspaces": [ "packages/*" @@ -5900,9 +5900,9 @@ } }, "node_modules/mediabunny": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/mediabunny/-/mediabunny-1.7.0.tgz", - "integrity": "sha512-QcTdptOtvjAHb4KQpgWWWHRS0+DgGwTXelTwPWaZwQu85iYy11bzsLS4e29rfH4nLL/eq8K/dBsjj1LuApc2Qw==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/mediabunny/-/mediabunny-1.7.1.tgz", + "integrity": "sha512-y9s+Vf6TLhXeVjvlJFSmHRrwUQi2CJCMhxthm6nfhBO1XHJhcOqNOxu4CjhYyjoWgVZB5pkPKyWgZxpPOZfglQ==", "license": "MPL-2.0", "peer": true, "workspaces": [ @@ -9017,7 +9017,7 @@ }, "packages/mp3-encoder": { "name": "@mediabunny/mp3-encoder", - "version": "1.7.1", + "version": "1.7.2", "license": "MPL-2.0", "devDependencies": { "@types/emscripten": "^1.40.1" diff --git a/package.json b/package.json index 327ea65..709c529 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mediabunny", "author": "Vanilagy", - "version": "1.7.1", + "version": "1.7.2", "description": "Pure TypeScript media toolkit for reading, writing, and converting media files, directly in the browser.", "type": "module", "workspaces": [ diff --git a/packages/mp3-encoder/package.json b/packages/mp3-encoder/package.json index 5b2b163..14f4776 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.7.1", + "version": "1.7.2", "description": "MP3 encoder extension for Mediabunny, based on LAME.", "main": "./dist/bundles/mediabunny-mp3-encoder.mjs", "module": "./dist/bundles/mediabunny-mp3-encoder.mjs",