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 ships with a powerful built-in file conversion abstraction that makes it easy to convert media files between formats, resize video, change codecs, trim clips, and more.
Features
The conversion API supports:
Transmuxing - Change the container format
Transcoding - Change track codecs
Track removal - Remove unwanted tracks
Compression - Reduce file size with lower bitrates
Trimming - Extract specific time ranges
Video resizing & fitting - Change dimensions and aspect ratio
Video rotation - Rotate video frames
Video cropping - Extract rectangular regions
Frame rate adjustment - Change video frame rate
Audio resampling - Change sample rate and channel count
Custom processing - Apply filters and effects
Basic usage
Create input and output
import {
Input ,
Output ,
Conversion ,
ALL_FORMATS ,
BlobSource ,
WebMOutputFormat ,
BufferTarget ,
} from 'mediabunny' ;
const input = new Input ({
source: new BlobSource ( file ),
formats: ALL_FORMATS ,
});
const output = new Output ({
format: new WebMOutputFormat (),
target: new BufferTarget (),
});
Initialize the conversion
const conversion = await Conversion . init ({ input , output });
if ( ! conversion . isValid ) {
// Check why tracks were discarded
console . log ( conversion . discardedTracks );
return ;
}
Execute the conversion
await conversion . execute ();
// Get the final file
const convertedFile = output . target . buffer ;
The Output passed to the conversion must be fresh - no tracks added, no metadata set, and in the 'pending' state.
Monitoring progress
Track conversion progress with the onProgress callback:
const conversion = await Conversion . init ({ input , output });
conversion . onProgress = ( progress ) => {
// progress is a number between 0 and 1
console . log ( ` ${ ( progress * 100 ). toFixed ( 1 ) } %` );
};
await conversion . execute ();
A progress of 1 doesn’t mean the conversion is finished - the conversion is only complete when execute() resolves.
Video options
Configure video track conversion with the video option:
Resizing video
const conversion = await Conversion . init ({
input ,
output ,
video: {
width: 1280 ,
height: 720 ,
fit: 'contain' , // 'fill' | 'contain' | 'cover'
},
});
Contains the entire image within the box while preserving aspect ratio. May result in letterboxing.
Scales the image until the entire box is filled, while preserving aspect ratio. May crop the image.
Stretches the image to fill the entire box, potentially altering the aspect ratio.
If only width or height is provided, the other dimension is calculated automatically to preserve aspect ratio.
Rotating video
video : {
rotate : 90 , // Degrees clockwise: 0 | 90 | 180 | 270
allowRotationMetadata : false , // Bake rotation into frames
}
Rotation is applied on top of any rotation metadata in the input file and happens before cropping and resizing.
Cropping video
video : {
crop : {
left : 100 ,
top : 50 ,
width : 1280 ,
height : 720 ,
},
}
Cropping is applied after rotation but before resizing.
Transcoding video
import { QUALITY_HIGH } from 'mediabunny' ;
video : {
codec : 'vp9' ,
bitrate : 2e6 , // 2 Mbps, or use QUALITY_HIGH
keyFrameInterval : 5 , // Key frame every 5 seconds
frameRate : 30 ,
alpha : 'keep' , // 'discard' | 'keep'
}
Processing video frames
Apply custom processing to each frame:
let ctx : CanvasRenderingContext2D | null = null ;
video : {
process : ( sample ) => {
if ( ! ctx ) {
const canvas = new OffscreenCanvas (
sample . displayWidth ,
sample . displayHeight
);
ctx = canvas . getContext ( '2d' ) ! ;
// Convert to grayscale
ctx . filter = 'saturate(0)' ;
}
sample . draw ( ctx , 0 , 0 );
return ctx . canvas ;
},
}
The process function can return:
A VideoSample
A CanvasImageSource (canvas, image, video frame)
An array of either
null to drop the frame
Audio options
Configure audio track conversion with the audio option:
Resampling audio
const conversion = await Conversion . init ({
input ,
output ,
audio: {
numberOfChannels: 2 , // Stereo
sampleRate: 48000 , // 48 kHz
},
});
Mediabunny performs automatic up/downmixing using the same algorithm as the Web Audio API.
Transcoding audio
import { QUALITY_MEDIUM } from 'mediabunny' ;
audio : {
codec : 'opus' ,
bitrate : 128e3 , // 128 kbps, or use QUALITY_MEDIUM
}
Processing audio samples
audio : {
process : ( sample ) => {
// Apply audio effects, transformations, etc.
return sample ;
},
}
Track-specific options
Apply different options to each track using functions:
const conversion = await Conversion . init ({
input ,
output ,
// Called for each video track
video : ( videoTrack ) => {
if ( videoTrack . number > 1 ) {
// Keep only the first video track
return { discard: true };
}
return {
// Shrink width to 640 only if wider
width: Math . min ( videoTrack . displayWidth , 640 ),
};
},
// Called for each audio track
audio : async ( audioTrack ) => {
if ( audioTrack . languageCode !== 'eng' ) {
// Keep only English audio tracks
return { discard: true };
}
return {
codec: 'aac' ,
bitrate: 128e3 ,
};
},
});
Trimming
Extract a specific time range from the input:
const conversion = await Conversion . init ({
input ,
output ,
trim: {
start: 10 , // Start at 10 seconds
end: 25 , // End at 25 seconds
},
});
The output will be 15 seconds long and will begin at timestamp 0.
You can also use negative values to add padding:
trim : {
start : - 2 , // Two seconds of freeze frame/silence at start
}
Control metadata tags in the output:
Set custom metadata
Augment input metadata
Remove all metadata
const conversion = await Conversion . init ({
input ,
output ,
tags: {
title: 're:Turning' ,
artist: 'Alexander Panos' ,
},
});
Discarded tracks
If an input track is excluded from the output, it’s considered discarded:
const conversion = await Conversion . init ({ input , output });
console . log ( conversion . discardedTracks );
// => DiscardedTrack[]
console . log ( conversion . isValid );
// => boolean
Possible discard reasons:
'discarded_by_user' - You set discard: true
'max_track_count_reached' - No room for more tracks
'max_track_count_of_type_reached' - No room for this track type
'unknown_source_codec' - Codec not recognized
'undecodable_source_codec' - Can’t decode the source
'no_encodable_target_codec' - Can’t find an encodable codec for output format
Canceling a conversion
await conversion . cancel ();
This frees up resources and causes any ongoing execute() call to throw a ConversionCanceledError.
Examples
Compress video
Convert to WebM
Extract 30-second clip
Resize and rotate
import { Conversion , QUALITY_VERY_LOW } from 'mediabunny' ;
const conversion = await Conversion . init ({
input ,
output ,
video: {
width: 320 ,
bitrate: QUALITY_VERY_LOW ,
},
audio: {
bitrate: 32e3 ,
},
});
await conversion . execute ();