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
- Drop packets with empty payloads before calling WriteRTP
- Validate the Opus TOC byte / frame count before writing
- Confirm the RTP stream is actually Opus-encoded (correct payload type)
- 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
- Drop empty RTP payloads before writing
- Validate the Opus TOC byte and frame count
- Ensure the negotiated payload type is Opus
- Sanitize/repair packets from lossy transports before writing
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
- bad opus tags signature
- payload for id page must be 19 bytes
- invalid nil packet
- duplicate Ogg track serial
- RTP packet SSRC does not match Ogg track SSRC
AI-assisted analysis of pion/webrtc@8c25dc09fa (2026-09-03).
Data as JSON: /api/errors/a20777d604a1e5a9.
Report an issue: GitHub.