### Example Web Server Startup Success Logs Source: https://github.com/xinnan-tech/xiaozhi-esp32-server/blob/main/docs/Deployment_all.md This snippet shows an example of successful startup logs for the `xiaozhi-esp32-server-web` component. The presence of `Started AdminApplication` and the `http://localhost:8002/xiaozhi/doc.html` URL indicates that the 'Smart Control Panel' has initialized correctly. ```Plaintext 2025-xx-xx 22:11:12.445 [main] INFO c.a.d.s.b.a.DruidDataSourceAutoConfigure - Init DruidDataSource 2025-xx-xx 21:28:53.873 [main] INFO xiaozhi.AdminApplication - Started AdminApplication in 16.057 seconds (process running for 17.941) http://localhost:8002/xiaozhi/doc.html ``` -------------------------------- ### Example Server Startup Success Logs Source: https://github.com/xinnan-tech/xiaozhi-esp32-server/blob/main/docs/Deployment_all.md This snippet shows example logs indicating the successful startup of the `xiaozhi-esp32-server`. The logs confirm the WebSocket address and provide instructions for testing, signifying that the core server functionality is operational. ```Plaintext 25-02-23 12:01:09[core.websocket_server] - INFO - Websocket地址是 ws://xxx.xx.xx.xx:8000/xiaozhi/v1/ 25-02-23 12:01:09[core.websocket_server] - INFO - =======上面的地址是websocket协议地址,请勿用浏览器访问======= 25-02-23 12:01:09[core.websocket_server] - INFO - 如想测试websocket请用谷歌浏览器打开test目录下的test_page.html 25-02-23 12:01:09[core.websocket_server] - INFO - ======================================================= ``` -------------------------------- ### Installing Dependencies for xiaozhi Project (npm) Source: https://github.com/xinnan-tech/xiaozhi-esp32-server/blob/main/main/manager-web/README.md This command installs all necessary project dependencies listed in the `package.json` file. It's a prerequisite for running or building the application and should be executed after importing the project. ```Shell npm install ``` -------------------------------- ### Starting All Docker Services Source: https://github.com/xinnan-tech/xiaozhi-esp32-server/blob/main/docs/Deployment_all.md This command starts all services defined in `docker-compose_all.yml` in detached mode (`-d`). It pulls necessary images, creates and starts containers for the Xiaozhi ESP32 server, web interface, database, and Redis. ```Shell docker compose -f docker-compose_all.yml up -d ``` -------------------------------- ### Initial Project Directory Structure Setup Source: https://github.com/xinnan-tech/xiaozhi-esp32-server/blob/main/docs/Deployment_all.md This snippet illustrates the initial directory structure required for the Xiaozhi ESP32 server project. It shows the main `xiaozhi-server` directory containing `data` and `models` folders, with `SenseVoiceSmall` nested inside `models` for storing the voice recognition model. ```Plaintext xiaozhi-server ├─ data ├─ models ├─ SenseVoiceSmall ``` -------------------------------- ### Building xiaozhi Project for Production (npm) Source: https://github.com/xinnan-tech/xiaozhi-esp32-server/blob/main/main/manager-web/README.md This command compiles and minifies the application's assets for production deployment. It optimizes the code for performance and smaller file sizes, preparing it for a live environment. ```Shell npm run build ``` -------------------------------- ### Running xiaozhi Project in Development Mode (npm) Source: https://github.com/xinnan-tech/xiaozhi-esp32-server/blob/main/main/manager-web/README.md This command compiles and hot-reloads the application for development purposes. It starts a local development server, allowing real-time code changes to be reflected in the browser without manual restarts. ```Shell npm run serve ``` -------------------------------- ### Downloading API Configuration File Source: https://github.com/xinnan-tech/xiaozhi-esp32-server/blob/main/docs/Deployment_all.md This command downloads the `config_from_api.yaml` file, which serves as a base configuration for the server's API. After download, it should be renamed to `.config.yaml` and placed in the `data` directory. ```Shell wget https://raw.githubusercontent.com/xinnan-tech/xiaozhi-esp32-server/refs/heads/main/main/xiaozhi-server/config_from_api.yaml ``` -------------------------------- ### Monitoring Web Server Logs Source: https://github.com/xinnan-tech/xiaozhi-esp32-server/blob/main/docs/Deployment_all.md This command displays the real-time logs of the `xiaozhi-esp32-server-web` container. It's used to verify the successful startup of the 'Smart Control Panel' (智控台) and troubleshoot any issues during its initialization. ```Shell docker logs -f xiaozhi-esp32-server-web ``` -------------------------------- ### Downloading Docker Compose Configuration Source: https://github.com/xinnan-tech/xiaozhi-esp32-server/blob/main/docs/Deployment_all.md This command downloads the `docker-compose_all.yml` file directly from the project's GitHub repository. This YAML file defines the Docker services and their configurations for deploying all modules of the Xiaozhi ESP32 server. ```Shell wget https://raw.githubusercontent.com/xinnan-tech/xiaozhi-esp32-server/refs/heads/main/main/xiaozhi-server/docker-compose_all.yml ``` -------------------------------- ### Stopping and Removing Existing Docker Containers and Images Source: https://github.com/xinnan-tech/xiaozhi-esp32-server/blob/main/docs/Deployment_all.md These commands are used to gracefully stop and remove all previously running Docker containers and their associated images for the Xiaozhi ESP32 server components. This step is crucial before deploying a new version to prevent conflicts and ensure a clean installation. ```Shell docker compose -f docker-compose_all.yml down docker stop xiaozhi-esp32-server docker rm xiaozhi-esp32-server docker stop xiaozhi-esp32-server-web docker rm xiaozhi-esp32-server-web docker stop xiaozhi-esp32-server-db docker rm xiaozhi-esp32-server-db docker stop xiaozhi-esp32-server-redis docker rm xiaozhi-esp32-server-redis docker rmi ghcr.nju.edu.cn/xinnan-tech/xiaozhi-esp32-server:server_latest docker rmi ghcr.nju.edu.cn/xinnan-tech/xiaozhi-esp32-server:web_latest ``` -------------------------------- ### Complete Project Directory Structure Source: https://github.com/xinnan-tech/xiaozhi-esp32-server/blob/main/docs/Deployment_all.md This snippet shows the final required directory structure after downloading all necessary configuration files and the voice recognition model. It includes `docker-compose_all.yml`, `.config.yaml` in `data`, and `model.pt` in `models/SenseVoiceSmall`. ```Plaintext xiaozhi-server ├─ docker-compose_all.yml ├─ data ├─ .config.yaml ├─ models ├─ SenseVoiceSmall ├─ model.pt ``` -------------------------------- ### Restarting Server and Monitoring Logs Source: https://github.com/xinnan-tech/xiaozhi-esp32-server/blob/main/docs/Deployment_all.md These commands restart the main `xiaozhi-esp32-server` container and then display its real-time logs. This step is performed after updating the configuration to apply changes and verify the server's successful re-initialization. ```Shell docker restart xiaozhi-esp32-server docker logs -f xiaozhi-esp32-server ``` -------------------------------- ### Updated Manager API Configuration Example Source: https://github.com/xinnan-tech/xiaozhi-esp32-server/blob/main/docs/Deployment_all.md This YAML snippet illustrates the updated `.config.yaml` content after configuring the `server.secret` and adjusting the `url` for Docker deployment. The `url` is set to the internal Docker service name `http://xiaozhi-esp32-server-web:8002/xiaozhi`, and `secret` is populated with the value obtained from the 'Smart Control Panel'. ```YAML manager-api: url: http://xiaozhi-esp32-server-web:8002/xiaozhi secret: 12345678-xxxx-xxxx-xxxx-123456789000 ``` -------------------------------- ### WebSocket Interface URL for ESP32 Source: https://github.com/xinnan-tech/xiaozhi-esp32-server/blob/main/docs/Deployment_all.md This URL specifies the WebSocket interface for the ESP32 device to communicate with the server. It enables real-time, bidirectional communication and requires the local IP address of the host machine. ```Plaintext ws://你电脑局域网的ip:8000/xiaozhi/v1/ ``` -------------------------------- ### OTA Interface URL for ESP32 Source: https://github.com/xinnan-tech/xiaozhi-esp32-server/blob/main/docs/Deployment_all.md This URL represents the Over-The-Air (OTA) update interface for the ESP32 device. It allows for remote firmware updates and should be configured with the local IP address of the computer running the server. ```Plaintext http://你电脑局域网的ip:8002/xiaozhi/ota/ ``` -------------------------------- ### Checking Opus Library Loading Status in JavaScript Source: https://github.com/xinnan-tech/xiaozhi-esp32-server/blob/main/main/xiaozhi-server/test/abbreviated_version/test.html This function attempts to verify if the Opus decoding library (expected as a global `Module` object from Emscripten) has loaded successfully. It checks for the presence of the `Module` object, specific decoder functions (`_opus_decoder_get_size`), and handles cases where the module might still be initializing by registering an `onRuntimeInitialized` callback. It updates UI status and enables/disables the start button based on success or failure. ```JavaScript function checkOpusLoaded() { try { // 检查Module是否存在(本地库导出的全局变量) if (typeof Module === 'undefined') { log("Module对象不存在", "error"); throw new Error('Opus库未加载,Module对象不存在'); } // 记录Module对象结构以便调试 log("Module对象结构: " + Object.keys(Module).join(", ")); // 尝试使用全局Module函数 if (typeof Module._opus_decoder_get_size === 'function') { window.ModuleInstance = Module; log('Opus库加载成功(使用全局Module)', "success"); updateScriptStatus('Opus库加载成功', 'success'); // 启用开始录音按钮 startButton.disabled = false; statusLabel.textContent = "待机"; // 3秒后隐藏状态 setTimeout(() => { const statusElement = document.getElementById('scriptStatus'); if (statusElement) statusElement.style.display = 'none'; }, 3000); window.opusLoaded = true; return true; } // 尝试使用Module.instance if (typeof Module.instance !== 'undefined' && typeof Module.instance._opus_decoder_get_size === 'function') { window.ModuleInstance = Module.instance; log('Opus库加载成功(使用Module.instance)', "success"); updateScriptStatus('Opus库加载成功', 'success'); // 启用开始录音按钮 startButton.disabled = false; statusLabel.textContent = "待机"; // 3秒后隐藏状态 setTimeout(() => { const statusElement = document.getElementById('scriptStatus'); if (statusElement) statusElement.style.display = 'none'; }, 3000); window.opusLoaded = true; return true; } // 检查是否有其他导出方式 log("Module上可用方法: " + Object.getOwnPropertyNames(Module).filter(prop => typeof Module[prop] === 'function').join(", ")); if (typeof Module.onRuntimeInitialized === 'function' || typeof Module.onRuntimeInitialized === 'undefined') { log("Module.onRuntimeInitialized 尚未执行,等待模块初始化完成..."); // Module可能未完成初始化,注册回调 Module.onRuntimeInitialized = function() { log("Opus库运行时初始化完成,重新检查"); checkOpusLoaded(); }; return false; } throw new Error('Opus解码函数未找到,可能Module结构不正确'); } catch (err) { log(`Opus库加载失败: ${err.message}`, "error"); updateScriptStatus(`Opus库加载失败: ${err.message}`, 'error'); statusLabel.textContent = "错误:Opus库加载失败"; return false; } } ``` -------------------------------- ### Initializing Web Audio API Context in JavaScript Source: https://github.com/xinnan-tech/xiaozhi-esp32-server/blob/main/main/xiaozhi-server/test/opus_test/test.html This function initializes or checks for the availability of the Web Audio API's AudioContext. It attempts to use window.AudioContext or its prefixed version (webkitAudioContext) and logs an error if the API is not supported, returning a boolean indicating success. ```JavaScript function initAudioContext() { try { window.AudioContext = window.AudioContext || window.webkitAudioContext; if (!window.AudioContext) { throw new Error("浏览器不支持AudioContext"); } log("AudioContext API 可用"); return true; } catch (err) { log("AudioContext初始化失败: " + err.message, "error"); updateScriptStatus("AudioContext初始化失败,录音功能不可用", "error"); return false; } } ``` -------------------------------- ### Verifying Opus Library Loading in JavaScript Source: https://github.com/xinnan-tech/xiaozhi-esp32-server/blob/main/main/xiaozhi-server/test/opus_test/test.html This function checks if the Opus codec library, typically loaded as a WebAssembly module, has been successfully initialized and its Module object is available. It attempts to find the _opus_decoder_get_size function, sets a global instance, updates UI status, and enables recording buttons upon successful loading. It also handles cases where the module is still initializing. ```JavaScript function checkOpusLoaded() { try { if (typeof Module === 'undefined') { log("Module对象不存在", "error"); throw new Error('Opus库未加载,Module对象不存在'); } log("Module对象结构: " + Object.keys(Module).join(", ")); if (typeof Module._opus_decoder_get_size === 'function') { window.ModuleInstance = Module; log('Opus库加载成功(使用全局Module)', "success"); updateScriptStatus('Opus库加载成功', 'success'); startButton.disabled = false; statusLabel.textContent = "待机"; setTimeout(() => { const statusElement = document.getElementById('scriptStatus'); if (statusElement) statusElement.style.display = 'none'; }, 3000); window.opusLoaded = true; return true; } if (typeof Module.instance !== 'undefined' && typeof Module.instance._opus_decoder_get_size === 'function') { window.ModuleInstance = Module.instance; log('Opus库加载成功(使用Module.instance)', "success"); updateScriptStatus('Opus库加载成功', 'success'); startButton.disabled = false; statusLabel.textContent = "待机"; setTimeout(() => { const statusElement = document.getElementById('scriptStatus'); if (statusElement) statusElement.style.display = 'none'; }, 3000); window.opusLoaded = true; return true; } log("Module上可用方法: " + Object.getOwnPropertyNames(Module).filter(prop => typeof Module[prop] === 'function').join(", ")); if (typeof Module.onRuntimeInitialized === 'function' || typeof Module.onRuntimeInitialized === 'undefined') { log("Module.onRuntimeInitialized 尚未执行,等待模块初始化完成..."); Module.onRuntimeInitialized = function() { log("Opus库运行时初始化完成,重新 ``` -------------------------------- ### Initializing Opus Library on Page Load in JavaScript Source: https://github.com/xinnan-tech/xiaozhi-esp32-server/blob/main/main/xiaozhi-server/test/abbreviated_version/test.html This event listener triggers when the entire page has loaded. It initiates the process of checking the Opus library's availability and includes a retry mechanism. If `checkOpusLoaded` fails initially, it will attempt to re-check after a delay, providing resilience against temporary loading issues. ```JavaScript window.addEventListener('load', function() { log("页面加载完成,开始初始化..."); updateScriptStatus('正在初始化录音环境...', 'info'); // 延迟一小段时间再检查,确保库有时间加载 setTimeout(function checkAndRetry() { if (!checkOpusLoaded()) { // 如果加载失败,5秒后重试 log("Opus库加载失败,5秒后重试..."); updateScriptStatus('Opus库加载失败,正在重试...', 'error'); setTimeout(checkAndRetry, 5000); } }, 1000); }); ``` -------------------------------- ### Styling Debug Information Panel - CSS Source: https://github.com/xinnan-tech/xiaozhi-esp32-server/blob/main/main/xiaozhi-server/test/abbreviated_version/test.html This snippet defines the visual presentation for a debug information panel. It includes styles for borders, padding, font, font size, and sets a maximum height with overflow scrolling, allowing for a compact display of potentially large debug logs. ```CSS #debugInfo { margin-top: 20px; border: 1px solid #ccc; border-radius: 5px; padding: 10px; font-family: monospace; font-size: 12px; max-height: 200px; overflow-y: auto; display: none; } ``` -------------------------------- ### Styling General Page Layout and Containers - CSS Source: https://github.com/xinnan-tech/xiaozhi-esp32-server/blob/main/main/xiaozhi-server/test/abbreviated_version/test.html This snippet defines the base styles for the HTML body, setting font family, max width, and margins. It also styles the main content container with background color, padding, border radius, and shadow for visual separation and structure. ```CSS body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; } .container { background-color: #f5f5f5; padding: 20px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); margin-bottom: 20px; } ``` -------------------------------- ### Checking Microphone Permissions in JavaScript Source: https://github.com/xinnan-tech/xiaozhi-esp32-server/blob/main/main/xiaozhi-server/test/opus_test/test.html This function verifies if the browser supports the getUserMedia API, which is essential for accessing the microphone. It logs an error and updates the script status if the API is unavailable, returning a boolean indicating support. ```JavaScript function checkMicrophonePermission() { if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) { log("浏览器不支持getUserMedia API", "error"); updateScriptStatus("浏览器不支持录音功能", "error"); return false; } log("getUserMedia API 可用"); return true; } ``` -------------------------------- ### Styling Interactive Buttons - CSS Source: https://github.com/xinnan-tech/xiaozhi-esp32-server/blob/main/main/xiaozhi-server/test/abbreviated_version/test.html This snippet provides styles for general buttons, including padding, margins, borders, background color, text color, and cursor. It also defines hover effects for interactive feedback and disabled states for non-clickable buttons, ensuring clear visual cues for user interaction. ```CSS button { padding: 8px 15px; margin-right: 10px; border: none; border-radius: 5px; background-color: #4285f4; color: white; cursor: pointer; transition: background-color 0.2s; } button:hover { background-color: #3367d6; } button:disabled { background-color: #cccccc; cursor: not-allowed; } #showDebug { margin-top: 10px; background-color: #f5f5f5; color: #444; font-size: 12px; } ``` -------------------------------- ### Adding Debug Log Entries in JavaScript Source: https://github.com/xinnan-tech/xiaozhi-esp32-server/blob/main/main/xiaozhi-server/test/opus_test/test.html This utility function appends a timestamped message to a debug information display (debugInfo element) on the webpage and also logs it to the browser console. It supports different message types ("info", "error", "success") to apply specific styling. ```JavaScript function log(message, type = "info") { console.log(message); const time = new Date().toLocaleTimeString(); const entry = document.createElement("div"); entry.textContent = `[${time}] ${message}`; if (type === "error") { entry.style.color = "#db4437"; } else if (type === "success") { entry.style.color = "#0f9d58"; } debugInfo.appendChild(entry); debugInfo.scrollTop = debugInfo.scrollHeight; } ``` -------------------------------- ### Styling Audio Level Meter - CSS Source: https://github.com/xinnan-tech/xiaozhi-esp32-server/blob/main/main/xiaozhi-server/test/abbreviated_version/test.html This snippet provides styles for an audio level meter, including its container and the dynamic level indicator. The container sets the overall size and appearance, while the level indicator uses a changing width to visually represent audio input volume. ```CSS #audioMeter { margin-top: 10px; height: 20px; background-color: #eee; border-radius: 4px; overflow: hidden; display: none; } #audioLevel { height: 100%; width: 0%; background-color: #4285f4; transition: width 0.1s; } ``` -------------------------------- ### Styling Dynamic Status Messages - CSS Source: https://github.com/xinnan-tech/xiaozhi-esp32-server/blob/main/main/xiaozhi-server/test/abbreviated_version/test.html This snippet defines styles for various status messages, including a general status indicator and a fixed script status notification. It provides distinct visual cues (colors, borders) for informational, success, and error states to clearly communicate application status to the user. ```CSS #status { font-weight: bold; } #scriptStatus { position: fixed; top: 10px; left: 50%; transform: translateX(-50%); padding: 15px; border-radius: 5px; display: block; z-index: 100; transition: all 0.3s ease; } #scriptStatus.info { background-color: #e8f0fe; color: #4285f4; border-left: 4px solid #4285f4; } #scriptStatus.success { background-color: #e6f4ea; color: #0f9d58; border-left: 44px solid #0f9d58; } #scriptStatus.error { background-color: #fce8e6; color: #db4437; border-left: 4px solid #db4437; } ``` -------------------------------- ### Styling Text Input Fields - CSS Source: https://github.com/xinnan-tech/xiaozhi-esp32-server/blob/main/main/xiaozhi-server/test/abbreviated_version/test.html This snippet provides styles for text input fields, specifically for server URL and message input. It ensures consistent padding, borders, border-radius, and width for these interactive elements within the UI, enhancing usability. ```CSS #serverUrl { flex-grow: 1; padding: 8px; border: 1px solid #ddd; border-radius: 5px; width: 60%; margin-right: 10px; } #messageInput { flex-grow: 1; padding: 8px; border: 1px solid #ddd; border-radius: 5px; width: 70%; margin-right: 10px; } ``` -------------------------------- ### Styling Conversation Message Display - CSS Source: https://github.com/xinnan-tech/xiaozhi-esp32-server/blob/main/main/xiaozhi-server/test/abbreviated_version/test.html This snippet defines the styles for a conversation display area, including the main scrollable container and individual message bubbles. It differentiates between user and server messages with distinct background colors and alignment, mimicking a chat interface. ```CSS .conversation { max-height: 300px; overflow-y: auto; border: 1px solid #ddd; border-radius: 5px; padding: 10px; background-color: white; margin-top: 10px; } .message { margin-bottom: 10px; padding: 8px 12px; border-radius: 8px; max-width: 80%; } .user { background-color: #e2f2ff; margin-left: auto; margin-right: 10px; text-align: right; } .server { background-color: #f0f0f0; margin-right: auto; margin-left: 10px; } ``` -------------------------------- ### Conditional JavaScript CDN Loading (EJS) Source: https://github.com/xinnan-tech/xiaozhi-esp32-server/blob/main/main/manager-web/public/index.html Similar to CSS loading, this EJS block conditionally includes JavaScript CDN links. It verifies the existence of `htmlWebpackPlugin.options.cdn` and `htmlWebpackPlugin.options.cdn.js` before iterating to insert `