{"record":{"id":"d4051022479eb5e6","repo":"AlexxIT/go2rtc","slug":"enable-return-audio-w","errorCode":null,"errorMessage":"enable return audio: %w","messagePattern":"enable return audio: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/wyze/client.go","lineNumber":215,"sourceCode":"\nfunc (c *Client) StartAudio() error {\n\tk10010 := c.buildK10010(MediaTypeAudio, true)\n\t_, err := c.conn.WriteAndWaitIOCtrl(k10010, c.matchHL(KCmdControlChannelResp), 5*time.Second)\n\treturn err\n}\n\nfunc (c *Client) StartIntercom() error {\n\tif c.conn == nil {\n\t\treturn fmt.Errorf(\"connection is nil\")\n\t}\n\n\tif c.conn.IsBackchannelReady() {\n\t\treturn nil\n\t}\n\n\tk10010 := c.buildK10010(MediaTypeReturnAudio, true)\n\tif _, err := c.conn.WriteAndWaitIOCtrl(k10010, c.matchHL(KCmdControlChannelResp), 5*time.Second); err != nil {\n\t\treturn fmt.Errorf(\"enable return audio: %w\", err)\n\t}\n\n\tif c.verbose {\n\t\tfmt.Printf(\"[Wyze] Speaker channel enabled, waiting for readiness...\\n\")\n\t}\n\n\treturn c.conn.AVServStart()\n}\n\nfunc (c *Client) StopIntercom() error {\n\tif c.conn == nil || !c.conn.IsBackchannelReady() {\n\t\treturn nil\n\t}\n\n\tk10010 := c.buildK10010(MediaTypeReturnAudio, false)\n\tc.conn.WriteIOCtrl(k10010)\n\n\treturn c.conn.AVServStop()","sourceCodeStart":197,"sourceCodeEnd":233,"githubUrl":"https://github.com/AlexxIT/go2rtc/blob/c245815e75e2a5fd60b4290f12bfc04e55a984d3/pkg/wyze/client.go#L197-L233","documentation":"StartIntercom sends a K10010 control message to enable return audio and waits up to 5 seconds for the KCmdControlChannelResp IO control reply. If WriteAndWaitIOCtrl fails (write error, timeout, or camera refusing the channel), the error is wrapped with this prefix.","triggerScenarios":"DTLS/AV channel dropped mid-session; camera firmware rejects or ignores the K10010 enable-return-audio request; 5s IO-ctrl timeout expires because the camera is busy or offline; write fails because the underlying socket is closed.","commonSituations":"Camera went offline or lost Wi-Fi during a session; firmware that does not support two-way audio; slow/unreliable networks causing the 5s timeout; calling intercom immediately after connect before the camera is ready.","solutions":["Inspect the wrapped error to distinguish timeout vs write failure; retry StartIntercom after a short delay on timeout.","Verify the camera model supports two-way audio (return audio) and firmware is up to date.","Check network stability; re-establish the session with Dial + doAVLogin if the socket is dead.","Increase patience around the call — check IsBackchannelReady after retry before writing audio."],"exampleFix":"// before\nif err := client.StartIntercom(); err != nil {\n    panic(err)\n}\n\n// after\nif err := client.StartIntercom(); err != nil {\n    // likely timeout or camera offline; reconnect and retry once\n    if derr := client.Dial(); derr == nil {\n        err = client.StartIntercom()\n    }\n    if err != nil {\n        return fmt.Errorf(\"intercom unavailable: %w\", err)\n    }\n}","handlingStrategy":"retry","validationCode":"if !client.IsConnected() {\n    return fmt.Errorf(\"not connected\")\n}","typeGuard":null,"tryCatchPattern":"if err := client.StartIntercom(); err != nil {\n    if errors.Is(err, context.DeadlineExceeded) || strings.Contains(err.Error(), \"enable return audio\") {\n        time.Sleep(2 * time.Second)\n        err = client.StartIntercom()\n    }\n    if err != nil {\n        return fmt.Errorf(\"intercom setup failed: %w\", err)\n    }\n}","preventionTips":["Verify the camera model/firmware supports two-way audio before enabling intercom","Retry once on timeout before surfacing the error","Reconnect (Dial) if the error persists — the tunnel is likely dead"],"tags":["go","timeout","iot","two-way-audio"],"backgroundTag":"request-timeout","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"}