diff --git a/package-lock.json b/package-lock.json index 54393d2..0e22cf4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediabunny", - "version": "1.3.0", + "version": "1.3.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "mediabunny", - "version": "1.3.0", + "version": "1.3.1", "license": "MPL-2.0", "dependencies": { "@types/dom-mediacapture-transform": "^0.1.11", diff --git a/package.json b/package.json index 3f6c0d7..5da7963 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mediabunny", "author": "Vanilagy", - "version": "1.3.0", + "version": "1.3.1", "description": "Pure TypeScript media toolkit for reading, writing, and converting media files, directly in the browser.", "type": "module", "main": "./dist/bundles/mediabunny.cjs", diff --git a/src/misc.ts b/src/misc.ts index 228e999..18ddc10 100644 --- a/src/misc.ts +++ b/src/misc.ts @@ -515,15 +515,15 @@ export const retriedFetch = async ( try { return await fetch(url, requestInit); } catch (error) { - console.error('Retrying failed fetch. Error:', error); - attempts++; - const retryDelayInSeconds = getRetryDelay(attempts); + if (retryDelayInSeconds === null) { throw error; } + console.error('Retrying failed fetch. Error:', error); + if (!Number.isFinite(retryDelayInSeconds) || retryDelayInSeconds < 0) { throw new TypeError('Retry delay must be a non-negative finite number.'); } diff --git a/src/source.ts b/src/source.ts index 30cb989..1fc4f2d 100644 --- a/src/source.ts +++ b/src/source.ts @@ -218,7 +218,8 @@ export class UrlSource extends Source { const buffer = await response.arrayBuffer(); - if (!range) { + if (response.status === 200) { + // The server didn't return 206 Partial Content, so it's not a range response this._fullData = buffer; } @@ -252,6 +253,26 @@ export class UrlSource extends Source { return this._fullData.byteLength; } + // First, try a HEAD request to get the size + try { + const headResponse = await retriedFetch( + this._url, + mergeObjectsDeeply(this._options.requestInit ?? {}, { + method: 'HEAD', + }), + this._options.getRetryDelay ?? (() => null), + ); + + if (headResponse.ok) { + const contentLength = headResponse.headers.get('Content-Length'); + if (contentLength) { + return parseInt(contentLength); + } + } + } catch { + // We tried + } + // Try a range request to get the Content-Range header const rangeResponse = await retriedFetch( this._url, @@ -267,9 +288,13 @@ export class UrlSource extends Source { if (contentRange) { const match = contentRange.match(/bytes \d+-\d+\/(\d+)/); if (match && match[1]) { - return parseInt(match[1], 10); + return parseInt(match[1]); } } + } else if (rangeResponse.status === 200) { + // The server just returned the whole thing + this._fullData = await rangeResponse.arrayBuffer(); + return this._fullData.byteLength; } // If the range request didn't provide the size, make a full GET request