Skip to content

moq_media

From the caprid-moq-media package: import moq_media

Pure LOC/MSF format helpers; transport belongs to the application.

The one encoder, moq_media.opus, needs the opus extra and is not imported here.

def annexb_to_avcc(data: bytes, *, drop_parameter_sets: bool = True) -> bytes

Re-frame an Annex B access unit as 4-byte-length-prefixed NAL units.

avc1 promises parameter sets out of band, so SPS/PPS (and access-unit delimiters) are dropped by default; they travel in the avcC instead.

Source

def avc_codec_string(avcc: bytes) -> str

The avc1.PPCCLL WebCodecs codec string an avcC declares (RFC 6381 §3.3).

Source

def build_avcc(sps: Sequence[bytes], pps: Sequence[bytes]) -> bytes

Build an AVCDecoderConfigurationRecord (avcC) with 4-byte NAL length prefixes.

Source

def build_interrupt(
*,
until_us: int,
from_us: int | None = None,
track: str = AUDIO_TRACK,
) -> bytes

An interrupt object’s payload: compact JSON, {"track":…,"fromUs":…,"untilUs":…}, fromUs only if given.

Raises ValueError on an empty track, a timestamp that is not a nonnegative safe integer, or from_us not before until_us.

Source

def build_media_timeline(entries: Iterable[MediaTimelineEntry]) -> bytes

Return a timeline object’s payload: the records in the order given, as compact JSON.

The same form serves an independent document (every retained record) and an incremental one (only new ones).

Source

def build_msf_catalog(
namespace: Sequence[str],
*,
video: VideoTrackInfo | None = None,
audio: AudioTrackInfo | None = None,
media: Sequence[VideoTrackInfo | AudioTrackInfo] = (),
data: Sequence[DataTrackInfo] = (),
media_timeline: MediaTimelineTrackInfo | None = None,
generated_at_ms: int | None = None,
) -> bytes

The independent MSF catalog JSON for a live LOC broadcast, byte-compatible with the Video.js parser.

The catalog leaves isComplete out: msf-01 §5.1.3 forbids it while false, and once present it can never be removed. End a broadcast with build_msf_end_catalog.

video and audio are shorthand for one-entry media lists, listed first. media lists further video and audio tracks in order: simulcast layers sharing an alt_group, or several sources in their own render groups. Every media entry carries its render group (default 1); the builder sets no target latency or buffer, which §5.2.8 and §5.2.9 require to be identical across a render group.

Source

def build_msf_end_catalog(*, generated_at_ms: int | None = None) -> bytes

The catalog that ends a broadcast (msf-01 §11.3): isComplete: true and no tracks.

It commits that no track will be added and no content published, so send it only for a broadcast that ends on purpose, once every media track has ended (closing a track sends PUBLISH_DONE Track Ended), and never on a crash or lost connection.

Source

def build_transcript_segment(
*,
seq: int,
from_us: int,
text: str,
until_us: int | None = None,
final: bool = False,
track: str = AUDIO_TRACK,
) -> bytes

A transcript object’s payload: compact JSON, {"seq":…,"track":…,"fromUs":…,"untilUs":…,"text":…,"final":…}.

untilUs only if given. Raises ValueError on a number that is not a nonnegative safe integer, an empty track, text that is not valid Unicode, until_us not after from_us, or a final segment without until_us.

Source

def compose_player_url(
relay_url: str,
namespace: Sequence[str],
*,
token: str | None = None,
track_name: str = CATALOG_TRACK,
) -> str

Compose the moqt:// MSF source URL a Video.js MoQ player takes, the inverse of its parser.

The relay origin may be written as https:// or moqt://; an existing path and query survive. The token, when given, rides the c4m fragment parameter, which the player moves onto the connect URL’s jwt query parameter.

Source

def encode_name_component(value: str) -> str

MSF namespace/name string form: [a-zA-Z0-9_] literal, every other UTF-8 byte as .xx lowercase hex.

Source

def encode_namespace_name(namespace: Sequence[str], track_name: str) -> str

The ns1-ns2--name identifier that follows #msf: in a source URL (msf-01 §11.1.2).

Source

def extract_parameter_sets(data: bytes) -> tuple[list[bytes], list[bytes]]

SPS and PPS NAL units found in an Annex B byte stream (an encoder’s extradata or a keyframe).

Source

def find_replacement_track(
current: MsfCatalogTrack,
tracks: Sequence[MsfCatalogTrack],
) -> MsfCatalogTrack | None

Find the track in a newer catalog that replaces current, a track of an older one.

A publisher that replaces a track lists a new name in its place (msf-01 §5.3: a changed track is a new Namespace|Name tuple), as a voice agent does to interrupt its own reply. While tracks still lists current’s namespace and name the answer is None. Otherwise it is the first track listed with current’s namespace, role and render group, or None when there is none (the track was removed, not replaced).

Source

def group_msf_tracks(tracks: Sequence[MsfCatalogTrack]) -> tuple[MsfTrackGroup, ...]

Group catalog tracks into the sets a viewer picks one track from, in order of each set’s first track.

Tracks sharing a render group and an alternate group form one set, and every other track is a set of its own. A viewer plays one track from each set of a render group, and moves between alternates with want(..., until=...).

Source

def iter_annexb_nal_units(data: bytes) -> Iterator[bytes]

Split an Annex B byte stream (3- or 4-byte start codes) into NAL units without their start codes.

Source

def loc_properties(
timestamp_us: int,
*,
timescale: int = MICROSECONDS_PER_SECOND,
video_config: bytes | None = None,
audio_config: bytes | None = None,
) -> list[KeyValuePair]

Package a microsecond timestamp; pass decoder configuration only on keyframes.

Other timescales round to the nearest tick, with ties rounded upward.

Source

def loc_timestamp_us(
properties: Iterable[KeyValuePair],
*,
track_properties: Iterable[KeyValuePair] = (),
) -> int | None

Return an object’s LOC Timestamp in microseconds, or None when it has no usable one.

The Timestamp is scaled by the first Timescale that is a positive safe integer: the object’s, then the track’s (track_properties, as SUBSCRIBE_OK carries them). The MSF catalog’s timescale is not consulted: MSF never ties it to the LOC Timestamp. With none, the Timestamp already is wall-clock microseconds since the Unix epoch (LOC §2.3.1.1). Ties round upward; a result past 2^53 - 1 is None.

Source

def loc_track_properties(timescale: int = MICROSECONDS_PER_SECOND) -> list[KeyValuePair]

Declare timestamp units on a LOC track; returns fresh properties on every call.

Source

def media_timeline_entry(
timestamp_us: int,
group: int,
*,
object: int = 0,
wallclock_us: int | None = None,
) -> MediaTimelineEntry

Return the record for an object whose LOC timestamp on the broadcast timeline is timestamp_us.

wallclock_us is when that media was captured, as Unix-epoch microseconds. It defaults to timestamp_us, since the broadcast timeline is anchored at the epoch; pass 0 for unknown, as msf-01 allows.

Source

def nal_unit_type(nal: bytes) -> int

The nal_unit_type of a NAL unit without its start code: 7 for SPS, 8 for PPS, 5 for IDR.

Source

def opus_packet_duration_us(packet: bytes) -> int | None

An Opus packet’s duration in microseconds from its TOC byte (RFC 6716 §3.1), or None if truncated.

Code 0 holds one frame, codes 1 and 2 two, and code 3 the count in the next byte’s low six bits.

Source

def parse_interrupt(payload: bytes) -> Interrupt

Read an interrupt object’s payload.

Raises ValueError on a payload that is not a UTF-8 JSON object with a non-empty string track and a nonnegative safe-integer untilUs, or whose fromUs, when present, is not one before untilUs. Other fields are ignored.

Source

def parse_media_timeline(payload: bytes) -> tuple[MediaTimelineEntry, ...]

Read a timeline object’s payload into its records, in document order.

Raises ValueError on a payload that is not a UTF-8 JSON array. Records that do not read as a nonnegative safe-integer [number, [number, number], number] are skipped, a §7.4 template among them; extra items are ignored. MSF_COMPRESSION payloads are not decompressed.

Source

def parse_msf_catalog(payload: bytes, *, catalog_namespace: Sequence[str]) -> MsfCatalog

Read an independent MSF catalog object’s payload into its track descriptions.

catalog_namespace is the namespace of the catalog track itself, which tracks that declare none inherit (§5.2.2). Raises ValueError on a payload that is not a UTF-8 JSON object, a missing or unsupported version, a missing tracks array, or a delta update (deltaUpdate, not supported). Everything else is lenient, as msf-01 requires: unknown fields and fields of the wrong type are ignored, track entries without a string name are skipped, and packaging is returned as declared, not interpreted.

Source

def parse_transcript_segment(payload: bytes) -> TranscriptSegment

Read a transcript object’s payload.

Raises ValueError on a payload that is not a UTF-8 JSON object with a nonnegative safe-integer seq and fromUs, a non-empty string track, a string text and a boolean final, or whose untilUs, when present, is not one after fromUs, or that is final without untilUs. Other fields are ignored.

Source

class AudioTrackInfo

The audio track build_msf_catalog describes. Fields left as None are omitted.

Source

Attributes

  • name: str

  • codec: str

  • samplerate: int — Opus always declares 48000, the rate it decodes at, whatever is given here.

  • channel_config: str

  • bitrate: int | None

  • init_data: bytes | None — Decoder configuration, emitted inline as initDataList.

  • render_group: int — Render group (msf-01 §5.2.11): tracks sharing one play together on one timeline.

    Give a second source, such as a screen share and its audio, its own.

  • alt_group: int | None — Alternate group (msf-01 §5.2.12): alternate versions of the same content, such as simulcast layers.

    A viewer subscribes to one member. Members share a role and a render group.

class BroadcastClock

A publisher’s single clock: every track in the broadcast is stamped from it, in Unix-epoch microseconds.

now_us is the monotonic time source in microseconds, time.monotonic_ns() // 1000 by default. origin_us is a moment on that source in integer microseconds; it defaults to the source’s time now, rounded to whole microseconds. origin_epoch_us is that moment as Unix-epoch microseconds; it defaults to time.time_ns() at creation less the source time elapsed since the origin, read once. A time t on the source maps to origin_epoch_us + t - origin_us, so the timeline advances at the source’s rate.

Source

Attributes

  • origin_us: int (property) — The origin, on the source clock.
  • origin_epoch_us: int (property) — The origin as microseconds since the Unix epoch.
def now_us(self) -> int

Return the timeline now: microseconds since the Unix epoch.

def from_source_us(self, source_us: int) -> int

Map a timestamp on this clock’s own source to Unix-epoch microseconds, rounded to whole microseconds.

For a capture clock with another origin, use source_timeline.

def source_timeline(
self,
*,
tolerance_us: int = 5000,
capture_latency_us: int = 0,
) -> SourceTimeline

Map a clock with its own origin and rate, kept on the broadcast timeline by calibration.

An AudioContext-style clock, or capture timestamps from another origin. tolerance_us is how far a calibration may disagree with the current anchor before it replaces it. capture_latency_us is the capture device’s input delay, subtracted from every timestamp; no helper knows it, so the application supplies it and sets it again when the device changes.

def sample_timeline(
self,
sample_rate: int,
*,
first_sample_us: int | None = None,
) -> SampleTimeline

Anchor a sample counter at first_sample_us on the timeline (default: now).

The device clock that drives the counter drifts against the source, so re-anchor with a fresh timeline when the two disagree by more than a frame.

class DataTrackInfo

A non-media track build_msf_catalog lists by name and role only.

Source

Attributes

  • name: str
  • role: str | None — Must not be a media role (video, audio, caption and the like).
class FrameSequencer

One track’s frame sequencer. Feed it the subscription’s events, then poll() for frames.

clock is the broadcast’s playout clock: it holds the target latency and is where lateness is measured. grouping is "keyframe" (a keyframe opens each group and later objects depend on it, as video) or "frame" (every group is independently decodable, as audio). track_properties are SUBSCRIBE_OK’s, which may declare the Timescale.

Source

Attributes

  • track_properties: Sequence[KeyValuePair] — The track properties used to read timestamps; set from each SUBSCRIBE_OK.
  • stats
def object(self, obj: MoqtObject) -> None

An object arrived.

def group_ended(self, group_id: int) -> None

A group’s stream ended cleanly: no further objects of it will come.

def group_reset(self, group_id: int) -> None

A group’s stream was reset: its remaining objects will not come.

def restart(self) -> None

The subscription was replaced (a Restart or a Move): forget everything and reset the clock; group IDs start over.

def poll(self, max_frames: int | None = None) -> SequencerPoll

Take the frames that are ready, at most max_frames (default all), and when to poll again.

A reader that cannot take frames as they come polls one at a time, so each is judged late when it is taken.

class FrameSequencerStats

Counters, cumulative across restarts.

Source

Attributes

  • delivered: int — Frames returned by poll().
  • late: int — Frames discarded: too late, or behind what was already delivered.
  • skipped_groups: int — Groups abandoned or passed over without being delivered whole.
  • resyncs: int — Resyncs: deliveries after nothing arrived within the target latency.
  • untimed: int — Objects without a LOC timestamp, which cannot be sequenced.
class H264Config

An avc1 decoder record and the codec string derived from it.

Source

Attributes

  • avcc: bytes
  • codec: str (property) — The avc1.PPCCLL codec string the record declares.
def from_annexb(cls, data: bytes) -> H264Config

Build the record from the SPS and PPS in Annex B bytes (an encoder’s extradata or a keyframe).

Raises ValueError as build_avcc does.

def to_avcc(self, data: bytes) -> bytes

Re-frame an Annex B access unit for this configuration, dropping in-band SPS/PPS and AUDs.

class Interrupt

One interrupt: drop the named audio track’s audio in a timeline range, in microseconds.

Source

Attributes

  • track: str — The audio track in the same namespace whose audio to drop.

  • until_us: int — Drop before this timestamp: the end of the last audio the talker sent.

    Frames that arrive later inside the range are dropped too, so the talker’s next audio must start at or after it.

  • from_us: int | None — Drop from this timestamp on; None drops from the oldest audio held.

class MediaTimeline

The retained entries of one broadcast’s media timeline, and the independent document they make.

max_entries bounds the document: past it, the oldest entry is dropped. The default 512 is about 18 KB, 17 minutes of two-second GOPs. A supervised publisher’s next generation is a new broadcast and starts a new timeline.

Source

Attributes

  • entries: tuple[MediaTimelineEntry, ...] (property) — The retained entries, oldest first.
  • document: bytes (property) — The independent document of the retained entries; [] before the first.
def add(
self,
timestamp_us: int,
group: int,
*,
object: int = 0,
wallclock_us: int | None = None,
) -> bytes

Record the object at group and object whose LOC timestamp is timestamp_us; return the document.

Call it once per group of the indexed track, for its first object, when that object was sent. wallclock_us is as for media_timeline_entry: the timestamp itself by default. A rejected argument raises ValueError and leaves the timeline unchanged.

class MediaTimelineEntry

One media timeline record, [media_time_ms, [group, object], wallclock_ms] on the wire (msf-01 §7.1.1).

Source

Attributes

  • media_time_ms: int — Media time of the first sample in the referenced object, floored to whole milliseconds.
  • group: int
  • object: int — The referenced object’s location in the track the timeline indexes.
  • wallclock_ms: int — Milliseconds since the Unix epoch when that media was captured; 0 when unknown.
class MediaTimelineTrackInfo

The Media Timeline track (msf-01 §7) build_msf_catalog announces.

The entry is listed only while a track it depends on is listed; see spec/media-layer.md.

Source

Attributes

  • name: str

  • depends: Sequence[str] | None — The video and audio tracks the timeline applies to (msf-01 §7.2); its locations point into the first.

    Default: the first video track followed by the first audio track, whichever the catalog has.

class MsfCatalog

An independent MSF catalog (msf-01 §5.1), as parse_msf_catalog reads it.

Source

Attributes

  • version: str
  • tracks: tuple[MsfCatalogTrack, ...]
  • generated_at_ms: int | None
  • is_complete: bool — True only when the catalog declares the broadcast complete (§5.1.3).
class MsfCatalogTrack

One track object of an independent MSF catalog (msf-01 §5.2), as parse_msf_catalog reads it.

Source

Attributes

  • namespace: tuple[str, ...] — The track’s own slash-joined namespace split into fields, else the catalog track’s.
  • name: str
  • packaging: str — Payload encapsulation as declared (loc, or e.g. moq-rs cmaf/legacy); empty when absent.
  • is_live: bool — False when absent.
  • role: str | None
  • codec: str | None
  • width: int | None
  • height: int | None
  • framerate: float | None
  • samplerate: int | None
  • channel_config: str | None
  • bitrate: int | None
  • render_group: int | None — Render group (§5.2.11): tracks sharing one are meant to play together.
  • alt_group: int | None — Alternate group (§5.2.12): tracks sharing one are alternate versions of one content.
  • mimetype: str | None — MIME type (§5.2.19), e.g. application/json on a media timeline track.
  • depends: tuple[str, ...] | None — Names of the tracks this one depends on (§5.2.14), its string items only.
  • init_data: bytes | None — Decoder init data, resolved from initRef through the catalog’s inline initDataList.
class MsfTrackGroup

A set of catalog tracks a viewer picks one of.

The members of one alternate group (§5.2.12) within one render group, or a single track that names no alternate group.

Source

Attributes

  • tracks: tuple[MsfCatalogTrack, ...] — The members, in catalog order.
  • render_group: int | None
  • alt_group: int | None — None for a group holding exactly one track that names no alternate group.
class PlayoutClock

A player’s clock for one broadcast’s timeline. Audio is the master; video asks it when each frame is due.

late_drop_us (default 40 ms, EBU R37’s audio-early limit) is how late a frame may be shown; max_video_delay_us (default 1 s) is how far a frame may lead before the clock re-syncs; audio_timeout_us (default 500 ms) is how long audio may stay silent before wall-clock pacing takes over. target_latency_us is how far behind the position a frame may still be delivered for decoding, and how late a frame must be before wall pacing re-anchors on it; by default twice the longest of the last four keyframe intervals reported, or 2 s before any is. now_us is the time source, time.monotonic_ns() // 1000 by default.

Source

Attributes

  • mode: PlayoutMode (property) — idle before anything anchors it, audio while audio reports arrive, wall otherwise.
  • late_drop_us: int (property) — How late a frame may be shown, in microseconds: the late_drop_us option.
  • target_latency_us: float (property) — The target latency now: the option, or twice the longest of the last four keyframe intervals reported.
  • resets: int (property) — How many times reset() has been called: a frame reader sees from it that the timeline changed.
def report_audio(self, timestamp_us: int, *, at_us: int | None = None) -> None

Report that the audio with this timeline timestamp is audible at local time at_us (default: now).

That is what was handed to the output, less the jitter-buffer depth, the output latency, and any extra path.

def stop_audio(self) -> None

Audio is muted or ended: pace by wall clock from the current position.

def due(self, timestamp_us: int) -> PlayoutDecision

Decide whether the frame with this timeline timestamp should wait, be shown now, or be dropped.

def position_us(self) -> float | None

Return the timeline position now, or None while idle.

def report_keyframe_interval(self, interval_us: float) -> None

Report the spacing between two consecutive keyframes on the timeline; a frame reader does this.

def reset(self) -> None

Forget every anchor, at a Restart, a Move, a resync, or a new catalog: the next frame anchors wall pacing.

The keyframe intervals reported so far are kept.

def local_now_us(self) -> float

The clock’s local time source now, in microseconds: what a frame reader measures its waits in.

class PlayoutDecision

What to do with one video frame.

offset_us is the frame’s timestamp minus the clock’s position (positive: early). wait_us is how long to hold the frame before asking again, and is 0 unless action is "wait".

Source

Attributes

  • action: PlayoutAction
  • offset_us: int
  • wait_us: int
class SampleTimeline

Maps an audio sample counter that starts at zero onto the broadcast timeline.

Source

Attributes

  • sample_rate: int
  • first_sample_us: int
def timestamp_us(self, sample_index: int) -> int

Return the broadcast time of the sample at this index: whole microseconds after the first sample.

class SequencedFrame

One frame in decode order.

Source

Attributes

  • group_id: int
  • object_id: int
  • timestamp_us: int — The LOC timestamp in microseconds on the broadcast timeline.
  • key: bool — Whether the frame starts its group: a keyframe under keyframe grouping, every frame under frame grouping.
  • payload: bytes
  • properties: list[KeyValuePair]
  • discontinuity: FrameDiscontinuity | None — Set on the first frame after a skip, a resync, or a restart.
class SequencerPoll

What FrameSequencer.poll returns.

Source

Attributes

  • frames: list[SequencedFrame] — The frames ready now, in decode order.
  • wait_us: int | None — Poll again after this many microseconds, when a wait can end; 0 when more is ready now (past max_frames, or a resync that takes a poll of its own); None when only new objects can change it.
class SourceTimeline

Maps timestamps from a clock with its own origin and rate onto the broadcast timeline.

Calibrate it with measured pairs of source time and time on the broadcast clock’s own source; without a calibration, the first timestamp mapped is anchored at the clock’s now_us(). capture_latency_us is subtracted from every timestamp.

Source

Attributes

  • capture_latency_us: int (property) — The capture device’s input delay in integer microseconds, subtracted from every timestamp.

    Set it again when the input device changes; it applies from the next timestamp and never to calibration.

  • anchor_source_us: float | None (property) — The source time of the current anchor; None until the first calibration or timestamp.

def calibrate(self, source_us: int, *, at_us: int | None = None) -> bool

Record that source time source_us happened at at_us on the clock’s own source (default: now).

The pair becomes the anchor when there is none, or when the current anchor predicts it more than the tolerance off: the source drifted, or jumped. Returns whether the anchor changed.

def timestamp_us(self, source_us: int) -> int

Return the broadcast time of this source timestamp, rounded to whole microseconds, less the capture latency.

Without an anchor, the first call anchors this timestamp at the clock’s now_us().

class Transcript

What a listener has read of one audio track’s transcript: each segment’s latest version, less what was cut.

apply each segment read for the track and cut on each interrupt for it; lines_at gives what to show as the audio plays. A segment’s final version is kept against later ones. Cuts are remembered, so a version that arrives after one is clipped as if it had arrived before. A segment is known by its seq within one run of the talker’s track, so use a new Transcript when the talker starts over.

Source

Attributes

  • lines: list[TranscriptLine] (property) — Every segment held, in timeline order.
def apply(self, segment: TranscriptSegment) -> bool

Keep a segment’s version, clipped by the cuts so far; False if it changed nothing.

Ignored: a version of a segment the talker already sent final, a segment that starts inside a range cut earlier (as audio arriving there late is), and an interim version of a segment a cut ended. A cut segment takes the talker’s final version, clipped: one whose audio ended before the cut is no longer cut.

def cut(
self,
*,
until_us: int,
from_us: int | None = None,
position_us: float | None = None,
) -> None

Apply an interrupt’s range, with the playout position now (PlayoutClock.position_us).

Audio before the position has been heard, so the cut starts at the later of from_us and the position. It drops the segments that start in the cut, and ends the one playing there at its start, final and cut. Raises ValueError on a range an interrupt could not have, or a negative or non-finite position.

def lines_at(self, position_us: float | None) -> list[TranscriptLine]

The segments whose audio has started playing at this position, in timeline order; none while idle.

class TranscriptLine

A segment as a Transcript holds it: its latest version, and whether an interrupt cut it short.

Source

Attributes

  • seq: int
  • track: str
  • from_us: int
  • until_us: int | None
  • text: str
  • final: bool
  • cut: bool — An interrupt cut the segment’s audio short at until_us: the listener heard only the start of the text.
class TranscriptSegment

One version of a transcript segment: the text of the named audio track’s audio from from_us on.

Source

Attributes

  • seq: int — The segment’s number; a later version of the same segment repeats it.
  • track: str — The audio track in the same namespace whose audio this is the text of.
  • from_us: int — Where the segment’s audio starts, in microseconds on the broadcast timeline.
  • until_us: int | None — Where it ends; None while the talker does not know yet. A final segment has it.
  • text: str — The text, which a later version replaces whole.
  • final: bool — No later version follows.
class VideoTrackInfo

The video track build_msf_catalog describes.

An avc1 or avc3 track needs init_data: without it the track is left out of the catalog, and with it the codec string’s profile and level come from the avcC. Fields left as None are omitted from the catalog.

Source

Attributes

  • name: str

  • codec: str — WebCodecs registry codec string, e.g. avc1.42E01F.

  • width: int | None

  • height: int | None

  • framerate: float | None

  • bitrate: int | None

  • init_data: bytes | None — Decoder configuration (avcC for avc1), emitted inline as initDataList.

  • render_group: int — Render group (msf-01 §5.2.11): tracks sharing one play together on one timeline.

    Give a second source, such as a screen share and its audio, its own.

  • alt_group: int | None — Alternate group (msf-01 §5.2.12): alternate versions of the same content, such as simulcast layers.

    A viewer subscribes to one member. Members share a role and a render group.

AUDIO_ONLY_TARGET_LATENCY_US = 500000

The target latency for a broadcast with no video: pass it as target_latency_us, since the 2 s default waits for keyframe intervals an audio-only track never reports. It covers a player’s 400 ms jitter-buffer ceiling plus a wired output delay, and a frame sequencer resyncs after half a second of nothing on time instead of two.

Source

AUDIO_TRACK = 'audio'

Source

CATALOG_TRACK = 'catalog'

Source

INTERRUPT_TRACK = 'interrupt'

The interrupt track’s default name, listed in the catalog as a data track.

Source

LOC_AUDIO_CONFIG = 15

Source

LOC_DOCUMENT = 'draft-ietf-moq-loc-04'

Source

LOC_TIMESCALE = 8

Source

LOC_TIMESTAMP = 16

Source

LOC_VIDEO_CONFIG = 13

Source

MEDIA_TIMELINE_TRACK = 'timeline'

Source

MICROSECONDS_PER_SECOND = 1000000

Source

MSF_CATALOG_VERSION = 'draft-01'

Source

MSF_DOCUMENT = 'draft-ietf-moq-msf-01'

Source

OPUS_FRAME_US = 20000

The frame length moq_media.opus.OpusEncoder emits, and the LOC mapping’s one frame per group.

Source

OPUS_SAMPLE_RATE = 48000

The rate every Opus stream decodes at (RFC 7845 §5.1), whatever rate the encoder was fed.

Source

TRACK_TIMESCALE_PROPERTIES = tuple(loc_track_properties())

Track properties declared on every media track: timestamps are microseconds.

Source

TRANSCRIPT_TRACK = 'transcript'

The transcript track’s default name, listed in the catalog as a data track.

Source

VIDEO_TRACK = 'video'

Source

FrameDiscontinuity = Literal['gap', 'resync', 'restart']

Why a frame is not the one decoded after the frame before it: gap (frames before it were skipped: missing, reset, or too late), resync (nothing arrived within the target latency for one target latency; the sequencer reset the clock), restart (the subscription was replaced: a want’s Restart or Move). A decoder resets there.

Source

PlayoutAction = Literal['wait', 'show', 'drop']

What a video renderer does with one frame.

Source

PlayoutMode = Literal['idle', 'audio', 'wall']

What a playout clock is paced by.

Source