mediabunny
Version:
Pure TypeScript media toolkit for reading, writing, and converting media files, directly in the browser.
1,160 lines (1,109 loc) • 206 kB
TypeScript
/// <reference types="dom-mediacapture-transform" />
/// <reference types="dom-webcodecs" />
/**
* ADTS input format singleton.
* @group Input formats
* @public
*/
export declare const ADTS: AdtsInputFormat;
/**
* ADTS file format.
*
* Do not instantiate this class; use the {@link ADTS} singleton instead.
*
* @group Input formats
* @public
*/
export declare class AdtsInputFormat extends InputFormat {
get name(): string;
get mimeType(): string;
}
/**
* ADTS file format.
* @group Output formats
* @public
*/
export declare class AdtsOutputFormat extends OutputFormat {
/** Creates a new {@link AdtsOutputFormat} configured with the specified `options`. */
constructor(options?: AdtsOutputFormatOptions);
getSupportedTrackCounts(): TrackCountLimits;
get fileExtension(): string;
get mimeType(): string;
getSupportedCodecs(): MediaCodec[];
get supportsVideoRotationMetadata(): boolean;
get supportsTimestampedMediaData(): boolean;
}
/**
* ADTS-specific output options.
* @group Output formats
* @public
*/
export declare type AdtsOutputFormatOptions = {
/**
* Will be called for each ADTS frame that is written.
*
* @param data - The raw bytes.
* @param position - The byte offset of the data in the file.
*/
onFrame?: (data: Uint8Array, position: number) => unknown;
};
/**
* List of all input format singletons. If you don't need to support all input formats, you should specify the
* formats individually for better tree shaking.
* @group Input formats
* @public
*/
export declare const ALL_FORMATS: InputFormat[];
/**
* List of all track types.
* @group Miscellaneous
* @public
*/
export declare const ALL_TRACK_TYPES: readonly ["video", "audio", "subtitle"];
/**
* Sync or async iterable.
* @group Miscellaneous
* @public
*/
export declare type AnyIterable<T> = Iterable<T> | AsyncIterable<T>;
/**
* This target writes to a `WritableStream<Uint8Array>`, meaning all writes are necessarily append-only and involve no
* seeking. Great for streaming data to a source that can only accept sequential data, like an HTTP server processing
* an incoming upload.
*
* Note that using this target *requires* that the underlying format write data sequentially. Not all formats do this,
* and this target will throw for the formats that don't. Check the guide for more.
*
* @group Output targets
* @public
*/
export declare class AppendOnlyStreamTarget extends Target {
constructor(writable: WritableStream<Uint8Array>);
}
/**
* Helper function for use in {@link InputTrackQuery.sortBy}, used to describe sorting tracks by a numeric property in
* ascending order. `null` and `undefined` are accepted too and are last in the order (sorted to the end).
*
* @group Input files & tracks
* @public
*/
export declare const asc: (value: number | null | undefined) => number;
/**
* A file attached to a media file.
*
* @group Metadata tags
* @public
*/
export declare class AttachedFile {
/** The raw file data. */
data: Uint8Array;
/** An RFC 6838 MIME type (e.g. image/jpeg, image/png, font/ttf, etc.) */
mimeType?: string | undefined;
/** The name of the file. */
name?: string | undefined;
/** A description of the file. */
description?: string | undefined;
/** Creates a new {@link AttachedFile}. */
constructor(
/** The raw file data. */
data: Uint8Array,
/** An RFC 6838 MIME type (e.g. image/jpeg, image/png, font/ttf, etc.) */
mimeType?: string | undefined,
/** The name of the file. */
name?: string | undefined,
/** A description of the file. */
description?: string | undefined);
}
/**
* An embedded image such as cover art, booklet scan, artwork or preview frame.
*
* @group Metadata tags
* @public
*/
export declare type AttachedImage = {
/** The raw image data. */
data: Uint8Array;
/** An RFC 6838 MIME type (e.g. image/jpeg, image/png, etc.) */
mimeType: string;
/** The kind or purpose of the image. */
kind: 'coverFront' | 'coverBack' | 'unknown';
/** The name of the image file. */
name?: string;
/** A description of the image. */
description?: string;
};
/**
* List of known audio codecs, ordered by encoding preference.
* @group Codecs
* @public
*/
export declare const AUDIO_CODECS: readonly ["aac", "opus", "mp3", "vorbis", "flac", "ac3", "eac3", "pcm-s16", "pcm-s16be", "pcm-s24", "pcm-s24be", "pcm-s32", "pcm-s32be", "pcm-f32", "pcm-f32be", "pcm-f64", "pcm-f64be", "pcm-u8", "pcm-s8", "ulaw", "alaw"];
/**
* A sink that retrieves decoded audio samples from an audio track and converts them to `AudioBuffer` instances. This is
* often more useful than directly retrieving audio samples, as audio buffers can be directly used with the
* Web Audio API.
* @group Media sinks
* @public
*/
export declare class AudioBufferSink {
/** Creates a new {@link AudioBufferSink} for the given {@link InputAudioTrack}. */
constructor(audioTrack: InputAudioTrack);
/**
* Retrieves the audio buffer corresponding to the given timestamp, in seconds. More specifically, returns
* the last audio buffer (in presentation order) with a start timestamp less than or equal to the given timestamp.
* Returns null if the timestamp is before the track's first timestamp.
*
* @param timestamp - The timestamp used for retrieval, in seconds.
* @param options - Options used for the underlying packet retrieval.
*/
getBuffer(timestamp: number, options?: PacketRetrievalOptions): Promise<WrappedAudioBuffer | null>;
/**
* Creates an async iterator that yields audio buffers of this track in presentation order. This method
* will intelligently pre-decode a few buffers ahead to enable fast iteration.
*
* @param startTimestamp - The timestamp in seconds at which to start yielding buffers (inclusive).
* @param endTimestamp - The timestamp in seconds at which to stop yielding buffers (exclusive).
* @param options - Options used for the underlying packet retrieval.
*/
buffers(startTimestamp?: number, endTimestamp?: number, options?: PacketRetrievalOptions): AsyncGenerator<WrappedAudioBuffer, void, unknown>;
/**
* Creates an async iterator that yields an audio buffer for each timestamp in the argument. This method
* uses an optimized decoding pipeline if these timestamps are monotonically sorted, decoding each packet at most
* once, and is therefore more efficient than manually getting the buffer for every timestamp. The iterator may
* yield null if no buffer is available for a given timestamp.
*
* @param timestamps - An iterable or async iterable of timestamps in seconds.
* @param options - Options used for the underlying packet retrieval.
*/
buffersAtTimestamps(timestamps: AnyIterable<number>, options?: PacketRetrievalOptions): AsyncGenerator<WrappedAudioBuffer | null, void, unknown>;
}
/**
* This source can be used to add audio data from an AudioBuffer to the output track. This is useful when working with
* the Web Audio API.
* @group Media sources
* @public
*/
export declare class AudioBufferSource extends AudioSource {
/**
* Creates a new {@link AudioBufferSource} whose `AudioBuffer` instances are encoded according to the specified
* {@link AudioEncodingConfig}.
*/
constructor(encodingConfig: AudioEncodingConfig);
/**
* Converts an AudioBuffer to audio samples, encodes them and adds them to the output. The first AudioBuffer will
* be played at timestamp 0, and any subsequent AudioBuffer will have a timestamp equal to the total duration of
* all previous AudioBuffers.
*
* @returns A Promise that resolves once the output is ready to receive more samples. You should await this Promise
* to respect writer and encoder backpressure.
*/
add(audioBuffer: AudioBuffer): Promise<void>;
}
/**
* Union type of known audio codecs.
* @group Codecs
* @public
*/
export declare type AudioCodec = typeof AUDIO_CODECS[number];
/**
* Additional options that control audio encoding.
* @group Encoding
* @public
*/
export declare type AudioEncodingAdditionalOptions = {
/** Configures the bitrate mode. */
bitrateMode?: 'constant' | 'variable';
/**
* The full codec string as specified in the Mediabunny Codec Registry. This string must match the codec
* specified in `codec`. When not set, a fitting codec string will be constructed automatically by the library.
*/
fullCodecString?: string;
};
/**
* Configuration object that controls audio encoding. Can be used to set codec, quality, and more.
* @group Encoding
* @public
*/
export declare type AudioEncodingConfig = {
/** The audio codec that should be used for encoding the audio samples. */
codec: AudioCodec;
/**
* The target bitrate for the encoded audio, in bits per second. Alternatively, a subjective {@link Quality} can
* be provided. Required for compressed audio codecs, unused for PCM codecs.
*/
bitrate?: number | Quality;
/**
* Optional transformations to apply to the audio samples before they are passed to the encoder.
*/
transform?: AudioTransformOptions;
/** Called for each successfully encoded packet. Both the packet and the encoding metadata are passed. */
onEncodedPacket?: (packet: EncodedPacket, meta: EncodedAudioChunkMetadata | undefined) => unknown;
/**
* Called when the internal [encoder config](https://www.w3.org/TR/webcodecs/#audio-encoder-config), as used by the
* WebCodecs API, is created.
*/
onEncoderConfig?: (config: AudioEncoderConfig) => unknown;
} & AudioEncodingAdditionalOptions;
/**
* Represents a raw, unencoded audio sample. Mainly used as an expressive wrapper around WebCodecs API's
* [`AudioData`](https://developer.mozilla.org/en-US/docs/Web/API/AudioData), but can also be used standalone.
* @group Samples
* @public
*/
export declare class AudioSample implements Disposable {
/**
* The audio sample format.
* [See sample formats](https://developer.mozilla.org/en-US/docs/Web/API/AudioData/format)
*/
readonly format: AudioSampleFormat;
/** The audio sample rate in hertz. */
readonly sampleRate: number;
/**
* The number of audio frames in the sample, per channel. In other words, the length of this audio sample in frames.
*/
readonly numberOfFrames: number;
/** The number of audio channels. */
readonly numberOfChannels: number;
/** The duration of the sample in seconds. */
readonly duration: number;
/**
* The presentation timestamp of the sample in seconds. May be negative. Samples with negative end timestamps should
* not be presented.
*/
readonly timestamp: number;
/** The presentation timestamp of the sample in microseconds. */
get microsecondTimestamp(): number;
/** The duration of the sample in microseconds. */
get microsecondDuration(): number;
/**
* Creates a new {@link AudioSample}, either from an existing
* [`AudioData`](https://developer.mozilla.org/en-US/docs/Web/API/AudioData) or from raw bytes specified in
* {@link AudioSampleInit}.
*/
constructor(init: AudioData | AudioSampleInit | AudioSampleResource);
/** Returns the number of bytes required to hold the audio sample's data as specified by the given options. */
allocationSize(options: AudioSampleCopyToOptions): number;
/** Copies the audio sample's data to an ArrayBuffer or ArrayBufferView as specified by the given options. */
copyTo(destination: AllowSharedBufferSource, options: AudioSampleCopyToOptions): void;
/** Clones this audio sample. */
clone(): AudioSample;
/**
* Closes this audio sample, releasing held resources. Audio samples should be closed as soon as they are not
* needed anymore.
*/
close(): void;
/**
* Converts this audio sample to an AudioData for use with the WebCodecs API. The AudioData returned by this
* method *must* be closed separately from this audio sample.
*/
toAudioData(): AudioData;
/** Convert this audio sample to an AudioBuffer for use with the Web Audio API. */
toAudioBuffer(): AudioBuffer;
/** Sets the presentation timestamp of this audio sample, in seconds. */
setTimestamp(newTimestamp: number): void;
/** Calls `.close()`. */
[Symbol.dispose](): void;
/**
* Creates AudioSamples from an AudioBuffer, starting at the given timestamp in seconds. Typically creates exactly
* one sample, but may create multiple if the AudioBuffer is exceedingly large.
*/
static fromAudioBuffer(audioBuffer: AudioBuffer, timestamp: number): AudioSample[];
}
/**
* Options used for copying audio sample data.
* @group Samples
* @public
*/
export declare type AudioSampleCopyToOptions = {
/**
* The index identifying the plane to copy from. This must be 0 if using a non-planar (interleaved) output format.
*/
planeIndex: number;
/**
* The output format for the destination data. Defaults to the AudioSample's format.
* [See sample formats](https://developer.mozilla.org/en-US/docs/Web/API/AudioData/format)
*/
format?: AudioSampleFormat;
/** An offset into the source plane data indicating which frame to begin copying from. Defaults to 0. */
frameOffset?: number;
/**
* The number of frames to copy. If not provided, the copy will include all frames in the plane beginning
* with frameOffset.
*/
frameCount?: number;
};
/**
* Metadata used for AudioSample initialization.
* @group Samples
* @public
*/
export declare type AudioSampleInit = {
/** The audio data for this sample. */
data: AllowSharedBufferSource;
/**
* The audio sample format. [See sample formats](https://developer.mozilla.org/en-US/docs/Web/API/AudioData/format)
*/
format: AudioSampleFormat;
/** The number of audio channels. */
numberOfChannels: number;
/** The audio sample rate in hertz. */
sampleRate: number;
/** The presentation timestamp of the sample in seconds. */
timestamp: number;
};
/**
* Abstract base class for custom audio sample resources. Implement this class to provide custom backing
* for AudioSample instances.
* @group Samples
* @public
*/
export declare abstract class AudioSampleResource {
/**
* Returns the audio sample format.
* [See sample formats](https://developer.mozilla.org/en-US/docs/Web/API/AudioData/format)
*/
abstract getFormat(): AudioSampleFormat;
/** Returns the audio sample rate in hertz. */
abstract getSampleRate(): number;
/** Returns the number of audio frames in the sample, per channel. */
abstract getNumberOfFrames(): number;
/** Returns the number of audio channels. */
abstract getNumberOfChannels(): number;
/** Returns the presentation timestamp of the sample in seconds. */
abstract getTimestamp(): number;
/**
* Closes this resource, releasing held resources. Called automatically when the last {@link AudioSample} using this
* resource is closed.
*/
abstract close(): void;
/**
* Returns the audio sample data for the plane given by `planeIndex`. The audio data must be in the format returned
* by `getFormat()`. For interleaved formats, there is only one plane.
*/
abstract getDataPlane(planeIndex: number): Uint8Array;
}
/**
* Sink for retrieving decoded audio samples from an audio track.
* @group Media sinks
* @public
*/
export declare class AudioSampleSink extends BaseMediaSampleSink<AudioSample> {
/** Creates a new {@link AudioSampleSink} for the given {@link InputAudioTrack}. */
constructor(audioTrack: InputAudioTrack);
/**
* Retrieves the audio sample corresponding to the given timestamp, in seconds. More specifically, returns
* the last audio sample (in presentation order) with a start timestamp less than or equal to the given timestamp.
* Returns null if the timestamp is before the track's first timestamp.
*
* @param timestamp - The timestamp used for retrieval, in seconds.
* @param options - Options used for the underlying packet retrieval.
*/
getSample(timestamp: number, options?: PacketRetrievalOptions): Promise<AudioSample | null>;
/**
* Creates an async iterator that yields the audio samples of this track in presentation order. This method
* will intelligently pre-decode a few samples ahead to enable fast iteration.
*
* @param startTimestamp - The timestamp in seconds at which to start yielding samples (inclusive).
* @param endTimestamp - The timestamp in seconds at which to stop yielding samples (exclusive).
* @param options - Options used for the underlying packet retrieval.
*/
samples(startTimestamp?: number, endTimestamp?: number, options?: PacketRetrievalOptions): AsyncGenerator<AudioSample, void, unknown>;
/**
* Creates an async iterator that yields an audio sample for each timestamp in the argument. This method
* uses an optimized decoding pipeline if these timestamps are monotonically sorted, decoding each packet at most
* once, and is therefore more efficient than manually getting the sample for every timestamp. The iterator may
* yield null if no sample is available for a given timestamp.
*
* This method is good for sparse access of media data. If you want primarily sequential media access, prefer
* {@link AudioSampleSink.samples} instead.
*
* @param timestamps - An iterable or async iterable of timestamps in seconds.
* @param options - Options used for the underlying packet retrieval.
*/
samplesAtTimestamps(timestamps: AnyIterable<number>, options?: PacketRetrievalOptions): AsyncGenerator<AudioSample | null, void, unknown>;
}
/**
* This source can be used to add raw, unencoded audio samples to an output audio track. These samples will
* automatically be encoded and then piped into the output.
* @group Media sources
* @public
*/
export declare class AudioSampleSource extends AudioSource {
/**
* Creates a new {@link AudioSampleSource} whose samples are encoded according to the specified
* {@link AudioEncodingConfig}.
*/
constructor(encodingConfig: AudioEncodingConfig);
/**
* Encodes an audio sample and then adds it to the output.
*
* @returns A Promise that resolves once the output is ready to receive more samples. You should await this Promise
* to respect writer and encoder backpressure.
*/
add(audioSample: AudioSample): Promise<void>;
}
/**
* Base class for audio sources - sources for audio tracks.
* @group Media sources
* @public
*/
export declare abstract class AudioSource extends MediaSource_2 {
/** Internal constructor. */
constructor(codec: AudioCodec);
}
/**
* Additional metadata for audio tracks.
* @group Output files
* @public
*/
export declare type AudioTrackMetadata = BaseTrackMetadata & {};
/**
* Options for transforming audio samples before encoding.
* @group Encoding
* @public
*/
export declare type AudioTransformOptions = {
/** The desired number of output channels to up/downmix to. */
numberOfChannels?: number;
/** The desired output sample rate in hertz to resample to. */
sampleRate?: number;
/**
* The desired sample format (and therefore bit depth) of the audio samples before they are passed to the encoder.
* Can be used to control bit depth with certain output codecs such as FLAC.
*/
sampleFormat?: 'u8' | 's16' | 's32' | 'f32';
/**
* Allows for custom user-defined processing of audio samples, e.g. for applying audio effects or timestamp
* modifications. Called for each audio sample after resampling and remixing.
*
* Must return an {@link AudioSample}, an array of them, or `null` for dropping the sample.
*/
process?: (sample: AudioSample) => MaybePromise<AudioSample | AudioSample[] | null>;
};
/**
* Base class for decoded media sample sinks.
* @group Media sinks
* @public
*/
export declare abstract class BaseMediaSampleSink<MediaSample extends VideoSample | AudioSample> {
}
/**
* Base track metadata, applicable to all tracks.
* @group Output files
* @public
*/
export declare type BaseTrackMetadata = {
/** The three-letter, ISO 639-2/T language code specifying the language of this track. */
languageCode?: string;
/** A user-defined name for this track, like "English" or "Director Commentary". */
name?: string;
/** The track's disposition, i.e. information about its intended usage. */
disposition?: Partial<TrackDisposition>;
/**
* The maximum amount of encoded packets that will be added to this track. Setting this field provides the muxer
* with an additional signal that it can use to preallocate space in the file.
*
* When this field is set, it is an error to provide more packets than whatever this field specifies.
*
* Predicting the maximum packet count requires considering both the maximum duration as well as the codec.
* - For video codecs, you can assume one packet per frame.
* - For audio codecs, there is one packet for each "audio chunk", the duration of which depends on the codec. For
* simplicity, you can assume each packet is roughly 10 ms or 512 samples long, whichever is shorter.
* - For subtitles, assume each cue and each gap in the subtitles adds a packet.
*
* If you're not fully sure, make sure to add a buffer of around 33% to make sure you stay below the maximum.
*/
maximumPacketCount?: number;
/**
* Whether the timestamps of this track are relative to the Unix epoch (January 1, 1970, 00:00:00 UTC). When `true`,
* each timestamp maps to a definitive point in time.
*/
isRelativeToUnixEpoch?: boolean;
/**
* Defines the group(s) this track is a part of. Group assignment determines track pairability, determining which
* tracks can be presented together with other tracks. This is needed for configuring things like HLS master
* playlists.
*
* Two groups are considered pairable if they are in the same group but are of different {@link TrackType}, or if
* they are in two separate groups that have been paired with each other.
*
* If left blank, a track is automatically assigned to {@link Output.defaultTrackGroup}.
*/
group?: OutputTrackGroup | OutputTrackGroup[];
};
/**
* A source backed by a [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob). Since a
* [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File) is also a `Blob`, this is the source to use when
* reading files off the disk.
* @group Input sources
* @public
*/
export declare class BlobSource extends Source {
/**
* Creates a new {@link BlobSource} backed by the specified
* [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob).
*/
constructor(blob: Blob, options?: BlobSourceOptions);
}
/**
* Options for {@link BlobSource}.
* @group Input sources
* @public
*/
export declare type BlobSourceOptions = {
/** The maximum number of bytes the cache is allowed to hold in memory. Defaults to 8 MiB. */
maxCacheSize?: number;
/**
* Defaults to `true`. When `true`, Mediabunny will acquire a `ReadableStream` reader internally to efficiently read
* data from the blob. Since this can lead to errors in some (very) rare cases due to browser bugs, you can set this
* field to `false` to try a slower but more stable reading method.
*/
useStreamReader?: boolean;
};
/**
* A source backed by an ArrayBuffer or ArrayBufferView, with the entire file held in memory.
* @group Input sources
* @public
*/
declare class BufferSource_2 extends Source {
/**
* Creates a new {@link BufferSource} backed by the specified `ArrayBuffer`, `SharedArrayBuffer`,
* or `ArrayBufferView`.
*/
constructor(buffer: AllowSharedBufferSource);
}
export { BufferSource_2 as BufferSource }
/**
* A target that writes data directly into an ArrayBuffer in memory. Great for performance, but not suitable for very
* large files. The buffer will be available once the output has been finalized.
* @group Output targets
* @public
*/
export declare class BufferTarget extends Target {
/** Stores the final output buffer. Until the output is finalized, this will be `null`. */
buffer: ArrayBuffer | null;
/** Creates a new {@link BufferTarget}. The buffer holding the data will be created and managed internally. */
constructor(options?: BufferTargetOptions);
}
/**
* Options for {@link BufferTarget}.
* @group Output targets
* @public
*/
export declare type BufferTargetOptions = {
/**
* Called once the target has been finalized, with the complete output buffer. If you return a promise, it will be
* used to apply backpressure internally.
*
* One use for this callback is for uploading to a server where the full buffer must be known before
* sending (e.g. S3 PutObject) and stream-uploading is not an option.
*/
onFinalize?: (buffer: ArrayBuffer) => MaybePromise<unknown>;
};
/**
* Checks if the browser is able to decode the given codec.
* @group Decoding
* @public
*/
export declare const canDecode: (codec: MediaCodec) => false | Promise<boolean>;
/**
* Checks if the browser is able to decode the given audio codec with the given parameters.
* @group Decoding
* @public
*/
export declare const canDecodeAudio: (codec: AudioCodec, options?: SetOptional<AudioDecoderConfig, "codec" | "numberOfChannels" | "sampleRate">) => Promise<boolean>;
/**
* Checks if the browser is able to decode the given video codec with the given parameters.
* @group Decoding
* @public
*/
export declare const canDecodeVideo: (codec: VideoCodec, options?: SetOptional<VideoDecoderConfig, "codec">) => Promise<boolean>;
/**
* Checks if the browser is able to encode the given codec.
* @group Encoding
* @public
*/
export declare const canEncode: (codec: MediaCodec) => Promise<boolean>;
/**
* Checks if the browser is able to encode the given audio codec with the given parameters.
* @group Encoding
* @public
*/
export declare const canEncodeAudio: (codec: AudioCodec, options?: {
numberOfChannels?: number;
sampleRate?: number;
bitrate?: number | Quality;
} & AudioEncodingAdditionalOptions) => Promise<boolean>;
/**
* Checks if the browser is able to encode the given subtitle codec.
* @group Encoding
* @public
*/
export declare const canEncodeSubtitles: (codec: SubtitleCodec) => Promise<boolean>;
/**
* Checks if the browser is able to encode the given video codec with the given parameters.
* @group Encoding
* @public
*/
export declare const canEncodeVideo: (codec: VideoCodec, options?: {
width?: number;
height?: number;
bitrate?: number | Quality;
} & VideoEncodingAdditionalOptions) => Promise<boolean>;
/**
* A sink that renders video samples (frames) of the given video track to canvases. This is often more useful than
* directly retrieving frames, as it comes with common preprocessing steps such as resizing or applying rotation
* metadata.
*
* This sink will yield `HTMLCanvasElement`s when in a DOM context, and `OffscreenCanvas`es otherwise.
*
* @group Media sinks
* @public
*/
export declare class CanvasSink {
/** Creates a new {@link CanvasSink} for the given {@link InputVideoTrack}. */
constructor(videoTrack: InputVideoTrack, options?: CanvasSinkOptions);
/**
* Retrieves a canvas with the video frame corresponding to the given timestamp, in seconds. More specifically,
* returns the last video frame (in presentation order) with a start timestamp less than or equal to the given
* timestamp. Returns null if the timestamp is before the track's first timestamp.
*
* @param timestamp - The timestamp used for retrieval, in seconds.
* @param options - Options used for the underlying packet retrieval.
*/
getCanvas(timestamp: number, options?: PacketRetrievalOptions): Promise<WrappedCanvas | null>;
/**
* Creates an async iterator that yields canvases with the video frames of this track in presentation order. This
* method will intelligently pre-decode a few frames ahead to enable fast iteration.
*
* @param startTimestamp - The timestamp in seconds at which to start yielding canvases (inclusive).
* @param endTimestamp - The timestamp in seconds at which to stop yielding canvases (exclusive).
* @param options - Options used for the underlying packet retrieval.
*/
canvases(startTimestamp?: number, endTimestamp?: number, options?: PacketRetrievalOptions): AsyncGenerator<WrappedCanvas, void, unknown>;
/**
* Creates an async iterator that yields a canvas for each timestamp in the argument. This method uses an optimized
* decoding pipeline if these timestamps are monotonically sorted, decoding each packet at most once, and is
* therefore more efficient than manually getting the canvas for every timestamp. The iterator may yield null if
* no frame is available for a given timestamp.
*
* This method is good for sparse access of media data. If you want primarily sequential media access, prefer
* {@link CanvasSink.canvases} instead.
*
* @param timestamps - An iterable or async iterable of timestamps in seconds.
* @param options - Options used for the underlying packet retrieval.
*/
canvasesAtTimestamps(timestamps: AnyIterable<number>, options?: PacketRetrievalOptions): AsyncGenerator<WrappedCanvas | null, void, unknown>;
}
/**
* Options for constructing a CanvasSink.
* @group Media sinks
* @public
*/
export declare type CanvasSinkOptions = {
/**
* Whether the output canvases should have transparency instead of a black background. Defaults to `false`. Set
* this to `true` when using this sink to read transparent videos.
*/
alpha?: boolean;
/**
* The width of the output canvas in pixels, defaulting to the display width of the video track. If height is not
* set, it will be deduced automatically based on aspect ratio.
*/
width?: number;
/**
* The height of the output canvas in pixels, defaulting to the display height of the video track. If width is not
* set, it will be deduced automatically based on aspect ratio.
*/
height?: number;
/**
* The fitting algorithm in case both width and height are set.
*
* - `'fill'` will stretch the image to fill the entire box, potentially altering aspect ratio.
* - `'contain'` will contain the entire image within the box while preserving aspect ratio. This may lead to
* letterboxing.
* - `'cover'` will scale the image until the entire box is filled, while preserving aspect ratio.
*/
fit?: 'fill' | 'contain' | 'cover';
/**
* The clockwise rotation by which to rotate the raw video frame. Defaults to the rotation set in the file metadata.
* Rotation is applied before resizing.
*/
rotation?: Rotation;
/**
* Specifies the rectangular region of the input video to crop to. The crop region will automatically be clamped to
* the dimensions of the input video track. Cropping is performed after rotation but before resizing. The crop
* region is in the _display pixel space_ of the underlying video data.
*/
crop?: CropRectangle;
/**
* When set, specifies the number of canvases in the pool. These canvases will be reused in a ring buffer /
* round-robin type fashion. This keeps the amount of allocated VRAM constant and relieves the browser from
* constantly allocating/deallocating canvases. A pool size of 0 or `undefined` disables the pool and means a new
* canvas is created each time.
*/
poolSize?: number;
};
/**
* This source can be used to add video frames to the output track from a fixed canvas element. Since canvases are often
* used for rendering, this source provides a convenient wrapper around {@link VideoSampleSource}.
* @group Media sources
* @public
*/
export declare class CanvasSource extends VideoSource {
/**
* Creates a new {@link CanvasSource} from a canvas element or `OffscreenCanvas` whose samples are encoded
* according to the specified {@link VideoEncodingConfig}.
*/
constructor(canvas: HTMLCanvasElement | OffscreenCanvas, encodingConfig: VideoEncodingConfig);
/**
* Captures the current canvas state as a video sample (frame), encodes it and adds it to the output.
*
* @param timestamp - The timestamp of the sample, in seconds.
* @param duration - The duration of the sample, in seconds.
*
* @returns A Promise that resolves once the output is ready to receive more samples. You should await this Promise
* to respect writer and encoder backpressure.
*/
add(timestamp: number, duration?: number, encodeOptions?: VideoEncoderEncodeOptions): Promise<void>;
}
/**
* Creates a single Common Media Application Format (CMAF) segment. An init segment will be written to the
* {@link Target} specified in {@link OutputOptions.initTarget}. Supports most codecs.
* @group Output formats
* @public
*/
export declare class CmafOutputFormat extends IsobmffOutputFormat {
/** Creates a new {@link CmafOutputFormat} configured with the specified `options`. */
constructor(options?: CmafOutputFormatOptions);
get fileExtension(): string;
get mimeType(): string;
getSupportedCodecs(): MediaCodec[];
}
/**
* CMAF-specific output options.
* @group Output formats
* @public
*/
export declare type CmafOutputFormatOptions = Omit<IsobmffOutputFormatOptions, 'fastStart'> & {
/**
* Controls the minimum duration of each fragment, in seconds. New fragments will only be created when the current
* fragment is longer than this value. Defaults to `Infinity`, meaning the file will contain only one fragment.
*/
minimumFragmentDuration?: number;
};
/**
* Utility class for running async functions in parallel up to a certain level of parallelism. Can be used to apply
* backpressure only if the concurrency level would be exceeded.
*
* @group Miscellaneous
* @public
*/
export declare class ConcurrentRunner {
/**
* The maximum number of in-flight promises. You can also think of it as the "high water mark".
* You can set this value to dynamically change the level of parallelism.
*/
parallelism: number;
constructor(parallelism: number);
/** Whether any function has errored. The runner is effectively bricked if this is `true`, by design. */
get errored(): boolean;
/** The number of tasks currently running. */
get inFlightCount(): number;
/**
* Schedules an async function to be run. If the maximum allowed level of parallelism has not yet been reached,
* the function will be executed immediately and `run()` will resolve immediately. Otherwise, the function will be
* called as soon as any currently-running function finishes, and `run()` will only resolve then.
*
* Throws if the runner is errored.
*/
run(fn: () => Promise<unknown>): Promise<void>;
/** Waits for all currently running functions to finish. Throws if the runner is errored. */
flush(): Promise<void>;
}
/**
* Represents a media file conversion process, used to convert one media file into another. In addition to conversion,
* this class can be used to resize and rotate video, resample audio, drop tracks, or trim to a specific time range.
* @group Conversion
* @public
*/
export declare class Conversion {
/** The input file. */
readonly input: Input;
/** The output file. */
readonly output: Output;
/**
* A callback that is fired whenever the conversion progresses. Gets passed as first argument a number between
* 0 and 1, indicating the completion of the conversion. Note that a progress of 1 doesn't necessarily mean the
* conversion is complete; the conversion is complete once `execute()` resolves.
*
* As second argument, this callback receives the input time in seconds that has been processed.
*
* In order for progress to be computed, this property must be set before `execute` is called.
*/
onProgress?: (progress: number, processedTime: number) => unknown;
/**
* Whether this conversion, as it has been configured, is valid and can be executed. If this field is `false`, check
* the `discardedTracks` field for reasons.
*
* Note: a conversion having discarded tracks does not automatically mean it is invalid; if the remaining, utilized
* tracks make for a valid output file, the conversion is still allowed.
*/
isValid: boolean;
/**
* The list of tracks that are included in the output file. When fan-out is used, the same track appears in this
* array multiple times.
*/
readonly utilizedTracks: InputTrack[];
/** The list of tracks from the input file that have been discarded, alongside the discard reason. */
readonly discardedTracks: DiscardedTrack[];
/** Initializes a new conversion process without starting the conversion. */
static init(options: ConversionOptions): Promise<Conversion>;
/** Creates a new Conversion instance (duh). */
private constructor();
/**
* Executes the conversion process. Resolves once conversion is complete.
*
* Will throw if `isValid` is `false`.
*/
execute(): Promise<void>;
/**
* Cancels the conversion process, causing any ongoing `execute` call to throw a `ConversionCanceledError`.
* Does nothing if the conversion is already complete.
*/
cancel(): Promise<void>;
}
/**
* Audio-specific options.
* @group Conversion
* @public
*/
export declare type ConversionAudioOptions = {
/** If `true`, all audio tracks will be discarded and will not be present in the output. */
discard?: boolean;
/** The desired channel count of the output audio. */
numberOfChannels?: number;
/** The desired sample rate of the output audio, in hertz. */
sampleRate?: number;
/**
* The desired sample format (and therefore bit depth) of the audio samples before they are passed to the encoder.
* Can be used to control bit depth with certain output codecs such as FLAC.
*
* Setting this field forces audio transcoding.
*/
sampleFormat?: 'u8' | 's16' | 's32' | 'f32';
/** The desired output audio codec. */
codec?: AudioCodec;
/** The desired bitrate of the output audio. */
bitrate?: number | Quality;
/** When `true`, audio will always be re-encoded instead of directly copying over the encoded samples. */
forceTranscode?: boolean;
/**
* Allows for custom user-defined processing of audio samples, e.g. for applying audio effects, transformations, or
* timestamp modifications. Will be called for each input audio sample after remixing and resampling.
*
* Must return an {@link AudioSample}, an array of them, or `null` for dropping the sample.
*
* This function can also be used to manually perform remixing or resampling. When doing so, you should signal the
* post-process parameters using the `processedNumberOfChannels` and `processedSampleRate` fields, which enables the
* encoder to better know what to expect. If these fields aren't set, Mediabunny will assume you won't perform
* remixing or resampling.
*/
process?: (sample: AudioSample) => MaybePromise<AudioSample | AudioSample[] | null>;
/**
* An optional hint specifying the channel count of audio samples returned by the `process` function, for better
* encoder configuration.
*/
processedNumberOfChannels?: number;
/**
* An optional hint specifying the sample rate of audio samples returned by the `process` function, for better
* encoder configuration.
*/
processedSampleRate?: number;
/**
* Defines the group(s) the output track is a part of. For more, see {@link BaseTrackMetadata.group}.
*
* If left blank, tracks will internally be assigned to groups such that the output track pairability graph exactly
* matches the input track pairability graph.
*/
group?: OutputTrackGroup | OutputTrackGroup[];
};
/**
* Thrown when a conversion couldn't complete due to being canceled.
* @group Conversion
* @public
*/
export declare class ConversionCanceledError extends Error {
/** Creates a new {@link ConversionCanceledError}. */
constructor(message?: string);
}
/**
* The options for media file conversion.
* @group Conversion
* @public
*/
export declare type ConversionOptions = {
/** The input file. */
input: Input;
/** The output file. */
output: Output;
/**
* Defines which input tracks are used for conversion. Defaults to `'all'` unless the input is an HLS input, in
* which case it defaults to `'primary'`.
*
* - `'all'`: All input tracks are eligible for conversion.
* - `'primary'`: Only the primary video and audio track from the input are eligible for conversion.
*/
tracks?: 'all' | 'primary';
/**
* Video-specific options. When passing an object, the same options are applied to all video tracks. When passing a
* function, it will be invoked for each video track and is expected to return or resolve to the options
* for that specific track. The function is passed an instance of {@link InputVideoTrack} as well as a number `n`,
* which is the 1-based index of the track in the list of all video tracks. Using `n` is deprecated, prefer the
* identical `track.number` instead.
*
* When passing an array of a function that returns an array, one output track per array element will be created,
* allowing for "fan-out". Useful for creating multiple variants from a single track, for example with different
* resolutions.
*/
video?: ConversionVideoOptions | ConversionVideoOptions[] | ((track: InputVideoTrack, n: number) => MaybePromise<ConversionVideoOptions | ConversionVideoOptions[] | undefined>);
/**
* Audio-specific options. When passing an object, the same options are applied to all audio tracks. When passing a
* function, it will be invoked for each audio track and is expected to return or resolve to the options
* for that specific track. The function is passed an instance of {@link InputAudioTrack} as well as a number `n`,
* which is the 1-based index of the track in the list of all audio tracks. Using `n` is deprecated, prefer the
* identical `track.number` instead.
*
* When passing an array of a function that returns an array, one output track per array element will be created,
* allowing for "fan-out". Useful for creating multiple variants from a single track, for example with different
* bitrates.
*/
audio?: ConversionAudioOptions | ConversionAudioOptions[] | ((track: InputAudioTrack, n: number) => MaybePromise<ConversionAudioOptions | ConversionAudioOptions[] | undefined>);
/** Options to trim the input file. */
trim?: {
/**
* The time in the input file in seconds at which the output file should start. Must be less than `end`.
* When omitted, defaults to the earliest start timestamp of the non-discarded tracks, or to 0, whichever
* is higher.
*/
start?: number;
/**
* The time in the input file in seconds at which the output file should end. Must be greater than `start`.
* Defaults to the duration of the input when omitted.
*/
end?: number;
};
/**
* An object or a callback that returns or resolves to an object containing the descriptive metadata tags that
* should be written to the output file. If a function is passed, it will be passed the tags of the input file as
* its first argument, allowing you to modify, augment or extend them.
*
* If no function is set, the input's metadata tags will be copied to the output.
*/
tags?: MetadataTags | ((inputTags: MetadataTags) => MaybePromise<MetadataTags>);
/**
* Whether to show potential console warnings about discarded tracks after calling `Conversion.init()`, defaults to
* `true`. Set this to `false` if you're properly handling the `discardedTracks` and `isValid` fields already and
* want to keep the console output clean.
*/
showWarnings?: boolean;
};
/**
* Video-specific options.
* @group Conversion
* @public
*/
export declare type ConversionVideoOptions = {
/** If `true`, all video tracks will be discarded and will not be present in the output. */
discard?: boolean;
/**
* The desired width of the output video in pixels, defaulting to the video's natural display width. If height
* is not set, it will be deduced automatically based on aspect ratio.
*/
width?: number;
/**
* The desired height of the output video in pixels, defaulting to the video's natural display height. If width
* is not set, it will be deduced automatically based on aspect ratio.
*/
height?: number;
/**
* The fitting algorithm in case both width and height are set, or if the input video changes its size over time.
*
* - `'fill'` will stretch the image to fill the entire box, potentially altering aspect ratio.
* - `'contain'` will contain the entire image within the box while preserving aspect ratio. This may lead to
* letterboxing.
* - `'cover'` will scale the image until the entire box is filled, while preserving aspect ratio.
*/
fit?: 'fill' | 'contain' | 'cover';
/**
* The angle in degrees to rotate the input video by, clockwise. Rotation is applied before cropping and resizing.
* This rotation is _in addition to_ the natural rotation of the input video as specified in input file's metadata.
*/
rotate?: Rotation;
/**
* Defaults to `true`. When enabled, Mediabunny will use the rotation metadata in the output file to perform video
* rotation whenever possible. Set this field to `false` if you want to ensure the output file does not make use of
* rotation metadata and that any rotation is baked into the video frames directly.
*/
allowRotationMetadata?: boolean;
/**
* Specifies the rectangular region of the input video to crop to. The crop region will automatically be clamped to
* the dimensions of the input video track. Cropping is performed after rotation but before resizing.
*/
crop?: CropRectangle;
/**
* The desired frame rate of the output video, in hertz. If not specified, the original input frame rate will
* be used (which may be variable).
*/
frameRate?: number;
/** The desired output video codec. */
codec?: VideoCodec;
/** The desired bitrate of the output video. */
bitrate?: number | Quality;
/**
* Whether to discard or keep the transparency information of the input video. The default is `'discard'`. Note that
* for `'keep'` to produce a transparent video, you must use an output config that supports it, such as WebM with
* VP9.
*/
alpha?: 'discard' | 'keep';
/**
* The interval, in seconds, of how often frames are encoded as a key frame. The default is 5 seconds. Frequent key
* frames improve seeking behavior but increase file size. When using multiple video tracks, you should give them
* all the same key frame interval.
*
* Setting this fields forces a transcode.
*/
keyFrameInterval?: number;
/**
* A hint that configures the hardware acceleration method used when transcoding. This is best left on
* `'no-preference'`, the default.
*/
hardwareAcceleration?: 'no-preference' | 'prefer-hardware' | 'prefer-software';
/** When `true`, video will always be re-encoded instead of directly copying over the encoded samples. */
forceTranscode?: boolean;
/**
* Allows for custom user-defined processing of video frames, e.g. for applying overlays, color transformations, or
* timestamp modifications. Will be called for each input video sample after transformations and frame rate
* corrections.
*
* Must return a {@link VideoSample}, a {@link VideoSampleResource} or a `CanvasImageSource`, an array of them, or
* `null` for dropping the frame. When non-timestamped data is returned, the timestamp and duration from the source
* sample will be used. Rotation metadata of the returned sample will be ignored.
*
* This function can also be used to manually resize frames. When doing so, you should signal the post-process
* dimensions using the `processedWidth` and `processedHeight` fields, which enables the encoder to better know what
* to expect. If these fields aren't set, Mediabunny will assume you won't perform any resizing.
*/
process?: (sample: VideoSample) => MaybePromise<CanvasImageSource | VideoSample | VideoSampleResource | (CanvasImageSource | VideoSample | VideoSampleResource)[] | null>;
/**
* An optional hint specifying the width of video samples returned by the `process` function, for better
* encoder configuration.
*/
processedWidth?: number;
/**
* An optional hint specifying the height of video samples returned by the `process` function, for better
* encoder configuration.
*/
processedHeight?: number;
/**
* Defines the group(s) the output t