Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/moqtail/moqtail/llms.txt

Use this file to discover all available pages before exploring further.

MoqtObject

The MoqtObject class is the fundamental unit of data in MOQtail, representing a single media or data object with associated metadata, location, and optional payload.

Overview

A MoqtObject encapsulates:
  • Location - Group and object IDs
  • Payload - Optional raw bytes (media frame, data chunk, etc.)
  • Status - Object status (normal, end of group, end of track, does not exist)
  • Metadata - Priority, forwarding preference, extension headers
  • Track Identity - Full track name reference

Class Definition

class MoqtObject {
  readonly fullTrackName: FullTrackName;
  readonly location: Location;
  readonly subgroupId: bigint | null;
  readonly publisherPriority: number;
  readonly objectForwardingPreference: ObjectForwardingPreference;
  readonly objectStatus: ObjectStatus;
  readonly extensionHeaders: KeyValuePair[] | null;
  readonly payload: Uint8Array | null;
}

Properties

fullTrackName
FullTrackName
Fully qualified track identifier this object belongs to
location
Location
Position within the track: { group: bigint, object: bigint }Accessible via:
  • location.group or groupId
  • location.object or objectId
subgroupId
bigint | null
Subgroup identifier for subgroup-forwarded objects. null for datagram-forwarded objects.
publisherPriority
number
Publisher-assigned priority (0 = highest, 255 = lowest)
objectForwardingPreference
ObjectForwardingPreference
Delivery mechanism:
  • ObjectForwardingPreference.Subgroup - Reliable ordered delivery
  • ObjectForwardingPreference.Datagram - Unreliable low-latency delivery
objectStatus
ObjectStatus
Status indicator:
  • ObjectStatus.Normal (0x0) - Object exists with payload
  • ObjectStatus.DoesNotExist (0x1) - Object does not exist
  • ObjectStatus.EndOfGroup (0x3) - End of group marker
  • ObjectStatus.EndOfTrack (0x4) - End of track marker
extensionHeaders
KeyValuePair[] | null
Optional extension headers (e.g., capture timestamp, audio level). null if none.
payload
Uint8Array | null
Raw object data bytes. null for status-only objects.

Convenience Getters

get groupId(): bigint        // Alias for location.group
get objectId(): bigint       // Alias for location.object

Factory Methods

newWithPayload()

Creates an object with payload data.
static newWithPayload(
  fullTrackName: FullTrackName,
  location: Location,
  publisherPriority: number,
  objectForwardingPreference: ObjectForwardingPreference,
  subgroupId: bigint | number | null,
  extensionHeaders: KeyValuePair[] | null,
  payload: Uint8Array
): MoqtObject
fullTrackName
FullTrackName
required
Track identifier
location
Location
required
Object position (group, object)
publisherPriority
number
required
Priority (0-255)
objectForwardingPreference
ObjectForwardingPreference
required
Delivery mechanism
subgroupId
bigint | number | null
required
Subgroup ID (required for Subgroup preference, null for Datagram)
extensionHeaders
KeyValuePair[] | null
required
Optional extension headers
payload
Uint8Array
required
Object data
const videoFrame = MoqtObject.newWithPayload(
  FullTrackName.tryNew('video/main', 'h264'),
  new Location(42n, 0n), // Group 42, Object 0
  0, // Highest priority
  ObjectForwardingPreference.Subgroup,
  0n, // Subgroup 0
  null, // No extensions
  frameBytes
);

newWithStatus()

Creates a status-only object (no payload).
static newWithStatus(
  fullTrackName: FullTrackName,
  location: Location,
  publisherPriority: number,
  objectForwardingPreference: ObjectForwardingPreference,
  subgroupId: bigint | number | null,
  extensionHeaders: KeyValuePair[] | null,
  objectStatus: ObjectStatus
): MoqtObject
objectStatus
ObjectStatus
required
Status code (cannot be Normal)
const endOfGroup = MoqtObject.newWithStatus(
  fullTrackName,
  new Location(42n, 99n), // Last object in group 42
  0,
  ObjectForwardingPreference.Subgroup,
  0n,
  null,
  ObjectStatus.EndOfGroup
);

Conversion Methods

From Wire Formats

fromDatagramObject()

Converts a DatagramObject (received from datagrams) to MoqtObject.
static fromDatagramObject(
  datagramObject: DatagramObject,
  fullTrackName: FullTrackName
): MoqtObject
const datagramObj = DatagramObject.deserialize(buffer);
const moqtObj = MoqtObject.fromDatagramObject(datagramObj, fullTrackName);

fromDatagramStatus()

Converts a DatagramStatus to MoqtObject.
static fromDatagramStatus(
  datagramStatus: DatagramStatus,
  fullTrackName: FullTrackName
): MoqtObject
const status = DatagramStatus.deserialize(buffer);
const moqtObj = MoqtObject.fromDatagramStatus(status, fullTrackName);

fromFetchObject()

Converts a FetchObject (from fetch streams) to MoqtObject.
static fromFetchObject(
  fetchObject: FetchObject,
  fullTrackName: FullTrackName
): MoqtObject
const fetchObj = FetchObject.deserialize(buffer);
const moqtObj = MoqtObject.fromFetchObject(fetchObj, fullTrackName);

fromSubgroupObject()

Converts a SubgroupObject (from subgroup streams) to MoqtObject.
static fromSubgroupObject(
  subgroupObject: SubgroupObject,
  groupId: bigint | number,
  publisherPriority: number,
  subgroupId: bigint | number,
  fullTrackName: FullTrackName
): MoqtObject
const subgroupObj = SubgroupObject.deserialize(buffer);
const moqtObj = MoqtObject.fromSubgroupObject(
  subgroupObj,
  100n, // groupId
  0,    // priority
  0n,   // subgroupId
  fullTrackName
);

To Wire Formats

tryIntoDatagramObject()

Converts to DatagramObject for transmission.
tryIntoDatagramObject(
  trackAlias: bigint | number,
  endOfGroup: boolean = false
): DatagramObject
trackAlias
bigint | number
required
Track alias to use in wire format
endOfGroup
boolean
Whether this is the last object in the group (Draft-14)
Throws:
  • CastingError - If forwarding preference is not Datagram
  • ProtocolViolationError - If object status is not Normal or payload is missing
const datagramObj = moqtObj.tryIntoDatagramObject(trackAlias, false);
const bytes = datagramObj.serialize().toUint8Array();
await datagramWriter.write(bytes);

tryIntoDatagramStatus()

Converts to DatagramStatus for transmission.
tryIntoDatagramStatus(trackAlias: bigint | number): DatagramStatus
Throws:
  • CastingError - If forwarding preference is not Datagram
  • ProtocolViolationError - If object status is Normal
const datagramStatus = moqtObj.tryIntoDatagramStatus(trackAlias);
const bytes = datagramStatus.serialize().toUint8Array();
await datagramWriter.write(bytes);

tryIntoFetchObject()

Converts to FetchObject for fetch responses.
tryIntoFetchObject(): FetchObject
Throws:
  • CastingError - If forwarding preference is not Subgroup
  • ProtocolViolationError - If subgroupId is null
const fetchObj = moqtObj.tryIntoFetchObject();
const bytes = fetchObj.serialize().toUint8Array();
await stream.write(bytes);

tryIntoSubgroupObject()

Converts to SubgroupObject for subgroup streams.
tryIntoSubgroupObject(): SubgroupObject
Throws:
  • CastingError - If forwarding preference is not Subgroup
const subgroupObj = moqtObj.tryIntoSubgroupObject();
const bytes = subgroupObj.serialize().toUint8Array();
await stream.write(bytes);

Utility Methods

Type Checks

isDatagram(): boolean       // True if forwarding preference is Datagram
isSubgroup(): boolean       // True if forwarding preference is Subgroup
isEndOfGroup(): boolean     // True if status is EndOfGroup
isEndOfTrack(): boolean     // True if status is EndOfTrack
doesNotExist(): boolean     // True if status is DoesNotExist
hasPayload(): boolean       // True if payload is not null
hasStatus(): boolean        // True if status is not Normal
if (obj.isDatagram()) {
  // Handle datagram object
  await sendViaDatagram(obj);
} else if (obj.isSubgroup()) {
  // Handle subgroup object
  await sendViaStream(obj);
}

Special Methods

getSubgroupHeaderType()

Determines the appropriate subgroup header type based on object properties.
getSubgroupHeaderType(containsEnd: boolean): SubgroupHeaderType
containsEnd
boolean
required
Whether this object contains end-of-group or end-of-track status
return
SubgroupHeaderType
Appropriate header type (0x10-0x1D)

isDatagramEndOfGroup() (Static)

Checks if a DatagramObject has the end-of-group flag set (Draft-14).
static isDatagramEndOfGroup(datagramObject: DatagramObject): boolean
This is separate from ObjectStatus.EndOfGroup - the flag indicates this is the last object in the group even with Normal status.

Location Class

The Location class represents a position within a track.

Constructor

const location = new Location(
  group: bigint | number,
  object: bigint | number
)
group
bigint | number
required
Group index (e.g., segment, GOP, logical group)
object
bigint | number
required
Object index within the group (e.g., frame, chunk)

Properties

readonly group: bigint    // Group index
readonly object: bigint   // Object index

Methods

equals()

Checks equality with another location.
equals(other: Location): boolean
if (loc1.equals(loc2)) {
  console.log('Same location');
}

compare()

Compares locations for ordering.
compare(other: Location): number
return
number
-1 if this < other, 1 if this > other, 0 if equal
if (loc1.compare(loc2) < 0) {
  console.log('loc1 comes before loc2');
}

serialize() / deserialize()

serialize(): FrozenByteBuffer
static deserialize(buf: BaseByteBuffer): Location

Usage Examples

Creating Objects

const obj = MoqtObject.newWithPayload(
  FullTrackName.tryNew('video/main', 'h264'),
  new Location(100n, 0n),
  0,
  ObjectForwardingPreference.Subgroup,
  0n,
  null,
  videoFrameBytes
);

Processing Objects from Streams

const result = await client.subscribe({
  fullTrackName,
  filterType: FilterType.LatestObject,
  forward: true,
  groupOrder: GroupOrder.Original,
  priority: 0
});

if (!(result instanceof SubscribeError)) {
  for await (const obj of result.stream) {
    console.log(`Object: group=${obj.groupId}, object=${obj.objectId}`);
    
    if (obj.hasPayload()) {
      // Process payload
      await processFrame(obj.payload);
    }
    
    if (obj.isEndOfGroup()) {
      console.log('End of group marker received');
      await finalizeGroup(obj.groupId);
    }
    
    if (obj.isEndOfTrack()) {
      console.log('Track ended');
      break;
    }
  }
}

Sending Objects

const obj = MoqtObject.newWithPayload(
  fullTrackName,
  location,
  0,
  ObjectForwardingPreference.Subgroup,
  0n,
  null,
  payload
);

const subgroupObj = obj.tryIntoSubgroupObject();
const bytes = subgroupObj.serialize().toUint8Array();
await streamWriter.write(bytes);

Best Practices

Location Ordering: Objects within a group should have sequential object IDs starting from 0:
for (let i = 0; i < framesInGroup; i++) {
  const obj = MoqtObject.newWithPayload(
    fullTrackName,
    new Location(groupId, i),
    // ...
  );
}
Status vs Payload: Objects cannot have both status (other than Normal) and payload. Use separate objects for status markers:
// Last payload object
const lastObj = MoqtObject.newWithPayload(/* ... */, payload);

// End of group marker (separate)
const endMarker = MoqtObject.newWithStatus(/* ... */, ObjectStatus.EndOfGroup);
Datagram Constraints: Datagram objects should be small (typically < 1200 bytes) to avoid fragmentation:
if (payload.length > 1200) {
  // Use subgroup forwarding instead
  objectForwardingPreference = ObjectForwardingPreference.Subgroup;
}

See Also