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 1/9] 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 2/9] 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 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 3/9] 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 4/9] 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 5/9] 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 6/9] 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 7/9] 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 8/9] 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 9/9] 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",