AlexxIT/go2rtc · error

mp4: unsupported codec:

Error message

mp4: unsupported codec: 

What it means

When consuming an MP4 (muxing incoming tracks into the container), MP4Consumer.AddTrack looks up a registered handler for the track's codec (which supplies both the RTP depacketizer and the muxer sample entry). If track.Codec.Name has no matching handler, handler.Handler stays nil and the function returns this error naming the unsupported codec string.

Solutions

  1. Transcode to a supported codec before recording, e.g. `ffmpeg ... -c:v libx264 -c:a aac`, since H.264+AAC/PCMA/PCMU have well-supported MP4 handlers.
  2. Upgrade go2rtc to the latest release — MP4 codec support (H.265, Opus, etc.) grows over time.
  3. Check the exact codec name of the incoming track (log track.Codec.String()) and confirm it matches a supported handler; fix producers that set non-standard codec names.
  4. Use a different consumer/record format (e.g. MPEG-TS or MKV via ffmpeg) that supports the codec if MP4 muxing is not mandatory.

Example fix

// before: recording an unsupported codec name directly
cons := mp4.NewConsumer()
cons.AddTrack(track) // track.Codec = MJPEG -> error

// after: force a supported codec via stream transcoding
stream.PutQuery("video", "h264")
stream.PutQuery("audio", "aac")
cons.AddTrack(track) // track.Codec = h264
Defensive patterns

Strategy: try-catch

Validate before calling

var mp4SupportedCodecs = map[string]bool{"h264": true, "aac": true, "pcma": true, "pcmu": true, "h265": true, "opus": true}
func mp4TrackSupported(track core.Track) bool {
	return mp4SupportedCodecs[strings.ToLower(track.Codec.Name)]
}

Try / catch

cons := mp4.NewConsumer()
if err := cons.AddTrack(track); err != nil && strings.Contains(err.Error(), "mp4: unsupported codec") {
	log.Warnf("%s; starting ffmpeg transcode to h264/aac for recording", err)
	recorder = startFFmpegRecorder(source) // fallback path
}

Prevention

When it happens

Trigger: Calling mp4.NewConsumer and then AddTrack with a track whose codec is not in the supported set (e.g. H.265 with an exotic profile, AV1, VP9, Opus variants, or a codec string the muxer has no box writer for) — or a misnamed codec coming from a source producer.

Common situations: Recording streams from cameras emitting codecs like H.265+ or MJPEG into MP4; browser streams with codecs (AV1/VP9) not mapped in the muxer; older go2rtc version lacking support for a newly added codec; case/name mismatch between producer codec name and the consumer's handler registry.

Related errors


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

Appendix: source

Thrown at pkg/mp4/consumer.go:156

		case core.CodecOpus, core.CodecMP3: // no changes
		case core.CodecPCMA, core.CodecPCMU, core.CodecPCM, core.CodecPCML:
			codec.Name = core.CodecFLAC
			if codec.Channels == 2 {
				// hacky way for support two channels audio
				codec.Channels = 1
				codec.ClockRate *= 2
			}
			handler.Handler = pcm.FLACEncoder(track.Codec.Name, codec.ClockRate, handler.Handler)

		default:
			handler.Handler = nil
		}
	}

	if handler.Handler == nil {
		s := "mp4: unsupported codec: " + track.Codec.String()
		println(s)
		return errors.New(s)
	}

	c.muxer.AddTrack(codec)

	handler.HandleRTP(track)
	c.Senders = append(c.Senders, handler)

	return nil
}

func (c *Consumer) WriteTo(wr io.Writer) (int64, error) {
	if len(c.Senders) == 1 && c.Senders[0].Codec.IsAudio() {
		c.start = true
	}

	init, err := c.muxer.GetInit()
	if err != nil {
		return 0, err

View on GitHub (pinned to c245815e75)