Documentation
¶
Overview ¶
Package moq is the ergonomic Go API for Media over QUIC: real-time pub/sub with built-in caching, fan-out, and prioritization.
It wraps the raw UniFFI bindings in moq.dev/moq-ffi with idiomatic Go: context.Context cancellation, Go error returns, and Go 1.23 range-over-func iterators (iter.Seq2) for live streams. The raw record, enum, and small object types are re-exported here without the Moq prefix (see types.go), so most programs never need to import the ffi package directly.
A typical full-duplex client wires a single origin as both publish source and consume sink; Dial does this automatically when no origin is supplied. See the package README for a runnable example.
Cancellation ¶
Every call that can block takes a context.Context, and cancelling it (or hitting its deadline) returns ctx.Err() promptly and tears the in-flight native work down with it. Nothing is left running in the background, so a per-call deadline is a real bound on resource use. When a call finishes at the very moment its context expires, either may win: the caller gets the result or it gets ctx.Err(). What is guaranteed is that the losing side costs nothing, so a result the caller never sees is disposed of rather than left live with no owner.
What a cancel tears down depends on the call. A one-shot call (a subscribe, a fetch, RequestBroadcast, Resolve, a producer's Used/Unused, Server.Accept) aborts on its own and leaves the object it was made on usable, so the same broadcast, producer, or server takes the next call. A stream read (any Next, RecvGroup, ReadFrame, or the iterators over them) instead cancels the stream it reads, which is what a range loop over a cancelled context wants: the consumer is finished, not merely this read. Cancel a stream read only when you are done with the stream; to bound one read, cancel the whole consumer's context.
Index ¶
- Constants
- Variables
- func IsAuthError(err error) bool
- func IsShutdown(err error) bool
- func LogLevel(level string) error
- func ProtocolError(err error) (ffi.MoqProtocolError, bool)
- type AnnounceConsumer
- type AnnounceOptions
- type AnnounceUpdate
- type AnnouncedBroadcast
- type Audio
- type AudioCodec
- type AudioConsumer
- type AudioDecoderOutput
- type AudioEncoderInput
- type AudioEncoderOutput
- type AudioFormat
- type AudioFrame
- type AudioOption
- type AudioProducer
- func (a *AudioProducer) Demand() (*TrackDemand, error)
- func (a *AudioProducer) Finish() error
- func (a *AudioProducer) Name() (string, error)
- func (a *AudioProducer) Reservation() *Reservation
- func (a *AudioProducer) ResetEpoch() error
- func (a *AudioProducer) Unused(ctx context.Context) error
- func (a *AudioProducer) Used(ctx context.Context) error
- func (a *AudioProducer) Write(frame AudioFrame) error
- type AudioSampleFormat
- type Backoff
- type Bandwidth
- type BroadcastConsumer
- func (b *BroadcastConsumer) Catalog(ctx context.Context) (*Catalog, error)
- func (b *BroadcastConsumer) DecodeAudio(ctx context.Context, name string, catalogAudio Audio, ...) (*AudioConsumer, error)
- func (b *BroadcastConsumer) DecodeVideo(ctx context.Context, name string, catalogVideo Video, ...) (*VideoConsumer, error)
- func (b *BroadcastConsumer) FetchGroup(ctx context.Context, name string, sequence uint64, options *FetchGroupOptions) (*GroupConsumer, error)
- func (b *BroadcastConsumer) FetchMediaGroup(ctx context.Context, name string, sequence uint64, container Container, ...) (*MediaGroupConsumer, error)
- func (b *BroadcastConsumer) Resolve(ctx context.Context, reference *string) (*BroadcastConsumer, error)
- func (b *BroadcastConsumer) SubscribeCatalog(ctx context.Context) (*CatalogConsumer, error)
- func (b *BroadcastConsumer) SubscribeJSONSnapshot(ctx context.Context, name string, options JSONSubscribeOptions) (*JSONSnapshotConsumer, error)
- func (b *BroadcastConsumer) SubscribeJSONStream(ctx context.Context, name string, options JSONSubscribeOptions) (*JSONStreamConsumer, error)
- func (b *BroadcastConsumer) SubscribeMedia(ctx context.Context, name string, container Container, ...) (*MediaConsumer, error)
- func (b *BroadcastConsumer) SubscribeTrack(ctx context.Context, name string, subscription *Subscription) (*TrackConsumer, error)
- type BroadcastDynamic
- type BroadcastProducer
- func (b *BroadcastProducer) Announce(route Route) error
- func (b *BroadcastProducer) Close() error
- func (b *BroadcastProducer) Consume() (*BroadcastConsumer, error)
- func (b *BroadcastProducer) Dynamic() (*BroadcastDynamic, error)
- func (b *BroadcastProducer) EncodeAudio(name string, input AudioEncoderInput, output AudioEncoderOutput, ...) (*AudioProducer, error)
- func (b *BroadcastProducer) EncodeVideo(input VideoEncoderInput, output VideoEncoderOutput, bandwidth *Bandwidth) (*VideoProducer, error)
- func (b *BroadcastProducer) Finish() errordeprecated
- func (b *BroadcastProducer) PublishAudio(format AudioFormat, init []byte, opts ...AudioOption) (*MediaProducer, error)
- func (b *BroadcastProducer) PublishAudioOnTrack(request *TrackRequest, format AudioFormat, init []byte, opts ...AudioOption) (*MediaProducer, error)
- func (b *BroadcastProducer) PublishContainer(format ContainerFormat, init []byte) (*ContainerProducer, error)
- func (b *BroadcastProducer) PublishContainerStream(format ContainerFormat) (*ContainerStreamProducer, error)
- func (b *BroadcastProducer) PublishJSONSnapshot(name string, options JSONSnapshotOptions) (*JSONSnapshotProducer, error)
- func (b *BroadcastProducer) PublishJSONStream(name string, options JSONStreamOptions) (*JSONStreamProducer, error)
- func (b *BroadcastProducer) PublishTrack(name string, info *TrackInfo) (*TrackProducer, error)
- func (b *BroadcastProducer) PublishVideo(format VideoFormat, init []byte, opts ...VideoOption) (*MediaProducer, error)
- func (b *BroadcastProducer) PublishVideoOnTrack(request *TrackRequest, format VideoFormat, init []byte, opts ...VideoOption) (*MediaProducer, error)
- func (b *BroadcastProducer) PublishVideoStream(format VideoFormat, opts ...VideoOption) (*MediaStreamProducer, error)
- func (b *BroadcastProducer) RemoveCatalogSection(name string) error
- func (b *BroadcastProducer) SetCatalogSection(name string, json string) error
- func (b *BroadcastProducer) SetVideoProperties(properties VideoProperties) error
- func (b *BroadcastProducer) Unannounce() error
- type BroadcastRequest
- type Catalog
- type CatalogConsumer
- type Client
- func (c *Client) Announced(options AnnounceOptions) (*AnnounceConsumer, error)
- func (c *Client) AnnouncedBroadcast(path string) (*AnnouncedBroadcast, error)
- func (c *Client) Close() error
- func (c *Client) CreateBroadcast(path string) (*BroadcastProducer, error)
- func (c *Client) RequestBroadcast(ctx context.Context, path string) (*BroadcastConsumer, error)
- func (c *Client) Session() *Session
- type ClientOption
- func WithBackoff(backoff Backoff) ClientOption
- func WithBind(addr string) ClientOption
- func WithClientTLSCert(path string) ClientOption
- func WithClientTLSKey(path string) ClientOption
- func WithPublishOrigin(o *OriginProducer) ClientOption
- func WithQUICMaxStreams(maxStreams uint64) ClientOption
- func WithReconnect(enabled bool) ClientOption
- func WithSubscribeOrigin(o *OriginProducer) ClientOption
- func WithTLSFingerprints(fingerprints ...string) ClientOption
- func WithTLSRoots(paths ...string) ClientOption
- func WithTLSSystemRoots(systemRoots bool) ClientOption
- func WithTLSVerify(verify bool) ClientOption
- func WithWebSocketDelay(delay time.Duration) ClientOption
- func WithWebSocketEnabled(enabled bool) ClientOption
- type ConnectionStats
- type ConnectionStatus
- type Container
- type ContainerCmaf
- type ContainerFormat
- type ContainerLegacy
- type ContainerLoc
- type ContainerProducer
- type ContainerStreamProducer
- type Datagram
- type Dimensions
- type Error
- type ErrorScope
- type FetchGroupOptions
- type Frame
- type GroupConsumer
- type GroupProducer
- type GroupRequest
- type JSONSnapshotConsumer
- type JSONSnapshotOptions
- type JSONSnapshotProducer
- type JSONStreamConsumer
- type JSONStreamOptions
- type JSONStreamProducer
- type JSONSubscribeOptions
- type MediaConsumer
- type MediaFrame
- type MediaGroupConsumer
- type MediaProducer
- func (m *MediaProducer) Cut() error
- func (m *MediaProducer) Demand() (*TrackDemand, error)
- func (m *MediaProducer) Discontinuity() error
- func (m *MediaProducer) Finish() error
- func (m *MediaProducer) Flush(timestampUs uint64) error
- func (m *MediaProducer) Name() (string, error)
- func (m *MediaProducer) Seek(sequence uint64) error
- func (m *MediaProducer) Unused(ctx context.Context) error
- func (m *MediaProducer) Used(ctx context.Context) error
- func (m *MediaProducer) WriteFrame(frame Frame) error
- type MediaStreamProducer
- type OriginConfig
- type OriginConsumer
- type OriginDynamic
- type OriginProducer
- type ProtocolKind
- type Request
- func (r *Request) Accept(ctx context.Context) (*Session, error)
- func (r *Request) Cancel()
- func (r *Request) Path() string
- func (r *Request) Query() *string
- func (r *Request) Reject(ctx context.Context, code uint16) error
- func (r *Request) SetConsume(o *OriginProducer) error
- func (r *Request) SetPublish(o *OriginProducer) error
- func (r *Request) Transport() Transport
- func (r *Request) URL() *string
- type Reservation
- type Route
- type Server
- func (s *Server) Accept(ctx context.Context) (*Request, error)
- func (s *Server) CertFingerprints() ([]string, error)
- func (s *Server) Close() error
- func (s *Server) CreateBroadcast(path string) (*BroadcastProducer, error)
- func (s *Server) LocalAddr() string
- func (s *Server) Requests(ctx context.Context) iter.Seq2[*Request, error]
- func (s *Server) Serve(ctx context.Context) error
- type ServerOption
- type Session
- func (s *Session) Bandwidth() *Bandwidth
- func (s *Session) Cancel(code uint32)
- func (s *Session) Closed(ctx context.Context) error
- func (s *Session) Consume() *OriginConsumer
- func (s *Session) Epoch() uint64
- func (s *Session) Publish() *OriginProducer
- func (s *Session) Shutdown()
- func (s *Session) Stats() ConnectionStats
- func (s *Session) Status(ctx context.Context) (ConnectionStatus, error)
- type Subscription
- type TrackConsumer
- func (t *TrackConsumer) Cancel()
- func (t *TrackConsumer) Datagrams(ctx context.Context) iter.Seq2[*Datagram, error]
- func (t *TrackConsumer) Groups(ctx context.Context) iter.Seq2[*GroupConsumer, error]
- func (t *TrackConsumer) GroupsAsArrived(ctx context.Context) iter.Seq2[*GroupConsumer, error]
- func (t *TrackConsumer) Info() (TrackInfo, error)
- func (t *TrackConsumer) NextGroup(ctx context.Context) (*GroupConsumer, error)
- func (t *TrackConsumer) ReadFrame(ctx context.Context) (*Frame, error)
- func (t *TrackConsumer) RecvDatagram(ctx context.Context) (*Datagram, error)
- func (t *TrackConsumer) RecvGroup(ctx context.Context) (*GroupConsumer, error)
- func (t *TrackConsumer) Update(subscription Subscription)
- type TrackDemand
- type TrackDynamic
- type TrackInfo
- type TrackProducer
- func (t *TrackProducer) Abort(errorCode uint16) error
- func (t *TrackProducer) AppendDatagram(frame Frame) (uint64, error)
- func (t *TrackProducer) AppendGroup() (*GroupProducer, error)
- func (t *TrackProducer) Consume(subscription *Subscription) (*TrackConsumer, error)
- func (t *TrackProducer) CreateGroup(sequence uint64) (*GroupProducer, error)
- func (t *TrackProducer) Demand() (*TrackDemand, error)
- func (t *TrackProducer) Dynamic() (*TrackDynamic, error)
- func (t *TrackProducer) Finish() error
- func (t *TrackProducer) FinishAt(finalSequence uint64) error
- func (t *TrackProducer) Name() (string, error)
- func (t *TrackProducer) Unused(ctx context.Context) error
- func (t *TrackProducer) Used(ctx context.Context) error
- func (t *TrackProducer) WriteFrame(frame Frame) error
- type TrackRequest
- type Transport
- type Video
- type VideoCodec
- type VideoConsumer
- type VideoDecodedFrame
- type VideoDecoderOutput
- type VideoEncoderInput
- type VideoEncoderKind
- type VideoEncoderKindAuto
- type VideoEncoderKindHardware
- type VideoEncoderKindNamed
- type VideoEncoderKindSoftware
- type VideoEncoderOutput
- type VideoFormat
- type VideoFrame
- type VideoHint
- type VideoOption
- type VideoPixelFormat
- type VideoProducer
- func (v *VideoProducer) Cut() error
- func (v *VideoProducer) Demand() (*TrackDemand, error)
- func (v *VideoProducer) Finish() error
- func (v *VideoProducer) Name() (string, error)
- func (v *VideoProducer) Reservation() *Reservation
- func (v *VideoProducer) SetBitrate(bitrate uint64) error
- func (v *VideoProducer) Unused(ctx context.Context) error
- func (v *VideoProducer) Used(ctx context.Context) error
- func (v *VideoProducer) Write(frame VideoFrame) error
- type VideoProperties
Examples ¶
Constants ¶
const ( // TransportQUIC is a session that arrived over native QUIC. TransportQUIC = ffi.MoqTransportQuic // TransportIroh is a session that arrived over an Iroh peer-to-peer connection. TransportIroh = ffi.MoqTransportIroh // TransportWebSocket is a session that arrived over the WebSocket fallback transport. TransportWebSocket = ffi.MoqTransportWebSocket // TransportTCP is a session that arrived over a plaintext TCP connection. TransportTCP = ffi.MoqTransportTcp // TransportUnix is a session that arrived over a Unix domain socket. TransportUnix = ffi.MoqTransportUnix )
const ( // AudioFormatAac is Advanced Audio Coding, configured by an AudioSpecificConfig. AudioFormatAac = ffi.MoqAudioFormatAac // AudioFormatOpus is Opus, configured by an OpusHead. AudioFormatOpus = ffi.MoqAudioFormatOpus // AudioFormatFlac is FLAC, configured by its STREAMINFO block. AudioFormatFlac = ffi.MoqAudioFormatFlac // AudioFormatMp3 is MPEG-1/2 Audio Layer III. AudioFormatMp3 = ffi.MoqAudioFormatMp3 )
AudioFormat values: a single audio codec an importer can parse.
const ( // VideoFormatAvc1 is H.264 with length-prefixed NALUs and an out-of-band avcC. VideoFormatAvc1 = ffi.MoqVideoFormatAvc1 // VideoFormatAvc3 is H.264 in Annex-B with inline SPS/PPS. VideoFormatAvc3 = ffi.MoqVideoFormatAvc3 // VideoFormatHvc1 is H.265 with length-prefixed NALUs and an out-of-band hvcC. VideoFormatHvc1 = ffi.MoqVideoFormatHvc1 // VideoFormatHev1 is H.265 in Annex-B with inline parameter sets. VideoFormatHev1 = ffi.MoqVideoFormatHev1 // VideoFormatAv01 is AV1. VideoFormatAv01 = ffi.MoqVideoFormatAv01 // VideoFormatVp8 is VP8. VideoFormatVp8 = ffi.MoqVideoFormatVp8 // VideoFormatVp9 is VP9. VideoFormatVp9 = ffi.MoqVideoFormatVp9 )
VideoFormat values: a single video codec an importer can parse. The two H.26x pairs differ by framing, not codec: Avc1/Hvc1 are length-prefixed with an out-of-band config record, Avc3/Hev1 are Annex-B with the parameter sets inline.
const ( // ContainerFormatFmp4 is fragmented MP4 / CMAF. ContainerFormatFmp4 = ffi.MoqContainerFormatFmp4 // ContainerFormatMkv is Matroska / WebM. ContainerFormatMkv = ffi.MoqContainerFormatMkv // ContainerFormatTs is an MPEG-2 transport stream. ContainerFormatTs = ffi.MoqContainerFormatTs // ContainerFormatFlv is Flash Video, as used by RTMP. ContainerFormatFlv = ffi.MoqContainerFormatFlv )
ContainerFormat values: a container that publishes its own tracks.
const ( // AudioSampleFormatU8 is unsigned 8-bit interleaved PCM. AudioSampleFormatU8 = ffi.MoqAudioSampleFormatU8 // AudioSampleFormatS16 is signed 16-bit interleaved PCM. AudioSampleFormatS16 = ffi.MoqAudioSampleFormatS16 // AudioSampleFormatS32 is signed 32-bit interleaved PCM. AudioSampleFormatS32 = ffi.MoqAudioSampleFormatS32 // AudioSampleFormatF32 is 32-bit float interleaved PCM. AudioSampleFormatF32 = ffi.MoqAudioSampleFormatF32 // AudioSampleFormatU8Planar is unsigned 8-bit planar PCM, one buffer per channel. AudioSampleFormatU8Planar = ffi.MoqAudioSampleFormatU8Planar // AudioSampleFormatS16Planar is signed 16-bit planar PCM, one buffer per channel. AudioSampleFormatS16Planar = ffi.MoqAudioSampleFormatS16Planar // AudioSampleFormatS32Planar is signed 32-bit planar PCM, one buffer per channel. AudioSampleFormatS32Planar = ffi.MoqAudioSampleFormatS32Planar // AudioSampleFormatF32Planar is 32-bit float planar PCM, one buffer per channel. AudioSampleFormatF32Planar = ffi.MoqAudioSampleFormatF32Planar )
AudioSampleFormat values: the raw PCM sample layout fed to or returned from the in-process Opus codec.
const ( // VideoPixelFormatI420 is tightly-packed planar I420: Y, then U, then V. VideoPixelFormatI420 = ffi.MoqVideoPixelFormatI420 // VideoPixelFormatRgba is tightly-packed RGBA, four bytes per pixel. VideoPixelFormatRgba = ffi.MoqVideoPixelFormatRgba )
VideoPixelFormat values: the raw pixel layout fed to the in-process encoder, and the one the in-process decoder delivers.
const ( // VideoCodecH264 publishes H.264 / AVC as an avc3 track. VideoCodecH264 = ffi.MoqVideoCodecH264 // VideoCodecH265 publishes H.265 / HEVC as a hev1 track. Hardware only, so it // fails where no hardware encoder is available. VideoCodecH265 = ffi.MoqVideoCodecH265 )
VideoCodec values: the codec a published video track is encoded to.
const ( // StatusConnected means a session connected (the first connect, or a reconnect after a drop). StatusConnected = ffi.MoqConnectionStatusConnected // StatusDisconnected means the session dropped; a reconnect attempt follows. StatusDisconnected = ffi.MoqConnectionStatusDisconnected // StatusMigrating means the peer sent a GOAWAY; the replacement is being dialed while the old session keeps serving. StatusMigrating = ffi.MoqConnectionStatusMigrating )
ConnectionStatus values: the lifecycle of a client session's connection.
const ( // ErrorScopeSession identifies a session close code. ErrorScopeSession = ffi.MoqErrorScopeSession // ErrorScopeStream identifies a stream reset code. ErrorScopeStream = ffi.MoqErrorScopeStream // ProtocolKindCancel identifies cancel. ProtocolKindCancel = ffi.MoqProtocolKindCancel // ProtocolKindInternal identifies internal. ProtocolKindInternal = ffi.MoqProtocolKindInternal ProtocolKindUnauthorized = ffi.MoqProtocolKindUnauthorized // ProtocolKindProtocolViolation identifies protocol violation. ProtocolKindProtocolViolation = ffi.MoqProtocolKindProtocolViolation // ProtocolKindKeyValueFormatting identifies key value formatting. ProtocolKindKeyValueFormatting = ffi.MoqProtocolKindKeyValueFormatting // ProtocolKindGoawayTimeout identifies goaway timeout. ProtocolKindGoawayTimeout = ffi.MoqProtocolKindGoawayTimeout // ProtocolKindTimeout identifies timeout. ProtocolKindTimeout = ffi.MoqProtocolKindTimeout // ProtocolKindVersion identifies version. ProtocolKindVersion = ffi.MoqProtocolKindVersion // ProtocolKindDeliveryTimeout identifies delivery timeout. ProtocolKindDeliveryTimeout = ffi.MoqProtocolKindDeliveryTimeout // ProtocolKindSessionClosed identifies session closed. ProtocolKindSessionClosed = ffi.MoqProtocolKindSessionClosed // ProtocolKindGoingAway identifies going away. ProtocolKindGoingAway = ffi.MoqProtocolKindGoingAway // ProtocolKindTooFarBehind identifies too far behind. ProtocolKindTooFarBehind = ffi.MoqProtocolKindTooFarBehind // ProtocolKindMalformedTrack identifies malformed track. ProtocolKindMalformedTrack = ffi.MoqProtocolKindMalformedTrack // ProtocolKindNotFound identifies not found. ProtocolKindNotFound = ffi.MoqProtocolKindNotFound // ProtocolKindUnroutable identifies unroutable. ProtocolKindUnroutable = ffi.MoqProtocolKindUnroutable // ProtocolKindOld identifies old. ProtocolKindOld = ffi.MoqProtocolKindOld // ProtocolKindEvicted identifies evicted. ProtocolKindEvicted = ffi.MoqProtocolKindEvicted // ProtocolKindWrongSize identifies wrong size. ProtocolKindWrongSize = ffi.MoqProtocolKindWrongSize // ProtocolKindFrameTooLarge identifies frame too large. ProtocolKindFrameTooLarge = ffi.MoqProtocolKindFrameTooLarge // ProtocolKindTimestampMismatch identifies timestamp mismatch. ProtocolKindTimestampMismatch = ffi.MoqProtocolKindTimestampMismatch // ProtocolKindApp identifies app. ProtocolKindApp = ffi.MoqProtocolKindApp // ProtocolKindUnknown identifies unknown. ProtocolKindUnknown = ffi.MoqProtocolKindUnknown )
Protocol registries and recognized kinds carried by ProtocolError.
const DefaultDeltaRatio uint32 = 8
DefaultDeltaRatio is used when JSONSnapshotOptions.DeltaRatio is nil. Go has no field defaults, so unlike the other bindings this restates the `#[uniffi(default = 8)]` on moq-ffi's MoqJsonSnapshotConfig (itself pinned to moq-json's default by a Rust test).
const RetryForever time.Duration = -1
RetryForever, passed as Backoff.Timeout, keeps a reconnecting session retrying indefinitely instead of giving up.
Variables ¶
var ( // ErrProtocol matches a session or stream protocol error; inspect ProtocolError for the code. ErrProtocol = ffi.ErrMoqErrorProtocol // ErrTransport matches a QUIC/WebTransport connection failure, not a protocol code. ErrTransport = ffi.ErrMoqErrorTransport // ErrInternal matches a local failure without a protocol code. ErrInternal = ffi.ErrMoqErrorInternal // ErrMedia matches a media error from the hang layer, such as a malformed catalog or container. ErrMedia = ffi.ErrMoqErrorMedia // ErrMux matches a muxing or demuxing failure from moq-mux. ErrMux = ffi.ErrMoqErrorMux // ErrJSONTrack matches a JSON track encoding or decoding failure. ErrJSONTrack = ffi.ErrMoqErrorJsonTrack // ErrAudio matches a raw-audio encode or decode failure. ErrAudio = ffi.ErrMoqErrorAudio // ErrVideo matches a raw-video encode or decode failure. ErrVideo = ffi.ErrMoqErrorVideo // ErrURL matches a malformed URL passed when connecting or publishing. ErrURL = ffi.ErrMoqErrorUrl // ErrTimeOverflow matches a timestamp that overflowed its timescale. ErrTimeOverflow = ffi.ErrMoqErrorTimeOverflow // ErrLogLevel matches an unparseable log level string passed to LogLevel. ErrLogLevel = ffi.ErrMoqErrorLogLevel // ErrTask matches a panic or cancellation in a background native task. ErrTask = ffi.ErrMoqErrorTask // ErrJSON matches malformed JSON passed through the FFI API. ErrJSON = ffi.ErrMoqErrorJson // ErrCancelled is returned when an operation is cancelled, e.g. via a cancelled context; IsShutdown treats it as a graceful stop. ErrCancelled = ffi.ErrMoqErrorCancelled // ErrClosed is returned when the session or stream has closed; IsShutdown treats it as a graceful stop. ErrClosed = ffi.ErrMoqErrorClosed // ErrBusy is returned when a configuration setter races an in-flight connect, listen, or accept. ErrBusy = ffi.ErrMoqErrorBusy // ErrConnect is returned when establishing a client session fails. ErrConnect = ffi.ErrMoqErrorConnect // ErrBind is returned when the server fails to bind its listening address. ErrBind = ffi.ErrMoqErrorBind // ErrReject is returned when a session is refused during the handshake. ErrReject = ffi.ErrMoqErrorReject // ErrAlreadyResponded is returned when a Request is accepted or rejected more than once. ErrAlreadyResponded = ffi.ErrMoqErrorAlreadyResponded // ErrCodec is returned when codec configuration or bitstream parsing fails. ErrCodec = ffi.ErrMoqErrorCodec ErrUnauthorized = ffi.ErrMoqErrorUnauthorized // ErrForbidden is returned when the relay rejects the session with HTTP 403. ErrForbidden = ffi.ErrMoqErrorForbidden // ErrNotFound is returned when the requested track or group is not available. ErrNotFound = ffi.ErrMoqErrorNotFound // ErrUnsupported is returned when the requested operation is not supported by this build or peer, however it is asked for. ErrUnsupported = ffi.ErrMoqErrorUnsupported // ErrAlreadyCommitted is returned when a track already reading in one group order is asked for the other; subscribe again for a second cursor. ErrAlreadyCommitted = ffi.ErrMoqErrorAlreadyCommitted // ErrInvalidRoute is returned when a route has an invalid hop ID or too many hops. ErrInvalidRoute = ffi.ErrMoqErrorInvalidRoute // ErrInvalidPattern is returned when a path pattern is empty, has a doubled slash, or uses a reserved segment form. ErrInvalidPattern = ffi.ErrMoqErrorInvalidPattern // ErrUnresolvableBroadcast is returned when a referenced sibling broadcast cannot be resolved without an origin. ErrUnresolvableBroadcast = ffi.ErrMoqErrorUnresolvableBroadcast // ErrLog is returned when installing or configuring the native log subscriber fails. ErrLog = ffi.ErrMoqErrorLog )
Error sentinels re-exported from the ffi layer without the MoqError prefix, so callers can errors.Is against them without importing moq.dev/moq-ffi directly. These mirror the variants of the native error enum; transparent variants (Protocol, Media, ...) wrap a lower-level error whose detail survives in the message.
var ( // ErrNoPublishOrigin is returned when a publish operation is attempted but the server has no publish origin configured. ErrNoPublishOrigin = errors.New("moq: no publish origin configured") )
Configuration errors returned by the wrapper itself (not the FFI layer).
Functions ¶
func IsAuthError ¶
IsAuthError reports whether err is an authentication/authorization failure (HTTP 401/403, or a protocol Unauthorized session close).
func IsShutdown ¶
IsShutdown reports whether err is the expected result of a graceful shutdown (Cancelled or Closed) rather than an actual failure. It's the value to check when a stream ends because its consumer was cancelled or the session closed.
func ProtocolError ¶
func ProtocolError(err error) (ffi.MoqProtocolError, bool)
ProtocolError reports the structured protocol failure, if err is one.
The record carries the peer's session or stream scope, the verbatim wire code, a known kind when recognized, and a diagnostic message.
Types ¶
type AnnounceConsumer ¶
type AnnounceConsumer struct {
// contains filtered or unexported fields
}
AnnounceConsumer is a stream of route announcements and retractions.
func (*AnnounceConsumer) All ¶
func (a *AnnounceConsumer) All(ctx context.Context) iter.Seq2[*AnnounceUpdate, error]
All ranges over announcements until the stream ends or the loop breaks.
func (*AnnounceConsumer) Cancel ¶
func (a *AnnounceConsumer) Cancel()
Cancel stops the announcement stream.
func (*AnnounceConsumer) Next ¶
func (a *AnnounceConsumer) Next(ctx context.Context) (*AnnounceUpdate, error)
Next returns the next announcement, or (nil, nil) when the stream ends.
type AnnounceOptions ¶
type AnnounceOptions struct {
// Prefix is a literal path root beneath the origin.
Prefix string
// Filter is a pattern relative to Prefix. Nil matches every path beneath it.
Filter *string
// Hidden also lists paths with a segment starting with "." below Prefix.
Hidden bool
}
AnnounceOptions scopes an announcement stream.
type AnnounceUpdate ¶
type AnnounceUpdate struct {
// contains filtered or unexported fields
}
AnnounceUpdate is a route announcement or retraction. A route claims that Prefix and every path beneath it can be served; it carries no broadcast. Resolve a specific path with OriginConsumer.RequestBroadcast. By convention a publisher announces each broadcast's exact path.
func (*AnnounceUpdate) Active ¶
func (a *AnnounceUpdate) Active() bool
Active reports whether the route is active (true) or was retracted (false). A repeated active announcement for the same prefix is a metadata update.
func (*AnnounceUpdate) Captures ¶
func (a *AnnounceUpdate) Captures() []string
Captures reports what each filter wildcard matched. Nil means the route only overlaps the scope without pinning every wildcard.
func (*AnnounceUpdate) Prefix ¶
func (a *AnnounceUpdate) Prefix() string
Prefix is the covered prefix, relative to the origin.
func (*AnnounceUpdate) Route ¶
func (a *AnnounceUpdate) Route() Route
Route is the route serving the prefix: its relay hops and costs (warm Cost, undiscounted Cold).
type AnnouncedBroadcast ¶
type AnnouncedBroadcast struct {
// contains filtered or unexported fields
}
AnnouncedBroadcast awaits a specific broadcast becoming available.
func (*AnnouncedBroadcast) Available ¶
func (a *AnnouncedBroadcast) Available(ctx context.Context) (*BroadcastConsumer, error)
Available blocks until the broadcast is available and returns its consumer.
func (*AnnouncedBroadcast) Cancel ¶
func (a *AnnouncedBroadcast) Cancel()
Cancel stops awaiting the broadcast.
type Audio ¶
Audio describes one audio rendition in a broadcast catalog: codec, sample rate, channel count, and container.
type AudioCodec ¶
type AudioCodec = ffi.MoqAudioCodec
AudioCodec selects the audio encoder codec. Build one with OpusAudioCodec or AacAudioCodec; adding a codec later adds a constructor, not a breaking enum change.
func AacAudioCodec ¶ added in v0.7.9
func AacAudioCodec() *AudioCodec
AacAudioCodec selects AAC-LC through the platform's encoder for EncodeAudio. A host without one refuses it. Leave FrameDurationUs at 0 for AAC's own frame.
func OpusAudioCodec ¶
func OpusAudioCodec() *AudioCodec
OpusAudioCodec selects Opus (RFC 6716) for EncodeAudio.
type AudioConsumer ¶
type AudioConsumer struct {
// contains filtered or unexported fields
}
AudioConsumer is a stream of decoded audio frames.
func (*AudioConsumer) Frames ¶
func (a *AudioConsumer) Frames(ctx context.Context) iter.Seq2[*AudioFrame, error]
Frames ranges over audio frames until the track ends or the loop breaks.
func (*AudioConsumer) Next ¶
func (a *AudioConsumer) Next(ctx context.Context) (*AudioFrame, error)
Next returns the next audio frame, or (nil, nil) when the track ends.
type AudioDecoderOutput ¶
type AudioDecoderOutput = ffi.MoqAudioDecoderOutput
AudioDecoderOutput configures the PCM format, sample rate, and channels DecodeAudio delivers.
type AudioEncoderInput ¶
type AudioEncoderInput = ffi.MoqAudioEncoderInput
AudioEncoderInput declares the PCM sample format, sample rate, and channel count of frames written to an audio producer.
type AudioEncoderOutput ¶
type AudioEncoderOutput = ffi.MoqAudioEncoderOutput
AudioEncoderOutput configures the encoder: codec, optional sample rate, channels, bitrate, and frame duration.
type AudioFormat ¶
type AudioFormat = ffi.MoqAudioFormat
AudioFormat is a single audio codec an importer can parse.
type AudioFrame ¶
type AudioFrame = ffi.MoqAudioFrame
AudioFrame is one audio frame: PCM payload plus a presentation timestamp in microseconds.
type AudioOption ¶
type AudioOption func(*ffi.MoqAudioInit)
AudioOption configures an audio publish.
func WithAudioLabel ¶
func WithAudioLabel(label string) AudioOption
WithAudioLabel sets the human-readable rendition name stored in the catalog.
func WithAudioTrack ¶ added in v0.7.3
func WithAudioTrack(track string) AudioOption
WithAudioTrack names the track instead of deriving a unique name from the format. A requested track already has a name, so the OnTrack variant refuses it.
type AudioProducer ¶
type AudioProducer struct {
// contains filtered or unexported fields
}
AudioProducer pushes raw PCM and lets libopus encode it on the way out.
func (*AudioProducer) Demand ¶
func (a *AudioProducer) Demand() (*TrackDemand, error)
Demand returns a watch-only handle to whether the audio track has subscribers.
func (*AudioProducer) Finish ¶
func (a *AudioProducer) Finish() error
Finish flushes pending samples and finalizes the track.
func (*AudioProducer) Name ¶
func (a *AudioProducer) Name() (string, error)
Name returns the audio track's name.
func (*AudioProducer) Reservation ¶
func (a *AudioProducer) Reservation() *Reservation
Reservation returns this encoder's bandwidth reservation, or nil if it was published without an allocator.
func (*AudioProducer) ResetEpoch ¶
func (a *AudioProducer) ResetEpoch() error
ResetEpoch re-anchors the timeline to the next frame after an idle gap.
func (*AudioProducer) Unused ¶
func (a *AudioProducer) Unused(ctx context.Context) error
Unused blocks until the audio track has no active subscribers. Prefer Demand.
func (*AudioProducer) Used ¶
func (a *AudioProducer) Used(ctx context.Context) error
Used blocks until the audio track has at least one active subscriber. Prefer Demand.
func (*AudioProducer) Write ¶
func (a *AudioProducer) Write(frame AudioFrame) error
Write pushes one frame of PCM in the configured input format.
type AudioSampleFormat ¶
type AudioSampleFormat = ffi.MoqAudioSampleFormat
AudioSampleFormat is a raw PCM sample layout, mirroring WebCodecs AudioData.format.
type Backoff ¶
type Backoff struct {
Initial time.Duration // delay before the first retry (default 1s)
Multiplier uint32 // applied to the delay after each failure (default 2)
Max time.Duration // ceiling on the delay (default 5s)
Timeout time.Duration // give up after this long (default 10s)
}
Backoff is the retry pacing for automatic reconnects: the delay starts at Initial, multiplies by Multiplier after each failed attempt, and caps at Max. After Timeout of consecutive failures the connection gives up for good.
Every field is optional: the zero value means the default beside it, so a partial Backoff overrides only what it sets. Pass RetryForever as Timeout to keep retrying indefinitely.
type Bandwidth ¶
type Bandwidth struct {
// contains filtered or unexported fields
}
Bandwidth divides one connection's send estimate among the tracks sharing it.
func (*Bandwidth) Reserve ¶
func (b *Bandwidth) Reserve(track *TrackProducer, maxBps uint64) (*Reservation, error)
Reserve claims up to maxBps for track. maxBps is a ceiling, not a measurement: reserve the most the track can ever send. Drop the reservation to hand the room back.
type BroadcastConsumer ¶
type BroadcastConsumer struct {
// contains filtered or unexported fields
}
BroadcastConsumer reads tracks from a broadcast.
func (*BroadcastConsumer) Catalog ¶
func (b *BroadcastConsumer) Catalog(ctx context.Context) (*Catalog, error)
Catalog subscribes and returns the first catalog. It reports ErrClosed if the catalog track ends before any catalog arrives.
func (*BroadcastConsumer) DecodeAudio ¶
func (b *BroadcastConsumer) DecodeAudio( ctx context.Context, name string, catalogAudio Audio, output AudioDecoderOutput, ) (*AudioConsumer, error)
DecodeAudio subscribes to a raw-audio track; samples come back in the format declared by output. catalogAudio comes from the catalog.
func (*BroadcastConsumer) DecodeVideo ¶
func (b *BroadcastConsumer) DecodeVideo( ctx context.Context, name string, catalogVideo Video, output VideoDecoderOutput, ) (*VideoConsumer, error)
DecodeVideo subscribes to a video track and decodes it inside the bindings. catalogVideo comes from the catalog. output.Format picks the packed CPU layout every frame arrives in, defaulting to I420 when nil; each frame repeats it. output.Resize is best effort, so read each frame's own dimensions.
func (*BroadcastConsumer) FetchGroup ¶
func (b *BroadcastConsumer) FetchGroup( ctx context.Context, name string, sequence uint64, options *FetchGroupOptions, ) (*GroupConsumer, error)
FetchGroup fetches one complete group by track name and group sequence without holding a live subscription.
func (*BroadcastConsumer) FetchMediaGroup ¶
func (b *BroadcastConsumer) FetchMediaGroup( ctx context.Context, name string, sequence uint64, container Container, options *FetchGroupOptions, ) (*MediaGroupConsumer, error)
FetchMediaGroup fetches one group by sequence and decodes it with the given container. Unlike SubscribeMedia this holds no live subscription and applies no latency-based group skipping, so every frame in the group is delivered.
func (*BroadcastConsumer) Resolve ¶
func (b *BroadcastConsumer) Resolve(ctx context.Context, reference *string) (*BroadcastConsumer, error)
Resolve returns the broadcast serving a catalog rendition, honoring its broadcast reference: Video.Broadcast / Audio.Broadcast. A nil or empty reference names this broadcast, anything else names a sibling relative to it (e.g. "./source"). Call it on a rendition that carries one before SubscribeMedia, SubscribeTrack, FetchGroup, or FetchMediaGroup, which take a track name rather than a rendition; DecodeAudio and DecodeVideo resolve it themselves.
Errors if this broadcast came from a local producer rather than an origin, since a standalone broadcast has no sibling to name.
func (*BroadcastConsumer) SubscribeCatalog ¶
func (b *BroadcastConsumer) SubscribeCatalog(ctx context.Context) (*CatalogConsumer, error)
SubscribeCatalog subscribes to the broadcast's catalog track.
func (*BroadcastConsumer) SubscribeJSONSnapshot ¶
func (b *BroadcastConsumer) SubscribeJSONSnapshot( ctx context.Context, name string, options JSONSubscribeOptions, ) (*JSONSnapshotConsumer, error)
SubscribeJSONSnapshot subscribes to a lossy latest-value JSON track.
func (*BroadcastConsumer) SubscribeJSONStream ¶
func (b *BroadcastConsumer) SubscribeJSONStream( ctx context.Context, name string, options JSONSubscribeOptions, ) (*JSONStreamConsumer, error)
SubscribeJSONStream subscribes to a lossless append-log JSON track.
func (*BroadcastConsumer) SubscribeMedia ¶
func (b *BroadcastConsumer) SubscribeMedia( ctx context.Context, name string, container Container, subscription *Subscription, ) (*MediaConsumer, error)
SubscribeMedia subscribes to a media track, decoded with the given container. subscription tunes delivery priority, group range, and the max age; pass nil for defaults. Raise Subscription.MaxAgeUs to buffer instead of skipping a stalled group.
func (*BroadcastConsumer) SubscribeTrack ¶
func (b *BroadcastConsumer) SubscribeTrack( ctx context.Context, name string, subscription *Subscription, ) (*TrackConsumer, error)
SubscribeTrack subscribes to a track, receiving arbitrary byte payloads. subscription tunes delivery priority, group range, and staleness; pass nil for defaults.
type BroadcastDynamic ¶
type BroadcastDynamic struct {
// contains filtered or unexported fields
}
BroadcastDynamic is a stream of subscriber-requested tracks.
func (*BroadcastDynamic) Cancel ¶
func (d *BroadcastDynamic) Cancel()
Cancel stops the dynamic request stream.
func (*BroadcastDynamic) RequestedTrack ¶
func (d *BroadcastDynamic) RequestedTrack(ctx context.Context) (*TrackRequest, error)
RequestedTrack waits for the next subscriber-requested track.
func (*BroadcastDynamic) Requests ¶
func (d *BroadcastDynamic) Requests(ctx context.Context) iter.Seq2[*TrackRequest, error]
Requests ranges over subscriber-requested tracks until the dynamic source ends.
type BroadcastProducer ¶
type BroadcastProducer struct {
// contains filtered or unexported fields
}
BroadcastProducer publishes a collection of tracks. Create one at a path with OriginProducer.CreateBroadcast (or Client.CreateBroadcast), then publish tracks onto it.
func NewBroadcastProducer ¶
func NewBroadcastProducer() (*BroadcastProducer, error)
NewBroadcastProducer creates a standalone broadcast, not attached to any origin: use it to serve a dynamic request (BroadcastRequest.Accept) or for local pub/sub. To publish at a path, use OriginProducer.CreateBroadcast.
func (*BroadcastProducer) Announce ¶
func (b *BroadcastProducer) Announce(route Route) error
Announce advertises this broadcast's exact path as a route.
Announcing again re-prices the route in place. Until announced, the broadcast is invisible and unroutable for local consumers and peers alike.
func (*BroadcastProducer) Close ¶ added in v0.7.6
func (b *BroadcastProducer) Close() error
Close ends the broadcast for good: it retracts and serves no new tracks. Tracks already subscribed carry on to their own end. Closing again is a no-op.
func (*BroadcastProducer) Consume ¶
func (b *BroadcastProducer) Consume() (*BroadcastConsumer, error)
Consume returns a consumer that reads from this broadcast's tracks.
func (*BroadcastProducer) Dynamic ¶
func (b *BroadcastProducer) Dynamic() (*BroadcastDynamic, error)
Dynamic accepts requests for tracks that are not published yet.
func (*BroadcastProducer) EncodeAudio ¶
func (b *BroadcastProducer) EncodeAudio(name string, input AudioEncoderInput, output AudioEncoderOutput, bandwidth *Bandwidth) (*AudioProducer, error)
EncodeAudio publishes a raw-audio track with an in-process encoder.
Select the codec with OpusAudioCodec or AacAudioCodec. Pass bandwidth to reserve this track's bitrate against the session's allocator so a co-resident video encoder sizes itself against what is left.
func (*BroadcastProducer) EncodeVideo ¶
func (b *BroadcastProducer) EncodeVideo(input VideoEncoderInput, output VideoEncoderOutput, bandwidth *Bandwidth) (*VideoProducer, error)
EncodeVideo publishes a raw-video track with an in-process H.264/H.265 encoder.
Set output.Track to choose the track name; otherwise one is derived from the codec (.avc3 / .hev1). The catalog rendition is published immediately so subscribers can discover it before the first frame exists.
Pass bandwidth to reserve this track's configured bitrate and follow the grant.
func (*BroadcastProducer) Finish
deprecated
func (b *BroadcastProducer) Finish() error
Finish ends the broadcast.
Deprecated: use BroadcastProducer.Close; a broadcast end carries no cause.
func (*BroadcastProducer) PublishAudio ¶
func (b *BroadcastProducer) PublishAudio(format AudioFormat, init []byte, opts ...AudioOption) (*MediaProducer, error)
PublishAudio publishes one audio codec as a new track, fed frame by frame with explicit timestamps. init carries the codec init bytes, which audio requires.
func (*BroadcastProducer) PublishAudioOnTrack ¶
func (b *BroadcastProducer) PublishAudioOnTrack(request *TrackRequest, format AudioFormat, init []byte, opts ...AudioOption) (*MediaProducer, error)
PublishAudioOnTrack publishes one audio codec onto a subscriber-requested track.
func (*BroadcastProducer) PublishContainer ¶
func (b *BroadcastProducer) PublishContainer(format ContainerFormat, init []byte) (*ContainerProducer, error)
PublishContainer publishes a container, which demuxes and publishes its own tracks. There is no label or hint: a container describes each track itself.
func (*BroadcastProducer) PublishContainerStream ¶
func (b *BroadcastProducer) PublishContainerStream(format ContainerFormat) (*ContainerStreamProducer, error)
PublishContainerStream publishes a container fed by a raw byte stream, which recovers its own framing.
func (*BroadcastProducer) PublishJSONSnapshot ¶
func (b *BroadcastProducer) PublishJSONSnapshot( name string, options JSONSnapshotOptions, ) (*JSONSnapshotProducer, error)
PublishJSONSnapshot opens a lossy latest-value JSON track.
func (*BroadcastProducer) PublishJSONStream ¶
func (b *BroadcastProducer) PublishJSONStream(name string, options JSONStreamOptions) (*JSONStreamProducer, error)
PublishJSONStream opens a lossless append-log JSON track.
func (*BroadcastProducer) PublishTrack ¶
func (b *BroadcastProducer) PublishTrack(name string, info *TrackInfo) (*TrackProducer, error)
PublishTrack creates a track that carries arbitrary byte payloads with no codec validation. info sets track properties (priority, cache, timescale); pass nil for defaults.
func (*BroadcastProducer) PublishVideo ¶
func (b *BroadcastProducer) PublishVideo(format VideoFormat, init []byte, opts ...VideoOption) (*MediaProducer, error)
PublishVideo publishes one video codec as a new track. init may be nil for a format that resolves in band.
Example (VideoHint) ¶
Publish a video track with catalog hints known before the first keyframe.
package main
import (
"log"
"moq.dev/moq"
)
func main() {
broadcast, err := moq.NewBroadcastProducer()
if err != nil {
log.Fatal(err)
}
defer broadcast.Close()
media, err := broadcast.PublishVideo(moq.VideoFormatAvc3, nil, moq.WithVideoHint(moq.VideoHint{}))
if err != nil {
log.Fatal(err)
}
defer media.Finish()
}
Output:
func (*BroadcastProducer) PublishVideoOnTrack ¶
func (b *BroadcastProducer) PublishVideoOnTrack(request *TrackRequest, format VideoFormat, init []byte, opts ...VideoOption) (*MediaProducer, error)
PublishVideoOnTrack publishes one video codec onto a subscriber-requested track.
func (*BroadcastProducer) PublishVideoStream ¶
func (b *BroadcastProducer) PublishVideoStream(format VideoFormat, opts ...VideoOption) (*MediaStreamProducer, error)
PublishVideoStream publishes a video track fed by a raw byte stream with unknown frame boundaries (e.g. Annex-B H.264). Only the self-delimiting formats work: Avc3, Hev1, Av01. Audio has no counterpart, having no frame boundaries to infer.
func (*BroadcastProducer) RemoveCatalogSection ¶
func (b *BroadcastProducer) RemoveCatalogSection(name string) error
RemoveCatalogSection removes an untyped application catalog section by name. It is a no-op if the section was absent.
func (*BroadcastProducer) SetCatalogSection ¶
func (b *BroadcastProducer) SetCatalogSection(name string, json string) error
SetCatalogSection sets (or replaces) an untyped application catalog section by name. json is any JSON document as a string; it rides alongside video/audio and reaches subscribers via Catalog.Sections. name must not be a reserved media section ("video"/"audio"). The catalog is republished automatically.
func (*BroadcastProducer) SetVideoProperties ¶
func (b *BroadcastProducer) SetVideoProperties(properties VideoProperties) error
SetVideoProperties replaces the catalog properties shared by every video rendition.
func (*BroadcastProducer) Unannounce ¶
func (b *BroadcastProducer) Unannounce() error
Unannounce retracts this broadcast's exact-path advertisement, if any, from local consumers and peers alike. Tracks already in flight carry on.
type BroadcastRequest ¶
type BroadcastRequest struct {
// contains filtered or unexported fields
}
BroadcastRequest is a requested broadcast that has not been accepted yet.
func (*BroadcastRequest) Accept ¶
func (r *BroadcastRequest) Accept(broadcast *BroadcastProducer) error
Accept serves the request with an unannounced broadcast.
func (*BroadcastRequest) Path ¶
func (r *BroadcastRequest) Path() (string, error)
Path returns the requested broadcast path.
func (*BroadcastRequest) Reject ¶
func (r *BroadcastRequest) Reject(errorCode uint16) error
Reject fails the request with an application error code.
type Catalog ¶
type Catalog = ffi.MoqCatalog
Catalog is a broadcast's manifest: its video and audio renditions plus display metadata.
type CatalogConsumer ¶
type CatalogConsumer struct {
// contains filtered or unexported fields
}
CatalogConsumer is a stream of catalog updates.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is a connected MoQ client with automatic origin wiring. When no origin option is given, both sides share one origin, so a broadcast announced here is also discoverable here.
func Dial ¶
Dial connects to a MoQ server and returns the established client. Cancel ctx to abort an in-flight connect.
func (*Client) Announced ¶
func (c *Client) Announced(options AnnounceOptions) (*AnnounceConsumer, error)
Announced streams routes announced by the remote under a pattern scope.
Example ¶
Subscribe to a broadcast and print its catalog. These examples have no Output line, so they are compiled (API-checked) but not executed.
package main
import (
"context"
"fmt"
"log"
"moq.dev/moq"
)
func main() {
ctx := context.Background()
client, err := moq.Dial(ctx, "https://relay.example.com")
if err != nil {
log.Fatal(err)
}
defer client.Close()
announced, err := client.Announced(moq.AnnounceOptions{Prefix: "demos/"})
if err != nil {
log.Fatal(err)
}
defer announced.Cancel()
for ann, err := range announced.All(ctx) {
if err != nil {
if moq.IsShutdown(err) {
break
}
log.Fatal(err)
}
if !ann.Active() {
continue
}
fmt.Println("broadcast:", ann.Prefix())
}
}
Output:
func (*Client) AnnouncedBroadcast ¶
func (c *Client) AnnouncedBroadcast(path string) (*AnnouncedBroadcast, error)
AnnouncedBroadcast waits for a route covering path, then resolves the broadcast there.
func (*Client) Close ¶
Close gracefully shuts down the session and stops the client. Safe to call more than once.
func (*Client) CreateBroadcast ¶
func (c *Client) CreateBroadcast(path string) (*BroadcastProducer, error)
CreateBroadcast creates an unannounced broadcast at path, invisible to everyone until announced. Announce it after populating tracks.
See OriginProducer.CreateBroadcast.
Example ¶
Publish a media track to a relay.
ctx := context.Background()
client, err := moq.Dial(ctx, "https://relay.example.com")
if err != nil {
log.Fatal(err)
}
defer client.Close()
broadcast, err := client.CreateBroadcast("me/mic")
if err != nil {
log.Fatal(err)
}
// Closing ends the broadcast for good.
defer broadcast.Close()
media, err := broadcast.PublishAudio(moq.AudioFormatOpus, opusHead())
if err != nil {
log.Fatal(err)
}
_ = broadcast.Announce(moq.Route{})
if err := media.WriteFrame(moq.Frame{Payload: []byte("opus frame")}); err != nil {
log.Fatal(err)
}
func (*Client) RequestBroadcast ¶
RequestBroadcast resolves a broadcast at path as soon as it can be served: an existing exact-path broadcast, a covering announced route, or a dynamic fallback on the origin, or an error. Unlike AnnouncedBroadcast, it does not wait for a future announcement.
func (*Client) Session ¶
Session returns the underlying session. Hold the client (or session) to keep the connection alive.
Example (Stats) ¶
Connect with pinned TLS material and read a stats snapshot.
package main
import (
"context"
"fmt"
"log"
"moq.dev/moq"
)
func main() {
ctx := context.Background()
client, err := moq.Dial(ctx, "https://relay.example.com",
moq.WithTLSRoots("/etc/ssl/custom-ca.pem"),
moq.WithTLSSystemRoots(true),
moq.WithTLSFingerprints("0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"),
)
if err != nil {
log.Fatal(err)
}
defer client.Close()
stats := client.Session().Stats()
fmt.Println("rtt:", stats.RttUs)
}
Output:
type ClientOption ¶
type ClientOption func(*clientConfig)
ClientOption configures a client created with Dial.
func WithBackoff ¶
func WithBackoff(backoff Backoff) ClientOption
WithBackoff sets retry pacing for the automatic reconnect.
func WithBind ¶
func WithBind(addr string) ClientOption
WithBind sets the local UDP socket bind address (default "[::]:0").
func WithClientTLSCert ¶
func WithClientTLSCert(path string) ClientOption
WithClientTLSCert sets the path to a PEM certificate chain for mTLS.
func WithClientTLSKey ¶
func WithClientTLSKey(path string) ClientOption
WithClientTLSKey sets the path to a PEM private key for mTLS.
func WithPublishOrigin ¶
func WithPublishOrigin(o *OriginProducer) ClientOption
WithPublishOrigin sets the origin whose broadcasts are published to the remote. Pair with WithSubscribeOrigin for full control; omit both to get a shared internal origin.
func WithQUICMaxStreams ¶
func WithQUICMaxStreams(maxStreams uint64) ClientOption
WithQUICMaxStreams caps the concurrent QUIC streams the peer may open toward this connection (default 1024). MoQ opens a stream per group, and for a subscriber those arrive from the relay, so a client subscribing to many tracks wants this raised. A publisher's own streams are bounded by the relay's advertised limit, not this one. Ignored by the WebSocket fallback.
func WithReconnect ¶
func WithReconnect(enabled bool) ClientOption
WithReconnect toggles automatic reconnecting. It is on by default: the session redials with backoff whenever the transport drops, and broadcasts consumed through it ride out the gap. Pass false for a one-shot dial whose transport close ends the session.
func WithSubscribeOrigin ¶
func WithSubscribeOrigin(o *OriginProducer) ClientOption
WithSubscribeOrigin sets the origin that receives broadcasts consumed from the remote.
func WithTLSFingerprints ¶
func WithTLSFingerprints(fingerprints ...string) ClientOption
WithTLSFingerprints pins the peer to one of these SHA-256 certificate fingerprints.
func WithTLSRoots ¶
func WithTLSRoots(paths ...string) ClientOption
WithTLSRoots trusts PEM root certificate files instead of the system roots.
func WithTLSSystemRoots ¶
func WithTLSSystemRoots(systemRoots bool) ClientOption
WithTLSSystemRoots controls whether platform roots are trusted with custom roots.
func WithTLSVerify ¶
func WithTLSVerify(verify bool) ClientOption
WithTLSVerify toggles TLS certificate verification. Verification is on by default; pass false only against a relay with a self-signed certificate during development.
func WithWebSocketDelay ¶ added in v0.7.3
func WithWebSocketDelay(delay time.Duration) ClientOption
WithWebSocketDelay sets the head start QUIC gets before the WebSocket fallback joins the race (default 200ms). Zero races both at once, and a negative delay fails Dial.
func WithWebSocketEnabled ¶ added in v0.7.3
func WithWebSocketEnabled(enabled bool) ClientOption
WithWebSocketEnabled toggles the WebSocket fallback, which races QUIC for http(s) URLs. It is on by default; pass false against a relay that only serves QUIC.
type ConnectionStats ¶
type ConnectionStats = ffi.MoqConnectionStats
ConnectionStats holds transport metrics for a session (RTT, bandwidth, byte and packet counters); each field is nil when unreported.
type ConnectionStatus ¶
type ConnectionStatus = ffi.MoqConnectionStatus
ConnectionStatus is a connection lifecycle transition reported by Session.Status.
type Container ¶
type Container = ffi.MoqContainer
Container selects how subscribed media frames are demuxed. Build one with LegacyContainer, CmafContainer, or LocContainer.
func CmafContainer ¶
CmafContainer selects the CMAF (fMP4) container for a media subscription, initialized from the given init segment.
func LegacyContainer ¶
func LegacyContainer() Container
LegacyContainer selects the legacy hang container for a media subscription.
func LocContainer ¶
func LocContainer() Container
LocContainer selects the low-overhead container for a media subscription.
type ContainerCmaf ¶
type ContainerCmaf = ffi.MoqContainerCmaf
ContainerCmaf is the CMAF (fMP4) container variant of Container, carrying its init segment; build one with CmafContainer.
type ContainerFormat ¶
type ContainerFormat = ffi.MoqContainerFormat
ContainerFormat is a container that publishes its own tracks.
type ContainerLegacy ¶
type ContainerLegacy = ffi.MoqContainerLegacy
ContainerLegacy is the legacy hang container variant of Container; build one with LegacyContainer.
type ContainerLoc ¶
type ContainerLoc = ffi.MoqContainerLoc
ContainerLoc is the low-overhead container variant of Container; build one with LocContainer.
type ContainerProducer ¶
type ContainerProducer struct {
// contains filtered or unexported fields
}
ContainerProducer publishes a container, which demuxes and publishes its own tracks. Unlike MediaProducer there is no per-frame timestamp: a container carries its tracks' timing itself.
func (*ContainerProducer) Cut ¶
func (c *ContainerProducer) Cut() error
Cut declares that the next chunk starts a new segment, rolling a group on every track. An fMP4 source carrying styp atoms declares its own, so this is only needed when it doesn't; MKV, TS, and FLV ignore it.
func (*ContainerProducer) Finish ¶
func (c *ContainerProducer) Finish() error
Finish finishes every track this container publishes.
func (*ContainerProducer) Seek ¶
func (c *ContainerProducer) Seek(sequence uint64) error
Seek starts a new segment and numbers its groups sequence.
func (*ContainerProducer) Write ¶
func (c *ContainerProducer) Write(payload []byte) error
Write pushes a whole chunk of container bytes.
type ContainerStreamProducer ¶
type ContainerStreamProducer struct {
// contains filtered or unexported fields
}
ContainerStreamProducer publishes a container fed by a raw byte stream, which recovers its own framing.
func (*ContainerStreamProducer) Finish ¶
func (c *ContainerStreamProducer) Finish() error
Finish finishes every track this container publishes.
func (*ContainerStreamProducer) Write ¶
func (c *ContainerStreamProducer) Write(payload []byte) error
Write pushes raw container bytes; chunk boundaries don't matter.
type Datagram ¶
type Datagram = ffi.MoqDatagram
Datagram is a best-effort track datagram as received: sequence number, timestamp, and payload.
type Error ¶
Error is the error type returned across the FFI boundary. Compare against the sentinels below with errors.Is, or use one of the Is* helpers for the common cases.
type ErrorScope ¶
type ErrorScope = ffi.MoqErrorScope
ErrorScope is whether a protocol code is from the session or stream registry.
type FetchGroupOptions ¶
type FetchGroupOptions = ffi.MoqFetchGroupOptions
FetchGroupOptions configures a single FetchGroup call, currently just the delivery priority.
type GroupConsumer ¶
type GroupConsumer struct {
// contains filtered or unexported fields
}
GroupConsumer is a stream of timestamped raw frames within a single group.
func (*GroupConsumer) Frames ¶
Frames ranges over timestamped frames until the group ends or the loop breaks.
func (*GroupConsumer) ReadFrame ¶
func (g *GroupConsumer) ReadFrame(ctx context.Context) (*Frame, error)
ReadFrame returns the next timestamped frame, or (nil, nil) when the group ends.
func (*GroupConsumer) Sequence ¶
func (g *GroupConsumer) Sequence() uint64
Sequence is this group's sequence number within the track.
type GroupProducer ¶
type GroupProducer struct {
// contains filtered or unexported fields
}
GroupProducer writes frames into a single group on a track.
func (*GroupProducer) Abort ¶
func (g *GroupProducer) Abort(errorCode uint16) error
Abort terminates the group with an application error code.
func (*GroupProducer) Consume ¶
func (g *GroupProducer) Consume() (*GroupConsumer, error)
Consume reads frames from this group.
func (*GroupProducer) Finish ¶
func (g *GroupProducer) Finish() error
Finish marks the group complete. The handle remains so Abort can still run.
func (*GroupProducer) Sequence ¶
func (g *GroupProducer) Sequence() uint64
Sequence is this group's sequence number within the track.
func (*GroupProducer) WriteFrame ¶
func (g *GroupProducer) WriteFrame(frame Frame) error
WriteFrame appends frame to the group.
type GroupRequest ¶
type GroupRequest struct {
// contains filtered or unexported fields
}
GroupRequest requests one uncached group from a track producer.
func (*GroupRequest) Abort ¶
func (r *GroupRequest) Abort(errorCode uint16) error
Abort rejects the fetch with an application error code.
func (*GroupRequest) Accept ¶
func (r *GroupRequest) Accept() (*GroupProducer, error)
Accept accepts the request and returns a producer for the group.
func (*GroupRequest) Priority ¶
func (r *GroupRequest) Priority() uint8
Priority is the consumer's delivery priority for this fetch.
func (*GroupRequest) Sequence ¶
func (r *GroupRequest) Sequence() uint64
Sequence is the requested group sequence within the track.
type JSONSnapshotConsumer ¶
type JSONSnapshotConsumer struct {
// contains filtered or unexported fields
}
JSONSnapshotConsumer receives the latest reconstructed JSON value.
func (*JSONSnapshotConsumer) Cancel ¶
func (c *JSONSnapshotConsumer) Cancel()
Cancel stops current and future reads.
func (*JSONSnapshotConsumer) Next ¶
func (c *JSONSnapshotConsumer) Next(ctx context.Context) (*json.RawMessage, error)
Next returns the next JSON value, or nil when the track ends.
func (*JSONSnapshotConsumer) Values ¶
func (c *JSONSnapshotConsumer) Values(ctx context.Context) iter.Seq2[*json.RawMessage, error]
Values ranges over reconstructed JSON values until the track ends.
type JSONSnapshotOptions ¶
type JSONSnapshotOptions struct {
// DeltaRatio controls how aggressively deltas replace full snapshots. Nil uses
// [DefaultDeltaRatio]; a pointer to zero disables deltas entirely.
DeltaRatio *uint32
// Compression enables group-scoped DEFLATE and must match on the consumer.
Compression bool
}
JSONSnapshotOptions configures publishing a lossy latest-value JSON track.
type JSONSnapshotProducer ¶
type JSONSnapshotProducer struct {
// contains filtered or unexported fields
}
JSONSnapshotProducer publishes a JSON value as lossy latest state.
func (*JSONSnapshotProducer) Demand ¶
func (p *JSONSnapshotProducer) Demand() (*TrackDemand, error)
Demand returns a watch-only handle to whether the track has subscribers.
func (*JSONSnapshotProducer) Finish ¶
func (p *JSONSnapshotProducer) Finish() error
Finish closes the snapshot track.
func (*JSONSnapshotProducer) Update ¶
func (p *JSONSnapshotProducer) Update(value any) error
Update publishes value as a JSON snapshot or delta. It is a no-op when unchanged.
type JSONStreamConsumer ¶
type JSONStreamConsumer struct {
// contains filtered or unexported fields
}
JSONStreamConsumer receives every JSON record in order.
func (*JSONStreamConsumer) Cancel ¶
func (c *JSONStreamConsumer) Cancel()
Cancel stops current and future reads.
func (*JSONStreamConsumer) Next ¶
func (c *JSONStreamConsumer) Next(ctx context.Context) (*json.RawMessage, error)
Next returns the next JSON record, or nil when the track ends.
func (*JSONStreamConsumer) Values ¶
func (c *JSONStreamConsumer) Values(ctx context.Context) iter.Seq2[*json.RawMessage, error]
Values ranges over every JSON record until the track ends.
type JSONStreamOptions ¶
type JSONStreamOptions struct {
// Compression enables group-scoped DEFLATE and must match on the consumer.
Compression bool
}
JSONStreamOptions configures publishing a lossless append-log JSON track.
type JSONStreamProducer ¶
type JSONStreamProducer struct {
// contains filtered or unexported fields
}
JSONStreamProducer publishes an ordered lossless log of JSON records.
func (*JSONStreamProducer) Append ¶
func (p *JSONStreamProducer) Append(value any) error
Append adds one JSON record to the log.
func (*JSONStreamProducer) Demand ¶
func (p *JSONStreamProducer) Demand() (*TrackDemand, error)
Demand returns a watch-only handle to whether the track has subscribers.
func (*JSONStreamProducer) Finish ¶
func (p *JSONStreamProducer) Finish() error
Finish closes the stream track.
type JSONSubscribeOptions ¶
type JSONSubscribeOptions struct {
// Compression enables group-scoped DEFLATE and must match the producer.
Compression bool
}
JSONSubscribeOptions configures subscribing to either kind of JSON track.
Delta encoding is a producer-side choice the consumer reconstructs automatically, so only the compression setting has to match.
type MediaConsumer ¶
type MediaConsumer struct {
// contains filtered or unexported fields
}
MediaConsumer is a stream of decoded media frames.
func (*MediaConsumer) Frames ¶
func (m *MediaConsumer) Frames(ctx context.Context) iter.Seq2[*MediaFrame, error]
Frames ranges over frames until the track ends or the loop breaks.
func (*MediaConsumer) Next ¶
func (m *MediaConsumer) Next(ctx context.Context) (*MediaFrame, error)
Next returns the next frame, or (nil, nil) when the track ends.
type MediaFrame ¶
type MediaFrame = ffi.MoqMediaFrame
MediaFrame is a Frame plus a flag for group starts or video keyframes; audio flags only group starts.
type MediaGroupConsumer ¶
type MediaGroupConsumer struct {
// contains filtered or unexported fields
}
MediaGroupConsumer is a finite stream of decoded media frames from one fetched group. It ends after the group's last frame.
func (*MediaGroupConsumer) Frames ¶
func (m *MediaGroupConsumer) Frames(ctx context.Context) iter.Seq2[*MediaFrame, error]
Frames ranges over decoded frames until the group ends or the loop breaks.
func (*MediaGroupConsumer) Next ¶
func (m *MediaGroupConsumer) Next(ctx context.Context) (*MediaFrame, error)
Next returns the next decoded frame, or (nil, nil) when the group ends.
func (*MediaGroupConsumer) Sequence ¶
func (m *MediaGroupConsumer) Sequence() uint64
Sequence is this group's sequence number within the track.
type MediaProducer ¶
type MediaProducer struct {
// contains filtered or unexported fields
}
MediaProducer writes timestamped frames into a media track.
func (*MediaProducer) Cut ¶
func (m *MediaProducer) Cut() error
Cut draws a group boundary here.
Audio has no boundary of its own (every packet is independently decodable), so this is the only thing that gives it groups: call it after every frame for one group (one QUIC stream) the relay forwards without waiting, or at a segment cadence to align with video. Video groups at its own keyframes and needs this only to override that.
On a container this declares a new segment, rolling a group on every track it publishes.
func (*MediaProducer) Demand ¶
func (m *MediaProducer) Demand() (*TrackDemand, error)
Demand returns a watch-only handle to whether the track has subscribers.
func (*MediaProducer) Discontinuity ¶ added in v0.7.6
func (m *MediaProducer) Discontinuity() error
Discontinuity marks a timeline break and restarts handoff measurement, preserving advertised jitter.
func (*MediaProducer) Finish ¶
func (m *MediaProducer) Finish() error
Finish closes the media track.
func (*MediaProducer) Flush ¶ added in v0.7.3
func (m *MediaProducer) Flush(timestampUs uint64) error
Flush records a local encoder's frame handoff on the broadcast media clock. Call after WriteFrame only for local encoder output, not file or network imports.
func (*MediaProducer) Name ¶
func (m *MediaProducer) Name() (string, error)
Name is the generated media track name.
func (*MediaProducer) Seek ¶
func (m *MediaProducer) Seek(sequence uint64) error
Seek draws a group boundary and numbers the next group sequence.
Cut with an explicit sequence, for a publisher whose group numbers have to be deterministic: two encoders aligning per GOP so a consumer can fail over between them.
func (*MediaProducer) Unused ¶
func (m *MediaProducer) Unused(ctx context.Context) error
Unused blocks until the track has no active subscribers. Prefer Demand.
func (*MediaProducer) Used ¶
func (m *MediaProducer) Used(ctx context.Context) error
Used blocks until the track has at least one active subscriber. Prefer Demand.
func (*MediaProducer) WriteFrame ¶
func (m *MediaProducer) WriteFrame(frame Frame) error
WriteFrame appends frame to the media track. The importer derives keyframe status from the bitstream, so a Frame carries only the payload and its timestamp.
type MediaStreamProducer ¶
type MediaStreamProducer struct {
// contains filtered or unexported fields
}
MediaStreamProducer feeds a raw encoder byte stream; whole frames are emitted as they complete.
func (*MediaStreamProducer) Finish ¶
func (m *MediaStreamProducer) Finish() error
Finish closes the stream.
func (*MediaStreamProducer) Write ¶
func (m *MediaStreamProducer) Write(payload []byte) error
Write pushes raw stream bytes.
type OriginConfig ¶
type OriginConfig = ffi.MoqOriginConfig
OriginConfig configures a new origin, such as its maximum cache size in bytes.
type OriginConsumer ¶
type OriginConsumer struct {
// contains filtered or unexported fields
}
OriginConsumer discovers and requests broadcasts published to an origin.
func (*OriginConsumer) Announced ¶
func (o *OriginConsumer) Announced(options AnnounceOptions) (*AnnounceConsumer, error)
Announced streams routes under a literal prefix matching an optional pattern filter.
func (*OriginConsumer) AnnouncedBroadcast ¶
func (o *OriginConsumer) AnnouncedBroadcast(path string) (*AnnouncedBroadcast, error)
AnnouncedBroadcast waits for a route covering an exact path, then resolves the broadcast there.
func (*OriginConsumer) RequestBroadcast ¶
func (o *OriginConsumer) RequestBroadcast(ctx context.Context, path string) (*BroadcastConsumer, error)
RequestBroadcast resolves a broadcast at path as soon as it can be served, through the best announced route covering it: an announced broadcast on this origin, a route a session announced (served on demand by that session), or a dynamic handler on the origin; errors if nothing can serve it, including a broadcast created but not announced. Unlike AnnouncedBroadcast, it does not wait for a future announcement. Blocks until resolved.
type OriginDynamic ¶
type OriginDynamic struct {
// contains filtered or unexported fields
}
OriginDynamic streams requests for paths with no existing exact-path broadcast.
func (*OriginDynamic) Cancel ¶
func (d *OriginDynamic) Cancel()
Cancel stops serving requested broadcasts and retracts the route.
func (*OriginDynamic) RequestedBroadcast ¶
func (d *OriginDynamic) RequestedBroadcast(ctx context.Context) (*BroadcastRequest, error)
RequestedBroadcast blocks until a consumer requests a path with no existing exact-path broadcast.
func (*OriginDynamic) Requests ¶
func (d *OriginDynamic) Requests(ctx context.Context) iter.Seq2[*BroadcastRequest, error]
Requests ranges over requested broadcasts until the stream errors or the loop breaks.
func (*OriginDynamic) Update ¶
func (d *OriginDynamic) Update(route Route) error
Update re-prices the route in place: replaces its hops and costs.
type OriginProducer ¶
type OriginProducer struct {
// contains filtered or unexported fields
}
OriginProducer publishes broadcasts under paths and hands out consumers that discover them. Wire one as both a client's/server's publish source and consume sink for a full-duplex peer.
There is no Close: the origin ends once the collector reaches every owner (each producer, published broadcast, and OriginDynamic), and its consumers then fail with ErrClosed. Keep an owner reachable for as long as the origin should live.
func NewOriginProducer ¶
func NewOriginProducer() *OriginProducer
NewOriginProducer creates an empty origin.
func NewOriginProducerWithConfig ¶
func NewOriginProducerWithConfig(config OriginConfig) *OriginProducer
NewOriginProducerWithConfig creates an origin with explicit config.
func (*OriginProducer) Consume ¶
func (o *OriginProducer) Consume() *OriginConsumer
Consume returns a consumer that observes broadcasts published to this origin.
func (*OriginProducer) CreateBroadcast ¶
func (o *OriginProducer) CreateBroadcast(path string) (*BroadcastProducer, error)
CreateBroadcast creates a broadcast at the given path, returning the producer that feeds it.
The broadcast is invisible and unroutable, for this origin's consumers and peers alike, until BroadcastProducer.Announce. Announce it after populating tracks. BroadcastProducer.Close ends it for good; dropping the last handle does the same.
func (*OriginProducer) Dynamic ¶
func (o *OriginProducer) Dynamic(prefix string, route Route) (*OriginDynamic, error)
Dynamic advertises prefix and serves the requests beneath it.
A route claims prefix and every path beneath it ("" claims every path). A service that only serves some of them rejects the rest as they are requested. Create, Dynamic if tracks are served on demand, populate, then BroadcastProducer.Announce.
type ProtocolKind ¶
type ProtocolKind = ffi.MoqProtocolKind
ProtocolKind is a recognized protocol kind, or App / Unknown when the code is not named.
type Request ¶
type Request struct {
// contains filtered or unexported fields
}
Request is an incoming session that can be accepted (Accept) or rejected (Reject). Dropping a Request without responding closes the connection silently.
func (*Request) Accept ¶
Accept completes the handshake and returns the established session. Hold the session to keep the connection alive.
func (*Request) Path ¶
Path is the query-free request path, or an empty string for the root/missing path.
func (*Request) Reject ¶
Reject refuses the session with an application error code; 401 and 403 map to unauthorized.
func (*Request) SetConsume ¶
func (r *Request) SetConsume(o *OriginProducer) error
SetConsume overrides the consume origin for this session. Pass nil to fall back to the server's configured consume origin. Captured at Accept.
func (*Request) SetPublish ¶
func (r *Request) SetPublish(o *OriginProducer) error
SetPublish overrides the publish origin for this session. Pass nil to fall back to the server's configured publish origin. Captured at Accept.
type Reservation ¶
type Reservation struct {
// contains filtered or unexported fields
}
Reservation is one track's standing claim on a Bandwidth.
Grant is a snapshot: nil means no estimate or no demand, so hold the current rate, and 0 is a real zero grant.
func (*Reservation) Grant ¶
func (r *Reservation) Grant() *uint64
Grant returns this reservation's slice right now, in bits per second.
func (*Reservation) Update ¶
func (r *Reservation) Update(maxBps uint64)
Update changes the ceiling, keeping the same claim.
type Route ¶
Route is the hop chain a broadcast takes to reach an origin, and its costs: warm Cost plus undiscounted Cold (nil Cold means Cost).
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server accepts incoming sessions with automatic origin wiring.
func Listen ¶
Listen binds the server and starts accepting. Cancel ctx to abort the bind.
Example ¶
Run a server with a self-signed certificate, accepting every session.
package main
import (
"context"
"log"
"moq.dev/moq"
)
func main() {
ctx := context.Background()
server, err := moq.Listen(ctx, "127.0.0.1:4443", moq.WithTLSGenerate("localhost"))
if err != nil {
log.Fatal(err)
}
defer server.Close()
if err := server.Serve(ctx); err != nil && !moq.IsShutdown(err) {
log.Fatal(err)
}
}
Output:
func (*Server) Accept ¶
Accept returns the next incoming request, or (nil, nil) when the server stops.
Cancelling ctx aborts this accept alone and leaves the server listening; use Close to tear the listener down.
func (*Server) CertFingerprints ¶
CertFingerprints returns the SHA-256 fingerprints of the configured TLS certificates, hex-encoded. Useful for pinning a generated self-signed certificate in a browser via WebTransport's serverCertificateHashes.
func (*Server) Close ¶
Close stops accepting new sessions and releases the listening socket before it returns, so the same address can be bound again immediately. In-flight sessions stay alive until their handles are dropped or cancelled. Safe to call more than once and from multiple goroutines (Serve calls it on ctx-driven shutdown).
func (*Server) CreateBroadcast ¶
func (s *Server) CreateBroadcast(path string) (*BroadcastProducer, error)
CreateBroadcast creates an unannounced broadcast at path, invisible to everyone until announced. Announce it after populating tracks.
func (*Server) Requests ¶
Requests ranges over incoming requests until the server stops or the loop breaks. Each request must be answered with Accept or Reject.
Example ¶
Drive the accept loop directly to decide which sessions to admit.
package main
import (
"context"
"log"
"moq.dev/moq"
)
func main() {
ctx := context.Background()
server, err := moq.Listen(ctx, "127.0.0.1:4443", moq.WithTLSGenerate("localhost"))
if err != nil {
log.Fatal(err)
}
defer server.Close()
for req, err := range server.Requests(ctx) {
if err != nil {
if moq.IsShutdown(err) {
break
}
log.Fatal(err)
}
// Reject anything that didn't arrive over QUIC.
if req.Transport() != moq.TransportQUIC {
_ = req.Reject(ctx, 403)
continue
}
session, err := req.Accept(ctx)
if err != nil {
continue
}
// Hold the session to keep the connection alive.
go func() { _ = session.Closed(ctx) }()
}
}
Output:
func (*Server) Serve ¶
Serve accepts every session in a loop, holding each one alive in its own goroutine until it closes, so memory does not grow with past connections. It returns when Accept stops (nil) or fails, after the in-flight sessions wind down.
To inspect or reject requests, range over Requests instead:
for req, err := range server.Requests(ctx) {
if err != nil {
return err
}
if req.Path() == "/admin" {
_ = req.Reject(ctx, 403)
continue
}
session, err := req.Accept(ctx)
// hold the session to keep the connection alive
}
type ServerOption ¶
type ServerOption func(*serverConfig)
ServerOption configures a server created with Listen.
func WithServerPublishOrigin ¶
func WithServerPublishOrigin(o *OriginProducer) ServerOption
WithServerPublishOrigin sets the origin whose broadcasts are served to incoming sessions. Omit both origin options to get a shared internal origin.
func WithServerSubscribeOrigin ¶
func WithServerSubscribeOrigin(o *OriginProducer) ServerOption
WithServerSubscribeOrigin sets the origin that receives broadcasts published by incoming sessions.
func WithTLSCert ¶
func WithTLSCert(paths ...string) ServerOption
WithTLSCert sets paths to TLS certificate chains.
func WithTLSGenerate ¶
func WithTLSGenerate(hostnames ...string) ServerOption
WithTLSGenerate generates a self-signed certificate for the given hostnames.
func WithTLSKey ¶
func WithTLSKey(paths ...string) ServerOption
WithTLSKey sets paths to TLS private keys.
type Session ¶
type Session struct {
// contains filtered or unexported fields
}
Session is an established MoQ connection. Hold it (or the Client/Server that produced it) to keep the connection alive; once every handle is dropped the connection closes.
func (*Session) Bandwidth ¶
Bandwidth is the session's bandwidth allocator. Every call returns a handle to the same registry, so reservations made through one are visible to the others. A client handle survives reconnects: the grant is nil while disconnected and resumes on the next connection.
func (*Session) Closed ¶
Closed blocks until the session closes and returns the reason. A graceful close reports an error for which IsShutdown returns true. Cancelling ctx gives up waiting and shuts the session down, so a caller that no longer cares about the connection can tear it down by cancelling.
func (*Session) Consume ¶
func (s *Session) Consume() *OriginConsumer
Consume returns the origin used to receive broadcasts from the remote.
func (*Session) Epoch ¶
Epoch is the connection epoch: 1 for the connect that built this session, one more on each reconnect. A server-accepted session stays at 1.
Pair it with Status to log each reconnect by number: a StatusConnected whose Epoch grew is a reconnect. Like Status, it reports the current state, so a drop that reconnects between reads is coalesced away.
func (*Session) Publish ¶
func (s *Session) Publish() *OriginProducer
Publish returns the origin used to advertise local broadcasts to the remote.
func (*Session) Stats ¶
func (s *Session) Stats() ConnectionStats
Stats snapshots the current connection statistics.
func (*Session) Status ¶
func (s *Session) Status(ctx context.Context) (ConnectionStatus, error)
Status blocks until the connection status differs from the one this session last reported. A client session reports StatusConnected first (the connect it was built from), then follows the reconnect loop: StatusDisconnected while redialing, StatusMigrating during a GOAWAY handover. It returns an error once the connection stops for good. A server-accepted session's only transition is terminal, so Status waits for the close and returns its reason. Cancelling ctx gives up waiting and shuts the session down.
This reports the current status rather than every edge: a drop that reconnects before the next call is coalesced away, so the outages it hides are the ones that already healed. Don't count outages with it.
type Subscription ¶
type Subscription = ffi.MoqSubscription
Subscription holds subscriber-side delivery preferences: priority, ordering, max age, and group range.
type TrackConsumer ¶
type TrackConsumer struct {
// contains filtered or unexported fields
}
TrackConsumer is a stream of groups from a track. Each group is itself a stream of timestamped raw frames.
func (*TrackConsumer) Groups ¶
func (t *TrackConsumer) Groups(ctx context.Context) iter.Seq2[*GroupConsumer, error]
Groups ranges over groups in sequence order.
func (*TrackConsumer) GroupsAsArrived ¶
func (t *TrackConsumer) GroupsAsArrived(ctx context.Context) iter.Seq2[*GroupConsumer, error]
GroupsAsArrived ranges over groups in arrival order, including out-of-sequence deliveries.
func (*TrackConsumer) Info ¶
func (t *TrackConsumer) Info() (TrackInfo, error)
Info returns the publisher-side track properties learned during subscription.
func (*TrackConsumer) NextGroup ¶
func (t *TrackConsumer) NextGroup(ctx context.Context) (*GroupConsumer, error)
NextGroup returns the next group in sequence order, skipping forward if behind, or (nil, nil) when the track ends. Prefer this when order matters more than latency. Shares the sequence cursor with ReadFrame: a group one method has already taken is not returned by the other.
func (*TrackConsumer) ReadFrame ¶
func (t *TrackConsumer) ReadFrame(ctx context.Context) (*Frame, error)
ReadFrame reads the first timestamped frame of the next group, or (nil, nil) when the track ends. Convenient for one-frame-per-group tracks. Completed empty groups are skipped; a nil frame is track EOF, not an empty group. Cancelling the context cancels this consumer, not just this call: see package docs.
func (*TrackConsumer) RecvDatagram ¶
func (t *TrackConsumer) RecvDatagram(ctx context.Context) (*Datagram, error)
RecvDatagram returns the next best-effort datagram in arrival order, or (nil, nil) when the track ends.
func (*TrackConsumer) RecvGroup ¶
func (t *TrackConsumer) RecvGroup(ctx context.Context) (*GroupConsumer, error)
RecvGroup returns the next group in arrival order (possibly out of sequence), or (nil, nil) when the track ends. Prefer this for live, latency-sensitive consumption.
func (*TrackConsumer) Update ¶
func (t *TrackConsumer) Update(subscription Subscription)
Update changes this subscriber's delivery preferences.
type TrackDemand ¶
type TrackDemand struct {
// contains filtered or unexported fields
}
TrackDemand watches whether a published track has subscribers.
It is weak: holding it neither keeps the track open nor locks the producer, so a wait can park here while the producer keeps publishing. Waits return ErrClosed once the track is released.
func (*TrackDemand) IsUsed ¶
func (d *TrackDemand) IsUsed() bool
IsUsed reports whether the track has at least one active subscriber right now.
func (*TrackDemand) Name ¶
func (d *TrackDemand) Name() string
Name is the name of the track this watches.
type TrackDynamic ¶
type TrackDynamic struct {
// contains filtered or unexported fields
}
TrackDynamic yields uncached groups requested by fetch consumers.
func (*TrackDynamic) Cancel ¶
func (d *TrackDynamic) Cancel()
Cancel stops current and future requested-group waits.
func (*TrackDynamic) RequestedGroup ¶
func (d *TrackDynamic) RequestedGroup(ctx context.Context) (*GroupRequest, error)
RequestedGroup waits for the next uncached group request.
func (*TrackDynamic) Requests ¶
func (d *TrackDynamic) Requests(ctx context.Context) iter.Seq2[*GroupRequest, error]
Requests ranges over uncached group requests until the dynamic source ends.
type TrackInfo ¶
type TrackInfo = ffi.MoqTrackInfo
TrackInfo holds publisher-side track properties: priority, ordering, max age, and timescale. A zero Priority is the least urgent, not the default; set 127 for the midpoint a nil TrackInfo uses.
type TrackProducer ¶
type TrackProducer struct {
// contains filtered or unexported fields
}
TrackProducer writes arbitrary byte payloads with no codec required.
func (*TrackProducer) Abort ¶
func (t *TrackProducer) Abort(errorCode uint16) error
Abort closes the track with an application error code.
func (*TrackProducer) AppendDatagram ¶
func (t *TrackProducer) AppendDatagram(frame Frame) (uint64, error)
AppendDatagram sends frame as a best-effort datagram and returns the sequence number assigned to it. Payloads are capped at 1200 bytes. There is no stream fallback.
func (*TrackProducer) AppendGroup ¶
func (t *TrackProducer) AppendGroup() (*GroupProducer, error)
AppendGroup starts a new group; write frames into it, then Finish.
func (*TrackProducer) Consume ¶
func (t *TrackProducer) Consume(subscription *Subscription) (*TrackConsumer, error)
Consume reads directly from this producer's track. subscription tunes delivery (delivery priority, group range); pass nil for defaults.
func (*TrackProducer) CreateGroup ¶
func (t *TrackProducer) CreateGroup(sequence uint64) (*GroupProducer, error)
CreateGroup creates a group with an explicit sequence number.
func (*TrackProducer) Demand ¶
func (t *TrackProducer) Demand() (*TrackDemand, error)
Demand returns a watch-only handle to whether the track has subscribers.
func (*TrackProducer) Dynamic ¶
func (t *TrackProducer) Dynamic() (*TrackDynamic, error)
Dynamic serves fetches for groups that are not currently cached.
func (*TrackProducer) Finish ¶
func (t *TrackProducer) Finish() error
Finish ends the track at the live edge. The handle remains so Abort can still run.
func (*TrackProducer) FinishAt ¶
func (t *TrackProducer) FinishAt(finalSequence uint64) error
FinishAt declares the exclusive final group sequence ahead of the live edge. The producer remains open for groups below the boundary.
func (*TrackProducer) Unused ¶
func (t *TrackProducer) Unused(ctx context.Context) error
Unused blocks until the track has no active subscribers. Prefer Demand.
func (*TrackProducer) Used ¶
func (t *TrackProducer) Used(ctx context.Context) error
Used blocks until the track has at least one active subscriber. Prefer Demand.
func (*TrackProducer) WriteFrame ¶
func (t *TrackProducer) WriteFrame(frame Frame) error
WriteFrame writes frame as a single-frame group.
type TrackRequest ¶
type TrackRequest struct {
// contains filtered or unexported fields
}
TrackRequest is a subscriber-requested track that has not been accepted yet.
func (*TrackRequest) Abort ¶
func (r *TrackRequest) Abort(errorCode uint16) error
Abort rejects the request with an application error code.
func (*TrackRequest) Accept ¶
func (r *TrackRequest) Accept(info *TrackInfo) (*TrackProducer, error)
Accept accepts the request as a raw track. For media, use PublishAudioOnTrack or PublishVideoOnTrack.
func (*TrackRequest) Dynamic ¶
func (r *TrackRequest) Dynamic() (*TrackDynamic, error)
Dynamic creates a fetch handler before accepting this requested track.
func (*TrackRequest) Name ¶
func (r *TrackRequest) Name() (string, error)
Name is the requested track name.
type Transport ¶
type Transport = ffi.MoqTransport
Transport is the network transport carrying an incoming session.
type Video ¶
Video describes one catalog rendition, including whether the publisher recommends temporarily avoiding it.
type VideoCodec ¶
type VideoCodec = ffi.MoqVideoCodec
VideoCodec identifies a published video track's codec: H.264 or H.265.
type VideoConsumer ¶
type VideoConsumer struct {
// contains filtered or unexported fields
}
VideoConsumer is a stream of decoded video frames.
func (*VideoConsumer) Frames ¶
func (v *VideoConsumer) Frames(ctx context.Context) iter.Seq2[*VideoDecodedFrame, error]
Frames ranges over decoded frames until the track ends or the loop breaks.
func (*VideoConsumer) Next ¶
func (v *VideoConsumer) Next(ctx context.Context) (*VideoDecodedFrame, error)
Next returns the next decoded frame, or (nil, nil) when the track ends.
type VideoDecodedFrame ¶
type VideoDecodedFrame = ffi.MoqVideoDecodedFrame
VideoDecodedFrame is one decoded video frame: packed pixels, the layout they are in, their dimensions, and a timestamp in microseconds.
type VideoDecoderOutput ¶
type VideoDecoderOutput = ffi.MoqVideoDecoderOutput
VideoDecoderOutput configures what DecodeVideo delivers: an optional pixel format and resize, plus a max age.
type VideoEncoderInput ¶
type VideoEncoderInput = ffi.MoqVideoEncoderInput
VideoEncoderInput declares the pixel layout, resolution, and framerate of frames written to a video producer.
type VideoEncoderKind ¶
type VideoEncoderKind = ffi.MoqVideoEncoderKind
VideoEncoderKind selects the encoder implementation. Build one with AutoEncoder, HardwareEncoder, SoftwareEncoder, or NamedEncoder.
func AutoEncoder ¶
func AutoEncoder() VideoEncoderKind
AutoEncoder prefers a platform hardware encoder, falling back to software.
func HardwareEncoder ¶
func HardwareEncoder() VideoEncoderKind
HardwareEncoder requires a hardware encoder, failing if none is available.
func NamedEncoder ¶
func NamedEncoder(name string) VideoEncoderKind
NamedEncoder selects a specific backend these bindings compile: "videotoolbox" (macOS), "mediafoundation" (Windows), or "openh264" (software, everywhere). Naming one this build lacks fails with a no-encoder error.
func SoftwareEncoder ¶
func SoftwareEncoder() VideoEncoderKind
SoftwareEncoder requires the software encoder (openh264, H.264 only).
type VideoEncoderKindAuto ¶
type VideoEncoderKindAuto = ffi.MoqVideoEncoderKindAuto
VideoEncoderKindAuto is the automatic variant of VideoEncoderKind; build one with AutoEncoder.
type VideoEncoderKindHardware ¶
type VideoEncoderKindHardware = ffi.MoqVideoEncoderKindHardware
VideoEncoderKindHardware is the hardware-only variant of VideoEncoderKind; build one with HardwareEncoder.
type VideoEncoderKindNamed ¶
type VideoEncoderKindNamed = ffi.MoqVideoEncoderKindNamed
VideoEncoderKindNamed is the specific-backend variant of VideoEncoderKind; build one with NamedEncoder.
type VideoEncoderKindSoftware ¶
type VideoEncoderKindSoftware = ffi.MoqVideoEncoderKindSoftware
VideoEncoderKindSoftware is the software-only variant of VideoEncoderKind; build one with SoftwareEncoder.
type VideoEncoderOutput ¶
type VideoEncoderOutput = ffi.MoqVideoEncoderOutput
VideoEncoderOutput configures the video track name, codec, bitrate, keyframe interval, and backend preference.
type VideoFormat ¶
type VideoFormat = ffi.MoqVideoFormat
VideoFormat is a single video codec an importer can parse.
type VideoFrame ¶
type VideoFrame = ffi.MoqVideoFrame
VideoFrame is one raw video frame: pixels in the configured layout plus a presentation timestamp in microseconds.
type VideoHint ¶
type VideoHint = ffi.MoqVideoHint
VideoHint supplies catalog fields a video stream can't reveal itself, such as bitrate, filling only the gaps.
type VideoOption ¶
type VideoOption func(*ffi.MoqVideoInit)
VideoOption configures a video publish.
func WithVideoHint ¶
func WithVideoHint(hint VideoHint) VideoOption
WithVideoHint seeds catalog fields that a video stream cannot reveal itself.
func WithVideoLabel ¶
func WithVideoLabel(label string) VideoOption
WithVideoLabel sets the human-readable rendition name stored in the catalog.
func WithVideoTrack ¶ added in v0.7.3
func WithVideoTrack(track string) VideoOption
WithVideoTrack names the track instead of deriving a unique name from the format. A requested track already has a name, so the OnTrack variant refuses it.
type VideoPixelFormat ¶
type VideoPixelFormat = ffi.MoqVideoPixelFormat
VideoPixelFormat is a CPU pixel layout (I420 or RGBA): written to a VideoProducer, or delivered by DecodeVideo.
type VideoProducer ¶
type VideoProducer struct {
// contains filtered or unexported fields
}
VideoProducer pushes raw pictures and lets a native encoder compress them on the way out.
func (*VideoProducer) Cut ¶
func (v *VideoProducer) Cut() error
Cut starts a new group at the next written frame.
Optional: the encoder keyframes every Gop frames on its own, and each of those cuts a group, so a subscriber can always join without this. Reach for it only to place the boundaries yourself, aligning groups with something the encoder can't see such as a scene change. An error means the selected encoder cannot force a keyframe; nothing is queued and groups keep their interval.
func (*VideoProducer) Demand ¶
func (v *VideoProducer) Demand() (*TrackDemand, error)
Demand returns a watch-only handle to whether the video track has subscribers.
func (*VideoProducer) Finish ¶
func (v *VideoProducer) Finish() error
Finish flushes any frames the codec is holding and finalizes the track.
func (*VideoProducer) Name ¶
func (v *VideoProducer) Name() (string, error)
Name returns the video track's name.
func (*VideoProducer) Reservation ¶
func (v *VideoProducer) Reservation() *Reservation
Reservation returns this encoder's bandwidth reservation, or nil if it was published without an allocator.
func (*VideoProducer) SetBitrate ¶
func (v *VideoProducer) SetBitrate(bitrate uint64) error
SetBitrate retunes the live encoder, in bits per second. Cheap enough to drive from a congestion controller: no keyframe is forced. An error means this backend can't retune while running, which is not fatal; the encoder keeps its current rate.
func (*VideoProducer) Unused ¶
func (v *VideoProducer) Unused(ctx context.Context) error
Unused blocks until the video track has no active subscribers. Prefer Demand.
func (*VideoProducer) Used ¶
func (v *VideoProducer) Used(ctx context.Context) error
Used blocks until the video track has at least one active subscriber. Prefer Demand.
func (*VideoProducer) Write ¶
func (v *VideoProducer) Write(frame VideoFrame) error
Write encodes and publishes one frame in the configured input format. A hardware encoder pipelines, so a call that puts nothing on the wire is normal rather than an error.
type VideoProperties ¶
type VideoProperties = ffi.MoqVideoProperties
VideoProperties holds catalog properties shared by every video rendition; nil fields clear those properties.