Skip to main content

Documentation Index

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

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

Supported audio formats

StructCodecPayload typeRFC / specEncoderDecoder
format.OpusOpus / MultiOpusdynamic (96–127)RFC 7587YesYes
format.MPEG4AudioMPEG-4 Audio (AAC-HBR)dynamic (96–127)RFC 3640YesYes
format.MPEG4AudioLATMMPEG-4 Audio LATMdynamic (96–127)RFC 3016YesYes
format.G711G.711 PCMU / PCMA0 (PCMU), 8 (PCMA), or dynamicRFC 3551YesYes
format.G722G.7229 (static)RFC 3551YesYes
format.LPCMLinear PCM (L8/L16/L24)10, 11 (static) or dynamicRFC 3190, RFC 3551YesYes
format.AC3AC-3 (Dolby Digital)dynamic (96–127)RFC 4184YesYes
format.MPEG1AudioMPEG-1/2 Audio14 (static)RFC 2250YesYes
format.SpeexSpeexdynamic (96–127)RFC 5574NoNo
format.VorbisVorbisdynamic (96–127)RFC 5215NoNo
format.G726G.726dynamic (96–127)RFC 3551NoNo

Package path: github.com/bluenviron/gortsplib/v5/pkg/formatSpecification: RFC 7587

Struct fields

type Opus struct {
    // RTP payload type (96–127).
    PayloadTyp uint8

    // Number of audio channels (1 = mono, 2 = stereo).
    // Determined from the sprop-stereo fmtp parameter.
    ChannelCount int
}

Playback example

// find the Opus media and format
var forma *format.Opus
medi := desc.FindFormat(&forma)
if medi == nil {
    panic("media not found")
}

// create decoder
rtpDec, err := forma.CreateDecoder()
if err != nil {
    panic(err)
}

_, err = c.Setup(desc.BaseURL, medi, 0, 0)
if err != nil {
    panic(err)
}

// called when a RTP packet arrives
c.OnPacketRTP(medi, forma, func(pkt *rtp.Packet) {
    pts, ok := c.PacketPTS(medi, pkt)
    if !ok {
        log.Printf("waiting for timestamp")
        return
    }

    // extract Opus packets from RTP packets
    op, err := rtpDec.Decode(pkt)
    if err != nil {
        log.Printf("ERR: %v", err)
        return
    }

    log.Printf("received Opus packet with PTS %v size %d", pts, len(op))
})
Package path: github.com/bluenviron/gortsplib/v5/pkg/formatSpecification: RFC 3640

Struct fields

type MPEG4Audio struct {
    // RTP payload type (96–127).
    PayloadTyp uint8

    ProfileLevelID   int

    // Parsed AudioSpecificConfig from the config fmtp parameter.
    // Contains sample rate, channel count, and codec profile.
    Config           *mpeg4audio.AudioSpecificConfig

    SizeLength       int
    IndexLength      int
    IndexDeltaLength int
}

Playback example

// find the MPEG-4 audio media and format
var forma *format.MPEG4Audio
medi := desc.FindFormat(&forma)
if medi == nil {
    panic("media not found")
}

// create decoder
rtpDec, err := forma.CreateDecoder()
if err != nil {
    panic(err)
}

_, err = c.Setup(desc.BaseURL, medi, 0, 0)
if err != nil {
    panic(err)
}

// called when a RTP packet arrives
c.OnPacketRTP(medi, forma, func(pkt *rtp.Packet) {
    pts, ok := c.PacketPTS(medi, pkt)
    if !ok {
        log.Printf("waiting for timestamp")
        return
    }

    // extract access units from RTP packets
    aus, err := rtpDec.Decode(pkt)
    if err != nil {
        log.Printf("ERR: %v", err)
        return
    }

    // one RTP packet may contain multiple access units
    for _, au := range aus {
        log.Printf("received access unit with PTS %v size %d", pts, len(au))
    }
})
The forma.Config field contains the parsed AudioSpecificConfig, including SampleRate and ChannelCount. Check this before configuring any downstream AAC decoder.
Package path: github.com/bluenviron/gortsplib/v5/pkg/formatSpecification: RFC 3551

Struct fields

type G711 struct {
    // RTP payload type.
    // Static: 0 (PCMU) or 8 (PCMA). Dynamic: 96–127.
    PayloadTyp uint8

    // MULaw selects mu-law encoding (PCMU). False selects A-law (PCMA).
    MULaw bool

    // Sample rate in Hz. Typically 8000.
    SampleRate int

    // Number of audio channels.
    ChannelCount int
}

Usage

The standard static payload types (0 = PCMU, 8 = PCMA) are detected automatically from the SDP. Dynamic payload types support non-standard sample rates.
// declare a PCMU stream for recording
forma := &format.G711{
    MULaw:        true, // PCMU
    SampleRate:   8000,
    ChannelCount: 1,
}

// — or detect while playing back —

var forma *format.G711
medi := desc.FindFormat(&forma)
if medi == nil {
    panic("media not found")
}

rtpDec, err := forma.CreateDecoder()
if err != nil {
    panic(err)
}

_, err = c.Setup(desc.BaseURL, medi, 0, 0)
if err != nil {
    panic(err)
}

c.OnPacketRTP(medi, forma, func(pkt *rtp.Packet) {
    pts, ok := c.PacketPTS(medi, pkt)
    if !ok {
        return
    }

    samples, err := rtpDec.Decode(pkt)
    if err != nil {
        log.Printf("ERR: %v", err)
        return
    }

    log.Printf("received G711 samples with PTS %v, size %d", pts, len(samples))
})
Package path: github.com/bluenviron/gortsplib/v5/pkg/formatSpecification: RFC 3190, RFC 3551

Struct fields

type LPCM struct {
    // RTP payload type.
    // Static: 10 (L16 stereo 44100 Hz) or 11 (L16 mono 44100 Hz).
    // Dynamic: 96–127 for L8, L16, or L24 at other rates.
    PayloadTyp uint8

    // Bit depth: 8, 16, or 24.
    BitDepth int

    // Sample rate in Hz.
    SampleRate int

    // Number of audio channels.
    ChannelCount int
}

Usage

// declare a 16-bit stereo 44100 Hz LPCM stream
forma := &format.LPCM{
    PayloadTyp:   96,
    BitDepth:     16,
    SampleRate:   44100,
    ChannelCount: 2,
}

// — or detect while playing back —

var forma *format.LPCM
medi := desc.FindFormat(&forma)
if medi == nil {
    panic("media not found")
}

rtpDec, err := forma.CreateDecoder()
if err != nil {
    panic(err)
}

_, err = c.Setup(desc.BaseURL, medi, 0, 0)
if err != nil {
    panic(err)
}

c.OnPacketRTP(medi, forma, func(pkt *rtp.Packet) {
    pts, ok := c.PacketPTS(medi, pkt)
    if !ok {
        return
    }

    samples, err := rtpDec.Decode(pkt)
    if err != nil {
        log.Printf("ERR: %v", err)
        return
    }

    log.Printf("received LPCM samples with PTS %v, size %d", pts, len(samples))
})
Package path: github.com/bluenviron/gortsplib/v5/pkg/formatSpecification: RFC 4184

Struct fields

type AC3 struct {
    // RTP payload type (96–127).
    PayloadTyp uint8

    // Sample rate in Hz.
    SampleRate int

    // Number of audio channels. Defaults to 6 if omitted in SDP.
    ChannelCount int
}

Usage

var forma *format.AC3
medi := desc.FindFormat(&forma)
if medi == nil {
    panic("media not found")
}

rtpDec, err := forma.CreateDecoder()
if err != nil {
    panic(err)
}

_, err = c.Setup(desc.BaseURL, medi, 0, 0)
if err != nil {
    panic(err)
}

c.OnPacketRTP(medi, forma, func(pkt *rtp.Packet) {
    pts, ok := c.PacketPTS(medi, pkt)
    if !ok {
        return
    }

    frame, err := rtpDec.Decode(pkt)
    if err != nil {
        log.Printf("ERR: %v", err)
        return
    }

    log.Printf("received AC-3 frame with PTS %v, size %d", pts, len(frame))
})
Package path: github.com/bluenviron/gortsplib/v5/pkg/formatSpecification: RFC 3551Static payload type: 9

Struct fields

// G722 has no configurable fields — payload type 9 is fixed by RFC 3551.
type G722 struct{}

Usage

var forma *format.G722
medi := desc.FindFormat(&forma)
if medi == nil {
    panic("media not found")
}

rtpDec, err := forma.CreateDecoder()
if err != nil {
    panic(err)
}

_, err = c.Setup(desc.BaseURL, medi, 0, 0)
if err != nil {
    panic(err)
}

c.OnPacketRTP(medi, forma, func(pkt *rtp.Packet) {
    pts, ok := c.PacketPTS(medi, pkt)
    if !ok {
        return
    }

    samples, err := rtpDec.Decode(pkt)
    if err != nil {
        log.Printf("ERR: %v", err)
        return
    }

    log.Printf("received G722 samples with PTS %v, size %d", pts, len(samples))
})

Formats without built-in encoder/decoder

The following formats are recognized and parsed from SDP, but do not provide CreateEncoder() or CreateDecoder() methods. You must supply your own RTP packetizer and depacketizer.
StructCodecPayload typeRFC
format.SpeexSpeexdynamic (96–127)RFC 5574
format.VorbisVorbisdynamic (96–127)RFC 5215
format.G726G.726dynamic (96–127)RFC 3551
For these formats you can still receive raw RTP packets via OnPacketRTP and implement your own framing logic:
var forma *format.Speex
medi := desc.FindFormat(&forma)
if medi == nil {
    panic("media not found")
}

_, err = c.Setup(desc.BaseURL, medi, 0, 0)
if err != nil {
    panic(err)
}

c.OnPacketRTP(medi, forma, func(pkt *rtp.Packet) {
    // pkt.Payload contains the raw Speex payload — apply your own depacketizer
    log.Printf("received raw Speex packet, payload size %d", len(pkt.Payload))
})

Build docs developers (and LLMs) love