{"record":{"id":"15abd9da33d61794","repo":"AlexxIT/go2rtc","slug":"wyze-no-audio-codec-detected-from-camera","errorCode":null,"errorMessage":"wyze: no audio codec detected from camera","messagePattern":"wyze: no audio codec detected from camera","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/wyze/backchannel.go","lineNumber":20,"sourceCode":"\nimport (\n\t\"fmt\"\n\n\t\"github.com/AlexxIT/go2rtc/pkg/aac\"\n\t\"github.com/AlexxIT/go2rtc/pkg/core\"\n\t\"github.com/AlexxIT/go2rtc/pkg/tutk\"\n\t\"github.com/pion/rtp\"\n)\n\nfunc (p *Producer) AddTrack(media *core.Media, codec *core.Codec, track *core.Receiver) error {\n\tif err := p.client.StartIntercom(); err != nil {\n\t\treturn fmt.Errorf(\"wyze: failed to enable intercom: %w\", err)\n\t}\n\n\t// Get the camera's audio codec info (what it sent us = what it accepts)\n\ttutkCodec, sampleRate, channels := p.client.GetBackchannelCodec()\n\tif tutkCodec == 0 {\n\t\treturn fmt.Errorf(\"wyze: no audio codec detected from camera\")\n\t}\n\n\tif p.client.verbose {\n\t\tfmt.Printf(\"[Wyze] Intercom enabled, using codec=0x%04x rate=%d ch=%d\\n\", tutkCodec, sampleRate, channels)\n\t}\n\n\tsender := core.NewSender(media, track.Codec)\n\n\t// Track our own timestamp - camera expects timestamps starting from 0\n\t// and incrementing by frame duration in microseconds\n\tvar timestamp uint32 = 0\n\tsamplesPerFrame := tutk.GetSamplesPerFrame(tutkCodec)\n\tframeDurationUS := samplesPerFrame * 1000000 / sampleRate\n\n\tsender.Handler = func(pkt *rtp.Packet) {\n\t\tif err := p.client.WriteAudio(tutkCodec, pkt.Payload, timestamp, sampleRate, channels); err == nil {\n\t\t\tp.Send += len(pkt.Payload)\n\t\t}","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/AlexxIT/go2rtc/blob/c245815e75e2a5fd60b4290f12bfc04e55a984d3/pkg/wyze/backchannel.go#L2-L38","documentation":"Returned by the Wyze Producer's AddTrack during backchannel setup. After intercom is enabled, it queries the camera's audio codec via GetBackchannelCodec(); a codec value of 0 means the camera never reported what audio format it accepts, so go2rtc cannot negotiate the upstream (talk) track and aborts.","triggerScenarios":"AddTrack on a Wyze stream when GetBackchannelCodec() returns 0: intercom succeeded but no audio frames/codec info arrived from the camera, the TUTK backchannel channel was not opened, or the firmware does not expose codec metadata.","commonSituations":"Camera model whose firmware omits backchannel codec info; intercom mode toggled but the audio stream never started; race where codec query runs before the camera answers; unsupported or very old firmware.","solutions":["Wait/check that the camera actually starts sending audio after intercom (packet capture on the TUTK channel)","Update camera firmware; older builds may not report backchannel codec info","Verify the model supports two-way audio at all (test talk in the Wyze app)","Retry the session — a race between intercom enable and codec query can yield 0 on first attempt","If the camera only ever returns 0, use a one-way stream and skip backchannel setup"],"exampleFix":"// before\n// immediately querying codec right after StartIntercom\ncodec, rate, ch := client.GetBackchannelCodec() // 0 -> error\n// after\n// ensure intercom session is established / retry with timeout\ndeadline := time.After(3 * time.Second)\nfor codec == 0 {\n    select {\n    case <-deadline:\n        return errors.New(\"wyze: no backchannel codec from camera\")\n    case <-time.After(100 * time.Millisecond):\n        codec, rate, ch = client.GetBackchannelCodec()\n    }\n}","handlingStrategy":"retry","validationCode":"// Go: confirm codec before building the track\nif codec, _, _ := client.GetBackchannelCodec(); codec == 0 {\n    return errors.New(\"no backchannel codec yet; wait or use one-way stream\")\n}","typeGuard":"func hasBackchannelCodec(codec uint16) bool { return codec != 0 }","tryCatchPattern":"if err := producer.AddTrack(media, codec, track); err != nil {\n    if strings.Contains(err.Error(), \"no audio codec detected\") {\n        time.Sleep(500 * time.Millisecond) // race: retry once\n        return producer.AddTrack(media, codec, track)\n    }\n    return err\n}","preventionTips":["Add small delay/retry between intercom enable and codec query","Keep firmware current so codec metadata is exposed","Verify the model supports talk-back before wiring backchannel","Fall back to one-way streaming when codec stays 0"],"tags":["wyze","backchannel","codec","negotiation"],"backgroundTag":"codec-negotiation-failed","analyzedSha":"c245815e75e2a5fd60b4290f12bfc04e55a984d3","analyzedAt":"2026-09-07T11:47:02.965Z","contentChangedAt":"2026-09-07T11:47:02.965Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}