---
sidebar:
  hidden: true
title: roboto.formats.mcap.reader
---
## Module Contents

### END_OF_STREAM

```python
roboto.formats.mcap.reader.END_OF_STREAM
```

`from roboto.formats.mcap import END_OF_STREAM`

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/formats/mcap/reader.py#L45-L45)

Sentinel returned by [`McapReader.next_decoded()`](/reference/python-sdk/roboto/formats/mcap/reader#roboto.formats.mcap.reader.McapReader.next_decoded) when the stream is exhausted.

A decoded message value can legitimately be `None` (a JSON `null` payload), so exhaustion cannot be signaled with `None` without making a real null-valued message indistinguishable from end-of-stream. Callers test `result is END_OF_STREAM` to detect exhaustion and treat every other value -- `None` included -- as a delivered message.

### McapEnvelopeTimestamp

```python
class roboto.formats.mcap.reader.McapEnvelopeTimestamp
```

`from roboto.formats.mcap.reader import McapEnvelopeTimestamp`

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/formats/mcap/reader.py#L56-L68)

Bases: `NamedTuple`

The pair of timestamps an MCAP message envelope carries.

Every MCAP message records two times in nanoseconds: 1. `log_time`, when the message was written to the file, and 2. `publish_time`, when its producer published it.

Both fields are `math.inf` when the reader is exhausted.

**Attributes**

- **McapEnvelopeTimestamp.log_time** (`int | float`)
- **McapEnvelopeTimestamp.publish_time** (`int | float`)

### McapReader

```python
class roboto.formats.mcap.reader.McapReader(
    stream: IO[bytes],
    fields: collections.abc.Sequence[roboto.formats.fields.FieldSelection],
    start_time: Optional[int] = None,
    end_time: Optional[int] = None,
    log_time_order: bool = True,
    topic_name: Optional[str] = None,
)
```

`from roboto.formats.mcap import McapReader`

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/formats/mcap/reader.py#L71-L254)

Reader for processing MCAP files with field projection.

Provides an iterator interface for reading decoded messages from MCAP files, filtered by log time and optionally by topic, and projected to selected fields. Handles JSON, msgpack, and the ROS/CDR encodings (`ros1msg` / `ros2msg` / `ros2idl` / `omgidl`).

**Parameters**

- **stream** (`IO[bytes]`)
- **fields** (`collections.abc.Sequence[roboto.formats.fields.FieldSelection]`)
- **start_time** (`Optional[int]`)
- **end_time** (`Optional[int]`)
- **log_time_order** (`bool`)
- **topic_name** (`Optional[str]`)

**Properties**

- **McapReader.field_paths** (`list[tuple[str, ...]]`): Get the path of each field being projected, in the order the fields were given at initialization.

  **Returns**

  - `list[tuple[str, ...]]`: One tuple per field, its [`path_in_schema`](/reference/python-sdk/roboto/formats/fields#roboto.formats.fields.FieldSelection.path_in_schema):

    the path components from the schema root to the field.

- **McapReader.has_next** (`bool`): Check if there are more messages available to read.

  **Returns**

  - `bool`: True if there are more messages to read, False otherwise.

- **McapReader.next_envelope_timestamp** (`McapEnvelopeTimestamp`): Get the envelope timestamps of the next message to be read.

  **Returns**

  - `McapEnvelopeTimestamp`: The next message's `log_time` and `publish_time` in nanoseconds, or both `math.inf` if no more messages.

#### McapReader.next()

```python
def next() -> Union[roboto.formats.mcap.decoded_message.DecodedMessage, None]
```

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/formats/mcap/reader.py#L177-L202)

Read and return the next decoded message.

Advances the reader to the next message and returns it as a DecodedMessage object, or None if no more messages are available.

**Returns**

- `Union[roboto.formats.mcap.decoded_message.DecodedMessage, None]`: DecodedMessage containing the next message data, or None if no more messages.

**Usage**

```python
while reader.has_next:
    message = reader.next()
    if message:
        data = message.to_dict()
        print(f"Message at {data.get('log_time')}: {data}")
```

#### McapReader.next_decoded()

```python
def next_decoded() -> Any
```

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/formats/mcap/reader.py#L204-L226)

Read and return the next message's raw decoded value, advancing the reader.

The raw value is what the format decoder produced -- a dict for JSON-encoded messages, and nested `dict` / sequence / scalar values for ROS/CDR encodings -- with no projection applied. Callers that want projected dictionary output use [`next()`](/reference/python-sdk/roboto/formats/mcap/reader#roboto.formats.mcap.reader.McapReader.next) and [`DecodedMessage.to_dict()`](/reference/python-sdk/roboto/formats/mcap/decoded_message#roboto.formats.mcap.decoded_message.DecodedMessage.to_dict) instead.

A decoded value of `None` is a real message (a JSON `null` payload) and is delivered as such. Exhaustion is signaled with the dedicated [`END_OF_STREAM`](/reference/python-sdk/roboto/formats/mcap/reader#roboto.formats.mcap.reader.END_OF_STREAM) sentinel instead, so callers must test `result is END_OF_STREAM` rather than `result is None` to detect the end.

**Returns**

- `Any`: The decoded message value, or [`END_OF_STREAM`](/reference/python-sdk/roboto/formats/mcap/reader#roboto.formats.mcap.reader.END_OF_STREAM) if no more messages are available.

#### McapReader.next_message_is_time_aligned()

```python
def next_message_is_time_aligned(timestamp: Union[int, float]) -> bool
```

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/formats/mcap/reader.py#L228-L243)

Check if the next message has the specified timestamp.

Used for time-aligned reading when merging data from multiple readers.

**Parameters**

- **timestamp** (`Union[int, float]`): Timestamp to check against in nanoseconds.

**Returns**

- `bool`: True if the next message has the specified timestamp, False otherwise.
