From 6d447660c226667f7ecaf80cc8d51c81ea669059 Mon Sep 17 00:00:00 2001 From: Vanilagy <1696106+Vanilagy@users.noreply.github.com> Date: Mon, 11 Aug 2025 16:10:43 +0200 Subject: [PATCH 1/2] Clarify EBML strings are ASCII --- src/input-format.ts | 2 +- src/matroska/ebml.ts | 7 +++---- src/matroska/matroska-demuxer.ts | 6 +++--- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/input-format.ts b/src/input-format.ts index 4c4c1c5..142ee0d 100644 --- a/src/input-format.ts +++ b/src/input-format.ts @@ -154,7 +154,7 @@ export class MatroskaInputFormat extends InputFormat { } }; break; case EBMLId.DocType: { - const docType = ebmlReader.readString(size); + const docType = ebmlReader.readAsciiString(size); if (docType !== desiredDocType) { return false; } diff --git a/src/matroska/ebml.ts b/src/matroska/ebml.ts index ace8b18..ab5d8d4 100644 --- a/src/matroska/ebml.ts +++ b/src/matroska/ebml.ts @@ -312,8 +312,7 @@ export class EBMLWriter { this.writer.write(this.helper.subarray(0, pos)); } - // Assumes the string is ASCII - writeString(str: string) { + writeAsciiString(str: string) { this.writer.write(new Uint8Array(str.split('').map(x => x.charCodeAt(0)))); } @@ -359,7 +358,7 @@ export class EBMLWriter { this.writeUnsignedInt(data.data, size); } else if (typeof data.data === 'string') { this.writeVarInt(data.data.length); - this.writeString(data.data); + this.writeAsciiString(data.data); } else if (data.data instanceof Uint8Array) { this.writeVarInt(data.data.byteLength, data.size); this.writer.write(data.data); @@ -495,7 +494,7 @@ export class EBMLReader { return value; } - readString(length: number) { + readAsciiString(length: number) { const { view, offset } = this.reader.getViewAndOffset(this.pos, this.pos + length); this.pos += length; diff --git a/src/matroska/matroska-demuxer.ts b/src/matroska/matroska-demuxer.ts index adafd0b..641f3e6 100644 --- a/src/matroska/matroska-demuxer.ts +++ b/src/matroska/matroska-demuxer.ts @@ -731,7 +731,7 @@ export class MatroskaDemuxer extends Demuxer { switch (id) { case EBMLId.DocType: { - this.isWebM = reader.readString(size) === 'webm'; + this.isWebM = reader.readAsciiString(size) === 'webm'; }; break; case EBMLId.Seek: { @@ -940,7 +940,7 @@ export class MatroskaDemuxer extends Demuxer { case EBMLId.CodecID: { if (!this.currentTrack) break; - this.currentTrack.codecId = reader.readString(size); + this.currentTrack.codecId = reader.readAsciiString(size); }; break; case EBMLId.CodecPrivate: { @@ -959,7 +959,7 @@ export class MatroskaDemuxer extends Demuxer { case EBMLId.Language: { if (!this.currentTrack) break; - this.currentTrack.languageCode = reader.readString(size); + this.currentTrack.languageCode = reader.readAsciiString(size); if (!isIso639Dash2LanguageCode(this.currentTrack.languageCode)) { this.currentTrack.languageCode = UNDETERMINED_LANGUAGE; From 1492fd5c6f2adcc7b6a7a90f25d1cb1a8c701eaa Mon Sep 17 00:00:00 2001 From: Vanilagy <1696106+Vanilagy@users.noreply.github.com> Date: Mon, 11 Aug 2025 18:14:02 +0200 Subject: [PATCH 2/2] Add workaround for Chromium range request caching bug --- dev/demux.html | 10 ++++++++++ package-lock.json | 12 ++++++------ package.json | 2 +- packages/mp3-encoder/package.json | 2 +- src/source.ts | 24 ++++++++++++++++++++++-- 5 files changed, 40 insertions(+), 10 deletions(-) diff --git a/dev/demux.html b/dev/demux.html index 1674f94..c9c5fd5 100644 --- a/dev/demux.html +++ b/dev/demux.html @@ -8,6 +8,15 @@ 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); @@ -20,6 +29,7 @@ const sink = new Mediabunny.EncodedPacketSink(audioTrack); console.log(await sink.getPacket(100)) + */ /* for await (const packet of sink.packets()) { diff --git a/package-lock.json b/package-lock.json index 8749fcf..7ea184f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediabunny", - "version": "1.7.0", + "version": "1.7.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "mediabunny", - "version": "1.7.0", + "version": "1.7.1", "license": "MPL-2.0", "workspaces": [ "packages/*" @@ -5900,9 +5900,9 @@ } }, "node_modules/mediabunny": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/mediabunny/-/mediabunny-1.6.2.tgz", - "integrity": "sha512-c0z6lfeYHYk5M6V9kLaXD/7HqW8UjjsDhoZUwLConxHCrL/pPMnZwX5tXjXz/T8DIeuXYYbjYR9X43LnEmWacA==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/mediabunny/-/mediabunny-1.7.0.tgz", + "integrity": "sha512-QcTdptOtvjAHb4KQpgWWWHRS0+DgGwTXelTwPWaZwQu85iYy11bzsLS4e29rfH4nLL/eq8K/dBsjj1LuApc2Qw==", "license": "MPL-2.0", "peer": true, "workspaces": [ @@ -9017,7 +9017,7 @@ }, "packages/mp3-encoder": { "name": "@mediabunny/mp3-encoder", - "version": "1.7.0", + "version": "1.7.1", "license": "MPL-2.0", "devDependencies": { "@types/emscripten": "^1.40.1" diff --git a/package.json b/package.json index eb98479..327ea65 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mediabunny", "author": "Vanilagy", - "version": "1.7.0", + "version": "1.7.1", "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 cbe71f6..5b2b163 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.0", + "version": "1.7.1", "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/source.ts b/src/source.ts index 1fc4f2d..0c511a7 100644 --- a/src/source.ts +++ b/src/source.ts @@ -164,11 +164,13 @@ export type UrlSourceOptions = { */ export class UrlSource extends Source { /** @internal */ - private _url: string | URL; + private _url: URL; /** @internal */ private _options: UrlSourceOptions; /** @internal */ private _fullData: ArrayBuffer | null = null; + /** @internal */ + private _nextUrlVersion: number | null = null; constructor( url: string | URL, @@ -189,7 +191,7 @@ export class UrlSource extends Source { super(); - this._url = url; + this._url = url instanceof URL ? url : new URL(url); this._options = options; } @@ -203,6 +205,11 @@ export class UrlSource extends Source { headers['Range'] = `bytes=${range.start}-${range.end - 1}`; } + if (this._nextUrlVersion !== null) { + this._url.searchParams.set('mediabunny_version', this._nextUrlVersion.toString()); + this._nextUrlVersion++; + } + const response = await retriedFetch( this._url, mergeObjectsDeeply(this._options.requestInit ?? {}, { @@ -218,6 +225,19 @@ export class UrlSource extends Source { const buffer = await response.arrayBuffer(); + if ( + response.status === 206 + && range + && buffer.byteLength !== range.end - range.start + && this._nextUrlVersion === null + ) { + // We did a range request but it resolved with the wrong range; in Chromium, this can be due to a caching + // bug (https://issues.chromium.org/issues/436025873). Let's circumvent the cache for the rest of the + // session by appending a version to the URL. + this._nextUrlVersion = 1; + return this._makeRequest(range); + } + if (response.status === 200) { // The server didn't return 206 Partial Content, so it's not a range response this._fullData = buffer;