Probe metadata

Read container format, duration, bitrate, and per-stream info without decoding a single frame.

wasmpeg.probe() opens a container, reads its metadata, and returns it as a plain object — all without decoding a single frame. Use it to show a duration, check dimensions, or inspect the stream layout before you commit to a full decode.

Synopsis

const info = await wasmpeg.probe(input);

Returns an object: { format, duration, bitrate, streams, video, audio }.

Description

Probing reads only enough of the stream to identify the container and its streams, then stops. No frames are decoded and no pixels or samples are produced, so it’s cheap relative to a decode — but it still uses one of the 8 shared session slots for the length of the call. That slot is released automatically before probe() resolves, so there’s nothing to close.

probe() takes encoded input only: a File, a Blob, an http(s) URL string, a Uint8Array, or an ArrayBuffer. It does not accept raw pixel inputs (a canvas, a video element, or ImageData) or WASM FS paths — those throw.

A few fields can be absent in the source. When a container doesn’t record its duration, duration comes back null. When there’s no video stream, every video.* field is -1; the same goes for audio.* when there’s no audio. Check those before you divide by them.

Return shape

{
  format:   'mov,mp4,m4a,3gp,3g2,mj2',   // container name
  duration: 12.4,                        // seconds, or null if unknown
  bitrate:  2400,                        // overall bitrate, kb/s
  streams: [
    { index: 0, type: 'video' },
    { index: 1, type: 'audio' },
  ],
  video: { width: 1920, height: 1080, fpsNum: 30000, fpsDen: 1001 },
  audio: { sampleRate: 48000, channels: 2 },
}

Fields

  • format — the demuxer name FFmpeg matched. Many demuxers cover a family of containers, so the name can be a comma-joined list like mov,mp4,m4a,3gp,3g2,mj2.
  • duration — total duration in seconds, or null when the container doesn’t record it (common for raw and streaming formats).
  • bitrate — overall bitrate in kb/s.
  • streams — one entry per stream, each { index, type }. index is the stream’s position in the container; type is one of 'video', 'audio', 'data', 'subtitle', 'attachment', or 'unknown'.
  • video{ width, height, fpsNum, fpsDen } for the first video stream. Frame rate is given as a rational pair so you keep exact rates like 30000/1001. All four are -1 when there’s no video.
  • audio{ sampleRate, channels } for the first audio stream. Both are -1 when there’s no audio.
Note
video and audio describe the first stream of each kind, the common case for most media. To inspect every track — say, a file with two audio languages — walk the streams array. Per-stream codec parameters beyond type aren’t exposed here; probe() reports the container-level summary.

Examples

Check for a video track and read its frame rate

const info = await wasmpeg.probe(file);
const hasVideo = info.streams.some((s) => s.type === 'video');
const fps = hasVideo ? info.video.fpsNum / info.video.fpsDen : 0;

Build fps from the rational pair rather than rounding, so 30000/1001 stays 29.97… rather than a lossy 30.

Format a duration label

const label = info.duration == null
    ? 'unknown'
    : `${Math.floor(info.duration / 60)}:${String(Math.floor(info.duration % 60)).padStart(2, '0')}`;

The == null guard catches the case where the container didn’t record a duration.

Count streams by kind

const counts = info.streams.reduce((acc, s) => {
    acc[s.type] = (acc[s.type] ?? 0) + 1;
    return acc;
}, {});
// e.g. { video: 1, audio: 2, subtitle: 1 }

Decide before decoding

const info = await wasmpeg.probe(file);

if (info.video.width === -1) {
    throw new Error('no video stream to decode');
}
if (info.video.width > 4096) {
    // huge source — decode straight to a smaller target
    const dec = await wasmpeg.decode(file);
    const frame = dec.nextFrame(1280, 720);
    dec.close();
}

Notes

  • Probing is read-light but not free — it allocates a session slot for the duration of the call and frees it before resolving. You never call close() on a probe.
  • For raw bitstreams with no header, the probe may report width: 0 or an unhelpful format. Those are the same formats where decode() and decodeAudio() take a format hint to force the demuxer.

See also