mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-22 07:03:53 +08:00
@@ -0,0 +1,46 @@
|
||||
name: Docker Image CI
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*.*.*' # 只在以 v 开头的标签推送时触发,例如 v1.0.0
|
||||
|
||||
jobs:
|
||||
release:
|
||||
name: Release Docker image
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
packages: write
|
||||
contents: write
|
||||
id-token: write
|
||||
issues: write
|
||||
|
||||
steps:
|
||||
- name: Check out the repo
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to the GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.TOKEN }}
|
||||
|
||||
- name: Extract version from tag
|
||||
id: get_version
|
||||
run: |
|
||||
echo "VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
|
||||
|
||||
- name: Build and push Docker image
|
||||
id: build_push
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
tags: |
|
||||
ghcr.io/${{ github.repository }}:${{ env.VERSION }}
|
||||
ghcr.io/${{ github.repository }}:latest
|
||||
platforms: linux/amd64,linux/arm64
|
||||
+30
-26
@@ -1,46 +1,50 @@
|
||||
# 第一阶段:前端构建
|
||||
FROM node:18 AS frontend-builder
|
||||
|
||||
FROM kalicyh/node:v18-alpine AS frontend-builder
|
||||
|
||||
WORKDIR /app/ZhiKongTaiWeb
|
||||
|
||||
RUN corepack enable && yarn config set registry https://registry.npmmirror.com
|
||||
# RUN corepack enable && yarn config set registry https://registry.npmmirror.com
|
||||
|
||||
COPY ZhiKongTaiWeb/package.json ZhiKongTaiWeb/yarn.lock ./
|
||||
|
||||
RUN mkdir node_modules && yarn install --frozen-lockfile
|
||||
RUN yarn install --frozen-lockfile
|
||||
|
||||
COPY ZhiKongTaiWeb .
|
||||
RUN yarn build
|
||||
|
||||
# 第二阶段:构建 Python 依赖
|
||||
FROM ccr.ccs.tencentyun.com/kalicyh/poetry:v3.10_latest AS builder
|
||||
|
||||
FROM kalicyh/poetry:v3.10_xiaozhi AS builder
|
||||
|
||||
WORKDIR /app
|
||||
COPY pyproject.toml poetry.lock /app/
|
||||
|
||||
# 同时拷贝本地环境.venv
|
||||
COPY . .
|
||||
# 检查是否有缺失
|
||||
RUN poetry install --no-root
|
||||
|
||||
# 第三阶段:生产镜像
|
||||
FROM python:3.10-slim
|
||||
|
||||
WORKDIR /opt/xiaozhi-esp32-server
|
||||
|
||||
# 使用清华源加速apt安装
|
||||
RUN rm -rf /etc/apt/sources.list.d/* && \
|
||||
echo "deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm main contrib non-free non-free-firmware" > /etc/apt/sources.list && \
|
||||
echo "deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm-updates main contrib non-free non-free-firmware" >> /etc/apt/sources.list && \
|
||||
echo "deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm-backports main contrib non-free non-free-firmware" >> /etc/apt/sources.list && \
|
||||
echo "deb https://mirrors.tuna.tsinghua.edu.cn/debian-security bookworm-security main contrib non-free non-free-firmware" >> /etc/apt/sources.list && \
|
||||
apt-get update && \
|
||||
apt-get install -y --no-install-recommends libopus0 ffmpeg && \
|
||||
apt-get clean
|
||||
# 使用清华源加速apt安装,该镜像内置所以注释
|
||||
# RUN rm -rf /etc/apt/sources.list.d/* && \
|
||||
# echo "deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm main contrib non-free non-free-firmware" > /etc/apt/sources.list && \
|
||||
# echo "deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm-updates main contrib non-free non-free-firmware" >> /etc/apt/sources.list && \
|
||||
# echo "deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm-backports main contrib non-free non-free-firmware" >> /etc/apt/sources.list && \
|
||||
# echo "deb https://mirrors.tuna.tsinghua.edu.cn/debian-security bookworm-security main contrib non-free non-free-firmware" >> /etc/apt/sources.list && \
|
||||
# apt-get update && \
|
||||
# apt-get install -y --no-install-recommends libopus0 ffmpeg && \
|
||||
# apt-get clean
|
||||
|
||||
# 从构建阶段复制虚拟环境和前端构建产物
|
||||
COPY --from=builder /app/.venv /opt/venv
|
||||
COPY --from=frontend-builder /app/ZhiKongTaiWeb/dist /opt/xiaozhi-esp32-server/manager/static/webui
|
||||
# 设置虚拟环境路径
|
||||
ENV PATH="/opt/venv/bin:$PATH"
|
||||
COPY --from=frontend-builder /app/ZhiKongTaiWeb/dist /app/manager/static/webui
|
||||
|
||||
# 复制应用代码
|
||||
COPY . .
|
||||
# 下载模型文件(断点续传 + 自动重试)
|
||||
RUN mkdir -p /app/model/SenseVoiceSmall && \
|
||||
wget -O /app/model/SenseVoiceSmall/model.pt -c --tries=5 --waitretry=5 \
|
||||
https://modelscope.cn/models/iic/SenseVoiceSmall/resolve/master/model.pt
|
||||
|
||||
# 设置虚拟环境路径
|
||||
ENV PATH="/app/.venv/bin:$PATH"
|
||||
|
||||
# 启动应用
|
||||
CMD ["python", "app.py"]
|
||||
ENTRYPOINT ["poetry", "run", "python"]
|
||||
CMD ["app.py"]
|
||||
@@ -4,7 +4,9 @@
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"dev": "concurrently -n 'Frontend,Backend' -c 'blue,green' 'yarn run dev:ui' 'npm run dev:api'",
|
||||
"dev:ui": "vite",
|
||||
"dev:api": "cd .. && poetry run python manager/http_server.py",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
@@ -15,6 +17,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^5.1.4",
|
||||
"concurrently": "^9.1.2",
|
||||
"vite": "^5.4.8"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -337,6 +337,18 @@
|
||||
resolved "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.13.tgz#87b309a6379c22b926e696893237826f64339b6f"
|
||||
integrity sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==
|
||||
|
||||
ansi-regex@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
|
||||
integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
|
||||
|
||||
ansi-styles@^4.0.0, ansi-styles@^4.1.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
|
||||
integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
|
||||
dependencies:
|
||||
color-convert "^2.0.1"
|
||||
|
||||
asynckit@^0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
|
||||
@@ -359,6 +371,35 @@ call-bind-apply-helpers@^1.0.1:
|
||||
es-errors "^1.3.0"
|
||||
function-bind "^1.1.2"
|
||||
|
||||
chalk@^4.1.2:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
|
||||
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
|
||||
dependencies:
|
||||
ansi-styles "^4.1.0"
|
||||
supports-color "^7.1.0"
|
||||
|
||||
cliui@^8.0.1:
|
||||
version "8.0.1"
|
||||
resolved "https://registry.npmmirror.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa"
|
||||
integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==
|
||||
dependencies:
|
||||
string-width "^4.2.0"
|
||||
strip-ansi "^6.0.1"
|
||||
wrap-ansi "^7.0.0"
|
||||
|
||||
color-convert@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
|
||||
integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
|
||||
dependencies:
|
||||
color-name "~1.1.4"
|
||||
|
||||
color-name@~1.1.4:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
|
||||
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
||||
|
||||
combined-stream@^1.0.8:
|
||||
version "1.0.8"
|
||||
resolved "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
|
||||
@@ -366,6 +407,19 @@ combined-stream@^1.0.8:
|
||||
dependencies:
|
||||
delayed-stream "~1.0.0"
|
||||
|
||||
concurrently@^9.1.2:
|
||||
version "9.1.2"
|
||||
resolved "https://registry.npmmirror.com/concurrently/-/concurrently-9.1.2.tgz#22d9109296961eaee773e12bfb1ce9a66bc9836c"
|
||||
integrity sha512-H9MWcoPsYddwbOGM6difjVwVZHl63nwMEwDJG/L7VGtuaJhb12h2caPG2tVPWs7emuYix252iGfqOyrz1GczTQ==
|
||||
dependencies:
|
||||
chalk "^4.1.2"
|
||||
lodash "^4.17.21"
|
||||
rxjs "^7.8.1"
|
||||
shell-quote "^1.8.1"
|
||||
supports-color "^8.1.1"
|
||||
tree-kill "^1.2.2"
|
||||
yargs "^17.7.2"
|
||||
|
||||
csstype@^3.1.3:
|
||||
version "3.1.3"
|
||||
resolved "https://registry.npmmirror.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81"
|
||||
@@ -385,6 +439,11 @@ dunder-proto@^1.0.1:
|
||||
es-errors "^1.3.0"
|
||||
gopd "^1.2.0"
|
||||
|
||||
emoji-regex@^8.0.0:
|
||||
version "8.0.0"
|
||||
resolved "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
|
||||
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
|
||||
|
||||
entities@^4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.npmmirror.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48"
|
||||
@@ -446,6 +505,11 @@ esbuild@^0.21.3:
|
||||
"@esbuild/win32-ia32" "0.21.5"
|
||||
"@esbuild/win32-x64" "0.21.5"
|
||||
|
||||
escalade@^3.1.1:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.npmmirror.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5"
|
||||
integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==
|
||||
|
||||
estree-walker@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac"
|
||||
@@ -476,6 +540,11 @@ function-bind@^1.1.2:
|
||||
resolved "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c"
|
||||
integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==
|
||||
|
||||
get-caller-file@^2.0.5:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.npmmirror.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
|
||||
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
|
||||
|
||||
get-intrinsic@^1.2.6:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.2.7.tgz#dcfcb33d3272e15f445d15124bc0a216189b9044"
|
||||
@@ -505,6 +574,11 @@ gopd@^1.2.0:
|
||||
resolved "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1"
|
||||
integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==
|
||||
|
||||
has-flag@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
|
||||
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
|
||||
|
||||
has-symbols@^1.0.3, has-symbols@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338"
|
||||
@@ -524,6 +598,16 @@ hasown@^2.0.2:
|
||||
dependencies:
|
||||
function-bind "^1.1.2"
|
||||
|
||||
is-fullwidth-code-point@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
|
||||
integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
|
||||
|
||||
lodash@^4.17.21:
|
||||
version "4.17.21"
|
||||
resolved "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||
|
||||
magic-string@^0.30.11:
|
||||
version "0.30.17"
|
||||
resolved "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.17.tgz#450a449673d2460e5bbcfba9a61916a1714c7453"
|
||||
@@ -572,6 +656,11 @@ proxy-from-env@^1.1.0:
|
||||
resolved "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
|
||||
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
|
||||
|
||||
require-directory@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.npmmirror.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
|
||||
integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==
|
||||
|
||||
rollup@^4.20.0:
|
||||
version "4.34.7"
|
||||
resolved "https://registry.npmmirror.com/rollup/-/rollup-4.34.7.tgz#e00d8550688a616a3481c6446bb688d4c753ba8f"
|
||||
@@ -600,11 +689,63 @@ rollup@^4.20.0:
|
||||
"@rollup/rollup-win32-x64-msvc" "4.34.7"
|
||||
fsevents "~2.3.2"
|
||||
|
||||
rxjs@^7.8.1:
|
||||
version "7.8.1"
|
||||
resolved "https://registry.npmmirror.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543"
|
||||
integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==
|
||||
dependencies:
|
||||
tslib "^2.1.0"
|
||||
|
||||
shell-quote@^1.8.1:
|
||||
version "1.8.2"
|
||||
resolved "https://registry.npmmirror.com/shell-quote/-/shell-quote-1.8.2.tgz#d2d83e057959d53ec261311e9e9b8f51dcb2934a"
|
||||
integrity sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==
|
||||
|
||||
source-map-js@^1.2.0, source-map-js@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46"
|
||||
integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==
|
||||
|
||||
string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
|
||||
version "4.2.3"
|
||||
resolved "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
||||
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
||||
dependencies:
|
||||
emoji-regex "^8.0.0"
|
||||
is-fullwidth-code-point "^3.0.0"
|
||||
strip-ansi "^6.0.1"
|
||||
|
||||
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
|
||||
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
||||
dependencies:
|
||||
ansi-regex "^5.0.1"
|
||||
|
||||
supports-color@^7.1.0:
|
||||
version "7.2.0"
|
||||
resolved "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
|
||||
integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
|
||||
dependencies:
|
||||
has-flag "^4.0.0"
|
||||
|
||||
supports-color@^8.1.1:
|
||||
version "8.1.1"
|
||||
resolved "https://registry.npmmirror.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c"
|
||||
integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==
|
||||
dependencies:
|
||||
has-flag "^4.0.0"
|
||||
|
||||
tree-kill@^1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.npmmirror.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc"
|
||||
integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==
|
||||
|
||||
tslib@^2.1.0:
|
||||
version "2.8.1"
|
||||
resolved "https://registry.npmmirror.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f"
|
||||
integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==
|
||||
|
||||
vite@^5.4.8:
|
||||
version "5.4.14"
|
||||
resolved "https://registry.npmmirror.com/vite/-/vite-5.4.14.tgz#ff8255edb02134df180dcfca1916c37a6abe8408"
|
||||
@@ -633,3 +774,35 @@ vue@^3.5.10:
|
||||
"@vue/runtime-dom" "3.5.13"
|
||||
"@vue/server-renderer" "3.5.13"
|
||||
"@vue/shared" "3.5.13"
|
||||
|
||||
wrap-ansi@^7.0.0:
|
||||
version "7.0.0"
|
||||
resolved "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
|
||||
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
|
||||
dependencies:
|
||||
ansi-styles "^4.0.0"
|
||||
string-width "^4.1.0"
|
||||
strip-ansi "^6.0.0"
|
||||
|
||||
y18n@^5.0.5:
|
||||
version "5.0.8"
|
||||
resolved "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
|
||||
integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
|
||||
|
||||
yargs-parser@^21.1.1:
|
||||
version "21.1.1"
|
||||
resolved "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35"
|
||||
integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==
|
||||
|
||||
yargs@^17.7.2:
|
||||
version "17.7.2"
|
||||
resolved "https://registry.npmmirror.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269"
|
||||
integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==
|
||||
dependencies:
|
||||
cliui "^8.0.1"
|
||||
escalade "^3.1.1"
|
||||
get-caller-file "^2.0.5"
|
||||
require-directory "^2.1.1"
|
||||
string-width "^4.2.3"
|
||||
y18n "^5.0.5"
|
||||
yargs-parser "^21.1.1"
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ def setup_logging(log_dir='tmp', data_dir='data'):
|
||||
|
||||
# 设置日志格式,时间、日志级别、标签、消息
|
||||
log_format = (
|
||||
"<green>{time:YYYY-MM-DD HH:mm:ss}</green>"
|
||||
# "<green>{time:YYYY-MM-DD HH:mm:ss}</green>"
|
||||
"[<light-blue>{extra[tag]}</light-blue>]"
|
||||
" - <level>{level}</level> - "
|
||||
"<light-green>{message}</light-green>"
|
||||
|
||||
@@ -172,21 +172,12 @@ class PrivateConfig:
|
||||
# 判断存在私有配置,并且self.device_id在私有配置中
|
||||
if not self.private_config:
|
||||
self.logger.bind(tag=TAG).error("Private config not found for device_id: {}", self.device_id)
|
||||
return None, None, None, None
|
||||
return None, None
|
||||
|
||||
"""创建私有处理模块实例"""
|
||||
config = self.private_config
|
||||
selected_modules = config['selected_module']
|
||||
return (
|
||||
vad.create_instance(
|
||||
selected_modules["VAD"],
|
||||
config["VAD"][selected_modules["VAD"]]
|
||||
),
|
||||
asr.create_instance(
|
||||
selected_modules["ASR"],
|
||||
config["ASR"][selected_modules["ASR"]],
|
||||
self.default_config.get("delete_audio", True) # Using default_config for global settings
|
||||
),
|
||||
llm.create_instance(
|
||||
selected_modules["LLM"]
|
||||
if not 'type' in config["LLM"][selected_modules["LLM"]]
|
||||
|
||||
+2
-4
@@ -108,10 +108,8 @@ class ConnectionHandler:
|
||||
if self.is_device_verified:
|
||||
await self.private_config.update_last_chat_time()
|
||||
|
||||
vad, asr, llm, tts = self.private_config.create_private_instances()
|
||||
if all([vad, asr, llm, tts]):
|
||||
self.vad = vad
|
||||
self.asr = asr
|
||||
llm, tts = self.private_config.create_private_instances()
|
||||
if all([llm, tts]):
|
||||
self.llm = llm
|
||||
self.tts = tts
|
||||
self.logger.bind(tag=TAG).info(f"Loaded private config and instances for device {device_id}")
|
||||
|
||||
@@ -2,7 +2,7 @@ import asyncio
|
||||
from config.logger import setup_logging
|
||||
import os
|
||||
import numpy as np
|
||||
import opuslib
|
||||
import opuslib_next
|
||||
from pydub import AudioSegment
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
@@ -58,7 +58,7 @@ class TTSProviderBase(ABC):
|
||||
raw_data = audio.raw_data
|
||||
|
||||
# 初始化Opus编码器
|
||||
encoder = opuslib.Encoder(16000, 1, opuslib.APPLICATION_AUDIO)
|
||||
encoder = opuslib_next.Encoder(16000, 1, opuslib_next.APPLICATION_AUDIO)
|
||||
|
||||
# 编码参数
|
||||
frame_duration = 60 # 60ms per frame
|
||||
|
||||
+29
-11
@@ -1,18 +1,36 @@
|
||||
import time
|
||||
import wave
|
||||
import os
|
||||
import sys
|
||||
import io
|
||||
from abc import ABC, abstractmethod
|
||||
from config.logger import setup_logging
|
||||
from typing import Optional, Tuple, List
|
||||
import uuid
|
||||
|
||||
import opuslib
|
||||
import opuslib_next
|
||||
from funasr import AutoModel
|
||||
from funasr.utils.postprocess_utils import rich_transcription_postprocess
|
||||
|
||||
TAG = __name__
|
||||
logger = setup_logging()
|
||||
|
||||
# 捕获标准输出
|
||||
class CaptureOutput:
|
||||
def __enter__(self):
|
||||
self._output = io.StringIO()
|
||||
self._original_stdout = sys.stdout
|
||||
sys.stdout = self._output
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
sys.stdout = self._original_stdout
|
||||
self.output = self._output.getvalue()
|
||||
self._output.close()
|
||||
|
||||
# 将捕获到的内容通过 logger 输出
|
||||
if self.output:
|
||||
logger.bind(tag=TAG).info(self.output.strip())
|
||||
|
||||
class ASR(ABC):
|
||||
@abstractmethod
|
||||
def save_audio_to_file(self, opus_data: List[bytes], session_id: str) -> str:
|
||||
@@ -33,28 +51,28 @@ class FunASR(ASR):
|
||||
|
||||
# 确保输出目录存在
|
||||
os.makedirs(self.output_dir, exist_ok=True)
|
||||
|
||||
self.model = AutoModel(
|
||||
model=self.model_dir,
|
||||
vad_kwargs={"max_single_segment_time": 30000},
|
||||
disable_update=True,
|
||||
hub="hf"
|
||||
# device="cuda:0", # 启用GPU加速
|
||||
)
|
||||
with CaptureOutput():
|
||||
self.model = AutoModel(
|
||||
model=self.model_dir,
|
||||
vad_kwargs={"max_single_segment_time": 30000},
|
||||
disable_update=True,
|
||||
hub="hf"
|
||||
# device="cuda:0", # 启用GPU加速
|
||||
)
|
||||
|
||||
def save_audio_to_file(self, opus_data: List[bytes], session_id: str) -> str:
|
||||
"""将Opus音频数据解码并保存为WAV文件"""
|
||||
file_name = f"asr_{session_id}_{uuid.uuid4()}.wav"
|
||||
file_path = os.path.join(self.output_dir, file_name)
|
||||
|
||||
decoder = opuslib.Decoder(16000, 1) # 16kHz, 单声道
|
||||
decoder = opuslib_next.Decoder(16000, 1) # 16kHz, 单声道
|
||||
pcm_data = []
|
||||
|
||||
for opus_packet in opus_data:
|
||||
try:
|
||||
pcm_frame = decoder.decode(opus_packet, 960) # 960 samples = 60ms
|
||||
pcm_data.append(pcm_frame)
|
||||
except opuslib.OpusError as e:
|
||||
except opuslib_next.OpusError as e:
|
||||
logger.bind(tag=TAG).error(f"Opus解码错误: {e}", exc_info=True)
|
||||
|
||||
with wave.open(file_path, "wb") as wf:
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
from abc import ABC, abstractmethod
|
||||
from config.logger import setup_logging
|
||||
import opuslib
|
||||
import opuslib_next
|
||||
import time
|
||||
import numpy as np
|
||||
import torch
|
||||
@@ -24,7 +24,7 @@ class SileroVAD(VAD):
|
||||
force_reload=False)
|
||||
(get_speech_timestamps, _, _, _, _) = self.utils
|
||||
|
||||
self.decoder = opuslib.Decoder(16000, 1)
|
||||
self.decoder = opuslib_next.Decoder(16000, 1)
|
||||
self.vad_threshold = config.get("threshold")
|
||||
self.silence_threshold_ms = config.get("min_silence_duration_ms")
|
||||
|
||||
@@ -59,7 +59,7 @@ class SileroVAD(VAD):
|
||||
conn.client_have_voice_last_time = time.time() * 1000
|
||||
|
||||
return client_have_voice
|
||||
except opuslib.OpusError as e:
|
||||
except opuslib_next.OpusError as e:
|
||||
logger.bind(tag=TAG).info(f"解码错误: {e}")
|
||||
except Exception as e:
|
||||
logger.bind(tag=TAG).error(f"Error processing audio packet: {e}")
|
||||
|
||||
+3
-2
@@ -1,11 +1,12 @@
|
||||
services:
|
||||
xiaozhi-esp32-server:
|
||||
image: ccr.ccs.tencentyun.com/xinnan/xiaozhi-esp32-server:latest
|
||||
image: ghcr.io/kalicyh/xiaozhi-esp32-server:latest
|
||||
container_name: xiaozhi-esp32-server
|
||||
restart: always
|
||||
#security_opt:
|
||||
# - seccomp:unconfined
|
||||
ports:
|
||||
- "8000:8000"
|
||||
- "8002:8002"
|
||||
volumes:
|
||||
- ./.config.yaml:/opt/xiaozhi-esp32-server/config.yaml
|
||||
- ./data:/app/data
|
||||
@@ -105,7 +105,7 @@ docker run -it --name xiaozhi-env --restart always --security-opt seccomp:unconf
|
||||
-p 8000:8000 \
|
||||
-p 8002:8002 \
|
||||
-v ./:/app \
|
||||
ccr.ccs.tencentyun.com/kalicyh/poetry:v3.10_latest
|
||||
kalicyh/poetry:v3.10_latest
|
||||
```
|
||||
|
||||
然后就和正常开发一样了
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
# 本地源码运行
|
||||
|
||||
## 1.安装基础环境
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
@@ -1,27 +1,28 @@
|
||||
<!doctype html>
|
||||
<html lang="en" style="height: 100%;">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>智控台</title>
|
||||
<!doctype html>
|
||||
<html lang="en" style="height: 100%;">
|
||||
<head>
|
||||
<meta charset="UTF-8"/>
|
||||
<link rel="icon" href="/favicon.ico"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<title>智控台</title>
|
||||
<style>
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
#app {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
<script type="module" crossorigin src="/assets/index-CvO82KVk.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-_IjUUKjO.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
</html>
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#app {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
<script type="module" crossorigin src="/assets/index-DF7ROAy9.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-D_oCZVZF.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
||||
</body>
|
||||
|
||||
Generated
+9
-668
File diff suppressed because it is too large
Load Diff
+1
-6
@@ -11,7 +11,6 @@ pyyml = "0.0.2"
|
||||
torch = "2.2.2"
|
||||
silero-vad = "5.1.2"
|
||||
websockets = "14.2"
|
||||
opuslib = "3.0.1"
|
||||
numpy = "1.26.4"
|
||||
pydub = "0.25.1"
|
||||
funasr = "1.2.3"
|
||||
@@ -26,13 +25,9 @@ ormsgpack = "1.7.0"
|
||||
ruamel-yaml = "0.18.10"
|
||||
setuptools = "^75.8.0"
|
||||
loguru = "^0.7.3"
|
||||
opuslib-next = "^1.1.2"
|
||||
|
||||
|
||||
[[tool.poetry.source]]
|
||||
name = "mirrors"
|
||||
url = "https://pypi.tuna.tsinghua.edu.cn/simple/"
|
||||
priority = "primary"
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core"]
|
||||
build-backend = "poetry.core.masonry.api"
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ pyyml==0.0.2
|
||||
torch==2.2.2
|
||||
silero_vad==5.1.2
|
||||
websockets==14.2
|
||||
opuslib==3.0.1
|
||||
opuslib_next==1.1.2
|
||||
numpy==1.26.4
|
||||
pydub==0.25.1
|
||||
funasr==1.2.3
|
||||
|
||||
Reference in New Issue
Block a user