supervision-js
    Preparing search index...

    Media Preparation

    supervision-js treats media preparation as part of the rendering foundation. For uploaded files, the browser may not be able to decode the input efficiently or consistently. The preparation APIs probe the file, choose a supported target, and normalize the video before rendering or inference workflows depend on it.

    Normalization does not close every gap. Which codecs a browser will decode, and what a browser without WebGPU costs to present a frame, are limits of the browser itself. Browser Support lists them.

    Use probeMedia() when the app wants to inspect browser support and explain problems before starting normalization:

    const probe = await probeMedia(file);

    if (probe.status === MediaProbeStatus.Unsupported) {
    console.warn(probe.issues);
    }

    Use prepareMedia() when the app can wait for a complete normalized blob:

    const prepared = await prepareMedia(file);

    const objectUrl = URL.createObjectURL(prepared.normalizedMedia.blob);

    This path is simple and useful for short files, export workflows, and tests.

    Use prepareMediaProgressively() when the app wants a renderer source as bytes are produced:

    const prepared = await prepareMediaProgressively(file, {
    normalization: {
    video: { frameRate: 30 },
    },
    });

    const session = await createMediaSession({
    container,
    media: prepared.normalizedMedia.rendererSource,
    });

    The progressive result also exposes completion, which resolves to the final normalized blob when conversion finishes.

    For the common viewer path, createMediaSession() can perform progressive normalization directly:

    const session = await createMediaSession({
    container,
    media: file,
    normalize: { stream: true },
    });

    This keeps media decoding and annotation rendering in the same renderer-owned composition while the normalized media becomes available.

    normalize makes the session build its own renderer source: an object URL for a full transcode, a streaming pull source for a progressive one. Neither is the video-engine source, so this route has no presented-frame channel, and an enabled playback gate holds every frame the renderer pulls rather than only the start of playback.

    Normalized bytes reach the engine perfectly well; there is simply no option that asks createMediaSession() for both. A host that wants both normalizes first and passes the result as an engine blob source:

    import {
    createMediaSession,
    createVideoEngineMediaRendererSource,
    prepareMedia,
    } from "supervision";
    import { SourceKind } from "supervision-js-web-video-engine";

    const prepared = await prepareMedia(file);

    const session = await createMediaSession({
    container,
    media: createVideoEngineMediaRendererSource({
    source: { blob: prepared.normalizedMedia.blob, kind: SourceKind.Blob },
    }),
    });

    Normalization is opt-in, and every field below is optional. Left unset, a session normalizes to this profile:

    Option Default
    container MediaNormalizationContainer.WebM
    video.codec VP9 for WebM, AVC for Mp4
    video.frameRate 30
    video.keyFrameInterval 1 second
    video.forceTranscode true
    video.width / video.height the source's display size
    video.bitrate unset, so the encoder chooses
    audio.discard true
    stream (session shortcut only) false

    The frame rate is the one to watch. A variable-rate input normalizes onto a constant 30Hz grid, which is what makes frameIndex a usable address for detections computed against the normalized media.

    video.forceTranscode defaults to true, so an input that already matches the target profile is still re-encoded. Set it to false when a compatible stream should be copied through instead.

    audio.discard defaults to true because nothing in the package plays audio. Keeping the track only makes the output larger.