MCAP (pronounced "em-cap") is an open source container file format for timestamped, multimodal data such as camera frames, LiDAR point clouds, inertial measurement unit (IMU) readings, and robot state. It is the default recording format in Robot Operating System 2 (ROS 2). This guide covers how an MCAP file is structured, how MCAP relates to rosbag and to training formats such as LeRobot, how to open and inspect MCAP files, and how teams search, curate, and annotate MCAP recordings at scale.
What is MCAP?
MCAP is a modular container file format for recording timestamped publish and subscribe messages in any serialization format. A robot or vehicle publishes streams of messages on named topics, such as /camera/front/image, /lidar/points, and /joint_states, and an MCAP file records every message from every topic, in time order, in a single file. Each message carries a nanosecond timestamp, and the file embeds the schema needed to decode every message type, so the file can be read without the software that wrote it.
MCAP was created by Foxglove and is maintained as an MIT-licensed open source project, with the specification, reference libraries, and the mcap command-line tool published at mcap.dev. It is the default storage format for rosbag2, the recording tool in ROS 2, and it is also widely used outside ROS by teams that log Protobuf, FlatBuffers, or JSON messages from custom robotics stacks.
MCAP exists because robotics logging used to be fragmented. Teams on ROS 1 recorded .bag files, which are hard to read outside the ROS ecosystem. Early ROS 2 recorded to a SQLite-based format that was not fully self-contained, so third-party tools struggled to decode it. Teams outside ROS often invented their own binary formats. MCAP gives all of them one self-describing container that can hold many streams in many encodings, survives interrupted recordings, and supports fast indexed reads.
In the physical AI data lifecycle, MCAP is the recording layer. Robots and vehicles write MCAP at capture. Engineers replay MCAP files to see what happened, search and curate across many recordings to find the moments that matter, annotate the episodes worth learning from, and export the best of them into training formats. The multimodal data guide covers that full lifecycle.
MCAP is an open container format that stores timestamped messages from many sensors and software topics in one file, with their schemas embedded.
MCAP is append-only, so a recording interrupted by a crash or power loss can usually be recovered, and it supports an optional index for fast seeking.
MCAP is serialization-agnostic: ROS 1, ROS 2 Common Data Representation (CDR), Protobuf, FlatBuffers, JSON, and other encodings can share one file.
MCAP is a recording format, not a training format. Teams curate MCAP recordings and export the episodes worth training on into formats such as LeRobotDataset.
MCAP tutorials and guides from the Voxel51 blog
These posts cover MCAP recordings from opening a file to building a training set. Each section below links to more.
MCAP borrows its vocabulary from robotics middleware and file formats. These terms anchor the rest of this guide.
MCAP: an open container file format for timestamped, multimodal robotics data, and the ROS 2 default.
Message: one timestamped record of data on a channel, such as a single camera frame or IMU reading. Each message carries a log time and a publish time in nanoseconds.
Channel: a stream of messages on one topic with one encoding, such as /lidar/points encoded as ROS 2 CDR.
Schema: the definition of a message type, embedded in the file so readers can decode messages without outside dependencies.
Chunk: a block of messages written together, optionally compressed with zstd or lz4, and indexed by time.
Summary section: optional index records at the end of the file that let readers find channels, chunks, attachments, and statistics without scanning the whole file.
rosbag: the ROS 1 recording format (.bag), which many teams now convert to MCAP.
rosbag2: the ROS 2 recording tool, which writes MCAP by default and supports SQLite (.db3) as an alternative storage plugin.
ROS 2: the robotics middleware widely used across research and industry, which records to MCAP by default.
MCAP annotation: labeling objects, events, and time ranges directly on MCAP recordings.
How is an MCAP file structured?
An MCAP file is a sequence of records between two sets of magic bytes. Every record starts with a one-byte opcode and a length, so a reader can skip any record it doesn't understand. The file has five parts: a header, a data section, an optional summary section, an optional summary offset section, and a footer.
The summary section is what makes MCAP fast to read. In an indexed file, it repeats the schemas and channels, lists every chunk with its time range and byte offset, and can include statistics such as message counts per channel. A reader that wants the camera frames from second 42 reads the footer, jumps to the summary, finds the chunk that covers second 42, and decompresses only that chunk. This is also what lets tools read just the parts they need from an MCAP file in cloud storage, without downloading the whole file.
Record
What it holds
Where it lives
Header
The profile (such as ros2) and the library that wrote the file
Start of file
Schema
A message type definition, such as sensor_msgs/msg/PointCloud2
Data section, repeated in summary
Channel
A topic, its message encoding, and its schema
Data section, repeated in summary
Message
One timestamped message on a channel
Data section, usually inside chunks
Chunk
A batch of records, optionally compressed with zstd or lz4
Data section
Message index
Timestamps and offsets of messages inside a chunk
After each chunk
Attachment
An auxiliary file, such as calibration data or a map
Data section
Metadata
Arbitrary key-value pairs, such as hardware info
Data section
Data end
Marks the end of the data section, with an optional checksum
End of data section
Chunk, attachment, and metadata indexes
Where each chunk, attachment, and metadata record sits in the file
Summary section
Statistics
Message, channel, and chunk counts, plus start and end times
Summary section
Footer
Offsets to the summary section
End of file
The records in an MCAP file, with what each one holds and where it lives in the file.
The append-only design is deliberate. A recorder writes records front to back and never goes back to edit earlier bytes, and the summary is written last. If a robot loses power mid-recording, the file is missing its summary and footer but the chunks already written are intact.
Encodings, schemas, and profiles
MCAP doesn't care how a message is serialized. Each channel declares a message encoding, and each schema declares a schema encoding, and readers use those to pick a decoder. That is why one MCAP file can hold ROS 2 sensor messages next to Protobuf messages from a custom service.
Message encoding
Typical schema encoding
Common source
cdr
ros2msg or ros2idl
ROS 2
ros1
ros1msg
ROS 1 recordings converted to MCAP
protobuf
protobuf (a FileDescriptorSet)
Custom stacks and many autonomous vehicle logging pipelines
flatbuffer
flatbuffer
Performance-sensitive custom stacks
json
jsonschema, or none
Prototyping and lightweight telemetry
Common MCAP message encodings, with their typical schema encodings and sources.
The MCAP registry lists several more. Profiles add framework rules on top. A file with the ros2 profile must use CDR messages, ROS 2 schemas, and record each channel's quality of service settings, so ROS 2 tools can play it back faithfully.
Encoding mismatches are a common reason an MCAP file writes cleanly and plays back broken. A schema named after a well-known message type but written with the wrong encoding passes every structural check and only fails when a viewer tries to decode it. What actually breaks when you author MCAP by hand walks through that bug and five others.
MCAP became the default storage format for rosbag2 with the ROS 2 Iron release in 2023, replacing SQLite. Recording with ros2 bag record writes MCAP unless you choose another storage plugin. MCAP bags written by rosbag2 carry their message schemas, so tools can decode them without the original ROS workspace. From Iron on, SQLite (.db3) bags embed message definitions too.
Two practical details matter for ROS 2 teams. First, compression: rosbag2 can compress whole files or individual messages, but compressed files lose their index. MCAP's own chunk compression keeps files compressed and indexable. The simplest way to use it is a storage preset such as zstd_fast or zstd_small, and a storage configuration file gives finer control. The fastwrite preset writes messages unchunked and without a message index, which is fast to write but can't be seeked or read by topic efficiently until the file is post-processed. Second, conversion: older .bag and .db3 recordings convert to MCAP with the mcap command-line interface (CLI) or ros2 bag convert (see the FAQ below).
mcap convert recording.bag recording.mcap
ros2 bag record -a -s mcap --storage-preset-profile zstd_fast
MCAP is often compared with formats that do different jobs. rosbag and SQLite-based rosbag2 are the recording formats teams are moving off. HDF5 and LeRobotDataset are formats teams train on.
MCAP
rosbag (.bag)
rosbag2 SQLite (.db3)
HDF5
LeRobotDataset
Layer
Recording container
Recording container
Recording container
General array storage
Training dataset
Serialization
Any (ROS, Protobuf, FlatBuffers, JSON, and more)
ROS 1 only
ROS 2 CDR
Arrays, not messages
Parquet tables and MP4 video
Self-describing
Yes, schemas embedded
Yes, message definitions embedded
Only from Iron on
Partly, through attributes
Yes, schema in metadata files
Random access
Optional index in the summary
Index at end of file
Database queries
Yes
Yes, by episode and frame
Interrupted recording
Recoverable, append-only
Reindexable with rosbag reindex
Depends on the SQLite journal
Can be left unreadable
Not a recording format
Typical use
ROS 2 and custom robotics logging, replay, and curation
Legacy ROS 1 systems
Early ROS 2 systems
Research datasets such as robomimic
Imitation learning and VLA training
MCAP compared with rosbag, rosbag2 SQLite, HDF5, and LeRobotDataset by layer, serialization, self-description, random access, recovery, and typical use.
ROS 1 reached end of life with Noetic in May 2025, which is why many teams are converting their .bag archives now.
To train a robot policy, teams usually export curated episodes from MCAP into a training format such as LeRobotDataset or RLDS. The LeRobot guide covers that side.
There are three common ways to look inside an MCAP file, and each answers a different question.
Open an MCAP file from the command line
The mcap CLI reports what a file contains and pulls data out of it. mcap info summarizes the profile, duration, compression, and every channel with its message count and rate. mcap cat prints messages from chosen topics, and can decode ROS 1, Protobuf, and JSON messages into JSON lines or CSV. mcap doctor checks the file's structure, and mcap recover rebuilds a damaged file. The CLI can also read files directly from S3, Google Cloud Storage, Azure, or HTTP using the summary index.
mcap info recording.mcap
mcap cat recording.mcap --topics /joint_states
mcap doctor recording.mcap
Read an MCAP file in Python and other languages
Reference libraries read and write MCAP in several languages, including Python, C++, Go, Rust, Swift, and TypeScript. In Python, the mcap package reads raw messages, and mcap-ros1-support, mcap-ros2-support, and mcap-protobuf-support decode ROS 1, ROS 2, and Protobuf payloads. Reading a ROS 2 topic takes a few lines:
from mcap.reader import make_reader
from mcap_ros2.decoder import DecoderFactory
with open("recording.mcap", "rb") as f:
reader = make_reader(f, decoder_factories=[DecoderFactory()])
for schema, channel, message, ros_msg in reader.iter_decoded_messages(topics=["/joint_states"]):
print(message.log_time, ros_msg.position)
View an MCAP file in a browser: an MCAP viewer without ROS
Many robotics visualization tools open .mcap files, and synchronized playback puts every camera, point cloud, and plotted signal on one timeline, so you can scrub to the moment something went wrong and see every sensor at once. Voxel51 opens MCAP files in the browser with nothing to install: upload a file to a free workspace and every camera and sensor stream plays back together. This is the fastest way to understand a single recording. To work across hundreds or thousands of recordings, the next section matters more.
One MCAP file is easy to replay. A fleet's worth is not. A robot team can record thousands of hours of MCAP across sites, robots, and software versions, and the questions that matter span all of it: how often does this failure happen, which recordings contain it, and which episodes are worth labeling or training on? Opening files one at a time doesn't answer those questions.
Curating MCAP data starts with indexing. Each recording, or each episode cut from a recording, becomes a searchable sample with its metadata, such as robot, site, task, and software version, plus events and tags on its timeline. Embeddings computed from the camera streams let engineers find visually similar moments that metadata misses, and segment-level embeddings narrow that to the exact few seconds inside a long recording. Natural-language search goes one step further: an engineer can ask for "episodes where the gripper misses the handle" across thousands of recordings and review what comes back.
Quality checks belong in the same pass. Dropped messages, drifting frame rates, channels on the wrong clock, and calibration that changed mid-session all corrupt training data quietly, so teams score recordings on those checks and watch the worst ones first. Voxel51's AV audit runs 80 such checks directly on raw MCAP before any recording reaches neural reconstruction.
MCAP annotation labels objects, events, and time ranges directly on recordings, without first extracting frames to a separate folder. Labels can be 2D boxes on camera messages, 3D cuboids on point cloud messages, tracks that follow an object across the recording, or temporal tags that mark when something happened, such as "gripper closed" or "hard braking." Because every stream shares one timeline, a label made in one sensor's view can be checked against every other sensor at the same moment.
MCAP files record everything a robot logged, which is more than a policy trains on. Turning MCAP recordings into a training dataset means choosing which topics become observations and actions, cutting recordings into episodes, resampling streams that ran at different rates to one frame rate, and writing the result in a training format. Teams typically curate first and export only the episodes worth training on, because conversion multiplies whatever problems the recordings already have.
For robot learning, the most common target today is LeRobotDataset v3.0, which stores state and action data in Parquet and camera streams as MP4 video. Converting MCAP to LeRobot format is a curation decision as much as a file conversion.
A manipulation episode in MCAP typically holds wrist and fixed camera streams, joint states, gripper state, commanded actions, and transforms. Autonomous vehicle fleet logs often carry Protobuf messages from custom stacks. Drones built on ROS 2 record their flight data to it. The format is the same in every case, which is why tooling built around MCAP carries from one domain to the next. The physical AI guide covers each domain.
You can run the opening and curation steps in this guide without writing code or installing anything. In the free tier of Voxel51, you can:
Browse the 20+ demo datasets and add DROID, 1,000 robot episodes stored as MCAP with three synchronized cameras, or upload your own MCAP files. Each dataset, demo or your own, uses one of three free dataset slots.
Play all three cameras in an episode on one timeline.
Ask the Voxel51 Agent for moments in plain language, such as episodes where the robot is picking up clothes, and review what it finds.
Tag the moments that matter and save them as a view your team can reopen.
An MCAP file (.mcap) is a recording of timestamped messages from a robot, vehicle, or other system, stored in the open MCAP container format. It can hold camera frames, point clouds, IMU readings, robot state, and any other topic, in any serialization format, with the schemas needed to decode them embedded in the file.
To open an MCAP file, use the mcap CLI to summarize it with mcap info and print messages with mcap cat, use the reference libraries to read it in code, or open it in a viewer that plays every stream back on one timeline. You can also upload MCAP files to a free Voxel51 workspace and replay them in your browser.
rosbag (.bag) is the ROS 1 recording format and stores only ROS 1 messages. MCAP is a newer container that stores messages in any encoding, including ROS 1 and ROS 2, embeds their schemas, supports compressed and indexed chunks, and is the default rosbag2 storage format in ROS 2. You can convert a .bag file with mcap convert.
MCAP is not officially an acronym. The MCAP project gives the name and its pronunciation, "em-cap," but no expansion, and the expansions that appear on third-party sites are guesses.
To view an MCAP file without ROS, upload it to a browser-based viewer that plays every stream on one timeline, such as a free Voxel51 workspace, or summarize it with mcap info from the command line. Neither needs a ROS install, because MCAP files carry their own schemas.
The mcap convert command converts ROS 1 .bag files and ROS 2 .db3 files to MCAP directly. .db3 files recorded before Iron don't embed message definitions, so convert those with ros2 bag convert while the original ROS workspace is sourced. Going the other way, ros2 bag convert can rewrite an MCAP bag as a ROS 2 SQLite (.db3) bag. The mcap CLI only converts into MCAP, and there is no official tool for converting back to ROS 1 .bag files.
A corrupted MCAP file can usually be recovered. Because MCAP is append-only, a recording cut short by a crash still contains the chunks written before it stopped. mcap recover reads what's intact and writes a valid, indexed copy, and its exit code tells you whether anything was lost.