MoQ for the Curious

Chapter 03

Tracks, Groups and Objects

On this page

MoQ names content so that a viewer can request just the pieces it needs. In our lecture, a student joining late might want audio and low-resolution video without downloading the earlier ten minutes.

We’ll build up the names one piece at a time: tracks, groups, then objects. After that, we’ll see how subgroups carry objects on streams and what happens to those names when a publisher restarts.

What is a track?

A track is a named sequence of groups that a subscriber can request. Our lecture has separate tracks for audio, low-resolution video, and high-resolution video. Subscribing to video-low asks for that sequence; it does not also request video-high.

Tracks belong to a namespace, which lets the application organize related names. For this lecture, we use the namespace lectures / session-7. Together, the namespace and track name identify the full track.

flowchart TD
  accTitle: Selecting tracks from a lecture
  accDescr: The lecture namespace contains audio, video-low, and video-high tracks. The example viewer subscribes to audio and video-low.
  L["Namespace: lectures / session-7"] --> A["Track: audio"]
  L --> V["Track: video-low"]
  L --> H["Track: video-high"]
  A --> S["Student receives audio and low-resolution video"]
  V --> S

We’ve written the names as text to make the example easy to follow. MOQT sends namespace components and track names as bytes, so the publisher and subscriber need to use exactly the same bytes. See track naming in draft-21 §2.4.1.

How do groups provide starting points?

A group organizes objects within a track. A video format can use each group as a place to begin decoding. That answers the late-arriving student’s next question: where should playback start?

Many compressed pictures describe changes from earlier pictures. Receiving one of these predicted frames without its reference pictures is like receiving “move it two pixels to the left” without knowing what “it” is. A keyframe provides a picture from which decoding can restart.

For our video format, the publisher begins each group with a keyframe, then puts the frames that depend on it in the same group. The student can start with a recent group instead of reconstructing the entire lecture. The player also needs the codec configuration, which the media format supplies separately.

flowchart LR
  accTitle: Two independently decodable video groups
  accDescr: Group 41 starts with its own keyframe and dependent frames. Group 42 starts with a new keyframe and has no picture dependency on group 41 in this example.
  subgraph G41["Group 41"]
    direction TB
    A["Object 0: keyframe"] --> B["Object 1: predicted frame"]
    B --> C["Object 2: predicted frame"]
  end
  subgraph G42["Group 42"]
    direction TB
    D["Object 0: new keyframe"] --> E["Object 1: predicted frame"]
    E --> F["Object 2: predicted frame"]
  end

Each arrow runs from a reference picture to a picture that needs it. These are decoding dependencies, not network packets. A viewer who has missed group 41 can still use group 42. This is why MOQT recommends independently useful groups. A group boundary alone cannot make a picture decodable: the publisher must put a suitable picture there.

Group IDs order groups within the track. Group 42 does not mean “42 seconds,” and groups need not have equal duration. The media format carries timing information for playback.

What identifies an object?

Inside each group are objects. Each normal object has an ID and a payload: the bytes being delivered. Our example puts one encoded picture in each object. Other media formats can divide their data differently. Subscription delivery also uses payload-free status markers to signal the end of a group or track; those markers are not encoded pictures. See object status in draft-21 §11.1.2.

We can now give a complete address for one picture:

Part of the identity Example What it selects
Track namespace lectures / session-7 This lecture
Track name video-low Its low-resolution video
Group ID 42 One group in that track
Object ID 1 One piece of data in that group

Suppose another service also has a track called video-low under lectures / session-7. That’s fine as long as the services belong to different scopes. A scope is the set of servers that agree to treat a full track name as the same track. Within our lecture service’s scope, the full address above must always refer to the same payload. See objects (§2.1) and scope (§2.5).

This property is called immutability. Once published, an object’s payload does not change. If Alice and Bob request the same object, a relay can serve the same stored bytes to both. A corrected payload needs a new identity; otherwise the relay would have no way to know which version the name means.

How do subgroups map objects to streams?

A subgroup organizes objects from one group for delivery. It lets the publisher put related objects on the same stream while separating other work.

For subscription delivery, MOQT normally carries each subgroup on one subgroup stream. Within a subgroup, objects are ordered by object ID. This lets the publisher separate work that benefits from separate transport streams. A subgroup can use another stream if an earlier stream was reset prematurely or upstream conditions forced objects out of order; different subgroups must not share a subscription stream.

For example, a layered video codec might produce a base layer that gives a usable picture and an enhancement layer that adds detail. Putting them in separate subgroups lets a scheduler favor the base layer when capacity is scarce. The enhancement still depends on the base; a separate stream does not remove that media dependency.

A subgroup organizes delivery; its ID is not an extra component of the object address in the table above. Objects delivered as datagrams do not belong to subgroups, and fetched objects have their own stream representation. These distinctions are defined in draft-21 §2.2.

Keep the two kinds of structure separate

A track describes content. A stream carries bytes. Their lifetimes need not match: one video track can continue throughout the lecture while new subgroup streams open as new groups are published.

Question Content structure Delivery structure
Which video does Alice want? The video-low track A subscription requests it
Where can her decoder start? A group beginning at a usable picture The required objects must arrive before playback
What identifies one picture in this example? Its track, group ID, and object ID That identity survives forwarding through a relay
Which bytes wait behind a loss? Objects may depend on other objects for decoding Bytes on the same stream share ordered delivery

This distinction matters in logs: a subgroup stream ending can be normal even while the track and subscription remain active.

What happens to names after a restart?

Suppose the lecturer’s publisher crashes. When it restarts, it reuses video-low, group 42, object 1 for a new picture. A relay still has the old picture stored under that address. It cannot safely treat both as the same immutable object.

We could put the restarted lecture under a fresh namespace, such as lectures / session-8. Or we could keep track of the group IDs and continue without reusing them. Either way, a new picture needs an address that won’t collide with an old one.

The relay can now distinguish the new content from its cached objects. Next, we’ll follow a student’s request for a track.

How does moq-lite name these concepts?

When working with the moq-lite implementation, you will encounter broadcast for a named collection of tracks and frame for the payload unit corresponding to an object. moq-lite omits MOQT subgroups and normally sends each group on its own stream. Since moq-lite 05, a small group containing one frame can instead use a datagram, subject to the transport’s size limit. Keep that distinction in mind when moving between its documentation and the IETF specification.

Sources and further reading