pion/webrtc · error

invalid Opus packet

Error message

invalid Opus packet

What it means

errInvalidOpusPacket is returned by opusPacketSampleCount when an RTP payload is not a parseable Opus packet: either the payload is empty or the computed sample count (samples per frame × frame count from the TOC byte) exceeds maxOpusPacketSamples. The writer needs a valid duration per packet to advance the Ogg granule position.

Source

Thrown at pkg/media/oggwriter/oggwriter.go:55

	idPageSignature                    = "OpusHead"
	commentPageSignature               = "OpusTags"
	defaultVendor                      = "pion"
	pageHeaderSignature                = "OggS"
	pageHeaderSize                     = 27
	maxOggPageSegments                 = 255
	noGranulePosition                  = ^uint64(0)
	maxUint32Length                    = uint64(1<<32 - 1)
)

var (
	errFileNotOpened        = errors.New("file not opened")
	errOutputNotOpened      = errors.New("output not opened")
	errInvalidNilPacket     = errors.New("invalid nil packet")
	errDuplicateTrackSSRC   = errors.New("duplicate Ogg track SSRC")
	errDuplicateTrackSerial = errors.New("duplicate Ogg track serial")
	errTracksStarted        = errors.New("cannot add Ogg tracks after writing has started")
	errPacketSSRCMismatch   = errors.New("RTP packet SSRC does not match Ogg track SSRC")
	errInvalidOpusPacket    = errors.New("invalid Opus packet")
	errInvalidChannelCount  = errors.New("invalid channel count")
	errInvalidChannelMap    = errors.New("invalid channel mapping")
	errInvalidOpusTags      = errors.New("invalid OpusTags")
)

type pageRewriter interface {
	io.Seeker
	io.WriterAt
}

type writerConfig struct {
	sampleRate     uint32
	channelMapping channelMapping
	pageRewriter   pageRewriter
	opusTags       OpusTags
}

type trackConfig struct {

View on GitHub (pinned to 8c25dc09fa)

Solutions

  1. Drop packets with empty payloads before calling WriteRTP
  2. Validate the Opus TOC byte / frame count before writing
  3. Confirm the RTP stream is actually Opus-encoded (correct payload type)
  4. Update the source encoder — it is producing out-of-spec Opus packets

Example fix

// before
track.WriteRTP(pkt) // pkt.Payload is empty -> errInvalidOpusPacket
// after
if len(pkt.Payload) > 0 {
    if err := track.WriteRTP(pkt); err != nil {
        log.Printf("skip packet: %v", err)
    }
}
Defensive patterns

Strategy: validation

Validate before calling

func writableOpusPayload(payload []byte) bool {
    if len(payload) == 0 {
        return false
    }
    // TOC byte: config(5) | stereo(1) | code(2)
    code := payload[0] & 0x03
    if code == 3 && len(payload) < 2 { // code 3 requires frame count byte
        return false
    }
    return true
}

Try / catch

err := track.WriteRTP(pkt)
if err != nil && strings.Contains(err.Error(), "invalid Opus packet") {
    log.Printf("dropping malformed opus packet: %v", err)
    return nil // drop, keep recording
}

Prevention

When it happens

Trigger: Writing an RTP packet whose payload is empty; an Opus packet whose TOC-implied frame count yields a sample count above the maximum allowed per packet.

Common situations: Corrupt or truncated RTP payloads from a lossy network; a codec misconfiguration sending non-Opus data to the writer; hand-crafted packets in tests that violate Opus TOC rules; writing keep-alive/DTMF-style empty payloads.

Related errors


AI-assisted analysis of pion/webrtc@8c25dc09fa (2026-09-03). Data as JSON: /api/errors/a20777d604a1e5a9. Report an issue: GitHub.