mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-22 07:03:53 +08:00
@@ -4,13 +4,14 @@ from config.settings import load_config, check_config_file
|
||||
from core.websocket_server import WebSocketServer
|
||||
from manager.http_server import WebUI
|
||||
from aiohttp import web
|
||||
from core.utils.util import get_local_ip
|
||||
from core.utils.util import get_local_ip, check_ffmpeg_installed
|
||||
|
||||
TAG = __name__
|
||||
|
||||
|
||||
async def main():
|
||||
check_config_file()
|
||||
check_ffmpeg_installed()
|
||||
logger = setup_logging()
|
||||
config = load_config()
|
||||
|
||||
|
||||
@@ -16,29 +16,37 @@ async def isLLMWantToFinish(last_text):
|
||||
|
||||
|
||||
async def sendAudioMessage(conn, audios, text):
|
||||
# 发送 tts.start
|
||||
# 发送句子开始消息
|
||||
if text == conn.tts_first_text:
|
||||
logger.bind(tag=TAG).info(f"发送第一段语音: {text}")
|
||||
conn.tts_start_speak_time = time.time()
|
||||
conn.tts_start_speak_time = time.perf_counter()
|
||||
await send_tts_message(conn, "sentence_start", text)
|
||||
|
||||
# 发送音频数据
|
||||
frame_duration = 60 # 初始帧持续时间(毫秒)
|
||||
start_time = time.time() # 记录开始时间
|
||||
for idx, opus_packet in enumerate(audios):
|
||||
# 初始化流控参数
|
||||
frame_duration = 60 # 毫秒
|
||||
start_time = time.perf_counter() # 使用高精度计时器
|
||||
play_position = 0 # 已播放的时长(毫秒)
|
||||
|
||||
for opus_packet in audios:
|
||||
if conn.client_abort:
|
||||
return
|
||||
|
||||
# 计算当前包的预期发送时间
|
||||
expected_time = start_time + idx * (frame_duration / 1000)
|
||||
current_time = time.time()
|
||||
# 如果未到预期时间则等待差值
|
||||
if current_time < expected_time:
|
||||
await asyncio.sleep(expected_time - current_time)
|
||||
expected_time = start_time + (play_position / 1000)
|
||||
current_time = time.perf_counter()
|
||||
|
||||
# 等待直到预期时间
|
||||
delay = expected_time - current_time
|
||||
if delay > 0:
|
||||
await asyncio.sleep(delay)
|
||||
|
||||
# 发送音频包
|
||||
await conn.websocket.send(opus_packet)
|
||||
|
||||
play_position += frame_duration # 更新播放位置
|
||||
await send_tts_message(conn, "sentence_end", text)
|
||||
# 发送结束消息(如果是最后一个文本)
|
||||
if conn.llm_finish_task and text == conn.tts_last_text:
|
||||
await send_tts_message(conn, 'stop')
|
||||
await send_tts_message(conn, 'stop', None)
|
||||
if await isLLMWantToFinish(text):
|
||||
await conn.close()
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import re
|
||||
import json
|
||||
import yaml
|
||||
import socket
|
||||
import subprocess
|
||||
|
||||
|
||||
def get_project_dir():
|
||||
@@ -114,3 +115,29 @@ def check_password(password):
|
||||
|
||||
# 如果满足所有条件,则返回True
|
||||
return True
|
||||
|
||||
def check_ffmpeg_installed():
|
||||
ffmpeg_installed = False
|
||||
try:
|
||||
# 执行ffmpeg -version命令,并捕获输出
|
||||
result = subprocess.run(
|
||||
['ffmpeg', '-version'],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
text=True,
|
||||
check=True # 如果返回码非零则抛出异常
|
||||
)
|
||||
# 检查输出中是否包含版本信息(可选)
|
||||
output = result.stdout + result.stderr
|
||||
if 'ffmpeg version' in output.lower():
|
||||
ffmpeg_installed = True
|
||||
return False
|
||||
except (subprocess.CalledProcessError, FileNotFoundError):
|
||||
# 命令执行失败或未找到
|
||||
ffmpeg_installed = False
|
||||
if not ffmpeg_installed:
|
||||
error_msg = "您的电脑还没正确安装ffmpeg\n"
|
||||
error_msg += "\n建议您:\n"
|
||||
error_msg += "1、按照项目的安装文档,正确进入conda环境\n"
|
||||
error_msg += "2、查阅安装文档,如何在conda环境中安装ffmpeg\n"
|
||||
raise ValueError(error_msg)
|
||||
+20
-3
@@ -159,14 +159,31 @@ poetry run python app.py
|
||||
本项目使用`conda`管理依赖环境。如果不方便安装`conda`,需要根据实际的操作系统安装好`libopus`和`ffmpeg`。
|
||||
如果确定使用`conda`,则安装好后,开始执行以下命令。
|
||||
|
||||
重要提示!windows 用户,可以通过安装`Anaconda`来管理环境。安装好`Anaconda`后,在`开始`那里搜索`anaconda`相关的关键词,
|
||||
找到`Anaconda Prpmpt`,使用管理员身份运行它。如下图。
|
||||
|
||||

|
||||
|
||||
运行之后,如果你能看到命令行窗口前面有一个(base)字样,说明你成功进入了`conda`环境。那么你就可以执行以下命令了。
|
||||
|
||||

|
||||
|
||||
```
|
||||
conda remove -n xiaozhi-esp32-server --all -y
|
||||
conda create -n xiaozhi-esp32-server python=3.10 -y
|
||||
conda activate xiaozhi-esp32-server
|
||||
conda install conda-forge::libopus -y
|
||||
conda install conda-forge::ffmpeg -y
|
||||
|
||||
# 添加清华源通道
|
||||
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main
|
||||
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free
|
||||
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge
|
||||
|
||||
conda install libopus -y
|
||||
conda install ffmpeg -y
|
||||
```
|
||||
|
||||
请注意,以上命令,不是一股脑执行就成功的,你需要一步步执行,每一步执行完后,都检查一下输出的日志,查看是否成功。
|
||||
|
||||
## 2.安装本项目依赖
|
||||
|
||||
你先要下载本项目源码,源码可以通过`git clone`命令下载,如果你不熟悉`git clone`命令。
|
||||
@@ -179,7 +196,7 @@ conda install conda-forge::ffmpeg -y
|
||||
你需要把它重命名成`xiaozhi-esp32-server`,好了请记住这个目录,我们暂且称它为`项目目录`。
|
||||
|
||||
```
|
||||
# 使用dos或者终端,进入到你的项目目录,执行以下命令
|
||||
# 继续使用conda环境,进入到你的项目目录,执行以下命令
|
||||
conda activate xiaozhi-esp32-server
|
||||
pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/
|
||||
pip install -r requirements.txt
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 781 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 588 KiB |
Reference in New Issue
Block a user