pion/webrtc · error
%w: ambisonics family type 3 is not supported
Error message
%w: ambisonics family type 3 is not supported
What it means
ParseOpusHead refuses to parse an Opus identification header whose ChannelMappingFamily byte is 3 (ambisonics projection). The library supports family 0 (RTP/vorbis order), 1/255 (discrete), and 2 (extended mapping); family 3 requires ambisonics channel ordering the reader does not implement. The returned error wraps errUnsupportedChannelMappingFamily so callers can detect it with errors.Is.
Source
Thrown at pkg/media/oggreader/oggreader.go:245
header.PreSkip = binary.LittleEndian.Uint16(payload[10:12])
header.SampleRate = binary.LittleEndian.Uint32(payload[12:16])
header.OutputGain = binary.LittleEndian.Uint16(payload[16:18])
header.ChannelMap = payload[18]
return header
}
// parseChannelMapping parses channel mapping data based on the channel map family.
// https://datatracker.ietf.org/doc/html/rfc7845#section-5.1.1
// family mapping of 2 and 3 are defined in https://datatracker.ietf.org/doc/html/rfc8486
func parseChannelMapping(header *OggHeader, payload []byte) error {
switch header.ChannelMap {
case 0:
return validatePayloadLength(payload, idPageBasePayloadLength)
case 1, 2, 255:
return parseExtendedChannelMapping(header, payload)
case 3:
return fmt.Errorf("%w: ambisonics family type 3 is not supported", errUnsupportedChannelMappingFamily)
default:
return errUnsupportedChannelMappingFamily
}
}
func validatePayloadLength(payload []byte, expectedLen int) error {
if len(payload) != expectedLen {
return errBadIDPageLength
}
return nil
}
func parseExtendedChannelMapping(header *OggHeader, payload []byte) error {
expectedPayloadLen := 21 + int(header.Channels)
if err := validatePayloadLength(payload, expectedPayloadLen); err != nil {
return err
}View on GitHub (pinned to 8c25dc09fa)
Solutions
- Remap or transcode the stream to channel mapping family 1 or 2 before feeding it to ParseOpusHead (e.g. with ffmpeg -c:a libopus -mapping_family 1 or 0).
- If ambisonics metadata is not needed, patch parseChannelMapping to treat family 3 as discrete channels (route it to parseExtendedChannelMapping) and document the limitation.
- Handle the error at the call site: check errors.Is(err, oggreader.ErrUnsupportedChannelMappingFamily) and skip or reject the stream gracefully.
Example fix
// before # ffmpeg -i in.opus -c copy out.opus // after # force a supported channel mapping family # ffmpeg -i in.opus -c:a libopus -mapping_family 1 out.opus
Defensive patterns
Strategy: validation
Validate before calling
func isAmbisonicsOpus(head []byte) bool {
return len(head) > 18 && head[0]=='O' && head[1]=='p' && head[2]=='u' && head[3]=='s' &&
head[4]=='H' && head[5]=='e' && head[6]=='a' && head[7]=='d' && head[18] == 3
}
// skip or transcode when isAmbisonicsOpus(packet) is true Type guard
func isSupportedOpusHead(p []byte) bool {
if len(p) < 19 || string(p[:8]) != "OpusHead" {
return false
}
switch p[18] {
case 0, 1, 2, 255:
return true
default:
return false
}
} Prevention
- Before parsing, inspect the ChannelMappingFamily byte at offset 18 of OpusHead and reject family 3 upstream.
- Configure encoders/transcoders with -mapping_family 0 or 1 unless ambisonics is explicitly required.
- Add a test with a family-3 OpusHead fixture so the rejection path is exercised.
- Match errors.Is(err, oggreader.ErrUnsupportedChannelMappingFamily) to distinguish this from corrupt-data errors.
When it happens
Trigger: Calling oggreader.ParseOpusHead on an OpusHead packet whose byte at offset 18 (ChannelMappingFamily) equals 3; readOpusHeader reaches parseChannelMapping and hits the case 3 branch.
Common situations: Decoding ambisonic/VR surround streams (e.g. YouTube 360 audio, B-format first-order ambisonics Opus streams); working with recently standardized ambisonics Opus content that older tooling, including this reader, does not yet support.
Related errors
- bad opus tags signature
- unsupported channel mapping family
- %w: payload too short
- %w: expected %q, got %q
- %w: payload too short for vendor string
AI-assisted analysis of pion/webrtc@8c25dc09fa (2026-09-03).
Data as JSON: /api/errors/906a20fa244536ea.
Report an issue: GitHub.