Documentation Index Fetch the complete documentation index at: https://mintlify.com/Vanilagy/mediabunny/llms.txt
Use this file to discover all available pages before exploring further.
Mediabunny uses Sources for reading data and Targets for writing data. These abstractions allow you to work with media files from various locations - memory, disk, network, or streams - using the same consistent API.
Sources for reading
A Source represents where you read media data from. All sources inherit from the abstract Source base class.
export abstract class Source {
abstract _retrieveSize () : MaybePromise < number | null >;
abstract _read ( start : number , end : number ) : MaybePromise < ReadResult | null >;
abstract _dispose () : void ;
async getSizeOrNull () : Promise < number | null >
async getSize () : Promise < number >
onread : (( start : number , end : number ) => unknown ) | null = null ;
}
BlobSource
Reads from a browser Blob or File object - perfect for file uploads and client-side processing.
export class BlobSource extends Source {
constructor ( blob : Blob , options : BlobSourceOptions = {})
}
BufferSource
Reads from an ArrayBuffer or ArrayBufferView in memory - ideal for small files or pre-loaded data.
export class BufferSource extends Source {
constructor ( buffer : AllowSharedBufferSource )
}
From ArrayBuffer
From Uint8Array
From fetch response
const arrayBuffer = await file . arrayBuffer ();
const source = new BufferSource ( arrayBuffer );
BufferSource loads the entire file into memory. Use BlobSource or UrlSource for large files.
UrlSource
Reads from a remote URL using HTTP range requests - perfect for streaming from servers or CDNs.
export class UrlSource extends Source {
constructor (
url : string | URL | Request ,
options : UrlSourceOptions = {}
)
}
import { Input , MP4 , UrlSource } from 'mediabunny' ;
const input = new Input ({
formats: [ MP4 ],
source: new UrlSource ( 'https://example.com/video.mp4' )
});
const source = new UrlSource ( 'https://example.com/video.mp4' , {
getRetryDelay : ( attempts , error , url ) => {
// Exponential backoff: 1s, 2s, 4s, 8s, then give up
if ( attempts >= 4 ) return null ;
return Math . pow ( 2 , attempts );
}
});
const source = new UrlSource ( 'https://example.com/video.mp4' , {
maxCacheSize: 64 * 1024 * 1024 , // 64 MB cache
parallelism: 4 // 4 parallel requests
});
UrlSource uses intelligent prefetching to minimize latency and optimize for sequential access patterns.
FilePathSource
Reads from a file path on the server - for Node.js, Bun, or Deno environments.
export class FilePathSource extends Source {
constructor ( filePath : string , options : FilePathSourceOptions = {})
}
import { Input , MP4 , FilePathSource } from 'mediabunny' ;
// Node.js / Bun / Deno
const input = new Input ({
formats: [ MP4 ],
source: new FilePathSource ( '/path/to/video.mp4' )
});
await processVideo ( input );
// IMPORTANT: Free the file handle when done
input . dispose ();
Always call input.dispose() to close the file handle when using FilePathSource.
StreamSource
A general-purpose, callback-driven source for custom reading logic.
export class StreamSource extends Source {
constructor ( options : StreamSourceOptions )
}
Custom implementation
S3 example
const source = new StreamSource ({
getSize : async () => {
// Return file size
return await getCustomFileSize ();
},
read : async ( start , end ) => {
// Return bytes for the requested range
return await fetchBytesFromCustomSource ( start , end );
},
dispose : () => {
// Clean up resources
closeCustomConnection ();
},
maxCacheSize: 8 * 1024 * 1024 ,
prefetchProfile: 'network'
});
import { S3Client , GetObjectCommand } from '@aws-sdk/client-s3' ;
const s3Client = new S3Client ({ region: 'us-east-1' });
const source = new StreamSource ({
getSize : async () => {
const headResult = await s3Client . send ( new HeadObjectCommand ({
Bucket: 'my-bucket' ,
Key: 'video.mp4'
}));
return headResult . ContentLength ;
},
read : async ( start , end ) => {
const result = await s3Client . send ( new GetObjectCommand ({
Bucket: 'my-bucket' ,
Key: 'video.mp4' ,
Range: `bytes= ${ start } - ${ end - 1 } `
}));
return await result . Body . transformToByteArray ();
},
prefetchProfile: 'network'
});
ReadableStreamSource
Reads from a ReadableStream<Uint8Array> - perfect for processing data as it arrives.
export class ReadableStreamSource extends Source {
constructor (
stream : ReadableStream < Uint8Array >,
options : ReadableStreamSourceOptions = {}
)
}
import { Input , MP4 , ReadableStreamSource } from 'mediabunny' ;
// From MediaRecorder
const mediaRecorder = new MediaRecorder ( stream );
const chunks = [];
const readable = new ReadableStream ({
start ( controller ) {
mediaRecorder . ondataavailable = ( e ) => {
controller . enqueue ( new Uint8Array ( await e . data . arrayBuffer ()));
};
mediaRecorder . onstop = () => controller . close ();
mediaRecorder . start ();
}
});
const input = new Input ({
formats: [ MP4 , WEBM ],
source: new ReadableStreamSource ( readable )
});
ReadableStreamSource is unsized - it doesn’t know the total length. This limits seeking and random access.
Targets for writing
A Target represents where you write media data to. All targets inherit from the abstract Target base class.
export abstract class Target {
abstract _createWriter () : Writer ;
onwrite : (( start : number , end : number ) => unknown ) | null = null ;
}
BufferTarget
Writes to an ArrayBuffer in memory - great for small files or when you need the complete buffer.
export class BufferTarget extends Target {
buffer : ArrayBuffer | null = null ;
}
Basic usage
Download file
import { Output , Mp4OutputFormat , BufferTarget } from 'mediabunny' ;
const target = new BufferTarget ();
const output = new Output ({
format: new Mp4OutputFormat (),
target
});
// ... add tracks, samples, etc.
await output . finalize ();
// Access the result
const arrayBuffer = target . buffer ;
const blob = new Blob ([ arrayBuffer ], { type: 'video/mp4' });
const target = new BufferTarget ();
// ... create and finalize output ...
// Download in browser
const blob = new Blob ([ target . buffer ], { type: 'video/mp4' });
const url = URL . createObjectURL ( blob );
const a = document . createElement ( 'a' );
a . href = url ;
a . download = 'output.mp4' ;
a . click ();
URL . revokeObjectURL ( url );
BufferTarget stores the entire output in memory. For large files, use StreamTarget or FilePathTarget.
StreamTarget
Writes to a WritableStream<StreamTargetChunk> - versatile target for streaming, files, or custom destinations.
export class StreamTarget extends Target {
constructor (
writable : WritableStream < StreamTargetChunk >,
options : StreamTargetOptions = {}
)
}
File System Access API
With chunking
Custom WritableStream
// Write to user's file system (browser)
const fileHandle = await window . showSaveFilePicker ({
suggestedName: 'output.mp4' ,
types: [{
description: 'MP4 Video' ,
accept: { 'video/mp4' : [ '.mp4' ] }
}]
});
const writable = await fileHandle . createWritable ();
const target = new StreamTarget ( writable );
const output = new Output ({
format: new Mp4OutputFormat (),
target
});
// ... process ...
await output . finalize ();
// File is automatically saved!
// Accumulate data in 16 MB chunks before writing
const target = new StreamTarget ( writable , {
chunked: true ,
chunkSize: 16 * 1024 * 1024
});
const chunks = [];
const writable = new WritableStream ({
write ( chunk ) {
console . log ( `Writing ${ chunk . data . length } bytes at position ${ chunk . position } ` );
chunks . push ( chunk );
},
close () {
console . log ( 'Stream closed' );
}
});
const target = new StreamTarget ( writable );
FilePathTarget
Writes to a file path on the server - for Node.js, Bun, or Deno.
export class FilePathTarget extends Target {
constructor ( filePath : string , options : FilePathTargetOptions = {})
}
import { Output , Mp4OutputFormat , FilePathTarget } from 'mediabunny' ;
// Node.js / Bun / Deno
const output = new Output ({
format: new Mp4OutputFormat (),
target: new FilePathTarget ( '/path/to/output.mp4' , {
chunked: true // Write in chunks (recommended)
})
});
// ... add tracks, samples ...
await output . finalize ();
// File is written to disk!
Use chunked: true (default) for better performance with FilePathTarget.
NullTarget
Discards all data - useful when extracting data through callbacks or events.
export class NullTarget extends Target {
// Discards all writes
}
import { Output , Mp4OutputFormat , NullTarget } from 'mediabunny' ;
// Extract fragments without keeping the full file
const output = new Output ({
format: new Mp4OutputFormat ({
fastStart: 'fragmented' ,
onMoof : ( data , position , timestamp ) => {
// Save this fragment separately
saveFragment ( data , timestamp );
}
}),
target: new NullTarget ()
});
// The main output is discarded, but fragments are captured
Choosing the right source and target
Browser
Node.js / Bun / Deno
Sources:
✅ BlobSource - File uploads, drag-and-drop
✅ UrlSource - Remote video streaming
✅ BufferSource - Small files in memory
✅ ReadableStreamSource - MediaRecorder output
Targets:
✅ BufferTarget - Download files
✅ StreamTarget - File System Access API, custom streams
✅ NullTarget - Extract specific data via callbacks
Sources:
✅ FilePathSource - Local files
✅ UrlSource - Remote files
✅ StreamSource - S3, databases, custom storage
✅ BufferSource - Small files in memory
Targets:
✅ FilePathTarget - Write to disk
✅ StreamTarget - Custom WritableStream
✅ BufferTarget - Keep in memory
✅ NullTarget - Extract fragments
Use appropriate caching Configure maxCacheSize based on file size and access patterns. Larger caches reduce I/O but use more memory.
Enable chunking Use chunked: true for StreamTarget and FilePathTarget to reduce write overhead.
Tune parallelism For UrlSource, increase parallelism for faster downloads on high-bandwidth connections.
Choose prefetch profiles Use 'network' for remote sources, 'fileSystem' for local files, 'none' for random access.
Monitoring reads and writes
Both sources and targets provide callbacks to monitor data flow:
Monitor reads
Monitor writes
const source = new UrlSource ( 'https://example.com/video.mp4' );
source . onread = ( start , end ) => {
console . log ( `Read bytes ${ start } - ${ end } ( ${ end - start } bytes)` );
};
These callbacks are called very frequently - avoid heavy processing inside them.
Next steps
Input and Output Learn how to use sources and targets with Input and Output
Formats and Codecs Understand which formats work with your sources