可以xiaozhi-esp32里配置OTA URL的位置是idf.py menuconfig → Xiaozhi Assistant → Default OTA URL这个配置对应源码里的CONFIG_OTA_URL。项目的main/Kconfig.projbuild里定义了OTA_URL默认值是官方 OTA 地址说明里也写明该 URL 用于检查新固件和服务器地址。(GitHub)1. OTA URL 不是 WebSocket URL这里容易搞错。OTA_URL应该填OTA 配置接口地址不是直接填wss://.../xiaozhi/v1/。比如你自己部署的服务是https://your-domain.com/xiaozhi/ota/那么Default OTA URL就填https://your-domain.com/xiaozhi/ota/固件启动后会先请求这个 OTA 接口然后 OTA 接口再返回{ websocket: { url: wss://your-domain.com/xiaozhi/v1/, token: your_token, version: 3 }, firmware: { version: 1.0.0, url: }, server_time: { timestamp: 1710000000000, timezone_offset: 480 } }源码里CheckVersion()会访问GetCheckVersionUrl()再解析 OTA 返回的activation、mqtt、websocket、server_time、firmware等字段。(GitHub)2. 推荐配置方法方法 A用 menuconfig 配置idf.py menuconfig进入Xiaozhi Assistant → Default OTA URL改成https://你的服务器域名/xiaozhi/ota/然后重新编译烧录idf.py build idf.py flash monitor项目 README 里建议使用 ESP-IDF 5.4 或以上版本。(GitHub)3. 如果改了不生效重点看这三个地方第一sdkconfig已经生成直接改Kconfig.projbuild不一定生效Kconfig.projbuild里的default只是在首次生成sdkconfig时生效。如果工程里已经有sdkconfig你直接改main/Kconfig.projbuild可能不会改变最终编译值。正确做法是改sdkconfig找到CONFIG_OTA_URLhttps://api.tenclass.net/xiaozhi/ota/改成CONFIG_OTA_URLhttps://你的服务器域名/xiaozhi/ota/或者重新跑idf.py menuconfig第二设备 NVS 里可能已经保存了旧的ota_url源码里实际优先级是NVS 中 wifi/ota_url 优先于 CONFIG_OTA_URL也就是说如果 NVS 里已经保存过ota_url固件会优先用 NVS 里的地址只有 NVS 为空时才使用CONFIG_OTA_URL。源码里GetCheckVersionUrl()先读Settings(wifi).GetString(ota_url)为空时才 fallback 到CONFIG_OTA_URL。(GitHub)所以建议改完 OTA URL 后执行一次idf.py erase-flash idf.py flash monitor或者至少确认 NVS 没有旧配置。第三自建 OTA 接口必须返回 WebSocket / MQTT 配置固件不是只靠OTA_URL工作。它启动流程是联网成功 → 创建 OTA 对象 → CheckAssetsVersion() → CheckNewVersion() → InitializeProtocol()InitializeProtocol()会根据 OTA 返回内容决定使用 MQTT 还是 WebSocket如果 OTA 返回mqtt就走 MQTT如果返回websocket就走 WebSocket。(GitHub)WebSocket 协议实际读取的是websocket.url websocket.token websocket.version源码在WebsocketProtocol::OpenAudioChannel()里从Settings(websocket)读取url、token、version然后连接 WebSocket 服务。(GitHub)4. 最小可用 OTA 返回示例如果你只想走 WebSocketOTA 接口最少建议返回{ websocket: { url: wss://your-domain.com/xiaozhi/v1/, token: , version: 3 }, firmware: { version: 1.0.0, url: } }如果当前固件版本也是1.0.0并且firmware.url为空一般不会触发升级只会把 WebSocket 配置写入 NVS然后正常初始化协议。5. 自建小智服务器时的地址对应关系通常是OTA 接口 https://your-domain.com/xiaozhi/ota/ WebSocket 接口 wss://your-domain.com/xiaozhi/v1/xiaozhi-esp32-server的说明里也给出了类似结构OTA 接口是/xiaozhi/ota/WebSocket 接口是/xiaozhi/v1/。(GitHub)6. 推荐排查顺序你可以按这个顺序查grep CONFIG_OTA_URL sdkconfig确认输出是你的地址CONFIG_OTA_URLhttps://your-domain.com/xiaozhi/ota/然后擦除并重新烧录idf.py erase-flash idf.py flash monitor串口里重点看Current version: Check new version failed url Connecting to websocket server:如果串口里的url还是官方地址说明sdkconfig或 NVS 没清干净。如果url是你的 OTA 地址但报status code或Failed to parse JSON response说明你的 OTA 接口返回格式不对。如果 OTA 成功但 WebSocket 连不上检查 OTA 返回里的websocket.url、token、version。
xiaozhi-esp32 里配置 OTA URL 的位置是
可以xiaozhi-esp32里配置OTA URL的位置是idf.py menuconfig → Xiaozhi Assistant → Default OTA URL这个配置对应源码里的CONFIG_OTA_URL。项目的main/Kconfig.projbuild里定义了OTA_URL默认值是官方 OTA 地址说明里也写明该 URL 用于检查新固件和服务器地址。(GitHub)1. OTA URL 不是 WebSocket URL这里容易搞错。OTA_URL应该填OTA 配置接口地址不是直接填wss://.../xiaozhi/v1/。比如你自己部署的服务是https://your-domain.com/xiaozhi/ota/那么Default OTA URL就填https://your-domain.com/xiaozhi/ota/固件启动后会先请求这个 OTA 接口然后 OTA 接口再返回{ websocket: { url: wss://your-domain.com/xiaozhi/v1/, token: your_token, version: 3 }, firmware: { version: 1.0.0, url: }, server_time: { timestamp: 1710000000000, timezone_offset: 480 } }源码里CheckVersion()会访问GetCheckVersionUrl()再解析 OTA 返回的activation、mqtt、websocket、server_time、firmware等字段。(GitHub)2. 推荐配置方法方法 A用 menuconfig 配置idf.py menuconfig进入Xiaozhi Assistant → Default OTA URL改成https://你的服务器域名/xiaozhi/ota/然后重新编译烧录idf.py build idf.py flash monitor项目 README 里建议使用 ESP-IDF 5.4 或以上版本。(GitHub)3. 如果改了不生效重点看这三个地方第一sdkconfig已经生成直接改Kconfig.projbuild不一定生效Kconfig.projbuild里的default只是在首次生成sdkconfig时生效。如果工程里已经有sdkconfig你直接改main/Kconfig.projbuild可能不会改变最终编译值。正确做法是改sdkconfig找到CONFIG_OTA_URLhttps://api.tenclass.net/xiaozhi/ota/改成CONFIG_OTA_URLhttps://你的服务器域名/xiaozhi/ota/或者重新跑idf.py menuconfig第二设备 NVS 里可能已经保存了旧的ota_url源码里实际优先级是NVS 中 wifi/ota_url 优先于 CONFIG_OTA_URL也就是说如果 NVS 里已经保存过ota_url固件会优先用 NVS 里的地址只有 NVS 为空时才使用CONFIG_OTA_URL。源码里GetCheckVersionUrl()先读Settings(wifi).GetString(ota_url)为空时才 fallback 到CONFIG_OTA_URL。(GitHub)所以建议改完 OTA URL 后执行一次idf.py erase-flash idf.py flash monitor或者至少确认 NVS 没有旧配置。第三自建 OTA 接口必须返回 WebSocket / MQTT 配置固件不是只靠OTA_URL工作。它启动流程是联网成功 → 创建 OTA 对象 → CheckAssetsVersion() → CheckNewVersion() → InitializeProtocol()InitializeProtocol()会根据 OTA 返回内容决定使用 MQTT 还是 WebSocket如果 OTA 返回mqtt就走 MQTT如果返回websocket就走 WebSocket。(GitHub)WebSocket 协议实际读取的是websocket.url websocket.token websocket.version源码在WebsocketProtocol::OpenAudioChannel()里从Settings(websocket)读取url、token、version然后连接 WebSocket 服务。(GitHub)4. 最小可用 OTA 返回示例如果你只想走 WebSocketOTA 接口最少建议返回{ websocket: { url: wss://your-domain.com/xiaozhi/v1/, token: , version: 3 }, firmware: { version: 1.0.0, url: } }如果当前固件版本也是1.0.0并且firmware.url为空一般不会触发升级只会把 WebSocket 配置写入 NVS然后正常初始化协议。5. 自建小智服务器时的地址对应关系通常是OTA 接口 https://your-domain.com/xiaozhi/ota/ WebSocket 接口 wss://your-domain.com/xiaozhi/v1/xiaozhi-esp32-server的说明里也给出了类似结构OTA 接口是/xiaozhi/ota/WebSocket 接口是/xiaozhi/v1/。(GitHub)6. 推荐排查顺序你可以按这个顺序查grep CONFIG_OTA_URL sdkconfig确认输出是你的地址CONFIG_OTA_URLhttps://your-domain.com/xiaozhi/ota/然后擦除并重新烧录idf.py erase-flash idf.py flash monitor串口里重点看Current version: Check new version failed url Connecting to websocket server:如果串口里的url还是官方地址说明sdkconfig或 NVS 没清干净。如果url是你的 OTA 地址但报status code或Failed to parse JSON response说明你的 OTA 接口返回格式不对。如果 OTA 成功但 WebSocket 连不上检查 OTA 返回里的websocket.url、token、version。