From 53824536fabe71d34b6fe9dd797f3c2298f810d2 Mon Sep 17 00:00:00 2001 From: Vanilagy <1696106+Vanilagy@users.noreply.github.com> Date: Tue, 6 Jan 2026 13:35:52 +0100 Subject: [PATCH 01/18] Remove packet iteration upper bound for mediaSamplesInRange (fixes #269) --- src/media-sink.ts | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/src/media-sink.ts b/src/media-sink.ts index 539606e..1ca7c1c 100644 --- a/src/media-sink.ts +++ b/src/media-sink.ts @@ -480,23 +480,13 @@ export abstract class BaseMediaSampleSink< let currentPacket: EncodedPacket | null = keyPacket; - let endPacket: EncodedPacket | undefined = undefined; - if (endTimestamp < Infinity) { - // When an end timestamp is set, we cannot simply use that for the packet iterator due to out-of-order - // frames (B-frames). Instead, we'll need to keep decoding packets until we get a frame that exceeds - // this end time. However, we can still put a bound on it: Since key frames are by definition never - // out of order, we can stop at the first key frame after the end timestamp. - const packet = await packetSink.getPacket(endTimestamp); - const keyPacket = !packet - ? null - : packet.type === 'key' && packet.timestamp === endTimestamp - ? packet - : await packetSink.getNextKeyPacket(packet, { verifyKeyPackets: true }); - - if (keyPacket) { - endPacket = keyPacket; - } - } + // B-frames make it exceedingly difficult to properly define an upper bound for packet iteration if an end + // timestamp is set, so we just don't do it. The case that makes it especially tricky is when the frames + // following a key frame have a lower timestamp than the keyframe; something that quite frequently happens + // in HEVC streams. The price to pay for not upper-bounding the packet iterator is a slight increase in + // decoder work at the end of the range, but the added correctness and reliability makes this tradeoff worth + // it. + const endPacket = undefined; const packets = packetSink.packets(keyPacket ?? undefined, endPacket); await packets.next(); // Skip the start packet as we already have it From 7580935639ad4fc50e5e4f742427f4de34dc70b4 Mon Sep 17 00:00:00 2001 From: Vanilagy <1696106+Vanilagy@users.noreply.github.com> Date: Tue, 6 Jan 2026 13:36:29 +0100 Subject: [PATCH 02/18] 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 62971f4..6c803d8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediabunny", - "version": "1.27.3", + "version": "1.27.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "mediabunny", - "version": "1.27.3", + "version": "1.27.4", "license": "MPL-2.0", "workspaces": [ "packages/*" @@ -7739,9 +7739,9 @@ } }, "node_modules/mediabunny": { - "version": "1.27.2", - "resolved": "https://registry.npmjs.org/mediabunny/-/mediabunny-1.27.2.tgz", - "integrity": "sha512-0g/vmb6X0xmnzqW0U44weF9CmzcUFFQRHrjzoVpSL2KXuhWIWcW3u9wIcohHiTY78jfr0SauYKLxjOQReaMxXQ==", + "version": "1.27.3", + "resolved": "https://registry.npmjs.org/mediabunny/-/mediabunny-1.27.3.tgz", + "integrity": "sha512-hlzmgzMznp9DhA5fMJKS5yEAyfCUMxAc+DbSPxD4J1J2cYVl1L+pZLndkt5xLlD5aB5eHEnphHMW14ammMlUXg==", "license": "MPL-2.0", "peer": true, "workspaces": [ @@ -12065,7 +12065,7 @@ }, "packages/mp3-encoder": { "name": "@mediabunny/mp3-encoder", - "version": "1.27.3", + "version": "1.27.4", "license": "MPL-2.0", "devDependencies": { "@types/emscripten": "^1.40.1" diff --git a/package.json b/package.json index c03709d..94043f6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mediabunny", "author": "Vanilagy", - "version": "1.27.3", + "version": "1.27.4", "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 b416c9b..cc1be31 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.27.3", + "version": "1.27.4", "description": "MP3 encoder extension for Mediabunny, based on LAME.", "main": "./dist/bundles/mediabunny-mp3-encoder.mjs", "module": "./dist/bundles/mediabunny-mp3-encoder.mjs", From d29f4f33b508a7a753562032fb90e57aef22bcc4 Mon Sep 17 00:00:00 2001 From: Alakh Chandarana <36898190+alakhpc@users.noreply.github.com> Date: Sun, 11 Jan 2026 04:05:55 -0500 Subject: [PATCH 03/18] implement fix --- src/matroska/matroska-demuxer.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/matroska/matroska-demuxer.ts b/src/matroska/matroska-demuxer.ts index db421b6..965ccf8 100644 --- a/src/matroska/matroska-demuxer.ts +++ b/src/matroska/matroska-demuxer.ts @@ -193,6 +193,7 @@ type InternalTrack = { codecId: string | null; codecPrivate: Uint8Array | null; defaultDuration: number | null; + defaultDurationNs: number | null; name: string | null; languageCode: string; decodingInstructions: DecodingInstruction[]; @@ -536,6 +537,13 @@ export class MatroskaDemuxer extends Demuxer { this.currentSegment.timestampFactor = 1e9 / 1e6; } + // Compute default duration for all tracks now that we have the timestamp factor + for (const track of this.currentSegment.tracks) { + if (track.defaultDurationNs !== null) { + track.defaultDuration = (this.currentSegment.timestampFactor * track.defaultDurationNs) / 1e9; + } + } + // Put default tracks first this.currentSegment.tracks.sort((a, b) => Number(b.disposition.default) - Number(a.disposition.default)); @@ -996,6 +1004,7 @@ export class MatroskaDemuxer extends Demuxer { codecId: null, codecPrivate: null, defaultDuration: null, + defaultDurationNs: null, name: null, languageCode: UNDETERMINED_LANGUAGE, decodingInstructions: [], @@ -1203,9 +1212,7 @@ export class MatroskaDemuxer extends Demuxer { case EBMLId.DefaultDuration: { if (!this.currentTrack) break; - - this.currentTrack.defaultDuration - = this.currentTrack.segment.timestampFactor * readUnsignedInt(slice, size) / 1e9; + this.currentTrack.defaultDurationNs = readUnsignedInt(slice, size); }; break; case EBMLId.Name: { From 91e7812fb23c59f87dc79dd5798edf9b61aad422 Mon Sep 17 00:00:00 2001 From: Alakh Chandarana <36898190+alakhpc@users.noreply.github.com> Date: Sun, 11 Jan 2026 16:45:18 -0500 Subject: [PATCH 04/18] fix --- src/input-format.ts | 5 +- src/matroska/ebml.ts | 108 +++++++++++++++++++++++-------- src/matroska/matroska-demuxer.ts | 4 +- 3 files changed, 85 insertions(+), 32 deletions(-) diff --git a/src/input-format.ts b/src/input-format.ts index 1748f27..1c0e292 100644 --- a/src/input-format.ts +++ b/src/input-format.ts @@ -154,10 +154,11 @@ export class MatroskaInputFormat extends InputFormat { return false; } - const dataSize = readElementSize(headerSlice); - if (dataSize === null) { + const dataSizeResult = readElementSize(headerSlice); + if (dataSizeResult === null || dataSizeResult.size === null) { return false; // Miss me with that shit } + const dataSize = dataSizeResult.size; let dataSlice = input._reader.requestSlice(headerSlice.filePos, dataSize); if (dataSlice instanceof Promise) dataSlice = await dataSlice; diff --git a/src/matroska/ebml.ts b/src/matroska/ebml.ts index eb27c40..0df632d 100644 --- a/src/matroska/ebml.ts +++ b/src/matroska/ebml.ts @@ -470,6 +470,11 @@ export const MIN_HEADER_SIZE = 2; // 1-byte ID and 1-byte size export const MAX_HEADER_SIZE = 2 * MAX_VAR_INT_SIZE; // 8-byte ID and 8-byte size export const readVarIntSize = (slice: FileSlice) => { + // Check if we have at least one byte to read + if (slice.remainingLength < 1) { + return null; + } + const firstByte = readU8(slice); slice.skip(-1); @@ -484,10 +489,20 @@ export const readVarIntSize = (slice: FileSlice) => { mask >>= 1; } + // Check if we have enough bytes to read the full varint + if (slice.remainingLength < width) { + return null; + } + return width; }; export const readVarInt = (slice: FileSlice) => { + // Check if we have at least one byte + if (slice.remainingLength < 1) { + return null; + } + // Read the first byte to determine the width of the variable-length integer const firstByte = readU8(slice); @@ -503,6 +518,13 @@ export const readVarInt = (slice: FileSlice) => { mask >>= 1; } + // Check if we have enough bytes remaining for the full varint + if (slice.remainingLength < width - 1) { + // Not enough bytes, rewind and return null + slice.skip(-1); + return null; + } + // First byte's value needs the marker bit cleared let value = firstByte & (mask - 1); @@ -567,37 +589,69 @@ export const readElementId = (slice: FileSlice) => { return id; }; -export const readElementSize = (slice: FileSlice) => { - let size: number | null = readU8(slice); - - if (size === 0xff) { - size = null; - } else { - slice.skip(-1); - size = readVarInt(slice); - - // In some (livestreamed) files, this is the value of the size field. While this technically is just a very - // large number, it is intended to behave like the reserved size 0xFF, meaning the size is undefined. We - // catch the number here. Note that it cannot be perfectly represented as a double, but the comparison works - // nonetheless. - // eslint-disable-next-line no-loss-of-precision - if (size === 0x00ffffffffffffff) { - size = null; - } - } - - return size; -}; - -export const readElementHeader = (slice: FileSlice) => { - const id = readElementId(slice); - if (id === null) { +/** + * Reads the size field of an EBML element. + * + * @returns + * - `{ size: number }` - Successfully read a definite size + * - `{ size: null }` - Successfully read an undefined size (0xFF marker, used in streaming) + * - `null` - Couldn't read (insufficient bytes or invalid data) + */ +export const readElementSize = (slice: FileSlice): { size: number | null } | null => { + // Need at least 1 byte to read the size + if (slice.remainingLength < 1) { return null; } - const size = readElementSize(slice); + const firstByte = readU8(slice); - return { id, size }; + if (firstByte === 0xff) { + // Legitimate undefined size marker + return { size: null }; + } + + slice.skip(-1); + const size = readVarInt(slice); + + if (size === null) { + // Couldn't read the varint (insufficient bytes or invalid) + return null; + } + + // In some (livestreamed) files, this is the value of the size field. While this technically is just a very + // large number, it is intended to behave like the reserved size 0xFF, meaning the size is undefined. We + // catch the number here. Note that it cannot be perfectly represented as a double, but the comparison works + // nonetheless. + // eslint-disable-next-line no-loss-of-precision + if (size === 0x00ffffffffffffff) { + return { size: null }; + } + + return { size }; +}; + +export const readElementHeader = (slice: FileSlice) => { + // We need at least MIN_HEADER_SIZE bytes to read a header + if (slice.remainingLength < MIN_HEADER_SIZE) { + return null; + } + + const startPos = slice.filePos; + + const id = readElementId(slice); + if (id === null) { + slice.filePos = startPos; + return null; + } + + const sizeResult = readElementSize(slice); + if (sizeResult === null) { + // Couldn't read size - rewind to start + slice.filePos = startPos; + return null; + } + + return { id, size: sizeResult.size }; }; export const readAsciiString = (slice: FileSlice, length: number) => { diff --git a/src/matroska/matroska-demuxer.ts b/src/matroska/matroska-demuxer.ts index db421b6..ab2db28 100644 --- a/src/matroska/matroska-demuxer.ts +++ b/src/matroska/matroska-demuxer.ts @@ -908,9 +908,7 @@ export class MatroskaDemuxer extends Demuxer { } readContiguousElements(slice: FileSlice, stopIds?: number[]) { - const startIndex = slice.filePos; - - while (slice.filePos - startIndex <= slice.length - MIN_HEADER_SIZE) { + while (slice.remainingLength >= MIN_HEADER_SIZE) { const startPos = slice.filePos; const foundElement = this.traverseElement(slice, stopIds); From 2bb84fd35b47135188c6f8f341547c08c220105c Mon Sep 17 00:00:00 2001 From: Vanilagy <1696106+Vanilagy@users.noreply.github.com> Date: Mon, 12 Jan 2026 10:32:43 +0100 Subject: [PATCH 05/18] Add new sponsors --- docs/index.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/index.md b/docs/index.md index c380cec..118e8ef 100644 --- a/docs/index.md +++ b/docs/index.md @@ -128,6 +128,8 @@ const sponsors = { { image: 'https://avatars.githubusercontent.com/u/3709646', name: 'Rodrigo Belfiore', url: 'https://github.com/roprgm' }, { image: 'https://avatars.githubusercontent.com/u/31102694', name: 'Aiden Liu', url: 'https://github.com/aidenlx' }, { image: 'https://avatars.githubusercontent.com/u/41021374', name: 'arthco', url: 'https://github.com/arthtyagi' }, + { image: 'https://avatars.githubusercontent.com/u/36898190', name: 'alakhpc', url: 'https://github.com/alakhpc' }, + { image: 'https://avatars.githubusercontent.com/u/5907357', name: 'Harvey Zhao', url: 'https://github.com/zhw2590582' }, ], }; From 7b036fe8ac12ee86b0bd5f0fb640eb6fff4d12c4 Mon Sep 17 00:00:00 2001 From: Vanilagy <1696106+Vanilagy@users.noreply.github.com> Date: Mon, 12 Jan 2026 11:59:37 +0100 Subject: [PATCH 06/18] Fix some things --- src/input-format.ts | 7 ++--- src/matroska/ebml.ts | 51 +++++++++++--------------------- src/matroska/matroska-demuxer.ts | 12 ++++---- 3 files changed, 26 insertions(+), 44 deletions(-) diff --git a/src/input-format.ts b/src/input-format.ts index 1c0e292..db1e5b7 100644 --- a/src/input-format.ts +++ b/src/input-format.ts @@ -154,11 +154,10 @@ export class MatroskaInputFormat extends InputFormat { return false; } - const dataSizeResult = readElementSize(headerSlice); - if (dataSizeResult === null || dataSizeResult.size === null) { + const dataSize = readElementSize(headerSlice); + if (typeof dataSize !== 'number') { return false; // Miss me with that shit } - const dataSize = dataSizeResult.size; let dataSlice = input._reader.requestSlice(headerSlice.filePos, dataSize); if (dataSlice instanceof Promise) dataSlice = await dataSlice; @@ -172,7 +171,7 @@ export class MatroskaInputFormat extends InputFormat { const { id, size } = header; const dataStartPos = dataSlice.filePos; - if (size === null) return false; + if (size === undefined) return false; switch (id) { case EBMLId.EBMLVersion: { diff --git a/src/matroska/ebml.ts b/src/matroska/ebml.ts index 0df632d..891adab 100644 --- a/src/matroska/ebml.ts +++ b/src/matroska/ebml.ts @@ -7,7 +7,7 @@ */ import { MediaCodec } from '../codec'; -import { assertNever, textDecoder, textEncoder } from '../misc'; +import { assert, assertNever, textDecoder, textEncoder } from '../misc'; import { FileSlice, readBytes, Reader, readF32Be, readF64Be, readU8 } from '../reader'; import { Writer } from '../writer'; @@ -470,7 +470,6 @@ export const MIN_HEADER_SIZE = 2; // 1-byte ID and 1-byte size export const MAX_HEADER_SIZE = 2 * MAX_VAR_INT_SIZE; // 8-byte ID and 8-byte size export const readVarIntSize = (slice: FileSlice) => { - // Check if we have at least one byte to read if (slice.remainingLength < 1) { return null; } @@ -498,7 +497,6 @@ export const readVarIntSize = (slice: FileSlice) => { }; export const readVarInt = (slice: FileSlice) => { - // Check if we have at least one byte if (slice.remainingLength < 1) { return null; } @@ -518,10 +516,8 @@ export const readVarInt = (slice: FileSlice) => { mask >>= 1; } - // Check if we have enough bytes remaining for the full varint if (slice.remainingLength < width - 1) { - // Not enough bytes, rewind and return null - slice.skip(-1); + // Not enough bytes return null; } @@ -585,19 +581,16 @@ export const readElementId = (slice: FileSlice) => { return null; } + if (slice.remainingLength < size) { + return null; // It don't fit + } + const id = readUnsignedInt(slice, size); return id; }; -/** - * Reads the size field of an EBML element. - * - * @returns - * - `{ size: number }` - Successfully read a definite size - * - `{ size: null }` - Successfully read an undefined size (0xFF marker, used in streaming) - * - `null` - Couldn't read (insufficient bytes or invalid data) - */ -export const readElementSize = (slice: FileSlice): { size: number | null } | null => { +/** Returns `undefined` to indicate the EBML undefined size. Returns `null` if the size couldn't be read. */ +export const readElementSize = (slice: FileSlice): number | undefined | null => { // Need at least 1 byte to read the size if (slice.remainingLength < 1) { return null; @@ -606,15 +599,13 @@ export const readElementSize = (slice: FileSlice): { size: number | null } | nul const firstByte = readU8(slice); if (firstByte === 0xff) { - // Legitimate undefined size marker - return { size: null }; + return undefined; } slice.skip(-1); const size = readVarInt(slice); if (size === null) { - // Couldn't read the varint (insufficient bytes or invalid) return null; } @@ -624,34 +615,26 @@ export const readElementSize = (slice: FileSlice): { size: number | null } | nul // nonetheless. // eslint-disable-next-line no-loss-of-precision if (size === 0x00ffffffffffffff) { - return { size: null }; + return undefined; } - return { size }; + return size; }; export const readElementHeader = (slice: FileSlice) => { - // We need at least MIN_HEADER_SIZE bytes to read a header - if (slice.remainingLength < MIN_HEADER_SIZE) { - return null; - } - - const startPos = slice.filePos; + assert(slice.remainingLength >= MIN_HEADER_SIZE); const id = readElementId(slice); if (id === null) { - slice.filePos = startPos; return null; } - const sizeResult = readElementSize(slice); - if (sizeResult === null) { - // Couldn't read size - rewind to start - slice.filePos = startPos; + const size = readElementSize(slice); + if (size === null) { return null; } - return { id, size: sizeResult.size }; + return { id, size }; }; export const readAsciiString = (slice: FileSlice, length: number) => { @@ -774,8 +757,8 @@ export const CODEC_STRING_MAP: Partial> = { 'webvtt': 'S_TEXT/WEBVTT', }; -export function assertDefinedSize(size: number | null): asserts size is number { - if (size === null) { +export function assertDefinedSize(size: number | undefined): asserts size is number { + if (size === undefined) { throw new Error('Undefined element size is used in a place where it is not supported.'); } }; diff --git a/src/matroska/matroska-demuxer.ts b/src/matroska/matroska-demuxer.ts index ab2db28..feffbff 100644 --- a/src/matroska/matroska-demuxer.ts +++ b/src/matroska/matroska-demuxer.ts @@ -364,7 +364,7 @@ export class MatroskaDemuxer extends Demuxer { // 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) { + if (size === undefined) { // 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 searchForNextElementId( @@ -389,7 +389,7 @@ export class MatroskaDemuxer extends Demuxer { })(); } - async readSegment(segmentDataStart: number, dataSize: number | null) { + async readSegment(segmentDataStart: number, dataSize: number | undefined) { this.currentSegment = { seekHeadSeen: false, infoSeen: false, @@ -406,7 +406,7 @@ export class MatroskaDemuxer extends Demuxer { cuePoints: [], dataStartPos: segmentDataStart, - elementEndPos: dataSize === null + elementEndPos: dataSize === undefined ? null // Assume it goes until the end of the file : segmentDataStart + dataSize, clusterSeekStartPos: segmentDataStart, @@ -483,7 +483,7 @@ export class MatroskaDemuxer extends Demuxer { break; // Stop at the first cluster } - if (size === null) { + if (size === undefined) { break; } else { currentPos = dataStartPos + size; @@ -606,7 +606,7 @@ export class MatroskaDemuxer extends Demuxer { let size = elementHeader.size; const dataStartPos = headerSlice.filePos; - if (size === null) { + if (size === undefined) { // The cluster's size is undefined (can happen in livestreamed files). We'd still like to know the size of // it, so we have no other choice but to iterate over the EBML structure until we find an element at level // 0 or 1, indicating the end of the cluster (all elements inside the cluster are at level 2). @@ -2220,7 +2220,7 @@ abstract class MatroskaTrackBacking implements InputTrackBacking { } } - if (size === null) { + if (size === undefined) { // Undefined element size (can happen in livestreamed files). In this case, we need to do some // searching to determine the actual size of the element. From d6b518b9fd6fe2442add14b64a1d0991812e96e0 Mon Sep 17 00:00:00 2001 From: Vanilagy <1696106+Vanilagy@users.noreply.github.com> Date: Mon, 12 Jan 2026 14:07:43 +0100 Subject: [PATCH 07/18] Fix thing --- src/matroska/matroska-demuxer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/matroska/matroska-demuxer.ts b/src/matroska/matroska-demuxer.ts index feffbff..2d7c9f9 100644 --- a/src/matroska/matroska-demuxer.ts +++ b/src/matroska/matroska-demuxer.ts @@ -346,7 +346,7 @@ export class MatroskaDemuxer extends Demuxer { } else if (id === EBMLId.Segment) { // Segment found! await this.readSegment(dataStartPos, size); - if (size === null) { + if (size === undefined) { // Segment sizes can be undefined (common in livestreamed files), so assume this is the last // and only segment break; From 78e78e5b4f3ff92603a01c540d7b7a9bbb694e65 Mon Sep 17 00:00:00 2001 From: Vanilagy <1696106+Vanilagy@users.noreply.github.com> Date: Mon, 12 Jan 2026 14:36:51 +0100 Subject: [PATCH 08/18] Make _flushOrWaitForOngoingClose set closingPromise (fixes #270) --- src/media-source.ts | 10 ++++----- test/browser/media-sources.test.ts | 35 ++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 6 deletions(-) create mode 100644 test/browser/media-sources.test.ts diff --git a/src/media-source.ts b/src/media-source.ts index 7b5cae6..ddf746b 100644 --- a/src/media-source.ts +++ b/src/media-source.ts @@ -134,12 +134,10 @@ export abstract class MediaSource { /** @internal */ async _flushOrWaitForOngoingClose(forceClose: boolean) { - if (this._closingPromise) { - // Since closing also flushes, we don't want to do it twice - return this._closingPromise; - } else { - return this._flushAndClose(forceClose); - } + return this._closingPromise ??= (async () => { + await this._flushAndClose(forceClose); + this._closed = true; + })(); } } diff --git a/test/browser/media-sources.test.ts b/test/browser/media-sources.test.ts new file mode 100644 index 0000000..cd218ba --- /dev/null +++ b/test/browser/media-sources.test.ts @@ -0,0 +1,35 @@ +import { test } from 'vitest'; +import { Output } from '../../src/output.js'; +import { WebMOutputFormat } from '../../src/output-format.js'; +import { BufferTarget } from '../../src/target.js'; +import { VideoSampleSource } from '../../src/media-source.js'; +import { VideoSample } from '../../src/sample.js'; +import { QUALITY_MEDIUM } from '../../src/encode.js'; + +test('VideoSampleSource.close() should be idempotent after finalize()', async () => { + const output = new Output({ + format: new WebMOutputFormat(), + target: new BufferTarget(), + }); + + const videoSource = new VideoSampleSource({ + codec: 'vp8', + bitrate: QUALITY_MEDIUM, + }); + + output.addVideoTrack(videoSource); + await output.start(); + + const canvas = new OffscreenCanvas(100, 100); + const ctx = canvas.getContext('2d')!; + ctx.fillStyle = 'red'; + ctx.fillRect(0, 0, 100, 100); + + const sample = new VideoSample(canvas, { timestamp: 0, duration: 1 / 30 }); + await videoSource.add(sample); + sample.close(); + + await output.finalize(); + + videoSource.close(); // This previously threw +}); From 24af125415cce7266fe2ccdc31385828bd16deea Mon Sep 17 00:00:00 2001 From: Vanilagy <1696106+Vanilagy@users.noreply.github.com> Date: Mon, 12 Jan 2026 15:13:00 +0100 Subject: [PATCH 09/18] Make Conversion.cancel() cause execute() to throw (closes #271) --- dev/convert.html | 3 ++- docs/guide/converting-media-files.md | 2 +- src/conversion.ts | 20 ++++++++++++++++++-- src/index.ts | 1 + 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/dev/convert.html b/dev/convert.html index 36a2645..3778784 100644 --- a/dev/convert.html +++ b/dev/convert.html @@ -100,6 +100,7 @@ }, */ video: () => ({ + forceTranscode: true, allowRotationMetadata: false, //width: 720, //frameRate: 30, @@ -181,7 +182,7 @@ }, trim: { start: 0, - end: 4 + //end: 4 }, }); console.log(conversion); diff --git a/docs/guide/converting-media-files.md b/docs/guide/converting-media-files.md index 43d812a..8e11193 100644 --- a/docs/guide/converting-media-files.md +++ b/docs/guide/converting-media-files.md @@ -108,7 +108,7 @@ Sometimes, you may want to cancel an ongoing conversion process. For this, use t await conversion.cancel(); // Resolves once the conversion is canceled ``` -This automatically frees up all resources used by the conversion process. +This automatically frees up all resources used by the conversion process and will cause any ongoing call to `execute` to throw a `ConversionCanceledError`. ## Video options diff --git a/src/conversion.ts b/src/conversion.ts index 862b6f0..4b56d08 100644 --- a/src/conversion.ts +++ b/src/conversion.ts @@ -822,7 +822,7 @@ export class Conversion { } if (this._canceled) { - await new Promise(() => {}); // Never resolve + throw new ConversionCanceledError(); } await this.output.finalize(); @@ -832,7 +832,10 @@ export class Conversion { } } - /** Cancels the conversion process. Does nothing if the conversion is already complete. */ + /** + * Cancels the conversion process, causing any ongoing `execute` call to throw a `ConversionCanceledError`. + * Does nothing if the conversion is already complete. + */ async cancel() { if (this.output.state === 'finalizing' || this.output.state === 'finalized') { return; @@ -1589,6 +1592,19 @@ export class Conversion { } } +/** + * Thrown when a conversion couldn't complete due to being canceled. + * @group Conversion + * @public + */ +export class ConversionCanceledError extends Error { + /** Creates a new {@link ConversionCanceledError}. */ + constructor(message = 'Conversion has been canceled.') { + super(message); + this.name = 'ConversionCanceledError'; + } +} + const MAX_TIMESTAMP_GAP = 5; /** diff --git a/src/index.ts b/src/index.ts index 6cd723f..4c5bee1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -190,6 +190,7 @@ export { ConversionOptions, ConversionVideoOptions, ConversionAudioOptions, + ConversionCanceledError, DiscardedTrack, } from './conversion'; export { From 7db0583058f9f9662ff063ac86fc0061230221d6 Mon Sep 17 00:00:00 2001 From: Vanilagy <1696106+Vanilagy@users.noreply.github.com> Date: Mon, 12 Jan 2026 15:20:10 +0100 Subject: [PATCH 10/18] Fix samples not being closed sometimes in conversion (closes #272) --- src/conversion.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/conversion.ts b/src/conversion.ts index 4b56d08..a723d7b 100644 --- a/src/conversion.ts +++ b/src/conversion.ts @@ -1162,6 +1162,7 @@ export class Conversion { for await (const sample of sink.samples(this._startTimestamp, this._endTimestamp)) { if (this._canceled) { + sample.close(); lastSample?.close(); return; } @@ -1444,6 +1445,7 @@ export class Conversion { const sink = new AudioSampleSink(track); for await (const sample of sink.samples(undefined, this._endTimestamp)) { if (this._canceled) { + sample.close(); return; } @@ -1554,6 +1556,7 @@ export class Conversion { for await (const sample of iterator) { if (this._canceled) { + sample.close(); return; } From b8f104d8b49dd649b5953fdb99c4077af645a3eb Mon Sep 17 00:00:00 2001 From: Vanilagy <1696106+Vanilagy@users.noreply.github.com> Date: Mon, 12 Jan 2026 16:11:23 +0100 Subject: [PATCH 11/18] Fix disabled Matroska tracks crashing demuxer (closes #276) --- src/matroska/matroska-demuxer.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/matroska/matroska-demuxer.ts b/src/matroska/matroska-demuxer.ts index 1c47d09..b373ff4 100644 --- a/src/matroska/matroska-demuxer.ts +++ b/src/matroska/matroska-demuxer.ts @@ -1012,6 +1012,11 @@ export class MatroskaDemuxer extends Demuxer { this.readContiguousElements(slice.slice(dataStartPos, size)); + // Check if track was disabled during parsing (e.g., by FlagEnabled being 0) + if (!this.currentTrack) { + break; + } + if (this.currentTrack.decodingInstructions.some((instruction) => { return instruction.data?.type !== 'decompress' || instruction.scope !== ContentEncodingScope.Block From 32d8b1544d362b5169125eb6414ee6dd6151d0c4 Mon Sep 17 00:00:00 2001 From: Vanilagy <1696106+Vanilagy@users.noreply.github.com> Date: Mon, 12 Jan 2026 16:15:35 +0100 Subject: [PATCH 12/18] 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 6c803d8..c56b8e8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediabunny", - "version": "1.27.4", + "version": "1.27.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "mediabunny", - "version": "1.27.4", + "version": "1.27.5", "license": "MPL-2.0", "workspaces": [ "packages/*" @@ -7739,9 +7739,9 @@ } }, "node_modules/mediabunny": { - "version": "1.27.3", - "resolved": "https://registry.npmjs.org/mediabunny/-/mediabunny-1.27.3.tgz", - "integrity": "sha512-hlzmgzMznp9DhA5fMJKS5yEAyfCUMxAc+DbSPxD4J1J2cYVl1L+pZLndkt5xLlD5aB5eHEnphHMW14ammMlUXg==", + "version": "1.27.4", + "resolved": "https://registry.npmjs.org/mediabunny/-/mediabunny-1.27.4.tgz", + "integrity": "sha512-j69K0yiXYMHyb5g4XyhYjbz1VpllRVyyDGF5lqYTsrdF0XoDRoGReoRvon9lnENv5yY5A5u+09dnqISwXvS86Q==", "license": "MPL-2.0", "peer": true, "workspaces": [ @@ -12065,7 +12065,7 @@ }, "packages/mp3-encoder": { "name": "@mediabunny/mp3-encoder", - "version": "1.27.4", + "version": "1.27.5", "license": "MPL-2.0", "devDependencies": { "@types/emscripten": "^1.40.1" diff --git a/package.json b/package.json index 94043f6..9b055b1 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mediabunny", "author": "Vanilagy", - "version": "1.27.4", + "version": "1.27.5", "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 cc1be31..9f82bf0 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.27.4", + "version": "1.27.5", "description": "MP3 encoder extension for Mediabunny, based on LAME.", "main": "./dist/bundles/mediabunny-mp3-encoder.mjs", "module": "./dist/bundles/mediabunny-mp3-encoder.mjs", From 571fbb31986c7e9b37310e144121ac964d48a29b Mon Sep 17 00:00:00 2001 From: Vanilagy <1696106+Vanilagy@users.noreply.github.com> Date: Mon, 12 Jan 2026 16:47:31 +0100 Subject: [PATCH 13/18] Fix too many tracks being removed --- package-lock.json | 12 ++++++------ package.json | 2 +- packages/mp3-encoder/package.json | 2 +- src/matroska/matroska-demuxer.ts | 1 - 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index c56b8e8..98c322f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediabunny", - "version": "1.27.5", + "version": "1.27.6", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "mediabunny", - "version": "1.27.5", + "version": "1.27.6", "license": "MPL-2.0", "workspaces": [ "packages/*" @@ -7739,9 +7739,9 @@ } }, "node_modules/mediabunny": { - "version": "1.27.4", - "resolved": "https://registry.npmjs.org/mediabunny/-/mediabunny-1.27.4.tgz", - "integrity": "sha512-j69K0yiXYMHyb5g4XyhYjbz1VpllRVyyDGF5lqYTsrdF0XoDRoGReoRvon9lnENv5yY5A5u+09dnqISwXvS86Q==", + "version": "1.27.5", + "resolved": "https://registry.npmjs.org/mediabunny/-/mediabunny-1.27.5.tgz", + "integrity": "sha512-VGiZILC3S7muo7bhnq5/PvorqB4A72qSFOzI5tg2Ed79ecco9VFY4kvzbU32lLuuxSLxb9TWpOe1cGGtQuP0vA==", "license": "MPL-2.0", "peer": true, "workspaces": [ @@ -12065,7 +12065,7 @@ }, "packages/mp3-encoder": { "name": "@mediabunny/mp3-encoder", - "version": "1.27.5", + "version": "1.27.6", "license": "MPL-2.0", "devDependencies": { "@types/emscripten": "^1.40.1" diff --git a/package.json b/package.json index 9b055b1..9ad9506 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mediabunny", "author": "Vanilagy", - "version": "1.27.5", + "version": "1.27.6", "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 9f82bf0..2661ccd 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.27.5", + "version": "1.27.6", "description": "MP3 encoder extension for Mediabunny, based on LAME.", "main": "./dist/bundles/mediabunny-mp3-encoder.mjs", "module": "./dist/bundles/mediabunny-mp3-encoder.mjs", diff --git a/src/matroska/matroska-demuxer.ts b/src/matroska/matroska-demuxer.ts index b373ff4..25ba506 100644 --- a/src/matroska/matroska-demuxer.ts +++ b/src/matroska/matroska-demuxer.ts @@ -1160,7 +1160,6 @@ export class MatroskaDemuxer extends Demuxer { const enabled = readUnsignedInt(slice, size); if (!enabled) { - this.currentSegment!.tracks.pop(); this.currentTrack = null; } }; break; From 2ab1be3834f95d7f54d82fc08c8ac5bfe8d007df Mon Sep 17 00:00:00 2001 From: Vanilagy <1696106+Vanilagy@users.noreply.github.com> Date: Tue, 13 Jan 2026 13:37:34 +0100 Subject: [PATCH 14/18] Add maximumPageDuration Ogg muxer option (closes #277) --- docs/guide/output-formats.md | 3 ++ src/ogg/ogg-muxer.ts | 51 ++++++++++++++++++++---------- src/output-format.ts | 12 +++++++ test/browser/ogg-muxer.test.ts | 57 ++++++++++++++++++++++++++++++++++ 4 files changed, 106 insertions(+), 17 deletions(-) create mode 100644 test/browser/ogg-muxer.test.ts diff --git a/docs/guide/output-formats.md b/docs/guide/output-formats.md index 6e125cb..0e151b4 100644 --- a/docs/guide/output-formats.md +++ b/docs/guide/output-formats.md @@ -194,9 +194,12 @@ This format ensures [append-only writing](#append-only-writing). The following options are available: ```ts type OggOutputFormatOptions = { + maximumPageDuration?: number; onPage?: (data: Uint8Array, position: number, source: MediaSource) => unknown; }; ``` +- `maximumPageDuration`\ + The maximum duration in seconds of each Ogg page. Pages will be flushed early if adding another packet would cause the page to exceed this duration. This is useful for streaming contexts where more frequent page output is desired. By default, pages are only flushed when they exceed a certain size. - `onPage`\ Will be called for each finalized Ogg page of the output file. The [media source](./media-sources) backing the page's track (logical bitstream) is also passed. diff --git a/src/ogg/ogg-muxer.ts b/src/ogg/ogg-muxer.ts index 91ee535..b47f86e 100644 --- a/src/ogg/ogg-muxer.ts +++ b/src/ogg/ogg-muxer.ts @@ -47,12 +47,13 @@ type OggTrackData = { currentPageData: Uint8Array[]; currentPageSize: number; currentPageStartsWithFreshPacket: boolean; + currentPageStartTimestampInSamples: number; }; type Packet = { data: Uint8Array; - endGranulePosition: number; - timestamp: number; + timestampInSamples: number; + durationInSamples: number; forcePageFlush: boolean; }; @@ -132,6 +133,7 @@ export class OggMuxer extends Muxer { currentPageData: [], currentPageSize: 27, currentPageStartsWithFreshPacket: true, + currentPageStartTimestampInSamples: 0, }; this.queueHeaderPackets(newTrackData, meta); @@ -199,18 +201,18 @@ export class OggMuxer extends Muxer { trackData.packetQueue.push({ data: identificationHeader, - endGranulePosition: 0, - timestamp: 0, + timestampInSamples: 0, + durationInSamples: 0, forcePageFlush: true, }, { data: commentHeader, - endGranulePosition: 0, - timestamp: 0, + timestampInSamples: 0, + durationInSamples: 0, forcePageFlush: false, }, { data: setupHeader, - endGranulePosition: 0, - timestamp: 0, + timestampInSamples: 0, + durationInSamples: 0, forcePageFlush: true, // The last header packet must flush the page }); @@ -239,13 +241,13 @@ export class OggMuxer extends Muxer { trackData.packetQueue.push({ data: identificationHeader, - endGranulePosition: 0, - timestamp: 0, + timestampInSamples: 0, + durationInSamples: 0, forcePageFlush: true, }, { data: commentHeader, - endGranulePosition: 0, - timestamp: 0, + timestampInSamples: 0, + durationInSamples: 0, forcePageFlush: true, // The last header packet must flush the page }); @@ -275,8 +277,8 @@ export class OggMuxer extends Muxer { trackData.packetQueue.push({ data: packet.data, - endGranulePosition: trackData.currentTimestampInSamples, - timestamp: currentTimestampInSamples / trackData.internalSampleRate, + timestampInSamples: currentTimestampInSamples, + durationInSamples, forcePageFlush: false, }); @@ -338,10 +340,10 @@ export class OggMuxer extends Muxer { if ( trackData.packetQueue.length > 0 - && trackData.packetQueue[0]!.timestamp < minTimestamp + && trackData.packetQueue[0]!.timestampInSamples < minTimestamp ) { trackWithMinTimestamp = trackData; - minTimestamp = trackData.packetQueue[0]!.timestamp; + minTimestamp = trackData.packetQueue[0]!.timestampInSamples; } } @@ -361,6 +363,20 @@ export class OggMuxer extends Muxer { } writePacket(trackData: OggTrackData, packet: Packet, isFinalPacket: boolean) { + const packetEndTimestampInSamples = packet.timestampInSamples + packet.durationInSamples; + + if (this.format._options.maximumPageDuration !== undefined) { + const maxDurationInSamples = this.format._options.maximumPageDuration * trackData.internalSampleRate; + + if ( + trackData.currentLacingValues.length > 0 + && packetEndTimestampInSamples - trackData.currentPageStartTimestampInSamples > maxDurationInSamples + ) { + // Flush the current page early to avoid exceeding the maximum page duration + this.writePage(trackData, false); + } + } + let remainingLength = packet.data.length; let dataStartOffset = 0; let dataOffset = 0; @@ -401,7 +417,7 @@ export class OggMuxer extends Muxer { const slice = packet.data.subarray(dataStartOffset); trackData.currentPageData.push(slice); trackData.currentPageSize += slice.length; - trackData.currentGranulePosition = packet.endGranulePosition; + trackData.currentGranulePosition = packetEndTimestampInSamples; if (trackData.currentPageSize >= PAGE_SIZE_TARGET || packet.forcePageFlush) { this.writePage(trackData, isFinalPacket); @@ -452,6 +468,7 @@ export class OggMuxer extends Muxer { trackData.currentPageData.length = 0; trackData.currentPageSize = 27; trackData.currentPageStartsWithFreshPacket = true; + trackData.currentPageStartTimestampInSamples = trackData.currentGranulePosition; if (this.format._options.onPage) { this.writer.startTrackingWrites(); diff --git a/src/output-format.ts b/src/output-format.ts index de50fe3..bd32b6c 100644 --- a/src/output-format.ts +++ b/src/output-format.ts @@ -725,6 +725,12 @@ export class WavOutputFormat extends OutputFormat { * @public */ export type OggOutputFormatOptions = { + /** + * The maximum duration of each Ogg page, in seconds. This is useful for streaming contexts where more frequent page + * output is desired. By default, pages are only flushed when they exceed a certain size. + */ + maximumPageDuration?: number; + /** * Will be called for each Ogg page that is written. * @@ -749,6 +755,12 @@ export class OggOutputFormat extends OutputFormat { if (!options || typeof options !== 'object') { throw new TypeError('options must be an object.'); } + if ( + options.maximumPageDuration !== undefined + && (!Number.isFinite(options.maximumPageDuration) || options.maximumPageDuration <= 0) + ) { + throw new TypeError('options.maximumPageDuration, when provided, must be a positive number.'); + } if (options.onPage !== undefined && typeof options.onPage !== 'function') { throw new TypeError('options.onPage, when provided, must be a function.'); } diff --git a/test/browser/ogg-muxer.test.ts b/test/browser/ogg-muxer.test.ts new file mode 100644 index 0000000..ea982e1 --- /dev/null +++ b/test/browser/ogg-muxer.test.ts @@ -0,0 +1,57 @@ +import { expect, test } from 'vitest'; +import { Output } from '../../src/output.js'; +import { OggOutputFormat } from '../../src/output-format.js'; +import { NullTarget } from '../../src/target.js'; +import { AudioBufferSource } from '../../src/media-source.js'; + +test('maximumPageDuration option', async () => { + const sampleRate = 48000; + const durationSeconds = 2; + const audioBuffer = new AudioBuffer({ numberOfChannels: 1, length: sampleRate * durationSeconds, sampleRate }); + + // First, create an Ogg file without the maximumPageDuration option + let pageCountWithoutOption = 0; + { + const output = new Output({ + format: new OggOutputFormat({ + onPage: () => { + pageCountWithoutOption++; + }, + }), + target: new NullTarget(), + }); + + const audioSource = new AudioBufferSource({ codec: 'opus', bitrate: 64000 }); + output.addAudioTrack(audioSource); + + await output.start(); + await audioSource.add(audioBuffer); + audioSource.close(); + await output.finalize(); + } + + // Then, create an Ogg file with maximumPageDuration set to 0.1 seconds + let pageCountWithOption = 0; + { + const output = new Output({ + format: new OggOutputFormat({ + maximumPageDuration: 0.1, + onPage: () => { + pageCountWithOption++; + }, + }), + target: new NullTarget(), + }); + + const audioSource = new AudioBufferSource({ codec: 'opus', bitrate: 64000 }); + output.addAudioTrack(audioSource); + + await output.start(); + await audioSource.add(audioBuffer); + audioSource.close(); + await output.finalize(); + } + + expect(pageCountWithoutOption).toBe(3); + expect(pageCountWithOption).toBe(23); // It created more pages +}); From a89101ff40069af26f29192cf0bdd3785336739c Mon Sep 17 00:00:00 2001 From: Igor Samokhovets Date: Tue, 13 Jan 2026 13:45:43 +0100 Subject: [PATCH 15/18] Fix OGG Vorbis decoding error for files with empty EOS pages (VLC-encoded) --- src/ogg/ogg-demuxer.ts | 4 ++++ test/browser/ogg-vorbis-windowed.test.ts | 26 +++++++++++++++++++++++ test/public/vorbis-eos.ogg | Bin 0 -> 92218 bytes 3 files changed, 30 insertions(+) create mode 100644 test/browser/ogg-vorbis-windowed.test.ts create mode 100644 test/public/vorbis-eos.ogg diff --git a/src/ogg/ogg-demuxer.ts b/src/ogg/ogg-demuxer.ts index c5164b9..e509933 100644 --- a/src/ogg/ogg-demuxer.ts +++ b/src/ogg/ogg-demuxer.ts @@ -499,6 +499,10 @@ class OggAudioTrackBacking implements InputAudioTrackBacking { return null; } + if (packet.data.byteLength === 0) { + return null; + } + const { durationInSamples, vorbisBlockSize } = extractSampleMetadata( packet.data, this.bitstream.codecInfo, diff --git a/test/browser/ogg-vorbis-windowed.test.ts b/test/browser/ogg-vorbis-windowed.test.ts new file mode 100644 index 0000000..388da44 --- /dev/null +++ b/test/browser/ogg-vorbis-windowed.test.ts @@ -0,0 +1,26 @@ +import { expect, test } from 'vitest'; +import { Input } from '../../src/input.js'; +import { UrlSource } from '../../src/source.js'; +import { ALL_FORMATS } from '../../src/input-format.js'; +import { AudioBufferSink } from '../../src/media-sink.js'; +import { assert } from '../../src/misc.js'; + +// VLC creates OGG files with an empty EOS page, which previously caused decoding errors +test('can decode OGG Vorbis file with empty EOS page', async () => { + using input = new Input({ + source: new UrlSource('/vorbis-eos.ogg'), + formats: ALL_FORMATS, + }); + + const track = await input.getPrimaryAudioTrack(); + assert(track); + + const sink = new AudioBufferSink(track); + const buffers: AudioBuffer[] = []; + + for await (const { buffer } of sink.buffers(4, 10)) { + buffers.push(buffer); + } + + expect(buffers.length).toBeGreaterThan(0); +}); diff --git a/test/public/vorbis-eos.ogg b/test/public/vorbis-eos.ogg new file mode 100644 index 0000000000000000000000000000000000000000..9a32d4f0e61e1e550798f117c2e5f6bdd23c821d GIT binary patch literal 92218 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 z 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 literal 0 HcmV?d00001 From 267c09abf8e0c443bac7f1a4ced9f78b03d312cf Mon Sep 17 00:00:00 2001 From: Vanilagy <1696106+Vanilagy@users.noreply.github.com> Date: Tue, 13 Jan 2026 17:34:33 +0100 Subject: [PATCH 16/18] Return null earlier on --- src/ogg/ogg-demuxer.ts | 8 ++++---- .../{ogg-vorbis-windowed.test.ts => ogg-demuxer.test.ts} | 0 2 files changed, 4 insertions(+), 4 deletions(-) rename test/browser/{ogg-vorbis-windowed.test.ts => ogg-demuxer.test.ts} (100%) diff --git a/src/ogg/ogg-demuxer.ts b/src/ogg/ogg-demuxer.ts index e509933..0b4569f 100644 --- a/src/ogg/ogg-demuxer.ts +++ b/src/ogg/ogg-demuxer.ts @@ -322,6 +322,10 @@ export class OggDemuxer extends Demuxer { } const totalPacketSize = chunks.reduce((sum, chunk) => sum + chunk.length, 0); + if (totalPacketSize === 0) { + return null; // Invalid packet, treat it as end of stream + } + const packetData = new Uint8Array(totalPacketSize); let offset = 0; @@ -499,10 +503,6 @@ class OggAudioTrackBacking implements InputAudioTrackBacking { return null; } - if (packet.data.byteLength === 0) { - return null; - } - const { durationInSamples, vorbisBlockSize } = extractSampleMetadata( packet.data, this.bitstream.codecInfo, diff --git a/test/browser/ogg-vorbis-windowed.test.ts b/test/browser/ogg-demuxer.test.ts similarity index 100% rename from test/browser/ogg-vorbis-windowed.test.ts rename to test/browser/ogg-demuxer.test.ts From e1478f8ebd112b1cd2d250855eaa1c9c79f10bcb Mon Sep 17 00:00:00 2001 From: Vanilagy <1696106+Vanilagy@users.noreply.github.com> Date: Wed, 14 Jan 2026 09:21:51 +0100 Subject: [PATCH 17/18] 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 98c322f..1a83717 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediabunny", - "version": "1.27.6", + "version": "1.27.7", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "mediabunny", - "version": "1.27.6", + "version": "1.27.7", "license": "MPL-2.0", "workspaces": [ "packages/*" @@ -7739,9 +7739,9 @@ } }, "node_modules/mediabunny": { - "version": "1.27.5", - "resolved": "https://registry.npmjs.org/mediabunny/-/mediabunny-1.27.5.tgz", - "integrity": "sha512-VGiZILC3S7muo7bhnq5/PvorqB4A72qSFOzI5tg2Ed79ecco9VFY4kvzbU32lLuuxSLxb9TWpOe1cGGtQuP0vA==", + "version": "1.27.6", + "resolved": "https://registry.npmjs.org/mediabunny/-/mediabunny-1.27.6.tgz", + "integrity": "sha512-Y6QLjH5lAea9swaLcfXzcK/Xw1cFW4KDLvkm+0fUFcwfp8SEnAiMh8RSBtMBVADoE7hTCA9yn7JoYJv3VBd/yQ==", "license": "MPL-2.0", "peer": true, "workspaces": [ @@ -12065,7 +12065,7 @@ }, "packages/mp3-encoder": { "name": "@mediabunny/mp3-encoder", - "version": "1.27.6", + "version": "1.27.7", "license": "MPL-2.0", "devDependencies": { "@types/emscripten": "^1.40.1" diff --git a/package.json b/package.json index 9ad9506..86232d9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mediabunny", "author": "Vanilagy", - "version": "1.27.6", + "version": "1.27.7", "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 2661ccd..440ba24 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.27.6", + "version": "1.27.7", "description": "MP3 encoder extension for Mediabunny, based on LAME.", "main": "./dist/bundles/mediabunny-mp3-encoder.mjs", "module": "./dist/bundles/mediabunny-mp3-encoder.mjs", From 868578685d6c88fb4ae08210eefa62880a485531 Mon Sep 17 00:00:00 2001 From: Vanilagy <1696106+Vanilagy@users.noreply.github.com> Date: Wed, 14 Jan 2026 09:22:43 +0100 Subject: [PATCH 18/18] Shoulda bumped minor, oops --- package-lock.json | 6 +++--- package.json | 2 +- packages/mp3-encoder/package.json | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1a83717..7d847a9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediabunny", - "version": "1.27.7", + "version": "1.28.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "mediabunny", - "version": "1.27.7", + "version": "1.28.0", "license": "MPL-2.0", "workspaces": [ "packages/*" @@ -12065,7 +12065,7 @@ }, "packages/mp3-encoder": { "name": "@mediabunny/mp3-encoder", - "version": "1.27.7", + "version": "1.28.0", "license": "MPL-2.0", "devDependencies": { "@types/emscripten": "^1.40.1" diff --git a/package.json b/package.json index 86232d9..d476f12 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mediabunny", "author": "Vanilagy", - "version": "1.27.7", + "version": "1.28.0", "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 440ba24..65c2f55 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.27.7", + "version": "1.28.0", "description": "MP3 encoder extension for Mediabunny, based on LAME.", "main": "./dist/bundles/mediabunny-mp3-encoder.mjs", "module": "./dist/bundles/mediabunny-mp3-encoder.mjs",