add_py_xiaozhi
6
py-xiaozhi-main/.flake8
Executable file
@ -0,0 +1,6 @@
|
||||
[flake8]
|
||||
max-line-length = 88
|
||||
extend-ignore = D100,D104,D401,E203,W503,D400,I001
|
||||
exclude = .git,__pycache__,.venv,build,dist
|
||||
import-order-style = google
|
||||
application-import-names = py_xiaozhi
|
32
py-xiaozhi-main/.github/ISSUE_TEMPLATE/bug_report.md
vendored
Executable file
@ -0,0 +1,32 @@
|
||||
---
|
||||
name: Bug 报告(Bug Report)
|
||||
about: 反馈项目中的缺陷或问题
|
||||
title: "[Bug] 简短描述问题"
|
||||
labels: bug
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
## 🐛 问题描述
|
||||
<!-- 清晰简洁地描述问题是什么 -->
|
||||
|
||||
## 🔍 复现步骤
|
||||
<!-- 详细描述复现问题的步骤 -->
|
||||
1. 打开 '...'
|
||||
2. 点击 '...'
|
||||
3. 滚动到 '...'
|
||||
4. 看到错误
|
||||
|
||||
## 🤔 预期行为
|
||||
<!-- 简要描述预期的正确行为 -->
|
||||
|
||||
## 😯 截图
|
||||
<!-- 如果适用,添加问题的截图 -->
|
||||
|
||||
## 🖥️ 环境信息
|
||||
- 操作系统: [例如 Windows 10]
|
||||
- 项目版本: [例如 1.0.0]
|
||||
- Python版本: [例如 3.9.13]
|
||||
- Nodejs版本: [例如 v20.14.0]
|
||||
|
||||
## 📋 其他信息
|
||||
<!-- 在此添加关于此问题的任何其他上下文信息 -->
|
19
py-xiaozhi-main/.github/ISSUE_TEMPLATE/code_improvement.md
vendored
Executable file
@ -0,0 +1,19 @@
|
||||
---
|
||||
name: 代码优化建议(Code Improvement)
|
||||
about: 提出对现有代码的优化或改进建议
|
||||
title: "[Improvement] 简短描述改进内容"
|
||||
labels: refactor
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
## 💡 改进描述
|
||||
<!-- 描述需要改进的代码部分以及存在的问题 -->
|
||||
|
||||
## 🌟 改进建议
|
||||
<!-- 提出具体的改进方案或思路 -->
|
||||
|
||||
## 🛠️ 相关代码
|
||||
<!-- 如果可能,提供相关代码片段或链接 -->
|
||||
|
||||
## 📋 其他信息
|
||||
<!-- 在此添加任何其他相关信息 -->
|
16
py-xiaozhi-main/.github/ISSUE_TEMPLATE/documentation_improvement.md
vendored
Executable file
@ -0,0 +1,16 @@
|
||||
---
|
||||
name: 文档改进建议(Documentation Improvement)
|
||||
about: 提出对项目文档的改进或补充建议
|
||||
title: "[Docs] 简短描述改进内容"
|
||||
labels: documentation
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
## 📚 改进描述
|
||||
<!-- 描述需要改进的文档部分以及存在的问题 -->
|
||||
|
||||
## ✨ 改进建议
|
||||
<!-- 提出具体的改进方案或内容 -->
|
||||
|
||||
## 📋 其他信息
|
||||
<!-- 在此添加任何其他相关信息 -->
|
19
py-xiaozhi-main/.github/ISSUE_TEMPLATE/feature_request.md
vendored
Executable file
@ -0,0 +1,19 @@
|
||||
---
|
||||
name: 功能请求(Feature Request)
|
||||
about: 提出新的功能或改进建议
|
||||
title: "[Feature] 简短描述功能"
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
## 🚀 需求描述
|
||||
<!-- 清晰简洁地描述你希望发生什么 -->
|
||||
|
||||
## 🎯 解决方案
|
||||
<!-- 描述你认为可行的解决方案或实现方式 -->
|
||||
|
||||
## 📝 备选方案
|
||||
<!-- 描述你考虑过的替代方案或功能 -->
|
||||
|
||||
## 📋 其他信息
|
||||
<!-- 在此添加关于需求的任何其他上下文信息 -->
|
119
py-xiaozhi-main/.github/workflows/build-window.yml
vendored
Executable file
@ -0,0 +1,119 @@
|
||||
name: Setup Inno Setup, Conda, and Build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
setup-and-build:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
# 检出代码
|
||||
- name: 检出代码
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# 安装 Inno Setup
|
||||
- name: 安装 Inno Setup(通过 Chocolatey)
|
||||
run: choco install innosetup -y
|
||||
shell: powershell
|
||||
|
||||
# 下载 ChineseSimplified.isl 文件
|
||||
- name: 下载中文语言文件
|
||||
run: |
|
||||
$languageDir = "C:\Program Files (x86)\Inno Setup 6\Languages"
|
||||
|
||||
# 确保目录存在
|
||||
if (-not (Test-Path $languageDir)) {
|
||||
New-Item -ItemType Directory -Path $languageDir -Force
|
||||
}
|
||||
|
||||
# 下载中文语言文件
|
||||
Invoke-WebRequest -Uri "https://raw.githubusercontent.com/jrsoftware/issrc/main/Files/Languages/Unofficial/ChineseSimplified.isl" -OutFile "$languageDir\ChineseSimplified.isl"
|
||||
|
||||
Write-Host "已下载中文语言文件到 $languageDir\ChineseSimplified.isl"
|
||||
|
||||
# 验证文件是否存在
|
||||
if (Test-Path "$languageDir\ChineseSimplified.isl") {
|
||||
Write-Host "文件下载成功!"
|
||||
} else {
|
||||
Write-Error "文件下载失败!"
|
||||
exit 1
|
||||
}
|
||||
shell: powershell
|
||||
|
||||
# 查找 ISCC.exe 路径并更新 build.json
|
||||
- name: 查找 ISCC.exe 路径并更新 build.json
|
||||
run: |
|
||||
# 获取 ISCC 路径
|
||||
$isccPath = Get-Command ISCC.exe | Select-Object -ExpandProperty Source
|
||||
|
||||
# 设置环境变量
|
||||
$envLine = "ISCC_PATH=$($isccPath -replace '`r','' -replace '`n','')"
|
||||
[System.IO.File]::AppendAllText($env:GITHUB_ENV, "$envLine`n", [System.Text.Encoding]::UTF8)
|
||||
|
||||
# 读取 JSON 内容
|
||||
$jsonPath = "build.json"
|
||||
$json = Get-Content $jsonPath -Raw | ConvertFrom-Json
|
||||
|
||||
# 设置新的 Inno Setup 路径
|
||||
$json.inno_setup_path = $isccPath
|
||||
|
||||
# 写回 JSON 文件,格式化为 UTF-8 编码
|
||||
$json | ConvertTo-Json -Depth 10 | Out-File -FilePath $jsonPath -Encoding UTF8
|
||||
|
||||
Write-Host "已更新 build.json 中的 Inno Setup 路径为: $isccPath"
|
||||
shell: powershell
|
||||
|
||||
# 安装 Miniconda 和 Conda
|
||||
- name: 安装 Miniconda 和 Conda
|
||||
uses: conda-incubator/setup-miniconda@v3
|
||||
with:
|
||||
python-version: "3.10"
|
||||
auto-update-conda: true
|
||||
auto-activate-base: false
|
||||
activate-environment: py-xiaozhi
|
||||
|
||||
# 创建 Conda 环境并安装依赖
|
||||
- name: 创建 Conda 环境 py-xiaozhi
|
||||
shell: bash -el {0}
|
||||
run: conda create -n py-xiaozhi python=3.10 -y
|
||||
|
||||
# 创建一个简单的 requirements.txt 文件(如果不存在)
|
||||
- name: 创建 requirements.txt
|
||||
run: |
|
||||
if (-not (Test-Path "requirements.txt")) {
|
||||
Set-Content -Path "requirements.txt" -Value ""
|
||||
}
|
||||
shell: powershell
|
||||
|
||||
# 安装 Python 依赖(pip + conda + pyinstaller)
|
||||
- name: 安装 Python 依赖(pip + conda + pyinstaller)
|
||||
shell: bash -el {0}
|
||||
run: |
|
||||
conda activate py-xiaozhi
|
||||
|
||||
# 安装依赖
|
||||
pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple
|
||||
conda install pyqt=5.15.10 opencv=4.10.0 -y
|
||||
pip install pyinstaller
|
||||
|
||||
# 拉取 UnifyPy 仓库
|
||||
- name: 拉取 UnifyPy 仓库
|
||||
run: git clone https://github.com/huangjunsen0406/UnifyPy.git
|
||||
shell: bash
|
||||
|
||||
# 运行 UnifyPy 构建项目
|
||||
- name: 运行 UnifyPy 构建项目
|
||||
shell: bash -el {0}
|
||||
run: |
|
||||
conda activate py-xiaozhi
|
||||
export PYTHONIOENCODING=utf-8
|
||||
python UnifyPy/main.py . --config build.json
|
||||
|
||||
# 只上传 Inno Setup 安装程序
|
||||
- name: 上传安装程序
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: installer-setup
|
||||
path: installer/
|
46
py-xiaozhi-main/.github/workflows/vitepress.yml
vendored
Executable file
@ -0,0 +1,46 @@
|
||||
# workflow 名称,可以自定义
|
||||
name: Deploy GitHub Pages
|
||||
|
||||
# 触发条件:在代码 push 到 master 分支后,自动执行该 workflow
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
# 任务
|
||||
jobs:
|
||||
build-and-deploy:
|
||||
# 服务器环境:最新版 Ubuntu,也可以自定义版本
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# 拉取代码
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
# 设置 Node.js 版本
|
||||
- name: Setup Node.js environment
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: "18.20.3"
|
||||
# 安装yarn
|
||||
- name: Install yarn
|
||||
run: npm i yarn -g
|
||||
|
||||
# 如果缓存没有命中,安装依赖
|
||||
- name: Install dependencies
|
||||
run: cd documents && yarn install
|
||||
|
||||
# 生成静态文件
|
||||
- name: Build
|
||||
run: cd documents && yarn docs:build
|
||||
|
||||
# 部署到 GitHub Pages
|
||||
- name: Deploy
|
||||
uses: crazy-max/ghaction-github-pages@v2
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }} # ACCESS_TOKEN 是创建的 Secret 名称,替换为你自己创建的名称
|
||||
with:
|
||||
target-branch: gh-pages # 部署到 gh-pages 分支,master 分支存放的是项目源码,而 gh-pages 分支则用来存放生成的静态文件
|
||||
build_dir: documents/docs/.vitepress/dist # vuepress 生成的静态文件存放的地方
|
32
py-xiaozhi-main/.gitignore
vendored
Executable file
@ -0,0 +1,32 @@
|
||||
/logs
|
||||
/config
|
||||
|
||||
.venv
|
||||
**/__pycache__/
|
||||
|
||||
.idea/
|
||||
venv/
|
||||
|
||||
# 音乐缓存
|
||||
cache/
|
||||
|
||||
|
||||
/models
|
||||
|
||||
# 打包相关
|
||||
/build
|
||||
/dist
|
||||
|
||||
# MACOS
|
||||
.DS_Store
|
||||
|
||||
# IDE - VSCode
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
|
||||
xiaozhi.spec
|
||||
|
||||
/installer
|
14
py-xiaozhi-main/.vscode/settings.json
vendored
Executable file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"python.formatting.provider": "black",
|
||||
"editor.formatOnSave": true,
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.organizeImports": "always"
|
||||
},
|
||||
"python.formatting.blackArgs": ["--line-length", "88"],
|
||||
"python.formatting.blackPath": "/Users/junsen/miniconda3/envs/py-test/bin/black",
|
||||
"python.linting.flake8Enabled": true,
|
||||
"python.linting.enabled": true,
|
||||
"python.linting.flake8Args": [
|
||||
"--max-line-length=88"
|
||||
]
|
||||
}
|
21
py-xiaozhi-main/LICENSE
Executable file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 Junsen
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
189
py-xiaozhi-main/README.en.md
Executable file
@ -0,0 +1,189 @@
|
||||
# py-xiaozhi
|
||||
<p align="center">
|
||||
<a href="https://github.com/huangjunsen0406/py-xiaozhi/releases/latest">
|
||||
<img src="https://img.shields.io/github/v/release/huangjunsen0406/py-xiaozhi?style=flat-square&logo=github&color=blue" alt="Release"/>
|
||||
</a>
|
||||
<a href="https://opensource.org/licenses/MIT">
|
||||
<img src="https://img.shields.io/badge/License-MIT-green.svg?style=flat-square" alt="License: MIT"/>
|
||||
</a>
|
||||
<a href="https://github.com/huangjunsen0406/py-xiaozhi/stargazers">
|
||||
<img src="https://img.shields.io/github/stars/huangjunsen0406/py-xiaozhi?style=flat-square&logo=github" alt="Stars"/>
|
||||
</a>
|
||||
<a href="https://github.com/huangjunsen0406/py-xiaozhi/releases/latest">
|
||||
<img src="https://img.shields.io/github/downloads/huangjunsen0406/py-xiaozhi/total?style=flat-square&logo=github&color=52c41a1&maxAge=86400" alt="Download"/>
|
||||
</a>
|
||||
<a href="https://gitee.com/huang-jun-sen/py-xiaozhi">
|
||||
<img src="https://img.shields.io/badge/Gitee-FF5722?style=flat-square&logo=gitee" alt="Gitee"/>
|
||||
</a>
|
||||
<a href="https://huangjunsen0406.github.io/py-xiaozhi/guide/00_%E6%96%87%E6%A1%A3%E7%9B%AE%E5%BD%95.html">
|
||||
<img alt="Usage Docs" src="https://img.shields.io/badge/Usage Docs-View-blue?labelColor=2d2d2d" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
English | [简体中文](README.md)
|
||||
|
||||
## Project Introduction
|
||||
py-xiaozhi is a Python-based Xiaozhi voice client, designed to learn coding and experience AI voice interaction without hardware requirements. This repository is ported from [xiaozhi-esp32](https://github.com/78/xiaozhi-esp32).
|
||||
|
||||
## Demo
|
||||
- [Bilibili Demo Video](https://www.bilibili.com/video/BV1HmPjeSED2/#reply255921347937)
|
||||
|
||||

|
||||
|
||||
## Features
|
||||
- **AI Voice Interaction**: Supports voice input and recognition, enabling smart human-computer interaction with natural conversation flow.
|
||||
- **Visual Multimodal**: Supports image recognition and processing, providing multimodal interaction capabilities and image content understanding.
|
||||
- **IoT Device Integration**:
|
||||
- Supports smart home device control including lights, volume, temperature sensors, etc.
|
||||
- Integrates with Home Assistant smart home platform to control lights, switches, number controllers, and buttons
|
||||
- Provides countdown timer functionality for delayed command execution
|
||||
- Features built-in virtual devices and physical device drivers, easily extensible
|
||||
- **Online Music Playback**: Advanced Music Player: A high-performance music player built on Pygame, supporting play/pause/stop, progress control, lyric display, and local caching, delivering a more stable and smooth listening experience.
|
||||
- **Voice Wake-up**: Supports wake word activation, eliminating manual operation (disabled by default, manual activation required).
|
||||
- **Auto Dialogue Mode**: Implements continuous dialogue experience, enhancing user interaction fluidity.
|
||||
- **Graphical Interface**: Provides intuitive GUI with Xiaozhi expressions and text display, enhancing visual experience.
|
||||
- **Command Line Mode**: Supports CLI operation, suitable for embedded devices or environments without GUI.
|
||||
- **Cross-platform Support**: Compatible with Windows 10+, macOS 10.15+, and Linux systems for use anywhere.
|
||||
- **Volume Control**: Supports volume adjustment to adapt to different environmental requirements with unified sound control interface.
|
||||
- **Session Management**: Effectively manages multi-turn dialogues to maintain interaction continuity.
|
||||
- **Encrypted Audio Transmission**: Supports WSS protocol to ensure audio data security and prevent information leakage.
|
||||
- **Automatic Verification Code Handling**: Automatically copies verification codes and opens browsers during first use, simplifying user operations.
|
||||
- **Automatic MAC Address Acquisition**: Avoids MAC address conflicts and improves connection stability.
|
||||
- **Modular Code**: Code is split and encapsulated into classes with clear responsibilities, facilitating secondary development.
|
||||
- **Stability Optimization**: Fixes multiple issues including reconnection and cross-platform compatibility.
|
||||
|
||||
## System Requirements
|
||||
- Python version: 3.9 >= version <= 3.12
|
||||
- Supported operating systems: Windows 10+, macOS 10.15+, Linux
|
||||
- Microphone and speaker devices
|
||||
|
||||
## Read This First!
|
||||
- Carefully read [项目文档](https://huangjunsen0406.github.io/py-xiaozhi/) for startup tutorials and file descriptions
|
||||
- The main branch has the latest code; manually reinstall pip dependencies after each update to ensure you have new dependencies
|
||||
|
||||
[Zero to Xiaozhi Client (Video Tutorial)](https://www.bilibili.com/video/BV1dWQhYEEmq/?vd_source=2065ec11f7577e7107a55bbdc3d12fce)
|
||||
|
||||
## Configuration System
|
||||
The project uses a layered configuration system, including:
|
||||
|
||||
1. **Basic Configuration**: Sets basic runtime parameters, located in `config/config.json`
|
||||
2. **Device Activation**: Device identity information, stored in `config/efuse.json`
|
||||
3. **Wake Word Settings**: Voice wake-up related configuration
|
||||
4. **IoT Devices**: Configuration for various IoT devices, including temperature sensors and Home Assistant integration
|
||||
|
||||
For detailed configuration instructions, please refer to [Configuration Documentation](./documents/docs/guide/02_配置说明.md)
|
||||
|
||||
## IoT Functionality
|
||||
py-xiaozhi provides rich IoT device control features:
|
||||
|
||||
- **Virtual Devices**: Light control, volume adjustment, countdown timers, etc.
|
||||
- **Physical Device Integration**: Temperature sensors, cameras, etc.
|
||||
- **Home Assistant Integration**: Connect to smart home systems via HTTP API
|
||||
- **Custom Device Extension**: Complete framework for device definition and registration
|
||||
|
||||
For supported device types and usage examples, please refer to [IoT Functionality Guide](./documents/docs/guide/05_IoT功能说明.md)
|
||||
|
||||
## State Transition Diagram
|
||||
|
||||
```
|
||||
+----------------+
|
||||
| |
|
||||
v |
|
||||
+------+ Wake/Button +------------+ | +------------+
|
||||
| IDLE | -----------> | CONNECTING | --+-> | LISTENING |
|
||||
+------+ +------------+ +------------+
|
||||
^ |
|
||||
| | Voice Recognition Complete
|
||||
| +------------+ v
|
||||
+--------- | SPEAKING | <-----------------+
|
||||
Playback +------------+
|
||||
Complete
|
||||
```
|
||||
|
||||
## Upcoming Features
|
||||
- [ ] **New GUI (Electron)**: Provides a more modern and beautiful user interface, optimizing the interaction experience.
|
||||
|
||||
## FAQ
|
||||
- **Can't find audio device**: Please check if your microphone and speakers are properly connected and enabled.
|
||||
- **Wake word not responding**: Check if the `USE_WAKE_WORD` setting in `config.json` is set to `true` and the model path is correct.
|
||||
- **Network connection failure**: Check network settings and firewall configuration to ensure WebSocket or MQTT communication is not blocked.
|
||||
- **Packaging failure**: Make sure PyInstaller is installed (`pip install pyinstaller`) and all dependencies are installed. Then re-execute `python scripts/build.py`
|
||||
- **IoT devices not responding**: Check if the corresponding device configuration information is correct, such as Home Assistant URL and Token.
|
||||
|
||||
## Related Third-party Open Source Projects
|
||||
[Xiaozhi Mobile Client](https://github.com/TOM88812/xiaozhi-android-client)
|
||||
|
||||
[xiaozhi-esp32-server (Open source server)](https://github.com/xinnan-tech/xiaozhi-esp32-server)
|
||||
|
||||
[XiaoZhiAI_server32_Unity(Unity Development)](https://gitee.com/vw112266/XiaoZhiAI_server32_Unity)
|
||||
|
||||
[IntelliConnect(Aiot Middleware)](https://github.com/ruanrongman/IntelliConnect)
|
||||
|
||||
[open-xiaoai(Xiaoai Audio Access Xiaozhi)](https://github.com/idootop/open-xiaoai.git)
|
||||
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
├── .github # GitHub related configurations
|
||||
├── assets # Resource files (emotion animations, etc.)
|
||||
├── cache # Cache directory (music and temporary files)
|
||||
├── config # Configuration directory
|
||||
├── documents # Documentation directory
|
||||
├── hooks # PyInstaller hooks directory
|
||||
├── libs # Dependencies directory
|
||||
├── scripts # Utility scripts directory
|
||||
├── src # Source code directory
|
||||
│ ├── audio_codecs # Audio encoding/decoding module
|
||||
│ ├── audio_processing # Audio processing module
|
||||
│ ├── constants # Constants definition
|
||||
│ ├── display # Display interface module
|
||||
│ ├── iot # IoT device related module
|
||||
│ │ └── things # Specific device implementation directory
|
||||
│ ├── network # Network communication module
|
||||
│ ├── protocols # Communication protocol module
|
||||
│ └── utils # Utility classes module
|
||||
```
|
||||
|
||||
## Contribution Guidelines
|
||||
We welcome issue reports and code contributions. Please ensure you follow these specifications:
|
||||
|
||||
1. Code style complies with PEP8 standards
|
||||
2. PR submissions include appropriate tests
|
||||
3. Update relevant documentation
|
||||
|
||||
## Community and Support
|
||||
|
||||
### Thanks to the Following Open Source Contributors
|
||||
> In no particular order
|
||||
|
||||
[Xiaoxia](https://github.com/78)
|
||||
[zhh827](https://github.com/zhh827)
|
||||
[SmartArduino-Li Honggang](https://github.com/SmartArduino)
|
||||
[HonestQiao](https://github.com/HonestQiao)
|
||||
[vonweller](https://github.com/vonweller)
|
||||
[Sun Weigong](https://space.bilibili.com/416954647)
|
||||
[isamu2025](https://github.com/isamu2025)
|
||||
[Rain120](https://github.com/Rain120)
|
||||
[kejily](https://github.com/kejily)
|
||||
[Radio bilibili Jun](https://space.bilibili.com/119751)
|
||||
|
||||
### Sponsorship Support
|
||||
|
||||
<div align="center">
|
||||
<h3>Thanks to All Sponsors ❤️</h3>
|
||||
<p>Whether it's API resources, device compatibility testing, or financial support, every contribution makes the project more complete</p>
|
||||
|
||||
<a href="https://huangjunsen0406.github.io/py-xiaozhi/sponsors/" target="_blank">
|
||||
<img src="https://img.shields.io/badge/View-Sponsors-brightgreen?style=for-the-badge&logo=github" alt="View Sponsors">
|
||||
</a>
|
||||
<a href="https://huangjunsen0406.github.io/py-xiaozhi/sponsors/" target="_blank">
|
||||
<img src="https://img.shields.io/badge/Become-Sponsor-orange?style=for-the-badge&logo=heart" alt="Become a Sponsor">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
## Project Statistics
|
||||
[](https://www.star-history.com/#huangjunsen0406/py-xiaozhi&Date)
|
||||
|
||||
## License
|
||||
[MIT License](LICENSE)
|
190
py-xiaozhi-main/README.md
Executable file
@ -0,0 +1,190 @@
|
||||
# py-xiaozhi
|
||||
<p align="center">
|
||||
<a href="https://github.com/huangjunsen0406/py-xiaozhi/releases/latest">
|
||||
<img src="https://img.shields.io/github/v/release/huangjunsen0406/py-xiaozhi?style=flat-square&logo=github&color=blue" alt="Release"/>
|
||||
</a>
|
||||
<a href="https://opensource.org/licenses/MIT">
|
||||
<img src="https://img.shields.io/badge/License-MIT-green.svg?style=flat-square" alt="License: MIT"/>
|
||||
</a>
|
||||
<a href="https://github.com/huangjunsen0406/py-xiaozhi/stargazers">
|
||||
<img src="https://img.shields.io/github/stars/huangjunsen0406/py-xiaozhi?style=flat-square&logo=github" alt="Stars"/>
|
||||
</a>
|
||||
<a href="https://github.com/huangjunsen0406/py-xiaozhi/releases/latest">
|
||||
<img src="https://img.shields.io/github/downloads/huangjunsen0406/py-xiaozhi/total?style=flat-square&logo=github&color=52c41a1&maxAge=86400" alt="Download"/>
|
||||
</a>
|
||||
<a href="https://gitee.com/huang-jun-sen/py-xiaozhi">
|
||||
<img src="https://img.shields.io/badge/Gitee-FF5722?style=flat-square&logo=gitee" alt="Gitee"/>
|
||||
</a>
|
||||
<a href="https://huangjunsen0406.github.io/py-xiaozhi/guide/00_%E6%96%87%E6%A1%A3%E7%9B%AE%E5%BD%95.html">
|
||||
<img alt="使用文档" src="https://img.shields.io/badge/使用文档-点击查看-blue?labelColor=2d2d2d" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
简体中文 | [English](README.en.md)
|
||||
|
||||
## 项目简介
|
||||
py-xiaozhi 是一个使用 Python 实现的小智语音客户端,旨在通过代码学习和在没有硬件条件下体验 AI 小智的语音功能。
|
||||
本仓库是基于[xiaozhi-esp32](https://github.com/78/xiaozhi-esp32)移植
|
||||
|
||||
## 演示
|
||||
- [Bilibili 演示视频](https://www.bilibili.com/video/BV1HmPjeSED2/#reply255921347937)
|
||||
|
||||

|
||||
|
||||
## 功能特点
|
||||
- **AI语音交互**:支持语音输入与识别,实现智能人机交互,提供自然流畅的对话体验。
|
||||
- **视觉多模态**:支持图像识别和处理,提供多模态交互能力,理解图像内容。
|
||||
- **IoT 设备集成**:
|
||||
- 支持智能家居设备控制,包括灯光、音量、温度传感器等
|
||||
- 集成Home Assistant智能家居平台,控制灯具、开关、数值控制器和按钮设备
|
||||
- 提供倒计时器功能,支持延时执行命令
|
||||
- 内置多种虚拟设备和物理设备驱动,可轻松扩展
|
||||
- **联网音乐播放**:基于pygame实现的高性能音乐播放器,支持播放/暂停/停止、进度控制、歌词显示和本地缓存,提供更稳定的音乐播放体验。
|
||||
- **语音唤醒**:支持唤醒词激活交互,免去手动操作的烦恼(默认关闭需要手动开启)。
|
||||
- **自动对话模式**:实现连续对话体验,提升用户交互流畅度。
|
||||
- **图形化界面**:提供直观易用的 GUI,支持小智表情与文本显示,增强视觉体验。
|
||||
- **命令行模式**:支持 CLI 运行,适用于嵌入式设备或无 GUI 环境。
|
||||
- **跨平台支持**:兼容 Windows 10+、macOS 10.15+ 和 Linux 系统,随时随地使用。
|
||||
- **音量控制**:支持音量调节,适应不同环境需求,统一声音控制接口。
|
||||
- **会话管理**:有效管理多轮对话,保持交互的连续性。
|
||||
- **加密音频传输**:支持 WSS 协议,保障音频数据的安全性,防止信息泄露。
|
||||
- **自动验证码处理**:首次使用时,程序自动复制验证码并打开浏览器,简化用户操作。
|
||||
- **自动获取 MAC 地址**:避免 MAC 地址冲突,提高连接稳定性。
|
||||
- **代码模块化**:拆分代码并封装为类,职责分明,便于二次开发。
|
||||
- **稳定性优化**:修复多项问题,包括断线重连、跨平台兼容等。
|
||||
|
||||
## 系统要求
|
||||
- 3.9 >= Python版本 <= 3.12
|
||||
- 支持的操作系统:Windows 10+、macOS 10.15+、Linux
|
||||
- 麦克风和扬声器设备
|
||||
|
||||
## 请先看这里!
|
||||
- 仔细阅读 [项目文档](https://huangjunsen0406.github.io/py-xiaozhi/) 启动教程和文件说明都在里面了
|
||||
- main是最新代码,每次更新都需要手动重新安装一次pip依赖防止我新增依赖后你们本地没有
|
||||
|
||||
[从零开始使用小智客户端(视频教程)](https://www.bilibili.com/video/BV1dWQhYEEmq/?vd_source=2065ec11f7577e7107a55bbdc3d12fce)
|
||||
|
||||
## 配置系统
|
||||
项目使用分层配置系统,主要包括:
|
||||
|
||||
1. **基础配置**:设置基本运行参数,位于`config/config.json`
|
||||
2. **设备激活**:设备身份信息,存储在`config/efuse.json`
|
||||
3. **唤醒词配置**:语音唤醒相关设置
|
||||
4. **物联网设备**:支持各种IoT设备的配置,包括温度传感器和Home Assistant集成
|
||||
|
||||
详细配置说明请参考 [配置说明文档](./documents/docs/guide/02_配置说明.md)
|
||||
|
||||
## IoT功能
|
||||
py-xiaozhi提供丰富的IoT设备控制功能:
|
||||
|
||||
- **虚拟设备**:灯光控制、音量调节、倒计时器等
|
||||
- **物理设备集成**:温度传感器、摄像头等
|
||||
- **Home Assistant集成**:通过HTTP API接入智能家居系统
|
||||
- **自定义设备扩展**:提供完整的设备定义和注册框架
|
||||
|
||||
支持的设备类型和使用示例请参考 [IoT功能说明](./documents/docs/guide/05_IoT功能说明.md)
|
||||
|
||||
## 状态流转图
|
||||
|
||||
```
|
||||
+----------------+
|
||||
| |
|
||||
v |
|
||||
+------+ 唤醒词/按钮 +------------+ | +------------+
|
||||
| IDLE | -----------> | CONNECTING | --+-> | LISTENING |
|
||||
+------+ +------------+ +------------+
|
||||
^ |
|
||||
| | 语音识别完成
|
||||
| +------------+ v
|
||||
+--------- | SPEAKING | <-----------------+
|
||||
完成播放 +------------+
|
||||
```
|
||||
|
||||
## 待实现功能
|
||||
- [ ] **新 GUI(Electron)**:提供更现代、美观的用户界面,优化交互体验。
|
||||
|
||||
## 常见问题
|
||||
- **找不到音频设备**:请检查麦克风和扬声器是否正常连接和启用。
|
||||
- **唤醒词不响应**:请检查`config.json`中的`USE_WAKE_WORD`设置是否为`true`,以及模型路径是否正确。
|
||||
- **网络连接失败**:请检查网络设置和防火墙配置,确保WebSocket或MQTT通信未被阻止。
|
||||
- **打包失败**:确保已安装PyInstaller (`pip install pyinstaller`),并且所有依赖项都已安装。然后重新执行`python scripts/build.py`
|
||||
- **IoT设备不响应**:检查对应设备的配置信息是否正确,如Home Assistant的URL和Token。
|
||||
|
||||
## 相关第三方开源项目
|
||||
[小智手机端](https://github.com/TOM88812/xiaozhi-android-client)
|
||||
|
||||
[xiaozhi-esp32-server(开源服务端)](https://github.com/xinnan-tech/xiaozhi-esp32-server)
|
||||
|
||||
[XiaoZhiAI_server32_Unity(Unity开发)](https://gitee.com/vw112266/XiaoZhiAI_server32_Unity)
|
||||
|
||||
[IntelliConnect(Aiot中间件)](https://github.com/ruanrongman/IntelliConnect)
|
||||
|
||||
[open-xiaoai(小爱音响接入小智)](https://github.com/idootop/open-xiaoai.git)
|
||||
|
||||
## 项目结构
|
||||
|
||||
```
|
||||
├── .github # GitHub 相关配置
|
||||
├── assets # 资源文件(表情动画等)
|
||||
├── cache # 缓存目录(音乐等临时文件)
|
||||
├── config # 配置文件目录
|
||||
├── documents # 文档目录
|
||||
├── hooks # PyInstaller钩子目录
|
||||
├── libs # 依赖库目录
|
||||
├── scripts # 实用脚本目录
|
||||
├── src # 源代码目录
|
||||
│ ├── audio_codecs # 音频编解码模块
|
||||
│ ├── audio_processing # 音频处理模块
|
||||
│ ├── constants # 常量定义
|
||||
│ ├── display # 显示界面模块
|
||||
│ ├── iot # IoT设备相关模块
|
||||
│ │ └── things # 具体设备实现目录
|
||||
│ ├── network # 网络通信模块
|
||||
│ ├── protocols # 通信协议模块
|
||||
│ └── utils # 工具类模块
|
||||
```
|
||||
|
||||
## 贡献指南
|
||||
欢迎提交问题报告和代码贡献。请确保遵循以下规范:
|
||||
|
||||
1. 代码风格符合PEP8规范
|
||||
2. 提交的PR包含适当的测试
|
||||
3. 更新相关文档
|
||||
|
||||
## 社区与支持
|
||||
|
||||
### 感谢以下开源人员
|
||||
> 排名不分前后
|
||||
|
||||
[Xiaoxia](https://github.com/78)
|
||||
[zhh827](https://github.com/zhh827)
|
||||
[四博智联-李洪刚](https://github.com/SmartArduino)
|
||||
[HonestQiao](https://github.com/HonestQiao)
|
||||
[vonweller](https://github.com/vonweller)
|
||||
[孙卫公](https://space.bilibili.com/416954647)
|
||||
[isamu2025](https://github.com/isamu2025)
|
||||
[Rain120](https://github.com/Rain120)
|
||||
[kejily](https://github.com/kejily)
|
||||
[电波bilibili君](https://space.bilibili.com/119751)
|
||||
|
||||
### 赞助支持
|
||||
|
||||
<div align="center">
|
||||
<h3>感谢所有赞助者的支持 ❤️</h3>
|
||||
<p>无论是接口资源、设备兼容测试还是资金支持,每一份帮助都让项目更加完善</p>
|
||||
|
||||
<a href="https://huangjunsen0406.github.io/py-xiaozhi/sponsors/" target="_blank">
|
||||
<img src="https://img.shields.io/badge/查看-赞助者名单-brightgreen?style=for-the-badge&logo=github" alt="赞助者名单">
|
||||
</a>
|
||||
<a href="https://huangjunsen0406.github.io/py-xiaozhi/sponsors/" target="_blank">
|
||||
<img src="https://img.shields.io/badge/成为-项目赞助者-orange?style=for-the-badge&logo=heart" alt="成为赞助者">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
## 项目统计
|
||||
[](https://www.star-history.com/#huangjunsen0406/py-xiaozhi&Date)
|
||||
|
||||
## 许可证
|
||||
[MIT License](LICENSE)
|
630
py-xiaozhi-main/alsa.conf
Executable file
@ -0,0 +1,630 @@
|
||||
#
|
||||
# ALSA library configuration file
|
||||
#
|
||||
|
||||
# pre-load the configuration files
|
||||
|
||||
@hooks [
|
||||
{
|
||||
func load
|
||||
files [
|
||||
"/etc/alsa/conf.d"
|
||||
"/etc/asound.conf"
|
||||
"~/.asoundrc"
|
||||
]
|
||||
errors false
|
||||
}
|
||||
]
|
||||
|
||||
# load card-specific configuration files (on request)
|
||||
|
||||
cards.@hooks [
|
||||
{
|
||||
func load
|
||||
files [
|
||||
{
|
||||
@func concat
|
||||
strings [
|
||||
{ @func datadir }
|
||||
"/cards/aliases.conf"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
{
|
||||
func load_for_all_cards
|
||||
files [
|
||||
{
|
||||
@func concat
|
||||
strings [
|
||||
{ @func datadir }
|
||||
"/cards/"
|
||||
{ @func private_string }
|
||||
".conf"
|
||||
]
|
||||
}
|
||||
]
|
||||
errors false
|
||||
}
|
||||
]
|
||||
|
||||
#
|
||||
# defaults
|
||||
#
|
||||
|
||||
# show all name hints also for definitions without hint {} section
|
||||
defaults.namehint.showall on
|
||||
# show just basic name hints
|
||||
defaults.namehint.basic on
|
||||
# show extended name hints
|
||||
defaults.namehint.extended on
|
||||
#
|
||||
defaults.ctl.card 0
|
||||
defaults.pcm.card 5
|
||||
defaults.pcm.device 0
|
||||
defaults.pcm.subdevice -1
|
||||
defaults.pcm.nonblock 1
|
||||
defaults.pcm.compat 0
|
||||
defaults.pcm.minperiodtime 5000 # in us
|
||||
defaults.pcm.ipc_key 5678293
|
||||
defaults.pcm.ipc_gid audio
|
||||
defaults.pcm.ipc_perm 0660
|
||||
defaults.pcm.dmix.max_periods 0
|
||||
defaults.pcm.dmix.channels 2
|
||||
defaults.pcm.dmix.rate 48000
|
||||
defaults.pcm.dmix.format "unchanged"
|
||||
defaults.pcm.dmix.card defaults.pcm.card
|
||||
defaults.pcm.dmix.device defaults.pcm.device
|
||||
defaults.pcm.dsnoop.card defaults.pcm.card
|
||||
defaults.pcm.dsnoop.device defaults.pcm.device
|
||||
defaults.pcm.front.card defaults.pcm.card
|
||||
defaults.pcm.front.device defaults.pcm.device
|
||||
defaults.pcm.rear.card defaults.pcm.card
|
||||
defaults.pcm.rear.device defaults.pcm.device
|
||||
defaults.pcm.center_lfe.card defaults.pcm.card
|
||||
defaults.pcm.center_lfe.device defaults.pcm.device
|
||||
defaults.pcm.side.card defaults.pcm.card
|
||||
defaults.pcm.side.device defaults.pcm.device
|
||||
defaults.pcm.surround21.card defaults.pcm.card
|
||||
defaults.pcm.surround21.device defaults.pcm.device
|
||||
defaults.pcm.surround40.card defaults.pcm.card
|
||||
defaults.pcm.surround40.device defaults.pcm.device
|
||||
defaults.pcm.surround41.card defaults.pcm.card
|
||||
defaults.pcm.surround41.device defaults.pcm.device
|
||||
defaults.pcm.surround50.card defaults.pcm.card
|
||||
defaults.pcm.surround50.device defaults.pcm.device
|
||||
defaults.pcm.surround51.card defaults.pcm.card
|
||||
defaults.pcm.surround51.device defaults.pcm.device
|
||||
defaults.pcm.surround71.card defaults.pcm.card
|
||||
defaults.pcm.surround71.device defaults.pcm.device
|
||||
defaults.pcm.iec958.card defaults.pcm.card
|
||||
defaults.pcm.iec958.device defaults.pcm.device
|
||||
defaults.pcm.modem.card defaults.pcm.card
|
||||
defaults.pcm.modem.device defaults.pcm.device
|
||||
# truncate files via file or tee PCM
|
||||
defaults.pcm.file_format "raw"
|
||||
defaults.pcm.file_truncate true
|
||||
defaults.rawmidi.card 0
|
||||
defaults.rawmidi.device 0
|
||||
defaults.rawmidi.subdevice -1
|
||||
defaults.hwdep.card 0
|
||||
defaults.hwdep.device 0
|
||||
defaults.timer.class 2
|
||||
defaults.timer.sclass 0
|
||||
defaults.timer.card 0
|
||||
defaults.timer.device 0
|
||||
defaults.timer.subdevice 0
|
||||
|
||||
#
|
||||
# PCM interface
|
||||
#
|
||||
|
||||
# redirect to load-on-demand extended pcm definitions
|
||||
pcm.cards cards.pcm
|
||||
|
||||
pcm.default cards.pcm.default
|
||||
pcm.sysdefault cards.pcm.default
|
||||
pcm.front cards.pcm.front
|
||||
pcm.rear cards.pcm.rear
|
||||
pcm.center_lfe cards.pcm.center_lfe
|
||||
pcm.side cards.pcm.side
|
||||
pcm.surround21 cards.pcm.surround21
|
||||
pcm.surround40 cards.pcm.surround40
|
||||
pcm.surround41 cards.pcm.surround41
|
||||
pcm.surround50 cards.pcm.surround50
|
||||
pcm.surround51 cards.pcm.surround51
|
||||
pcm.surround71 cards.pcm.surround71
|
||||
pcm.iec958 cards.pcm.iec958
|
||||
#pcm.spdif
|
||||
iec958
|
||||
pcm.hdmi cards.pcm.hdmi
|
||||
pcm.dmix cards.pcm.dmix
|
||||
pcm.dsnoop cards.pcm.dsnoop
|
||||
pcm.modem cards.pcm.modem
|
||||
pcm.phoneline cards.pcm.phoneline
|
||||
|
||||
pcm.hw {
|
||||
@args [ CARD DEV SUBDEV ]
|
||||
@args.CARD {
|
||||
type string
|
||||
default {
|
||||
@func getenv
|
||||
vars [
|
||||
ALSA_PCM_CARD
|
||||
ALSA_CARD
|
||||
]
|
||||
default {
|
||||
@func refer
|
||||
name defaults.pcm.card
|
||||
}
|
||||
}
|
||||
}
|
||||
@args.DEV {
|
||||
type integer
|
||||
default {
|
||||
@func igetenv
|
||||
vars [
|
||||
ALSA_PCM_DEVICE
|
||||
]
|
||||
default {
|
||||
@func refer
|
||||
name defaults.pcm.device
|
||||
}
|
||||
}
|
||||
}
|
||||
@args.SUBDEV {
|
||||
type integer
|
||||
default {
|
||||
@func refer
|
||||
name defaults.pcm.subdevice
|
||||
}
|
||||
}
|
||||
type hw
|
||||
card $CARD
|
||||
device $DEV
|
||||
subdevice $SUBDEV
|
||||
hint {
|
||||
show {
|
||||
@func refer
|
||||
name defaults.namehint.extended
|
||||
}
|
||||
description "Direct hardware device without any conversions"
|
||||
}
|
||||
}
|
||||
|
||||
pcm.plughw {
|
||||
@args [ CARD DEV SUBDEV ]
|
||||
@args.CARD {
|
||||
type string
|
||||
default {
|
||||
@func getenv
|
||||
vars [
|
||||
ALSA_PCM_CARD
|
||||
ALSA_CARD
|
||||
]
|
||||
default {
|
||||
@func refer
|
||||
name defaults.pcm.card
|
||||
}
|
||||
}
|
||||
}
|
||||
@args.DEV {
|
||||
type integer
|
||||
default {
|
||||
@func igetenv
|
||||
vars [
|
||||
ALSA_PCM_DEVICE
|
||||
]
|
||||
default {
|
||||
@func refer
|
||||
name defaults.pcm.device
|
||||
}
|
||||
}
|
||||
}
|
||||
@args.SUBDEV {
|
||||
type integer
|
||||
default {
|
||||
@func refer
|
||||
name defaults.pcm.subdevice
|
||||
}
|
||||
}
|
||||
type plug
|
||||
slave.pcm {
|
||||
type hw
|
||||
card $CARD
|
||||
device $DEV
|
||||
subdevice $SUBDEV
|
||||
}
|
||||
hint {
|
||||
show {
|
||||
@func refer
|
||||
name defaults.namehint.extended
|
||||
}
|
||||
description "Hardware device with all software conversions"
|
||||
}
|
||||
}
|
||||
|
||||
pcm.plug {
|
||||
@args [ SLAVE ]
|
||||
@args.SLAVE {
|
||||
type string
|
||||
}
|
||||
type plug
|
||||
slave.pcm $SLAVE
|
||||
}
|
||||
|
||||
pcm.shm {
|
||||
@args [ SOCKET PCM ]
|
||||
@args.SOCKET {
|
||||
type string
|
||||
}
|
||||
@args.PCM {
|
||||
type string
|
||||
}
|
||||
type shm
|
||||
server $SOCKET
|
||||
pcm $PCM
|
||||
}
|
||||
|
||||
pcm.tee {
|
||||
@args [ SLAVE FILE FORMAT ]
|
||||
@args.SLAVE {
|
||||
type string
|
||||
}
|
||||
@args.FILE {
|
||||
type string
|
||||
}
|
||||
@args.FORMAT {
|
||||
type string
|
||||
default {
|
||||
@func refer
|
||||
name defaults.pcm.file_format
|
||||
}
|
||||
}
|
||||
type file
|
||||
slave.pcm $SLAVE
|
||||
file $FILE
|
||||
format $FORMAT
|
||||
truncate {
|
||||
@func refer
|
||||
name defaults.pcm.file_truncate
|
||||
}
|
||||
}
|
||||
|
||||
pcm.file {
|
||||
@args [ FILE FORMAT ]
|
||||
@args.FILE {
|
||||
type string
|
||||
}
|
||||
@args.FORMAT {
|
||||
type string
|
||||
default {
|
||||
@func refer
|
||||
name defaults.pcm.file_format
|
||||
}
|
||||
}
|
||||
type file
|
||||
slave.pcm null
|
||||
file $FILE
|
||||
format $FORMAT
|
||||
truncate {
|
||||
@func refer
|
||||
name defaults.pcm.file_truncate
|
||||
}
|
||||
}
|
||||
|
||||
pcm.null {
|
||||
type null
|
||||
hint {
|
||||
show {
|
||||
@func refer
|
||||
name defaults.namehint.basic
|
||||
}
|
||||
description "Discard all samples (playback) or generate zero samples (capture)"
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Control interface
|
||||
#
|
||||
|
||||
ctl.sysdefault {
|
||||
type hw
|
||||
card {
|
||||
@func getenv
|
||||
vars [
|
||||
ALSA_CTL_CARD
|
||||
ALSA_CARD
|
||||
]
|
||||
default {
|
||||
@func refer
|
||||
name defaults.ctl.card
|
||||
}
|
||||
}
|
||||
hint.description "Default control device"
|
||||
}
|
||||
ctl.default ctl.sysdefault
|
||||
|
||||
ctl.hw {
|
||||
@args [ CARD ]
|
||||
@args.CARD {
|
||||
type string
|
||||
default {
|
||||
@func getenv
|
||||
vars [
|
||||
ALSA_CTL_CARD
|
||||
ALSA_CARD
|
||||
]
|
||||
default {
|
||||
@func refer
|
||||
name defaults.ctl.card
|
||||
}
|
||||
}
|
||||
}
|
||||
type hw
|
||||
card $CARD
|
||||
hint.description "Direct control device"
|
||||
}
|
||||
|
||||
ctl.shm {
|
||||
@args [ SOCKET CTL ]
|
||||
@args.SOCKET {
|
||||
type string
|
||||
}
|
||||
@args.CTL {
|
||||
type string
|
||||
}
|
||||
type shm
|
||||
server $SOCKET
|
||||
ctl $CTL
|
||||
}
|
||||
|
||||
#
|
||||
# RawMidi interface
|
||||
#
|
||||
|
||||
rawmidi.default {
|
||||
type hw
|
||||
card {
|
||||
@func getenv
|
||||
vars [
|
||||
ALSA_RAWMIDI_CARD
|
||||
ALSA_CARD
|
||||
]
|
||||
default {
|
||||
@func refer
|
||||
name defaults.rawmidi.card
|
||||
}
|
||||
}
|
||||
device {
|
||||
@func igetenv
|
||||
vars [
|
||||
ALSA_RAWMIDI_DEVICE
|
||||
]
|
||||
default {
|
||||
@func refer
|
||||
name defaults.rawmidi.device
|
||||
}
|
||||
}
|
||||
hint.description "Default raw MIDI device"
|
||||
}
|
||||
|
||||
rawmidi.hw {
|
||||
@args [ CARD DEV SUBDEV ]
|
||||
@args.CARD {
|
||||
type string
|
||||
default {
|
||||
@func getenv
|
||||
vars [
|
||||
ALSA_RAWMIDI_CARD
|
||||
ALSA_CARD
|
||||
]
|
||||
default {
|
||||
@func refer
|
||||
name defaults.rawmidi.card
|
||||
}
|
||||
}
|
||||
}
|
||||
@args.DEV {
|
||||
type integer
|
||||
default {
|
||||
@func igetenv
|
||||
vars [
|
||||
ALSA_RAWMIDI_DEVICE
|
||||
]
|
||||
default {
|
||||
@func refer
|
||||
name defaults.rawmidi.device
|
||||
}
|
||||
}
|
||||
}
|
||||
@args.SUBDEV {
|
||||
type integer
|
||||
default -1
|
||||
}
|
||||
type hw
|
||||
card $CARD
|
||||
device $DEV
|
||||
subdevice $SUBDEV
|
||||
hint {
|
||||
description "Direct rawmidi driver device"
|
||||
device $DEV
|
||||
}
|
||||
}
|
||||
|
||||
rawmidi.virtual {
|
||||
@args [ MERGE ]
|
||||
@args.MERGE {
|
||||
type string
|
||||
default 1
|
||||
}
|
||||
type virtual
|
||||
merge $MERGE
|
||||
}
|
||||
|
||||
#
|
||||
# Sequencer interface
|
||||
#
|
||||
|
||||
seq.default {
|
||||
type hw
|
||||
hint.description "Default sequencer device"
|
||||
}
|
||||
|
||||
seq.hw {
|
||||
type hw
|
||||
}
|
||||
|
||||
#
|
||||
# HwDep interface
|
||||
#
|
||||
|
||||
hwdep.default {
|
||||
type hw
|
||||
card {
|
||||
@func getenv
|
||||
vars [
|
||||
ALSA_HWDEP_CARD
|
||||
ALSA_CARD
|
||||
]
|
||||
default {
|
||||
@func refer
|
||||
name defaults.hwdep.card
|
||||
}
|
||||
}
|
||||
device {
|
||||
@func igetenv
|
||||
vars [
|
||||
ALSA_HWDEP_DEVICE
|
||||
]
|
||||
default {
|
||||
@func refer
|
||||
name defaults.hwdep.device
|
||||
}
|
||||
}
|
||||
hint.description "Default hardware dependent device"
|
||||
}
|
||||
|
||||
hwdep.hw {
|
||||
@args [ CARD DEV ]
|
||||
@args.CARD {
|
||||
type string
|
||||
default {
|
||||
@func getenv
|
||||
vars [
|
||||
ALSA_HWDEP_CARD
|
||||
ALSA_CARD
|
||||
]
|
||||
default {
|
||||
@func refer
|
||||
name defaults.hwdep.card
|
||||
}
|
||||
}
|
||||
}
|
||||
@args.DEV {
|
||||
type integer
|
||||
default {
|
||||
@func igetenv
|
||||
vars [
|
||||
ALSA_HWDEP_DEVICE
|
||||
]
|
||||
default {
|
||||
@func refer
|
||||
name defaults.hwdep.device
|
||||
}
|
||||
}
|
||||
}
|
||||
type hw
|
||||
card $CARD
|
||||
device $DEV
|
||||
hint {
|
||||
description "Direct hardware dependent device"
|
||||
device $DEV
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Timer interface
|
||||
#
|
||||
|
||||
timer_query.default {
|
||||
type hw
|
||||
}
|
||||
|
||||
timer_query.hw {
|
||||
type hw
|
||||
}
|
||||
|
||||
timer.default {
|
||||
type hw
|
||||
class {
|
||||
@func refer
|
||||
name defaults.timer.class
|
||||
}
|
||||
sclass {
|
||||
@func refer
|
||||
name defaults.timer.sclass
|
||||
}
|
||||
card {
|
||||
@func refer
|
||||
name defaults.timer.card
|
||||
}
|
||||
device {
|
||||
@func refer
|
||||
name defaults.timer.device
|
||||
}
|
||||
subdevice {
|
||||
@func refer
|
||||
name defaults.timer.subdevice
|
||||
}
|
||||
hint.description "Default timer device"
|
||||
}
|
||||
|
||||
timer.hw {
|
||||
@args [ CLASS SCLASS CARD DEV SUBDEV ]
|
||||
@args.CLASS {
|
||||
type integer
|
||||
default {
|
||||
@func refer
|
||||
name defaults.timer.class
|
||||
}
|
||||
}
|
||||
@args.SCLASS {
|
||||
type integer
|
||||
default {
|
||||
@func refer
|
||||
name defaults.timer.sclass
|
||||
}
|
||||
}
|
||||
@args.CARD {
|
||||
type string
|
||||
default {
|
||||
@func refer
|
||||
name defaults.timer.card
|
||||
}
|
||||
}
|
||||
@args.DEV {
|
||||
type integer
|
||||
default {
|
||||
@func refer
|
||||
name defaults.timer.device
|
||||
}
|
||||
}
|
||||
@args.SUBDEV {
|
||||
type integer
|
||||
default {
|
||||
@func refer
|
||||
name defaults.timer.subdevice
|
||||
}
|
||||
}
|
||||
type hw
|
||||
class $CLASS
|
||||
sclass $SCLASS
|
||||
card $CARD
|
||||
device $DEV
|
||||
subdevice $SUBDEV
|
||||
hint {
|
||||
description "Direct timer device"
|
||||
device $DEV
|
||||
}
|
||||
}
|
BIN
py-xiaozhi-main/assets/emojis/angry.gif
Executable file
After Width: | Height: | Size: 487 KiB |
BIN
py-xiaozhi-main/assets/emojis/confident.gif
Executable file
After Width: | Height: | Size: 563 KiB |
BIN
py-xiaozhi-main/assets/emojis/confused.gif
Executable file
After Width: | Height: | Size: 1.1 MiB |
BIN
py-xiaozhi-main/assets/emojis/cool.gif
Executable file
After Width: | Height: | Size: 642 KiB |
BIN
py-xiaozhi-main/assets/emojis/crying.gif
Executable file
After Width: | Height: | Size: 691 KiB |
BIN
py-xiaozhi-main/assets/emojis/delicious.gif
Executable file
After Width: | Height: | Size: 847 KiB |
BIN
py-xiaozhi-main/assets/emojis/embarrassed.gif
Executable file
After Width: | Height: | Size: 652 KiB |
BIN
py-xiaozhi-main/assets/emojis/funny.gif
Executable file
After Width: | Height: | Size: 711 KiB |
BIN
py-xiaozhi-main/assets/emojis/happy.gif
Executable file
After Width: | Height: | Size: 572 KiB |
BIN
py-xiaozhi-main/assets/emojis/kissy.gif
Executable file
After Width: | Height: | Size: 660 KiB |
BIN
py-xiaozhi-main/assets/emojis/laughing.gif
Executable file
After Width: | Height: | Size: 1.2 MiB |
BIN
py-xiaozhi-main/assets/emojis/loving.gif
Executable file
After Width: | Height: | Size: 573 KiB |
BIN
py-xiaozhi-main/assets/emojis/neutral.gif
Executable file
After Width: | Height: | Size: 196 KiB |
BIN
py-xiaozhi-main/assets/emojis/relaxed.gif
Executable file
After Width: | Height: | Size: 901 KiB |
BIN
py-xiaozhi-main/assets/emojis/sad.gif
Executable file
After Width: | Height: | Size: 1.0 MiB |
BIN
py-xiaozhi-main/assets/emojis/shocked.gif
Executable file
After Width: | Height: | Size: 686 KiB |
BIN
py-xiaozhi-main/assets/emojis/silly.gif
Executable file
After Width: | Height: | Size: 494 KiB |
BIN
py-xiaozhi-main/assets/emojis/sleepy.gif
Executable file
After Width: | Height: | Size: 761 KiB |
BIN
py-xiaozhi-main/assets/emojis/surprised.gif
Executable file
After Width: | Height: | Size: 298 KiB |
BIN
py-xiaozhi-main/assets/emojis/thinking.gif
Executable file
After Width: | Height: | Size: 802 KiB |
BIN
py-xiaozhi-main/assets/emojis/winking.gif
Executable file
After Width: | Height: | Size: 655 KiB |
46
py-xiaozhi-main/build.json
Executable file
@ -0,0 +1,46 @@
|
||||
{
|
||||
"name": "xiaozhi",
|
||||
"version": "1.0.0",
|
||||
"publisher": "Junsen",
|
||||
"entry": "main.py",
|
||||
"icon": "assets/xiaozhi_icon.ico",
|
||||
"hooks": "hooks",
|
||||
"onefile": false,
|
||||
"additional_pyinstaller_args": "--add-data assets;assets --add-data libs;libs --add-data src;src --add-data models;models --hidden-import=PyQt5",
|
||||
"inno_setup_path": "E:\\application\\Inno Setup 6\\ISCC.exe",
|
||||
"platform_specific": {
|
||||
"windows": {
|
||||
"format": "exe",
|
||||
"additional_pyinstaller_args": "--add-data assets;assets --add-data libs;libs --add-data src;src --add-data models;models --hidden-import=PyQt5 --noconsole",
|
||||
"desktop_entry": true,
|
||||
"installer_options": {
|
||||
"languages": ["ChineseSimplified", "English"],
|
||||
"license_file": "LICENSE",
|
||||
"readme_file": "README.md",
|
||||
"create_desktop_icon": true,
|
||||
"allow_run_after_install": true
|
||||
}
|
||||
},
|
||||
"linux": {
|
||||
"format": "deb",
|
||||
"desktop_entry": true,
|
||||
"categories": "Utility;Development;",
|
||||
"description": "小智Ai客户端",
|
||||
"requires": "libc6,libgtk-3-0,libx11-6,libopenblas-dev",
|
||||
"additional_pyinstaller_args": "--add-data assets:assets --add-data libs:libs --add-data src:src --add-data models:models --hidden-import=PyQt5"
|
||||
},
|
||||
"macos": {
|
||||
"format": "app",
|
||||
"additional_pyinstaller_args": "--add-data assets:assets --add-data libs:libs --add-data src:src --add-data models:models --hidden-import=PyQt5 --windowed",
|
||||
"app_bundle_name": "XiaoZhi.app",
|
||||
"bundle_identifier": "com.junsen.xiaozhi",
|
||||
"sign_bundle": false,
|
||||
"create_dmg": true,
|
||||
"installer_options": {
|
||||
"license_file": "LICENSE",
|
||||
"readme_file": "README.md"
|
||||
}
|
||||
}
|
||||
},
|
||||
"build_installer": true
|
||||
}
|
2
py-xiaozhi-main/documents/.gitignore
vendored
Executable file
@ -0,0 +1,2 @@
|
||||
dist
|
||||
node_modules
|
74
py-xiaozhi-main/documents/README.md
Executable file
@ -0,0 +1,74 @@
|
||||
# py-xiaozhi 文档
|
||||
|
||||
这是 py-xiaozhi 项目的文档网站,基于 VitePress 构建。
|
||||
|
||||
## 功能
|
||||
|
||||
- 项目指南:提供项目的详细使用说明和开发文档
|
||||
- 赞助商页面:展示并感谢项目的所有赞助者
|
||||
- 贡献指南:说明如何为项目贡献代码
|
||||
- 贡献者名单:展示所有为项目做出贡献的开发者
|
||||
- 响应式设计:适配桌面和移动设备
|
||||
|
||||
## 本地开发
|
||||
|
||||
```bash
|
||||
# 安装依赖
|
||||
pnpm install
|
||||
|
||||
# 启动开发服务器
|
||||
pnpm docs:dev
|
||||
|
||||
# 构建静态文件
|
||||
pnpm docs:build
|
||||
|
||||
# 预览构建结果
|
||||
pnpm docs:preview
|
||||
```
|
||||
|
||||
## 目录结构
|
||||
|
||||
```
|
||||
documents/
|
||||
├── docs/ # 文档源文件
|
||||
│ ├── .vitepress/ # VitePress 配置
|
||||
│ ├── guide/ # 指南文档
|
||||
│ ├── sponsors/ # 赞助商页面
|
||||
│ ├── contributing.md # 贡献指南
|
||||
│ ├── contributors.md # 贡献者名单
|
||||
│ └── index.md # 首页
|
||||
├── package.json # 项目配置
|
||||
└── README.md # 项目说明
|
||||
```
|
||||
|
||||
## 赞助商页面
|
||||
|
||||
赞助商页面通过以下方式实现:
|
||||
|
||||
1. `/sponsors/` 目录包含了赞助商相关的内容
|
||||
2. `data.json` 文件存储赞助商数据
|
||||
3. 使用 Vue 组件在客户端动态渲染赞助商列表
|
||||
4. 提供成为赞助者的详细说明和支付方式
|
||||
|
||||
## 贡献指南
|
||||
|
||||
贡献指南页面提供了以下内容:
|
||||
|
||||
1. 开发环境准备指南
|
||||
2. 代码贡献流程说明
|
||||
3. 编码规范和提交规范
|
||||
4. Pull Request 创建和审核流程
|
||||
5. 文档贡献指南
|
||||
|
||||
## 贡献者名单
|
||||
|
||||
贡献者名单页面展示了所有为项目做出贡献的开发者,包括:
|
||||
|
||||
1. 核心开发团队成员
|
||||
2. 代码贡献者
|
||||
3. 文档贡献者
|
||||
4. 测试和反馈提供者
|
||||
|
||||
## 部署
|
||||
|
||||
文档网站通过 GitHub Actions 自动部署到 GitHub Pages。
|
74
py-xiaozhi-main/documents/docs/.vitepress/config.mts
Executable file
@ -0,0 +1,74 @@
|
||||
import { defineConfig } from 'vitepress'
|
||||
import { getGuideSideBarItems } from './guide'
|
||||
import tailwindcss from '@tailwindcss/vite'
|
||||
// https://vitepress.dev/reference/site-config
|
||||
export default defineConfig({
|
||||
title: "PY-XIAOZHI",
|
||||
description: "py-xiaozhi 是一个使用 Python 实现的小智语音客户端,旨在通过代码学习和在没有硬件条件下体验 AI 小智的语音功能。",
|
||||
base: '/py-xiaozhi/',
|
||||
themeConfig: {
|
||||
// https://vitepress.dev/reference/default-theme-config
|
||||
nav: [
|
||||
{ text: '主页', link: '/' },
|
||||
{ text: '指南', link: '/guide/00_文档目录' },
|
||||
{ text: '系统架构', link: '/architecture/' },
|
||||
{ text: '相关生态', link: '/ecosystem/' },
|
||||
{ text: '团队', link: '/about/team' },
|
||||
{ text: '贡献指南', link: '/contributing' },
|
||||
{ text: '赞助', link: '/sponsors/' }
|
||||
],
|
||||
|
||||
sidebar: {
|
||||
'/guide/': [
|
||||
{
|
||||
text: '指南',
|
||||
// 默认展开
|
||||
collapsed: false,
|
||||
items: getGuideSideBarItems(),
|
||||
},
|
||||
{
|
||||
text: '旧版文档',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: '使用文档', link: '/guide/old_docs/使用文档' }
|
||||
]
|
||||
}
|
||||
],
|
||||
'/ecosystem/': [
|
||||
{
|
||||
text: '生态系统概览',
|
||||
link: '/ecosystem/'
|
||||
},
|
||||
{
|
||||
text: '相关项目',
|
||||
collapsed: false,
|
||||
items: [
|
||||
{ text: '小智手机端', link: '/ecosystem/projects/xiaozhi-android-client/' },
|
||||
{ text: 'xiaozhi-esp32-server', link: '/ecosystem/projects/xiaozhi-esp32-server/' },
|
||||
{ text: 'XiaoZhiAI_server32_Unity', link: '/ecosystem/projects/xiaozhi-unity/' },
|
||||
{ text: 'IntelliConnect', link: '/ecosystem/projects/intelliconnect/' },
|
||||
{ text: 'open-xiaoai', link: '/ecosystem/projects/open-xiaoai/' }
|
||||
]
|
||||
},
|
||||
],
|
||||
'/about/': [],
|
||||
// 赞助页面不显示侧边栏
|
||||
'/sponsors/': [],
|
||||
// 贡献指南页面不显示侧边栏
|
||||
'/contributing': [],
|
||||
// 系统架构页面不显示侧边栏
|
||||
'/architecture/': [],
|
||||
// 团队页面不显示侧边栏
|
||||
'/about/team': []
|
||||
},
|
||||
|
||||
socialLinks: [
|
||||
{ icon: 'github', link: 'https://github.com/huangjunsen0406/py-xiaozhi' }
|
||||
]
|
||||
},
|
||||
vite: {
|
||||
plugins: [
|
||||
tailwindcss()
|
||||
]
|
||||
}
|
||||
})
|
15
py-xiaozhi-main/documents/docs/.vitepress/guide/index.ts
Executable file
@ -0,0 +1,15 @@
|
||||
import { getMdFilesAsync } from "../utils";
|
||||
import path from 'path';
|
||||
import { DefaultTheme } from 'vitepress';
|
||||
|
||||
export function getGuideSideBarItems(): (DefaultTheme.SidebarItem)[] {
|
||||
return getMdFilesAsync(path.resolve(__dirname, '../../guide'))
|
||||
.map(item => {
|
||||
return {
|
||||
text: item,
|
||||
link: `/guide/${item}`
|
||||
}
|
||||
}).filter(item => {
|
||||
return !item.text.includes('使用文档')
|
||||
})
|
||||
}
|
7
py-xiaozhi-main/documents/docs/.vitepress/theme/index.ts
Executable file
@ -0,0 +1,7 @@
|
||||
import DefaultTheme from 'vitepress/theme'
|
||||
import './styles/index.css'
|
||||
import './styles/custom.scss'
|
||||
|
||||
export default {
|
||||
...DefaultTheme,
|
||||
}
|
28
py-xiaozhi-main/documents/docs/.vitepress/theme/styles/badges.css
Executable file
@ -0,0 +1,28 @@
|
||||
.vt-badge.wip:before {
|
||||
content: 'WIP';
|
||||
}
|
||||
|
||||
.vt-badge.ts {
|
||||
background-color: #3178c6;
|
||||
}
|
||||
.vt-badge.ts:before {
|
||||
content: 'TS';
|
||||
}
|
||||
|
||||
.vt-badge.dev-only,
|
||||
.vt-badge.experimental {
|
||||
color: var(--vt-c-text-light-1);
|
||||
background-color: var(--vt-c-yellow);
|
||||
}
|
||||
|
||||
.vt-badge.dev-only:before {
|
||||
content: 'Dev only';
|
||||
}
|
||||
|
||||
.vt-badge.experimental:before {
|
||||
content: 'Experimental';
|
||||
}
|
||||
|
||||
.vt-badge[data-text]:before {
|
||||
content: attr(data-text);
|
||||
}
|
26
py-xiaozhi-main/documents/docs/.vitepress/theme/styles/custom.scss
Executable file
@ -0,0 +1,26 @@
|
||||
.architecture-page-class {
|
||||
@media (min-width: 1440px) {
|
||||
|
||||
.VPDoc:not(.has-sidebar) .content {
|
||||
|
||||
max-width: 1284px !important; /* <-- update your values */
|
||||
|
||||
}
|
||||
|
||||
.VPDoc:not(.has-sidebar) .container {
|
||||
|
||||
max-width: 1604px !important;
|
||||
|
||||
}
|
||||
.VPDoc.has-aside .content-container {
|
||||
max-width: 1188px !important;
|
||||
}
|
||||
|
||||
.vp-doc h3 {
|
||||
margin: 0;
|
||||
}
|
||||
.vp-doc ul {
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
}
|
7
py-xiaozhi-main/documents/docs/.vitepress/theme/styles/index.css
Executable file
@ -0,0 +1,7 @@
|
||||
@import "./pages.css";
|
||||
@import "./badges.css";
|
||||
@import "./options-boxes.css";
|
||||
@import "./inline-demo.css";
|
||||
@import "./utilities.css";
|
||||
@import "./style-guide.css";
|
||||
@import "tailwindcss";
|
90
py-xiaozhi-main/documents/docs/.vitepress/theme/styles/inline-demo.css
Executable file
@ -0,0 +1,90 @@
|
||||
.vt-doc a[href^="https://play.vuejs.org"]:before
|
||||
{
|
||||
content: '▶';
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
display: inline-flex;
|
||||
border-radius: 10px;
|
||||
vertical-align: middle;
|
||||
position: relative;
|
||||
top: -2px;
|
||||
color: var(--vt-c-green);
|
||||
border: 2px solid var(--vt-c-green);
|
||||
margin-right: 8px;
|
||||
margin-left: 4px;
|
||||
line-height: 16px;
|
||||
padding-left: 4.2px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.demo {
|
||||
padding: 22px 24px;
|
||||
border-radius: 8px;
|
||||
box-shadow: var(--vt-shadow-2);
|
||||
margin-bottom: 1.2em;
|
||||
transition: background-color 0.5s ease;
|
||||
}
|
||||
|
||||
.dark .demo {
|
||||
background-color: var(--vt-c-bg-soft);
|
||||
}
|
||||
|
||||
.demo p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.demo button {
|
||||
background-color: var(--vt-c-bg-mute);
|
||||
transition: background-color 0.5s;
|
||||
padding: 5px 12px;
|
||||
border: 1px solid var(--vt-c-divider);
|
||||
border-radius: 8px;
|
||||
font-size: 0.9em;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.demo button + button {
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
.demo input,
|
||||
.demo textarea,
|
||||
.demo select {
|
||||
border: 1px solid var(--vt-c-divider);
|
||||
border-radius: 4px;
|
||||
padding: 0.2em 0.6em;
|
||||
margin-top: 10px;
|
||||
background: transparent;
|
||||
transition: background-color 0.5s;
|
||||
}
|
||||
|
||||
.dark .demo select {
|
||||
background: var(--vt-c-bg-soft);
|
||||
}
|
||||
|
||||
.dark .demo select option {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.demo input:not([type]):focus,
|
||||
.demo textarea:focus,
|
||||
.demo select:focus {
|
||||
outline: 1px solid blue;
|
||||
}
|
||||
|
||||
.demo select {
|
||||
/* this was set by normalize.css */
|
||||
-webkit-appearance: listbox;
|
||||
}
|
||||
|
||||
.demo label {
|
||||
margin: 0 1em 0 0.4em;
|
||||
}
|
||||
|
||||
.demo select[multiple] {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.demo h1 {
|
||||
margin: 10px 0 0;
|
||||
}
|
27
py-xiaozhi-main/documents/docs/.vitepress/theme/styles/options-boxes.css
Executable file
@ -0,0 +1,27 @@
|
||||
.next-steps {
|
||||
margin-top: 3rem;
|
||||
}
|
||||
|
||||
.next-steps .vt-box {
|
||||
border: 1px solid var(--vt-c-bg-soft);
|
||||
}
|
||||
|
||||
.next-steps .vt-box:hover {
|
||||
border-color: var(--vt-c-green-light);
|
||||
transition: border-color 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
|
||||
}
|
||||
|
||||
.vt-doc .next-steps-link {
|
||||
font-size: 20px;
|
||||
line-height: 1.4;
|
||||
letter-spacing: -0.02em;
|
||||
margin-bottom: 0.75em;
|
||||
display: block;
|
||||
color: var(--vt-c-green);
|
||||
}
|
||||
|
||||
.vt-doc .next-steps-caption {
|
||||
margin-bottom: 0;
|
||||
color: var(--vt-c-text-2);
|
||||
transition: color 0.5s;
|
||||
}
|
15
py-xiaozhi-main/documents/docs/.vitepress/theme/styles/pages.css
Executable file
@ -0,0 +1,15 @@
|
||||
/* always show anchors on /api/ and /style-guide/ pages */
|
||||
.vt-doc.api h2 .header-anchor,
|
||||
.vt-doc.style-guide h2 .header-anchor {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.vt-doc.sponsor h3 {
|
||||
text-align: center;
|
||||
padding-bottom: 1em;
|
||||
border-bottom: 1px solid var(--vt-c-divider-light);
|
||||
}
|
||||
|
||||
.vt-doc.sponsor h3 .header-anchor {
|
||||
display: none;
|
||||
}
|
65
py-xiaozhi-main/documents/docs/.vitepress/theme/styles/style-guide.css
Executable file
@ -0,0 +1,65 @@
|
||||
.style-example {
|
||||
border-radius: 8px 8px 12px 12px;
|
||||
margin: 1.6em 0;
|
||||
padding: 1.6em 1.6em 0.1px;
|
||||
position: relative;
|
||||
border: 1px solid transparent;
|
||||
transition: background-color 0.25s ease, border-color 0.25s ease;
|
||||
}
|
||||
|
||||
.vt-doc .style-example h3 {
|
||||
margin: 0;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
.style-example-bad {
|
||||
background: #f7e8e8;
|
||||
}
|
||||
.dark .style-example-bad {
|
||||
background: transparent;
|
||||
border-color: var(--vt-c-red);
|
||||
}
|
||||
|
||||
.style-example-bad h3 {
|
||||
color: var(--vt-c-red);
|
||||
}
|
||||
|
||||
.style-example-good {
|
||||
background: #ecfaf7;
|
||||
}
|
||||
.dark .style-example-good {
|
||||
background: transparent;
|
||||
border-color: var(--vt-c-green);
|
||||
}
|
||||
|
||||
.style-example-good h3 {
|
||||
color: var(--vt-c-green);
|
||||
}
|
||||
|
||||
.details summary {
|
||||
font-weight: bold !important;
|
||||
}
|
||||
|
||||
.style-verb {
|
||||
font-size: 0.6em;
|
||||
display: inline-block;
|
||||
border-radius: 6px;
|
||||
font-size: 0.65em;
|
||||
line-height: 1;
|
||||
font-weight: 600;
|
||||
padding: 0.35em 0.4em 0.3em;
|
||||
position: relative;
|
||||
top: -0.15em;
|
||||
margin-right: 0.5em;
|
||||
color: var(--vt-c-bg);
|
||||
transition: color 0.5s;
|
||||
background-color: var(--vt-c-brand);
|
||||
}
|
||||
|
||||
.style-verb.avoid {
|
||||
background-color: var(--vt-c-red);
|
||||
}
|
||||
.vt-doc summary {
|
||||
width: fit-content;
|
||||
cursor: pointer;
|
||||
}
|
14
py-xiaozhi-main/documents/docs/.vitepress/theme/styles/utilities.css
Executable file
@ -0,0 +1,14 @@
|
||||
.nowrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.sr-only {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
border: 0;
|
||||
}
|
65
py-xiaozhi-main/documents/docs/.vitepress/theme/styles/vue-mastery.css
Executable file
@ -0,0 +1,65 @@
|
||||
.vue-mastery-link {
|
||||
background-color: var(--vt-c-bg-soft);
|
||||
border-radius: 8px;
|
||||
padding: 8px 16px 8px 8px;
|
||||
transition: color 0.5s, background-color 0.5s;
|
||||
}
|
||||
|
||||
.vue-mastery-link a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.vue-mastery-link .banner {
|
||||
background-color: var(--vt-c-white-soft);
|
||||
border-radius: 4px;
|
||||
width: 96px;
|
||||
height: 56px;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.vue-mastery-link .description {
|
||||
flex: 1;
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
color: var(--vt-c-text-1);
|
||||
margin: 0 0 0 16px;
|
||||
transition: color 0.5s;
|
||||
}
|
||||
|
||||
.vue-mastery-link .description span {
|
||||
color: var(--vt-c-brand);
|
||||
}
|
||||
|
||||
.vue-mastery-link .logo-wrapper {
|
||||
position: relative;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 50%;
|
||||
background-color: var(--vt-c-white);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.vue-mastery-link .logo-wrapper img {
|
||||
width: 25px;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
@media (max-width: 576px) {
|
||||
.vue-mastery-link .banner {
|
||||
width: 56px;
|
||||
}
|
||||
|
||||
.vue-mastery-link .description {
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
.vue-mastery-link .logo-wrapper {
|
||||
position: relative;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
}
|
26
py-xiaozhi-main/documents/docs/.vitepress/utils/index.ts
Executable file
@ -0,0 +1,26 @@
|
||||
import fs from 'fs-extra';
|
||||
import path from 'path';
|
||||
|
||||
export function getMdFilesAsync(rootDir: string) {
|
||||
const results: string[] = [];
|
||||
|
||||
function traverse(currentDir) {
|
||||
const entries = fs.readdirSync(currentDir, { withFileTypes: true });
|
||||
|
||||
entries.map(async (entry) => {
|
||||
const entryPath = path.join(currentDir, entry.name);
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
traverse(entryPath); // 递归子目录[3](@ref)
|
||||
} else if (path.extname(entry.name).toLowerCase() === '.md') {
|
||||
const relativePath = path.relative(rootDir, entryPath);
|
||||
results.push(relativePath);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
traverse(rootDir);
|
||||
return results.map(item => {
|
||||
return item.replace('.md', '');
|
||||
});
|
||||
}
|
BIN
py-xiaozhi-main/documents/docs/about/images/ben-hong.jpeg
Executable file
After Width: | Height: | Size: 36 KiB |
BIN
py-xiaozhi-main/documents/docs/about/images/evan-you.jpeg
Executable file
After Width: | Height: | Size: 40 KiB |
11
py-xiaozhi-main/documents/docs/about/team.md
Executable file
@ -0,0 +1,11 @@
|
||||
---
|
||||
page: true
|
||||
title: Py-xiaozhi团队
|
||||
layout: home
|
||||
---
|
||||
|
||||
<script setup>
|
||||
import TeamPage from './team/TeamPage.vue'
|
||||
</script>
|
||||
|
||||
<TeamPage />
|
26
py-xiaozhi-main/documents/docs/about/team/Member.ts
Executable file
@ -0,0 +1,26 @@
|
||||
export interface Member {
|
||||
name: string
|
||||
avatarPic?: string
|
||||
title: string
|
||||
company?: string
|
||||
companyLink?: string
|
||||
projects: Link[]
|
||||
location: string | string[]
|
||||
languages: string[]
|
||||
website?: Link
|
||||
socials: Socials
|
||||
sponsor?: boolean | string
|
||||
reposPersonal?: string[]
|
||||
}
|
||||
|
||||
export interface Link {
|
||||
label: string
|
||||
url: string
|
||||
}
|
||||
|
||||
export interface Socials {
|
||||
github: string
|
||||
twitter?: string
|
||||
linkedin?: string
|
||||
codepen?: string
|
||||
}
|
75
py-xiaozhi-main/documents/docs/about/team/TeamHero.vue
Executable file
@ -0,0 +1,75 @@
|
||||
<template>
|
||||
<div class="TeamHero">
|
||||
<div class="container">
|
||||
<h1 class="title">
|
||||
<slot name="title" />
|
||||
</h1>
|
||||
<p class="lead">
|
||||
<slot name="lead" />
|
||||
</p>
|
||||
<p class="action">
|
||||
<slot name="action" />
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.TeamHero {
|
||||
padding: 48px 24px;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.TeamHero {
|
||||
padding: 64px 32px 48px;
|
||||
}
|
||||
}
|
||||
|
||||
.container {
|
||||
margin: 0 auto;
|
||||
max-width: 960px;
|
||||
}
|
||||
|
||||
.title,
|
||||
.lead {
|
||||
transition: color 0.25s;
|
||||
}
|
||||
|
||||
.title {
|
||||
line-height: 32px;
|
||||
font-size: 32px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.title {
|
||||
line-height: 40px;
|
||||
font-size: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.lead {
|
||||
padding-top: 8px;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
max-width: 512px;
|
||||
color: var(--vt-c-text-2);
|
||||
}
|
||||
|
||||
.action {
|
||||
padding-top: 4px;
|
||||
}
|
||||
|
||||
.action :deep(a) {
|
||||
display: inline-block;
|
||||
line-height: 20px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: var(--vt-c-brand);
|
||||
transition: color 0.25s;
|
||||
}
|
||||
|
||||
.action :deep(a:hover) {
|
||||
color: var(--vt-c-brand-dark);
|
||||
}
|
||||
</style>
|
128
py-xiaozhi-main/documents/docs/about/team/TeamList.vue
Executable file
@ -0,0 +1,128 @@
|
||||
<script setup lang="ts">
|
||||
import type { Member } from './Member'
|
||||
import TeamMember from './TeamMember.vue'
|
||||
|
||||
defineProps<{
|
||||
members: Member[]
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section class="TeamList">
|
||||
<div class="container">
|
||||
<div class="info">
|
||||
<h2 class="title">
|
||||
<slot name="title" />
|
||||
</h2>
|
||||
<p class="lead">
|
||||
<slot name="lead" />
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="members">
|
||||
<!-- to skip SSG since the members are shuffled -->
|
||||
<ClientOnly>
|
||||
<div v-for="member in members" :key="member.name" class="member">
|
||||
<TeamMember :member="member" />
|
||||
</div>
|
||||
</ClientOnly>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
@media (min-width: 768px) {
|
||||
.TeamList {
|
||||
padding: 0 32px;
|
||||
}
|
||||
}
|
||||
|
||||
.container {
|
||||
border-top: 1px solid var(--vt-c-divider-light);
|
||||
padding-top: 24px;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.container {
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
max-width: 960px;
|
||||
}
|
||||
}
|
||||
|
||||
.info {
|
||||
flex-shrink: 0;
|
||||
padding: 0 24px;
|
||||
max-width: 512px;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.info {
|
||||
position: sticky;
|
||||
top: calc(var(--vt-banner-height, 0px) + 32px);
|
||||
left: 0;
|
||||
padding: 0 24px 0 0;
|
||||
width: 256px;
|
||||
}
|
||||
|
||||
html.banner-dismissed .info {
|
||||
top: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 960px) {
|
||||
.info {
|
||||
top: calc(var(--vt-banner-height, 0px) + 88px);
|
||||
padding: 0 64px 0 0;
|
||||
width: 384px;
|
||||
}
|
||||
|
||||
html.banner-dismissed .info {
|
||||
top: 88px;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.lead {
|
||||
padding-top: 8px;
|
||||
line-height: 24px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: var(--vt-c-text-2);
|
||||
}
|
||||
|
||||
.members {
|
||||
padding-top: 24px;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.members {
|
||||
flex-grow: 1;
|
||||
padding-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.member + .member {
|
||||
padding-top: 16px;
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.member {
|
||||
margin: 0 auto;
|
||||
max-width: 592px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.member {
|
||||
margin: 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
472
py-xiaozhi-main/documents/docs/about/team/TeamMember.vue
Executable file
@ -0,0 +1,472 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import {
|
||||
VTIconCode,
|
||||
VTIconCodePen,
|
||||
VTIconGitHub,
|
||||
VTIconGlobe,
|
||||
VTIconHeart,
|
||||
VTIconLink,
|
||||
VTIconLinkedIn,
|
||||
VTIconMapPin,
|
||||
VTIconX,
|
||||
VTLink
|
||||
} from '@vue/theme'
|
||||
import type { Member } from './Member'
|
||||
|
||||
const props = defineProps<{
|
||||
member: Member
|
||||
}>()
|
||||
|
||||
const avatarUrl = computed(() => {
|
||||
return (
|
||||
props.member.avatarPic ??
|
||||
`https://www.github.com/${props.member.socials.github}.png`
|
||||
)
|
||||
})
|
||||
|
||||
function arrayify(value: string | string[]): string[] {
|
||||
return Array.isArray(value) ? value : [value]
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<article class="TeamMember">
|
||||
<VTLink
|
||||
v-if="member.sponsor"
|
||||
class="sponsor"
|
||||
:href="`https://github.com/sponsors/${member.socials.github}`"
|
||||
no-icon
|
||||
>
|
||||
<VTIconHeart class="sponsor-icon" /> 赞助
|
||||
</VTLink>
|
||||
|
||||
<div class="member-content">
|
||||
<figure class="avatar">
|
||||
<img
|
||||
class="avatar-img"
|
||||
:src="avatarUrl"
|
||||
:alt="`${member.name}'s Profile Picture`"
|
||||
/>
|
||||
</figure>
|
||||
|
||||
<div class="data">
|
||||
<h1 class="name">{{ member.name }}</h1>
|
||||
<p class="org">
|
||||
{{ member.title }}
|
||||
<span v-if="member.company" class="nowrap">
|
||||
@
|
||||
<VTLink
|
||||
v-if="member.companyLink"
|
||||
class="company link"
|
||||
:href="member.companyLink"
|
||||
:no-icon="true"
|
||||
>
|
||||
{{ member.company }}
|
||||
</VTLink>
|
||||
<span v-else class="company">
|
||||
{{ member.company }}
|
||||
</span>
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<div class="profiles">
|
||||
<section v-if="member.projects && member.projects.length > 0" class="desc">
|
||||
<div class="desc-title">
|
||||
<VTIconCode class="desc-icon code" />
|
||||
</div>
|
||||
<ul class="desc-list">
|
||||
<li
|
||||
v-for="project in member.projects"
|
||||
:key="project.label"
|
||||
class="desc-item"
|
||||
>
|
||||
<VTLink
|
||||
class="desc-link"
|
||||
:href="project.url"
|
||||
:no-icon="true"
|
||||
>
|
||||
{{ project.label }}
|
||||
</VTLink>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="desc">
|
||||
<div class="desc-title">
|
||||
<VTIconMapPin class="desc-icon" />
|
||||
</div>
|
||||
<ul class="desc-list">
|
||||
<li
|
||||
v-for="location in arrayify(member.location)"
|
||||
:key="location"
|
||||
class="desc-item"
|
||||
>
|
||||
{{ location }}
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="desc">
|
||||
<div class="desc-title">
|
||||
<VTIconGlobe class="desc-icon" />
|
||||
</div>
|
||||
<ul class="desc-list">
|
||||
<li
|
||||
v-for="language in member.languages"
|
||||
:key="language"
|
||||
class="desc-item"
|
||||
>
|
||||
{{ language }}
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section v-if="member.website" class="desc">
|
||||
<div class="desc-title">
|
||||
<VTIconLink class="desc-icon" />
|
||||
</div>
|
||||
<p class="desc-text">
|
||||
<VTLink
|
||||
class="desc-link"
|
||||
:href="member.website.url"
|
||||
:no-icon="true"
|
||||
>
|
||||
{{ member.website.label }}
|
||||
</VTLink>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<div class="social-container">
|
||||
<ul class="social-list">
|
||||
<li v-if="member.socials.github" class="social-item">
|
||||
<VTLink
|
||||
class="social-link"
|
||||
:href="`https://github.com/${member.socials.github}`"
|
||||
:no-icon="true"
|
||||
>
|
||||
<VTIconGitHub class="social-icon" />
|
||||
</VTLink>
|
||||
</li>
|
||||
<li v-if="member.socials.twitter" class="social-item">
|
||||
<VTLink
|
||||
class="social-link"
|
||||
:href="`https://twitter.com/${member.socials.twitter}`"
|
||||
:no-icon="true"
|
||||
>
|
||||
<VTIconX class="social-icon" />
|
||||
</VTLink>
|
||||
</li>
|
||||
<li v-if="member.socials.linkedin" class="social-item">
|
||||
<VTLink
|
||||
class="social-link"
|
||||
:href="`https://www.linkedin.com/in/${member.socials.linkedin}`"
|
||||
:no-icon="true"
|
||||
>
|
||||
<VTIconLinkedIn class="social-icon" />
|
||||
</VTLink>
|
||||
</li>
|
||||
<li v-if="member.socials.codepen" class="social-item">
|
||||
<VTLink
|
||||
class="social-link"
|
||||
:href="`https://codepen.io/${member.socials.codepen}`"
|
||||
:no-icon="true"
|
||||
>
|
||||
<VTIconCodePen class="social-icon" />
|
||||
</VTLink>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.TeamMember {
|
||||
position: relative;
|
||||
background-color: var(--vt-c-bg-soft);
|
||||
transition: background-color 0.5s;
|
||||
border-radius: 8px;
|
||||
padding: 32px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.member-content {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
@media (max-width: 511px) {
|
||||
.member-content {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.vp-doc li + li {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.sponsor {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
right: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: 1px solid #fd1d7c;
|
||||
border-radius: 4px;
|
||||
padding: 4px 8px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: #fd1d7c;
|
||||
transition: color 0.25s, background-color 0.25s;
|
||||
}
|
||||
|
||||
.sponsor:hover {
|
||||
color: var(--vt-c-white);
|
||||
background-color: #fd1d7c;
|
||||
}
|
||||
|
||||
.sponsor-icon {
|
||||
margin-right: 6px;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
flex-shrink: 0;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
margin-right: 24px;
|
||||
}
|
||||
|
||||
@media (max-width: 511px) {
|
||||
.avatar {
|
||||
justify-content: center;
|
||||
margin-right: 0;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.avatar-img {
|
||||
border-radius: 50%;
|
||||
width: 110px;
|
||||
height: 110px;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.data {
|
||||
flex: 1;
|
||||
padding-top: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
@media (max-width: 511px) {
|
||||
.data {
|
||||
padding-top: 16px;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.name {
|
||||
font-size: 22px;
|
||||
font-weight: 600;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.org {
|
||||
padding-top: 4px;
|
||||
line-height: 20px;
|
||||
max-width: 320px;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: var(--vt-c-text-2);
|
||||
transition: color 0.5s;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.company {
|
||||
color: var(--vt-c-text-1);
|
||||
transition: color 0.25s;
|
||||
}
|
||||
|
||||
.company.link:hover {
|
||||
color: var(--vt-c-brand);
|
||||
transition: color 0.5s;
|
||||
}
|
||||
|
||||
.profiles {
|
||||
padding-top: 16px;
|
||||
}
|
||||
|
||||
@media (max-width: 511px) {
|
||||
.profiles {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.desc {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
@media (max-width: 511px) {
|
||||
.desc {
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.desc-title {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
margin-right: 12px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.desc-icon {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
fill: var(--vt-c-text-2);
|
||||
transition: fill 0.25s;
|
||||
}
|
||||
|
||||
.desc-icon.code {
|
||||
transform: translateY(1px);
|
||||
}
|
||||
|
||||
.desc-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
@media (max-width: 511px) {
|
||||
.desc-list {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.desc-text {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.desc-item {
|
||||
line-height: 20px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: var(--vt-c-text-1);
|
||||
transition: color 0.5s;
|
||||
}
|
||||
|
||||
.desc-item::after {
|
||||
margin: 0 8px;
|
||||
content: '•';
|
||||
color: var(--vt-c-text-3);
|
||||
transition: color 0.25s;
|
||||
}
|
||||
|
||||
.desc-item:last-child::after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.desc-text {
|
||||
line-height: 20px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: var(--vt-c-text-1);
|
||||
transition: color 0.25s;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.desc-link {
|
||||
line-height: 20px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: var(--vt-c-brand);
|
||||
transition: color 0.25s;
|
||||
}
|
||||
|
||||
.desc-link:hover {
|
||||
color: var(--vt-c-brand-dark);
|
||||
}
|
||||
|
||||
.social-container {
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.social-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
@media (max-width: 511px) {
|
||||
.social-container {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.social-list {
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.social-item {
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
.social-link {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
color: var(--vt-c-text-2);
|
||||
transition: color 0.25s;
|
||||
}
|
||||
|
||||
.social-link:hover {
|
||||
color: var(--vt-c-text-1);
|
||||
}
|
||||
|
||||
.social-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
.sr-only {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
.nowrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
</style>
|
84
py-xiaozhi-main/documents/docs/about/team/TeamPage.vue
Executable file
@ -0,0 +1,84 @@
|
||||
<script lang="ts">
|
||||
import type { Member } from './Member'
|
||||
|
||||
const shuffleMembers = (
|
||||
members: Member[],
|
||||
pinTheFirstMember = false
|
||||
): void => {
|
||||
let offset = pinTheFirstMember ? 1 : 0
|
||||
// `i` is between `1` and `length - offset`
|
||||
// `j` is between `0` and `length - offset - 1`
|
||||
// `offset + i - 1` is between `offset` and `length - 1`
|
||||
// `offset + j` is between `offset` and `length - 1`
|
||||
let i = members.length - offset
|
||||
while (i > 0) {
|
||||
const j = Math.floor(Math.random() * i)
|
||||
;[members[offset + i - 1], members[offset + j]] = [
|
||||
members[offset + j],
|
||||
members[offset + i - 1]
|
||||
]
|
||||
i--
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
// @ts-ignore
|
||||
import { VTLink } from '@vue/theme'
|
||||
// @ts-ignore
|
||||
import membersCoreData from './members-core.json'
|
||||
// @ts-ignore
|
||||
import membersPartnerData from './members-partner.json'
|
||||
import TeamHero from './TeamHero.vue'
|
||||
// @ts-ignore
|
||||
import TeamList from './TeamList.vue'
|
||||
|
||||
shuffleMembers(membersCoreData, true)
|
||||
shuffleMembers(membersPartnerData)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="TeamPage">
|
||||
<TeamHero>
|
||||
<template #title>团队成员</template>
|
||||
<template #lead>
|
||||
py-xiaozhi项目的开发和维护由社区人员负责,
|
||||
以下是核心团队成员以及社区贡献者的部分信息。
|
||||
</template>
|
||||
</TeamHero>
|
||||
|
||||
<TeamList :members="membersCoreData">
|
||||
<template #title>核心团队成员</template>
|
||||
<template #lead>
|
||||
核心团队成员积极参与项目开发和维护,对py-xiaozhi项目做出了重大贡献。
|
||||
</template>
|
||||
</TeamList>
|
||||
|
||||
<TeamList :members="membersPartnerData">
|
||||
<template #title>社区贡献者</template>
|
||||
<template #lead>
|
||||
感谢以下社区成员在项目初期提供的帮助和支持。
|
||||
</template>
|
||||
</TeamList>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.TeamPage {
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.TeamPage {
|
||||
padding-bottom: 96px;
|
||||
}
|
||||
}
|
||||
|
||||
.TeamList + .TeamList {
|
||||
padding-top: 64px;
|
||||
}
|
||||
|
||||
* {
|
||||
list-style: none;
|
||||
}
|
||||
</style>
|
90
py-xiaozhi-main/documents/docs/about/team/members-core.json
Executable file
@ -0,0 +1,90 @@
|
||||
[
|
||||
{
|
||||
"name": "Junsen Huang",
|
||||
"title": "py-xiaozhi发起者 & 核心开发者",
|
||||
"company": "南方电网人工智能有限公司 前端开发工程师",
|
||||
"location": "中国",
|
||||
"languages": ["中文"],
|
||||
"projects": [
|
||||
{
|
||||
"label": "py-xiaozhi",
|
||||
"url": "https://github.com/huangjunsen0406/py-xiaozhi"
|
||||
},
|
||||
{
|
||||
"label": "UnifyPy",
|
||||
"url": "https://github.com/huangjunsen0406/UnifyPy"
|
||||
},
|
||||
{
|
||||
"label": "xiaozhi-esp32-server",
|
||||
"url": "https://github.com/xinnan-tech/xiaozhi-esp32-server"
|
||||
}
|
||||
],
|
||||
"socials": {
|
||||
"github": "huangjunsen0406"
|
||||
},
|
||||
"website": {
|
||||
"label": "https://junsen.online",
|
||||
"url": "https://junsen.online"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ASLant",
|
||||
"title": "核心开发者、PyQt5界面开发、嵌入式兼容",
|
||||
"company": "山东青橙数字科技有限公司 嵌入式软件工程师",
|
||||
"location": "中国",
|
||||
"languages": ["中文"],
|
||||
"projects": [
|
||||
],
|
||||
"socials": {
|
||||
"github": "Y-ASLant"
|
||||
},
|
||||
"website": {
|
||||
"label": "aslant.top",
|
||||
"url": "https://aslant.top/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "fengzai6",
|
||||
"title": "前期核心开发者",
|
||||
"company": "中山华定科技有限公司 前端开发工程师",
|
||||
"location": "中国",
|
||||
"languages": ["中文"],
|
||||
"projects": [
|
||||
],
|
||||
"socials": {
|
||||
"github": "fengzai6"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Cal And Nong",
|
||||
"title": "文档贡献者",
|
||||
"company": "腾讯 前端开发工程师",
|
||||
"location": "中国",
|
||||
"languages": ["中文"],
|
||||
"projects": [
|
||||
],
|
||||
"socials": {
|
||||
"github": "calandnong"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "vonweller",
|
||||
"title": "视觉功能贡献者",
|
||||
"projects": [],
|
||||
"location": "中国",
|
||||
"languages": ["中文"],
|
||||
"socials": {
|
||||
"github": "vonweller"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "gaochuang",
|
||||
"company": "诺基亚通信技术 高级平台开发工程师",
|
||||
"projects": [],
|
||||
"location": "中国",
|
||||
"languages": ["中文"],
|
||||
"socials": {
|
||||
"github": "gaochuang"
|
||||
}
|
||||
}
|
||||
]
|
113
py-xiaozhi-main/documents/docs/about/team/members-partner.json
Executable file
@ -0,0 +1,113 @@
|
||||
[
|
||||
{
|
||||
"name": "Xiaoxia",
|
||||
"title": "社区贡献者",
|
||||
"projects": [
|
||||
{
|
||||
"label": "小智Ai创始人",
|
||||
"url": "https://github.com/78/xiaozhi-esp32"
|
||||
}
|
||||
],
|
||||
"location": "中国",
|
||||
"languages": ["中文"],
|
||||
"socials": {
|
||||
"github": "78"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "zhh827",
|
||||
"title": "社区贡献者",
|
||||
"projects": [
|
||||
],
|
||||
"location": "中国",
|
||||
"languages": ["中文"],
|
||||
"socials": {
|
||||
"github": "zhh827"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "四博智联-李洪刚",
|
||||
"title": "社区贡献者",
|
||||
"projects": [
|
||||
],
|
||||
"location": "中国",
|
||||
"languages": ["中文"],
|
||||
"socials": {
|
||||
"github": "SmartArduino"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "HonestQiao",
|
||||
"title": "社区贡献者",
|
||||
"projects": [
|
||||
],
|
||||
"location": "中国",
|
||||
"languages": ["中文"],
|
||||
"socials": {
|
||||
"github": "HonestQiao"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "孙卫公",
|
||||
"title": "社区贡献者",
|
||||
"avatarPic": "https://tuchuang.junsen.online/i/2025/04/27/i7ndx4.png",
|
||||
"projects": [
|
||||
],
|
||||
"location": "中国",
|
||||
"languages": ["中文"],
|
||||
"socials": {
|
||||
},
|
||||
"website": {
|
||||
"label": "Bilibili 主页",
|
||||
"url": "https://space.bilibili.com/416954647"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "isamu2025",
|
||||
"title": "社区贡献者",
|
||||
"projects": [
|
||||
],
|
||||
"location": "中国",
|
||||
"languages": ["中文"],
|
||||
"socials": {
|
||||
"github": "isamu2025"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Rain120",
|
||||
"title": "社区贡献者",
|
||||
"projects": [
|
||||
],
|
||||
"location": "中国",
|
||||
"languages": ["中文"],
|
||||
"socials": {
|
||||
"github": "Rain120"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "kejily",
|
||||
"title": "社区贡献者",
|
||||
"projects": [
|
||||
],
|
||||
"location": "中国",
|
||||
"languages": ["中文"],
|
||||
"socials": {
|
||||
"github": "kejily"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "电波bilibili君",
|
||||
"title": "社区贡献者",
|
||||
"avatarPic": "https://tuchuang.junsen.online/i/2025/04/27/f4g54b.png",
|
||||
"projects": [
|
||||
],
|
||||
"location": "中国",
|
||||
"languages": ["中文"],
|
||||
"socials": {
|
||||
},
|
||||
"website": {
|
||||
"label": "Bilibili 主页",
|
||||
"url": "https://space.bilibili.com/119751"
|
||||
}
|
||||
}
|
||||
]
|
@ -0,0 +1,73 @@
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
PuzzlePieceIcon,
|
||||
CubeIcon,
|
||||
ArrowsRightLeftIcon,
|
||||
BoltIcon,
|
||||
ShareIcon
|
||||
} from '@heroicons/vue/24/solid';
|
||||
// 架构特点
|
||||
const architectureFeatures = [
|
||||
{
|
||||
title: '模块化设计',
|
||||
description: '各功能模块高度解耦,便于维护和扩展',
|
||||
icon: CubeIcon
|
||||
},
|
||||
{
|
||||
title: '协议抽象',
|
||||
description: '通过抽象接口支持多种通信协议',
|
||||
icon: ArrowsRightLeftIcon
|
||||
},
|
||||
{
|
||||
title: '事件驱动',
|
||||
description: '基于事件的异步处理机制',
|
||||
icon: BoltIcon
|
||||
},
|
||||
{
|
||||
title: '状态机模式',
|
||||
description: '清晰的状态转换逻辑',
|
||||
icon: ShareIcon
|
||||
},
|
||||
{
|
||||
title: '插件式IoT设备',
|
||||
description: '统一设备接口,支持动态加载设备',
|
||||
icon: PuzzlePieceIcon
|
||||
}
|
||||
];
|
||||
|
||||
const featureColors = [
|
||||
'bg-blue-500',
|
||||
'bg-indigo-500',
|
||||
'bg-purple-500',
|
||||
'bg-pink-500',
|
||||
'bg-red-500'
|
||||
];
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="bg-white rounded-lg relative mb-10">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
<div v-for="(feature, index) in architectureFeatures" :key="index"
|
||||
class="bg-white rounded-lg p-6 hover:shadow-xl transition-shadow">
|
||||
<div class="w-12 h-12 rounded-full flex items-center justify-center mb-4"
|
||||
:class="featureColors[index % featureColors.length]">
|
||||
<component :is="feature.icon" class="w-6 h-6 text-white" />
|
||||
</div>
|
||||
<h3 class="text-xl font-semibold mb-2">{{ feature.title }}</h3>
|
||||
<p class="text-gray-700">{{ feature.description }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
/* 架构特点卡片样式优化 */
|
||||
.grid-cols-1.md\:grid-cols-2.lg\:grid-cols-3 > div {
|
||||
transition: all 0.3s ease;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.grid-cols-1.md\:grid-cols-2.lg\:grid-cols-3 > div:hover {
|
||||
transform: translateY(-5px);
|
||||
}
|
||||
</style>
|
98
py-xiaozhi-main/documents/docs/architecture/components/CoreArchitecture.vue
Executable file
@ -0,0 +1,98 @@
|
||||
<template>
|
||||
<div class="bg-white rounded-lg relative mb-10">
|
||||
<div ref="architectureChart" class="w-full h-[500px]"></div>
|
||||
<p class="text-gray-600 mt-4 text-center">核心架构图:展示了应用核心、通信协议层、音频处理系统、用户界面系统、IoT设备管理等模块的关系</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue';
|
||||
import * as echarts from 'echarts';
|
||||
|
||||
const architectureChart = ref(null);
|
||||
|
||||
onMounted(() => {
|
||||
if (architectureChart.value) {
|
||||
const chart = echarts.init(architectureChart.value);
|
||||
chart.setOption({
|
||||
animation: false,
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: '{b}: {c}'
|
||||
},
|
||||
legend: {
|
||||
orient: 'vertical',
|
||||
right: 10,
|
||||
top: 'center',
|
||||
data: ['核心', '主要模块', '子模块']
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '架构图',
|
||||
type: 'graph',
|
||||
layout: 'force',
|
||||
data: [
|
||||
{ name: '应用核心', value: 'Application', category: 0, symbolSize: 70 },
|
||||
{ name: '通信协议层', value: 'Protocols', category: 1, symbolSize: 50 },
|
||||
{ name: '音频处理系统', value: 'Audio Processing', category: 1, symbolSize: 50 },
|
||||
{ name: '用户界面系统', value: 'UI System', category: 1, symbolSize: 50 },
|
||||
{ name: 'IoT设备管理', value: 'IoT Management', category: 1, symbolSize: 50 },
|
||||
{ name: 'WebSocket', value: 'WebSocket', category: 2, symbolSize: 30 },
|
||||
{ name: 'MQTT', value: 'MQTT', category: 2, symbolSize: 30 },
|
||||
{ name: '音频编解码', value: 'Audio Codecs', category: 2, symbolSize: 30 },
|
||||
{ name: 'VAD检测', value: 'VAD', category: 2, symbolSize: 30 },
|
||||
{ name: '唤醒词检测', value: 'Wakeword', category: 2, symbolSize: 30 },
|
||||
{ name: 'GUI界面', value: 'GUI', category: 2, symbolSize: 30 },
|
||||
{ name: 'CLI界面', value: 'CLI', category: 2, symbolSize: 30 },
|
||||
{ name: '设备抽象', value: 'Device Abstract', category: 2, symbolSize: 30 },
|
||||
{ name: '智能家居', value: 'Smart Home', category: 2, symbolSize: 30 }
|
||||
],
|
||||
links: [
|
||||
{ source: '应用核心', target: '通信协议层' },
|
||||
{ source: '应用核心', target: '音频处理系统' },
|
||||
{ source: '应用核心', target: '用户界面系统' },
|
||||
{ source: '应用核心', target: 'IoT设备管理' },
|
||||
{ source: '通信协议层', target: 'WebSocket' },
|
||||
{ source: '通信协议层', target: 'MQTT' },
|
||||
{ source: '音频处理系统', target: '音频编解码' },
|
||||
{ source: '音频处理系统', target: 'VAD检测' },
|
||||
{ source: '音频处理系统', target: '唤醒词检测' },
|
||||
{ source: '用户界面系统', target: 'GUI界面' },
|
||||
{ source: '用户界面系统', target: 'CLI界面' },
|
||||
{ source: 'IoT设备管理', target: '设备抽象' },
|
||||
{ source: 'IoT设备管理', target: '智能家居' }
|
||||
],
|
||||
categories: [
|
||||
{ name: '核心' },
|
||||
{ name: '主要模块' },
|
||||
{ name: '子模块' }
|
||||
],
|
||||
roam: true,
|
||||
label: {
|
||||
show: true,
|
||||
position: 'right',
|
||||
formatter: '{b}'
|
||||
},
|
||||
lineStyle: {
|
||||
color: 'source',
|
||||
curveness: 0.3
|
||||
},
|
||||
emphasis: {
|
||||
focus: 'adjacency',
|
||||
lineStyle: {
|
||||
width: 3
|
||||
}
|
||||
},
|
||||
force: {
|
||||
repulsion: 300,
|
||||
edgeLength: 120
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
window.addEventListener('resize', () => {
|
||||
chart.resize();
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
169
py-xiaozhi-main/documents/docs/architecture/components/DataFlow.vue
Executable file
@ -0,0 +1,169 @@
|
||||
<template>
|
||||
<div class="bg-white rounded-lg relative mb-10">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
||||
<div v-for="(flow, index) in dataFlows" :key="index"
|
||||
class="data-flow-card bg-white rounded-xl shadow-xl overflow-hidden transform hover:scale-[1.02] transition-all duration-300">
|
||||
<div class="p-5 text-white font-semibold bg-gradient-to-r" :class="[
|
||||
index === 0 ? 'from-blue-500 to-blue-600' :
|
||||
index === 1 ? 'from-green-500 to-green-600' :
|
||||
'from-purple-500 to-purple-600'
|
||||
]">
|
||||
<div class="flex items-center">
|
||||
<div class="w-10 h-10 rounded-full bg-white/20 backdrop-blur-sm flex items-center justify-center">
|
||||
<component :is="flow.icon" class="w-5 h-5 text-white" />
|
||||
</div>
|
||||
<div class="ml-4">
|
||||
<h3 class="text-xl font-bold">{{ flow.title }}</h3>
|
||||
<p class="text-white/80 text-sm mt-1">{{ flow.subtitle }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-5 flex-grow">
|
||||
<div class="relative py-3 h-full" >
|
||||
<div v-for="(step, stepIndex) in flow.steps" :key="stepIndex"
|
||||
class="flow-step flex items-center mb-5 last:mb-0">
|
||||
<div
|
||||
class="flow-step-number w-10 h-10 rounded-full bg-gradient-to-br flex items-center justify-center text-white font-bold shadow-md"
|
||||
:class="[
|
||||
index === 0 ? 'from-blue-400 to-blue-500' :
|
||||
index === 1 ? 'from-green-400 to-green-500' :
|
||||
'from-purple-400 to-purple-500'
|
||||
]">
|
||||
{{ stepIndex + 1 }}
|
||||
</div>
|
||||
<div class="flow-step-content ml-3 flex-1 bg-gradient-to-br from-gray-50 to-white rounded-lg p-3 shadow-sm">
|
||||
<p class="text-gray-700">{{ step }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="absolute left-5 top-8 bottom-5 w-0.5" :class="[
|
||||
index === 0 ? 'bg-blue-200' :
|
||||
index === 1 ? 'bg-green-200' :
|
||||
'bg-purple-200'
|
||||
]">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
AcademicCapIcon,
|
||||
SpeakerWaveIcon,
|
||||
CommandLineIcon
|
||||
} from '@heroicons/vue/24/solid';
|
||||
|
||||
// 数据流
|
||||
const dataFlows = [
|
||||
{
|
||||
title: '音频输入流程',
|
||||
subtitle: '从用户到服务器',
|
||||
icon: AcademicCapIcon,
|
||||
steps: [
|
||||
'麦克风捕获音频',
|
||||
'VAD 判断是否有语音',
|
||||
'音频编码压缩',
|
||||
'发送到服务器'
|
||||
]
|
||||
},
|
||||
{
|
||||
title: '音频输出流程',
|
||||
subtitle: '从服务器到用户',
|
||||
icon: SpeakerWaveIcon,
|
||||
steps: [
|
||||
'服务器返回音频数据',
|
||||
'解码音频数据',
|
||||
'音频播放'
|
||||
]
|
||||
},
|
||||
{
|
||||
title: '控制命令流程',
|
||||
subtitle: '命令处理与执行',
|
||||
icon: CommandLineIcon,
|
||||
steps: [
|
||||
'用户命令输入',
|
||||
'命令解析',
|
||||
'发送到服务器',
|
||||
'服务器响应处理',
|
||||
'更新 UI 和状态'
|
||||
]
|
||||
}
|
||||
];
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.data-flow-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.data-flow-card > div:last-child {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.flow-chart {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.flow-step {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.flow-chart .flow-step {
|
||||
margin-bottom: 1.25rem;
|
||||
min-height: 3rem;
|
||||
}
|
||||
|
||||
.flow-chart .flow-step:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.flow-step-content {
|
||||
padding: 0.75rem 1rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-height: 3rem;
|
||||
}
|
||||
|
||||
.flow-chart .absolute {
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.grid-cols-1.lg\:grid-cols-3 {
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.grid-cols-1.lg\:grid-cols-3 > div {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.grid-cols-1.lg\:grid-cols-3 > div > div:last-child {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.flow-chart {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1023px) {
|
||||
.grid-cols-1.lg\:grid-cols-3 > div {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
}
|
||||
</style>
|
132
py-xiaozhi-main/documents/docs/architecture/components/ModuleDetails.vue
Executable file
@ -0,0 +1,132 @@
|
||||
<template>
|
||||
<div class="bg-white rounded-lg relative mb-10">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-x-8 gap-y-6">
|
||||
<div v-for="(module, index) in modules" :key="index" class="module-card">
|
||||
<div class="flex items-start">
|
||||
<div class="w-12 h-12 rounded-lg flex items-center justify-center"
|
||||
:class="moduleColors[index % moduleColors.length]">
|
||||
<component :is="module.icon" class="w-6 h-6 text-white" />
|
||||
</div>
|
||||
<div class="ml-4 flex-1">
|
||||
<h3 class="text-lg font-semibold mb-2">{{ module.name }}</h3>
|
||||
<ul class="space-y-2">
|
||||
<li v-for="(feature, featureIndex) in module.features" :key="featureIndex" class="flex items-start">
|
||||
<CheckCircleIcon class="w-5 h-5 text-green-500 mt-1 mr-2" />
|
||||
<span>{{ feature }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
CogIcon,
|
||||
ArrowsRightLeftIcon,
|
||||
DocumentIcon,
|
||||
SpeakerXMarkIcon,
|
||||
ComputerDesktopIcon,
|
||||
ServerIcon,
|
||||
LightBulbIcon,
|
||||
WrenchIcon,
|
||||
CheckCircleIcon
|
||||
} from '@heroicons/vue/24/solid';
|
||||
|
||||
// 模块详情
|
||||
const modules = [
|
||||
{
|
||||
name: 'src/application.py',
|
||||
icon: CogIcon,
|
||||
features: [
|
||||
'应用主类,负责协调所有子系统',
|
||||
'实现了单例模式,管理全局状态',
|
||||
'处理事件调度和状态转换'
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'src/protocols/',
|
||||
icon: ArrowsRightLeftIcon,
|
||||
features: [
|
||||
'通信协议的抽象接口和具体实现',
|
||||
'WebSocket协议:用于实时双向通信',
|
||||
'MQTT协议:用于物联网设备通信'
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'src/audio_codecs/',
|
||||
icon: DocumentIcon,
|
||||
features: [
|
||||
'音频编解码器,处理音频数据压缩/解压缩',
|
||||
'支持Opus编码格式'
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'src/audio_processing/',
|
||||
icon: SpeakerXMarkIcon,
|
||||
features: [
|
||||
'语音活动检测:判断用户是否在说话',
|
||||
'唤醒词检测:识别指定的唤醒词'
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'src/display/',
|
||||
icon: ComputerDesktopIcon,
|
||||
features: [
|
||||
'用户界面抽象和实现',
|
||||
'GUI界面:基于PyQt5的图形界面',
|
||||
'CLI界面:命令行交互界面'
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'src/iot/',
|
||||
icon: ServerIcon,
|
||||
features: [
|
||||
'IoT设备管理框架',
|
||||
'设备抽象类和具体实现',
|
||||
'支持智能家居设备控制'
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'src/iot/things/',
|
||||
icon: LightBulbIcon,
|
||||
features: [
|
||||
'具体IoT设备的实现',
|
||||
'音乐播放器、温度传感器',
|
||||
'灯光控制、摄像头等'
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'src/utils/',
|
||||
icon: WrenchIcon,
|
||||
features: [
|
||||
'各类工具函数和辅助类',
|
||||
'日志管理、配置管理等'
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
const moduleColors = [
|
||||
'bg-blue-600',
|
||||
'bg-indigo-600',
|
||||
'bg-purple-600',
|
||||
'bg-pink-600',
|
||||
'bg-red-600',
|
||||
'bg-orange-600',
|
||||
'bg-yellow-600',
|
||||
'bg-green-600'
|
||||
];
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.module-card {
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.module-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
</style>
|
85
py-xiaozhi-main/documents/docs/architecture/components/StateManagement.vue
Executable file
@ -0,0 +1,85 @@
|
||||
<template>
|
||||
<div class="bg-white rounded-lg relative mb-10">
|
||||
<div ref="stateChart" class="w-full h-[300px]"></div>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 mt-6">
|
||||
<div v-for="(state, index) in states" :key="index" class="bg-gray-50 p-4 rounded-lg border-l-4"
|
||||
:class="stateBorderColors[index]">
|
||||
<h4 class="font-bold mb-2">{{ state.name }}</h4>
|
||||
<p class="text-gray-700">{{ state.description }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue';
|
||||
import * as echarts from 'echarts';
|
||||
|
||||
// 状态管理数据
|
||||
const states = [
|
||||
{ name: 'IDLE', description: '空闲状态,等待用户交互或唤醒词' },
|
||||
{ name: 'CONNECTING', description: '正在建立连接' },
|
||||
{ name: 'LISTENING', description: '正在监听用户输入' },
|
||||
{ name: 'SPEAKING', description: '正在播放语音回复' }
|
||||
];
|
||||
|
||||
const stateBorderColors = [
|
||||
'border-blue-500',
|
||||
'border-yellow-500',
|
||||
'border-green-500',
|
||||
'border-purple-500'
|
||||
];
|
||||
|
||||
const stateChart = ref(null);
|
||||
|
||||
onMounted(() => {
|
||||
if (stateChart.value) {
|
||||
const chart = echarts.init(stateChart.value);
|
||||
chart.setOption({
|
||||
animation: false,
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: '{b}'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
type: 'graph',
|
||||
layout: 'circular',
|
||||
symbolSize: 60,
|
||||
roam: false,
|
||||
label: {
|
||||
show: true
|
||||
},
|
||||
edgeSymbol: ['circle', 'arrow'],
|
||||
edgeSymbolSize: [4, 10],
|
||||
edgeLabel: {
|
||||
fontSize: 12
|
||||
},
|
||||
data: [
|
||||
{ name: 'IDLE', itemStyle: { color: '#3b82f6' } },
|
||||
{ name: 'CONNECTING', itemStyle: { color: '#eab308' } },
|
||||
{ name: 'LISTENING', itemStyle: { color: '#22c55e' } },
|
||||
{ name: 'SPEAKING', itemStyle: { color: '#a855f7' } }
|
||||
],
|
||||
links: [
|
||||
{ source: 'IDLE', target: 'CONNECTING', label: { show: true, formatter: '唤醒' } },
|
||||
{ source: 'CONNECTING', target: 'LISTENING', label: { show: true, formatter: '连接成功' } },
|
||||
{ source: 'LISTENING', target: 'SPEAKING', label: { show: true, formatter: '收到响应' } },
|
||||
{ source: 'SPEAKING', target: 'IDLE', label: { show: true, formatter: '播放完成' } },
|
||||
{ source: 'LISTENING', target: 'IDLE', label: { show: true, formatter: '超时' } },
|
||||
{ source: 'CONNECTING', target: 'IDLE', label: { show: true, formatter: '连接失败' } }
|
||||
],
|
||||
lineStyle: {
|
||||
opacity: 0.9,
|
||||
width: 2,
|
||||
curveness: 0.2
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
window.addEventListener('resize', () => {
|
||||
chart.resize();
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
101
py-xiaozhi-main/documents/docs/architecture/components/TechnologyStack.vue
Executable file
@ -0,0 +1,101 @@
|
||||
<template>
|
||||
<div class="bg-white rounded-lg relative mb-10">
|
||||
<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-4">
|
||||
<div v-for="(tech, index) in techStack" :key="index"
|
||||
class="flex flex-col items-center p-4 rounded-lg hover:bg-gray-100 transition-colors">
|
||||
<div class="w-16 h-16 rounded-full flex items-center justify-center mb-3"
|
||||
:class="techColors[index % techColors.length]">
|
||||
<component :is="tech.icon" class="w-8 h-8 text-white" />
|
||||
</div>
|
||||
<h4 class="font-semibold text-center">{{ tech.name }}</h4>
|
||||
<p class="text-sm text-gray-600 text-center mt-1">{{ tech.description }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
CodeBracketIcon,
|
||||
WindowIcon,
|
||||
DocumentIcon,
|
||||
SpeakerWaveIcon as AudioIcon,
|
||||
PuzzlePieceIcon,
|
||||
SignalIcon,
|
||||
ArrowPathIcon,
|
||||
ArrowsUpDownIcon,
|
||||
MusicalNoteIcon as MusicIcon
|
||||
} from '@heroicons/vue/24/solid';
|
||||
|
||||
// 技术栈
|
||||
const techStack = [
|
||||
{
|
||||
name: 'Python',
|
||||
description: '3.9-3.12',
|
||||
icon: CodeBracketIcon
|
||||
},
|
||||
{
|
||||
name: 'PyQt5',
|
||||
description: 'GUI框架',
|
||||
icon: WindowIcon
|
||||
},
|
||||
{
|
||||
name: 'OpusLib',
|
||||
description: '音频编解码',
|
||||
icon: DocumentIcon
|
||||
},
|
||||
{
|
||||
name: 'PyAudio',
|
||||
description: '音频处理',
|
||||
icon: AudioIcon
|
||||
},
|
||||
{
|
||||
name: 'WebSocket',
|
||||
description: '通信协议',
|
||||
icon: PuzzlePieceIcon
|
||||
},
|
||||
{
|
||||
name: 'MQTT',
|
||||
description: 'IoT通信',
|
||||
icon: SignalIcon
|
||||
},
|
||||
{
|
||||
name: 'AsyncIO',
|
||||
description: '异步处理',
|
||||
icon: ArrowPathIcon
|
||||
},
|
||||
{
|
||||
name: 'Threading',
|
||||
description: '并发处理',
|
||||
icon: ArrowsUpDownIcon
|
||||
},
|
||||
{
|
||||
name: 'Pygame',
|
||||
description: '音乐播放',
|
||||
icon: MusicIcon
|
||||
}
|
||||
];
|
||||
|
||||
const techColors = [
|
||||
'bg-blue-500',
|
||||
'bg-indigo-500',
|
||||
'bg-purple-500',
|
||||
'bg-pink-500',
|
||||
'bg-red-500',
|
||||
'bg-orange-500',
|
||||
'bg-yellow-500',
|
||||
'bg-green-500',
|
||||
'bg-teal-500'
|
||||
];
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 技术栈图标优化 */
|
||||
.grid-cols-2.md\:grid-cols-3.lg\:grid-cols-6 > div {
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.grid-cols-2.md\:grid-cols-3.lg\:grid-cols-6 > div:hover {
|
||||
transform: translateY(-3px);
|
||||
}
|
||||
</style>
|
46
py-xiaozhi-main/documents/docs/architecture/index.md
Executable file
@ -0,0 +1,46 @@
|
||||
---
|
||||
title: Py-Xiaozhi 项目架构
|
||||
description: 基于 Python 实现的小智语音客户端,采用模块化设计,支持多种通信协议和设备集成
|
||||
sidebar: false,
|
||||
pageClass: architecture-page-class
|
||||
---
|
||||
<script setup>
|
||||
import CoreArchitecture from './components/CoreArchitecture.vue'
|
||||
import StateManagement from './components/StateManagement.vue'
|
||||
import DataFlow from './components/DataFlow.vue'
|
||||
import ModuleDetails from './components/ModuleDetails.vue'
|
||||
import TechnologyStack from './components/TechnologyStack.vue'
|
||||
import ArchitectureFeatures from './components/ArchitectureFeatures.vue'
|
||||
</script>
|
||||
|
||||
<div class="architecture-page">
|
||||
|
||||
# Py-Xiaozhi 项目架构
|
||||
|
||||
<p>基于 Python 实现的小智语音客户端,采用模块化设计,支持多种通信协议和设备集成</p>
|
||||
|
||||
## 核心架构
|
||||
<CoreArchitecture/>
|
||||
|
||||
## 状态管理
|
||||
<StateManagement/>
|
||||
|
||||
## 数据流
|
||||
<DataFlow/>
|
||||
|
||||
## 模块详情
|
||||
<ModuleDetails/>
|
||||
|
||||
## 技术栈
|
||||
<TechnologyStack/>
|
||||
|
||||
## 架构特点
|
||||
<ArchitectureFeatures/>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.architecture-page {
|
||||
max-width: 100%;
|
||||
padding: 0 2rem;
|
||||
}
|
||||
</style>
|
451
py-xiaozhi-main/documents/docs/contributing.md
Executable file
@ -0,0 +1,451 @@
|
||||
---
|
||||
title: 贡献指南
|
||||
description: 如何为 py-xiaozhi 项目贡献代码
|
||||
sidebar: false
|
||||
outline: deep
|
||||
---
|
||||
|
||||
<div class="contributing-page">
|
||||
|
||||
# 贡献指南
|
||||
|
||||
<div class="header-content">
|
||||
<h2>如何为 py-xiaozhi 项目贡献代码 🚀</h2>
|
||||
</div>
|
||||
|
||||
## 前言
|
||||
|
||||
感谢您对 py-xiaozhi 项目感兴趣!我们非常欢迎社区成员参与贡献,无论是修复错误、改进文档还是添加新功能。本指南将帮助您了解如何向项目提交贡献。
|
||||
|
||||
## 开发环境准备
|
||||
|
||||
### 基本要求
|
||||
|
||||
- Python 3.9 或更高版本
|
||||
- Git 版本控制系统
|
||||
- 基本的 Python 开发工具(推荐使用 Visual Studio Code)
|
||||
|
||||
### 获取源代码
|
||||
|
||||
1. 首先,在 GitHub 上 Fork 本项目到您自己的账号
|
||||
- 访问 [py-xiaozhi 项目页面](https://github.com/huangjunsen0406/py-xiaozhi)
|
||||
- 点击右上角的"Fork"按钮
|
||||
- 等待 Fork 完成,您将被重定向到您的仓库副本
|
||||
|
||||
2. 克隆您 fork 的仓库到本地:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/YOUR_USERNAME/py-xiaozhi.git
|
||||
cd py-xiaozhi
|
||||
```
|
||||
|
||||
3. 添加上游仓库作为远程源:
|
||||
|
||||
```bash
|
||||
git remote add upstream https://github.com/huangjunsen0406/py-xiaozhi.git
|
||||
```
|
||||
|
||||
你可以使用 `git remote -v` 命令确认远程仓库已正确配置:
|
||||
|
||||
```bash
|
||||
git remote -v
|
||||
# 应显示:
|
||||
# origin https://github.com/YOUR_USERNAME/py-xiaozhi.git (fetch)
|
||||
# origin https://github.com/YOUR_USERNAME/py-xiaozhi.git (push)
|
||||
# upstream https://github.com/huangjunsen0406/py-xiaozhi.git (fetch)
|
||||
# upstream https://github.com/huangjunsen0406/py-xiaozhi.git (push)
|
||||
```
|
||||
|
||||
### 安装开发依赖
|
||||
- 其他依赖需要查看指南下的相关文档
|
||||
```bash
|
||||
# 创建并激活虚拟环境(推荐)
|
||||
python -m venv venv
|
||||
source venv/bin/activate # 在 Windows 上使用: venv\Scripts\activate
|
||||
|
||||
# 安装项目依赖
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
## 开发流程
|
||||
|
||||
### 与主仓库保持同步
|
||||
|
||||
在开始工作之前,确保您的本地仓库与主项目保持同步是非常重要的。以下是同步本地仓库的步骤:
|
||||
|
||||
1. 切换到您的主分支(`main`):
|
||||
|
||||
```bash
|
||||
git checkout main
|
||||
```
|
||||
|
||||
2. 拉取上游仓库的最新更改:
|
||||
|
||||
```bash
|
||||
git fetch upstream
|
||||
```
|
||||
|
||||
3. 将上游主分支的更改合并到您的本地主分支:
|
||||
|
||||
```bash
|
||||
git merge upstream/main
|
||||
```
|
||||
|
||||
4. 将更新后的本地主分支推送到您的 GitHub 仓库:
|
||||
|
||||
```bash
|
||||
git push origin main
|
||||
```
|
||||
|
||||
### 创建分支
|
||||
|
||||
在开始任何工作之前,请确保从最新的上游主分支创建新的分支:
|
||||
|
||||
```bash
|
||||
# 获取最新的上游代码(如上节所述)
|
||||
git fetch upstream
|
||||
git checkout -b feature/your-feature-name upstream/main
|
||||
```
|
||||
|
||||
为分支命名时,可以遵循以下约定:
|
||||
- `feature/xxx`:新功能开发
|
||||
- `fix/xxx`:修复 bug
|
||||
- `docs/xxx`:文档更新
|
||||
- `test/xxx`:测试相关工作
|
||||
- `refactor/xxx`:代码重构
|
||||
|
||||
### 编码规范
|
||||
|
||||
我们使用 [PEP 8](https://www.python.org/dev/peps/pep-0008/) 作为 Python 代码风格指南。在提交代码前,请确保您的代码符合以下要求:
|
||||
|
||||
- 使用 4 个空格进行缩进
|
||||
- 行长度不超过 120 个字符
|
||||
- 使用有意义的变量和函数名称
|
||||
- 为公共 API 添加文档字符串
|
||||
- 使用类型提示(Type Hints)
|
||||
|
||||
我们推荐使用静态代码分析工具来帮助您遵循编码规范:
|
||||
|
||||
```bash
|
||||
# 使用 flake8 检查代码风格
|
||||
flake8 .
|
||||
|
||||
# 使用 mypy 进行类型检查
|
||||
mypy .
|
||||
```
|
||||
|
||||
### 测试
|
||||
|
||||
在提交之前,请确保所有测试都能通过
|
||||
|
||||
## 提交变更
|
||||
|
||||
### 提交前的检查清单
|
||||
|
||||
在提交您的代码之前,请确保完成以下检查:
|
||||
|
||||
1. 代码是否符合 PEP 8 规范
|
||||
2. 是否添加了必要的测试用例
|
||||
3. 所有测试是否通过
|
||||
4. 是否添加了适当的文档
|
||||
5. 是否解决了您计划解决的问题
|
||||
6. 是否与最新的上游代码保持同步
|
||||
|
||||
### 提交变更
|
||||
|
||||
在开发过程中,养成小批量、频繁提交的习惯。这样可以使您的更改更容易跟踪和理解:
|
||||
|
||||
```bash
|
||||
# 查看更改的文件
|
||||
git status
|
||||
|
||||
# 暂存更改
|
||||
git add file1.py file2.py
|
||||
|
||||
# 提交更改
|
||||
git commit -m "feat: add new feature X"
|
||||
```
|
||||
|
||||
### 解决冲突
|
||||
|
||||
如果您在尝试合并上游更改时遇到冲突,请按照以下步骤解决:
|
||||
|
||||
1. 首先了解冲突的位置:
|
||||
|
||||
```bash
|
||||
git status
|
||||
```
|
||||
|
||||
2. 打开冲突文件,您会看到类似以下标记:
|
||||
|
||||
```
|
||||
<<<<<<< HEAD
|
||||
您的代码
|
||||
=======
|
||||
上游代码
|
||||
>>>>>>> upstream/main
|
||||
```
|
||||
|
||||
3. 修改文件以解决冲突,删除冲突标记
|
||||
4. 解决完所有冲突后,暂存并提交:
|
||||
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "fix: resolve merge conflicts"
|
||||
```
|
||||
|
||||
### 提交规范
|
||||
|
||||
我们使用[约定式提交](https://www.conventionalcommits.org/zh-hans/)规范来格式化 Git 提交消息。提交消息应该遵循以下格式:
|
||||
|
||||
```
|
||||
<类型>[可选 作用域]: <描述>
|
||||
|
||||
[可选 正文]
|
||||
|
||||
[可选 脚注]
|
||||
```
|
||||
|
||||
常用的提交类型包括:
|
||||
- `feat`:新功能
|
||||
- `fix`:错误修复
|
||||
- `docs`:文档更改
|
||||
- `style`:不影响代码含义的变更(如空格、格式化等)
|
||||
- `refactor`:既不修复错误也不添加功能的代码重构
|
||||
- `perf`:提高性能的代码更改
|
||||
- `test`:添加或修正测试
|
||||
- `chore`:对构建过程或辅助工具和库的更改
|
||||
|
||||
例如:
|
||||
|
||||
```
|
||||
feat(tts): 添加新的语音合成引擎支持
|
||||
|
||||
添加对百度语音合成API的支持,包括以下功能:
|
||||
- 支持多种音色选择
|
||||
- 支持语速和音量调节
|
||||
- 支持中英文混合合成
|
||||
|
||||
修复 #123
|
||||
```
|
||||
|
||||
### 推送更改
|
||||
|
||||
完成代码更改后,将您的分支推送到您的 GitHub 仓库:
|
||||
|
||||
```bash
|
||||
git push origin feature/your-feature-name
|
||||
```
|
||||
|
||||
如果您已经创建了 Pull Request,并且需要更新它,只需再次推送到同一分支即可:
|
||||
|
||||
```bash
|
||||
# 在进行更多更改后
|
||||
git add .
|
||||
git commit -m "refactor: improve code based on feedback"
|
||||
git push origin feature/your-feature-name
|
||||
```
|
||||
|
||||
### 创建 Pull Request 前同步最新代码
|
||||
|
||||
在创建 Pull Request 前,建议再次与上游仓库同步,以避免潜在的冲突:
|
||||
|
||||
```bash
|
||||
# 获取上游最新代码
|
||||
git fetch upstream
|
||||
|
||||
# 将上游最新代码变基到您的特性分支
|
||||
git rebase upstream/main
|
||||
|
||||
# 如果出现冲突,解决冲突并继续变基
|
||||
git add .
|
||||
git rebase --continue
|
||||
|
||||
# 强制推送更新后的分支到您的仓库
|
||||
git push --force-with-lease origin feature/your-feature-name
|
||||
```
|
||||
|
||||
注意:使用 `--force-with-lease` 比直接使用 `--force` 更安全,它可以防止覆盖他人推送的更改。
|
||||
|
||||
### 创建 Pull Request
|
||||
|
||||
当您完成功能开发或问题修复后,请按照以下步骤创建 Pull Request:
|
||||
|
||||
1. 将您的更改推送到 GitHub:
|
||||
|
||||
```bash
|
||||
git push origin feature/your-feature-name
|
||||
```
|
||||
|
||||
2. 访问 GitHub 上您 fork 的仓库页面,点击 "Compare & pull request" 按钮
|
||||
|
||||
3. 填写 Pull Request 表单:
|
||||
- 使用清晰的标题,遵循提交消息格式
|
||||
- 在描述中提供详细信息
|
||||
- 引用相关 issue(使用 `#issue编号` 格式)
|
||||
- 如果这是一个进行中的工作,请添加 `[WIP]` 前缀到标题
|
||||
|
||||
4. 提交 Pull Request,等待项目维护者审核
|
||||
|
||||
### Pull Request 的生命周期
|
||||
|
||||
1. **创建**:提交您的 PR
|
||||
2. **CI 检查**:自动化测试和代码风格检查
|
||||
3. **代码审核**:维护者会审核您的代码并提供反馈
|
||||
4. **修订**:根据反馈修改您的代码
|
||||
5. **批准**:一旦您的 PR 被批准
|
||||
6. **合并**:维护者会将您的 PR 合并到主分支
|
||||
|
||||
## 文档贡献
|
||||
|
||||
如果您想改进项目文档,请按照以下步骤操作:
|
||||
|
||||
1. 按照上述步骤 Fork 项目并克隆到本地
|
||||
|
||||
2. 文档位于 `documents/docs` 目录下,使用 Markdown 格式
|
||||
|
||||
3. 安装文档开发依赖:
|
||||
|
||||
```bash
|
||||
cd documents
|
||||
pnpm install
|
||||
```
|
||||
|
||||
4. 启动本地文档服务器:
|
||||
|
||||
```bash
|
||||
pnpm docs:dev
|
||||
```
|
||||
|
||||
5. 在浏览器中访问 `http://localhost:5173/py-xiaozhi/` 预览您的更改
|
||||
|
||||
6. 完成更改后,提交您的贡献并创建 Pull Request
|
||||
|
||||
### 文档编写准则
|
||||
|
||||
- 使用清晰、简洁的语言
|
||||
- 提供实际示例
|
||||
- 对复杂概念进行详细解释
|
||||
- 包含适当的截图或图表(需要时)
|
||||
- 避免技术术语过多,必要时提供解释
|
||||
- 保持文档结构一致
|
||||
|
||||
## 问题反馈
|
||||
|
||||
如果您发现了问题但暂时无法修复,请在 GitHub 上[创建 Issue](https://github.com/huangjunsen0406/py-xiaozhi/issues/new)。创建 Issue 时,请包含以下信息:
|
||||
|
||||
- 问题的详细描述
|
||||
- 重现问题的步骤
|
||||
- 预期行为和实际行为
|
||||
- 您的操作系统和 Python 版本
|
||||
- 相关的日志输出或错误信息
|
||||
|
||||
## 代码审核
|
||||
|
||||
提交 Pull Request 后,项目维护者将会审核您的代码。在代码审核过程中:
|
||||
|
||||
- 请耐心等待反馈
|
||||
- 及时响应评论和建议
|
||||
- 必要时进行修改并更新您的 Pull Request
|
||||
- 保持礼貌和建设性的讨论
|
||||
|
||||
### 处理代码审核反馈
|
||||
|
||||
1. 认真阅读所有评论和建议
|
||||
2. 针对每个要点作出回应或更改
|
||||
3. 如果您不同意某个建议,礼貌地解释您的理由
|
||||
4. 修改完成后,在 PR 中留言通知审核者
|
||||
|
||||
## 成为项目维护者
|
||||
|
||||
如果您持续为项目做出有价值的贡献,您可能会被邀请成为项目的维护者。作为维护者,您将有权限审核和合并其他人的 Pull Request。
|
||||
|
||||
### 维护者的职责
|
||||
|
||||
- 审核 Pull Request
|
||||
- 管理 issue
|
||||
- 参与项目规划
|
||||
- 回答社区问题
|
||||
- 帮助引导新贡献者
|
||||
|
||||
## 行为准则
|
||||
|
||||
请尊重所有项目参与者,遵循以下行为准则:
|
||||
|
||||
- 使用包容性语言
|
||||
- 尊重不同的观点和经验
|
||||
- 优雅地接受建设性批评
|
||||
- 关注社区最佳利益
|
||||
- 对其他社区成员表示同理心
|
||||
|
||||
## 常见问题解答
|
||||
|
||||
### 我应该从哪里开始贡献?
|
||||
|
||||
1. 查看标记为 "good first issue" 的问题
|
||||
2. 修复文档中的错误或不清晰的部分
|
||||
3. 添加更多测试用例
|
||||
4. 解决您自己在使用过程中发现的问题
|
||||
|
||||
### 我提交的 PR 已经很久没有回应了,我该怎么办?
|
||||
|
||||
在 PR 中留言,礼貌地询问是否需要进一步的改进或澄清。请理解维护者可能很忙,需要一些时间来审核您的贡献。
|
||||
|
||||
### 我可以贡献哪些类型的更改?
|
||||
|
||||
- 错误修复
|
||||
- 新功能
|
||||
- 性能改进
|
||||
- 文档更新
|
||||
- 测试用例
|
||||
- 代码重构
|
||||
|
||||
## 致谢
|
||||
|
||||
再次感谢您为项目做出贡献!您的参与对我们非常重要,共同努力让 py-xiaozhi 变得更好!
|
||||
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.contributing-page {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem 1.5rem;
|
||||
}
|
||||
|
||||
.contributing-page h1 {
|
||||
text-align: center;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.header-content {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.header-content h2 {
|
||||
color: var(--vp-c-brand);
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.contributing-page h2 {
|
||||
margin-top: 3rem;
|
||||
padding-top: 1rem;
|
||||
border-top: 1px solid var(--vp-c-divider);
|
||||
}
|
||||
|
||||
.contributing-page h3 {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.contributing-page code {
|
||||
background-color: var(--vp-c-bg-soft);
|
||||
padding: 0.2em 0.4em;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.contributing-page pre {
|
||||
margin: 1rem 0;
|
||||
border-radius: 8px;
|
||||
overflow: auto;
|
||||
}
|
||||
</style>
|
130
py-xiaozhi-main/documents/docs/ecosystem/index.md
Executable file
@ -0,0 +1,130 @@
|
||||
---
|
||||
title: 相关生态
|
||||
description: py-xiaozhi项目相关的生态系统和扩展项目
|
||||
outline: deep
|
||||
---
|
||||
|
||||
<div class="ecosystem-page">
|
||||
|
||||
# 相关生态
|
||||
|
||||
<div class="header-content">
|
||||
<h2>py-xiaozhi项目生态系统 🌱</h2>
|
||||
<p>探索围绕py-xiaozhi构建的相关项目和扩展</p>
|
||||
</div>
|
||||
|
||||
## 生态概览
|
||||
|
||||
本页面将收集和展示py-xiaozhi项目相关的生态系统项目,包括:
|
||||
|
||||
- 官方扩展和插件
|
||||
- 社区贡献的项目
|
||||
- 兼容的硬件设备
|
||||
- 第三方集成方案
|
||||
- 示例项目和案例分析
|
||||
|
||||
## 即将推出
|
||||
|
||||
我们计划收集和整理以下内容:
|
||||
|
||||
- 各种设备上的安装和运行指南
|
||||
- 与智能家居系统的集成方案
|
||||
- 定制语音指令和技能的开发教程
|
||||
- 基于py-xiaozhi构建的项目案例
|
||||
- 社区贡献的扩展功能
|
||||
|
||||
## 参与贡献
|
||||
|
||||
如果您有相关的项目或扩展想要分享,欢迎通过以下方式参与贡献:
|
||||
|
||||
1. 在GitHub上提交Pull Request,添加您的项目
|
||||
2. 在Issues中建议您希望看到的集成或扩展
|
||||
3. 分享您使用py-xiaozhi的经验和案例
|
||||
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.ecosystem-page {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem 1.5rem;
|
||||
}
|
||||
|
||||
.ecosystem-page h1 {
|
||||
text-align: center;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.header-content {
|
||||
text-align: center;
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.header-content h2 {
|
||||
color: var(--vp-c-brand);
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.ecosystem-page h2 {
|
||||
margin-top: 3rem;
|
||||
padding-top: 1rem;
|
||||
border-top: 1px solid var(--vp-c-divider);
|
||||
}
|
||||
|
||||
.ecosystem-page blockquote {
|
||||
border-left: 4px solid var(--vp-c-brand);
|
||||
padding: 1rem;
|
||||
background-color: var(--vp-c-bg-soft);
|
||||
margin: 2rem 0;
|
||||
border-radius: 0 8px 8px 0;
|
||||
}
|
||||
|
||||
.features {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
gap: 2rem;
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
.feature {
|
||||
background-color: var(--vp-c-bg-soft);
|
||||
border-radius: 8px;
|
||||
padding: 1.5rem;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.feature:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.feature h3 {
|
||||
color: var(--vp-c-brand);
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
font-size: 1.3rem;
|
||||
}
|
||||
|
||||
.feature-links {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.feature-links a {
|
||||
display: block;
|
||||
padding: 0.5rem;
|
||||
border-radius: 4px;
|
||||
background-color: rgba(var(--vp-c-brand-rgb), 0.1);
|
||||
color: var(--vp-c-brand-dark);
|
||||
text-decoration: none;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.feature-links a:hover {
|
||||
background-color: rgba(var(--vp-c-brand-rgb), 0.2);
|
||||
transform: translateX(5px);
|
||||
}
|
||||
</style>
|
BIN
py-xiaozhi-main/documents/docs/ecosystem/projects/intelliconnect/images/logo.png
Executable file
After Width: | Height: | Size: 87 KiB |
237
py-xiaozhi-main/documents/docs/ecosystem/projects/intelliconnect/index.md
Executable file
@ -0,0 +1,237 @@
|
||||
---
|
||||
title: IntelliConnect
|
||||
description: 基于SpringBoot的智能物联网平台,集成Agent智能体技术的IoT解决方案
|
||||
---
|
||||
|
||||
# IntelliConnect
|
||||
|
||||
<div class="project-header">
|
||||
<div class="project-logo">
|
||||
<img src="./images/logo.png" alt="IntelliConnect Logo">
|
||||
</div>
|
||||
<div class="project-badges">
|
||||
<span class="badge platform">跨平台</span>
|
||||
<span class="badge language">Java/Spring</span>
|
||||
<span class="badge status">v0.1</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ascii-art">
|
||||
<pre>
|
||||
██╗ ███╗ ██╗ ████████╗ ███████╗ ██╗ ██╗ ██╗ ██████╗ ██████╗ ███╗ ██╗ ███╗ ██╗ ███████╗ ██████╗ ████████╗
|
||||
██║ ████╗ ██║ ╚══██╔══╝ ██╔════╝ ██║ ██║ ██║ ██╔════╝ ██╔═══██╗ ████╗ ██║ ████╗ ██║ ██╔════╝ ██╔════╝ ╚══██╔══╝
|
||||
██║ ██╔██╗ ██║ ██║ █████╗ ██║ ██║ ██║ ██║ ██║ ██║ ██╔██╗ ██║ ██╔██╗ ██║ █████╗ ██║ ██║
|
||||
██║ ██║╚██╗██║ ██║ ██╔══╝ ██║ ██║ ██║ ██║ ██║ ██║ ██║╚██╗██║ ██║╚██╗██║ ██╔══╝ ██║ ██║
|
||||
██║ ██║ ╚████║ ██║ ███████╗ ███████╗ ███████╗ ██║ ╚██████╗ ╚██████╔╝ ██║ ╚████║ ██║ ╚████║ ███████╗ ╚██████╗ ██║
|
||||
╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚══════╝ ╚══════╝ ╚══════╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═══╝ ╚═╝ ╚═══╝ ╚══════╝ ╚═════╝ ╚═╝
|
||||
</pre>
|
||||
<p class="ascii-caption">Built by RSLLY</p>
|
||||
</div>
|
||||
|
||||
<div class="project-badges-center">
|
||||
<img src="https://img.shields.io/badge/license-apache2.0-yellow?style=flat-square" alt="License" />
|
||||
<img src="https://img.shields.io/badge/release-v0.1-blue?style=flat-square" alt="Release" />
|
||||
<img src="https://img.shields.io/badge/cwl-project1.8-green?style=flat-square" alt="CWL Project" />
|
||||
</div>
|
||||
|
||||
## 概述
|
||||
|
||||
* 本项目基于springboot2.7开发,使用spring security作为安全框架
|
||||
* 配备物模型(属性,功能和事件模块)和完善的监控模块
|
||||
* 支持多种大模型和先进的Agent智能体技术提供出色的AI智能,可以快速搭建智能物联网应用(首个基于Agent智能体设计的物联网平台)
|
||||
* 支持快速构建智能语音应用,支持语音识别和语音合成
|
||||
* 支持多种iot协议,使用emqx exhook作为mqtt通讯,可扩展性强
|
||||
* 支持OTA空中升级技术
|
||||
* 支持微信小程序和微信服务号
|
||||
* 支持小智AI硬件
|
||||
* 使用常见的mysql和redis数据库,上手简单
|
||||
* 支持时序数据库influxdb
|
||||
|
||||
## 安装运行
|
||||
|
||||
<div class="notice">
|
||||
<p>推荐使用docker安装,docker-compose.yaml文件在docker目录下,执行 docker-compose up 可初始化mysql,redis,emqx和influxdb环境,安装详情请看官方文档。</p>
|
||||
</div>
|
||||
|
||||
* 安装mysql和redis数据库,高性能运行推荐安装时序数据库influxdb
|
||||
* 安装EMQX集群,并配置好exhook,本项目使用exhook作为mqtt消息的处理器
|
||||
* 安装java17环境
|
||||
* 修改配置文件application.yaml(设置ddl-auto为update模式)
|
||||
* java -jar IntelliConnect-1.8-SNAPSHOT.jar
|
||||
|
||||
```bash
|
||||
# 克隆仓库
|
||||
git clone https://github.com/ruanrongman/IntelliConnect
|
||||
cd intelliconnect/docker
|
||||
|
||||
# 启动所需环境(MySQL, Redis, EMQX, InfluxDB)
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
## 项目特色
|
||||
|
||||
* 极简主义,层次分明,符合mvc分层结构
|
||||
* 完善的物模型抽象,使得iot开发者可以专注于业务本身
|
||||
* AI能力丰富,支持Agent智能体技术,快速开发AI智能应用
|
||||
|
||||
## 小智 ESP-32 后端服务(xiaozhi-esp32-server)
|
||||
|
||||
<div class="esp32-section">
|
||||
<p>本项目能够为开源智能硬件项目 <a href="https://github.com/78/xiaozhi-esp32" target="_blank">xiaozhi-esp32</a> 提供后端服务。根据 <a href="https://ccnphfhqs21z.feishu.cn/wiki/M0XiwldO9iJwHikpXD5cEx71nKh" target="_blank">小智通信协议</a> 使用 <code>Java</code> 实现。</p>
|
||||
<p>适合希望本地部署的用户,不同于单纯语音交互,本项目重点在于提供更强大的物联网和智能体能力。</p>
|
||||
</div>
|
||||
|
||||
## 项目文档和视频演示
|
||||
|
||||
* 项目文档和视频演示地址:[https://ruanrongman.github.io/IntelliConnect/](https://ruanrongman.github.io/IntelliConnect/)
|
||||
* 技术博客地址:[https://wordpress.rslly.top](https://wordpress.rslly.top)
|
||||
* 社区地址:[https://github.com/cwliot](https://github.com/cwliot)
|
||||
* 创万联社区公众号:微信直接搜索创万联
|
||||
|
||||
## 相关项目和社区
|
||||
|
||||
* **创万联(cwl)**: 专注于物联网和人工智能技术的开源社区。
|
||||
* **Promptulate**: [https://github.com/Undertone0809/promptulate](https://github.com/Undertone0809/promptulate) - A LLM application and Agent development framework.
|
||||
* **Rymcu**: [https://github.com/rymcu](https://github.com/rymcu) - 为数百万人服务的开源嵌入式知识学习交流平台
|
||||
|
||||
## 致谢
|
||||
|
||||
* 感谢项目[xiaozhi-esp32](https://github.com/78/xiaozhi-esp32)提供强大的硬件语音交互。
|
||||
* 感谢项目[Concentus: Opus for Everyone](https://github.com/lostromb/concentus)提供opus解码和编码。
|
||||
* 感谢项目[TalkX](https://github.com/big-mouth-cn/talkx)提供了opus解码和编码的参考。
|
||||
* 感谢项目[py-xiaozhi](https://github.com/huangjunsen0406/py-xiaozhi)方便项目进行小智开发调试。
|
||||
|
||||
## 贡献
|
||||
|
||||
本人正在尝试一些更加完善的抽象模式,支持更多的物联网协议和数据存储形式,如果你有更好的建议,欢迎一起讨论交流。
|
||||
|
||||
<style>
|
||||
.project-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.project-logo {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
margin-right: 1.5rem;
|
||||
}
|
||||
|
||||
.project-logo img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.project-badges {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.badge {
|
||||
display: inline-block;
|
||||
padding: 0.25rem 0.75rem;
|
||||
border-radius: 1rem;
|
||||
font-size: 0.85rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.badge.platform {
|
||||
background-color: var(--vp-c-brand-soft);
|
||||
color: var(--vp-c-brand-dark);
|
||||
}
|
||||
|
||||
.badge.language {
|
||||
background-color: rgba(59, 130, 246, 0.2);
|
||||
color: rgb(59, 130, 246);
|
||||
}
|
||||
|
||||
.badge.status {
|
||||
background-color: rgba(234, 179, 8, 0.2);
|
||||
color: rgb(234, 179, 8);
|
||||
}
|
||||
|
||||
.ascii-art {
|
||||
overflow-x: auto;
|
||||
margin: 2rem 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.ascii-art pre {
|
||||
display: inline-block;
|
||||
text-align: left;
|
||||
font-size: 0.6rem;
|
||||
line-height: 1;
|
||||
white-space: pre;
|
||||
margin: 0;
|
||||
background: transparent;
|
||||
color: var(--vp-c-brand);
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
.ascii-caption {
|
||||
font-size: 0.8rem;
|
||||
margin-top: 0.5rem;
|
||||
color: var(--vp-c-text-2);
|
||||
}
|
||||
|
||||
.project-badges-center {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.5rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.notice {
|
||||
background-color: var(--vp-c-bg-soft);
|
||||
border-left: 4px solid var(--vp-c-brand);
|
||||
padding: 1rem 1.5rem;
|
||||
margin: 1.5rem 0;
|
||||
border-radius: 0 8px 8px 0;
|
||||
}
|
||||
|
||||
.esp32-section {
|
||||
background-color: var(--vp-c-bg-soft);
|
||||
border-radius: 8px;
|
||||
padding: 1.5rem;
|
||||
margin: 1.5rem 0;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
}
|
||||
|
||||
.qr-container {
|
||||
text-align: center;
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
.qr-code {
|
||||
width: 250px;
|
||||
height: auto;
|
||||
object-fit: contain;
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.ascii-art pre {
|
||||
font-size: 0.4rem;
|
||||
}
|
||||
|
||||
.project-header {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.project-logo {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.ascii-art {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
BIN
py-xiaozhi-main/documents/docs/ecosystem/projects/open-xiaoai/images/logo.png
Executable file
After Width: | Height: | Size: 1.1 MiB |
459
py-xiaozhi-main/documents/docs/ecosystem/projects/open-xiaoai/index.md
Executable file
@ -0,0 +1,459 @@
|
||||
---
|
||||
title: open-xiaoai
|
||||
description: 让小爱音箱「听见你的声音」,解锁无限可能的开源项目
|
||||
---
|
||||
|
||||
# open-xiaoai
|
||||
|
||||
<div class="project-header">
|
||||
<div class="project-logo">
|
||||
<img src="https://avatars.githubusercontent.com/u/35302658?s=48&v=4" alt="open-xiaoai Logo">
|
||||
</div>
|
||||
<div class="project-badges">
|
||||
<span class="badge platform">跨平台</span>
|
||||
<span class="badge language">Rust/Python/Node.js</span>
|
||||
<span class="badge status">实验性</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="project-banner">
|
||||
<img src="./images/logo.png" alt="Open-XiaoAI 项目封面">
|
||||
</div>
|
||||
|
||||
## 项目简介
|
||||
|
||||
Open-XiaoAI 是一个让小爱音箱"听见你的声音"的开源项目,将小爱音箱与小智AI生态系统无缝集成。该项目直接接管小爱音箱的"耳朵"和"嘴巴",通过多模态大模型和AI Agent技术,将小爱音箱的潜力完全释放,解锁无限可能。
|
||||
|
||||
2017年,当全球首款千万级销量的智能音箱诞生时,我们以为触摸到了未来。但很快发现,这些设备被困在「指令-响应」的牢笼里:
|
||||
|
||||
- 它听得见分贝,却听不懂情感
|
||||
- 它能执行命令,却不会主动思考
|
||||
- 它有千万用户,却只有一套思维
|
||||
|
||||
我们曾幻想中的"贾维斯"级人工智能,在现实场景中沦为"闹钟+音乐播放器"。
|
||||
|
||||
**真正的智能不应被预设的代码逻辑所束缚,而应像生命体般在交互中进化。**
|
||||
|
||||
在上一个 [MiGPT](https://github.com/idootop/mi-gpt) 项目的基础上,Open-XiaoAI再次进化,为小智生态系统提供了与小爱音箱交互的新方式。
|
||||
|
||||
## 核心功能
|
||||
|
||||
<div class="features-grid">
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">🎤</div>
|
||||
<h3>语音输入接管</h3>
|
||||
<p>直接捕获小爱音箱的麦克风输入,绕过原有语音识别限制</p>
|
||||
</div>
|
||||
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">🔊</div>
|
||||
<h3>声音输出控制</h3>
|
||||
<p>完全接管小爱音箱的扬声器,可以播放自定义音频和TTS内容</p>
|
||||
</div>
|
||||
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">🧠</div>
|
||||
<h3>AI模型整合</h3>
|
||||
<p>支持接入小智AI、ChatGPT等多种大模型,实现自然对话体验</p>
|
||||
</div>
|
||||
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">🌐</div>
|
||||
<h3>跨平台支持</h3>
|
||||
<p>Client端使用Rust开发,Server端支持Python和Node.js实现</p>
|
||||
</div>
|
||||
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">🛠️</div>
|
||||
<h3>可扩展架构</h3>
|
||||
<p>模块化设计,方便开发者添加自定义功能和集成其他服务</p>
|
||||
</div>
|
||||
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">🎮</div>
|
||||
<h3>开发者友好</h3>
|
||||
<p>详细的文档和教程,帮助开发者快速上手并定制自己的功能</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
## 演示视频
|
||||
|
||||
<div class="demo-videos">
|
||||
<div class="video-item">
|
||||
<a href="https://www.bilibili.com/video/BV1NBXWYSEvX" target="_blank" class="video-link">
|
||||
<div class="video-thumbnail">
|
||||
<img src="https://raw.githubusercontent.com/idootop/open-xiaoai/main/docs/images/xiaozhi.jpg" alt="小爱音箱接入小智AI">
|
||||
</div>
|
||||
<div class="video-title">
|
||||
<span class="video-icon">▶️</span>
|
||||
<span>小爱音箱接入小智AI演示</span>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="video-item">
|
||||
<a href="https://www.bilibili.com/video/BV1N1421y7qn" target="_blank" class="video-link">
|
||||
<div class="video-thumbnail">
|
||||
<img src="https://github.com/idootop/open-xiaoai/raw/main/docs/images/migpt.jpg" alt="小爱音箱接入MiGPT">
|
||||
</div>
|
||||
<div class="video-title">
|
||||
<span class="video-icon">▶️</span>
|
||||
<span>小爱音箱接入MiGPT演示</span>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
## 快速开始
|
||||
|
||||
<div class="important-notice">
|
||||
<div class="notice-icon">⚠️</div>
|
||||
<div class="notice-content">
|
||||
<strong>重要提示</strong>
|
||||
<p>本教程仅适用于 <strong>小爱音箱 Pro(LX06)</strong> 和 <strong>Xiaomi 智能音箱 Pro(OH2P)</strong> 这两款机型,<strong>其他型号</strong>的小爱音箱请勿直接使用!</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Open-XiaoAI项目由Client端和Server端两部分组成,您可以按照以下步骤快速开始:
|
||||
|
||||
### 安装步骤
|
||||
|
||||
<div class="steps">
|
||||
<div class="step">
|
||||
<div class="step-number">1</div>
|
||||
<div class="step-content">
|
||||
<h4>小爱音箱固件更新</h4>
|
||||
<p>刷机更新小爱音箱补丁固件,开启并SSH连接到小爱音箱</p>
|
||||
<a href="https://github.com/idootop/open-xiaoai/blob/main/docs/flash.md" target="_blank" class="step-link">查看详细教程</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="step">
|
||||
<div class="step-number">2</div>
|
||||
<div class="step-content">
|
||||
<h4>客户端部署</h4>
|
||||
<p>在电脑上编译Client端补丁程序,然后复制到小爱音箱上运行</p>
|
||||
<a href="https://github.com/idootop/open-xiaoai/blob/main/packages/client-rust/README.md" target="_blank" class="step-link">查看详细教程</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="step">
|
||||
<div class="step-number">3</div>
|
||||
<div class="step-content">
|
||||
<h4>服务端部署</h4>
|
||||
<p>在电脑上运行Server端演示程序,体验小爱音箱的全新能力</p>
|
||||
<ul class="step-options">
|
||||
<li><a href="https://github.com/idootop/open-xiaoai/blob/main/packages/server-python/README.md" target="_blank">Python Server - 小爱音箱接入小智AI</a></li>
|
||||
<li><a href="https://github.com/idootop/open-xiaoai/blob/main/packages/server-node/README.md" target="_blank">Node.js Server - 小爱音箱接入MiGPT-Next</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
## 工作原理
|
||||
|
||||
Open-XiaoAI通过以下方式工作:
|
||||
|
||||
1. **固件补丁**: 修改小爱音箱的固件,允许SSH访问和底层系统控制
|
||||
2. **音频流劫持**: 客户端程序直接捕获麦克风输入和控制扬声器输出
|
||||
3. **网络通信**: 客户端与服务端之间建立WebSocket连接进行实时通信
|
||||
4. **AI处理**: 服务端接收语音输入,交由AI模型处理后返回响应
|
||||
5. **自定义功能**: 开发者可以在服务端实现各种自定义功能和集成
|
||||
|
||||
## 相关项目
|
||||
|
||||
如果您不想刷机,或者不是小爱音箱Pro,以下项目可能对您有用:
|
||||
|
||||
- [MiGPT](https://github.com/idootop/mi-gpt) - 将ChatGPT接入小爱音箱的原始项目
|
||||
- [MiGPT-Next](https://github.com/idootop/migpt-next) - MiGPT的下一代版本
|
||||
- [XiaoGPT](https://github.com/yihong0618/xiaogpt) - 另一个小爱音箱ChatGPT接入方案
|
||||
- [XiaoMusic](https://github.com/hanxi/xiaomusic) - 小爱音箱音乐播放增强
|
||||
|
||||
## 技术参考
|
||||
|
||||
如果您想了解更多技术细节,以下链接可能对您有帮助:
|
||||
|
||||
- [xiaoai-patch](https://github.com/duhow/xiaoai-patch) - 小爱音箱固件补丁
|
||||
- [open-lx01](https://github.com/jialeicui/open-lx01) - 小爱音箱LX01开源项目
|
||||
- [小爱FM研究](https://javabin.cn/2021/xiaoai_fm.html) - 小爱音箱FM功能研究
|
||||
- [小米设备安全研究](https://github.com/yihong0618/gitblog/issues/258) - 小米IoT设备安全分析
|
||||
- [小爱音箱探索](https://xuanxuanblingbling.github.io/iot/2022/09/16/mi/) - 小爱音箱技术探索
|
||||
|
||||
## 免责声明
|
||||
|
||||
<div class="disclaimer">
|
||||
<h4>适用范围</h4>
|
||||
<p>本项目为非盈利开源项目,仅限于技术原理研究、安全漏洞验证及非营利性个人使用。严禁用于商业服务、网络攻击、数据窃取、系统破坏等违反《网络安全法》及使用者所在地司法管辖区的法律规定的场景。</p>
|
||||
|
||||
<h4>非官方声明</h4>
|
||||
<p>本项目由第三方开发者独立开发,与小米集团及其关联方(下称"权利方")无任何隶属/合作关系,未获其官方授权/认可或技术支持。项目中涉及的商标、固件、云服务的所有权利归属小米集团。若权利方主张权益,使用者应立即主动停止使用并删除本项目。</p>
|
||||
|
||||
<p>继续使用本项目,即表示您已完整阅读并同意<a href="https://github.com/idootop/open-xiaoai/blob/main/agreement.md" target="_blank">用户协议</a>,否则请立即终止使用并彻底删除本项目。</p>
|
||||
</div>
|
||||
|
||||
## 许可证
|
||||
|
||||
本项目使用 [MIT](https://github.com/idootop/open-xiaoai/blob/main/LICENSE) 许可证 © 2024-PRESENT Del Wang
|
||||
|
||||
<style>
|
||||
.project-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.project-logo {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
margin-right: 1.5rem;
|
||||
}
|
||||
|
||||
.project-logo img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.project-badges {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.badge {
|
||||
display: inline-block;
|
||||
padding: 0.25rem 0.75rem;
|
||||
border-radius: 1rem;
|
||||
font-size: 0.85rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.badge.platform {
|
||||
background-color: var(--vp-c-brand-soft);
|
||||
color: var(--vp-c-brand-dark);
|
||||
}
|
||||
|
||||
.badge.language {
|
||||
background-color: rgba(59, 130, 246, 0.2);
|
||||
color: rgb(59, 130, 246);
|
||||
}
|
||||
|
||||
.badge.status {
|
||||
background-color: rgba(139, 92, 246, 0.2);
|
||||
color: rgb(139, 92, 246);
|
||||
}
|
||||
|
||||
.project-banner {
|
||||
width: 100%;
|
||||
margin: 2rem 0;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
}
|
||||
|
||||
.project-banner img {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.features-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
||||
gap: 1.5rem;
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
.feature-card {
|
||||
background-color: var(--vp-c-bg-soft);
|
||||
border-radius: 8px;
|
||||
padding: 1.5rem;
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.feature-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.feature-icon {
|
||||
font-size: 2rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.feature-card h3 {
|
||||
color: var(--vp-c-brand);
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.demo-videos {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
||||
gap: 1.5rem;
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
.video-item {
|
||||
background-color: var(--vp-c-bg-soft);
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
.video-item:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.video-link {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.video-thumbnail {
|
||||
width: 100%;
|
||||
height: 180px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.video-thumbnail img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.video-item:hover .video-thumbnail img {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.video-title {
|
||||
padding: 1rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.video-icon {
|
||||
color: var(--vp-c-brand);
|
||||
}
|
||||
|
||||
.important-notice {
|
||||
background-color: rgba(234, 179, 8, 0.1);
|
||||
border-left: 4px solid rgba(234, 179, 8, 0.8);
|
||||
border-radius: 0 8px 8px 0;
|
||||
padding: 1rem 1.5rem;
|
||||
margin: 2rem 0;
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.notice-icon {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.notice-content strong {
|
||||
display: block;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.steps {
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
.step {
|
||||
display: flex;
|
||||
margin-bottom: 1.5rem;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.step-number {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
background-color: var(--vp-c-brand);
|
||||
color: white;
|
||||
border-radius: 50%;
|
||||
font-weight: bold;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.step-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.step-content h4 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
color: var(--vp-c-brand);
|
||||
}
|
||||
|
||||
.step-link {
|
||||
display: inline-block;
|
||||
margin-top: 0.5rem;
|
||||
color: var(--vp-c-brand);
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.step-link:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.step-options {
|
||||
list-style-type: disc;
|
||||
padding-left: 1.5rem;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.architecture-diagram {
|
||||
text-align: center;
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
.architecture-diagram img {
|
||||
max-width: 100%;
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
}
|
||||
|
||||
.disclaimer {
|
||||
background-color: rgba(239, 68, 68, 0.1);
|
||||
border-left: 4px solid rgba(239, 68, 68, 0.8);
|
||||
border-radius: 0 8px 8px 0;
|
||||
padding: 1.5rem;
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
.disclaimer h4 {
|
||||
margin-top: 0;
|
||||
color: rgba(239, 68, 68, 0.8);
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.disclaimer p {
|
||||
margin: 0.5rem 0;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.project-header {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.project-logo {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.demo-videos {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
After Width: | Height: | Size: 84 KiB |
After Width: | Height: | Size: 146 KiB |
@ -0,0 +1,500 @@
|
||||
---
|
||||
title: 小智手机端
|
||||
description: 基于Flutter的跨平台小智客户端,支持iOS、Android、Web等多平台
|
||||
---
|
||||
|
||||
# 小智手机客户端
|
||||
|
||||
<div class="project-header">
|
||||
<div class="project-logo">
|
||||
<img src="https://avatars.githubusercontent.com/u/196275872?s=48&v=4" alt="小智手机客户端">
|
||||
</div>
|
||||
<div class="project-badges">
|
||||
<span class="badge platform">多平台</span>
|
||||
<span class="badge language">Flutter/Dart</span>
|
||||
<span class="badge status">活跃开发中</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
## 项目简介
|
||||
|
||||
小智手机客户端是基于Flutter框架开发的跨平台应用,为小智AI生态系统提供了移动端接入能力。通过一套代码,实现了在iOS、Android、Web、Windows、macOS和Linux等多个平台的部署,让用户随时随地都能与小智AI进行实时语音交互和文字对话。
|
||||
|
||||
<div class="app-showcase">
|
||||
<div class="showcase-image">
|
||||
<img src="./images/界面1.jpg" alt="应用展示" onerror="this.src='./images/界面1.jpg'; this.onerror=null;">
|
||||
<div class="overlay">
|
||||
<a href="https://www.bilibili.com/video/BV1fgXvYqE61" target="_blank" class="watch-demo">观看演示视频</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="showcase-description">
|
||||
<p>最新版本客户端已全面升级,支持iOS与Android平台,并可自行打包为Web、PC版本。通过精心设计的UI和流畅的交互体验,为用户提供随时随地与小智AI交流的能力。</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
## 核心功能
|
||||
|
||||
<div class="features-grid">
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">📱</div>
|
||||
<h3>跨平台支持</h3>
|
||||
<p>使用Flutter开发,一套代码支持iOS、Android、Web、Windows、macOS和Linux等多平台</p>
|
||||
</div>
|
||||
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">🤖</div>
|
||||
<h3>多AI模型集成</h3>
|
||||
<p>支持小智AI服务、Dify、OpenAI等多种AI服务,可随时切换不同模型</p>
|
||||
</div>
|
||||
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">💬</div>
|
||||
<h3>丰富交互方式</h3>
|
||||
<p>支持实时语音对话、文字消息、图片消息,以及通话中手动打断功能</p>
|
||||
</div>
|
||||
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">🔊</div>
|
||||
<h3>语音优化技术</h3>
|
||||
<p>实现安卓设备AEC+NS回音消除,提升语音交互质量</p>
|
||||
</div>
|
||||
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">🎨</div>
|
||||
<h3>精美界面设计</h3>
|
||||
<p>轻度拟物化设计、流畅动画效果、自适应UI布局</p>
|
||||
</div>
|
||||
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">⚙️</div>
|
||||
<h3>灵活配置选项</h3>
|
||||
<p>支持多种AI服务配置管理,可添加多个小智到聊天列表</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
## 功能亮点
|
||||
|
||||
### 实时语音交互
|
||||
|
||||
<div class="feature-highlight">
|
||||
<div class="highlight-image">
|
||||
<img src="./images/界面1.jpg" alt="实时语音交互" onerror="this.src='./images/界面1.jpg'; this.onerror=null;">
|
||||
</div>
|
||||
<div class="highlight-content">
|
||||
<h3>流畅的语音对话体验</h3>
|
||||
<ul>
|
||||
<li>实时语音识别和响应</li>
|
||||
<li>支持持续对话模式</li>
|
||||
<li>语音交互过程中支持手动打断</li>
|
||||
<li>按住说话快捷模式</li>
|
||||
<li>语音会话历史记录</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
### 多AI服务支持
|
||||
|
||||
<div class="feature-highlight reverse">
|
||||
<div class="highlight-content">
|
||||
<h3>灵活切换不同AI服务</h3>
|
||||
<ul>
|
||||
<li>集成小智WebSocket实时语音对话</li>
|
||||
<li>支持Dify平台接入</li>
|
||||
<li>支持OpenAI图文消息和流式输出</li>
|
||||
<li>支持官方小智服务一键设备注册</li>
|
||||
<li>可同时添加多个AI服务到对话列表</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="highlight-image">
|
||||
<img src="./images/界面2.jpg" alt="多AI服务支持" onerror="this.src='./images/界面2.jpg'; this.onerror=null;">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
## 系统要求
|
||||
|
||||
- **Flutter**: ^3.7.0
|
||||
- **Dart**: ^3.7.0
|
||||
- **iOS**: 12.0+
|
||||
- **Android**: API 21+ (Android 5.0+)
|
||||
- **Web**: 现代浏览器
|
||||
|
||||
## 安装与使用
|
||||
|
||||
### 安装方法
|
||||
|
||||
1. 克隆项目仓库:
|
||||
```bash
|
||||
git clone https://github.com/TOM88812/xiaozhi-android-client.git
|
||||
```
|
||||
|
||||
2. 安装依赖:
|
||||
```bash
|
||||
flutter pub get
|
||||
```
|
||||
|
||||
3. 运行应用:
|
||||
```bash
|
||||
flutter run
|
||||
```
|
||||
|
||||
### 构建发布版本
|
||||
|
||||
```bash
|
||||
# Android应用
|
||||
flutter build apk --release
|
||||
|
||||
# iOS应用
|
||||
flutter build ios --release
|
||||
|
||||
# Web应用
|
||||
flutter build web --release
|
||||
```
|
||||
|
||||
> **注意**: iOS编译完成后,需要在设置-APP中打开网络权限
|
||||
|
||||
## 配置说明
|
||||
|
||||
应用支持灵活的服务配置管理,包括:
|
||||
|
||||
### 小智服务配置
|
||||
- 支持配置多个小智服务地址
|
||||
- WebSocket URL设置
|
||||
- Token认证
|
||||
- 自定义MAC地址
|
||||
|
||||
### Dify API配置
|
||||
- 支持配置多个Dify服务
|
||||
- API密钥管理
|
||||
- 服务器URL配置
|
||||
|
||||
### OpenAI配置
|
||||
- API密钥设置
|
||||
- 模型选择
|
||||
- 参数调整
|
||||
|
||||
## 开发计划
|
||||
|
||||
<div class="roadmap">
|
||||
<div class="roadmap-item done">
|
||||
<div class="status-dot"></div>
|
||||
<div class="item-content">
|
||||
<h4>已实现功能</h4>
|
||||
<ul>
|
||||
<li>支持多种AI服务提供商</li>
|
||||
<li>支持OTA自动注册设备</li>
|
||||
<li>增强语音识别准确性</li>
|
||||
<li>实现文字和语音混合会话</li>
|
||||
<li>支持OpenAI接口图文交互</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="roadmap-item progress">
|
||||
<div class="status-dot"></div>
|
||||
<div class="item-content">
|
||||
<h4>正在开发</h4>
|
||||
<ul>
|
||||
<li>深色/浅色主题适配</li>
|
||||
<li>iOS平台回音消除实现</li>
|
||||
<li>本地ASR语音识别支持</li>
|
||||
<li>本地唤醒词功能</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="roadmap-item planned">
|
||||
<div class="status-dot"></div>
|
||||
<div class="item-content">
|
||||
<h4>计划实现</h4>
|
||||
<ul>
|
||||
<li>支持IoT映射手机操作</li>
|
||||
<li>本地TTS实现</li>
|
||||
<li>支持MCP_Client</li>
|
||||
<li>OpenAI接口联网搜索功能</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
## 项目贡献
|
||||
|
||||
欢迎为小智手机客户端贡献代码或提交问题反馈:
|
||||
|
||||
- 目前iOS端回音消除尚未实现,欢迎有经验的开发者PR
|
||||
- 提交Bug、功能请求或改进建议
|
||||
- 分享您使用小智手机客户端的经验和案例
|
||||
|
||||
## 相关链接
|
||||
|
||||
- [项目GitHub仓库](https://github.com/TOM88812/xiaozhi-android-client)
|
||||
- [演示视频](https://www.bilibili.com/video/BV1fgXvYqE61)
|
||||
- [问题反馈](https://github.com/TOM88812/xiaozhi-android-client/issues)
|
||||
|
||||
<style>
|
||||
.project-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.project-logo {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
margin-right: 1.5rem;
|
||||
}
|
||||
|
||||
.project-logo img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.project-badges {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.badge {
|
||||
display: inline-block;
|
||||
padding: 0.25rem 0.75rem;
|
||||
border-radius: 1rem;
|
||||
font-size: 0.85rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.badge.platform {
|
||||
background-color: var(--vp-c-brand-soft);
|
||||
color: var(--vp-c-brand-dark);
|
||||
}
|
||||
|
||||
.badge.language {
|
||||
background-color: rgba(59, 130, 246, 0.2);
|
||||
color: rgb(59, 130, 246);
|
||||
}
|
||||
|
||||
.badge.status {
|
||||
background-color: rgba(16, 185, 129, 0.2);
|
||||
color: rgb(16, 185, 129);
|
||||
}
|
||||
|
||||
.app-showcase {
|
||||
margin: 2rem 0;
|
||||
background-color: var(--vp-c-bg-soft);
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
}
|
||||
|
||||
.showcase-image {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
.showcase-image img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.showcase-image:hover .overlay {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.watch-demo {
|
||||
padding: 0.75rem 1.5rem;
|
||||
/*background-color: var(--vp-c-brand);*/
|
||||
color: white;
|
||||
border-radius: 4px;
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
transition: background-color 0.1s ease;
|
||||
}
|
||||
|
||||
.watch-demo:hover {
|
||||
background-color: var(--vp-c-brand-dark);
|
||||
}
|
||||
|
||||
.showcase-description {
|
||||
padding: 1.5rem;
|
||||
font-size: 1.1rem;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.features-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
||||
gap: 1.5rem;
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
.feature-card {
|
||||
background-color: var(--vp-c-bg-soft);
|
||||
border-radius: 8px;
|
||||
padding: 1.5rem;
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.feature-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.feature-icon {
|
||||
font-size: 2rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.feature-card h3 {
|
||||
color: var(--vp-c-brand);
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.feature-highlight {
|
||||
display: flex;
|
||||
margin: 3rem 0;
|
||||
background-color: var(--vp-c-bg-soft);
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
}
|
||||
|
||||
.feature-highlight.reverse {
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
.highlight-image {
|
||||
flex: 1;
|
||||
min-width: 40%;
|
||||
}
|
||||
|
||||
.highlight-image img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.highlight-content {
|
||||
flex: 1;
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
.highlight-content h3 {
|
||||
color: var(--vp-c-brand);
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.highlight-content ul {
|
||||
padding-left: 1.5rem;
|
||||
}
|
||||
|
||||
.highlight-content li {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.roadmap {
|
||||
position: relative;
|
||||
margin: 3rem 0;
|
||||
padding-left: 2rem;
|
||||
}
|
||||
|
||||
.roadmap:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 7px;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 2px;
|
||||
background-color: var(--vp-c-divider);
|
||||
}
|
||||
|
||||
.roadmap-item {
|
||||
position: relative;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.status-dot {
|
||||
position: absolute;
|
||||
left: -2rem;
|
||||
top: 0;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 50%;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.roadmap-item.done .status-dot {
|
||||
background-color: rgb(16, 185, 129);
|
||||
}
|
||||
|
||||
.roadmap-item.progress .status-dot {
|
||||
background-color: rgb(245, 158, 11);
|
||||
}
|
||||
|
||||
.roadmap-item.planned .status-dot {
|
||||
background-color: rgb(99, 102, 241);
|
||||
}
|
||||
|
||||
.item-content {
|
||||
background-color: var(--vp-c-bg-soft);
|
||||
border-radius: 8px;
|
||||
padding: 1.5rem;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
}
|
||||
|
||||
.item-content h4 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.roadmap-item.done h4 {
|
||||
color: rgb(16, 185, 129);
|
||||
}
|
||||
|
||||
.roadmap-item.progress h4 {
|
||||
color: rgb(245, 158, 11);
|
||||
}
|
||||
|
||||
.roadmap-item.planned h4 {
|
||||
color: rgb(99, 102, 241);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.feature-highlight,
|
||||
.feature-highlight.reverse {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.highlight-image {
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.project-header {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.project-logo {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
}
|
||||
</style>
|
After Width: | Height: | Size: 24 KiB |
475
py-xiaozhi-main/documents/docs/ecosystem/projects/xiaozhi-esp32-server/index.md
Executable file
@ -0,0 +1,475 @@
|
||||
---
|
||||
title: xiaozhi-esp32-server
|
||||
description: 基于ESP32的小智开源服务端,轻量级且高效的语音交互服务
|
||||
---
|
||||
|
||||
# xiaozhi-esp32-server
|
||||
|
||||
<div class="project-header">
|
||||
<div class="project-logo">
|
||||
<img src="./images/logo.png" alt="xiaozhi-esp32-server Logo" onerror="this.src='/py-xiaozhi/images/logo.png'; this.onerror=null;">
|
||||
</div>
|
||||
<div class="project-badges">
|
||||
<span class="badge platform">ESP32</span>
|
||||
<span class="badge language">Python</span>
|
||||
<span class="badge status">活跃开发中</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="project-intro">
|
||||
<p>xiaozhi-esp32-server是为开源智能硬件项目<a href="https://github.com/78/xiaozhi-esp32" target="_blank">xiaozhi-esp32</a>提供的后端服务,根据<a href="https://ccnphfhqs21z.feishu.cn/wiki/M0XiwldO9iJwHikpXD5cEx71nKh" target="_blank">小智通信协议</a>使用Python实现,帮助您快速搭建小智服务器。</p>
|
||||
</div>
|
||||
|
||||
## 适用人群
|
||||
|
||||
本项目需要配合ESP32硬件设备使用。如果您已经购买了ESP32相关硬件,且成功对接过虾哥部署的后端服务,并希望独立搭建自己的`xiaozhi-esp32`后端服务,那么本项目非常适合您。
|
||||
|
||||
<div class="warning-box">
|
||||
<h3>⚠️ 重要提示</h3>
|
||||
<ol>
|
||||
<li>本项目为开源软件,与对接的任何第三方API服务商(包括但不限于语音识别、大模型、语音合成等平台)均不存在商业合作关系,不为其服务质量及资金安全提供任何形式的担保。建议使用者优先选择持有相关业务牌照的服务商,并仔细阅读其服务协议及隐私政策。本软件不托管任何账户密钥、不参与资金流转、不承担充值资金损失风险。</li>
|
||||
<li>本项目成立时间较短,还未通过网络安全测评,请勿在生产环境中使用。如果您在公网环境中部署学习本项目,请务必在配置文件<code>config.yaml</code>中开启防护。</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
## 核心特性
|
||||
|
||||
<div class="features-container">
|
||||
<div class="feature-item">
|
||||
<div class="feature-icon">🔄</div>
|
||||
<h3>通信协议</h3>
|
||||
<p>基于<code>xiaozhi-esp32</code>协议,通过WebSocket实现数据交互</p>
|
||||
</div>
|
||||
|
||||
<div class="feature-item">
|
||||
<div class="feature-icon">💬</div>
|
||||
<h3>对话交互</h3>
|
||||
<p>支持唤醒对话、手动对话及实时打断,长时间无对话时自动休眠</p>
|
||||
</div>
|
||||
|
||||
<div class="feature-item">
|
||||
<div class="feature-icon">🧠</div>
|
||||
<h3>意图识别</h3>
|
||||
<p>支持使用LLM意图识别、function call函数调用,减少硬编码意图判断</p>
|
||||
</div>
|
||||
|
||||
<div class="feature-item">
|
||||
<div class="feature-icon">🌐</div>
|
||||
<h3>多语言识别</h3>
|
||||
<p>支持国语、粤语、英语、日语、韩语(默认使用FunASR)</p>
|
||||
</div>
|
||||
|
||||
<div class="feature-item">
|
||||
<div class="feature-icon">🤖</div>
|
||||
<h3>LLM模块</h3>
|
||||
<p>支持灵活切换LLM模块,默认使用ChatGLMLLM,也可选用阿里百炼、DeepSeek、Ollama等</p>
|
||||
</div>
|
||||
|
||||
<div class="feature-item">
|
||||
<div class="feature-icon">🔊</div>
|
||||
<h3>TTS模块</h3>
|
||||
<p>支持EdgeTTS(默认)、火山引擎豆包TTS等多种TTS接口,满足语音合成需求</p>
|
||||
</div>
|
||||
|
||||
<div class="feature-item">
|
||||
<div class="feature-icon">📝</div>
|
||||
<h3>记忆功能</h3>
|
||||
<p>支持超长记忆、本地总结记忆、无记忆三种模式,满足不同场景需求</p>
|
||||
</div>
|
||||
|
||||
<div class="feature-item">
|
||||
<div class="feature-icon">🏠</div>
|
||||
<h3>IOT功能</h3>
|
||||
<p>支持管理注册设备IOT功能,支持基于对话上下文语境下的智能物联网控制</p>
|
||||
</div>
|
||||
|
||||
<div class="feature-item">
|
||||
<div class="feature-icon">🖥️</div>
|
||||
<h3>智控台</h3>
|
||||
<p>提供Web管理界面,支持智能体管理、用户管理、系统配置等功能</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
## 部署方式
|
||||
|
||||
本项目提供两种部署方式,请根据您的具体需求选择:
|
||||
|
||||
<div class="deployment-table">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>部署方式</th>
|
||||
<th>特点</th>
|
||||
<th>适用场景</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><strong>最简化安装</strong></td>
|
||||
<td>智能对话、IOT功能,数据存储在配置文件</td>
|
||||
<td>低配置环境,无需数据库</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>全模块安装</strong></td>
|
||||
<td>智能对话、IOT、OTA、智控台,数据存储在数据库</td>
|
||||
<td>完整功能体验</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
详细部署文档请参考:
|
||||
- [Docker部署文档](https://github.com/xinnan-tech/xiaozhi-esp32-server/blob/main/docs/Deployment.md)
|
||||
- [源码部署文档](https://github.com/xinnan-tech/xiaozhi-esp32-server/blob/main/docs/Deployment_all.md)
|
||||
|
||||
## 支持平台列表
|
||||
|
||||
xiaozhi-esp32-server支持丰富的第三方平台和组件:
|
||||
|
||||
### LLM 语言模型
|
||||
|
||||
<div class="platform-item">
|
||||
<h4>接口调用</h4>
|
||||
<p><strong>支持平台:</strong>阿里百炼、火山引擎豆包、深度求索、智谱ChatGLM、Gemini、Ollama、Dify、Fastgpt、Coze</p>
|
||||
<p><strong>免费平台:</strong>智谱ChatGLM、Gemini</p>
|
||||
<p><em>实际上,任何支持openai接口调用的LLM均可接入使用</em></p>
|
||||
</div>
|
||||
|
||||
### TTS 语音合成
|
||||
|
||||
<div class="platform-item">
|
||||
<h4>接口调用</h4>
|
||||
<p><strong>支持平台:</strong>EdgeTTS、火山引擎豆包TTS、腾讯云、阿里云TTS、CosyVoiceSiliconflow、TTS302AI、CozeCnTTS、GizwitsTTS、ACGNTTS、OpenAITTS</p>
|
||||
<p><strong>免费平台:</strong>EdgeTTS、CosyVoiceSiliconflow(部分)</p>
|
||||
|
||||
<h4>本地服务</h4>
|
||||
<p><strong>支持平台:</strong>FishSpeech、GPT_SOVITS_V2、GPT_SOVITS_V3、MinimaxTTS</p>
|
||||
<p><strong>免费平台:</strong>FishSpeech、GPT_SOVITS_V2、GPT_SOVITS_V3、MinimaxTTS</p>
|
||||
</div>
|
||||
|
||||
### ASR 语音识别
|
||||
|
||||
<div class="platform-item">
|
||||
<h4>接口调用</h4>
|
||||
<p><strong>支持平台:</strong>DoubaoASR</p>
|
||||
|
||||
<h4>本地服务</h4>
|
||||
<p><strong>支持平台:</strong>FunASR、SherpaASR</p>
|
||||
<p><strong>免费平台:</strong>FunASR、SherpaASR</p>
|
||||
</div>
|
||||
|
||||
### 更多组件
|
||||
|
||||
- **VAD语音活动检测**:支持SileroVAD(本地免费使用)
|
||||
- **记忆存储**:支持mem0ai(1000次/月额度)、mem_local_short(本地总结,免费)
|
||||
- **意图识别**:支持intent_llm(通过大模型识别意图)、function_call(通过大模型函数调用完成意图)
|
||||
|
||||
## 参与贡献
|
||||
|
||||
xiaozhi-esp32-server是一个活跃的开源项目,欢迎贡献代码或提交问题反馈:
|
||||
|
||||
- [GitHub仓库](https://github.com/xinnan-tech/xiaozhi-esp32-server)
|
||||
- [问题反馈](https://github.com/xinnan-tech/xiaozhi-esp32-server/issues)
|
||||
- [致开发者的公开信](https://github.com/xinnan-tech/xiaozhi-esp32-server/blob/main/docs/contributor_open_letter.md)
|
||||
|
||||
<style>
|
||||
.project-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.project-logo {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
margin-right: 1.5rem;
|
||||
}
|
||||
|
||||
.project-logo img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.project-badges {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.badge {
|
||||
display: inline-block;
|
||||
padding: 0.25rem 0.75rem;
|
||||
border-radius: 1rem;
|
||||
font-size: 0.85rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.badge.platform {
|
||||
background-color: var(--vp-c-brand-soft);
|
||||
color: var(--vp-c-brand-dark);
|
||||
}
|
||||
|
||||
.badge.language {
|
||||
background-color: rgba(59, 130, 246, 0.2);
|
||||
color: rgb(59, 130, 246);
|
||||
}
|
||||
|
||||
.badge.status {
|
||||
background-color: rgba(16, 185, 129, 0.2);
|
||||
color: rgb(16, 185, 129);
|
||||
}
|
||||
|
||||
.project-intro {
|
||||
font-size: 1.1rem;
|
||||
line-height: 1.6;
|
||||
margin-bottom: 2rem;
|
||||
padding: 1.5rem;
|
||||
background-color: var(--vp-c-bg-soft);
|
||||
border-radius: 8px;
|
||||
border-left: 4px solid var(--vp-c-brand);
|
||||
}
|
||||
|
||||
.warning-box {
|
||||
margin: 2rem 0;
|
||||
padding: 1.5rem;
|
||||
background-color: rgba(234, 179, 8, 0.1);
|
||||
border-left: 4px solid rgba(234, 179, 8, 0.8);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.warning-box h3 {
|
||||
color: rgb(234, 179, 8);
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.features-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
||||
gap: 1.5rem;
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
.feature-item {
|
||||
background-color: var(--vp-c-bg-soft);
|
||||
border-radius: 8px;
|
||||
padding: 1.5rem;
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
}
|
||||
|
||||
.feature-item:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.feature-icon {
|
||||
font-size: 2rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.feature-item h3 {
|
||||
color: var(--vp-c-brand);
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.deployment-table {
|
||||
margin: 2rem 0;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.deployment-table table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.deployment-table th,
|
||||
.deployment-table td {
|
||||
padding: 1rem;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid var(--vp-c-divider);
|
||||
}
|
||||
|
||||
.deployment-table th {
|
||||
background-color: var(--vp-c-bg-soft);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.platform-item {
|
||||
margin: 1.5rem 0;
|
||||
padding: 1.5rem;
|
||||
background-color: var(--vp-c-bg-soft);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.platform-item h4 {
|
||||
color: var(--vp-c-brand);
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.platform-item p {
|
||||
margin: 0.5rem 0;
|
||||
}
|
||||
|
||||
.demo-videos {
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
.video-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.video-item {
|
||||
display: block;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
transition: transform 0.3s ease;
|
||||
background-color: var(--vp-c-bg-soft);
|
||||
}
|
||||
|
||||
.video-item:hover {
|
||||
transform: translateY(-5px);
|
||||
}
|
||||
|
||||
.video-thumbnail {
|
||||
width: 100%;
|
||||
aspect-ratio: 16 / 9;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.video-thumbnail img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.video-item:hover .video-thumbnail img {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.video-title {
|
||||
padding: 1rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.demo-more {
|
||||
text-align: center;
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
|
||||
.demo-more a {
|
||||
display: inline-block;
|
||||
padding: 0.5rem 1.5rem;
|
||||
background-color: var(--vp-c-brand);
|
||||
color: white;
|
||||
border-radius: 4px;
|
||||
text-decoration: none;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
.demo-more a:hover {
|
||||
background-color: var(--vp-c-brand-dark);
|
||||
}
|
||||
|
||||
.related-projects {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
||||
gap: 1.5rem;
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
.project-card {
|
||||
background-color: var(--vp-c-bg-soft);
|
||||
border-radius: 8px;
|
||||
padding: 1.5rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
.project-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.project-card h3 {
|
||||
color: var(--vp-c-brand);
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.project-link {
|
||||
margin-top: auto;
|
||||
display: inline-block;
|
||||
padding: 0.5rem 1rem;
|
||||
background-color: var(--vp-c-brand);
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
.project-link:hover {
|
||||
background-color: var(--vp-c-brand-dark);
|
||||
}
|
||||
|
||||
.contributors {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
||||
gap: 2rem;
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
.contributor {
|
||||
background-color: var(--vp-c-bg-soft);
|
||||
border-radius: 8px;
|
||||
padding: 1.5rem;
|
||||
text-align: center;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
}
|
||||
|
||||
.contributor img {
|
||||
width: 120px;
|
||||
height: 60px;
|
||||
object-fit: contain;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.contributor h4 {
|
||||
color: var(--vp-c-brand);
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.project-header {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.project-logo {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.contributors {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.related-projects {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.features-container {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
BIN
py-xiaozhi-main/documents/docs/ecosystem/projects/xiaozhi-unity/images/logo.png
Executable file
After Width: | Height: | Size: 549 KiB |
BIN
py-xiaozhi-main/documents/docs/ecosystem/projects/xiaozhi-unity/images/界面1.png
Executable file
After Width: | Height: | Size: 2.0 MiB |
BIN
py-xiaozhi-main/documents/docs/ecosystem/projects/xiaozhi-unity/images/界面2.png
Executable file
After Width: | Height: | Size: 2.3 MiB |
504
py-xiaozhi-main/documents/docs/ecosystem/projects/xiaozhi-unity/index.md
Executable file
@ -0,0 +1,504 @@
|
||||
---
|
||||
title: XiaoZhiAI_server32_Unity
|
||||
description: 基于Unity的小智AI视觉交互服务,实现语音与Live2D多模态人机交互体验
|
||||
---
|
||||
|
||||
# XiaoZhiAI_server32_Unity
|
||||
|
||||
<div class="project-header">
|
||||
<div class="project-logo">
|
||||
<img src="./images/logo.png" alt="Unity Logo">
|
||||
</div>
|
||||
<div class="project-badges">
|
||||
<span class="badge platform">跨平台</span>
|
||||
<span class="badge language">C#/Unity</span>
|
||||
<span class="badge status">活跃开发中</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
## 项目简介
|
||||
|
||||
XiaoZhiAI_server32_Unity是一个基于Unity开发的AI应用程序,专注于提供高质量的语音交互和网络服务功能。本项目利用Unity的跨平台特性,支持多种设备和操作系统,包括PC、Android、iOS、WebGL和微信小程序,为用户提供流畅的AI语音与Live2D交互体验。
|
||||
|
||||
## 技术架构
|
||||
|
||||
XiaoZhiAI_server32_Unity基于以下技术栈构建:
|
||||
|
||||
- **开发引擎**:Unity 2020.3或更高版本
|
||||
- **目标平台**:PC、Android、iOS、WebGL、微信小程序
|
||||
- **核心功能模块**:
|
||||
- **语音交互系统**:实时语音识别、自然语言处理、语音合成
|
||||
- **Live2D交互**:服务端返回LLM表情交互Live2D
|
||||
- **Mqtt硬件交互**:服务端functioncall处理IoT返回
|
||||
|
||||
- **依赖包**:
|
||||
- OPUS解码SDK
|
||||
- WebSocket网络通信库
|
||||
- YooAsset资源管理框架2.3.7版本
|
||||
- YuikFrameWork (YOO分支)
|
||||
- Hycrl热更新框架
|
||||
|
||||
|
||||
## 核心功能
|
||||
|
||||
### 语音交互能力
|
||||
|
||||
<div class="features-grid">
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">🎤</div>
|
||||
<h3>实时语音识别</h3>
|
||||
<p>支持多种语言的实时语音转文字,准确率高达95%以上</p>
|
||||
</div>
|
||||
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">🧠</div>
|
||||
<h3>自然语言理解</h3>
|
||||
<p>基于深度学习的语义分析,精准理解用户意图</p>
|
||||
</div>
|
||||
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">🔊</div>
|
||||
<h3>语音合成</h3>
|
||||
<p>自然流畅的语音输出,支持多种音色和语速调节</p>
|
||||
</div>
|
||||
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">🤖</div>
|
||||
<h3>Live2D表情交互</h3>
|
||||
<p>根据LLM返回结果实现实时表情变化和情感表达</p>
|
||||
</div>
|
||||
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">📱</div>
|
||||
<h3>IoT与Mqtt对接</h3>
|
||||
<p>通过functioncall实现智能家居设备控制和状态反馈</p>
|
||||
</div>
|
||||
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">🔄</div>
|
||||
<h3>热更新支持</h3>
|
||||
<p>基于Hycrl框架的热更新能力,无需重装即可升级</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
## 环境要求
|
||||
|
||||
### 开发环境
|
||||
- Unity版本:2020.3或更高
|
||||
- 操作系统:Windows 10/11(开发环境)
|
||||
|
||||
### 运行环境
|
||||
- **PC平台**:
|
||||
- 操作系统:Windows 10/11、macOS 10.14+
|
||||
- 处理器:Intel i5或同等性能
|
||||
- 内存:8GB以上
|
||||
- 显卡:支持DirectX 11
|
||||
|
||||
- **移动平台**:
|
||||
- Android 6.0+
|
||||
- iOS 11.0+
|
||||
|
||||
- **Web平台**:
|
||||
- 支持WebGL 2.0的现代浏览器
|
||||
|
||||
- **硬件要求**:
|
||||
- 麦克风:支持16kHz采样率的高质量麦克风(语音交互)
|
||||
- 网络:稳定的网络连接,建议5Mbps以上带宽
|
||||
|
||||
## 项目结构
|
||||
|
||||
```
|
||||
XiaoZhiAI_server32_Unity/
|
||||
├── Assets/ # Unity资源文件
|
||||
│ ├── Scenes/ # 场景文件
|
||||
│ ├── Scripts/ # 脚本文件
|
||||
│ │ ├── VoiceInteraction/ # 语音交互相关脚本
|
||||
│ │ ├── Networking/ # 网络通信相关脚本
|
||||
│ │ └── ...
|
||||
│ ├── Prefabs/ # 预制体
|
||||
│ ├── Plugins/ # 第三方插件
|
||||
│ │ ├── VoiceSDK/ # 语音识别SDK
|
||||
│ │ └── NetworkLibs/ # 网络库
|
||||
│ └── ...
|
||||
├── Packages/ # 项目依赖包
|
||||
├── ProjectSettings/ # Unity项目设置
|
||||
└── README.md # 项目说明文档
|
||||
```
|
||||
|
||||
## 安装指南
|
||||
|
||||
### 开发者安装
|
||||
|
||||
1. 克隆仓库到本地:
|
||||
```bash
|
||||
git clone https://gitee.com/vw112266/XiaoZhiAI_server32_Unity.git
|
||||
```
|
||||
|
||||
2. 安装依赖包:
|
||||
- 手动引入YooAsset资源管理框架(v2.3.7):https://github.com/tuyoogame/YooAsset
|
||||
- 手动引入YuikFrameWork-YOO分支:https://gitee.com/NikaidoShinku/YukiFrameWork
|
||||
|
||||
3. 使用Unity Hub打开项目,并确保Unity版本兼容
|
||||
|
||||
### 用户安装
|
||||
|
||||
1. 从发布页下载对应平台的安装包
|
||||
2. 按照向导完成安装
|
||||
3. 启动应用并完成初始配置
|
||||
|
||||
## 功能特性展示
|
||||
|
||||
### Live2D交互
|
||||
|
||||
<div class="feature-highlight">
|
||||
<div class="highlight-content">
|
||||
<h3>表情丰富的Live2D模型</h3>
|
||||
<ul>
|
||||
<li>根据对话内容实时改变表情</li>
|
||||
<li>支持多种情感状态表达</li>
|
||||
<li>精准的口型同步</li>
|
||||
<li>自然的眨眼和头部动作</li>
|
||||
<li>可定制的角色形象</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="highlight-image">
|
||||
<img src="./images/界面1.png" alt="演示界面" >
|
||||
</div>
|
||||
</div>
|
||||
|
||||
### IoT智能控制
|
||||
|
||||
<div class="feature-highlight reverse">
|
||||
<div class="highlight-content">
|
||||
<h3>家居设备智能控制</h3>
|
||||
<ul>
|
||||
<li>通过语音控制智能家居设备</li>
|
||||
<li>基于functioncall的智能意图识别</li>
|
||||
<li>支持多种MQTT协议设备</li>
|
||||
<li>设备状态实时反馈</li>
|
||||
<li>场景联动与自动化</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="highlight-image">
|
||||
<img src="./images/界面2.png" alt="演示界面">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
## 开发计划
|
||||
|
||||
<div class="roadmap">
|
||||
<div class="roadmap-item done">
|
||||
<div class="status-dot"></div>
|
||||
<div class="item-content">
|
||||
<h4>已完成功能</h4>
|
||||
<ul>
|
||||
<li>基础语音交互系统</li>
|
||||
<li>Live2D模型集成</li>
|
||||
<li>WebSocket网络通信</li>
|
||||
<li>基础MQTT支持</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="roadmap-item progress">
|
||||
<div class="status-dot"></div>
|
||||
<div class="item-content">
|
||||
<h4>开发中功能</h4>
|
||||
<ul>
|
||||
<li>更多Live2D模型支持</li>
|
||||
<li>表情系统优化</li>
|
||||
<li>移动平台性能优化</li>
|
||||
<li>更多IoT设备支持</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="roadmap-item planned">
|
||||
<div class="status-dot"></div>
|
||||
<div class="item-content">
|
||||
<h4>计划功能</h4>
|
||||
<ul>
|
||||
<li>微信小程序集成</li>
|
||||
<li>AR互动体验</li>
|
||||
<li>多角色场景支持</li>
|
||||
<li>用户自定义模型系统</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
## 贡献指南
|
||||
|
||||
我们欢迎社区开发者参与XiaoZhiAI_server32_Unity项目的开发:
|
||||
|
||||
- 提交bug报告和功能建议
|
||||
- 贡献代码改进和新功能
|
||||
- 创建和分享Live2D模型
|
||||
- 优化性能和用户体验
|
||||
- 完善文档和教程
|
||||
|
||||
请参考我们的贡献指南,了解如何参与项目开发。
|
||||
|
||||
## 相关链接
|
||||
|
||||
- [项目仓库](https://gitee.com/vw112266/XiaoZhiAI_server32_Unity)
|
||||
|
||||
<style>
|
||||
.project-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.project-logo {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
margin-right: 1.5rem;
|
||||
}
|
||||
|
||||
.project-logo img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.project-badges {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.badge {
|
||||
display: inline-block;
|
||||
padding: 0.25rem 0.75rem;
|
||||
border-radius: 1rem;
|
||||
font-size: 0.85rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.badge.platform {
|
||||
background-color: var(--vp-c-brand-soft);
|
||||
color: var(--vp-c-brand-dark);
|
||||
}
|
||||
|
||||
.badge.language {
|
||||
background-color: rgba(59, 130, 246, 0.2);
|
||||
color: rgb(59, 130, 246);
|
||||
}
|
||||
|
||||
.badge.status {
|
||||
background-color: rgba(16, 185, 129, 0.2);
|
||||
color: rgb(16, 185, 129);
|
||||
}
|
||||
|
||||
.project-images {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
margin: 2rem 0;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.image-container {
|
||||
flex: 1;
|
||||
min-width: 300px;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
}
|
||||
|
||||
.image-container img {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.architecture-diagram {
|
||||
margin: 2rem 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.diagram-container {
|
||||
max-width: 100%;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
}
|
||||
|
||||
.diagram-container img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.features-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
||||
gap: 1.5rem;
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
.feature-card {
|
||||
background-color: var(--vp-c-bg-soft);
|
||||
border-radius: 8px;
|
||||
padding: 1.5rem;
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.feature-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.feature-icon {
|
||||
font-size: 2rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.feature-card h3 {
|
||||
color: var(--vp-c-brand);
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.feature-highlight {
|
||||
display: flex;
|
||||
margin: 3rem 0;
|
||||
background-color: var(--vp-c-bg-soft);
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
}
|
||||
|
||||
.feature-highlight.reverse {
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
.highlight-image {
|
||||
flex: 1;
|
||||
min-width: 40%;
|
||||
}
|
||||
|
||||
.highlight-image img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.highlight-content {
|
||||
flex: 1;
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
.highlight-content h3 {
|
||||
color: var(--vp-c-brand);
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.highlight-content ul {
|
||||
padding-left: 1.5rem;
|
||||
}
|
||||
|
||||
.highlight-content li {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.roadmap {
|
||||
position: relative;
|
||||
margin: 3rem 0;
|
||||
padding-left: 2rem;
|
||||
}
|
||||
|
||||
.roadmap:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 7px;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 2px;
|
||||
background-color: var(--vp-c-divider);
|
||||
}
|
||||
|
||||
.roadmap-item {
|
||||
position: relative;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.status-dot {
|
||||
position: absolute;
|
||||
left: -2rem;
|
||||
top: 0;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 50%;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.roadmap-item.done .status-dot {
|
||||
background-color: rgb(16, 185, 129);
|
||||
}
|
||||
|
||||
.roadmap-item.progress .status-dot {
|
||||
background-color: rgb(245, 158, 11);
|
||||
}
|
||||
|
||||
.roadmap-item.planned .status-dot {
|
||||
background-color: rgb(99, 102, 241);
|
||||
}
|
||||
|
||||
.item-content {
|
||||
background-color: var(--vp-c-bg-soft);
|
||||
border-radius: 8px;
|
||||
padding: 1.5rem;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
}
|
||||
|
||||
.item-content h4 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.roadmap-item.done h4 {
|
||||
color: rgb(16, 185, 129);
|
||||
}
|
||||
|
||||
.roadmap-item.progress h4 {
|
||||
color: rgb(245, 158, 11);
|
||||
}
|
||||
|
||||
.roadmap-item.planned h4 {
|
||||
color: rgb(99, 102, 241);
|
||||
}
|
||||
|
||||
pre {
|
||||
background-color: var(--vp-c-bg-soft);
|
||||
border-radius: 8px;
|
||||
padding: 1.5rem;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.feature-highlight,
|
||||
.feature-highlight.reverse {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.highlight-image {
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.project-header {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.project-logo {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.project-images {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
</style>
|
47
py-xiaozhi-main/documents/docs/guide/00_文档目录.md
Executable file
@ -0,0 +1,47 @@
|
||||
# py-xiaozhi文档目录
|
||||
|
||||
本目录包含了 py-xiaozhi 项目 的全部功能文档,按功能模块进行划分,便于查阅和使用。
|
||||
|
||||
项目默认启用了以下模块:音乐、灯光、音量、定时器、Home asssistant控制器、相机 IoT 控制。
|
||||
其他模块可根据需求自行扩展与启用。
|
||||
视觉识别功能 需配置 智普大模型的 API Key 才可使用。
|
||||
当前项目已经启用v2授权协议,wss链接通过ota接口返回、无论是官方小智和开源后端已经对齐认证流程
|
||||
|
||||
## 基础文档
|
||||
|
||||
- [01_系统依赖安装](01_系统依赖安装) - 各平台的系统依赖和Python环境配置
|
||||
- [02_配置说明](02_配置说明.md) - 配置文件结构、配置项说明和修改指南
|
||||
- [03_语音交互模式说明](03_语音交互模式说明) - 项目概述、基本使用说明和运行模式
|
||||
- [04_语音唤醒](04_语音唤醒.md) - 语音唤醒功能的配置和使用说明
|
||||
- [05_IoT功能说明](05_IoT功能说明.md) - 物联网功能架构、设备控制和扩展方法
|
||||
- [06_音量控制功能](06_音量控制功能.md) - 系统音量控制功能的使用和配置
|
||||
- [07_视觉识别功能](07_视觉识别功能.md) - 摄像头控制和视觉分析功能
|
||||
- [08_设备激活流程](08_设备激活流程) - 设备激活和注册流程说明
|
||||
- [09_打包教程](09_打包教程.md) - 使用UnifyPy打包小智客户端的详细教程
|
||||
|
||||
## 其他文档
|
||||
|
||||
- [异常汇总](异常汇总.md) - 常见问题和解决方案
|
||||
|
||||
## 旧版文档
|
||||
|
||||
为了便于参考,我们保留了旧版文档:
|
||||
|
||||
- [旧版使用文档](old_docs/使用文档.md) - 较早版本的使用说明文档
|
||||
|
||||
## 参与贡献
|
||||
|
||||
如果您想参与项目开发或提供反馈,请查看以下资源:
|
||||
|
||||
- [贡献指南](/contributing) - 如何为项目贡献代码,包括开发流程、代码规范和PR提交流程
|
||||
- [团队成员](/about/team) - 感谢为项目做出贡献的团队成员
|
||||
- [赞助支持](/sponsors/) - 如何赞助项目发展
|
||||
|
||||
## 相关生态
|
||||
|
||||
- [相关生态](/ecosystem/) - py-xiaozhi项目的相关生态系统和扩展项目
|
||||
|
||||
|
||||
## 版本信息
|
||||
|
||||
文档最后更新时间:2025年5月
|
254
py-xiaozhi-main/documents/docs/guide/01_系统依赖安装.md
Executable file
@ -0,0 +1,254 @@
|
||||
# 系统依赖安装
|
||||
⚠️务必按照教程安装顺序进行软件、工具的安装
|
||||
|
||||
⚠️推荐使用conda环境进行安装,PyQt5、OpenCV可以直接使用conda预编译好的版本。pip在arm64 4GB及其以下设备上PyQt5、OpenCV极其容易编译失败无法安装
|
||||
|
||||
|
||||
## 系统依赖安装
|
||||
### 多媒体处理组件
|
||||
#### 1. **FFmpeg 视频处理工具**
|
||||
|
||||
##### 📦 Windows 安装方式
|
||||
|
||||
* **推荐方式:使用 Scoop 安装**
|
||||
|
||||
```bash
|
||||
scoop install ffmpeg
|
||||
```
|
||||
|
||||
* **手动安装**
|
||||
|
||||
1. 前往 [BtbN/FFmpeg-Builds](https://github.com/BtbN/FFmpeg-Builds/releases) 下载对应版本
|
||||
2. 解压后将 `bin` 目录路径添加至系统环境变量 `PATH`
|
||||
|
||||
##### 🌐 跨平台安装(适用于 Conda 环境)
|
||||
|
||||
```bash
|
||||
conda install -c conda-forge ffmpeg
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 2. **Opus 音频编解码器**
|
||||
|
||||
* 默认情况下,项目已自动引入 `opus.dll`,**通常无需额外安装**
|
||||
|
||||
* 如遇找不到库的问题,Windows 用户可手动复制 `/libs/windows/opus.dll` 到以下任一位置:
|
||||
|
||||
* 应用程序运行目录
|
||||
* `C:\Windows\System32`
|
||||
|
||||
##### Conda 环境安装方式:
|
||||
|
||||
```bash
|
||||
conda install -c conda-forge opus
|
||||
```
|
||||
|
||||
### Linux (Debian/Ubuntu)
|
||||
```bash
|
||||
# 安装系统依赖
|
||||
sudo apt-get update
|
||||
# 必装
|
||||
sudo apt-get install python3-pyaudio portaudio19-dev ffmpeg libopus0 libopus-dev build-essential python3-venv
|
||||
|
||||
# 安装音量控制依赖(以下三选一)
|
||||
# 1. PulseAudio 工具(推荐)
|
||||
sudo apt-get install pulseaudio-utils
|
||||
|
||||
# 2. 或者 ALSA 工具
|
||||
sudo apt-get install alsa-utils
|
||||
|
||||
# 3. 如果需要使用 alsamixer 方式,还需要安装 expect
|
||||
sudo apt-get install alsa-utils expect
|
||||
```
|
||||
|
||||
### macOS
|
||||
```bash
|
||||
# 使用 Homebrew 安装系统依赖
|
||||
brew install portaudio opus python-tk ffmpeg gfortran
|
||||
brew upgrade tcl-tk
|
||||
```
|
||||
|
||||
## Python 依赖安装
|
||||
|
||||
---
|
||||
|
||||
### 方式一:使用 Miniconda(推荐)
|
||||
|
||||
### 1. 下载 Miniconda 安装包(
|
||||
根据你的系统架构或操作系统选择下载命令:
|
||||
|
||||
| 系统 / 架构 | 下载指令 |
|
||||
|:-----------|:---------|
|
||||
| **Linux - x86_64**(PC/服务器常用) | ```bash wget -O Miniconda3-latest-Linux-x86_64.sh https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh ``` |
|
||||
| **Linux - aarch64**(ARM64,比如树莓派、部分服务器) | ```bash wget -O Miniconda3-latest-Linux-aarch64.sh https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-aarch64.sh ``` |
|
||||
| **Linux - ppc64le**(IBM Power服务器) | ```bash wget -O Miniconda3-latest-Linux-ppc64le.sh https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-ppc64le.sh ``` |
|
||||
| **Windows - x86_64**(普通Windows PC) | [点击下载](https://repo.anaconda.com/miniconda/Miniconda3-latest-Windows-x86_64.exe) |
|
||||
| **Windows - arm64**(ARM Windows设备,如Surface Pro X) | [点击下载](https://repo.anaconda.com/miniconda/Miniconda3-latest-Windows-arm64.exe) |
|
||||
| **macOS - x86_64**(Intel芯片Mac) | ```bash wget -O Miniconda3-latest-MacOSX-x86_64.sh https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-x86_64.sh ``` |
|
||||
| **macOS - arm64**(Apple Silicon芯片,如M1/M2/M3) | ```bash wget -O Miniconda3-latest-MacOSX-arm64.sh https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-arm64.sh ``` |
|
||||
|
||||
---
|
||||
|
||||
### 2. 给安装脚本添加执行权限(仅Linux/macOS)
|
||||
|
||||
```bash
|
||||
chmod +x Miniconda3-latest-*.sh
|
||||
```
|
||||
|
||||
### 3. 运行安装程序(仅Linux/macOS)
|
||||
|
||||
```bash
|
||||
./Miniconda3-latest-*.sh
|
||||
```
|
||||
⚡ *注意:Linux/macOS下不需要用`sudo`,用普通用户安装即可。*
|
||||
|
||||
---
|
||||
|
||||
### 4. 安装过程中 (windows请按照网络搜索到的教程来)
|
||||
|
||||
1. 出现许可协议 → 按 `Enter` 键慢慢翻,或按 `q` 直接跳过。
|
||||
2. 输入 `yes` 接受协议。
|
||||
3. 选择安装路径,默认是 `$HOME/miniconda3` → 直接按 `Enter` 确认。
|
||||
4. 是否初始化 Miniconda → 输入 `yes`(推荐)。
|
||||
|
||||
---
|
||||
|
||||
### 5. 配置环境变量(如果未自动配置)
|
||||
|
||||
Linux/macOS 编辑 `.bashrc`:
|
||||
|
||||
```bash
|
||||
nano ~/.bashrc
|
||||
```
|
||||
|
||||
在文件末尾添加:
|
||||
|
||||
```bash
|
||||
export PATH="$HOME/miniconda3/bin:$PATH"
|
||||
```
|
||||
|
||||
保存并退出:
|
||||
- 按 `Ctrl + X`
|
||||
- 按 `Y`
|
||||
- 按 `Enter`
|
||||
|
||||
让配置立即生效:
|
||||
|
||||
```bash
|
||||
source ~/.bashrc
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 6. 检查 conda 安装成功
|
||||
|
||||
```bash
|
||||
conda --version
|
||||
```
|
||||
如果看到版本号,比如 `conda 24.1.2`,就代表安装成功!
|
||||
|
||||
---
|
||||
|
||||
### 7. 初始化conda(可选但推荐)
|
||||
|
||||
```bash
|
||||
conda init
|
||||
bash
|
||||
```
|
||||
|
||||
然后打开新终端,看到 `(base)`,说明环境正常激活。
|
||||
|
||||
---
|
||||
|
||||
### 8. (推荐)关闭开机自动激活 base 环境
|
||||
|
||||
```bash
|
||||
conda config --set auto_activate_base false
|
||||
```
|
||||
|
||||
这样以后打开终端是干净的,需要的时候再手动 `conda activate base`。
|
||||
|
||||
### 一键自动更换当前网络下最快pip软件源
|
||||
|
||||
* **为了更稳定更快速的安装所需依赖包,建议安装**
|
||||
|
||||
[工具地址|chsrc 全平台通用换源工具|GitHub仓库](https://github.com/RubyMetric/chsrc)
|
||||
|
||||
```bash
|
||||
# windows安装(PowerShell管理员权限打开输入下面这句)
|
||||
winget install RubyMetric.chsrc --source winget
|
||||
|
||||
# 个人服务器,加速下载,支持x86_64和arm64架构
|
||||
wget -O- aslant.top/chsrc.sh|sudo bash
|
||||
|
||||
# 更换pip软件源
|
||||
chsrc set pip
|
||||
```
|
||||
|
||||
## 安装项目依赖
|
||||
|
||||
### 1. 创建 Conda 环境
|
||||
```bash
|
||||
conda create -n py-xiaozhi python=3.10 -y
|
||||
```
|
||||
|
||||
### 2. 激活环境
|
||||
```bash
|
||||
conda activate py-xiaozhi
|
||||
```
|
||||
|
||||
### 3. 安装 Python 依赖
|
||||
```bash
|
||||
# Windows/Linux
|
||||
pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple
|
||||
# macOS
|
||||
pip install -r requirements_mac.txt -i https://mirrors.aliyun.com/pypi/simple
|
||||
```
|
||||
|
||||
* 安装其它依赖(**因为pip安装这两个可能会启动不了。需要在conda单独安装**)
|
||||
```bash
|
||||
# 依然在创建的px-xiaozhi虚拟环境中
|
||||
# PyQt5
|
||||
conda install pyqt=5.15.10 -y
|
||||
|
||||
# OpenCV
|
||||
conda install opencv=4.10.0 -y
|
||||
|
||||
# windows电脑需要单独安装这个
|
||||
pip install wmi
|
||||
```
|
||||
|
||||
|
||||
---
|
||||
|
||||
### 方式二:使用 venv (不再推荐)
|
||||
- mac上会提示系统无法验证 SSL 证书的签发机构,也就是说缺少或未安装系统根证书(CA certificates)
|
||||
```bash
|
||||
# 1. 创建虚拟环境
|
||||
python -m venv .venv
|
||||
|
||||
# 2. 激活虚拟环境
|
||||
# Windows
|
||||
.venv\Scripts\activate
|
||||
# Linux/macOS
|
||||
source .venv/bin/activate
|
||||
|
||||
# 3. 安装依赖
|
||||
# Windows/Linux
|
||||
pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple
|
||||
# macOS
|
||||
pip install -r requirements_mac.txt -i https://mirrors.aliyun.com/pypi/simple
|
||||
|
||||
# 由于requirements 去除了这几个默认的需要单独安装
|
||||
pip install PyQt5==5.15.9 opencv-python==4.11.0.86 wmi==1.5.1 -i https://mirrors.aliyun.com/pypi/simple
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
1. 建议使用 Python 3.9.13+ 版本,推荐 3.10 最大版本3.12(不行就降级)
|
||||
2. Windows 用户无需手动安装 opus.dll,项目会自动处理
|
||||
3. 使用 Conda 环境时必须安装 ffmpeg 和 Opus
|
||||
4. 使用 Conda 环境时请勿和esp32-server共用同一个Conda环境,因为服务端websocket依赖版本高于本项目
|
||||
5. 建议使用国内镜像源安装依赖,可以提高下载速度
|
||||
6. macOS 用户需使用专门的 requirements_mac.txt
|
||||
7. 确保系统依赖安装完成后再安装 Python 依赖
|
185
py-xiaozhi-main/documents/docs/guide/02_配置说明.md
Executable file
@ -0,0 +1,185 @@
|
||||
# 配置说明
|
||||
|
||||
## 项目基础配置
|
||||
|
||||
### 配置文件说明
|
||||
项目使用两种配置方式:初始配置模板和运行时配置文件。
|
||||
|
||||
1. **初始配置模板**
|
||||
- 位置:`/src/utils/config_manager.py`
|
||||
- 作用:提供默认配置模板,首次运行时会自动生成配置文件
|
||||
- 使用场景:首次运行或需要重置配置时修改此文件
|
||||
|
||||
2. **运行时配置文件**
|
||||
- 位置:`/config/config.json`
|
||||
- 作用:存储实际运行时的配置信息
|
||||
- 使用场景:日常使用时修改此文件
|
||||
|
||||
3. **设备身份文件**
|
||||
- 位置:`/config/efuse.json`
|
||||
- 作用:存储设备唯一标识信息,包括序列号和激活状态
|
||||
- 使用场景:设备激活流程中自动生成和更新
|
||||
|
||||
### 配置项访问方式
|
||||
配置系统设计为层级结构,使用点分隔的路径访问特定配置项:
|
||||
|
||||
```python
|
||||
# 示例:获取配置值
|
||||
from src.utils.config_manager import ConfigManager
|
||||
config = ConfigManager.get_instance()
|
||||
mqtt_endpoint = config.get_config("SYSTEM_OPTIONS.NETWORK.MQTT_INFO.endpoint")
|
||||
|
||||
# 示例:更新配置值
|
||||
config.update_config("WAKE_WORD_OPTIONS.USE_WAKE_WORD", True)
|
||||
```
|
||||
|
||||
## 网络配置
|
||||
|
||||
网络配置位于`SYSTEM_OPTIONS.NETWORK`下,主要包含以下内容:
|
||||
|
||||
```json
|
||||
"NETWORK": {
|
||||
"OTA_VERSION_URL": "https://api.tenclass.net/xiaozhi/ota/", // OTA更新地址
|
||||
"WEBSOCKET_URL": "ws://192.168.31.232:8000/xiaozhi/v1/", // WebSocket服务器地址
|
||||
"WEBSOCKET_ACCESS_TOKEN": "test-token", // 访问令牌
|
||||
"MQTT_INFO": {
|
||||
"endpoint": "", // MQTT服务器地址
|
||||
"client_id": "", // MQTT客户端ID
|
||||
"username": "", // MQTT用户名
|
||||
"password": "", // MQTT密码
|
||||
"publish_topic": "", // 发布主题
|
||||
"subscribe_topic": "" // 订阅主题
|
||||
},
|
||||
"ACTIVATION_VERSION": "v2", // 激活版本,可选值: v1, v2
|
||||
"AUTHORIZATION_URL": "https://xiaozhi.me/" // 授权URL地址
|
||||
}
|
||||
```
|
||||
|
||||
## 设备激活
|
||||
|
||||
设备首次使用时需要进行激活,激活信息存储在`config/efuse.json`文件中:
|
||||
|
||||
```json
|
||||
{
|
||||
"serial_number": "SN-E3E1F618-902e16dbe116", // 设备序列号
|
||||
"hmac_key": "b5bf012dd518080532f928b70ed958799f34f9224e80dd4128795a70a5baca24", // 密钥
|
||||
"activation_status": false // 激活状态,激活成功后变为true
|
||||
}
|
||||
```
|
||||
|
||||
激活流程由`ACTIVATION_VERSION`配置项控制:
|
||||
- `v1`:简化激活模式
|
||||
- `v2`:完整激活流程,包括验证码确认
|
||||
|
||||
## 唤醒词配置
|
||||
|
||||
语音唤醒相关配置位于`WAKE_WORD_OPTIONS`下:
|
||||
|
||||
```json
|
||||
"WAKE_WORD_OPTIONS": {
|
||||
"USE_WAKE_WORD": false, // 是否启用语音唤醒
|
||||
"MODEL_PATH": "models/vosk-model-small-cn-0.22", // 唤醒模型路径
|
||||
"WAKE_WORDS": [ // 唤醒词列表
|
||||
"小智",
|
||||
"小美"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 摄像头与视觉识别
|
||||
|
||||
摄像头和视觉识别相关配置位于`CAMERA`下:
|
||||
|
||||
```json
|
||||
"CAMERA": {
|
||||
"camera_index": 0, // 摄像头索引
|
||||
"frame_width": 640, // 画面宽度
|
||||
"frame_height": 480, // 画面高度
|
||||
"fps": 30, // 帧率
|
||||
"Loacl_VL_url": "https://open.bigmodel.cn/api/paas/v4/", // 智普API地址
|
||||
"VLapi_key": "你自己的key", // 智普视觉大模型API密钥
|
||||
"models": "glm-4v-plus" // 使用的视觉模型
|
||||
}
|
||||
```
|
||||
|
||||
## IoT设备配置
|
||||
|
||||
### 温度传感器
|
||||
|
||||
温度传感器通过MQTT协议连接,配置位于`TEMPERATURE_SENSOR_MQTT_INFO`下:
|
||||
|
||||
```json
|
||||
"TEMPERATURE_SENSOR_MQTT_INFO": {
|
||||
"endpoint": "你的Mqtt连接地址", // MQTT服务器地址
|
||||
"port": 1883, // MQTT服务器端口
|
||||
"username": "admin", // MQTT用户名
|
||||
"password": "123456", // MQTT密码
|
||||
"publish_topic": "sensors/temperature/command", // 发布主题
|
||||
"subscribe_topic": "sensors/temperature/device_001/state" // 订阅主题
|
||||
}
|
||||
```
|
||||
|
||||
需要注意:
|
||||
- `endpoint`必须是有效的MQTT服务器地址
|
||||
- `port`默认为1883,如使用TLS加密则通常为8883
|
||||
- `publish_topic`用于发送命令到设备
|
||||
- `subscribe_topic`用于接收设备状态
|
||||
|
||||
### Home Assistant集成
|
||||
|
||||
Home Assistant智能家居平台集成配置位于`HOME_ASSISTANT`下:
|
||||
|
||||
```json
|
||||
"HOME_ASSISTANT": {
|
||||
"URL": "http://你的Home Assistant地址:8123", // Home Assistant服务器地址
|
||||
"TOKEN": "长期访问令牌", // 访问令牌
|
||||
"DEVICES": [] // 要集成的设备列表
|
||||
}
|
||||
```
|
||||
|
||||
通过此配置,可以控制添加到Home Assistant中的各类设备,包括:
|
||||
- 灯光设备(HomeAssistantLight)
|
||||
- 开关设备(HomeAssistantSwitch)
|
||||
- 数值设备(HomeAssistantNumber)
|
||||
- 按钮设备(HomeAssistantButton)
|
||||
|
||||
## 配置修改指南
|
||||
|
||||
1. **首次使用配置**
|
||||
- 直接运行程序,系统会自动生成默认配置文件
|
||||
- 如需修改默认值,可编辑 `config_manager.py` 中的 `DEFAULT_CONFIG`
|
||||
|
||||
2. **更换服务器配置**
|
||||
- 打开 `/config/config.json`
|
||||
- 修改 `SYSTEM_OPTIONS.NETWORK.WEBSOCKET_URL` 为新的服务器地址
|
||||
- 示例:
|
||||
```json
|
||||
"SYSTEM_OPTIONS": {
|
||||
"NETWORK": {
|
||||
"WEBSOCKET_URL": "ws://你的服务器地址:端口号/"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
3. **启用语音唤醒**
|
||||
- 修改 `WAKE_WORD_OPTIONS.USE_WAKE_WORD` 为 `true`
|
||||
- 可在 `WAKE_WORD_OPTIONS.WAKE_WORDS` 数组中添加或修改唤醒词
|
||||
|
||||
4. **配置摄像头与视觉识别**
|
||||
- 修改 `CAMERA` 部分的相关配置
|
||||
- 将 `VLapi_key` 设置为你从智普AI平台获取的API密钥
|
||||
- 可以根据需要调整分辨率和帧率
|
||||
|
||||
5. **配置Home Assistant集成**
|
||||
- 在Home Assistant中创建长期访问令牌
|
||||
- 填写 `HOME_ASSISTANT.URL` 和 `HOME_ASSISTANT.TOKEN`
|
||||
- 设备会自动发现并集成
|
||||
|
||||
## 注意事项
|
||||
- 修改配置文件后需要重启程序才能生效
|
||||
- WebSocket URL 必须以 `ws://` 或 `wss://` 开头
|
||||
- 首次运行时会自动生成 CLIENT_ID,建议不要手动修改
|
||||
- DEVICE_ID 默认使用设备MAC地址,可按需修改
|
||||
- 配置文件使用 UTF-8 编码,请使用支持 UTF-8 的编辑器修改
|
||||
- 请妥善保管API密钥和访问令牌等敏感信息
|
||||
- Home Assistant集成需要保证网络可以正常访问到Home Assistant服务器
|
152
py-xiaozhi-main/documents/docs/guide/03_语音交互模式说明.md
Executable file
@ -0,0 +1,152 @@
|
||||
# 语音交互模式说明
|
||||
|
||||

|
||||
|
||||
## 项目概述
|
||||
|
||||
py-xiaozhi是一个智能语音交互助手,支持多种操作模式和功能,包括语音对话、物联网设备控制、视觉识别等功能。本文档主要介绍语音交互的基本使用方法。
|
||||
|
||||
## 语音交互模式
|
||||
|
||||
语音交互支持两种模式,您可以根据实际需求选择合适的交互方式:
|
||||
|
||||
### 1. 长按对话模式
|
||||
|
||||
- **操作方法**:按住说话按钮,松手发送
|
||||
- **适用场景**:短句交流,精确控制对话开始和结束时间
|
||||
- **优点**:避免误触发,控制精确
|
||||
- **快捷键**:Alt+Shift+V(按住说话)
|
||||
|
||||
### 2. 自动对话模式
|
||||
|
||||
- **操作方法**:点击开始对话,系统自动检测语音并发送
|
||||
- **适用场景**:长句交流,无需手动控制
|
||||
- **优点**:解放双手,自然交流
|
||||
- **界面提示**:显示"聆听中"表示系统正在接收您的语音
|
||||
- **快捷键**:Alt+Shift+A(开始自动对话)
|
||||
|
||||
### 模式切换
|
||||
|
||||
- 在GUI界面右下角显示当前模式
|
||||
- 点击按钮可以切换模式
|
||||
- 通过Alt+Shift+M快捷键切换模式
|
||||
- 可以通过配置文件设置默认模式
|
||||
|
||||
## 对话控制
|
||||
|
||||
### 打断功能
|
||||
|
||||
当系统正在语音回复时,您可以随时打断:
|
||||
- **GUI模式**:使用Alt+Shift+X或界面上的打断按钮
|
||||
- **CLI模式**:使用F3键
|
||||
|
||||
## 系统托盘
|
||||
|
||||
GUI模式下支持系统托盘功能:
|
||||
|
||||
- **状态指示**:托盘图标颜色反映当前系统状态
|
||||
- 绿色:已启动/待命状态
|
||||
- 黄色:聆听中状态
|
||||
- 蓝色:说话中状态
|
||||
- 红色:错误状态
|
||||
- 灰色:未连接状态
|
||||
- **最小化**:关闭窗口时自动最小化到系统托盘
|
||||
- **退出**:右键点击托盘图标选择"退出程序"完全退出应用
|
||||
|
||||
### 状态流转
|
||||
|
||||
语音交互系统有以下几种状态:
|
||||
|
||||
```
|
||||
+----------------+
|
||||
| |
|
||||
v |
|
||||
+------+ 唤醒词/按钮 +------------+ | +------------+
|
||||
| IDLE | -----------> | CONNECTING | --+-> | LISTENING |
|
||||
+------+ +------------+ +------------+
|
||||
^ |
|
||||
| | 语音识别完成
|
||||
| +------------+ v
|
||||
+--------- | SPEAKING | <-----------------+
|
||||
完成播放 +------------+
|
||||
```
|
||||
|
||||
- **IDLE**:空闲状态,等待唤醒词或按钮触发
|
||||
- **CONNECTING**:正在连接服务器
|
||||
- **LISTENING**:正在聆听用户语音
|
||||
- **SPEAKING**:系统正在语音回复
|
||||
|
||||
## 快捷键一览
|
||||
|
||||
| 功能 | 快捷键 | 说明 |
|
||||
|------|--------|------|
|
||||
| 按住说话 | Alt+Shift+V | 按住进行录音,松开发送(仅手动模式) |
|
||||
| 自动对话 | Alt+Shift+A | 开始自动对话(自动检测语音并发送) |
|
||||
| 打断对话 | Alt+Shift+X | 打断当前AI正在进行的回复 |
|
||||
| 切换模式 | Alt+Shift+M | 在手动对话/自动对话模式间切换 |
|
||||
|
||||
## 语音命令
|
||||
|
||||
系统支持多种语音命令,以下是常用命令示例:
|
||||
|
||||
### 基础交互
|
||||
- "你好"/"你是谁" - 基础打招呼和身份询问
|
||||
- "谢谢"/"再见" - 礼貌用语
|
||||
|
||||
### 物联网控制
|
||||
- "打开/关闭客厅的灯" - 控制灯光
|
||||
- "播放 菊花台 通过iot音乐播放器播放" - 开始播放音乐
|
||||
|
||||
### 视觉识别
|
||||
- "打开摄像头" - 开启摄像头
|
||||
- "识别画面" - 分析当前画面
|
||||
- "识别到了什么" - ai播放识别的内容
|
||||
- "关闭摄像头" - 关闭摄像头
|
||||
|
||||
## 运行模式
|
||||
|
||||
### GUI 模式运行(默认)
|
||||
```bash
|
||||
python main.py
|
||||
```
|
||||
|
||||
### CLI模式运行
|
||||
```bash
|
||||
python main.py --mode cli
|
||||
```
|
||||
|
||||
### 构建打包
|
||||
|
||||
使用PyInstaller打包为可执行文件:
|
||||
|
||||
```bash
|
||||
# 各平台通用命令
|
||||
python scripts/build.py
|
||||
```
|
||||
|
||||
## 平台兼容性说明
|
||||
|
||||
- **Windows**: 完全支持所有功能
|
||||
- **macOS**:
|
||||
- 系统托盘显示在顶部状态栏,而非任务栏
|
||||
- 快捷键使用可能需要系统权限授权
|
||||
- **Linux**:
|
||||
- 系统托盘支持可能因桌面环境(GNOME/KDE/Xfce等)有所不同
|
||||
- 部分发行版可能需要安装额外的系统托盘支持包
|
||||
|
||||
## 最佳实践
|
||||
|
||||
1. **清晰发音**:确保在安静环境中清晰发音
|
||||
2. **适当停顿**:句子间适当停顿有助于系统识别
|
||||
3. **使用唤醒词**:开启唤醒词功能,可以避免误触发
|
||||
4. **查看反馈**:注意界面状态提示,了解系统当前状态
|
||||
5. **简洁命令**:使用简洁明了的命令获得更好的识别效果
|
||||
|
||||
## 获取帮助
|
||||
|
||||
如果遇到问题:
|
||||
|
||||
1. 优先查看 docs/异常汇总.md 文档
|
||||
2. 通过 GitHub Issues 提交问题
|
||||
3. 通过 AI 助手寻求帮助
|
||||
4. 联系作者(主页有微信)(请自备 Todesk 链接并说明来意,作者工作日晚上处理)
|
47
py-xiaozhi-main/documents/docs/guide/04_语音唤醒.md
Executable file
@ -0,0 +1,47 @@
|
||||
# 语音唤醒功能
|
||||
|
||||
## 唤醒词模型
|
||||
|
||||
使用语音唤醒功能需要下载和配置唤醒词模型:
|
||||
|
||||
- [唤醒词模型下载](https://alphacephei.com/vosk/models)
|
||||
- 下载完成后解压放至根目录/models
|
||||
- 默认读取vosk-model-small-cn-0.22小模型
|
||||
- 
|
||||
|
||||
## 启用语音唤醒
|
||||
|
||||
1. 打开配置文件 `/config/config.json`
|
||||
2. 修改 `WAKE_WORD_OPTIONS.USE_WAKE_WORD` 设置为 `true`
|
||||
3. 可以在 `WAKE_WORD_OPTIONS.WAKE_WORDS` 数组中自定义唤醒词
|
||||
4. 确保 `WAKE_WORD_OPTIONS.MODEL_PATH` 设置正确,指向您下载的模型
|
||||
|
||||
示例配置:
|
||||
```json
|
||||
{
|
||||
"WAKE_WORD_OPTIONS": {
|
||||
"USE_WAKE_WORD": true,
|
||||
"MODEL_PATH": "models/vosk-model-small-cn-0.22",
|
||||
"WAKE_WORDS": [
|
||||
"小智",
|
||||
"你好小智",
|
||||
"嘿小智"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 使用方法
|
||||
|
||||
1. 启动程序后,系统会加载唤醒词模型并自动进入唤醒词监听状态
|
||||
2. 说出您设置的唤醒词(如"小智"),系统会自动从IDLE状态切换到LISTENING状态
|
||||
3. 此时可以继续说出您的指令
|
||||
4. 如果您未说出任何指令,系统会在一段时间后自动回到唤醒词监听状态
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. 唤醒词模型加载需要一定时间,请耐心等待
|
||||
2. 唤醒词识别准确度取决于模型质量和环境噪音
|
||||
3. 可以尝试不同大小的模型,小模型速度快但准确度较低
|
||||
4. 考虑使用独特的唤醒词以避免误触发
|
||||
5. 使用唤醒词功能会略微增加系统资源占用
|
649
py-xiaozhi-main/documents/docs/guide/05_IoT功能说明.md
Executable file
@ -0,0 +1,649 @@
|
||||
# IoT功能说明
|
||||
|
||||
## 概述
|
||||
|
||||
py-xiaozhi项目中的IoT(物联网)模块提供了一个灵活、可扩展的设备控制框架,支持通过语音命令控制多种虚拟和物理设备。本文档详细介绍IoT模块的架构、使用方法以及如何扩展自定义设备。
|
||||
如需执行完立马同步状态和播报结果请参考相机模块和温湿度模块
|
||||
|
||||
## 核心架构
|
||||
|
||||
IoT模块采用分层设计,由以下主要组件构成:
|
||||
|
||||
```
|
||||
├── iot # IoT设备相关模块
|
||||
│ ├── things # 具体设备实现目录
|
||||
│ │ ├── lamp.py # 灯设备实现
|
||||
│ │ ├── speaker.py # 音量控制实现
|
||||
│ │ ├── music_player.py # 音乐播放器实现
|
||||
│ │ ├── countdown_timer.py # 倒计时器实现
|
||||
│ │ ├── ha_control.py # Home Assistant设备控制
|
||||
│ │ ├── CameraVL/ # 摄像头与视觉识别集成设备
|
||||
│ │ ├── temperature_sensor.py# 温度传感器实现
|
||||
│ │ └── query_bridge_rag.py # RAG检索桥接设备
|
||||
│ ├── thing.py # IoT设备基类和工具类定义
|
||||
│ │ ├── Thing # IoT设备抽象基类
|
||||
│ │ ├── Property # 设备属性类
|
||||
│ │ ├── Parameter # 设备方法参数类
|
||||
│ │ └── Method # 设备方法类
|
||||
│ └── thing_manager.py # IoT设备管理器
|
||||
│ └── ThingManager # 单例模式实现的设备管理器
|
||||
```
|
||||
|
||||
### 核心类说明
|
||||
|
||||
1. **Thing(设备基类)**:
|
||||
- 所有IoT设备的抽象基类
|
||||
- 提供属性和方法的注册机制
|
||||
- 提供状态和描述的JSON序列化
|
||||
|
||||
2. **Property(属性类)**:
|
||||
- 定义设备的可变状态(如开/关、亮度等)
|
||||
- 支持布尔、数字和字符串三种基本类型
|
||||
- 使用getter回调实时获取设备状态
|
||||
|
||||
3. **Method(方法类)**:
|
||||
- 定义设备可执行的操作(如打开、关闭等)
|
||||
- 支持带参数的方法调用
|
||||
- 通过callback处理具体操作实现
|
||||
|
||||
4. **Parameter(参数类)**:
|
||||
- 定义方法的参数规范
|
||||
- 包含名称、描述、类型和是否必需等信息
|
||||
|
||||
5. **ThingManager(设备管理器)**:
|
||||
- 集中管理所有IoT设备实例
|
||||
- 处理设备注册和命令分发
|
||||
- 提供设备描述和状态查询接口
|
||||
|
||||
## 命令处理流程
|
||||
|
||||
以下是语音命令被处理并执行IoT设备控制的完整流程:
|
||||
|
||||
```
|
||||
+-------------------+
|
||||
| 用户语音指令 |
|
||||
+-------------------+
|
||||
|
|
||||
v
|
||||
+-------------------+
|
||||
| 语音识别 |
|
||||
| (STT) |
|
||||
+-------------------+
|
||||
|
|
||||
v
|
||||
+-------------------+
|
||||
| 语义理解 |
|
||||
| (LLM) |
|
||||
+-------------------+
|
||||
|
|
||||
v
|
||||
+-------------------+
|
||||
| 物联网命令生成 |
|
||||
+-------------------+
|
||||
|
|
||||
v
|
||||
+------------------------------+ | +------------------------------+
|
||||
| WebSocket服务端处理 | | | Application._handle_iot_message()
|
||||
| <--------+-------> |
|
||||
+------------------------------+ +------------------------------+
|
||||
|
|
||||
v
|
||||
+------------------------------+
|
||||
| ThingManager.invoke() |
|
||||
+------------------------------+
|
||||
|
|
||||
+-------------------------+----------+------------+
|
||||
| | |
|
||||
v v v
|
||||
+---------------+-------+ +------------+---------+ +---------+----------+
|
||||
| Lamp | | Speaker | | MusicPlayer |
|
||||
| (控制灯设备) | | (控制系统音量) | | (音乐播放器) |
|
||||
+---------------+-------+ +------------+---------+ +---------+----------+
|
||||
| | |
|
||||
v v v
|
||||
+---------------+-------+ +------------+---------+ +---------+----------+
|
||||
| 执行设备相关操作 | | 执行设备相关操作 | | 执行设备相关操作 |
|
||||
+---------------+-------+ +------------+---------+ +---------+----------+
|
||||
| | |
|
||||
+-------------------------+-----------------------+
|
||||
|
|
||||
v
|
||||
+-----------------------------+
|
||||
| 更新设备状态 |
|
||||
| Application._update_iot_states()
|
||||
+-----------------------------+
|
||||
|
|
||||
v
|
||||
+-----------------------------+
|
||||
| 发送状态更新到服务器 |
|
||||
| send_iot_states() |
|
||||
+-----------------------------+
|
||||
|
|
||||
v
|
||||
+-----------------------------+
|
||||
| 语音或界面反馈结果 |
|
||||
+-----------------------------+
|
||||
```
|
||||
|
||||
## 内置设备说明
|
||||
|
||||
### 1. 灯设备 (Lamp)
|
||||
|
||||
虚拟灯设备,用于演示基本的IoT控制功能。
|
||||
|
||||
**属性**:
|
||||
- `power`:灯的开关状态(布尔值)
|
||||
|
||||
**方法**:
|
||||
- `TurnOn`:打开灯
|
||||
- `TurnOff`:关闭灯
|
||||
|
||||
**语音命令示例**:
|
||||
- "打开灯"
|
||||
- "关闭灯"
|
||||
|
||||
### 2. 系统音量控制 (Speaker)
|
||||
|
||||
控制系统音量的设备,可调整应用程序的音量大小。
|
||||
|
||||
**属性**:
|
||||
- `volume`:当前音量值(0-100)
|
||||
|
||||
**方法**:
|
||||
- `SetVolume`:设置音量级别
|
||||
|
||||
**语音命令示例**:
|
||||
- "把音量调到50%"
|
||||
- "音量调小一点"
|
||||
- "音量调大"
|
||||
|
||||
### 3. 音乐播放器 (MusicPlayer)
|
||||
|
||||
功能丰富的在线音乐播放器,支持歌曲搜索、播放控制和歌词显示。
|
||||
|
||||
**属性**:
|
||||
- `current_song`:当前播放的歌曲
|
||||
- `playing`:播放状态
|
||||
- `total_duration`:歌曲总时长
|
||||
- `current_position`:当前播放位置
|
||||
- `progress`:播放进度
|
||||
|
||||
**方法**:
|
||||
- `Play`:播放指定歌曲
|
||||
- `Pause`:暂停播放
|
||||
- `GetDuration`:获取播放信息
|
||||
|
||||
**语音命令示例**:
|
||||
- "播放音乐周杰伦的稻香,通过iot音乐播放器播放"
|
||||
- "暂停播放"
|
||||
- "播放下一首"
|
||||
|
||||
### 4. 倒计时器 (CountdownTimer)
|
||||
|
||||
一个用于延迟执行命令的倒计时器设备,可以设置定时任务。
|
||||
|
||||
**属性**:
|
||||
- 无可查询属性
|
||||
|
||||
**方法**:
|
||||
- `StartCountdown`:启动一个倒计时,结束后执行指定命令
|
||||
- `command`:要执行的IoT命令(JSON格式字符串)
|
||||
- `delay`:延迟时间(秒),默认为5秒
|
||||
- `CancelCountdown`:取消指定的倒计时
|
||||
- `timer_id`:要取消的计时器ID
|
||||
|
||||
**语音命令示例**:
|
||||
- "设置5秒后打开灯"
|
||||
- "10秒后把音量调到70%"
|
||||
- "取消倒计时3"
|
||||
|
||||
### 5. 温度传感器 (TemperatureSensor)
|
||||
|
||||
通过MQTT协议连接的温湿度传感器设备,可以实时获取环境温湿度数据。
|
||||
|
||||
**属性**:
|
||||
- `temperature`:当前温度(摄氏度)
|
||||
- `humidity`:当前湿度(%)
|
||||
- `last_update_time`:最后更新时间(时间戳)
|
||||
|
||||
**方法**:
|
||||
- 无可调用方法,设备自动通过MQTT接收数据并更新状态
|
||||
|
||||
**特殊功能**:
|
||||
- 当接收到新的温湿度数据时,会自动通过语音播报结果
|
||||
|
||||
**语音命令示例**:
|
||||
- "查询当前室内温度"
|
||||
- "室内湿度是多少"
|
||||
- "温湿度传感器状态"
|
||||
|
||||
### 6. Home Assistant设备控制 (HomeAssistantDevice)
|
||||
|
||||
通过HTTP API连接到Home Assistant智能家居平台,控制各种智能设备。
|
||||
|
||||
#### 6.1 HomeAssistant灯设备 (HomeAssistantLight)
|
||||
|
||||
**属性**:
|
||||
- `state`:灯的状态(on/off)
|
||||
- `brightness`:灯的亮度(0-100)
|
||||
- `last_update`:最后更新时间戳
|
||||
|
||||
**方法**:
|
||||
- `TurnOn`:打开灯
|
||||
- `TurnOff`:关闭灯
|
||||
- `SetBrightness`:设置灯的亮度
|
||||
- `brightness`:亮度值(0-100%)
|
||||
|
||||
**语音命令示例**:
|
||||
- "打开客厅灯"
|
||||
- "把卧室灯亮度调到60%"
|
||||
- "关闭所有灯"
|
||||
|
||||
#### 6.2 HomeAssistant开关 (HomeAssistantSwitch)
|
||||
|
||||
**属性**:
|
||||
- `state`:开关状态(on/off)
|
||||
- `last_update`:最后更新时间戳
|
||||
|
||||
**方法**:
|
||||
- `TurnOn`:打开开关
|
||||
- `TurnOff`:关闭开关
|
||||
|
||||
**语音命令示例**:
|
||||
- "打开电风扇"
|
||||
- "关闭空调"
|
||||
|
||||
#### 6.3 HomeAssistant数值控制器 (HomeAssistantNumber)
|
||||
|
||||
**属性**:
|
||||
- `state`:当前状态(on/off)
|
||||
- `value`:当前数值
|
||||
- `min_value`:最小值
|
||||
- `max_value`:最大值
|
||||
- `last_update`:最后更新时间戳
|
||||
|
||||
**方法**:
|
||||
- `TurnOn`:打开设备
|
||||
- `TurnOff`:关闭设备
|
||||
- `SetValue`:设置数值
|
||||
- `value`:要设置的数值
|
||||
|
||||
**语音命令示例**:
|
||||
- "把空调温度设为26度"
|
||||
- "将风扇转速调到3档"
|
||||
|
||||
#### 6.4 HomeAssistant按钮 (HomeAssistantButton)
|
||||
|
||||
**属性**:
|
||||
- `state`:当前状态(on/off,通常为虚拟状态)
|
||||
- `last_update`:最后更新时间戳
|
||||
|
||||
**方法**:
|
||||
- `TurnOn`:激活按钮(执行Press操作)
|
||||
- `TurnOff`:形式方法,大多数情况下无实际效果
|
||||
- `Press`:按下按钮,触发按钮关联的动作
|
||||
|
||||
**语音命令示例**:
|
||||
- "按下门铃按钮"
|
||||
- "触发紧急模式"
|
||||
- "启动场景播放"
|
||||
|
||||
### 7. 摄像头与视觉识别 (CameraVL)
|
||||
|
||||
集成摄像头控制和视觉识别功能,可以捕获画面并进行智能分析。
|
||||
|
||||
**功能**:
|
||||
- 摄像头开启/关闭
|
||||
- 画面智能识别
|
||||
- 视觉内容分析
|
||||
|
||||
**语音命令示例**:
|
||||
- "打开摄像头"
|
||||
- "识别画面"
|
||||
- "关闭摄像头"
|
||||
|
||||
## 扩展自定义设备
|
||||
|
||||
要添加新的IoT设备,需要遵循以下步骤:
|
||||
|
||||
### 1. 创建设备类
|
||||
|
||||
在`src/iot/things/`目录下创建新的Python文件,定义设备类:
|
||||
|
||||
```python
|
||||
from src.iot.thing import Thing, Parameter, ValueType
|
||||
|
||||
class MyCustomDevice(Thing):
|
||||
"""
|
||||
自定义IoT设备实现示例
|
||||
|
||||
此类演示了如何创建一个符合项目IoT架构的自定义设备,
|
||||
包括属性定义、方法注册以及实际功能实现
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
# 调用父类初始化方法,设置设备名称和描述
|
||||
# 第一个参数是设备ID(全局唯一),第二个参数是对设备的描述文本
|
||||
super().__init__("MyCustomDevice", "自定义设备描述")
|
||||
|
||||
# 设备状态变量定义
|
||||
self.status = False # 定义设备的开关状态,初始为关闭(False)
|
||||
self.parameter_value = 0 # 定义设备的参数值,初始为0
|
||||
self.last_update_time = 0 # 记录最后一次状态更新的时间戳
|
||||
|
||||
# 设备初始化日志
|
||||
print("[IoT设备] 自定义设备初始化完成")
|
||||
|
||||
# =========================
|
||||
# 注册设备属性(状态值)
|
||||
# =========================
|
||||
|
||||
# 注册status属性,使其可被查询
|
||||
# 参数1: 属性名称 - 在JSON中显示的键名
|
||||
# 参数2: 属性描述 - 对此属性的解释说明
|
||||
# 参数3: getter回调函数 - 用于实时获取属性值的lambda函数
|
||||
self.add_property("status", "设备开关状态(True为开启,False为关闭)",
|
||||
lambda: self.status)
|
||||
|
||||
# 注册parameter_value属性
|
||||
self.add_property("parameter_value", "设备参数值(0-100)",
|
||||
lambda: self.parameter_value)
|
||||
|
||||
# 注册last_update_time属性
|
||||
self.add_property("last_update_time", "最后一次状态更新时间",
|
||||
lambda: self.last_update_time)
|
||||
|
||||
# =========================
|
||||
# 注册设备方法(可执行的操作)
|
||||
# =========================
|
||||
|
||||
# 注册TurnOn方法,用于打开设备
|
||||
# 参数1: 方法名称 - 用于API调用的标识符
|
||||
# 参数2: 方法描述 - 对此方法功能的说明
|
||||
# 参数3: 参数列表 - 空列表表示无参数
|
||||
# 参数4: 回调函数 - 执行实际功能的lambda函数,调用内部的_turn_on方法
|
||||
self.add_method(
|
||||
"TurnOn", # 方法名称
|
||||
"打开设备", # 方法描述
|
||||
[], # 无参数
|
||||
lambda params: self._turn_on() # 回调函数,调用内部的_turn_on方法
|
||||
)
|
||||
|
||||
# 注册TurnOff方法,用于关闭设备
|
||||
self.add_method(
|
||||
"TurnOff",
|
||||
"关闭设备",
|
||||
[],
|
||||
lambda params: self._turn_off()
|
||||
)
|
||||
|
||||
# 注册SetParameter方法,用于设置参数值
|
||||
# 此方法需要一个参数value
|
||||
self.add_method(
|
||||
"SetParameter",
|
||||
"设置设备参数值(范围0-100)",
|
||||
# 定义方法所需参数:
|
||||
[
|
||||
# 创建参数对象:
|
||||
# 参数1: 参数名称 - API中的参数键名
|
||||
# 参数2: 参数描述 - 对此参数的说明
|
||||
# 参数3: 参数类型 - 值类型(NUMBER表示数字类型)
|
||||
# 参数4: 是否必需 - True表示此参数必须提供
|
||||
Parameter("value", "参数值(0-100之间的数字)", ValueType.NUMBER, True)
|
||||
],
|
||||
# 回调函数 - 从params字典中提取参数值并传递给_set_parameter方法
|
||||
lambda params: self._set_parameter(params["value"].get_value())
|
||||
)
|
||||
|
||||
# 注册GetStatus方法,用于获取设备状态信息
|
||||
self.add_method(
|
||||
"GetStatus",
|
||||
"获取设备完整状态信息",
|
||||
[], # 无参数
|
||||
lambda params: self._get_status()
|
||||
)
|
||||
|
||||
# =========================
|
||||
# 内部方法实现(实际功能)
|
||||
# =========================
|
||||
|
||||
def _turn_on(self):
|
||||
"""
|
||||
打开设备的内部实现方法
|
||||
|
||||
返回:
|
||||
dict: 包含操作状态和消息的字典
|
||||
"""
|
||||
self.status = True # 修改设备状态为开启
|
||||
self.last_update_time = int(time.time()) # 更新状态变更时间
|
||||
|
||||
# 这里可以添加实际的硬件控制代码,如GPIO操作、串口通信等
|
||||
print(f"[IoT设备] 自定义设备已打开")
|
||||
|
||||
# 返回操作结果,包含状态和消息
|
||||
return {
|
||||
"status": "success", # 操作状态: success或error
|
||||
"message": "设备已打开" # 操作结果消息
|
||||
}
|
||||
|
||||
def _turn_off(self):
|
||||
"""
|
||||
关闭设备的内部实现方法
|
||||
|
||||
返回:
|
||||
dict: 包含操作状态和消息的字典
|
||||
"""
|
||||
self.status = False # 修改设备状态为关闭
|
||||
self.last_update_time = int(time.time()) # 更新状态变更时间
|
||||
|
||||
# 这里可以添加实际的硬件控制代码
|
||||
print(f"[IoT设备] 自定义设备已关闭")
|
||||
|
||||
# 返回操作结果
|
||||
return {
|
||||
"status": "success",
|
||||
"message": "设备已关闭"
|
||||
}
|
||||
|
||||
def _set_parameter(self, value):
|
||||
"""
|
||||
设置设备参数值的内部实现方法
|
||||
|
||||
参数:
|
||||
value (float): 要设置的参数值
|
||||
|
||||
返回:
|
||||
dict: 包含操作状态和消息的字典
|
||||
|
||||
异常:
|
||||
ValueError: 如果参数值超出有效范围
|
||||
"""
|
||||
# 参数值验证
|
||||
if not isinstance(value, (int, float)):
|
||||
return {"status": "error", "message": "参数必须是数字"}
|
||||
|
||||
if not 0 <= value <= 100:
|
||||
return {"status": "error", "message": "参数值必须在0-100之间"}
|
||||
|
||||
# 设置参数值
|
||||
self.parameter_value = value
|
||||
self.last_update_time = int(time.time()) # 更新状态变更时间
|
||||
|
||||
# 这里可以添加实际的参数设置代码
|
||||
print(f"[IoT设备] 自定义设备参数已设置为: {value}")
|
||||
|
||||
# 返回操作结果
|
||||
return {
|
||||
"status": "success",
|
||||
"message": f"参数已设置为 {value}",
|
||||
"value": value
|
||||
}
|
||||
|
||||
def _get_status(self):
|
||||
"""
|
||||
获取设备完整状态的内部实现方法
|
||||
|
||||
返回:
|
||||
dict: 包含设备所有状态信息的字典
|
||||
"""
|
||||
# 返回设备的完整状态信息
|
||||
return {
|
||||
"status": "success",
|
||||
"device_status": {
|
||||
"is_on": self.status,
|
||||
"parameter": self.parameter_value,
|
||||
"last_update": self.last_update_time
|
||||
}
|
||||
}
|
||||
|
||||
### 2. 注册设备
|
||||
|
||||
在程序启动时注册设备到ThingManager:
|
||||
|
||||
```python
|
||||
# 在Application._initialize_iot_devices方法中
|
||||
from src.iot.thing_manager import ThingManager
|
||||
from src.iot.things.my_custom_device import MyCustomDevice
|
||||
from src.utils.logging_config import get_logger
|
||||
|
||||
# 获取日志记录器实例
|
||||
logger = get_logger(__name__)
|
||||
|
||||
def _initialize_iot_devices(self):
|
||||
"""
|
||||
初始化并注册所有IoT设备
|
||||
此方法在应用程序启动时被调用
|
||||
"""
|
||||
# 记录日志:开始初始化IoT设备
|
||||
logger.info("开始初始化IoT设备...")
|
||||
|
||||
# 获取设备管理器单例实例
|
||||
# ThingManager使用单例模式,确保全局只有一个管理器实例
|
||||
thing_manager = ThingManager.get_instance()
|
||||
|
||||
# 创建自定义设备实例
|
||||
my_device = MyCustomDevice()
|
||||
|
||||
# 将设备实例添加到设备管理器
|
||||
# 一旦添加,设备将可以通过API和语音命令访问
|
||||
thing_manager.add_thing(my_device)
|
||||
|
||||
# 记录成功添加设备的日志
|
||||
logger.info(f"已添加自定义设备: {my_device.name}")
|
||||
|
||||
# 可以在这里继续添加其他设备...
|
||||
|
||||
# 记录设备初始化完成的日志
|
||||
logger.info(f"IoT设备初始化完成,共注册了 {len(thing_manager.things)} 个设备")
|
||||
```
|
||||
|
||||
### 3. 设备通信(可选)
|
||||
|
||||
如果设备需要与实体硬件通信,可以通过各种协议实现:
|
||||
|
||||
- MQTT:用于与标准物联网设备通信
|
||||
- HTTP:用于REST API调用
|
||||
- 串口/GPIO:用于直接硬件控制
|
||||
|
||||
## 使用示例
|
||||
|
||||
### 基本设备控制
|
||||
|
||||
1. 启动应用程序
|
||||
2. 使用语音指令"打开灯"
|
||||
3. 系统识别指令并执行lamp.py中的TurnOn方法
|
||||
4. 灯设备状态更新,反馈给用户"灯已打开"
|
||||
|
||||
### 音乐播放控制
|
||||
|
||||
1. 使用指令"播放音乐周杰伦的稻香,通过iot音乐播放器播放"
|
||||
2. 系统解析指令并调用MusicPlayer的Play方法
|
||||
3. 播放器搜索歌曲,开始播放,并显示歌词
|
||||
4. 可以继续使用"暂停播放"等命令控制播放
|
||||
|
||||
### 倒计时控制示例
|
||||
|
||||
1. 使用指令"设置5秒后打开灯"
|
||||
2. 系统解析指令并调用CountdownTimer的StartCountdown方法
|
||||
3. 5秒后自动执行打开灯的命令
|
||||
4. 返回操作结果"倒计时已设置"
|
||||
|
||||
### Home Assistant设备控制示例
|
||||
|
||||
1. 使用指令"把客厅灯调暗一点"
|
||||
2. 系统解析指令并调用HomeAssistantLight的SetBrightness方法
|
||||
3. 通过HTTP API向Home Assistant发送亮度调整命令
|
||||
4. 返回操作结果"客厅灯亮度已调整"
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. 设备属性更新后,会自动通过WebSocket推送状态到服务端和UI界面
|
||||
2. 设备方法的实现应该考虑异步操作,避免阻塞主线程
|
||||
3. 参数类型和格式应严格遵循ValueType中定义的类型
|
||||
4. 新增设备时应确保设备ID全局唯一
|
||||
5. 所有设备方法应该实现适当的错误处理和反馈机制
|
||||
|
||||
## 高级主题:Home Assistant集成
|
||||
|
||||
### 通过HTTP API控制Home Assistant
|
||||
|
||||
Home Assistant是一个流行的开源家庭自动化平台,本项目通过HTTP API与Home Assistant集成,支持控制各种智能设备。以下是Home Assistant集成的关键点:
|
||||
|
||||
1. **配置文件设置**
|
||||
|
||||
在`config/config.json`中添加Home Assistant配置:
|
||||
|
||||
```json
|
||||
{
|
||||
"HOME_ASSISTANT": {
|
||||
"URL": "http://your-homeassistant-url:8123",
|
||||
"TOKEN": "your-long-lived-access-token",
|
||||
"DEVICES": [
|
||||
{
|
||||
"entity_id": "light.cuco_cn_573924446_v3_s_13_indicator_light",
|
||||
"friendly_name": "米家智能插座3-冰箱 指示灯"
|
||||
},
|
||||
{
|
||||
"entity_id": "switch.cuco_cn_573924446_v3_on_p_2_1",
|
||||
"friendly_name": "米家智能插座3-冰箱 开关 开关"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
### 配置ha地址和密钥
|
||||

|
||||
### 设备选择
|
||||
- 左上角开关处点击可以切换设备类型
|
||||
- 选中设备后天机右下角添加选中设备
|
||||
- 导入后需要重启小智等待程序加载完成就可以通过语音控制了
|
||||

|
||||
### 导入后
|
||||

|
||||
2. **支持的设备类型**
|
||||
|
||||
- `light`: 灯设备,支持开关和亮度控制
|
||||
- `switch`: 开关设备,支持开关控制
|
||||
- `number`: 数值控制器,支持设置数值
|
||||
- `button`: 按钮设备,支持按下操作
|
||||
|
||||
3. **语音命令示例**
|
||||
|
||||
- "打开客厅灯"
|
||||
- "把卧室灯调暗一点"
|
||||
- "将空调温度设为26度"
|
||||
- "关闭所有灯"
|
||||
|
||||
### 通信协议限制
|
||||
|
||||
当前IoT协议(1.0版本)存在以下限制:
|
||||
|
||||
1. **单向控制流**:大模型只能下发指令,无法立即获取指令执行结果
|
||||
2. **状态更新延迟**:设备状态变更需要等到下一轮对话时,通过读取property属性值才能获知
|
||||
3. **异步反馈**:如果需要操作结果反馈,必须通过设备属性的方式间接实现
|
||||
|
||||
### 最佳实践
|
||||
|
||||
1. **使用有意义的属性名称**:属性名称应清晰表达其含义,便于大模型理解和使用
|
||||
|
||||
2. **不产生歧义的方法描述**:为每个方法提供明确的自然语言描述,帮助大模型更准确地理解和调用
|
224
py-xiaozhi-main/documents/docs/guide/06_音量控制功能.md
Executable file
@ -0,0 +1,224 @@
|
||||
# 音量控制功能
|
||||
|
||||
## 功能概述
|
||||
|
||||
本应用支持调整系统音量,根据不同操作系统需要安装不同的依赖。应用程序会在启动时自动检查这些依赖是否已安装。如果缺少依赖,将会显示相应的安装指令。
|
||||
|
||||
## 平台支持
|
||||
|
||||
系统针对不同操作系统提供了不同的音量控制实现:
|
||||
|
||||
1. **Windows**: 使用 pycaw 和 comtypes 控制系统音量
|
||||
2. **macOS**: 使用 applescript 控制系统音量
|
||||
3. **Linux**: 根据系统环境使用 pactl (PulseAudio)、amixer (ALSA) 或 alsamixer 控制音量
|
||||
|
||||
## 依赖安装
|
||||
|
||||
### Windows
|
||||
```bash
|
||||
pip install pycaw comtypes
|
||||
```
|
||||
|
||||
### macOS
|
||||
macOS系统需要安装applescript模块:
|
||||
```bash
|
||||
pip install applescript
|
||||
```
|
||||
|
||||
### Linux
|
||||
根据您的音频系统安装以下依赖之一:
|
||||
|
||||
```bash
|
||||
# PulseAudio 工具(推荐)
|
||||
sudo apt-get install pulseaudio-utils
|
||||
|
||||
# 或者 ALSA 工具
|
||||
sudo apt-get install alsa-utils
|
||||
|
||||
# 如果需要使用 alsamixer 方式,还需要安装 expect
|
||||
sudo apt-get install alsa-utils expect
|
||||
```
|
||||
|
||||
## 使用方法
|
||||
|
||||
### GUI模式
|
||||
- 使用界面上的音量滑块直接调节音量
|
||||
- 滑块会在移动后300毫秒更新系统音量(防抖设计)
|
||||
- 可通过语音命令控制音量,如"调高音量"、"把音量调到50%"等
|
||||
|
||||
### CLI模式
|
||||
- 使用 `v <音量值>` 命令调节音量,例如 `v 50` 将音量设置为50%
|
||||
- 支持的命令:
|
||||
- `v <数值>` 设置为指定音量值(0-100)
|
||||
|
||||
### 语音控制
|
||||
通过IoT功能,可以使用语音命令控制音量:
|
||||
- "把音量调到50%"
|
||||
- "音量调小一点"
|
||||
- "音量调大"
|
||||
- "设置音量为80"
|
||||
|
||||
## 架构设计
|
||||
|
||||
音量控制功能采用分层设计,包括:
|
||||
|
||||
1. **VolumeController类** - 底层实现,负责跨平台音量操作
|
||||
2. **BaseDisplay.update_volume** - 中间层,应用程序与底层控制器的桥接
|
||||
3. **Speaker IoT设备** - 高级抽象,提供语音命令接口
|
||||
|
||||
## 内部实现
|
||||
|
||||
### 1. VolumeController类
|
||||
|
||||
VolumeController类是一个跨平台的音量控制实现,支持Windows、macOS和Linux系统:
|
||||
|
||||
```python
|
||||
# src/utils/volume_controller.py
|
||||
class VolumeController:
|
||||
"""跨平台音量控制器"""
|
||||
|
||||
def __init__(self):
|
||||
self.system = platform.system()
|
||||
# 根据不同操作系统初始化控制器
|
||||
if self.system == "Windows":
|
||||
self._init_windows()
|
||||
elif self.system == "Darwin": # macOS
|
||||
self._init_macos()
|
||||
elif self.system == "Linux":
|
||||
self._init_linux()
|
||||
|
||||
def get_volume(self):
|
||||
"""获取当前音量 (0-100)"""
|
||||
# 根据不同平台实现获取音量
|
||||
|
||||
def set_volume(self, volume):
|
||||
"""设置音量 (0-100)"""
|
||||
# 根据不同平台实现设置音量
|
||||
```
|
||||
|
||||
### 2. BaseDisplay音量控制
|
||||
|
||||
BaseDisplay类提供音量控制接口,由CLI和GUI显示类继承:
|
||||
|
||||
```python
|
||||
# src/display/base_display.py
|
||||
class BaseDisplay(ABC):
|
||||
def __init__(self):
|
||||
self.current_volume = 70 # 默认音量值
|
||||
self.volume_controller = None
|
||||
|
||||
# 初始化音量控制器
|
||||
try:
|
||||
from src.utils.volume_controller import VolumeController
|
||||
if VolumeController.check_dependencies():
|
||||
self.volume_controller = VolumeController()
|
||||
self.current_volume = self.volume_controller.get_volume()
|
||||
except Exception as e:
|
||||
# 错误处理...
|
||||
|
||||
def get_current_volume(self):
|
||||
"""获取当前音量"""
|
||||
if self.volume_controller:
|
||||
try:
|
||||
self.current_volume = self.volume_controller.get_volume()
|
||||
except Exception:
|
||||
pass
|
||||
return self.current_volume
|
||||
|
||||
def update_volume(self, volume: int):
|
||||
"""更新系统音量"""
|
||||
volume = max(0, min(100, volume))
|
||||
self.current_volume = volume
|
||||
|
||||
if self.volume_controller:
|
||||
try:
|
||||
self.volume_controller.set_volume(volume)
|
||||
except Exception:
|
||||
# 错误处理...
|
||||
pass
|
||||
```
|
||||
|
||||
### 3. Speaker IoT设备
|
||||
|
||||
Speaker类是一个IoT设备,允许通过语音命令控制音量:
|
||||
|
||||
```python
|
||||
# src/iot/things/speaker.py
|
||||
from src.application import Application
|
||||
from src.iot.thing import Thing, Parameter, ValueType
|
||||
|
||||
class Speaker(Thing):
|
||||
def __init__(self):
|
||||
super().__init__("Speaker", "当前 AI 机器人的扬声器")
|
||||
|
||||
# 获取当前显示实例的音量作为初始值
|
||||
try:
|
||||
app = Application.get_instance()
|
||||
self.volume = app.display.current_volume
|
||||
except Exception:
|
||||
# 如果获取失败,使用默认值
|
||||
self.volume = 100 # 默认音量
|
||||
|
||||
# 定义音量属性
|
||||
self.add_property("volume", "当前音量值", lambda: self.volume)
|
||||
|
||||
# 定义设置音量方法
|
||||
self.add_method(
|
||||
"SetVolume",
|
||||
"设置音量",
|
||||
[Parameter("volume", "0到100之间的整数", ValueType.NUMBER, True)],
|
||||
lambda params: self._set_volume(params["volume"].get_value())
|
||||
)
|
||||
|
||||
def _set_volume(self, volume):
|
||||
"""设置音量的具体实现"""
|
||||
if 0 <= volume <= 100:
|
||||
self.volume = volume
|
||||
try:
|
||||
app = Application.get_instance()
|
||||
app.display.update_volume(volume)
|
||||
return {"success": True, "message": f"音量已设置为: {volume}"}
|
||||
except Exception as e:
|
||||
return {"success": False, "message": f"设置音量失败: {e}"}
|
||||
else:
|
||||
raise ValueError("音量必须在0-100之间")
|
||||
```
|
||||
|
||||
### 4. 在Application中注册
|
||||
|
||||
音量控制设备在应用程序启动时被注册:
|
||||
|
||||
```python
|
||||
# src/application.py (部分代码)
|
||||
def _initialize_iot_devices(self):
|
||||
"""初始化物联网设备"""
|
||||
from src.iot.thing_manager import ThingManager
|
||||
from src.iot.things.speaker import Speaker
|
||||
|
||||
# 获取物联网设备管理器实例
|
||||
thing_manager = ThingManager.get_instance()
|
||||
|
||||
# 添加音量控制设备
|
||||
thing_manager.add_thing(Speaker())
|
||||
```
|
||||
|
||||
## 常见问题
|
||||
|
||||
1. **无法调节音量**
|
||||
- 检查是否安装了对应操作系统的音量控制依赖
|
||||
- Windows用户确保安装了pycaw和comtypes
|
||||
- macOS用户确保安装了applescript模块
|
||||
- Linux用户确保安装了对应的音频控制工具(pactl或amixer)
|
||||
|
||||
2. **调节音量命令无响应**
|
||||
- 确保IoT模块正常运行
|
||||
- 检查系统音频设备是否正常工作
|
||||
- 尝试重启应用
|
||||
|
||||
3. **音量调节不准确**
|
||||
- 可能是由于不同音频接口导致的精度问题
|
||||
- 尝试使用较大幅度的调节命令
|
||||
|
||||
4. **GUI滑块与实际音量不同步**
|
||||
- 在某些情况下,系统音量可能被其他应用程序更改
|
||||
- 重新启动应用程序将重新获取当前系统音量
|
97
py-xiaozhi-main/documents/docs/guide/07_视觉识别功能.md
Executable file
@ -0,0 +1,97 @@
|
||||
# 视觉识别功能
|
||||
|
||||
## 功能概述
|
||||
|
||||
py-xiaozhi提供了摄像头控制和视觉识别功能,支持通过语音命令打开/关闭摄像头,以及对摄像头捕获的画面进行智能识别分析。
|
||||
|
||||
## 配置说明
|
||||
|
||||
视觉识别功能需要在配置文件中进行相关设置:
|
||||
|
||||
```json
|
||||
"CAMERA": {
|
||||
"camera_index": 0, // 摄像头索引,0通常是电脑内置摄像头
|
||||
"frame_width": 640, // 画面宽度
|
||||
"frame_height": 480, // 画面高度
|
||||
"fps": 30, // 帧率
|
||||
"Loacl_VL_url": "https://open.bigmodel.cn/api/paas/v4/", // 智普API地址
|
||||
"VLapi_key": "你的key", // 智普视觉大模型API密钥
|
||||
"models": "glm-4v-plus" // 使用的视觉模型
|
||||
}
|
||||
```
|
||||
|
||||
## 智普视觉大模型配置
|
||||
|
||||
1. 访问 [智普AI开放平台](https://open.bigmodel.cn/)
|
||||
2. 注册账号并创建API密钥
|
||||
3. 将获取的API密钥配置到`config.json`的`CAMERA.VLapi_key`字段
|
||||
4. 可以选择使用的模型,默认为`glm-4v-plus`
|
||||
|
||||
## 使用方法
|
||||
|
||||
### 语音命令控制
|
||||
|
||||
系统支持以下语音命令控制摄像头和视觉识别功能:
|
||||
|
||||
- **打开摄像头**:激活系统摄像头,开始捕获视频流
|
||||
- **关闭摄像头**:停止摄像头捕获
|
||||
- **识别画面**:对当前摄像头画面进行智能视觉分析,识别画面中的内容
|
||||
- **分析图像**:对当前画面进行详细视觉分析并提供描述
|
||||
- **看到了什么**:询问当前摄像头看到的内容
|
||||
|
||||
### GUI 界面控制
|
||||
|
||||
在图形界面模式下,可以通过界面上的相关按钮控制摄像头功能。
|
||||
|
||||
## 内部实现
|
||||
|
||||
视觉识别功能通过IoT模块中的CameraVL设备类实现,主要由Camera和VL两个组件组成:
|
||||
|
||||
1. **Camera 组件**:负责摄像头的基本控制,如开启、关闭、获取视频帧等
|
||||
2. **VL(Vision Language)组件**:负责对图像进行智能分析,调用智普视觉大模型API
|
||||
|
||||
实现结构:
|
||||
|
||||
```
|
||||
CameraVL # 摄像头与视觉识别集成设备
|
||||
├── Camera.py # 摄像头控制模块
|
||||
└── VL.py # 视觉语言分析模块
|
||||
```
|
||||
|
||||
## 工作流程
|
||||
|
||||
1. 用户通过语音命令打开摄像头
|
||||
2. 系统激活摄像头并在界面显示视频流
|
||||
3. 用户请求识别当前画面
|
||||
4. 系统截取当前帧,并将图像发送给智普视觉大模型
|
||||
5. 获取视觉分析结果并通过语音或文字反馈给用户
|
||||
|
||||
## 隐私说明
|
||||
|
||||
视觉识别功能会使用您的摄像头并处理画面内容,请注意:
|
||||
|
||||
1. 摄像头捕获的画面仅用于本地分析或发送至智普API进行分析
|
||||
2. 非语音命令控制时,摄像头处于关闭状态
|
||||
3. 可以在配置中修改摄像头设置或完全禁用此功能
|
||||
|
||||
## 常见问题
|
||||
|
||||
1. **摄像头无法打开**
|
||||
- 确认您的设备有可用摄像头
|
||||
- 检查摄像头是否被其他应用占用
|
||||
- 确认已授予应用使用摄像头的权限
|
||||
|
||||
2. **视觉识别功能无响应**
|
||||
- 检查智普API密钥是否正确配置
|
||||
- 确认网络连接正常
|
||||
- 检查是否超出API调用次数限制
|
||||
|
||||
3. **识别结果不准确**
|
||||
- 尝试改善摄像头光线条件
|
||||
- 确保目标对象在画面中清晰可见
|
||||
- 可能需要升级智普视觉模型版本
|
||||
|
||||
4. **摄像头画面卡顿**
|
||||
- 尝试在配置中降低分辨率或帧率
|
||||
- 关闭其他占用系统资源的应用
|
||||
- 更新摄像头驱动
|
324
py-xiaozhi-main/documents/docs/guide/08_设备激活流程.md
Executable file
@ -0,0 +1,324 @@
|
||||
# 设备激活流程 v2
|
||||
|
||||
## 概述
|
||||
|
||||
当前流程是虾哥设备认证v2版本
|
||||
|
||||
## 激活流程
|
||||
|
||||
每个设备都有一个唯一的序列号(Serial Number)和HMAC密钥(HMAC Key),用于身份验证和安全通信。新设备首次使用时需要通过以下流程进行激活:
|
||||
|
||||
1. 客户端启动时,向服务器发送设备信息,包括序列号、MAC地址和客户端ID
|
||||
2. 服务器检查设备是否已激活:
|
||||
- 如果已激活,客户端正常工作
|
||||
- 如果未激活,服务器返回包含验证码和Challenge的激活请求
|
||||
3. 客户端显示验证码,提示用户前往xiaozhi.me网站输入验证码
|
||||
4. 客户端使用HMAC密钥对Challenge进行签名,并发送给服务器验证
|
||||
5. 客户端通过轮询方式等待服务器确认验证结果:
|
||||
- 如果验证成功,设备激活完成
|
||||
- 如果验证失败或超时,设备激活失败
|
||||
|
||||
### 小智 ESP32 设备激活流程图
|
||||
|
||||
```
|
||||
┌────────────────────┐
|
||||
│ 设备启动 │
|
||||
└──────────┬─────────┘
|
||||
↓
|
||||
┌────────────────────┐
|
||||
│ 初始化各组件 │
|
||||
│ 连接WiFi/网络 │
|
||||
└──────────┬─────────┘
|
||||
↓
|
||||
┌────────────────────┐
|
||||
│ 调用CheckVersion │
|
||||
│ 访问OTA服务器 │──→ POST /xiaozhi/ota/
|
||||
└──────────┬─────────┘
|
||||
↓
|
||||
┌────────────────────┐
|
||||
│ 解析服务器响应 │
|
||||
└──────────┬─────────┘
|
||||
↓
|
||||
┌─────┴─────┐
|
||||
↓ ↓
|
||||
┌─────────┐ ┌─────────┐
|
||||
│是否有新版本│ │是否需要激活│
|
||||
└─────┬───┘ └─────┬───┘
|
||||
│ │
|
||||
┌─────▼───┐ └───┬─── 否 ──┐
|
||||
│升级固件 │ ↓ ↓
|
||||
└─────────┘ ┌─────────────┐ ┌─────────────┐
|
||||
│是否有激活码 │ │初始化协议连接│
|
||||
└──────┬──────┘ │MQTT/WebSocket│
|
||||
│ └─────────────┘
|
||||
┌────▼───┐
|
||||
│ 是 │
|
||||
└────┬───┘
|
||||
↓
|
||||
┌──────────────────┐
|
||||
│显示激活码给用户 │
|
||||
│播放语音提示 │
|
||||
└────────┬─────────┘
|
||||
↓
|
||||
┌──────────────────┐
|
||||
│ 开始激活流程 │
|
||||
└────────┬─────────┘
|
||||
↓
|
||||
┌────────────────────────────────┐
|
||||
│ 检查设备序列号 │
|
||||
└───────────────┬────────────────┘
|
||||
↓
|
||||
┌──────┴───────┐
|
||||
↓ ↓
|
||||
┌─────────┐ ┌─────────┐
|
||||
│ 有序列号 │ │ 无序列号 │
|
||||
└─────┬────┘ └────┬────┘
|
||||
│ │
|
||||
┌─────────▼────────┐ │
|
||||
│构造激活载荷JSON: │ │
|
||||
│- serial_number │ │
|
||||
│- challenge │ │
|
||||
│- hmac签名 │ │
|
||||
└─────────┬─────────┘ │
|
||||
│ │
|
||||
└──────┬───────┘
|
||||
↓
|
||||
┌───────────────────────┐
|
||||
│发送POST请求到激活端点 │──→ POST /xiaozhi/ota/activate
|
||||
└────────────┬──────────┘
|
||||
↓
|
||||
┌───────────┴───────────┐
|
||||
↓ ↓ ↓
|
||||
┌─────────┐ ┌─────────┐ ┌─────────┐
|
||||
│状态码200 │ │状态码202 │ │其他状态码│
|
||||
│激活成功 │ │超时重试 │ │激活失败 │
|
||||
└────┬────┘ └────┬────┘ └────┬────┘
|
||||
│ │ │
|
||||
│ ┌────▼─────┐ │
|
||||
│ │延迟后重试 │ │
|
||||
│ │最多10次 │ │
|
||||
│ └────┬─────┘ │
|
||||
│ │ │
|
||||
└───────────┼───────────┘
|
||||
↓
|
||||
┌──────────────────┐
|
||||
│设置激活状态标志位 │
|
||||
└────────┬─────────┘
|
||||
↓
|
||||
┌──────────────────┐
|
||||
│ 继续正常运行 │
|
||||
│ 连接MQTT/WS协议 │
|
||||
└──────────────────┘
|
||||
```
|
||||
|
||||
### 激活数据交互详细流程
|
||||
|
||||
```
|
||||
┌────────────┐ ┌────────────┐ ┌────────────┐
|
||||
│ │ │ │ │ │
|
||||
│ 设备客户端 │ │ 服务器 │ │ 用户浏览器 │
|
||||
│ │ │ │ │ │
|
||||
└─────┬──────┘ └─────┬──────┘ └─────┬──────┘
|
||||
│ │ │
|
||||
│ 请求设备状态 (MAC, ClientID, SN) │ │
|
||||
│ ────────────────────────────────> │ │
|
||||
│ │ │
|
||||
│ 返回激活请求 (验证码, Challenge) │ │
|
||||
│ <──────────────────────────────── │ │
|
||||
│ │ │
|
||||
│ 显示验证码 │ │
|
||||
│ ┌─────────────┐ │ │
|
||||
│ │请前往网站输入 │ │ │
|
||||
│ │验证码: 123456│ │ │
|
||||
│ └─────────────┘ │ │
|
||||
│ │ │
|
||||
│ │ 用户访问xiaozhi.me │
|
||||
│ │ <─────────────────────────────────│
|
||||
│ │ │
|
||||
│ │ 输入验证码 123456 │
|
||||
│ │ <─────────────────────────────────│
|
||||
│ │ │
|
||||
│ 计算HMAC签名 │ │
|
||||
│ ┌─────────────┐ │ │
|
||||
│ │ HMAC(密钥, │ │ │
|
||||
│ │ Challenge) │ │ │
|
||||
│ └─────────────┘ │ │
|
||||
│ │ │
|
||||
│ 发送激活请求 (SN, Challenge, 签名) │ │
|
||||
│ ────────────────────────────────> │ │
|
||||
│ │ ┌───────────────┐ │
|
||||
│ │ │ 等待用户输入验证码 │ │
|
||||
│ │ │ 超时返回202 │ │
|
||||
│ │ └───────────────┘ │
|
||||
│ │ │
|
||||
│ 轮询等待 (HTTP Long Polling) │ │
|
||||
│ ────────────────────────────────> │ │
|
||||
│ HTTP 202 (Pending) │ │
|
||||
│ <──────────────────────────────── │ │
|
||||
│ │ │
|
||||
│ 继续轮询... │ │
|
||||
│ ────────────────────────────────> │ │
|
||||
│ │ │
|
||||
│ │ 验证码验证成功 │
|
||||
│ │───────────────────────────────────│
|
||||
│ │ │
|
||||
│ 激活成功 (HTTP 200) │ │
|
||||
│ <──────────────────────────────── │ │
|
||||
│ │ │
|
||||
│ ┌─────────────┐ │ │
|
||||
│ │设备激活成功! │ │ │
|
||||
│ └─────────────┘ │ │
|
||||
│ │ │
|
||||
```
|
||||
|
||||
## 设备与服务器通信内容详解
|
||||
|
||||
### 1. 设备信息请求 (POST /xiaozhi/ota/)
|
||||
|
||||
**请求头**:
|
||||
```
|
||||
Activation-Version: 2 // 表示支持序列号激活
|
||||
Device-Id: AA:BB:CC:DD:EE:FF // MAC地址
|
||||
Client-Id: xxxx-xxxx-xxxx-xxxx // 设备UUID
|
||||
User-Agent: BOARD_NAME/1.0.0 // 开发板名称和固件版本
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
**请求体** (POST时):
|
||||
```json
|
||||
{
|
||||
"version": 2,
|
||||
"flash_size": 16777216,
|
||||
"psram_size": 8388608,
|
||||
"minimum_free_heap_size": 7265024,
|
||||
"mac_address": "你的mac地址",
|
||||
"uuid": "你的client_id",
|
||||
"chip_model_name": "esp32s3",
|
||||
"chip_info": {
|
||||
"model": 9,
|
||||
"cores": 2,
|
||||
"revision": 0,
|
||||
"features": 20
|
||||
},
|
||||
"application": {
|
||||
"name": "xiaozhi",
|
||||
"version": "1.6.0",
|
||||
"compile_time": "2025-04-16T12:00:00Z",
|
||||
"idf_version": "v5.3.2"
|
||||
},
|
||||
"partition_table": [
|
||||
{
|
||||
"label": "nvs",
|
||||
"type": 1,
|
||||
"subtype": 2,
|
||||
"address": 36864,
|
||||
"size": 24576
|
||||
},
|
||||
{
|
||||
"label": "otadata",
|
||||
"type": 1,
|
||||
"subtype": 0,
|
||||
"address": 61440,
|
||||
"size": 8192
|
||||
},
|
||||
{
|
||||
"label": "app0",
|
||||
"type": 0,
|
||||
"subtype": 0,
|
||||
"address": 65536,
|
||||
"size": 1966080
|
||||
},
|
||||
{
|
||||
"label": "app1",
|
||||
"type": 0,
|
||||
"subtype": 0,
|
||||
"address": 2031616,
|
||||
"size": 1966080
|
||||
},
|
||||
{
|
||||
"label": "spiffs",
|
||||
"type": 1,
|
||||
"subtype": 130,
|
||||
"address": 3997696,
|
||||
"size": 1966080
|
||||
}
|
||||
],
|
||||
"ota": {
|
||||
"label": "app0"
|
||||
},
|
||||
"board": {
|
||||
"type": "lc-esp32-s3",
|
||||
"name": "立创ESP32-S3开发板",
|
||||
"features": ["wifi", "ble", "psram", "octal_flash"],
|
||||
"ip": "你的ip地址",
|
||||
"mac": "你的mac地址"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 服务器响应
|
||||
|
||||
**响应体**:
|
||||
```json
|
||||
{
|
||||
"firmware": {
|
||||
"version": "1.0.1",
|
||||
"url": ""
|
||||
},
|
||||
"activation": {
|
||||
"message": "请访问xiaozhi.me输入激活码",
|
||||
"code": "123456",
|
||||
"challenge": "randomstring123456",
|
||||
"timeout_ms": 30000
|
||||
},
|
||||
"mqtt": {
|
||||
"endpoint": "mqtt.xiaozhi.me",
|
||||
"client_id": "device123",
|
||||
"username": "user123",
|
||||
"password": "pass123",
|
||||
"publish_topic": ""
|
||||
},
|
||||
"websocket": {
|
||||
"url": "wss://api.tenclass.net/xiaozhi/v1/",
|
||||
"token": "test-token"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 设备激活请求 (POST /xiaozhi/ota/activate)
|
||||
|
||||
**请求体**:
|
||||
```json
|
||||
{
|
||||
"Payload": {
|
||||
"algorithm": "hmac-sha256",
|
||||
"serial_number": "SN-5CD8467B47FB4920",
|
||||
"challenge": "dac852d6-4ac4-4650-ba1a-c2a5bf00a766",
|
||||
"hmac": "ada4775e3ed93cf9c0eb9ed00444138554ba416af41283a0e5603c77681a8022"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 激活响应
|
||||
|
||||
- **成功**: 状态码 200
|
||||
- **等待用户输入验证码**: 状态码 202
|
||||
- **失败**: 状态码 4xx (如401表示未授权,400表示请求错误)
|
||||
|
||||
**响应体** (失败时):
|
||||
|
||||
```json
|
||||
{
|
||||
"error": "错误原因描述"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## 安全机制
|
||||
|
||||
设备激活流程v2版本采用以下安全机制:
|
||||
|
||||
1. **设备唯一标识**:每个设备有一个唯一的序列号(Serial Number)
|
||||
2. **HMAC签名验证**:使用HMAC-SHA256算法对Challenge进行签名,确保设备身份的真实性
|
||||
3. **验证码验证**:通过要求用户在网页端输入验证码,防止自动化的激活攻击
|
||||
4. **轮询等待机制**:使用HTTP Long Polling等待服务器验证结果,适应各种网络环境
|
349
py-xiaozhi-main/documents/docs/guide/09_打包教程.md
Executable file
@ -0,0 +1,349 @@
|
||||
# 项目打包教程
|
||||
|
||||
## 概述
|
||||
|
||||
UnifyPy是一个强大的自动化解决方案,能将Python项目打包成跨平台的独立可执行文件和安装程序。小智客户端已配置了相应的打包配置文件,本教程将指导您如何使用UnifyPy进行打包。
|
||||
|
||||
## 准备工作
|
||||
|
||||
### 1. 安装py-xiaozhi项目依赖
|
||||
|
||||
首先,确保您已安装项目的所有依赖:
|
||||
|
||||
```bash
|
||||
# Windows
|
||||
pip install -r requirements.txt
|
||||
|
||||
# macOS
|
||||
pip install -r requirements_mac.txt
|
||||
|
||||
# Linux
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
### 2. 克隆UnifyPy仓库
|
||||
|
||||
```bash
|
||||
git clone https://github.com/huangjunsen0406/UnifyPy.git
|
||||
```
|
||||
|
||||
### 3. 安装平台特定工具
|
||||
|
||||
#### Windows平台
|
||||
- 安装[Inno Setup](https://jrsoftware.org/isdl.php)(用于创建安装程序)
|
||||
- 安装后,在build.json中配置Inno Setup路径,或设置环境变量INNO_SETUP_PATH
|
||||
|
||||
#### macOS平台
|
||||
- 安装create-dmg(用于创建DMG镜像):
|
||||
```bash
|
||||
brew install create-dmg
|
||||
```
|
||||
|
||||
#### Linux平台
|
||||
根据需要的打包格式,安装相应的工具:
|
||||
|
||||
```bash
|
||||
# DEB格式(Debian/Ubuntu)
|
||||
sudo apt-get install dpkg-dev
|
||||
|
||||
# RPM格式(Fedora/CentOS)
|
||||
sudo dnf install rpm-build
|
||||
|
||||
# AppImage格式(通用Linux)
|
||||
wget -c https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage
|
||||
chmod a+x appimagetool-x86_64.AppImage
|
||||
sudo mv appimagetool-x86_64.AppImage /usr/local/bin/appimagetool
|
||||
```
|
||||
|
||||
## 打包配置详解
|
||||
|
||||
小智客户端已经提供了预配置的`build.json`文件,以下是各配置项的详细说明:
|
||||
|
||||
### 基本配置
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "xiaozhi", // 应用程序名称,将用于可执行文件和安装程序名称
|
||||
"version": "1.0.0", // 应用程序版本号
|
||||
"publisher": "Junsen", // 发布者名称
|
||||
"entry": "main.py", // 程序入口文件
|
||||
"icon": "assets/xiaozhi_icon.ico", // 应用图标路径
|
||||
"hooks": "hooks", // PyInstaller钩子目录
|
||||
"onefile": false, // 是否生成单文件模式的可执行文件
|
||||
|
||||
// PyInstaller通用参数,适用于所有平台
|
||||
"additional_pyinstaller_args": "--add-data assets;assets --add-data libs;libs --add-data src;src --add-data models;models --hidden-import=PyQt5",
|
||||
|
||||
// Inno Setup路径(Windows平台需要)
|
||||
"inno_setup_path": "E:\\application\\Inno Setup 6\\ISCC.exe",
|
||||
|
||||
// 其他配置...
|
||||
}
|
||||
```
|
||||
|
||||
> **注意**:JSON文件不支持注释,上述代码中的注释仅用于说明,实际配置文件中不应包含注释。
|
||||
|
||||
### 平台特定配置
|
||||
|
||||
#### Windows平台配置
|
||||
|
||||
```json
|
||||
"windows": {
|
||||
"format": "exe", // 输出格式
|
||||
"additional_pyinstaller_args": "--add-data assets;assets --add-data libs;libs --add-data src;src --add-data models;models --hidden-import=PyQt5 --noconsole",
|
||||
"desktop_entry": true, // 是否创建桌面快捷方式
|
||||
"installer_options": {
|
||||
"languages": ["ChineseSimplified", "English"], // 安装程序支持的语言
|
||||
"license_file": "LICENSE", // 许可证文件
|
||||
"readme_file": "README.md", // 自述文件
|
||||
"create_desktop_icon": true, // 是否创建桌面图标
|
||||
"allow_run_after_install": true // 安装后是否允许立即运行
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Linux平台配置
|
||||
|
||||
```json
|
||||
"linux": {
|
||||
"format": "deb", // 输出格式,可选值:deb, rpm, appimage
|
||||
"desktop_entry": true, // 是否创建桌面快捷方式
|
||||
"categories": "Utility;Development;", // 应用程序类别
|
||||
"description": "小智Ai客户端", // 应用描述
|
||||
"requires": "libc6,libgtk-3-0,libx11-6,libopenblas-dev", // 依赖项
|
||||
"additional_pyinstaller_args": "--add-data assets:assets --add-data libs:libs --add-data src:src --add-data models:models --hidden-import=PyQt5"
|
||||
}
|
||||
```
|
||||
|
||||
#### macOS平台配置
|
||||
|
||||
```json
|
||||
"macos": {
|
||||
"format": "app", // 输出格式,可选值:app, dmg
|
||||
"additional_pyinstaller_args": "--add-data assets:assets --add-data libs:libs --add-data src:src --add-data models:models --hidden-import=PyQt5 --windowed",
|
||||
"app_bundle_name": "XiaoZhi.app", // 应用包名称
|
||||
"bundle_identifier": "com.junsen.xiaozhi", // 应用标识符
|
||||
"sign_bundle": false, // 是否签名应用包
|
||||
"create_dmg": true, // 是否创建DMG镜像
|
||||
"installer_options": {
|
||||
"license_file": "LICENSE", // 许可证文件
|
||||
"readme_file": "README.md" // 自述文件
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 其他重要配置项
|
||||
|
||||
```json
|
||||
"build_installer": true // 是否构建安装程序,设为false只生成可执行文件
|
||||
```
|
||||
|
||||
### 自定义安装程序模板
|
||||
|
||||
当打包Windows安装程序时,UnifyPy使用`setup.iss.template`文件作为Inno Setup的脚本模板。需要注意的是,模板中的AppId需要更换为自己的唯一标识符:
|
||||
|
||||
```
|
||||
[Setup]
|
||||
; 应用程序信息
|
||||
AppId={{05DBB87C-AE34-4F2F-AEC5-3CD2AFE9DC90}} ; 需要替换为你自己生成的GUID
|
||||
```
|
||||
|
||||
> **重要**:请勿直接使用示例中的AppId,这可能导致与其他应用程序冲突。您可以使用在线GUID生成工具(如[Online GUID Generator](https://www.guidgenerator.com/))来生成自己的唯一标识符。
|
||||
|
||||
## 执行打包
|
||||
|
||||
### 基本打包命令
|
||||
- 建议UnifyPy放在和py-xiaozhi项目同级目录下, 直接 `python ../UnifyPy/main.py. --config build.json` 即可
|
||||
```bash
|
||||
# 导航到UnifyPy目录
|
||||
cd 到当前py-xiaozhi项目目录下
|
||||
|
||||
# 执行打包命令
|
||||
# UnifyPy_路径/main.py 是UnifyPy的项目路径
|
||||
# . 表示当前项目目录
|
||||
# --config build.json 表示使用当前目录下的build.json配置文件
|
||||
python UnifyPy_路径/main.py . --config build.json
|
||||
```
|
||||
|
||||
### 针对不同平台的打包命令
|
||||
|
||||
#### Windows平台
|
||||
```bash
|
||||
python C:\路径\到\UnifyPy\main.py . --config build.json
|
||||
```
|
||||
|
||||
#### macOS平台
|
||||
```bash
|
||||
python /路径/到/UnifyPy/main.py . --config build.json
|
||||
```
|
||||
|
||||
#### Linux平台
|
||||
|
||||
Linux平台下打包有两种主要格式:DEB和AppImage。根据需要选择其中一种格式。
|
||||
|
||||
##### DEB格式打包(适用于Debian/Ubuntu系统)
|
||||
|
||||
1. **准备环境**
|
||||
|
||||
```bash
|
||||
# 更新系统并安装必要的依赖
|
||||
sudo apt update
|
||||
sudo apt install -y build-essential python3-dev python3-pip python3-setuptools libopenblas-dev liblapack-dev gfortran patchelf autoconf automake libtool cmake libssl-dev libatlas-base-dev
|
||||
```
|
||||
|
||||
2. **执行打包**
|
||||
|
||||
确保build.json中linux.format设置为"deb",然后执行:
|
||||
|
||||
```bash
|
||||
python3 /路径/到/UnifyPy/main.py . --config build.json
|
||||
```
|
||||
|
||||
##### AppImage格式打包(适用于通用Linux系统)
|
||||
|
||||
AppImage格式需要特别注意NumPy库的编译,以下是完整步骤:
|
||||
|
||||
1. **升级pip和基本构建工具**
|
||||
|
||||
```bash
|
||||
python -m pip install --upgrade pip setuptools wheel
|
||||
```
|
||||
|
||||
2. **安装必要的系统依赖**
|
||||
|
||||
```bash
|
||||
sudo apt update
|
||||
sudo apt install -y build-essential python3-dev python3-pip python3-setuptools libopenblas-dev liblapack-dev gfortran patchelf autoconf automake libtool cmake libssl-dev libatlas-base-dev
|
||||
```
|
||||
|
||||
3. **安装Meson和Ninja构建系统**
|
||||
|
||||
```bash
|
||||
pip install meson ninja
|
||||
sudo apt install -y meson ninja-build
|
||||
```
|
||||
|
||||
4. **准备NumPy编译环境**
|
||||
|
||||
```bash
|
||||
# 卸载现有NumPy
|
||||
pip uninstall numpy -y
|
||||
|
||||
# 设置环境变量
|
||||
export BLAS=openblas
|
||||
export LAPACK=openblas
|
||||
export NPY_NUM_BUILD_JOBS=$(nproc) # 使用所有CPU核心加速编译
|
||||
|
||||
# 从源码编译安装NumPy
|
||||
pip install numpy==1.26.4 --no-binary :all:
|
||||
```
|
||||
|
||||
5. **执行打包**
|
||||
|
||||
确保build.json中linux.format设置为"appimage",然后执行:
|
||||
|
||||
```bash
|
||||
python3 /路径/到/UnifyPy/main.py . --config build.json
|
||||
```
|
||||
|
||||
## 打包输出
|
||||
|
||||
成功打包后,将在项目根目录下的`dist`文件夹中找到打包的应用程序:
|
||||
|
||||
- **Windows**:
|
||||
- 可执行文件(.exe)位于`dist/xiaozhi`目录
|
||||
- 安装程序位于`dist/installer`目录,命名为`xiaozhi-1.0.0-setup.exe`
|
||||
|
||||
- **macOS**:
|
||||
- 应用程序包(.app)位于`dist/xiaozhi`目录
|
||||
- 磁盘镜像(.dmg)位于`dist/installer`目录,命名为`xiaozhi-1.0.0.dmg`
|
||||
|
||||
- **Linux**:
|
||||
- 可执行文件位于`dist/xiaozhi`目录
|
||||
- 安装包位于`dist/installer`目录:
|
||||
- DEB格式:`xiaozhi-1.0.0.deb`
|
||||
- RPM格式:`xiaozhi-1.0.0.rpm`
|
||||
- AppImage格式:`xiaozhi-1.0.0.AppImage`
|
||||
|
||||
## 高级配置选项
|
||||
|
||||
### PyInstaller参数
|
||||
|
||||
在`additional_pyinstaller_args`字段中,您可以添加任何PyInstaller支持的参数。以下是一些常用参数:
|
||||
|
||||
- `--noconsole`: 不显示控制台窗口(仅适用于图形界面程序)
|
||||
- `--windowed`: 等同于`--noconsole`
|
||||
- `--hidden-import=MODULE`: 添加隐式导入的模块
|
||||
- `--add-data SRC;DEST`: 添加数据文件(Windows平台使用分号分隔)
|
||||
- `--add-data SRC:DEST`: 添加数据文件(macOS/Linux平台使用冒号分隔)
|
||||
- `--icon=FILE.ico`: 设置应用程序图标
|
||||
|
||||
### 处理特殊依赖
|
||||
|
||||
某些Python库可能需要特殊处理才能正确打包,可以通过以下方式解决:
|
||||
|
||||
1. **使用钩子文件**:在`hooks`目录中创建自定义钩子,处理特殊导入情况
|
||||
2. **添加隐式导入**:使用`--hidden-import`参数显式包含隐式导入的模块
|
||||
3. **添加数据文件**:使用`--add-data`参数包含程序运行所需的数据文件
|
||||
|
||||
## 常见问题及解决方案
|
||||
|
||||
### Windows平台常见问题
|
||||
|
||||
1. **找不到Inno Setup**
|
||||
|
||||
解决方案:确保已安装Inno Setup,并在build.json中正确配置路径,或设置环境变量INNO_SETUP_PATH
|
||||
|
||||
2. **缺少隐式导入的模块**
|
||||
|
||||
解决方案:在`additional_pyinstaller_args`中添加`--hidden-import=模块名称`
|
||||
|
||||
3. **打包后无法找到资源文件**
|
||||
|
||||
解决方案:确保使用相对路径访问资源文件,并使用`--add-data`参数正确包含资源文件
|
||||
|
||||
### macOS平台常见问题
|
||||
|
||||
1. **创建DMG出错**
|
||||
|
||||
解决方案:确保已安装create-dmg工具,并有正确的权限
|
||||
|
||||
2. **签名问题**
|
||||
|
||||
解决方案:如果需要签名,在配置文件中启用`sign_bundle`并提供有效的开发者身份
|
||||
|
||||
3. **动态库加载问题**
|
||||
|
||||
解决方案:确保代码中正确处理库路径,特别是使用`sys._MEIPASS`路径
|
||||
|
||||
### Linux平台常见问题
|
||||
|
||||
1. **缺少依赖库**
|
||||
|
||||
解决方案:在Linux配置中的`requires`字段中添加所需的系统依赖
|
||||
|
||||
2. **打包工具不可用**
|
||||
|
||||
解决方案:确保已安装相应格式的打包工具(dpkg-dev, rpmbuild, appimagetool)
|
||||
|
||||
3. **权限问题**
|
||||
|
||||
解决方案:确保脚本有正确的执行权限,对某些资源目录可能需要特别处理
|
||||
|
||||
4. **NumPy编译失败**
|
||||
|
||||
解决方案:确保已安装所有必要的开发库,特别是OpenBLAS、LAPACK和Fortran编译器
|
||||
|
||||
5. **找不到appimagetool**
|
||||
|
||||
解决方案:确保已正确安装并设置appimagetool的可执行权限
|
||||
|
||||
## 最佳实践
|
||||
|
||||
1. **清理项目**:打包前移除临时文件、缓存和不必要的大型文件
|
||||
2. **测试依赖**:确保所有依赖都正确安装并可以导入
|
||||
3. **确认文件路径**:检查代码中的文件路径是否使用相对路径或资源路径
|
||||
4. **验证配置**:确保build.json中的配置与您的环境一致
|
||||
5. **多平台测试**:如果条件允许,在多个平台上测试打包的应用程序
|
||||
6. **保存配置**:为不同的打包场景保存不同版本的配置文件,方便复用
|
||||
7. **版本管理**:每次发布前更新版本号,保持版本一致性
|
BIN
py-xiaozhi-main/documents/docs/guide/images/home_assistatnt配置.png
Executable file
After Width: | Height: | Size: 116 KiB |
BIN
py-xiaozhi-main/documents/docs/guide/images/唤醒词.png
Executable file
After Width: | Height: | Size: 10 KiB |
BIN
py-xiaozhi-main/documents/docs/guide/images/导入ha.png
Executable file
After Width: | Height: | Size: 21 KiB |
BIN
py-xiaozhi-main/documents/docs/guide/images/已注册设备.png
Executable file
After Width: | Height: | Size: 46 KiB |
BIN
py-xiaozhi-main/documents/docs/guide/images/系统界面.png
Executable file
After Width: | Height: | Size: 37 KiB |
BIN
py-xiaozhi-main/documents/docs/guide/images/设备选择.png
Executable file
After Width: | Height: | Size: 44 KiB |
421
py-xiaozhi-main/documents/docs/guide/old_docs/使用文档.md
Executable file
@ -0,0 +1,421 @@
|
||||
---
|
||||
title: 旧版使用文档
|
||||
description: py-xiaozhi项目的旧版使用文档,提供早期版本的使用指南
|
||||
outline: deep
|
||||
---
|
||||
|
||||
# py-xiaozhi使用文档(请认真阅读使用文档)
|
||||
|
||||

|
||||
## 使用介绍
|
||||
- 语音模式分为两种长按对话和自动对话,右下角按钮显示的是当前模式
|
||||
- 长按对话:按住说话松手发送
|
||||
- 自动对话:点击开始对话即可,当界面显示聆听中就表示到你说话了,说完会自行发送
|
||||
- gui模式:
|
||||
- F2 键:长按说话
|
||||
- F3 键:打断对话
|
||||
- cli模式
|
||||
- F2 键:按一次开始自动对话
|
||||
- F3 键:打断对话
|
||||
|
||||
## 配置说明
|
||||
|
||||
### 项目基础配置
|
||||
|
||||
#### 配置文件说明
|
||||
项目使用两种配置方式:初始配置模板和运行时配置文件。
|
||||
|
||||
1. **初始配置模板**
|
||||
- 位置:`/src/utils/config_manager.py`
|
||||
- 作用:提供默认配置模板,首次运行时会自动生成配置文件
|
||||
- 使用场景:首次运行或需要重置配置时修改此文件
|
||||
|
||||
2. **运行时配置文件**
|
||||
- 位置:`/config/config.json`
|
||||
- 作用:存储实际运行时的配置信息
|
||||
- 使用场景:日常使用时修改此文件
|
||||
|
||||
#### 配置项说明
|
||||
- 需要什么加什么配置通过config_manager去获取就行了,参考websocket或iot\things\temperature_sensor.py
|
||||
- 例如获取 "MQTT_INFO"的"endpoint" , 通过这样 `config.get_config("MQTT_INFO.endpoint")`就能拿到**endpoint**
|
||||
```json
|
||||
{
|
||||
"CLIENT_ID": "自动生成的客户端ID",
|
||||
"DEVICE_ID": "设备MAC地址",
|
||||
"NETWORK": {
|
||||
"OTA_VERSION_URL": "OTA更新地址",
|
||||
"WEBSOCKET_URL": "WebSocket服务器地址",
|
||||
"WEBSOCKET_ACCESS_TOKEN": "访问令牌"
|
||||
},
|
||||
"MQTT_INFO": {
|
||||
"endpoint": "MQTT服务器地址",
|
||||
"client_id": "MQTT客户端ID",
|
||||
"username": "MQTT用户名",
|
||||
"password": "MQTT密码",
|
||||
"publish_topic": "发布主题",
|
||||
"subscribe_topic": "订阅主题"
|
||||
},
|
||||
"USE_WAKE_WORD": false, // 是否启用语音唤醒
|
||||
"WAKE_WORDS": [ // 唤醒词列表
|
||||
"小智",
|
||||
"你好小明"
|
||||
],
|
||||
"WAKE_WORD_MODEL_PATH": "./models/vosk-model-small-cn-0.22", // 唤醒模型路径
|
||||
"TEMPERATURE_SENSOR_MQTT_INFO": {
|
||||
"endpoint": "你的Mqtt地址",
|
||||
"port": 1883,
|
||||
"username": "admin",
|
||||
"password": "dtwin@123",
|
||||
"publish_topic": "sensors/temperature/command",
|
||||
"subscribe_topic": "sensors/temperature/device_001/state"
|
||||
},
|
||||
"CAMERA": { // 视觉配置
|
||||
"camera_index": 0,
|
||||
"frame_width": 640,
|
||||
"frame_height": 480,
|
||||
"fps": 30,
|
||||
"Loacl_VL_url": "https://open.bigmodel.cn/api/paas/v4/", // 智普的申请地址 https://open.bigmodel.cn/
|
||||
"VLapi_key": "你的key"
|
||||
}
|
||||
// ...可以添加任意配置
|
||||
}
|
||||
```
|
||||
|
||||
#### 配置修改指南
|
||||
|
||||
1. **首次使用配置**
|
||||
- 直接运行程序,系统会自动生成默认配置文件
|
||||
- 如需修改默认值,可编辑 `config_manager.py` 中的 `DEFAULT_CONFIG`
|
||||
|
||||
2. **更换服务器配置**
|
||||
- 打开 `/config/config.json`
|
||||
- 修改 `NETWORK.WEBSOCKET_URL` 为新的服务器地址
|
||||
- 示例:
|
||||
```json
|
||||
"NETWORK": {
|
||||
"WEBSOCKET_URL": "ws://你的服务器地址:端口号/"
|
||||
}
|
||||
```
|
||||
|
||||
3. **启用语音唤醒**
|
||||
- 修改 `USE_WAKE_WORD` 为 `true`
|
||||
- 可在 `WAKE_WORDS` 数组中添加或修改唤醒词
|
||||
|
||||
#### 注意事项
|
||||
- 修改配置文件后需要重启程序才能生效
|
||||
- WebSocket URL 必须以 `ws://` 或 `wss://` 开头
|
||||
- 首次运行时会自动生成 CLIENT_ID,建议不要手动修改
|
||||
- DEVICE_ID 默认使用设备MAC地址,可按需修改
|
||||
- 配置文件使用 UTF-8 编码,请使用支持 UTF-8 的编辑器修改
|
||||
|
||||
## 启动说明
|
||||
### 系统依赖安装
|
||||
#### Windows
|
||||
1. **安装 FFmpeg**
|
||||
```bash
|
||||
# 方法一:使用 Scoop 安装(推荐)
|
||||
scoop install ffmpeg
|
||||
|
||||
# 方法二:手动安装
|
||||
# 1. 访问 https://github.com/BtbN/FFmpeg-Builds/releases 下载
|
||||
# 2. 解压并将 bin 目录添加到系统 PATH
|
||||
```
|
||||
|
||||
2. **Opus 音频编解码库**
|
||||
- 项目默认会自动引入 opus.dll,无需手动安装
|
||||
- 如遇问题,可将 `/libs/windows/opus.dll` 复制到以下位置之一:
|
||||
- 应用程序目录
|
||||
- `C:\Windows\System32`
|
||||
|
||||
#### Linux (Debian/Ubuntu)
|
||||
```bash
|
||||
# 安装系统依赖
|
||||
sudo apt-get update
|
||||
sudo apt-get install python3-pyaudio portaudio19-dev ffmpeg libopus0 libopus-dev
|
||||
|
||||
# 安装音量控制依赖(以下三选一)
|
||||
# 1. PulseAudio 工具(推荐)
|
||||
sudo apt-get install pulseaudio-utils
|
||||
|
||||
# 2. 或者 ALSA 工具
|
||||
sudo apt-get install alsa-utils
|
||||
|
||||
# 3. 如果需要使用 alsamixer 方式,还需要安装 expect
|
||||
sudo apt-get install alsa-utils expect
|
||||
|
||||
|
||||
sudo apt install build-essential python3-dev
|
||||
```
|
||||
|
||||
#### macOS
|
||||
```bash
|
||||
# 使用 Homebrew 安装系统依赖
|
||||
brew install portaudio opus python-tk ffmpeg gfortran
|
||||
brew upgrade tcl-tk
|
||||
```
|
||||
|
||||
### Python 依赖安装
|
||||
|
||||
#### 方式一:使用 venv(推荐)
|
||||
```bash
|
||||
# 1. 创建虚拟环境
|
||||
python -m venv .venv
|
||||
|
||||
# 2. 激活虚拟环境
|
||||
# Windows
|
||||
.venv\Scripts\activate
|
||||
# Linux/macOS
|
||||
source .venv/bin/activate
|
||||
|
||||
# 3. 安装依赖
|
||||
# Windows/Linux
|
||||
pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple
|
||||
# macOS
|
||||
pip install -r requirements_mac.txt -i https://mirrors.aliyun.com/pypi/simple
|
||||
```
|
||||
|
||||
#### 方式二:使用 Conda
|
||||
```bash
|
||||
# 1. 创建 Conda 环境
|
||||
conda create -n py-xiaozhi python=3.12
|
||||
|
||||
# 2. 激活环境
|
||||
conda activate py-xiaozhi
|
||||
|
||||
# 3. 安装 Conda 特定依赖
|
||||
conda install conda-forge::libopus
|
||||
conda install conda-forge::ffmpeg
|
||||
|
||||
# 4. 安装 Python 依赖
|
||||
# Windows/Linux
|
||||
pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple
|
||||
# macOS
|
||||
pip install -r requirements_mac.txt -i https://mirrors.aliyun.com/pypi/simple
|
||||
```
|
||||
|
||||
### 唤醒词模型
|
||||
|
||||
- [唤醒词模型下载](https://alphacephei.com/vosk/models)
|
||||
- 下载完成后解压放至根目录/models
|
||||
- 默认读取vosk-model-small-cn-0.22小模型
|
||||
- 
|
||||
|
||||
### IoT功能说明
|
||||
|
||||
#### IoT模块结构
|
||||
|
||||
```
|
||||
├── iot # IoT设备相关模块
|
||||
│ ├── things # 具体设备实现目录
|
||||
│ │ ├── lamp.py # 智能灯控制实现
|
||||
│ │ │ └── Lamp # 灯设备类,提供开关、调节亮度、改变颜色等功能
|
||||
│ │ ├── music_player.py # 音乐播放器实现
|
||||
│ │ │ └── MusicPlayer # 音乐播放器类,提供播放、暂停、切换歌曲等功能
|
||||
│ │ └── speaker.py # 音量控制实现
|
||||
│ │ └── Speaker # 扬声器类,提供音量调节、静音等功能
|
||||
│ ├── thing.py # IoT设备基类定义
|
||||
│ │ ├── Thing # 所有IoT设备的抽象基类
|
||||
│ │ ├── Property # 设备属性类,定义设备的可变状态
|
||||
│ │ ├── Action # 设备动作类,定义设备可执行的操作
|
||||
│ │ └── Event # 设备事件类,定义设备可触发的事件
|
||||
│ └── thing_manager.py # IoT设备管理器(统一管理各类设备)
|
||||
│ └── ThingManager # 单例模式实现的设备管理器,负责设备注册、查找和命令分发
|
||||
```
|
||||
|
||||
#### Iot 状态流转
|
||||
```text
|
||||
+----------------+
|
||||
| 用户语音 |
|
||||
| 指令 |
|
||||
+-------+-------+
|
||||
|
|
||||
v
|
||||
+-------+-------+
|
||||
| 语音识别 |
|
||||
| (STT) |
|
||||
+-------+-------+
|
||||
|
|
||||
v
|
||||
+-------+-------+
|
||||
| LLM处理指令 |
|
||||
| |
|
||||
+-------+-------+
|
||||
|
|
||||
v
|
||||
+-------+-------+
|
||||
| 生成物联网命令 |
|
||||
| |
|
||||
+-------+-------+
|
||||
|
|
||||
v
|
||||
+---------------+---------------+
|
||||
| Application接收IoT消息 |
|
||||
| _handle_iot_message() |
|
||||
+---------------+---------------+
|
||||
|
|
||||
v
|
||||
+---------------+---------------+
|
||||
| ThingManager.invoke() |
|
||||
+---------------+---------------+
|
||||
|
|
||||
+------------------+------------------+------------------+
|
||||
| | | |
|
||||
v v v v
|
||||
+----------+-------+ +-------+--------+ +------+---------+ +----+-----------+
|
||||
| Lamp | | Speaker | | MusicPlayer | | CameraVL |
|
||||
| (控制灯设备) | | (控制音量设备) | | (播放音乐设备) | | (摄像头与视觉) |
|
||||
+----------+-------+ +-------+--------+ +------+---------+ +----+-----------+
|
||||
| | | |
|
||||
| | | |
|
||||
| | | |
|
||||
| | | v
|
||||
| | | +------+---------+
|
||||
| | | | Camera.py |
|
||||
| | | | (摄像头控制) |
|
||||
| | | +------+---------+
|
||||
| | | |
|
||||
| | | v
|
||||
| | | +------+---------+
|
||||
| | | | VL.py |
|
||||
| | | | (视觉识别处理) |
|
||||
| | | +------+---------+
|
||||
| | | |
|
||||
+------------------+------------------+------------------+
|
||||
|
|
||||
v
|
||||
+---------------+---------------+
|
||||
| 执行设备操作 |
|
||||
+---------------+---------------+
|
||||
|
|
||||
v
|
||||
+---------------+---------------+
|
||||
| 更新设备状态 |
|
||||
| _update_iot_states() |
|
||||
+---------------+---------------+
|
||||
|
|
||||
v
|
||||
+---------------+---------------+
|
||||
| 发送状态更新到服务器 |
|
||||
| send_iot_states(states) |
|
||||
+---------------+---------------+
|
||||
|
|
||||
v
|
||||
+---------------+---------------+
|
||||
| 服务器更新设备状态 |
|
||||
+---------------+---------------+
|
||||
|
|
||||
v
|
||||
+---------------+---------------+
|
||||
| 返回执行结果给用户 |
|
||||
| (语音或界面反馈) |
|
||||
+-------------------------------+
|
||||
```
|
||||
|
||||
#### IoT设备管理
|
||||
- IoT模块采用灵活的多协议通信架构:
|
||||
- MQTT协议:用于与标准物联网设备通信,如智能灯、空调等
|
||||
- HTTP协议:用于与Web服务交互,如获取在线音乐、调用多模态AI模型等
|
||||
- 可扩展支持其他协议:如WebSocket、TCP等
|
||||
- 支持自动发现和管理IoT设备
|
||||
- 可通过语音命令控制IoT设备,例如:
|
||||
- "查看当前物联网设备"
|
||||
- "打开客厅的灯"
|
||||
- "关闭空调"
|
||||
- "设置温度为26度"
|
||||
- "打开摄像头"
|
||||
- "关闭摄像头"
|
||||
- "识别画面"
|
||||
|
||||
#### 添加新的IoT设备
|
||||
1. 在`src/iot/things`目录下创建新的设备类
|
||||
2. 继承`Thing`基类并实现必要方法
|
||||
3. 在`thing_manager.py`中注册新设备
|
||||
|
||||
### 注意事项
|
||||
1. 确保相应的服务器配置正确且可访问:
|
||||
- MQTT服务器配置(用于物联网设备)
|
||||
- API接口地址(用于HTTP服务)
|
||||
2. 不同协议的设备/服务需实现对应的连接和通信逻辑
|
||||
3. 建议为每个新增设备/服务添加基本的错误处理和重连机制
|
||||
4. 可以通过扩展Thing基类来支持新的通信协议
|
||||
5. 在添加新设备时,建议先进行通信测试,确保连接稳定
|
||||
|
||||
#### 在线音乐配置
|
||||
- 接入在线音源了,无需自行配置默认可用
|
||||
### 运行模式说明
|
||||
#### GUI 模式运行(默认)
|
||||
```bash
|
||||
python main.py
|
||||
```
|
||||
|
||||
|
||||
#### CLI模式运行
|
||||
```bash
|
||||
python main.py --mode cli
|
||||
```
|
||||
|
||||
#### 构建打包
|
||||
|
||||
使用PyInstaller打包为可执行文件:
|
||||
|
||||
```bash
|
||||
# Windows
|
||||
python scripts/build.py
|
||||
|
||||
# macOS
|
||||
python scripts/build.py
|
||||
|
||||
# Linux
|
||||
python scripts/build.py
|
||||
```
|
||||
|
||||
### 注意事项
|
||||
1. 建议使用 Python 3.9.13+ 版本,推荐 3.12
|
||||
2. Windows 用户无需手动安装 opus.dll,项目会自动处理
|
||||
3. 使用 Conda 环境时必须安装 ffmpeg 和 Opus
|
||||
4. 使用 Conda 环境时请勿和esp32-server共用同一个Conda环境,因为服务端websocket依赖版本高于本项目
|
||||
5. 建议使用国内镜像源安装依赖,可以提高下载速度
|
||||
6. macOS 用户需使用专门的 requirements_mac.txt
|
||||
7. 确保系统依赖安装完成后再安装 Python 依赖
|
||||
8. 如若使用xiaozhi-esp32-server作为服务端该项目只能自动对话才有反应
|
||||
9. esp32-server视频部署教程 [新版!小智ai服务端本地部署完整教程,支持DeepSeek接入](https://www.bilibili.com/video/BV1GvQWYZEd2/?share_source=copy_web&vd_source=86370b0cff2da3ab6e3d26eb1cab13d3)
|
||||
10. 音量控制功能需要安装特定依赖,程序会在启动时自动检查并提示缺少的依赖
|
||||
|
||||
### 音量控制功能说明
|
||||
|
||||
本应用支持调整系统音量,根据不同操作系统需要安装不同的依赖:
|
||||
|
||||
1. **Windows**: 使用 pycaw 和 comtypes 控制系统音量
|
||||
2. **macOS**: 使用 applescript 控制系统音量
|
||||
3. **Linux**: 根据系统环境使用 pactl (PulseAudio)、wpctl (PipeWire)、amixer (ALSA) 或 alsamixer 控制音量
|
||||
|
||||
应用程序会在启动时自动检查这些依赖是否已安装。如果缺少依赖,将会显示相应的安装指令。
|
||||
|
||||
#### 音量控制使用方法
|
||||
|
||||
- **GUI模式**: 使用界面上的音量滑块调节音量
|
||||
- **CLI模式**: 使用 `v <音量值>` 命令调节音量,例如 `v 50` 将音量设置为50%
|
||||
|
||||
### 状态流转图
|
||||
|
||||
```
|
||||
+----------------+
|
||||
| |
|
||||
v |
|
||||
+------+ 唤醒词/按钮 +------------+ | +------------+
|
||||
| IDLE | -----------> | CONNECTING | --+-> | LISTENING |
|
||||
+------+ +------------+ +------------+
|
||||
^ |
|
||||
| | 语音识别完成
|
||||
| +------------+ v
|
||||
+--------- | SPEAKING | <-----------------+
|
||||
完成播放 +------------+
|
||||
```
|
||||
|
||||
## 获取帮助
|
||||
如果遇到问题:
|
||||
|
||||
1. 优先查看 docs/异常汇总.md 文档
|
||||
2. 通过 GitHub Issues 提交问题
|
||||
3. 通过 AI 助手寻求帮助
|
||||
4. 联系作者(主页有微信)(请自备 Todesk 链接并说明来意,作者工作日晚上处理)
|
331
py-xiaozhi-main/documents/docs/guide/异常汇总.md
Executable file
@ -0,0 +1,331 @@
|
||||
# 错误问题汇总
|
||||
|
||||
## 1. `Could not find Opus library. Make sure it is installed.`
|
||||
|
||||
### **错误描述**
|
||||
|
||||
```
|
||||
(.venv) C:\Users\Junsen\Desktop\learning\xiaozhi-python>python xiaozhi-python.py
|
||||
Traceback (most recent call last):
|
||||
File "C:\Users\Junsen\Desktop\learning\xiaozhi-python\xiaozhi-python.py", line 5, in <module>
|
||||
import opuslib
|
||||
File "C:\Users\Junsen\Desktop\learning\xiaozhi-python\.venv\lib\site-packages\opuslib\__init__.py", line 19, in <module>
|
||||
from .exceptions import OpusError # NOQA
|
||||
File "C:\Users\Junsen\Desktop\learning\xiaozhi-python\.venv\lib\site-packages\opuslib\exceptions.py", line 10, in <module>
|
||||
import opuslib.api.info
|
||||
File "C:\Users\Junsen\Desktop\learning\xiaozhi-python\.venv\lib\site-packages\opuslib\api\__init__.py", line 20, in <module>
|
||||
raise Exception(
|
||||
Exception: Could not find Opus library. Make sure it is installed.
|
||||
```
|
||||
|
||||
### **解决方案**
|
||||
|
||||
1. **Windows**
|
||||
|
||||
- 下载并安装 Opus 库。
|
||||
- 确保 `opuslib` 相关库正确安装。
|
||||
|
||||
2. **Linux/macOS**
|
||||
|
||||
- 运行以下命令安装 `libopus`:
|
||||
```sh
|
||||
sudo apt-get install libopus-dev # Ubuntu/Debian
|
||||
brew install opus # macOS
|
||||
```
|
||||
|
||||
3. **Python 代码安装**
|
||||
|
||||
```sh
|
||||
pip install opuslib
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. `externally-managed-environment` (macOS)
|
||||
|
||||
### **错误描述**
|
||||
|
||||
```
|
||||
(.venv) huangjunsen@huangjunsendeMac-mini py-xiaozhi % pip install -r requirements_mac.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
|
||||
|
||||
error: externally-managed-environment
|
||||
|
||||
× This environment is externally managed
|
||||
╰─> To install Python packages system-wide, try brew install
|
||||
xyz, where xyz is the package you are trying to
|
||||
install.
|
||||
|
||||
If you wish to install a Python library that isn't in Homebrew,
|
||||
use a virtual environment:
|
||||
|
||||
python3 -m venv path/to/venv
|
||||
source path/to/venv/bin/activate
|
||||
python3 -m pip install xyz
|
||||
|
||||
If you wish to install a Python application that isn't in Homebrew,
|
||||
it may be easiest to use 'pipx install xyz', which will manage a
|
||||
virtual environment for you. You can install pipx with
|
||||
|
||||
brew install pipx
|
||||
|
||||
You may restore the old behavior of pip by passing
|
||||
the '--break-system-packages' flag to pip, or by adding
|
||||
'break-system-packages = true' to your pip.conf file. The latter
|
||||
will permanently disable this error.
|
||||
|
||||
If you disable this error, we STRONGLY recommend that you additionally
|
||||
pass the '--user' flag to pip, or set 'user = true' in your pip.conf
|
||||
file. Failure to do this can result in a broken Homebrew installation.
|
||||
|
||||
Read more about this behavior here: <https://peps.python.org/pep-0668/>
|
||||
|
||||
note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages.
|
||||
hint: See PEP 668 for the detailed specification.
|
||||
```
|
||||
|
||||
### **解决方案**
|
||||
|
||||
1. **使用虚拟环境安装**
|
||||
```sh
|
||||
python3 -m venv my_env
|
||||
source my_env/bin/activate
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
2. **使用 **``** 进行全局安装**
|
||||
```sh
|
||||
brew install pipx
|
||||
pipx install package_name
|
||||
```
|
||||
3. **强制安装(不推荐)**
|
||||
```sh
|
||||
pip install package_name --break-system-packages
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. `WebSocket连接失败: BaseEventLoop.create_connection() got an unexpected keyword argument 'extra_headers'`
|
||||
|
||||
### **错误描述**
|
||||
|
||||
```python
|
||||
# 建立WebSocket连接
|
||||
self.websocket = await websockets.connect(
|
||||
self.WEBSOCKET_URL,
|
||||
extra_headers=headers # 高版本这里改为 additional_headers=headers
|
||||
)
|
||||
```
|
||||
|
||||
### **解决方案**
|
||||
|
||||
- **新版本 **``: `extra_headers` 改为 `additional_headers`。
|
||||
- **旧版本 **``: `additional_headers` 改为 `extra_headers`。
|
||||
|
||||
---
|
||||
|
||||
## 4. `没有找到默认的输入/输出音频设备`
|
||||
|
||||
### **错误描述**
|
||||
|
||||
```
|
||||
AudioCodec - ERROR - 初始化音频设备失败: [Errno -9996] Invalid input device (no default output device)
|
||||
AudioCodec - WARNING - 无法初始化音频设备: [Errno -9996] Invalid input device (no default output device)
|
||||
```
|
||||
|
||||
### **解决方案**
|
||||
|
||||
1. **Windows**:
|
||||
|
||||
- 在 **声音设置** 中启用麦克风和扬声器。
|
||||
|
||||
2. **Linux/macOS**:
|
||||
|
||||
```sh
|
||||
pactl list sources | grep "Name"
|
||||
```
|
||||
|
||||
3. **检查可用音频设备**:
|
||||
|
||||
```python
|
||||
import pyaudio
|
||||
p = pyaudio.PyAudio()
|
||||
for i in range(p.get_device_count()):
|
||||
print(f"设备 {i}: {p.get_device_info_by_index(i)['name']}")
|
||||
```
|
||||
|
||||
4. **手动指定音频设备**:
|
||||
|
||||
```python
|
||||
stream = p.open(format=pyaudio.paInt16, channels=1, rate=16000, input=True, input_device_index=0)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
|
||||
## **5. `ModuleNotFoundError: No module named '_tkinter'` mac m4以下常见 **
|
||||
|
||||
### **错误描述**
|
||||
```
|
||||
(.venv) apple@appledeMac-mini py-xiaozhi % python main.py
|
||||
|
||||
Traceback (most recent call last):
|
||||
File "/Users/apple/Desktop/py-xiaozhi/main.py", line 5, in <module>
|
||||
from src.application import Application
|
||||
File "/Users/apple/Desktop/py-xiaozhi/src/application.py", line 23, in <module>
|
||||
from src.display import gui_display, cli_display
|
||||
File "/Users/apple/Desktop/py-xiaozhi/src/display/gui_display.py", line 2, in <module>
|
||||
import tkinter as tk
|
||||
File "/opt/homebrew/Cellar/python@3.12/3.12.9/Frameworks/Python.framework/Versions/3.12/lib/python3.12/tkinter/__init__.py", line 38, in <module>
|
||||
import _tkinter # If this fails your Python may not be configured for Tk
|
||||
^^^^^^^^^^^^^^^
|
||||
ModuleNotFoundError: No module named '_tkinter'
|
||||
```
|
||||
|
||||
### **解决方案**
|
||||
|
||||
1. **安装 `tcl-tk`**
|
||||
```sh
|
||||
brew upgrade tcl-tk # 一般第一步就可以了
|
||||
```
|
||||
|
||||
2. **检查 Homebrew 的 `tcl-tk` 路径**
|
||||
```sh
|
||||
brew info tcl-tk
|
||||
```
|
||||
|
||||
3. **重新安装 Python,并链接 `tcl-tk`**
|
||||
```sh
|
||||
brew install python-tk
|
||||
```
|
||||
|
||||
4. **手动指定 `Tcl/Tk` 路径(如有必要)**
|
||||
```sh
|
||||
export PATH="/opt/homebrew/opt/tcl-tk/bin:$PATH"
|
||||
export LDFLAGS="-L/opt/homebrew/opt/tcl-tk/lib"
|
||||
export CPPFLAGS="-I/opt/homebrew/opt/tcl-tk/include"
|
||||
```
|
||||
|
||||
5. **重新创建虚拟环境**
|
||||
```sh
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. `导入 opuslib 失败: No module named 'pyaudioop'或'_cffi_backend'`
|
||||
|
||||
### **错误描述**
|
||||
|
||||
```
|
||||
找到opus库文件: D:\xiaozhi\PC\py-xiaozhi-main\libs\windows\opus.dll
|
||||
已添加DLL搜索路径: D:\xiaozhi\PC\py-xiaozhi-main\libs\windows
|
||||
已成功加载 opus.dll: D:\xiaozhi\PC\py-xiaozhi-main\libs\windows\opus.dll
|
||||
导入 opuslib 失败: No module named 'pyaudioop'
|
||||
确保 opus 动态库已正确安装或位于正确的位置
|
||||
```
|
||||
|
||||
或
|
||||
|
||||
```
|
||||
找到opus库文件: D:\xiaozhi\PC\py-xiaozhi-main\libs\windows\opus.dll
|
||||
已添加DLL搜索路径: D:\xiaozhi\PC\py-xiaozhi-main\libs\windows
|
||||
已成功加载 opus.dll: D:\xiaozhi\PC\py-xiaozhi-main\libs\windows\opus.dll
|
||||
导入 opuslib 失败: No module named '_cffi_backend'
|
||||
请确保 opus 动态库已正确安装或位于正确的位置
|
||||
```
|
||||
|
||||
### **解决方案**
|
||||
|
||||
1. **Python版本兼容性问题**
|
||||
- 这个错误通常与Python版本有关,尤其是Python 3.13版本
|
||||
- 建议使用Python 3.9-3.12版本
|
||||
|
||||
2. **重新安装cffi**
|
||||
```sh
|
||||
pip uninstall cffi
|
||||
pip install cffi
|
||||
```
|
||||
|
||||
3. **opus.dll放置**
|
||||
- 确保已将opus.dll放在正确位置(项目根目录和System32目录)
|
||||
```sh
|
||||
# 检查是否已复制到这些位置
|
||||
C:\Windows\System32\opus.dll
|
||||
项目根目录\opus.dll
|
||||
项目根目录\libs\windows\opus.dll
|
||||
```
|
||||
|
||||
4. **安装pyaudioop支持库**
|
||||
- 对于'pyaudioop'错误,尝试降级Python版本或安装相关依赖
|
||||
```sh
|
||||
pip install pyaudio
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
|
||||
## 8. `error: subprocess-exited-with-error`(安装 `numpy` 失败)
|
||||
|
||||
### **错误描述**
|
||||
```
|
||||
Collecting numpy==2.0.2 (from -r requirements.txt (line 8))
|
||||
Using cached https://mirrors.aliyun.com/pypi/packages/a9/75/10dd1f8116a8b796cb2c737b674e02d02e80454bda953fa7e65d8c12b016/numpy-2.0.2.tar.gz (18.9 MB)
|
||||
Installing build dependencies ... done
|
||||
Getting requirements to build wheel ... done
|
||||
Installing backend dependencies ... done
|
||||
Preparing metadata (pyproject.toml) ... error
|
||||
error: subprocess-exited-with-error
|
||||
|
||||
× Preparing metadata (pyproject.toml) did not run successfully.
|
||||
│ exit code: 1
|
||||
╰─> [21 lines of output]
|
||||
...
|
||||
WARNING: Failed to activate VS environment: Could not parse vswhere.exe output
|
||||
ERROR: Unknown compiler(s): [['icl'], ['cl'], ['cc'], ['gcc'], ['clang'], ['clang-cl'], ['pgcc']]
|
||||
The following exception(s) were encountered:
|
||||
Running `icl ""` gave "[WinError 2] 系统找不到指定的文件。"
|
||||
Running `cl /?` gave "[WinError 2] 系统找不到指定的文件。"
|
||||
Running `cc --version` gave "[WinError 2] 系统找不到指定的文件。"
|
||||
Running `gcc --version` gave "[WinError 2] 系统找不到指定的文件。"
|
||||
Running `clang --version` gave "[WinError 2] 系统找不到指定的文件。"
|
||||
Running `clang-cl /?` gave "[WinError 2] 系统找不到指定的文件。"
|
||||
Running `pgcc --version` gave "[WinError 2] 系统找不到指定的文件。"
|
||||
|
||||
note: This error originates from a subprocess, and is likely not a problem with pip.
|
||||
error: metadata-generation-failed
|
||||
|
||||
× Encountered error while generating package metadata.
|
||||
╰─> See above for output.
|
||||
|
||||
note: This is an issue with the package mentioned above, not pip.
|
||||
hint: See above for details.
|
||||
```
|
||||
|
||||
### **解决方案**
|
||||
- 建议python版本在 3.9 - 3.12
|
||||
|
||||
1. **确保 `numpy` 版本兼容**
|
||||
|
||||
`numpy==2.0.2` 可能存在构建问题,建议尝试安装较稳定的版本:
|
||||
```sh
|
||||
pip install numpy==1.24.3
|
||||
```
|
||||
|
||||
如果你不需要特定版本,可以安装最新稳定版本:
|
||||
```sh
|
||||
pip install numpy
|
||||
```
|
||||
|
||||
2. **安装编译工具**
|
||||
|
||||
Windows用户可能需要安装Visual C++ Build Tools:
|
||||
```sh
|
||||
# 安装Microsoft C++ Build Tools
|
||||
# 下载并安装: https://visualstudio.microsoft.com/visual-cpp-build-tools/
|
||||
```
|
||||
|
||||
3. **使用预编译的轮子**
|
||||
```sh
|
||||
pip install --only-binary=numpy numpy
|
||||
```
|