distribution

package
v0.1.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 12, 2026 License: MIT Imports: 24 Imported by: 0

Documentation

Overview

Package distribution implements the WebTransport-based viewer delivery layer, including the fan-out relay, MoQ session management, and the HTTP/QUIC server that ties them together. The low-level MoQ wire protocol codec lives in github.com/zsiec/prism/moq.

Index

Constants

View Source
const (
	TrackIDVideo     byte = 0
	TrackIDCaptions  byte = 2
	TrackIDAudioBase byte = 10
)

Track ID constants used to identify media types in the MoQ catalog and session logic. Audio tracks beyond the first use sequential IDs starting at TrackIDAudioBase.

Variables

This section is empty.

Functions

func AudioTrackID

func AudioTrackID(trackIndex int) byte

AudioTrackID converts a zero-based audio track index to its wire track ID.

Types

type AudioInfo

type AudioInfo struct {
	Codec      string
	SampleRate int
	Channels   int
}

AudioInfo holds the audio codec parameters for a single track, derived from the first ADTS frame seen by the demuxer.

type AudioTrackStats

type AudioTrackStats struct {
	TrackIndex  int     `json:"trackIndex"`
	Codec       string  `json:"codec"`
	SampleRate  int     `json:"sampleRate"`
	Channels    int     `json:"channels"`
	Frames      int64   `json:"frames"`
	BitrateKbps float64 `json:"bitrateKbps"`
	PTSErrors   int64   `json:"ptsErrors"`
	TotalBytes  int64   `json:"totalBytes"`
}

AudioTrackStats holds per-track audio metrics for a stream.

type CaptionStats

type CaptionStats struct {
	ActiveChannels []int `json:"activeChannels"`
	TotalFrames    int64 `json:"totalFrames"`
}

CaptionStats tracks closed-caption activity across all channels.

type ControlBroadcaster added in v0.1.1

type ControlBroadcaster struct {
	// contains filtered or unexported fields
}

ControlBroadcaster fans out messages from a single source channel to multiple subscriber channels. Each subscriber gets its own buffered channel; slow subscribers have messages dropped (non-blocking send) rather than blocking other subscribers or the source.

func NewControlBroadcaster added in v0.1.1

func NewControlBroadcaster() *ControlBroadcaster

NewControlBroadcaster creates a ControlBroadcaster ready for use.

func (*ControlBroadcaster) Run added in v0.1.1

func (b *ControlBroadcaster) Run(ctx context.Context, source <-chan []byte)

Run reads from the source channel and fans out each message to all subscribers. It blocks until ctx is cancelled or the source channel is closed. Non-blocking sends: if a subscriber's channel is full, the message is dropped for that subscriber (matching the Viewer drop pattern).

func (*ControlBroadcaster) Subscribe added in v0.1.1

func (b *ControlBroadcaster) Subscribe(id string) <-chan []byte

Subscribe creates a per-subscriber buffered channel and returns it. The caller must call Unsubscribe when done. If a channel already exists for the given id, it is closed and replaced.

func (*ControlBroadcaster) Unsubscribe added in v0.1.1

func (b *ControlBroadcaster) Unsubscribe(id string)

Unsubscribe removes and closes the subscriber's channel. It is safe to call multiple times for the same id.

type DebugProvider

type DebugProvider interface {
	StatsProvider
	PipelineDebug() PipelineDebugStats
	DemuxStats() *DemuxStats
}

DebugProvider extends StatsProvider with lower-level pipeline and demuxer diagnostics, exposed via the /api/streams/{key}/debug endpoint.

type DemuxStats

type DemuxStats struct {
	// contains filtered or unexported fields
}

DemuxStats accumulates stream telemetry from the demuxer in a concurrency-safe manner using atomic counters. It implements the demux.StatsRecorder interface and produces point-in-time Snapshots for the stats API.

Fields are organized by the mutex/mechanism that guards them:

  • Atomic counters: lock-free concurrent reads/writes
  • ptsWrapMu: PTS wrap event log
  • timecodeMu: SMPTE timecode string
  • mu: audio track accumulators, caption channels
  • scte35Mu: SCTE-35 event log
  • bitrateWindowMu: video bitrate sliding window
  • fpsWindowMu: video FPS sliding window
  • videoCodecMu: video codec label

func NewDemuxStats

func NewDemuxStats() *DemuxStats

NewDemuxStats creates a DemuxStats ready for use as a StatsRecorder.

func (*DemuxStats) PTSDebug

func (ds *DemuxStats) PTSDebug() PTSDebugStats

PTSDebug returns a snapshot of PTS debugging information.

func (*DemuxStats) RecordAudioFrame

func (ds *DemuxStats) RecordAudioFrame(trackIdx int, bytes int64, pts int64, sampleRate, channels int)

RecordAudioFrame records an audio frame for the given track, creating the per-track accumulator on first use.

func (*DemuxStats) RecordCaption

func (ds *DemuxStats) RecordCaption(channel int)

RecordCaption records a caption frame on the given channel.

func (*DemuxStats) RecordResolution

func (ds *DemuxStats) RecordResolution(width, height int)

RecordResolution stores the detected video resolution from an SPS.

func (*DemuxStats) RecordSCTE35

func (ds *DemuxStats) RecordSCTE35(event demux.SCTE35Event)

RecordSCTE35 records a SCTE-35 event, maintaining a bounded recent-events window.

func (*DemuxStats) RecordTimecode

func (ds *DemuxStats) RecordTimecode(tc string)

RecordTimecode stores the latest SMPTE 12M timecode string.

func (*DemuxStats) RecordVideoCodec

func (ds *DemuxStats) RecordVideoCodec(codec string)

RecordVideoCodec stores the detected video codec label (e.g. "H.264", "H.265").

func (*DemuxStats) RecordVideoFrame

func (ds *DemuxStats) RecordVideoFrame(bytes int64, isKeyframe bool, pts int64)

RecordVideoFrame records a video frame's size, type, and PTS, updating frame counters, GOP length, bitrate/FPS sliding windows, and PTS continuity.

func (*DemuxStats) Snapshot

Snapshot produces a consistent point-in-time view of all stream statistics.

func (*DemuxStats) VideoBitrateKbps

func (ds *DemuxStats) VideoBitrateKbps() float64

VideoBitrateKbps computes the current video bitrate from a 2-second sliding window of frame sizes.

func (*DemuxStats) VideoFPS

func (ds *DemuxStats) VideoFPS() float64

VideoFPS computes the current frame rate from a 2-second sliding window.

type IngestDebugStats

type IngestDebugStats struct {
	BytesReceived int64  `json:"bytesReceived"`
	ReadCount     int64  `json:"readCount"`
	ConnectedAt   int64  `json:"connectedAt"`
	UptimeMs      int64  `json:"uptimeMs"`
	RemoteAddr    string `json:"remoteAddr"`
}

IngestDebugStats captures SRT ingest connection metrics for the debug API.

type IngestLookup

type IngestLookup func(key string) *IngestDebugStats

IngestLookup resolves a stream key to its ingest debug stats, or nil if the stream is not currently being ingested.

type MoQSession

type MoQSession struct {
	// contains filtered or unexported fields
}

MoQSession manages a single MoQ viewer connection. It implements the Viewer interface so the Relay can fan out frames to it. Internally, it dispatches frames to per-track subscriptions, each with its own write loop and moqWriter.

func NewMoQSession

func NewMoQSession(cfg MoQSessionConfig) *MoQSession

NewMoQSession creates a new MoQ session for the given stream key.

func (*MoQSession) ID

func (m *MoQSession) ID() string

ID returns the unique identifier for this MoQ session.

func (*MoQSession) Run

func (m *MoQSession) Run(ctx context.Context) error

Run starts the MoQ session control loop. It blocks until the session ends.

func (*MoQSession) SendAudio

func (m *MoQSession) SendAudio(frame *media.AudioFrame)

SendAudio dispatches an audio frame to the matching audio subscription.

func (*MoQSession) SendCaptions

func (m *MoQSession) SendCaptions(frame *ccx.CaptionFrame)

SendCaptions dispatches a caption frame to the caption subscription.

func (*MoQSession) SendVideo

func (m *MoQSession) SendVideo(frame *media.VideoFrame)

SendVideo dispatches a video frame to the video subscription if active.

func (*MoQSession) Stats

func (m *MoQSession) Stats() ViewerStats

Stats returns delivery metrics for this MoQ session.

type MoQSessionConfig

type MoQSessionConfig struct {
	ID                 string
	Session            *webtransport.Session
	Control            webtransport.Stream
	StreamKey          string
	Relay              *Relay
	StatsProvider      StatsProviderFunc
	ControlBroadcaster *ControlBroadcaster

	// OnDatagram is called when a WebTransport datagram arrives from a viewer.
	// The callback receives the viewer's stream key and the raw datagram bytes.
	// Called from the session's datagram read goroutine — must not block.
	OnDatagram func(streamKey string, data []byte)
}

MoQSessionConfig holds the parameters for creating a new MoQ session.

type PTSDebugStats

type PTSDebugStats struct {
	FirstVideoPTS int64          `json:"firstVideoPTS"`
	FirstAudioPTS int64          `json:"firstAudioPTS"`
	LastVideoPTS  int64          `json:"lastVideoPTS"`
	LastAudioPTS  int64          `json:"lastAudioPTS"`
	VideoPTSWraps int64          `json:"videoPTSWraps"`
	AudioPTSWraps int64          `json:"audioPTSWraps"`
	RecentWraps   []PTSWrapEvent `json:"recentWraps,omitempty"`
}

PTSDebugStats provides low-level PTS debugging information, including first/last timestamps and wrap events, exposed via the debug API endpoint.

type PTSWrapEvent

type PTSWrapEvent struct {
	Timestamp int64  `json:"ts"`
	Track     string `json:"track"`
	OldPTS    int64  `json:"oldPTS"`
	NewPTS    int64  `json:"newPTS"`
	DeltaMs   int64  `json:"deltaMs"`
}

PTSWrapEvent records a detected PTS wrap-around, which occurs when the 33-bit MPEG-TS PTS counter overflows (every ~26.5 hours).

type PipelineDebugSnapshot

type PipelineDebugSnapshot struct {
	Ingest   *IngestDebugStats  `json:"ingest,omitempty"`
	Demuxer  PTSDebugStats      `json:"demuxer"`
	Pipeline PipelineDebugStats `json:"pipeline"`
	Viewers  []ViewerStats      `json:"viewers"`
}

PipelineDebugSnapshot is the JSON response for /api/streams/{key}/debug, aggregating ingest, demuxer, pipeline, and viewer diagnostics.

type PipelineDebugStats

type PipelineDebugStats struct {
	VideoForwarded  int64 `json:"videoForwarded"`
	AudioForwarded  int64 `json:"audioForwarded"`
	CaptionFwd      int64 `json:"captionForwarded"`
	LastVideoFwdPTS int64 `json:"lastVideoFwdPTS"`
	LastAudioFwdPTS int64 `json:"lastAudioFwdPTS"`
	VideoChanDepth  int   `json:"videoChanDepth"`
	AudioChanDepth  int   `json:"audioChanDepth"`
}

PipelineDebugStats captures frame forwarding counters and channel depths for the demux-to-relay pipeline, useful for diagnosing backpressure.

type Relay

type Relay struct {
	// contains filtered or unexported fields
}

Relay is the fan-out hub for a single stream. It distributes video, audio, and caption frames from the pipeline to all connected MoQ viewers. It also caches the current GOP so that late-joining viewers can start playback immediately from the most recent keyframe, and recent audio frames so that new audio subscribers can pre-fill their buffers.

func NewRelay

func NewRelay() *Relay

NewRelay creates a Relay with no viewers.

func (*Relay) AddViewer

func (r *Relay) AddViewer(session Viewer)

AddViewer replays the cached GOP to the viewer, then registers it for live frame delivery. Replay happens before registration so that BroadcastVideo cannot interleave live frames before the replay completes.

func (*Relay) AudioInfo

func (r *Relay) AudioInfo() AudioInfo

AudioInfo returns the detected audio codec parameters, or sensible defaults if no audio frame has been seen yet.

func (*Relay) AudioTrackCount

func (r *Relay) AudioTrackCount() int

AudioTrackCount returns the number of audio tracks, defaulting to 1.

func (*Relay) BroadcastAudio

func (r *Relay) BroadcastAudio(frame *media.AudioFrame)

BroadcastAudio sends an audio frame to all connected viewers and updates the per-track audio cache for late-joining subscriber replay.

func (*Relay) BroadcastCaptions

func (r *Relay) BroadcastCaptions(frame *ccx.CaptionFrame)

BroadcastCaptions sends a caption frame to all connected viewers.

func (*Relay) BroadcastVideo

func (r *Relay) BroadcastVideo(frame *media.VideoFrame)

BroadcastVideo sends a video frame to all connected viewers and updates the GOP cache. Codec detection is handled by the pipeline via SetVideoInfo.

func (*Relay) BroadcastVideoNoCache added in v0.1.3

func (r *Relay) BroadcastVideoNoCache(frame *media.VideoFrame)

BroadcastVideoNoCache sends a video frame to all connected viewers without storing it in the GOP cache. Use this for streams where every frame is independently decodable (e.g., raw YUV) and GOP caching provides no value.

Because no frame data is retained after this call returns, the caller may safely reuse the frame's WireData buffer on the next call. This eliminates per-frame allocation for high-throughput streams like raw video monitors.

Late-joining viewers on a no-cache relay will not receive a GOP replay; they simply wait for the next frame (~33ms at 30fps).

func (*Relay) RemoveViewer

func (r *Relay) RemoveViewer(id string)

RemoveViewer unregisters a viewer by ID.

func (*Relay) ReplayAudioToChannel

func (r *Relay) ReplayAudioToChannel(trackIndex int, ch chan<- *media.AudioFrame) int

ReplayAudioToChannel sends the cached recent audio frames for the given track index into a channel, pre-filling the subscriber's buffer so playback can start without waiting for new frames from the live edge. Returns the number of frames replayed.

func (*Relay) ReplayFullGOPToChannel

func (r *Relay) ReplayFullGOPToChannel(ch chan<- *media.VideoFrame) int

ReplayFullGOPToChannel sends the entire cached GOP (keyframe + all delta frames) into a channel, bypassing the Viewer interface. The client-side renderer skips to the latest decoded frame, so replaying the full GOP provides immediate decodable content at the live edge. Returns the number of frames replayed.

func (*Relay) SetAudioInfo

func (r *Relay) SetAudioInfo(info AudioInfo)

SetAudioInfo stores the audio codec parameters detected from the first audio frame. Called by the pipeline once ADTS header parsing succeeds.

func (*Relay) SetAudioTrackCount

func (r *Relay) SetAudioTrackCount(count int)

SetAudioTrackCount sets the number of audio tracks discovered by the demuxer, used to advertise available tracks during viewer connection setup.

func (*Relay) SetVideoInfo

func (r *Relay) SetVideoInfo(info VideoInfo)

SetVideoInfo stores the video codec parameters detected from the first keyframe. Called by the pipeline once SPS parsing succeeds.

func (*Relay) VideoInfo

func (r *Relay) VideoInfo() VideoInfo

VideoInfo returns the detected video codec and resolution, or sensible defaults if the first keyframe hasn't arrived yet.

func (*Relay) ViewerCount

func (r *Relay) ViewerCount() int

ViewerCount returns the number of currently connected viewers.

func (*Relay) ViewerStatsAll

func (r *Relay) ViewerStatsAll() []ViewerStats

ViewerStatsAll returns delivery metrics for every connected viewer.

func (*Relay) WaitVideoInfo

func (r *Relay) WaitVideoInfo(ctx context.Context) bool

WaitVideoInfo blocks until the real video codec info is available, or until ctx is cancelled. Returns true if info is ready.

type SCTE35Stats

type SCTE35Stats struct {
	TotalEvents int64               `json:"totalEvents"`
	Recent      []demux.SCTE35Event `json:"recent,omitempty"`
}

SCTE35Stats summarizes SCTE-35 splice event activity for a stream.

type SRTListFunc

type SRTListFunc func() []SRTPullInfo

SRTListFunc returns all active SRT pulls.

type SRTPullFunc

type SRTPullFunc func(address, streamKey, streamID string) error

SRTPullFunc initiates an SRT caller-mode pull from a remote address.

type SRTPullInfo

type SRTPullInfo struct {
	Address   string `json:"address"`
	StreamKey string `json:"streamKey"`
	StreamID  string `json:"streamId,omitempty"`
}

SRTPullInfo describes an active SRT caller-mode pull, returned by the /api/srt-pull GET endpoint.

type SRTStopFunc

type SRTStopFunc func(streamKey string) error

SRTStopFunc stops an active SRT pull by stream key.

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server is the WebTransport/HTTP3 distribution server. It manages relays, pipelines, viewer sessions, and serves both the WebTransport watch endpoints and the REST API.

func NewServer

func NewServer(config ServerConfig) (*Server, error)

NewServer creates a distribution Server with the given configuration. It returns an error if required fields are missing.

func (*Server) APIHandler

func (s *Server) APIHandler() http.Handler

APIHandler returns an http.Handler for the HTTPS REST API, including stream listing, debug endpoints, cert hash, and SRT pull management.

func (*Server) GetPipeline

func (s *Server) GetPipeline(streamKey string) StatsProvider

GetPipeline returns the StatsProvider for a stream key, or nil if not found.

func (*Server) GetRelay

func (s *Server) GetRelay(streamKey string) *Relay

GetRelay returns the Relay for a stream key, or nil if not found.

func (*Server) RegisterStream

func (s *Server) RegisterStream(streamKey string) *Relay

RegisterStream creates a Relay for the given stream key and returns it. If the stream already has a relay, the existing one is returned. For new streams, OnStreamRegistered is called (if set) after releasing the lock. Concurrent calls with the same key are safe (only one creates a relay), but the callback may observe transient inconsistency if a concurrent UnregisterStream for the same key interleaves between the lock release and the callback invocation.

func (*Server) SetPipeline

func (s *Server) SetPipeline(streamKey string, p StatsProvider)

SetPipeline associates a StatsProvider with a stream key. The stream must already be registered via RegisterStream.

func (*Server) Start

func (s *Server) Start(ctx context.Context) error

Start launches the HTTP/3 WebTransport server and blocks until the context is cancelled or a fatal error occurs.

func (*Server) UnregisterStream

func (s *Server) UnregisterStream(streamKey string)

UnregisterStream removes the relay and pipeline for a stream key. If the stream existed, OnStreamUnregistered is called (if set) after releasing the lock. If a concurrent RegisterStream for the same key races with this call, the callback may fire after a new relay has already been registered.

type ServerConfig

type ServerConfig struct {
	Addr         string
	WebDir       string
	Cert         *certs.CertInfo
	StreamLister StreamLister
	IngestLookup IngestLookup
	SRTPull      SRTPullFunc
	SRTStop      SRTStopFunc
	SRTList      SRTListFunc
	ExtraRoutes  func(mux *http.ServeMux)

	// OnStreamRegistered is called after a new stream relay is created
	// and added to the server's stream map. It is NOT called when
	// RegisterStream returns an existing relay for a duplicate key.
	// The callback is invoked outside the server's mutex.
	OnStreamRegistered func(key string, relay *Relay)

	// OnStreamUnregistered is called after a stream is removed from
	// the server's stream map. It is NOT called if the stream key
	// was not present. The callback is invoked outside the server's mutex.
	OnStreamUnregistered func(key string)

	// ControlCh receives JSON-encoded control state. If set, a "control"
	// track is advertised in the MoQ catalog and subscribers receive state
	// updates as JSON objects. Each send produces one MoQ group.
	// Messages are internally broadcast to all connected viewers via
	// ControlBroadcaster.
	ControlCh <-chan []byte

	// OnDatagram is called when a WebTransport datagram arrives from a viewer.
	// The callback receives the viewer's stream key and the raw datagram bytes.
	// Called from the session's datagram read goroutine — must not block.
	OnDatagram func(streamKey string, data []byte)
}

ServerConfig holds the configuration for the distribution Server, including listen addresses, TLS certificate, and callback hooks.

type StatsProvider

type StatsProvider interface {
	StreamSnapshot() StreamSnapshot
}

StatsProvider is implemented by Pipeline to supply stream statistics for the viewer stats overlay and the REST API.

type StatsProviderFunc

type StatsProviderFunc func(streamKey string) StatsProvider

StatsProviderFunc resolves the StatsProvider for a stream key lazily, since the pipeline may not exist when the MoQ session is created.

type StreamFrameWriter

type StreamFrameWriter interface {
	// WriteStreamHeader writes the stream-level header (subgroup header)
	// at the start of a new unidirectional stream.
	WriteStreamHeader(w io.Writer, trackID byte, groupID uint32, timestampMS uint32) error

	// WriteVideoFrame writes a single video frame (header + payload) to w,
	// returning the total bytes written.
	WriteVideoFrame(w io.Writer, frame *media.VideoFrame) (int64, error)

	// WriteAudioFrame writes a single audio frame (header + payload) to w,
	// returning the total bytes written.
	WriteAudioFrame(w io.Writer, data []byte, timestampMS uint32) (int64, error)

	// WriteDataObject writes a single data object (caption, stats JSON,
	// control JSON, etc.) with header + payload to w, returning the total
	// bytes written.
	WriteDataObject(w io.Writer, data []byte, timestampMS uint32) (int64, error)

	// StreamHeaderSize returns the byte size of the stream header written
	// by WriteStreamHeader, used for accurate byte accounting.
	StreamHeaderSize() int64
}

StreamFrameWriter abstracts the wire format used to write media data to WebTransport unidirectional streams. The MoQ writer implements this interface using MoQ Transport subgroup/object framing with LOC extensions.

func NewMoQWriter

func NewMoQWriter(trackAlias uint64, publisherPriority byte) StreamFrameWriter

NewMoQWriter returns a StreamFrameWriter that produces MoQ-compliant data stream framing. trackAlias is a session-scoped identifier for the track, and publisherPriority sets the priority (0=highest, 255=lowest).

type StreamInfo

type StreamInfo struct {
	Key             string `json:"key"`
	Viewers         int    `json:"viewers"`
	Description     string `json:"description,omitempty"`
	VideoCodec      string `json:"videoCodec,omitempty"`
	Width           int    `json:"width,omitempty"`
	Height          int    `json:"height,omitempty"`
	AudioTracks     int    `json:"audioTracks,omitempty"`
	AudioChannels   int    `json:"audioChannels,omitempty"`
	HasCaptions     bool   `json:"hasCaptions,omitempty"`
	CaptionChannels []int  `json:"captionChannels,omitempty"`
	HasSCTE35       bool   `json:"hasScte35,omitempty"`
	Protocol        string `json:"protocol,omitempty"`
	UptimeMs        int64  `json:"uptimeMs,omitempty"`
}

StreamInfo is the JSON-serializable summary of a live stream, returned by the /api/streams list endpoint and used by the multi-stream viewer.

type StreamLister

type StreamLister func() []StreamInfo

StreamLister is a callback that returns the current list of active streams.

type StreamSnapshot

type StreamSnapshot struct {
	Timestamp   int64             `json:"ts"`
	UptimeMs    int64             `json:"uptimeMs"`
	Protocol    string            `json:"protocol"`
	IngestBytes int64             `json:"ingestBytes"`
	IngestKbps  float64           `json:"ingestKbps"`
	Video       VideoStats        `json:"video"`
	Audio       []AudioTrackStats `json:"audio"`
	Captions    CaptionStats      `json:"captions"`
	SCTE35      SCTE35Stats       `json:"scte35"`
	ViewerCount int               `json:"viewerCount"`
	Viewers     []ViewerStats     `json:"viewers,omitempty"`
}

StreamSnapshot is the top-level stats payload sent periodically to viewers over the control stream. It aggregates video, audio, caption, SCTE-35, and viewer metrics into a single JSON-serializable structure.

type VideoInfo

type VideoInfo struct {
	Codec         string
	Width         int
	Height        int
	DecoderConfig []byte // AVCDecoderConfigurationRecord or HEVCDecoderConfigurationRecord
}

VideoInfo holds the video codec string, resolution, and decoder configuration record. Sent to viewers during connection setup so they can configure their WebCodecs decoders immediately without waiting for the first keyframe.

type VideoStats

type VideoStats struct {
	Codec         string  `json:"codec"`
	Width         int     `json:"width"`
	Height        int     `json:"height"`
	TotalFrames   int64   `json:"totalFrames"`
	KeyFrames     int64   `json:"keyFrames"`
	DeltaFrames   int64   `json:"deltaFrames"`
	CurrentGOPLen int     `json:"currentGOPLen"`
	BitrateKbps   float64 `json:"bitrateKbps"`
	FrameRate     float64 `json:"frameRate"`
	PTSErrors     int64   `json:"ptsErrors"`
	TotalBytes    int64   `json:"totalBytes"`
	Timecode      string  `json:"timecode,omitempty"`
}

VideoStats holds point-in-time video metrics for a stream, serialized as JSON in stats snapshots sent to viewers over the control stream.

type Viewer

type Viewer interface {
	ID() string
	SendVideo(frame *media.VideoFrame)
	SendAudio(frame *media.AudioFrame)
	SendCaptions(frame *ccx.CaptionFrame)
	Stats() ViewerStats
}

Viewer is the interface that a viewer session (single or mux) must implement to receive frames from a Relay.

type ViewerStats

type ViewerStats struct {
	ID             string `json:"id"`
	VideoSent      int64  `json:"videoSent"`
	AudioSent      int64  `json:"audioSent"`
	CaptionSent    int64  `json:"captionSent"`
	VideoDropped   int64  `json:"videoDropped"`
	AudioDropped   int64  `json:"audioDropped"`
	CaptionDropped int64  `json:"captionDropped"`
	BytesSent      int64  `json:"bytesSent"`
	LastVideoTsMS  int64  `json:"lastVideoTsMs,omitempty"`
	LastAudioTsMS  int64  `json:"lastAudioTsMs,omitempty"`
}

ViewerStats captures per-viewer delivery metrics including frame counts and drop rates, used for diagnostics and the stats overlay.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL