AlexxIT/go2rtc · error

mpegts: wrong adaptation size

Error message

mpegts: wrong adaptation size

What it means

The MPEG-TS demuxer validates the adaptation field length byte in every transport packet header. The spec limits the adaptation field to the bytes remaining after the fixed 4-byte TS header plus the 1-byte length field; go2rtc enforces this as adSize <= PacketSize-6 (184). If the packet claims a longer adaptation field, the stream is corrupt or misaligned, so ReadPacket fails rather than skipping garbage.

Solutions

  1. Re-sync the demuxer to a valid 0x47 sync byte before reading packets (seek/skip to the next sync byte and retry ReadPacket).
  2. Verify the input source integrity: re-download or re-record the .ts file, or check network loss on multicast inputs.
  3. Ensure you start demuxing at a packet boundary (offset 0 or multiple of 188/192 bytes), not mid-packet.
  4. If the source is a known-buggy muxer, remux the stream with ffmpeg (`ffmpeg -i in.ts -c copy out.ts`) to normalize adaptation fields.

Example fix

// before: blind loop reading packets
for {
    _, _, err := demux.ReadPacket()
    if err != nil { return err }
}
// after: resync on corruption
for {
    if _, _, err := demux.ReadPacket(); err != nil {
        if err := resyncToSyncByte(reader); err != nil { return err }
        continue
    }
    ...
}
Defensive patterns

Strategy: retry

Validate before calling

// Peek for TS sync byte before demuxing
buf, _ := bufio.NewReader(r).Peek(188)
if len(buf) > 0 && buf[0] != 0x47 {
    // not aligned; resync to next 0x47 before ReadPacket
}

Try / catch

for {
    pid, pusi, err := demux.ReadPacket()
    if err != nil {
        if strings.Contains(err.Error(), "wrong adaptation size") {
            if resyncErr := resyncToSyncByte(r); resyncErr != nil { return resyncErr }
            continue
        }
        return err
    }
}

Prevention

When it happens

Trigger: Reading a TS packet whose adaptation_field_length byte (byte 4 of the packet, when adaptation_field_flag is set) exceeds 184 bytes, via mpegts.Demuxer.ReadPacket.

Common situations: Corrupt or truncated .ts files, packet loss in multicast/IPTS streams, byte-offset misalignment when starting demux mid-stream (not starting at a 0x47 sync byte boundary), or malformed streams produced by buggy muxers.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of AlexxIT/go2rtc@c245815e75 (2026-09-07). Data as JSON: /api/errors/8e16fcd60163f934. Report an issue: GitHub.

Appendix: source

Thrown at pkg/mpegts/demuxer.go:90

	sb := d.readByte() // Sync byte
	if sb != SyncByte {
		return 0, false, errors.New("mpegts: wrong sync byte")
	}

	_ = d.readBit()        // Transport error indicator (TEI)
	pusi := d.readBit()    // Payload unit start indicator (PUSI)
	_ = d.readBit()        // Transport priority
	pid = d.readBits16(13) // PID

	_ = d.readBits(2) // Transport scrambling control (TSC)
	af := d.readBit() // Adaptation field
	_ = d.readBit()   // Payload
	_ = d.readBits(4) // Continuity counter

	if af != 0 {
		adSize := d.readByte() // Adaptation field length
		if adSize > PacketSize-6 {
			return 0, false, errors.New("mpegts: wrong adaptation size")
		}
		d.skip(adSize)
	}

	return pid, pusi != 0, nil
}

func (d *Demuxer) skip(i byte) {
	d.pos += i
}

func (d *Demuxer) readBytes(i byte) []byte {
	d.pos += i
	return d.buf[d.pos-i : d.pos]
}

func (d *Demuxer) readPSIHeader() {
	// https://en.wikipedia.org/wiki/Program-specific_information#Table_Sections

View on GitHub (pinned to c245815e75)