Compare commits

...
7 Commits
Author SHA1 Message Date
Vanilagy cacbc2a399 Fix assertion failure 2026-02-07 10:35:40 +01:00
Vanilagy ab0fd6a8d8 Fix WAVE demuxer out of bounds reads 2026-02-07 10:28:14 +01:00
Vanilagy 6a099b4259 Bump minor 2026-02-04 18:28:34 +01:00
Vanilagy 172b4a1fd2 Add two new sponsors 2026-02-04 16:54:45 +01:00
David P.andGitHub 43c1ea7efd Merge pull request #292 from fredrikj/parallelism
Add UrlSourceOptions.parallelism
2026-02-03 16:03:55 +01:00
Vanilagy cab92c55ec Fix a few things 2026-02-03 16:01:46 +01:00
Fredrik Johansson 3209363470 Add UrlSourceOptions.parallelism 2026-01-29 09:31:51 +01:00
7 changed files with 30 additions and 12 deletions
+3
View File
@@ -506,6 +506,9 @@ type UrlSourceOptions = {
// in memory. Defaults to 8 MiB.
maxCacheSize?: number;
// The maximum number of parallel requests to use for fetching. Defaults to 2.
parallelism?: number;
// Used to provide a custom fetch function
fetchFn?: typeof fetch;
};
+2
View File
@@ -113,6 +113,7 @@ const sponsors = {
{ image: 'https://avatars.githubusercontent.com/u/84167135', name: 'Memenome', url: 'https://github.com/memenome' },
{ image: 'https://avatars.githubusercontent.com/u/5913254', name: 'Brandon McConnell', url: 'https://github.com/brandonmcconnell' },
{ image: 'https://avatars.githubusercontent.com/u/9549394', name: 'studnitz', url: 'https://github.com/studnitz' },
{ image: 'https://avatars.githubusercontent.com/u/4714175', name: 'Phoomparin Mano', url: 'https://github.com/heypoom' },
{ image: 'https://avatars.githubusercontent.com/u/504909', name: 'Hirbod', url: 'https://github.com/hirbod' },
{ image: 'https://avatars.githubusercontent.com/u/2698271', name: 'Matthew Gardner', url: 'https://github.com/spheric' },
{ image: 'https://avatars.githubusercontent.com/u/5475819', name: 'AJ Funk', url: 'https://github.com/AJFunk' },
@@ -122,6 +123,7 @@ const sponsors = {
{ image: 'https://avatars.githubusercontent.com/u/38181164', name: 'wcw', url: 'https://github.com/asd55667' },
{ image: 'https://avatars.githubusercontent.com/u/1836701', name: 'Bean Deng', url: 'https://github.com/HADB' },
{ image: 'https://avatars.githubusercontent.com/u/255616819', name: 'cronischarles-del', url: 'https://github.com/cronischarles-del' },
{ image: 'https://avatars.githubusercontent.com/u/37973863', name: 'Gomi', url: 'https://github.com/gxy5202' },
{ image: 'https://avatars.githubusercontent.com/u/63088713', name: 'taf2000', url: 'https://github.com/taf2000' },
{ image: 'https://avatars.githubusercontent.com/u/58149663', name: 'H7GhosT', url: 'https://github.com/H7GhosT' },
{ image: 'https://avatars.githubusercontent.com/u/91711202', name: 'ihasq', url: 'https://github.com/ihasq' },
+6 -6
View File
@@ -1,12 +1,12 @@
{
"name": "mediabunny",
"version": "1.31.1",
"version": "1.32.2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "mediabunny",
"version": "1.31.1",
"version": "1.32.2",
"license": "MPL-2.0",
"workspaces": [
"packages/*"
@@ -7739,9 +7739,9 @@
}
},
"node_modules/mediabunny": {
"version": "1.31.0",
"resolved": "https://registry.npmjs.org/mediabunny/-/mediabunny-1.31.0.tgz",
"integrity": "sha512-nqM+6cOpNC/aDxCAZKnZe7oXnGaCn4rlgprzAmiH6C8GRdOHFnB6bZC0+WXGTT6mtAxXQd+BXuZ2q2zkma7dWg==",
"version": "1.32.1",
"resolved": "https://registry.npmjs.org/mediabunny/-/mediabunny-1.32.1.tgz",
"integrity": "sha512-pPxhBEIY7dNEhRarN/DTVL56RTce0iCwNwkhu/at+S9S/HKc01PpHs8oM2I+1I9ztQH/bo2zdyszxDuAwsEBAg==",
"license": "MPL-2.0",
"peer": true,
"workspaces": [
@@ -12065,7 +12065,7 @@
},
"packages/mp3-encoder": {
"name": "@mediabunny/mp3-encoder",
"version": "1.31.1",
"version": "1.32.2",
"license": "MPL-2.0",
"devDependencies": {
"@types/emscripten": "^1.40.1"
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "mediabunny",
"author": "Vanilagy",
"version": "1.31.1",
"version": "1.32.2",
"description": "Pure TypeScript media toolkit for reading, writing, and converting media files, directly in the browser.",
"type": "module",
"workspaces": [
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@mediabunny/mp3-encoder",
"author": "Vanilagy",
"version": "1.31.1",
"version": "1.32.2",
"description": "MP3 encoder extension for Mediabunny, based on LAME.",
"main": "./dist/bundles/mediabunny-mp3-encoder.mjs",
"module": "./dist/bundles/mediabunny-mp3-encoder.mjs",
+11 -3
View File
@@ -343,6 +343,9 @@ export type UrlSourceOptions = {
/** The maximum number of bytes the cache is allowed to hold in memory. Defaults to 64 MiB. */
maxCacheSize?: number;
/** The maximum number of parallel requests to use for fetching. Defaults to 2. */
parallelism?: number;
/**
* A WHATWG-compatible fetch function. You can use this field to polyfill the `fetch` function, add missing
* features, or use a custom implementation.
@@ -403,6 +406,9 @@ export class UrlSource extends Source {
) {
throw new TypeError('options.maxCacheSize, when provided, must be a non-negative number.');
}
if (options.parallelism !== undefined && (!Number.isInteger(options.parallelism) || options.parallelism < 1)) {
throw new TypeError('options.parallelism, when provided, must be a positive number.');
}
if (options.fetchFn !== undefined && typeof options.fetchFn !== 'function') {
throw new TypeError('options.fetchFn, when provided, must be a function.');
// Won't bother validating this function beyond this
@@ -414,11 +420,13 @@ export class UrlSource extends Source {
this._options = options;
this._getRetryDelay = options.getRetryDelay ?? DEFAULT_RETRY_DELAY;
// Most files in the real-world have a single sequential access pattern, but having two in parallel can
// also happen
const DEFAULT_PARALLELISM = 2;
this._orchestrator = new ReadOrchestrator({
maxCacheSize: options.maxCacheSize ?? (64 * 2 ** 20 /* 64 MiB */),
// Most files in the real-world have a single sequential access pattern, but having two in parallel can
// also happen
maxWorkerCount: 2,
maxWorkerCount: options.parallelism ?? DEFAULT_PARALLELISM,
runWorker: this._runWorker.bind(this),
prefetchProfile: PREFETCH_PROFILES.network,
});
+6 -1
View File
@@ -425,6 +425,8 @@ class WaveAudioTrackBacking implements InputAudioTrackBacking {
packetIndex: number,
options: PacketRetrievalOptions,
): Promise<EncodedPacket | null> {
assert(packetIndex >= 0);
assert(this.demuxer.audioInfo);
const startOffset = packetIndex * PACKET_SIZE_IN_FRAMES * this.demuxer.audioInfo.blockSizeInBytes;
if (startOffset >= this.demuxer.dataSize) {
@@ -465,7 +467,7 @@ class WaveAudioTrackBacking implements InputAudioTrackBacking {
this.demuxer.lastKnownPacketIndex = Math.max(
packetIndex,
timestamp,
this.demuxer.lastKnownPacketIndex,
);
return new EncodedPacket(
@@ -489,6 +491,9 @@ class WaveAudioTrackBacking implements InputAudioTrackBacking {
timestamp * this.demuxer.audioInfo.sampleRate / PACKET_SIZE_IN_FRAMES,
(this.demuxer.dataSize - 1) / (PACKET_SIZE_IN_FRAMES * this.demuxer.audioInfo.blockSizeInBytes),
));
if (packetIndex < 0) {
return null;
}
const packet = await this.getPacketAtIndex(packetIndex, options);
if (packet) {