### Install Mediabunny using Package Managers (Bash) Source: https://mediabunny.dev/guide/installation Install Mediabunny using your preferred JavaScript package manager. This command installs the library for use in your project. ```bash npm install mediabunny ``` ```bash yarn add mediabunny ``` ```bash pnpm add mediabunny ``` ```bash bun add mediabunny ``` -------------------------------- ### Include Mediabunny via Script Tag (HTML) Source: https://mediabunny.dev/guide/installation Include the Mediabunny library directly in your HTML file using a script tag. This method adds a global `Mediabunny` object to the window scope. ```html ``` -------------------------------- ### MediaStreamAudioTrackSource Setup - TypeScript Source: https://mediabunny.dev/guide/media-sources Demonstrates how to set up MediaStreamAudioTrackSource to capture real-time audio from a MediaStream, such as a microphone. It includes obtaining the audio track and configuring the source with codec and bitrate, along with essential error handling. ```typescript import { MediaStreamAudioTrackSource } from 'mediabunny'; // Get the user's microphone const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); const audioTrack = stream.getAudioTracks()[0]; const audioTrackSource = new MediaStreamAudioTrackSource(audioTrack, { codec: 'opus', bitrate: 128e3, }); // Make sure to allow any internal errors to properly bubble up audioTrackSource.errorPromise.catch((error) => ...); ``` -------------------------------- ### Add Media Data using Media Sources Source: https://mediabunny.dev/guide/media-sources This pattern demonstrates the basic usage of adding media data to an output file using a media source. It is a common starting point for integrating media into your project. The `add` method is asynchronous and returns a promise. ```typescript await mediaSource.add(...); ``` -------------------------------- ### Import Mediabunny in JavaScript (TypeScript/JavaScript) Source: https://mediabunny.dev/guide/installation Import the Mediabunny library into your JavaScript or TypeScript project. Supports both ECMAScript Modules (ESM) and CommonJS (CJS) module systems. ESM is recommended for tree-shaking. ```typescript import { ... } from 'mediabunny'; // ESM ``` ```javascript const { ... } = require('mediabunny'); // or CommonJS ``` -------------------------------- ### Install mediabunny and mp3-encoder (npm) Source: https://mediabunny.dev/guide/extensions/mp3-encoder Installs the mediabunny library and the mp3-encoder extension package using npm. This is a prerequisite for using the MP3 encoder. ```bash npm install mediabunny @mediabunny/mp3-encoder ``` -------------------------------- ### Create VideoSampleSource Source: https://mediabunny.dev/guide/media-sources Initializes a VideoSampleSource for encoding and adding video samples. Requires codec and bitrate, and supports adding samples with optional key frame forcing. ```typescript import { VideoSampleSource } from 'mediabunny'; const sampleSource = new VideoSampleSource({ codec: 'avc', bitrate: 1e6, }); await sampleSource.add(videoSample); videoSample.close(); // If it's not needed anymore // You may optionally force samples to be encoded as key frames: await sampleSource.add(videoSample, { keyFrame: true }); ``` -------------------------------- ### Record Live Media with mediabunny Source: https://mediabunny.dev/guide/quick-start Records live media streams (video and audio) using mediabunny. It obtains user media, configures an Output with WebM format and BufferTarget, adds video and audio tracks with specified codecs and quality, then starts and finalizes the recording. This is presented as an alternative to the native MediaRecorder API. ```typescript import { Output, BufferTarget, WebMOutputFormat, MediaStreamVideoTrackSource, MediaStreamAudioTrackSource, QUALITY_MEDIUM } from 'mediabunny'; const userMedia = await navigator.mediaDevices.getUserMedia({ video: true, audio: true, }); const videoTrack = userMedia.getVideoTracks()[0]; const audioTrack = userMedia.getAudioTracks()[0]; const output = new Output({ format: new WebMOutputFormat(), target: new BufferTarget(), }); if (videoTrack) { const source = new MediaStreamVideoTrackSource(videoTrack, { codec: 'vp9', bitrate: QUALITY_MEDIUM, }); output.addVideoTrack(source); } if (audioTrack) { const source = new MediaStreamAudioTrackSource(audioTrack, { codec: 'opus', bitrate: QUALITY_MEDIUM, }); output.addAudioTrack(source); } await output.start(); // Wait... await output.finalize(); ``` -------------------------------- ### Example Video Decoder Configuration Source: https://mediabunny.dev/guide/reading-media-files An example of a `VideoDecoderConfig` object for a 1080p video, showcasing the codec string, coded dimensions, and the decoder-specific description bytes (AVCDecoderConfigurationRecord). ```json { "codec": "avc1.4d4029", "codedWidth": 1920, "codedHeight": 1080, "description": new Uint8Array([ // Bytes of the AVCDecoderConfigurationRecord 1, 77, 64, 41, 255, 225, 0, 22, 39, 77, 64, 41, 169, 24, 15, 0, 68, 252, 184, 3, 80, 16, 16, 27, 108, 43, 94, 247, 192, 64, 1, 0, 4, 40, 222, 9, 200, ]) } ``` -------------------------------- ### AudioSampleSource Usage - TypeScript Source: https://mediabunny.dev/guide/media-sources Shows how to initialize and use the AudioSampleSource to encode and add audio samples to an output. It highlights the codec and bitrate configuration and the add method for providing audio data. ```typescript import { AudioSampleSource } from 'mediabunny'; const sampleSource = new AudioSampleSource({ codec: 'aac', bitrate: 128e3, }); await sampleSource.add(audioSample); audioSample.close(); // If it's not needed anymore ``` -------------------------------- ### Example Audio Decoder Configuration Source: https://mediabunny.dev/guide/reading-media-files An example of an `AudioDecoderConfig` object for an AAC audio track, detailing the codec, number of channels, sample rate, and the audio-specific description bytes (AudioSpecificConfig). ```json { "codec": "mp4a.40.2", "numberOfChannels": 2, "sampleRate": 44100, "description": new Uint8Array([ // Bytes of the AudioSpecificConfig 17, 144, ]) } ``` -------------------------------- ### Canvas Pooling Example - TypeScript Source: https://mediabunny.dev/guide/media-sinks Demonstrates the usage of the `poolSize` option in CanvasSink for efficient memory management. By reusing a fixed number of canvases, it reduces VRAM allocation and deallocation overhead. ```typescript import { CanvasSink } from 'mediabunny'; // Assuming 'assert' is imported or available globally // Example with poolSize: 3 const sinkWithPool = new CanvasSink(videoTrack, { poolSize: 3 }); const a = await sinkWithPool.getCanvas(42); const b = await sinkWithPool.getCanvas(42); const c = await sinkWithPool.getCanvas(42); const d = await sinkWithPool.getCanvas(42); const e = await sinkWithPool.getCanvas(42); const f = await sinkWithPool.getCanvas(42); // Asserting canvas reuse assert(a.canvas === d.canvas); assert(b.canvas === e.canvas); assert(c.canvas === f.canvas); assert(a.canvas !== b.canvas); assert(a.canvas !== c.canvas); // Example with poolSize: 1 for closed iterators const sinkForIterator = new CanvasSink(videoTrack, { poolSize: 1 }); const canvasesIterator = sinkForIterator.canvases(); for await (const { canvas, timestamp } of canvasesIterator) { // Process canvas } ``` -------------------------------- ### Mediabunny Output API - Starting an Output Source: https://mediabunny.dev/guide/writing-media-files After all tracks have been added to the Output, you need to start it. This spins up the writing process, allows media data to be sent, and prevents adding new tracks. ```APIDOC ## Starting an Output After all tracks have been added to the `Output`, you need to *start* it. Starting an output spins up the writing process, allowing you to now start sending media data to the output file. It also prevents you from adding any new tracks to it. ```ts await output.start(); // Resolves once the output is ready to receive media data ``` ``` -------------------------------- ### QuickTime Output Format Initialization Source: https://mediabunny.dev/guide/output-formats Initializes the QuickTime (.mov) output format for mediabunny. Similar to MP4, it uses the Output class with MovOutputFormat, accepting the same configuration options as IsobmffOutputFormatOptions. ```typescript import { Output, MovOutputFormat } from 'mediabunny'; const output = new Output({ format: new MovOutputFormat(options), // ... }); ``` -------------------------------- ### Get Track Start Timestamp (TypeScript) Source: https://mediabunny.dev/guide/reading-media-files Retrieves the start timestamp of the first sample of a track in seconds. This value indicates when the track's media content begins presentation. It can be zero, positive (starting after composition), or negative (starting before composition, indicating cut-off data). ```typescript await track.getFirstTimestamp(); // => 0.041666666666666664 ``` -------------------------------- ### Convert Media Files with mediabunny Source: https://mediabunny.dev/guide/quick-start Converts media files between formats using mediabunny. It sets up an Input with BlobSource and ALL_FORMATS, an Output with Mp4OutputFormat and BufferTarget, and then initializes and executes a Conversion. This process can transmux or transcode as needed. ```typescript import { Input, Output, Conversion, ALL_FORMATS, BlobSource, Mp4OutputFormat, } from 'mediabunny'; // Check the above snippets for more examples of Input and Output const input = new Input({ formats: ALL_FORMATS, source: new BlobSource(file), }); const output = new Output({ format: new Mp4OutputFormat(), target: new BufferTarget(), }); const conversion = await Conversion.init({ input, output }); if (!conversion.isValid) { // The conversion isn't possible and would error upon execution. // Check `discardedTracks` for the reasons. return; } // List of tracks that won't make it into the output: conversion.discardedTracks; conversion.onProgress = (progress) => { progress; // Number between 0 and 1, inclusive }; await conversion.execute(); // Conversion is complete const buffer = output.target.buffer; // ArrayBuffer containing the final MP4 file ``` -------------------------------- ### Propagate Backpressure with Awaited Add Method Source: https://mediabunny.dev/guide/media-sources Illustrates the correct method for handling backpressure from media sources. By awaiting the promise returned by the `add` method, your application logic automatically pauses when the output pipeline cannot keep up, preventing data loss and ensuring smooth processing. The incorrect example shows a common mistake where backpressure is ignored. ```typescript // Wrong: // [!code error] while (notDone) { // [!code error] mediaSource.add(...); // [!code error] } // [!code error] // Correct: while (notDone) { await mediaSource.add(...); } ``` -------------------------------- ### Calculate Average Loudness with AudioSampleSink Source: https://mediabunny.dev/guide/media-sinks This example demonstrates calculating the average loudness (Root Mean Square) of an audio track using an AudioSampleSink. It iterates through audio samples, copies them to Float32Array, and computes the average. Dependencies include the AudioSampleSink and basic JavaScript math functions. ```typescript const sink = new AudioSampleSink(audioTrack); let sumOfSquares = 0; let totalSampleCount = 0; for await (const sample of sink.samples()) { const bytesNeeded = sample.allocationSize({ format: 'f32', planeIndex: 0 }); const floats = new Float32Array(bytesNeeded / 4); sample.copyTo(floats, { format: 'f32', planeIndex: 0 }); for (let i = 0; i < floats.length; i++) { sumOfSquares += floats[i] ** 2; } totalSampleCount += floats.length; } const averageLoudness = Math.sqrt(sumOfSquares / totalSampleCount); ``` -------------------------------- ### Configure WAVE Output Options Source: https://mediabunny.dev/guide/output-formats Defines the configuration options for WAVE output format. Includes `large` for RF64 compliance, `metadataFormat` for INFO or ID3 tags, and `onHeader` for header writing callbacks. ```typescript type WavOutputFormatOptions = { large?: boolean; metadataFormat?: 'info' | 'id3'; onHeader?: (data: Uint8Array, position: number) => unknown; }; ``` -------------------------------- ### Create WebM Output with MediaBunny Source: https://mediabunny.dev/guide/output-formats This snippet demonstrates how to initialize an Output object with the WebMOutputFormat. It takes options to configure the WebM file generation, such as append-only writing and minimum cluster duration. ```typescript import { Output, WebMOutputFormat } from 'mediabunny'; const output = new Output({ format: new WebMOutputFormat(options), // ... }); ``` -------------------------------- ### Create CanvasSink Instance - TypeScript Source: https://mediabunny.dev/guide/media-sinks Demonstrates the creation of a CanvasSink instance. This sink extracts video samples as canvases, allowing for transformations. It requires a video track and optional configuration options. ```typescript import { CanvasSink } from 'mediabunny'; const sink = new CanvasSink(videoTrack, options); type CanvasSinkOptions = { width?: number; height?: number; fit?: 'fill' | 'contain' | 'cover'; rotation?: 0 | 90 | 180 | 270; crop?: { left: number; top: number; width: number; height: number }; poolSize?: number; }; // Example usage with different options: // Default options, respecting track metadata new CanvasSink(videoTrack); // Specify width, maintain aspect ratio new CanvasSink(videoTrack, { width: 1280, }); // Square canvas, cover mode new CanvasSink(videoTrack, { width: 512, height: 512, fit: 'cover', }); // No rotation applied new CanvasSink(videoTrack, { rotation: 0, }); ``` -------------------------------- ### Create WAVE (.wav) Output with MediaBunny Source: https://mediabunny.dev/guide/output-formats This snippet shows how to initialize an Output object with the WavOutputFormat for creating WAVE files. Options allow for handling large files, specifying metadata format, and providing a header callback. ```typescript import { Output, WavOutputFormat } from 'mediabunny'; const output = new Output({ format: new WavOutputFormat(options), // ... }); ``` -------------------------------- ### MP4/QuickTime Output Format Options Source: https://mediabunny.dev/guide/output-formats Defines the configuration options for Isobmff-based output formats like MP4 and QuickTime. These options control metadata handling, fragment duration, metadata format, and callbacks for different file parts. ```typescript type IsobmffOutputFormatOptions = { fastStart?: false | 'in-memory' | 'reserve' | 'fragmented'; minimumFragmentDuration?: number; metadataFormat?: 'mdir' | 'mdta' | 'udta' | 'auto'; onFtyp?: (data: Uint8Array, position: number) => unknown; onMoov?: (data: Uint8Array, position: number) => unknown; onMdat?: (data: Uint8Array, position: number) => unknown; onMoof?: (data: Uint8Array, position: number, timestamp: number) => unknown; }; ``` -------------------------------- ### Extract Audio with mediabunny Source: https://mediabunny.dev/guide/quick-start Extracts audio from media files using mediabunny. It configures an Input and an Output with WavOutputFormat, specifying audio resampling to 16 kHz. The Conversion.init method is used to set up the audio extraction process. ```typescript import { Input, Output, Conversion, WavOutputFormat, } from 'mediabunny'; const input = new Input(...); const output = new Output({ // Write to a .wav file, keeping only the audio track format: new WavOutputFormat(), // ... }); const conversion = await Conversion.init({ input, output, audio: { sampleRate: 16000, // Resample to 16 kHz }, }); await conversion.execute(); // Conversion is complete ``` -------------------------------- ### Play Last 10 Seconds of Audio with AudioBufferSink Source: https://mediabunny.dev/guide/media-sinks This example shows how to play the last 10 seconds of an audio track using AudioBufferSink and the Web Audio API. It retrieves audio buffers for the specified time range and schedules them to play using an AudioContext. ```typescript const sink = new AudioBufferSink(audioTrack); const audioContext = new AudioContext(); const lastTimestamp = await audioTrack.computeDuration(); const baseTime = audioContext.currentTime; for await (const { buffer, timestamp } of sink.buffers(lastTimestamp - 10)) { const source = audioContext.createBufferSource(); source.buffer = buffer; source.connect(audioContext.destination); source.start(baseTime + timestamp); } ``` -------------------------------- ### MP4 Output Format Initialization Source: https://mediabunny.dev/guide/output-formats Initializes the MP4 output format for mediabunny. This involves creating an Output instance with Mp4OutputFormat, specifying various options for metadata placement and format. ```typescript import { Output, Mp4OutputFormat } from 'mediabunny'; const output = new Output({ format: new Mp4OutputFormat(options), // ... }); ``` -------------------------------- ### Create MediaStreamVideoTrackSource Source: https://mediabunny.dev/guide/media-sources Initializes a MediaStreamVideoTrackSource from a MediaStreamVideoTrack. This source pipes real-time video from sources like webcams. It requires the video track and configuration including codec and bitrate. Errors can be caught via errorPromise. ```typescript import { MediaStreamVideoTrackSource } from 'mediabunny'; // Get the user's screen const stream = await navigator.mediaDevices.getDisplayMedia({ video: true }); const videoTrack = stream.getVideoTracks()[0]; const videoTrackSource = new MediaStreamVideoTrackSource(videoTrack, { codec: 'vp9', bitrate: 1e7, }); // Make sure to allow any internal errors to properly bubble up videoTrackSource.errorPromise.catch((error) => ...); ``` -------------------------------- ### Create MP3 Output with MediaBunny Source: https://mediabunny.dev/guide/output-formats Demonstrates how to create an Output object with the Mp3OutputFormat for generating MP3 files. This includes options for enabling/disabling the Xing header and callbacks for Xing frame events. ```typescript import { Output, Mp3OutputFormat } from 'mediabunny'; const output = new Output({ format: new Mp3OutputFormat(options), // ... }); ``` -------------------------------- ### Configure Ogg Output Options Source: https://mediabunny.dev/guide/output-formats Defines the options available for the Ogg output format. The primary option is `onPage`, which is a callback function executed for each finalized Ogg page. ```typescript type OggOutputFormatOptions = { onPage?: (data: Uint8Array, position: number, source: MediaSource) => unknown; }; ``` -------------------------------- ### AudioBufferSource Usage - TypeScript Source: https://mediabunny.dev/guide/media-sources Illustrates the use of AudioBufferSource for directly accepting AudioBuffer objects. This is useful for integration with the Web Audio API, appending buffers sequentially. ```typescript import { AudioBufferSource, QUALITY_MEDIUM } from 'mediabunny'; const bufferSource = new AudioBufferSource({ codec: 'opus', bitrate: QUALITY_MEDIUM, }); await bufferSource.add(audioBuffer1); await bufferSource.add(audioBuffer2); await bufferSource.add(audioBuffer3); ``` -------------------------------- ### Create EncodedVideoPacketSource Source: https://mediabunny.dev/guide/media-sources Initializes an EncodedVideoPacketSource for directly piping pre-encoded video packets. Requires the codec name and supports adding packets sequentially. Additional metadata like decoderConfig is needed for the first packet. ```typescript import { EncodedVideoPacketSource } from 'mediabunny'; // You must specify the codec name: const packetSource = new EncodedVideoPacketSource('vp9'); await packetSource.add(packet1); await packetSource.add(packet2); ``` -------------------------------- ### Create Ogg Output with MediaBunny Source: https://mediabunny.dev/guide/output-formats This snippet illustrates initializing an Output object with the OggOutputFormat. This format supports append-only writing and provides a callback for Ogg page events. ```typescript import { Output, OggOutputFormat } from 'mediabunny'; const output = new Output({ format: new OggOutputFormat(options), // ... }); ``` -------------------------------- ### Create Matroska (.mkv) Output with MediaBunny Source: https://mediabunny.dev/guide/output-formats Shows how to create an Output object using the MkvOutputFormat for generating Matroska files. The configuration options are identical to those used for WebM output. ```typescript import { Output, MkvOutputFormat } from 'mediabunny'; const output = new Output({ format: new MkvOutputFormat(options), // ... }); ``` -------------------------------- ### Initialize Conversion with Audio Resampling Source: https://mediabunny.dev/guide/converting-media-files Demonstrates initializing a conversion process with specific audio resampling settings. This example sets the audio to mono (1 channel) and a sample rate of 48000 Hz. ```typescript const conversion = await Conversion.init({ input, output, audio: { numberOfChannels: 1, sampleRate: 48000, }, }); ``` -------------------------------- ### Import Mediabunny Quality Constants Source: https://mediabunny.dev/guide/media-sources Imports subjective quality constants from the mediabunny library. These constants represent different quality levels used for calculating bitrates. ```typescript import { QUALITY_VERY_LOW, QUALITY_LOW, QUALITY_MEDIUM, QUALITY_HIGH, QUALITY_VERY_HIGH, } from 'mediabunny'; ``` -------------------------------- ### Configure MP3 Output Options Source: https://mediabunny.dev/guide/output-formats Specifies the options for MP3 output format. Key options include `xingHeader` to control the Xing header inclusion and `onXingFrame` for callbacks when the Xing metadata frame is finalized. ```typescript type Mp3OutputFormatOptions = { xingHeader?: boolean; onXingFrame?: (data: Uint8Array, position: number) => unknown; }; ``` -------------------------------- ### Create Transparent Video with mediabunny Source: https://mediabunny.dev/guide/quick-start Generates a transparent video using mediabunny. It initializes an Output with WebM format and BufferTarget, creates an OffscreenCanvas for drawing, and adds a CanvasSource with 'vp9' codec and 'keep' alpha setting. This allows for encoding transparency data. ```typescript import { Output, WebMOutputFormat, BufferTarget, CanvasSource, QUALITY_MEDIUM, } from 'mediabunny'; const output = new Output({ // Use a format that supports transparency: format: new WebMOutputFormat(), target: new BufferTarget(), }); const canvas = new OffscreenCanvas(1280, 720); const context = canvas.getContext('2d', { alpha: true })!; const source = new CanvasSource(canvas, { codec: 'vp9', bitrate: QUALITY_MEDIUM, alpha: 'keep', // => Also encode alpha data }); output.addVideoTrack(source); await output.start(); // Add data... await source.add(0, 1 / 30); // ... await output.finalize(); ``` -------------------------------- ### Create AudioBufferSink for Web Audio API Source: https://mediabunny.dev/guide/media-sinks This code illustrates how to create an AudioBufferSink for extracting AudioBuffer instances compatible with the Web Audio API. It takes an audio track as input and is part of the mediabunny library. ```typescript import { AudioBufferSink } from 'mediabunny'; const sink = new AudioBufferSink(audioTrack); ``` -------------------------------- ### Create CanvasSource Source: https://mediabunny.dev/guide/media-sources Sets up a CanvasSource to capture frames from a canvas element. It takes the canvas element, codec, and bitrate (or quality constant) as configuration. Frames can be added with timestamps and durations, and key frames can be forced. ```typescript import { CanvasSource, QUALITY_MEDIUM } from 'mediabunny'; const canvasSource = new CanvasSource(canvasElement, { codec: 'av1', bitrate: QUALITY_MEDIUM, }); await canvasSource.add(0.0, 0.1); // Timestamp, duration (in seconds) await canvasSource.add(0.1, 0.1); await canvasSource.add(0.2, 0.1); // You may optionally force frames to be encoded as key frames: await canvasSource.add(0.3, 0.1, { keyFrame: true }); ``` -------------------------------- ### Implement UrlSource with Custom Retry Logic Source: https://mediabunny.dev/guide/reading-media-files Provides an example of using the `getRetryDelay` option in UrlSource to implement custom retry logic, specifically exponential backoff, for failed network requests. ```typescript // UrlSource using retry logic with exponential backoff: const source = new UrlSource('https://example.com/bigbuckbunny.mp4', { getRetryDelay: (previousAttempts) => Math.min(2 ** previousAttempts, 16), }); ``` -------------------------------- ### Create AudioSampleSink for Audio Tracks Source: https://mediabunny.dev/guide/media-sinks This snippet shows how to instantiate an AudioSampleSink to extract decoded audio samples from an audio track. It requires an audio track object as input and is part of the mediabunny library. ```typescript import { AudioSampleSink } from 'mediabunny'; const sink = new AudioSampleSink(audioTrack); ``` -------------------------------- ### Read file metadata using TypeScript Source: https://mediabunny.dev/guide/quick-start Reads metadata from media files using MediaBunny's Input API. It extracts duration, tracks, video/audio details, and metadata tags like title, date, and cover art. Dependencies include the mediabunny library. ```typescript import { Input, ALL_FORMATS, BlobSource } from 'mediabunny'; const input = new Input({ formats: ALL_FORMATS, // Supporting all file formats source: new BlobSource(file), // Assuming a File instance }); const duration = await input.computeDuration(); // in seconds const allTracks = await input.getTracks(); // List of all tracks // Extract video metadata const videoTrack = await input.getPrimaryVideoTrack(); if (videoTrack) { videoTrack.displayWidth; // in pixels videoTrack.displayHeight; // in pixels videoTrack.rotation; // in degrees clockwise // Estimate frame rate (FPS) const packetStats = await videoTrack.computePacketStats(100); const averageFrameRate = packetStats.averagePacketRate; } // Extract audio metadata const audioTrack = await input.getPrimaryAudioTrack(); if (audioTrack) { audioTrack.numberOfChannels; audioTrack.sampleRate; // in Hz } // Extract metadata tags const tags = await input.getMetadataTags(); tags.title; // Title tags.date; // Release date tags.images[0]; // Cover art tags.raw['TBPM']; // Custom tags // ... ``` -------------------------------- ### Extract video thumbnails using TypeScript Source: https://mediabunny.dev/guide/quick-start Extracts video thumbnails from media files using MediaBunny's CanvasSink. This allows fetching frames at specific timestamps or generating a series of equally-spaced thumbnails. Thumbnails can be automatically resized. ```typescript import { Input, ALL_FORMATS, BlobSource, CanvasSink, } from 'mediabunny'; const input = new Input({ formats: ALL_FORMATS, source: new BlobSource(file), }); const videoTrack = await input.getPrimaryVideoTrack(); if (videoTrack) { const decodable = await videoTrack.canDecode(); if (decodable) { const sink = new CanvasSink(videoTrack, { width: 320, // Automatically resize the thumbnails }); // Get the thumbnail at timestamp 10s const result = await sink.getCanvas(10); result.canvas; // HTMLCanvasElement | OffscreenCanvas result.timestamp; // in seconds result.duration; // in seconds // Generate five equally-spaced thumbnails through the video const startTimestamp = await videoTrack.getFirstTimestamp(); const endTimestamp = await videoTrack.computeDuration(); const timestamps = [0, 0.2, 0.4, 0.6, 0.8].map( (t) => startTimestamp + t * (endTimestamp - startTimestamp) ); // Loop over these timestamps for await (const result of sink.canvasesAtTimestamps(timestamps)) { // ... } } } ``` -------------------------------- ### Configure WebM Output Options Source: https://mediabunny.dev/guide/output-formats Defines the available options for WebM output format. These include append-only mode, minimum cluster duration, and callbacks for EBML header, segment header, and cluster events. ```typescript type MkvOutputFormatOptions = { appendOnly?: boolean; minimumClusterDuration?: number; onEbmlHeader?: (data: Uint8Array, position: number) => void; onSegmentHeader?: (data: Uint8Array, position: number) => unknown; onCluster?: (data: Uint8Array, position: number, timestamp: number) => unknown; }; ``` -------------------------------- ### Efficiently Retrieve Key Frame Samples Source: https://mediabunny.dev/guide/media-sinks Demonstrates an efficient method for retrieving media samples corresponding to key frames. It uses an async generator with `EncodedPacketSink` and `samplesAtTimestamps` to yield key frame timestamps progressively, avoiding the need to collect all timestamps upfront. ```typescript // Better implementation: const packetSink = new EncodedPacketSink(videoTrack); const sampleSink = new VideoSampleSink(videoTrack); const keyFrameSamples = sampleSink.samplesAtTimestamps((async function* () { let currentPacket = await packetSink.getFirstPacket(); while (currentPacket) { yield currentPacket.timestamp; currentPacket = await packetSink.getNextKeyPacket(currentPacket); } })()); for await (const sample of keyFrameSamples) { // ... sample.close(); } ``` -------------------------------- ### Basic Media Conversion to WebM Source: https://mediabunny.dev/guide/converting-media-files Demonstrates the fundamental process of initializing a conversion from an input source to a WebM output format using a BufferTarget. It highlights checking conversion validity and handling discarded tracks before execution. ```typescript import { Input, Output, WebMOutputFormat, BufferTarget, Conversion, } from 'mediabunny'; const input = new Input({ ... }); const output = new Output({ format: new WebMOutputFormat(), target: new BufferTarget(), }); const conversion = await Conversion.init({ input, output }); if (!conversion.isValid) { // Conversion is invalid and cannot be executed without error. // This field gives reasons for why tracks were discarded: conversion.discardedTracks; // => DiscardedTrack[] return; } await conversion.execute(); // output.target.buffer contains the final file ``` -------------------------------- ### Create FLAC Output with MediaBunny Source: https://mediabunny.dev/guide/output-formats Configures MediaBunny to generate FLAC (.flac) audio files. The `FlacOutputFormat` constructor accepts an options object, where `onFrame` is a callback function that is invoked for each FLAC frame written, providing the frame data and its position. ```typescript import { Output, FlacOutputFormat } from 'mediabunny'; const output = new Output({ format: new FlacOutputFormat(options), // ... }); ``` ```typescript type FlacOutputFormatOptions = { onFrame?: (data: Uint8Array, position: number) => unknown; }; ``` -------------------------------- ### Audio Encoding Configuration in TypeScript Source: https://mediabunny.dev/guide/media-sources Specifies the configuration for audio encoding, including the codec, bitrate, and bitrate mode. It allows for an optional full codec string and provides callbacks for handling encoded packets and encoder configuration. ```typescript type AudioEncodingConfig = { codec: AudioCodec; bitrate?: number | Quality; bitrateMode?: 'constant' | 'variable'; fullCodecString?: string; onEncodedPacket?: ( packet: EncodedPacket, meta: EncodedAudioChunkMetadata | undefined ) => unknown; onEncoderConfig?: ( config: AudioEncoderConfig ) => unknown; }; ``` -------------------------------- ### Iterate Through Encoded Packets Source: https://mediabunny.dev/guide/media-sinks Provides methods to get the successor of a given packet in decode order. It also offers a dedicated `packets` iterator for efficient, in-order traversal of all packets, optionally within a specified range. ```typescript let currentPacket = await sink.getFirstPacket(); while (currentPacket) { console.log('Packet:', currentPacket); currentPacket = await sink.getNextPacket(currentPacket); } for await (const packet of sink.packets()) { // ... } const start = await sink.getPacket(5); const end = await sink.getPacket(10, { metadataOnly: true }); for await (const packet of sink.packets(start, end)) { // ... } ``` -------------------------------- ### Provide Decoder Configuration for EncodedVideoPacketSource Source: https://mediabunny.dev/guide/media-sources Adds initial metadata, specifically decoder configuration, to an EncodedVideoPacketSource. This configuration is crucial for the output to correctly interpret the encoded video data, including codec details, dimensions, and color space. ```typescript await packetSource.add(firstPacket, { decoderConfig: { codec: 'vp09.00.31.08', codedWidth: 1280, codedHeight: 720, colorSpace: { primaries: 'bt709', transfer: 'iec61966-2-1', matrix: 'smpte170m', fullRange: false, }, description: undefined, }, }); ``` -------------------------------- ### Get Output Format Track Limits - TypeScript Source: https://mediabunny.dev/guide/output-formats Determine the minimum and maximum number of video, audio, subtitle, and total tracks an output format can contain. This helps in configuring media files to adhere to the format's specifications. ```typescript format.getSupportedTrackCounts(); type TrackCountLimits = { video: { min: number, max: number }, audio: { min: number, max: number }, subtitle: { min: number, max: number }, total: { min: number, max: number }, }; ``` -------------------------------- ### Add Media Data to Output Source: https://mediabunny.dev/guide/writing-media-files Pipes media data from media sources to the output file after the Output has been started. The specific method (`add`) may vary by media source. This example shows adding canvas frames at a specific timestamp and duration. ```typescript let framesAdded = 0; const intervalId = setInterval(() => { const timestampInSeconds = framesAdded / 30; const durationInSeconds = 1 / 30; // Captures the canvas state at the time of calling `add`: videoSource.add(timestampInSeconds, durationInSeconds); framesAdded++; }, 1000 / 30); ``` -------------------------------- ### Read media data using TypeScript Source: https://mediabunny.dev/guide/quick-start Reads video frames and audio chunks from media files using MediaBunny. It utilizes VideoSampleSink and AudioSampleSink to decode and retrieve samples at specific timestamps or iterate through them. Supports Web Audio API conversion for audio. ```typescript import { Input, ALL_FORMATS, BlobSource, VideoSampleSink, AudioSampleSink, } from 'mediabunny'; const input = new Input({ formats: ALL_FORMATS, source: new BlobSource(file), }); // Read video frames const videoTrack = await input.getPrimaryVideoTrack(); if (videoTrack) { const decodable = await videoTrack.canDecode(); if (decodable) { const sink = new VideoSampleSink(videoTrack); // Get the video frame at timestamp 5s const videoSample = await sink.getSample(5); videoSample.timestamp; // in seconds videoSample.duration; // in seconds // Draw the frame to a canvas videoSample.draw(ctx, 0, 0); // Loop over all frames in the first 30s of video for await (const sample of sink.samples(0, 30)) { // ... } } } // Read audio chunks const audioTrack = await input.getPrimaryAudioTrack(); if (audioTrack) { const decodable = await audioTrack.canDecode(); if (decodable) { const sink = new AudioSampleSink(audioTrack); // Get audio chunk at timestamp 5s; a short chunk of audio const audioSample = await sink.getSample(5); audioSample.timestamp; // in seconds audioSample.duration; // in seconds audioSample.numberOfFrames; // Convert to AudioBuffer for use with the Web Audio API const audioBuffer = audioSample.toAudioBuffer(); // Loop over all samples in the first 30s of audio for await (const sample of sink.samples(0, 30)) { // ... } } } ``` -------------------------------- ### Iterate Over Media Samples in a Range Source: https://mediabunny.dev/guide/media-sinks Allows iteration over a contiguous range of media samples using the `samples` iterator. This can be used to iterate through all samples or a specific time window. Remember to close each sample after use to release resources. ```typescript // Iterate over all samples: for await (const sample of sink.samples()) { console.log('Sample:', sample); // Do something with the sample sample.close(); } // Iterate over all samples in a specific time range: for await (const sample of sink.samples(5, 10)) { // ... sample.close(); } ``` -------------------------------- ### Use ALL_FORMATS Singleton Source: https://mediabunny.dev/guide/input-formats Illustrates the use of the `ALL_FORMATS` constant, which includes all available input format singletons. This is useful when you want to support the maximum number of formats. Note that using `ALL_FORMATS` can significantly increase bundle size due to the inclusion of all demuxers. ```typescript import { Input, ALL_FORMATS } from 'mediabunny'; const input = new Input({ formats: ALL_FORMATS, // ... }); ``` -------------------------------- ### Retrieve Specific Encoded Packets Source: https://mediabunny.dev/guide/media-sinks Fetches an EncodedPacket based on a given timestamp in seconds. It returns the last packet with a timestamp less than or equal to the specified time, or null if none exists. Includes methods for getting key packets and the very first packet. ```typescript await sink.getPacket(5); // => EncodedPacket | null await sink.getKeyPacket(5); // => EncodedPacket | null await sink.getFirstPacket(); // => EncodedPacket | null await sink.getPacket(Infinity); // => EncodedPacket | null ``` -------------------------------- ### Compress Media with mediabunny Source: https://mediabunny.dev/guide/quick-start Compresses media files using mediabunny with customizable parameters. It allows setting video and audio bitrates to QUALITY_LOW, specifying video dimensions, trimming the media to the first 60 seconds, and removing metadata tags. The Conversion.init method orchestrates the compression process. ```typescript import { Input, Output, Conversion, QUALITY_LOW, } from 'mediabunny'; const input = new Input(...); const output = new Output(...); const conversion = await Conversion.init({ input, output, video: { width: 480, bitrate: QUALITY_LOW, }, audio: { numberOfChannels: 1, bitrate: QUALITY_LOW, }, trim: { // Let's keep only the first 60 seconds start: 0, end: 60, }, tags: {}, // Remove any metadata tags }); await conversion.execute(); // Conversion is complete ``` -------------------------------- ### Extract Encoded Packets from Input Source: https://mediabunny.dev/guide/quick-start Extracts encoded video packets from an input source. It allows retrieval of packets by timestamp, the closest key packet, or the next packet. It also demonstrates setting up a manual decoder to loop over all packets in decode order. Requires the 'mediabunny' library. ```typescript import { Input, ALL_FORMATS, BlobSource, EncodedPacketSink, } from 'mediabunny'; const input = new Input({ formats: ALL_FORMATS, source: new BlobSource(file), }); const videoTrack = await input.getPrimaryVideoTrack(); if (videoTrack) { const sink = new EncodedPacketSink(videoTrack); // Get packet for timestamp 10s const packet = await sink.getPacket(10); packet.data; // Uint8Array packet.type; // 'key' | 'delta' packet.timestamp; // in seconds packet.duration; // in seconds // Get the closest key packet to timestamp 10s const keyPacket = await sink.getKeyPacket(10); // Get the following packet const nextPacket = await sink.getNextPacket(keyPacket); // Set up a manual decoder const decoderConfig = await videoTrack.getDecoderConfig(); const videoDecoder = new VideoDecoder({ output: console.log, error: console.error, }); videoDecoder.configure(decoderConfig); // Loop over all packets in decode order for await (const packet of sink.packets()) { videoDecoder.decode(packet.toEncodedVideoChunk()); } await videoDecoder.flush(); } ``` -------------------------------- ### Write Media Files Directly to Disk Source: https://mediabunny.dev/guide/quick-start Writes a new media file directly to the user's disk using the File System API. It utilizes `StreamTarget` for efficient, chunked writing to a `WritableStream`. Requires browser environment with File System Access API support. Requires the 'mediabunny' library. ```typescript import { Output, StreamTarget, } from 'mediabunny'; // File System API const handle = await window.showSaveFilePicker(); const writableStream = await handle.createWritable(); const output = new Output({ // `chunked: true` to batch disk operations target: new StreamTarget(writableStream, { chunked: true }), // ... }); // ... await output.finalize(); // The file has been fully written to disk ``` -------------------------------- ### Add Text Subtitles from File Content (TypeScript) Source: https://mediabunny.dev/guide/media-sources Shows how to create a TextSubtitleSource for 'webvtt' format and add subtitle content. It illustrates adding the entire subtitle text at once and the importance of closing the source afterward. This method is suitable for loading complete subtitle files. ```TypeScript import { TextSubtitleSource } from 'mediabunny'; const textSource = new TextSubtitleSource('webvtt'); const text = `WEBVTT 00:00:00.000 --> 00:00:02.000 This is your last chance. 00:00:02.500 --> 00:00:04.000 After this, there is no turning back. 00:00:04.500 --> 00:00:06.000 If you take the blue pill, the story ends. 00:00:06.500 --> 00:00:08.000 You wake up in your bed and believe whatever you want to believe. 00:00:08.500 --> 00:00:10.000 If you take the red pill, you stay in Wonderland 00:00:10.500 --> 00:00:12.000 and I show you how deep the rabbit hole goes. `; await textSource.add(text); textSource.close(); ```