mcap-format

GitHub

提供MCAP文件格式规范知识,涵盖二进制结构、记录类型、索引策略及压缩选项。旨在指导创建优化Lichtblick读取性能的MCAP文件,包含格式概览、头部、数据段、摘要段等详细结构说明。

.github/skills/mcap-format/SKILL.md lichtblick-suite/lichtblick

Trigger Scenarios

询问MCAP文件格式细节 分析MCAP文件结构 优化MCAP文件以改善Lichtblick性能 了解MCAP记录类型和索引

Install

npx skills add lichtblick-suite/lichtblick --skill mcap-format -g -y
More Options

Non-standard path

npx skills add https://github.com/lichtblick-suite/lichtblick/tree/develop/.github/skills/mcap-format -g -y

Use without installing

npx skills use lichtblick-suite/lichtblick@mcap-format

指定 Agent (Claude Code)

npx skills add lichtblick-suite/lichtblick --skill mcap-format -a claude-code -g -y

安装 repo 全部 skill

npx skills add lichtblick-suite/lichtblick --all -g -y

预览 repo 内 skill

npx skills add lichtblick-suite/lichtblick --list

SKILL.md

Frontmatter
{
    "name": "mcap-format",
    "description": "MCAP file format specification knowledge: binary structure, record types, indexing strategies, compression options, and best practices for creating MCAP files that optimize Lichtblick reading performance."
}

MCAP Format Skill

Format Overview

MCAP is an open-source container format for heterogeneous timestamped data, designed for high-performance reading of robotics/autonomous driving recordings.

Specification: https://mcap.dev/spec

Documentation:

Binary Structure

┌─────────────────────────────────────────┐
│ Magic bytes (8 bytes)                   │
├─────────────────────────────────────────┤
│ Header record                           │
│   - profile: "ros1" | "ros2" | ""       │
│   - library: writer identifier          │
├─────────────────────────────────────────┤
│ DATA SECTION                            │
│   Schema records                        │
│   Channel records                       │
│   Message records (bulk of file)        │
│   Attachment records (optional)         │
│   Metadata records (optional)           │
│   ─── grouped into Chunks ───           │
├─────────────────────────────────────────┤
│ DataEnd record                          │
├─────────────────────────────────────────┤
│ SUMMARY SECTION (optional but critical) │
│   Schema records (copy)                 │
│   Channel records (copy)                │
│   ChunkIndex records                    │
│   AttachmentIndex records               │
│   MetadataIndex records                 │
│   Statistics record                     │
├─────────────────────────────────────────┤
│ Footer record                           │
│   - summarySectionOffset                │
│   - summarySectionCrc                   │
├─────────────────────────────────────────┤
│ Magic bytes (8 bytes)                   │
└─────────────────────────────────────────┘

Record Types

Header

  • profile: Identifies message conventions (e.g., "ros1", "ros2")
  • library: Identifies the writing library (for debugging)

Schema

  • id: Unique schema identifier within the file
  • name: Schema name (e.g., "sensor_msgs/PointCloud2")
  • encoding: How to interpret schema data ("ros1msg", "ros2msg", "protobuf", "flatbuffer", "jsonschema", "ros2idl")
  • data: Raw schema definition bytes

Channel

  • id: Unique channel identifier
  • topic: Topic name (e.g., "/camera/image")
  • schemaId: References a Schema record
  • messageEncoding: How messages are serialized ("ros1", "cdr", "json", "protobuf", "flatbuffer")
  • metadata: Key-value pairs (e.g., callerid for ROS 1 publisher identification)

Message

  • channelId: Which channel this message belongs to
  • logTime: When the message was recorded (nanoseconds)
  • publishTime: When the message was originally published (nanoseconds)
  • data: Raw serialized message bytes
  • sequence: Optional sequence number

Chunk

  • compression: "zstd" | "lz4" | "" (none)
  • data: Compressed block containing Schema + Channel + Message records
  • Messages within a chunk are ordered by logTime
  • Chunk boundaries define the granularity of random access

ChunkIndex (Summary)

  • messageStartTime / messageEndTime: Time range of messages in this chunk
  • chunkOffset: Byte offset of the chunk in the file
  • messageIndexOffsets: Per-channel index within the chunk
  • Critical for random access — without these, no seeking is possible

Statistics (Summary)

  • messageCount: Total messages in file
  • channelMessageCounts: Per-channel message counts
  • schemaCount: Number of schemas
  • channelCount: Number of channels
  • chunkCount: Number of chunks
  • messageStartTime / messageEndTime: Global time bounds

Attachment

  • Named binary blobs (e.g., calibration files, maps)
  • Indexed separately from messages
  • Not time-ordered with messages

Metadata

  • Named key-value string maps
  • Used for recording metadata (robot name, location, session info)

Indexed vs Unindexed Reading

Indexed (preferred for Lichtblick)

  • File has Summary section with ChunkIndex records
  • Reader reads Footer → jumps to Summary → builds index in memory
  • Random access: find chunks overlapping time range → read only those chunks
  • Reverse iteration: read chunks in reverse order for backfill
  • Lichtblick uses: McapIndexedReaderMcapIndexedIterableSource

Unindexed (fallback)

  • No Summary section — file must be read sequentially from start
  • All messages loaded into memory (Lichtblick limits to 1GB)
  • No seeking, no backfill, no progress reporting during load
  • Lichtblick uses: McapStreamReaderMcapUnindexedIterableSource

Compression Trade-offs

Algorithm Ratio Decompress Speed Best For
zstd Excellent (~3-5x) Fast Storage, archival, remote files
lz4 Good (~2-3x) Very fast Real-time recording, low-latency playback
None 1:1 Instant Debugging, maximum seek speed

Impact on Lichtblick

  • Decompression uses WASM modules (wasm-zstd, wasm-lz4, wasm-bz2)
  • Modules are loaded lazily on first MCAP open (adds ~100ms startup)
  • loadDecompressHandlers() is a singleton — loads once, shared across all readers
  • Larger chunks with zstd = fewer decompressions but more memory per chunk

Best Practices for Optimal Lichtblick Performance

1. Always Include Chunk Indexes

  • Without indexes, Lichtblick falls back to streaming (1GB limit, no seek)
  • Write summary section at end of file with all ChunkIndex records
  • Include Statistics record for immediate UI display of file metadata

2. Put Schemas and Channels in Summary

  • Allows Lichtblick to display topic list without reading data section
  • Speeds up initialization (only 2 Range requests for remote files)

3. Target ~4MB Chunk Size

  • Too small (<100KB): excessive index overhead, many seeks
  • Too large (>50MB): wastes memory when seeking (must decompress full chunk)
  • ~4MB: good balance for random access granularity vs overhead

4. Use Consistent Chunk Boundaries

  • Align chunk boundaries with logical time units when possible
  • Avoid chunks spanning very long time ranges (hurts seek precision)

5. Order Messages by logTime Within Chunks

  • MCAP spec allows out-of-order, but ordered messages enable streaming reads
  • Lichtblick's reader assumes logTime ordering within chunks

6. Include callerid in Channel Metadata (ROS)

  • Used by Lichtblick to identify publishers per topic
  • Helps with diagnostics and multi-publisher scenarios

7. Choose Compression Based on Use Case

  • Remote viewing: zstd (minimize download size, acceptable decompress cost)
  • Local playback: lz4 (fastest decompress, acceptable file size)
  • Real-time recording: lz4 or none (lowest CPU overhead during recording)

Lichtblick Code Mapping

MCAP Concept Lichtblick Code
Indexed reading McapIndexedReader (from @mcap/core)
Streaming reading McapStreamReader (from @mcap/core)
Indexed source McapIndexedIterableSource.ts
Unindexed source McapUnindexedIterableSource.ts
File readable BlobReadable.ts (local), RemoteFileReadable.ts (HTTP Range)
Remote read coalescing BatchingReadable.ts (merges nearby read() calls in a microtask tick)
Decompression packages/mcap-support/src/decompressHandlers.ts
Schema parsing packages/mcap-support/src/parseChannel.ts
10s read-ahead (default) BufferedIterableSource (DEFAULT_READ_AHEAD_DURATION = { sec: 10, nsec: 0 })
Reverse iteration McapIndexedIterableSource.getBackfillMessages()

Version History

  • cab9317 Current 2026-07-24 12:16

Same Skill Collection

.github/skills/3d-rendering/SKILL.md
.github/skills/caching-internals/SKILL.md
.github/skills/deserialization/SKILL.md
.github/skills/e2e-playwright-mcp/SKILL.md
.github/skills/electron-internals/SKILL.md
.github/skills/extensions-internals/SKILL.md
.github/skills/layouts-internals/SKILL.md
.github/skills/message-path/SKILL.md
.github/skills/message-pipeline/SKILL.md
.github/skills/panel-extension-api/SKILL.md
.github/skills/panel-image/SKILL.md
.github/skills/panel-log/SKILL.md
.github/skills/panel-map/SKILL.md
.github/skills/panel-raw-messages/SKILL.md
.github/skills/panel-state-transitions/SKILL.md
.github/skills/panel-user-scripts/SKILL.md
.github/skills/performance/SKILL.md
.github/skills/player-internals/SKILL.md
.github/skills/plot-internals/SKILL.md
.github/skills/remote-caching/SKILL.md
.github/skills/test-conventions/SKILL.md
.github/skills/theme/SKILL.md
.github/skills/unit-testing/SKILL.md
.github/skills/web-workers/SKILL.md
.github/skills/websocket-connection/SKILL.md

Metadata

Files
0
Version
cab9317
Hash
2d79473d
Indexed
2026-07-24 12:16

Accueil - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-08-07 13:21
浙ICP备14020137号-1 $Carte des visiteurs$