Description
Playback via media_player.play_media (and TTS) fails immediately with:
AttributeError: 'bytes' object has no attribute 'encode'. Did you mean: 'decode'?
The error occurs regardless of the audio source — it happens with TTS (tts.speak) as well as with a local MP3 via media-source://. So it is not audio-related, it happens during the Baichuan talk handshake.
Environment
|
|
| Home Assistant |
2026.x (Python 3.14) |
| reolink_aio |
version bundled with current HA core |
| Integration |
installed via HACS from this repo |
| Camera |
Reolink, TrackMix & E1 Pro |
Full traceback
File "/config/custom_components/reolink_talk/media_player.py", line 168, in async_play_media
await self._play_bytes(media_bytes)
File "/config/custom_components/reolink_talk/media_player.py", line 288, in _play_bytes
await talk_playback(bc, self._target.channel, adpcm_bytes, ability, block_align=full_block_size)
File "/config/custom_components/reolink_talk/talk.py", line 791, in talk_playback
await send_talk_binary(bc, channel, payload, enc_type=enc_used)
File "/config/custom_components/reolink_talk/talk.py", line 609, in send_talk_binary
enc_ext = bc._aes_encrypt(ensure_bytes(ext, name="extension XML"))
File "/usr/local/lib/python3.14/site-packages/reolink_aio/baichuan/baichuan.py", line 445, in _aes_encrypt
return cipher.encrypt(body.encode("utf8"))
AttributeError: 'bytes' object has no attribute 'encode'
Root cause
talk.py line 609 passes the extension XML through ensure_bytes() before handing it to reolink_aio's _aes_encrypt():
enc_ext = bc._aes_encrypt(ensure_bytes(ext, name="extension XML"))
However, _aes_encrypt() in reolink_aio/baichuan/baichuan.py (line 445) expects a str and calls .encode("utf8") internally:
return cipher.encrypt(body.encode("utf8"))
So the value is converted to bytes twice. Since _aes_encrypt() lives in the official upstream library, it cannot be patched locally — the conversion has to be removed on this side.
Fix that works for me
Changing line 609 in talk.py to pass a str instead resolves the issue:
enc_ext = bc._aes_encrypt(ext.decode("utf-8") if isinstance(ext, bytes) else ext)
After a restart, both TTS and local MP3 playback work correctly.
Note
There may be other call sites of _aes_encrypt() with the same pattern that I haven't triggered yet — might be worth grepping for _aes_encrypt and ensure_bytes across the codebase.
Happy to test a patch. Thanks for building and maintaining this integration!
Description
Playback via
media_player.play_media(and TTS) fails immediately with:AttributeError: 'bytes' object has no attribute 'encode'. Did you mean: 'decode'?The error occurs regardless of the audio source — it happens with TTS (
tts.speak) as well as with a local MP3 viamedia-source://. So it is not audio-related, it happens during the Baichuan talk handshake.Environment
Full traceback
Root cause
talk.pyline 609 passes the extension XML throughensure_bytes()before handing it toreolink_aio's_aes_encrypt():However,
_aes_encrypt()inreolink_aio/baichuan/baichuan.py(line 445) expects a str and calls.encode("utf8")internally:So the value is converted to bytes twice. Since
_aes_encrypt()lives in the official upstream library, it cannot be patched locally — the conversion has to be removed on this side.Fix that works for me
Changing line 609 in
talk.pyto pass astrinstead resolves the issue:After a restart, both TTS and local MP3 playback work correctly.
Note
There may be other call sites of
_aes_encrypt()with the same pattern that I haven't triggered yet — might be worth grepping for_aes_encryptandensure_bytesacross the codebase.Happy to test a patch. Thanks for building and maintaining this integration!