npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

mp4-to-mcap

v0.1.1

Published

Convert an MP4 video file to an MCAP file by repackaging its H.264/H.265 bitstream into foxglove.CompressedVideo messages — no re-encoding.

Readme

mp4-to-mcap

Convert an MP4 video file to an MCAP file — with no transcoding. Each video frame is repackaged, byte-for-byte, into a foxglove.CompressedVideo message, so the result plays back in Foxglove Studio or any other Foxglove-schema-aware MCAP viewer.

npx mp4-to-mcap input.mp4
Converting |████████████████████████████████████████| 100% | 300/300 frames | ETA: 0s
Wrote 300 h264 frames (1920x1080, 10.00s) to input.mcap (42.31 MB)

Why "no transcoding"?

The video bitstream inside your MP4 is already H.264 or H.265 encoded. This tool doesn't decode and re-encode it — it demuxes the MP4 container in pure JS (no ffmpeg, no protoc), converts each sample from MP4's length-prefixed NAL format to the Annex-B start-code format foxglove.CompressedVideo expects, and writes one message per frame. The encoded pixels never change.

On every keyframe, the track's SPS/PPS (and VPS, for H.265) parameter sets are prepended so the bitstream is self-decodable from that point — the same thing a camera-facing encoder does natively.

Install

npm install -g mp4-to-mcap

Or run it once with npx mp4-to-mcap ... without installing.

Usage

mp4-to-mcap <input.mp4> [options]

Options:
  -o, --output <path>   output .mcap file path (default: <input> with .mcap extension)
  -t, --topic <topic>   MCAP topic for the video channel (default: "/camera/h264")
  --frame-id <id>       frame_id recorded in each CompressedVideo message (default: "")
  -q, --quiet           suppress the progress bar
  -V, --version         output the version number
  -h, --help            display help

As a library

import { convertMp4ToMcap } from "mp4-to-mcap";

const result = await convertMp4ToMcap("input.mp4", "output.mcap", {
  topic: "/camera/h264",
  onProgress: (framesWritten, totalFrames) => {
    console.log(`${framesWritten}/${totalFrames}`);
  },
});

Limitations

  • Codecs: only H.264 (avc1/avc3) and H.265 (hvc1/hev1) video tracks are supported — the whole point of this tool is repackaging an existing bitstream, so other codecs (VP9, AV1, ...) aren't handled.
  • B-frames: frames are written in decode order using each sample's decode timestamp. For the common case (no B-frame reordering, dts == cts) this is exactly correct. If the source uses B-frames, the CLI prints a warning — Foxglove's video panel does not support B-frame video streams (it has no lookahead), so playback may be inaccurate. This matches a documented limitation of foxglove.CompressedVideo itself.
  • Audio and other tracks in the source MP4 are ignored; only the first video track is converted.
  • The whole input file is read into memory.

The foxglove.CompressedVideo convention

This isn't a bespoke format — it's the same schema and per-frame-message structure that coScene's own MCAP video tooling (encoders that produce .mini.mcap files, OSS video extraction pipelines) already uses. If you're working in that ecosystem, output from this tool is drop-in compatible.

License

MIT