From da159bb0632010657599f350f416447ecb841e90 Mon Sep 17 00:00:00 2001 From: Vanilagy <1696106+Vanilagy@users.noreply.github.com> Date: Mon, 24 Nov 2025 16:28:10 +0100 Subject: [PATCH 1/6] Stop retrying requests when the source is disposed, log warning in possible CORS detection case (see #158) --- src/misc.ts | 9 +++++++++ src/source.ts | 11 +++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/misc.ts b/src/misc.ts index dfbc42d..b11c45f 100644 --- a/src/misc.ts +++ b/src/misc.ts @@ -584,6 +584,7 @@ export const retriedFetch = async ( url: string | URL | Request, requestInit: RequestInit, getRetryDelay: (previousAttempts: number, error: unknown, url: string | URL | Request) => number | null, + shouldStop: () => boolean, ) => { let attempts = 0; @@ -591,6 +592,10 @@ export const retriedFetch = async ( try { return await fetchFn(url, requestInit); } catch (error) { + if (shouldStop()) { + throw error; + } + attempts++; const retryDelayInSeconds = getRetryDelay(attempts, error, url); @@ -607,6 +612,10 @@ export const retriedFetch = async ( if (retryDelayInSeconds > 0) { await new Promise(resolve => setTimeout(resolve, 1000 * retryDelayInSeconds)); } + + if (shouldStop()) { + throw error; + } } } }; diff --git a/src/source.ts b/src/source.ts index 68ebac1..0f936a8 100644 --- a/src/source.ts +++ b/src/source.ts @@ -297,6 +297,10 @@ const DEFAULT_RETRY_DELAY = typeof navigator !== 'undefined' && typeof navigator.onLine === 'boolean' ? navigator.onLine : true; if (isOnline && originOfSrc !== null && originOfSrc !== window.location.origin) { + console.warn( + `Request will not be retried because a CORS error was suspected due to different origins. You can` + + ` modify this behavior by providing your own function for the 'getRetryDelay' option.`, + ); return null; } } @@ -425,6 +429,7 @@ export class UrlSource extends Source { signal: abortController.signal, }), this._getRetryDelay, + () => this._disposed, ); if (!response.ok) { @@ -492,6 +497,7 @@ export class UrlSource extends Source { signal: abortController.signal, }), this._getRetryDelay, + () => this._disposed, ); } @@ -539,6 +545,11 @@ export class UrlSource extends Source { try { readResult = await reader.read(); } catch (error) { + if (this._disposed) { + // No need to try to retry + throw error; + } + const retryDelayInSeconds = this._getRetryDelay(1, error, this._url); if (retryDelayInSeconds !== null) { console.error('Error while reading response stream. Attempting to resume.', error); From f62ecb0eb6fad92346a68157568b71984ebedc39 Mon Sep 17 00:00:00 2001 From: Vanilagy <1696106+Vanilagy@users.noreply.github.com> Date: Mon, 24 Nov 2025 16:53:53 +0100 Subject: [PATCH 2/6] Fix wrong type being used --- src/source.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/source.ts b/src/source.ts index 0f936a8..98cdc52 100644 --- a/src/source.ts +++ b/src/source.ts @@ -650,7 +650,7 @@ export class FilePathSource extends Source { _fileHandle: FileHandle | null = null; /** Creates a new {@link FilePathSource} backed by the file at the specified file path. */ - constructor(filePath: string, options: BlobSourceOptions = {}) { + constructor(filePath: string, options: FilePathSourceOptions = {}) { if (typeof filePath !== 'string') { throw new TypeError('filePath must be a string.'); } From ef7a40944ece3744a3b6138c128f67cca0fbdd3c Mon Sep 17 00:00:00 2001 From: Vanilagy <1696106+Vanilagy@users.noreply.github.com> Date: Mon, 24 Nov 2025 17:18:46 +0100 Subject: [PATCH 3/6] Stronger encodability checks for Firefox (fixes #222) --- src/encode.ts | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/src/encode.ts b/src/encode.ts index 75b2a21..9f07a69 100644 --- a/src/encode.ts +++ b/src/encode.ts @@ -22,6 +22,7 @@ import { VideoCodec, } from './codec'; import { customAudioEncoders, customVideoEncoders } from './custom-coder'; +import { isFirefox } from './misc'; import { EncodedPacket } from './packet'; /** @@ -529,7 +530,45 @@ export const canEncodeVideo = async ( }); const support = await VideoEncoder.isConfigSupported(encoderConfig); - return support.supported === true; + if (!support.supported) { + return false; + } + + if (isFirefox()) { + // isConfigSupported on Firefox appears to unreliably indicate if encoding will actually succeed. Therefore, we + // just try encoding a frame to see if it actually works. + // https://github.com/Vanilagy/mediabunny/issues/222 + + // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor + return new Promise(async (resolve) => { + try { + const encoder = new VideoEncoder({ + output: () => {}, + error: () => resolve(false), + }); + encoder.configure(encoderConfig); + + const frameData = new Uint8Array(width * height * 4); + const frame = new VideoFrame(frameData, { + format: 'RGBA', + codedWidth: width, + codedHeight: height, + timestamp: 0, + }); + + encoder.encode(frame); + frame.close(); + + await encoder.flush(); + + resolve(true); + } catch { + resolve(false); + } + }); + } else { + return true; + } }; /** From 896242a5a50f3ad3192884dc9c6fb89415a6ae9e Mon Sep 17 00:00:00 2001 From: Vanilagy <1696106+Vanilagy@users.noreply.github.com> Date: Mon, 24 Nov 2025 17:34:07 +0100 Subject: [PATCH 4/6] Enable sitemap generation for docs --- docs/.vitepress/config.mts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index 6a1502a..7f398ba 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -14,6 +14,9 @@ export default withMermaid({ title: 'Mediabunny', description: DESCRIPTION, cleanUrls: true, + sitemap: { + hostname: 'https://mediabunny.dev', + }, head: [ ['link', { rel: 'icon', type: 'image/png', href: '/mediabunny-logo.png' }], ['link', { rel: 'icon', type: 'image/svg+xml', href: '/mediabunny-logo.svg' }], From 34b3ef0d44c8731437560c8b3f59c86b13cbe2a2 Mon Sep 17 00:00:00 2001 From: Vanilagy <1696106+Vanilagy@users.noreply.github.com> Date: Mon, 24 Nov 2025 17:41:41 +0100 Subject: [PATCH 5/6] Fix URLs that get redirected --- docs/.vitepress/config.mts | 2 +- docs/examples.md | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index 7f398ba..a1e44e7 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -37,7 +37,7 @@ export default withMermaid({ // https://vitepress.dev/reference/default-theme-config nav: [ { text: 'Guide', link: '/guide/introduction', activeMatch: '/guide' }, - { text: 'API', link: '/api', activeMatch: '/api' }, + { text: 'API', link: '/api/', activeMatch: '/api' }, { text: 'LLMs', link: '/llms', activeMatch: '/llms' }, { text: 'Examples', link: '/examples', activeMatch: '/examples' }, { text: 'Sponsors', link: '/#sponsors', activeMatch: '/#sponsors' }, diff --git a/docs/examples.md b/docs/examples.md index 7c65313..68ce4ff 100644 --- a/docs/examples.md +++ b/docs/examples.md @@ -9,37 +9,37 @@ hero: features: - title: Metadata extraction details: Extract various metadata from an input media file. - link: /examples/metadata-extraction + link: /examples/metadata-extraction/ target: _self icon: src: /mingcute--file-info-line.svg - title: Thumbnail generation details: Generate multiple small thumbnails for a video track. - link: /examples/thumbnail-generation + link: /examples/thumbnail-generation/ target: _self icon: src: /mingcute--photo-album-line.svg - title: Media player (advanced) details: "A full video & audio media player, implemented from scratch with Mediabunny, with microsecond playback accuracy." - link: /examples/media-player + link: /examples/media-player/ target: _self icon: src: /mingcute--video-line.svg - title: File compression details: Convert an input file to a highly-compressed MP4 file. - link: /examples/file-compression + link: /examples/file-compression/ target: _self icon: src: /mingcute--file-zip-line.svg - title: Procedural video generation details: Generate a video file as fast as the hardware allows. - link: /examples/procedural-generation + link: /examples/procedural-generation/ target: _self icon: src: /mingcute--magic-3-line.svg - title: Live recording & streaming details: Record a video from live sources and stream it to a video element. - link: /examples/live-recording + link: /examples/live-recording/ target: _self icon: src: /mingcute--microphone-line.svg From cc3d48451e53f3eea1e20b6e37115b113e7f2a04 Mon Sep 17 00:00:00 2001 From: Vanilagy <1696106+Vanilagy@users.noreply.github.com> Date: Tue, 25 Nov 2025 17:26:12 +0100 Subject: [PATCH 6/6] 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 d6808d6..68a6f34 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediabunny", - "version": "1.25.1", + "version": "1.25.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "mediabunny", - "version": "1.25.1", + "version": "1.25.2", "license": "MPL-2.0", "workspaces": [ "packages/*" @@ -7749,9 +7749,9 @@ } }, "node_modules/mediabunny": { - "version": "1.25.0", - "resolved": "https://registry.npmjs.org/mediabunny/-/mediabunny-1.25.0.tgz", - "integrity": "sha512-ozaqk6zS2Vbf3+3+OoxKfnCVeZRcv5PO8DgQtBrM5vpWIbpEK+kMVV6pgfo4mC3XtMwvQEMbhj3zEf0LNklh9w==", + "version": "1.25.1", + "resolved": "https://registry.npmjs.org/mediabunny/-/mediabunny-1.25.1.tgz", + "integrity": "sha512-0Rrd47PMCVJbTPA7IJaXPCupV5/RZ/icgr+a0qExRJAr0n5vB4fsGSo+fdHIehG0CrddXtVRvNZwFtJz709yfA==", "license": "MPL-2.0", "peer": true, "workspaces": [ @@ -12242,7 +12242,7 @@ }, "packages/mp3-encoder": { "name": "@mediabunny/mp3-encoder", - "version": "1.25.1", + "version": "1.25.2", "license": "MPL-2.0", "devDependencies": { "@types/emscripten": "^1.40.1" diff --git a/package.json b/package.json index 235421f..6e96abc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mediabunny", "author": "Vanilagy", - "version": "1.25.1", + "version": "1.25.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 0925875..172e319 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.25.1", + "version": "1.25.2", "description": "MP3 encoder extension for Mediabunny, based on LAME.", "main": "./dist/bundles/mediabunny-mp3-encoder.mjs", "module": "./dist/bundles/mediabunny-mp3-encoder.mjs",