Compare commits

...
1 Commits
Author SHA1 Message Date
Vanilagy c4d13ed698 Improve UrlSource fetching logic 2025-07-25 12:07:54 +02:00
4 changed files with 33 additions and 8 deletions
+2 -2
View File
@@ -1,12 +1,12 @@
{ {
"name": "mediabunny", "name": "mediabunny",
"version": "1.3.0", "version": "1.3.1",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "mediabunny", "name": "mediabunny",
"version": "1.3.0", "version": "1.3.1",
"license": "MPL-2.0", "license": "MPL-2.0",
"dependencies": { "dependencies": {
"@types/dom-mediacapture-transform": "^0.1.11", "@types/dom-mediacapture-transform": "^0.1.11",
+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"name": "mediabunny", "name": "mediabunny",
"author": "Vanilagy", "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.", "description": "Pure TypeScript media toolkit for reading, writing, and converting media files, directly in the browser.",
"type": "module", "type": "module",
"main": "./dist/bundles/mediabunny.cjs", "main": "./dist/bundles/mediabunny.cjs",
+3 -3
View File
@@ -515,15 +515,15 @@ export const retriedFetch = async (
try { try {
return await fetch(url, requestInit); return await fetch(url, requestInit);
} catch (error) { } catch (error) {
console.error('Retrying failed fetch. Error:', error);
attempts++; attempts++;
const retryDelayInSeconds = getRetryDelay(attempts); const retryDelayInSeconds = getRetryDelay(attempts);
if (retryDelayInSeconds === null) { if (retryDelayInSeconds === null) {
throw error; throw error;
} }
console.error('Retrying failed fetch. Error:', error);
if (!Number.isFinite(retryDelayInSeconds) || retryDelayInSeconds < 0) { if (!Number.isFinite(retryDelayInSeconds) || retryDelayInSeconds < 0) {
throw new TypeError('Retry delay must be a non-negative finite number.'); throw new TypeError('Retry delay must be a non-negative finite number.');
} }
+27 -2
View File
@@ -218,7 +218,8 @@ export class UrlSource extends Source {
const buffer = await response.arrayBuffer(); 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; this._fullData = buffer;
} }
@@ -252,6 +253,26 @@ export class UrlSource extends Source {
return this._fullData.byteLength; 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 // Try a range request to get the Content-Range header
const rangeResponse = await retriedFetch( const rangeResponse = await retriedFetch(
this._url, this._url,
@@ -267,9 +288,13 @@ export class UrlSource extends Source {
if (contentRange) { if (contentRange) {
const match = contentRange.match(/bytes \d+-\d+\/(\d+)/); const match = contentRange.match(/bytes \d+-\d+\/(\d+)/);
if (match && match[1]) { 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 // If the range request didn't provide the size, make a full GET request