mcut
@mcut/media

Functions

Functions and constants exported by @mcut/media.

Constants

DEFAULT_ACTIVITY_FRAME_MS

const DEFAULT_ACTIVITY_FRAME_MS = 30

Default analysis frame length for audio activity, 30 ms.

DEFAULT_ACTIVITY_THRESHOLD

const DEFAULT_ACTIVITY_THRESHOLD = 0.004

Default RMS level above which a frame counts as sound.

DEFAULT_MIN_SILENCE_MS

const DEFAULT_MIN_SILENCE_MS = 120

Default length below which a silent run is treated as sound, 120 ms.

DEFAULT_MIN_SOUND_MS

const DEFAULT_MIN_SOUND_MS = 120

Default length below which a sound run is treated as silence, 120 ms.

MAX_HASHABLE_BYTES

const MAX_HASHABLE_BYTES = 512 * 1024 * 1024

The largest blob size that hashBlob will digest, 512 MiB.

containerFormats

const containerFormats = {
  mp4: {
    label: 'MP4',
    extension: 'mp4',
    mimeType: 'video/mp4',
    createOutputFormat: () => Promise<Mp4OutputFormat>,
  },
  webm: {
    label: 'WebM',
    extension: 'webm',
    mimeType: 'video/webm',
    createOutputFormat: () => Promise<WebMOutputFormat>,
  },
  mkv: {
    label: 'MKV',
    extension: 'mkv',
    mimeType: 'video/x-matroska',
    createOutputFormat: () => Promise<MkvOutputFormat>,
  },
} satisfies Record<string, ContainerFormat>

The closed table of export containers, MP4, WebM, and MKV, each muxed by the matching Mediabunny output format. Each factory is async () => new (await import('mediabunny')).Mp4OutputFormat() and so on, because Mediabunny loads on first use.

Functions

mediabunnyProber

const mediabunnyProber: MediaProber

The default MediaProber. Its id is mediabunny and its probe reads a blob origin through probeMedia.

createAsset

async function createAsset(origin: MediaOrigin, prober: MediaProber = mediabunnyProber): Promise<AssetRef>

Probes a media origin with the given prober and returns an AssetRef with an object URL as src and a SHA-256 hash when the blob is small enough to hash. Image origins skip the prober and are measured with probeImage.

preloadMediabunny

async function preloadMediabunny(): Promise<void>

Loads Mediabunny ahead of the first media call. Call it once the shell has painted so the first import or preview does not wait on the download.

inputFor

async function inputFor(src: MediaSourceLike): Promise<Input>

Opens a Mediabunny Input over a blob or a blob or HTTP URL. Mediabunny itself loads on the first call, so nothing in @mcut/media pulls the demuxers and muxers into an app's startup bundle.

probeImage

function probeImage(src: string): Promise<{ width: number; height: number }>

Loads an image URL in the browser and resolves with its intrinsic width and height.

probeMedia

async function probeMedia(src: MediaSourceLike): Promise<MediaProbe>

Reads the duration, dimensions, track presence, and MIME type of an audio or video file.

getVideoThumbnail

async function getVideoThumbnail(
  src: MediaSourceLike,
  options: ThumbnailOptions = {},
): Promise<HTMLCanvasElement | OffscreenCanvas | null>

Captures one poster frame from a video into a canvas, preferring native video capture and falling back to a Mediabunny canvas sink, or returns null for audio-only files.

getVideoThumbnailUrl

async function getVideoThumbnailUrl(
  src: MediaSourceLike,
  options: ThumbnailOptions = {},
): Promise<string | null>

Returns a poster frame as a data URL, or null for audio-only files.

extractAudioToWav

async function extractAudioToWav(
  src: MediaSourceLike,
  options: ExtractAudioOptions = {},
): Promise<Blob | null>

Decodes a file's audio track into a PCM WAV blob at 16 kHz mono by default, retrying without resampling when conversion fails, or returns null when there is no audio track.

ensureFallbackAudioEncoders

function ensureFallbackAudioEncoders(): Promise<void>

Registers the WASM AAC encoder once when the runtime cannot encode AAC natively, loading it on demand.

getActiveMediaItems

function getActiveMediaItems(project: Project, timeMs: number): ActiveMediaItem[]

Returns the video feeds the preview pool keeps live at timeMs on visible tracks, with their source time, rate, and reversal. Audio clips and audio-only multicam sources are left out because PreviewAudio plays sound.

exportProject

async function exportProject(
  project: Project,
  options: ExportProjectOptions = {},
): Promise<ExportResult>

Renders a project to a video file in the browser, mixing audio on the main thread and then decoding, compositing, encoding, and muxing frames in a worker when one is available.

getExportSupport

async function getExportSupport(format: ContainerFormatId = 'mp4'): Promise<{
  video: boolean
  audio: boolean
}>

Resolves with whether the browser can encode video and audio for the given container format.

renderProjectStill

Renders one timeline frame to a PNG blob. A timeMs past the project end throws, and the error names the project duration. A timeMs at the project end renders the last frame. soloElementId draws only that element, including a multicam composite, and throws when that element is not on screen. width caps the PNG width and keeps the project aspect ratio. Omit it to render at the project size. The result carries the PNG blob, the pixel size, and the ids of the elements drawn.

findSceneChanges

async function findSceneChanges(project: Project, options?: SceneChangeOptions): Promise<SceneChangeReport>

Reports the timeline times where the picture of one video clip or one multicam source changes. It decodes the source, downscales every frame it samples to 64 by 36 luma, and compares each sample with the one stepMs before it. A pair counts as a change when the fraction of cells whose luma moves by more than 24 of 255 reaches the threshold for sensitivity. It then decodes every frame between that pair and puts the change on the frame with the largest difference. The report lists the changes with the fraction that changed, and the segments between them.

renderContactSheet

async function renderContactSheet(project: Project, options?: ContactSheetOptions): Promise<ContactSheet>

Renders a PNG grid of thumbnails of one video clip or one multicam source, one tile per time, each labelled with its timeline time in seconds. Pass timesMs for exact times, or count to spread tiles evenly over the range. Times outside the range are dropped, and the call throws when none is left.

listContainerFormats

function listContainerFormats(): ContainerFormatEntry[]

Returns every entry of the containerFormats table with its id, in table order.

getFilmstrip

async function getFilmstrip(
  src: MediaSourceLike,
  options: FilmstripOptions,
): Promise<Filmstrip | null>

Draws evenly spaced frames of a video side by side into one canvas, preferring native video capture and falling back to a Mediabunny canvas sink, or returns null.

canUseNativeVideoPreview

function canUseNativeVideoPreview(media: VideoPreviewCapability): boolean

Returns true when an asset plays through a native video element rather than decoded frames, based on its nativePreview flag, container, and canPlayType.

isMatroskaLike

function isMatroskaLike(media: VideoPreviewCapability): boolean

Returns true when the file name or MIME type indicates a Matroska container.

bucketPeaks

function bucketPeaks(samples: Float32Array, buckets: number): Float32Array

Folds samples into the given number of buckets, each holding the maximum absolute amplitude of its span.

extractAudioPeaks

async function extractAudioPeaks(
  src: MediaSourceLike,
  options: AudioPeaksOptions = {},
): Promise<AudioPeaks | null>

Decodes a file's audio and reduces it to waveform peaks over the source range, or returns null when there is no audio track.

analyzeAudioActivity

async function analyzeAudioActivity(
  src: MediaSourceLike,
  options: AudioActivityOptions = {},
): Promise<AudioActivity | null>

Decodes a media source's primary audio track and returns its sound and silence windows, or null when there is no audio track.

analyzeAudioSamples

function analyzeAudioSamples(
  samples: Float32Array,
  sampleRate: number,
  options: AudioActivityOptions = {},
): AudioActivity

Splits mono PCM samples into frames, classifies them by RMS, smooths short runs, and returns sound and silence windows with a summary.

hashBlob

async function hashBlob(blob: Blob): Promise<string | null>

Returns the SHA-256 hex digest of a blob, or null when the store is unsupported or the blob is too large.

isMediaStoreSupported

function isMediaStoreSupported(): boolean

Returns true when the origin private file system and WebCrypto are available.

loadMediaBlob

async function loadMediaBlob(hash: string): Promise<Blob | null>

Loads the blob stored under a hash from the origin private file system, or null.

pruneMediaBlobs

async function pruneMediaBlobs(keep: ReadonlySet<string>): Promise<number>

Deletes stored blobs whose hash is not in keep and returns how many were removed.

saveMediaBlob

async function saveMediaBlob(hash: string, blob: Blob): Promise<boolean>

Stores a blob under its hash in the origin private file system, skipping the write when it is already present, and returns whether it is stored.

constantSpeedOf

function constantSpeedOf(timeMap: TimeMap | undefined): ConstantSpeed | null

Returns the constant rate and source span a two-point linear time map encodes, or null for ramps and freezes.

stretchStereo

async function stretchStereo(data: StereoData, tempo: number): Promise<StereoData>

Stretches stereo PCM by tempo with pitch preserved, so a tempo of 2 yields half the length.

crossCorrelateEnvelopes

function crossCorrelateEnvelopes(
  a: Float32Array,
  b: Float32Array,
  maxLagBuckets: number,
): { lag: number; confidence: number }

Cross-correlates two zero-meaned envelopes over a bounded lag range and returns the lag in buckets that best aligns b to a together with a confidence score.

extractEnvelope

async function extractEnvelope(
  src: MediaSourceLike,
  { windowS = 60, rateHz = 100, signal }: AudioSyncOptions = {},
): Promise<Float32Array | null>

Decodes the first windowS seconds of a source's audio into an RMS envelope at rateHz buckets per second, or null without audio.

findSyncOffsetMs

async function findSyncOffsetMs(
  a: MediaSourceLike,
  b: MediaSourceLike,
  options: AudioSyncOptions = {},
): Promise<SyncResult | null>

Returns how many milliseconds after recording a started recording b started, with a confidence score, or null when either has no audio.

createLocalFaceDetector

createLocalFaceDetector(options) returns a detector whose detect(src, { sampleRateHz, signal }) reads a video in a module worker, 5 times a second by default, and resolves to one FaceSample per sample time. The worker bundles the MIT-licensed YuNet 2023mar model from OpenCV Zoo, so no run downloads it. Calls run one at a time, and an aborted signal rejects its call and stops the worker.

OptionMeaning
ortWasmPaths{ mjs, wasm } URLs of the onnxruntime files, loaded instead of the jsDelivr copies
onProgressCalled with { phase, progress }, where phase is model during the download and detect while frames are read, and progress runs from 0 to 1
createWorkerReplaces the worker the detector starts

On this page