1
0
mirror of https://github.com/hanxi/xiaomusic.git synced 2025-12-06 14:52:50 +08:00

Compare commits

...

154 Commits

Author SHA1 Message Date
涵曦
7994ab65e0 bump: version 0.3.73 → 0.3.74 2025-01-21 08:11:38 +08:00
涵曦
1c7317d3bb build: update static version 2025-01-21 08:11:37 +08:00
Issues Docs [BOT]
ea0748b35b Auto-Generate docs 🤖 2025-01-19 15:28:27 +00:00
涵曦
2b4dcebba5 feat: 新增 Tailwind 主题 2025-01-19 23:27:08 +08:00
Issues Docs [BOT]
63d57c3086 Auto-Generate docs 🤖 2025-01-19 15:23:54 +00:00
Formatter [BOT]
73839b72cc Auto-format code 🧹🌟🤖 2025-01-19 15:18:31 +00:00
jhcj.z
253c620c66 使用 tailwindcss 创建了一个新的主题 (#372)
* 引入tailwindcss, 更新默认主题ui

* 引入tailwindcss, 添加新的主题ui

* 引入tailwindcss, 添加新的主题ui
2025-01-19 23:18:06 +08:00
Issues Docs [BOT]
58e9cdcb6c Auto-Generate docs 🤖 2025-01-18 07:22:39 +00:00
Issues Docs [BOT]
d632edf6ad Auto-Generate docs 🤖 2025-01-18 02:56:18 +00:00
Issues Docs [BOT]
45a7d65c07 Auto-Generate docs 🤖 2025-01-18 01:42:12 +00:00
Issues Docs [BOT]
bf2642c469 Auto-Generate docs 🤖 2025-01-17 17:13:54 +00:00
涵曦
b6691e8848 feat: 修改设置页面文档链接 2025-01-17 20:17:48 +08:00
涵曦
43d657dd6f fix: 修复下载歌单重命名问题 2025-01-17 20:01:09 +08:00
Issues Docs [BOT]
696aaf06b3 Auto-Generate docs 🤖 2025-01-16 13:29:55 +00:00
涵曦
fd8455e592 bump: version 0.3.72 → 0.3.73 2025-01-16 21:28:17 +08:00
涵曦
85945c14d7 build: update static version 2025-01-16 21:28:17 +08:00
涵曦
0ac273f7c9 fix: 当前歌曲不在列表中时才切换列表 close #359 2025-01-16 14:23:23 +08:00
涵曦
56c5a267df fix: 修复默认主题播放进度时间问题 2025-01-16 11:48:48 +08:00
涵曦
e9253fed57 fix: 尝试修复获取对话记录失败的问题 close #362 2025-01-16 11:35:45 +08:00
Issues Docs [BOT]
a317337a01 Auto-Generate docs 🤖 2025-01-15 08:05:32 +00:00
Issues Docs [BOT]
e7c012870a Auto-Generate docs 🤖 2025-01-15 00:47:29 +00:00
Issues Docs [BOT]
fe02b9b4ad Auto-Generate docs 🤖 2025-01-14 17:01:14 +00:00
Issues Docs [BOT]
012513aca0 Auto-Generate docs 🤖 2025-01-14 10:45:58 +00:00
涵曦
8f1cc890a7 Update README.md 2025-01-14 18:44:35 +08:00
Issues Docs [BOT]
0e937892e7 Auto-Generate docs 🤖 2025-01-14 10:42:25 +00:00
Issues Docs [BOT]
996f0c6780 Auto-Generate docs 🤖 2025-01-14 01:13:57 +00:00
Issues Docs [BOT]
8468f41721 Auto-Generate docs 🤖 2025-01-11 06:20:27 +00:00
涵曦
7b555159b5 bump: version 0.3.71 → 0.3.72 2025-01-11 14:18:43 +08:00
涵曦
1520654a6d build: update static version 2025-01-11 14:18:43 +08:00
Issues Docs [BOT]
052f395b9d Auto-Generate docs 🤖 2025-01-11 03:40:40 +00:00
涵曦
ed33d94a6f Update index.md 2025-01-11 10:46:58 +08:00
Issues Docs [BOT]
cbb282acda Auto-Generate docs 🤖 2025-01-11 02:15:40 +00:00
Issues Docs [BOT]
81cd64c4d8 Auto-Generate docs 🤖 2025-01-11 01:41:15 +00:00
涵曦
dab4903487 fix: 修复默认主题没有单曲循环的问题 see #355 2025-01-11 09:29:17 +08:00
Issues Docs [BOT]
11c1ac4753 Auto-Generate docs 🤖 2025-01-10 05:59:10 +00:00
Issues Docs [BOT]
80bacdee0f Auto-Generate docs 🤖 2025-01-09 04:39:19 +00:00
Issues Docs [BOT]
867d16700c Auto-Generate docs 🤖 2025-01-08 05:09:29 +00:00
涵曦
1ca8955b94 feat: 新增播放文字功能 2025-01-08 12:56:52 +08:00
Issues Docs [BOT]
8f19b9b33b Auto-Generate docs 🤖 2025-01-07 14:23:55 +00:00
Issues Docs [BOT]
b88712d6b0 Auto-Generate docs 🤖 2025-01-07 07:57:13 +00:00
Issues Docs [BOT]
859c12f047 Auto-Generate docs 🤖 2025-01-07 06:21:59 +00:00
Issues Docs [BOT]
a0ec94e036 Auto-Generate docs 🤖 2025-01-07 00:58:18 +00:00
涵曦
bbc6c30557 bump: version 0.3.70 → 0.3.71 2025-01-07 08:55:37 +08:00
涵曦
4a61ff8074 build: update static version 2025-01-07 08:55:36 +08:00
涵曦
0a1b467507 style: 换个图标 2025-01-07 08:43:13 +08:00
涵曦
d244575d7b feat: 支持自动填 ip 和端口 2025-01-07 08:34:21 +08:00
Issues Docs [BOT]
a8161579b4 Auto-Generate docs 🤖 2025-01-06 14:32:24 +00:00
Issues Docs [BOT]
fac7816c64 Auto-Generate docs 🤖 2025-01-06 09:25:43 +00:00
涵曦
4adfc0e3b1 fix: 搜索歌曲窗口不自动关闭 see #351 2025-01-05 11:23:16 +08:00
涵曦
abe70b1146 fix: 解决歌词信息写入失败的问题 2025-01-05 10:52:55 +08:00
Issues Docs [BOT]
e47c6eaf9d Auto-Generate docs 🤖 2025-01-05 01:52:14 +00:00
涵曦
be636abaa0 fix: 修复一些小问题 2025-01-05 09:40:11 +08:00
涵曦
6b41b7b18e fix: 非播放中也返回歌曲时长 see #340 2025-01-05 07:44:01 +08:00
Issues Docs [BOT]
198963897e Auto-Generate docs 🤖 2025-01-04 11:18:15 +00:00
涵曦
2deab08351 bump: version 0.3.69 → 0.3.70 2025-01-04 19:16:07 +08:00
涵曦
7048e38e32 build: update static version 2025-01-04 19:16:07 +08:00
涵曦
dab756da7f Update ci.yml 2025-01-04 18:45:31 +08:00
涵曦
2cf883bcf4 ci: 调试 2025-01-04 18:22:19 +08:00
涵曦
f71b594a75 ci: 调试 2025-01-04 17:54:24 +08:00
涵曦
3a4d0b6c9b ci: 调试 2025-01-04 17:41:50 +08:00
Issues Docs [BOT]
3f8bae4568 Auto-Generate docs 🤖 2025-01-04 08:38:34 +00:00
涵曦
a4f21670bb ci: 调试 2025-01-04 15:44:47 +08:00
涵曦
fdc57d1b47 fix: 尝试修复部分设备无法启动的问题 2025-01-04 15:20:55 +08:00
Issues Docs [BOT]
0797f2ef3f Auto-Generate docs 🤖 2025-01-03 12:53:34 +00:00
涵曦
1da94f5730 Update README.md 2025-01-03 20:51:17 +08:00
涵曦
12427151f5 Update README.md 2025-01-03 20:49:43 +08:00
Issues Docs [BOT]
526193f0f6 Auto-Generate docs 🤖 2025-01-03 04:36:24 +00:00
涵曦
c9d0c8720a fix: 解决首页提示翻译英文问题 2025-01-02 21:39:14 +08:00
Issues Docs [BOT]
0bd661c98f Auto-Generate docs 🤖 2025-01-02 03:49:49 +00:00
涵曦
b9534d3a1f docs: 更新文档 2025-01-02 11:47:50 +08:00
Issues Docs [BOT]
27c6dd31fc Auto-Generate docs 🤖 2025-01-01 19:51:01 +00:00
涵曦
5906daade6 fix: 尝试解决 supervisor 启动报错 2025-01-02 03:38:16 +08:00
Issues Docs [BOT]
4c36d90ad2 Auto-Generate docs 🤖 2025-01-01 06:58:04 +00:00
涵曦
66905fae7e bump: version 0.3.68 → 0.3.69 2025-01-01 14:55:55 +08:00
涵曦
65e02540e8 build: update static version 2025-01-01 14:55:54 +08:00
涵曦
bf2d29790a feat: 支持关闭获取对话记录功能 2025-01-01 14:32:41 +08:00
涵曦
a28c65febf fix: 尝试解决网络卡顿问题 2025-01-01 14:18:03 +08:00
Issues Docs [BOT]
1cb01f43bf Auto-Generate docs 🤖 2024-12-31 15:21:41 +00:00
涵曦
62f90422bb Update README.md 2024-12-31 23:19:34 +08:00
Issues Docs [BOT]
402c417eeb Auto-Generate docs 🤖 2024-12-31 14:47:57 +00:00
涵曦
3899623a32 Update static.yml 2024-12-31 22:46:12 +08:00
涵曦
bdfcf43083 ci: 删除 pdm.lock 文件 2024-12-31 22:38:04 +08:00
涵曦
90e660165a Update static.yml 2024-12-31 22:19:17 +08:00
涵曦
a87c1fcbcf Update static.yml 2024-12-31 22:02:36 +08:00
涵曦
b880e861d4 Update static.yml 2024-12-31 20:46:39 +08:00
涵曦
33d6594029 Update static.yml 2024-12-31 20:23:00 +08:00
涵曦
33ca5138ee Update static.yml 2024-12-31 20:00:22 +08:00
涵曦
35d715526e Update static.yml 2024-12-31 19:56:00 +08:00
涵曦
be0687819d Update static.yml 2024-12-31 19:50:11 +08:00
涵曦
f5c4a6505f Update static.yml 2024-12-31 19:46:08 +08:00
涵曦
328cb03f8e bump: version 0.3.67 → 0.3.68 2024-12-31 19:19:47 +08:00
涵曦
a6742938eb build: update static version 2024-12-31 19:19:46 +08:00
涵曦
8f63bc181d feat: umami 脚本改为异步加载 2024-12-31 14:08:03 +08:00
涵曦
6bc3c46d00 feat: 支持 python3.13 版本 2024-12-31 13:04:49 +08:00
涵曦
f2f1f43b93 build: 修改镜像构建 2024-12-31 08:28:21 +08:00
涵曦
8435c10964 fix: 修复保存设置时可能出现报错的情况 2024-12-31 08:19:39 +08:00
Issues Docs [BOT]
ff54f11a4b Auto-Generate docs 🤖 2024-12-29 12:54:48 +00:00
Formatter [BOT]
e8b705e9d1 Auto-format code 🧹🌟🤖 2024-12-29 11:40:41 +00:00
AisukaYuki
2c3a95b98d feat: 增加均衡歌曲响度(可选) (#338)
可选下载和转换mp3时,是否均衡的歌曲响度,避免歌声忽大忽小。#336
2024-12-29 19:40:10 +08:00
Issues Docs [BOT]
52bce6af9d Auto-Generate docs 🤖 2024-12-29 10:09:55 +00:00
Issues Docs [BOT]
e5af13208a Auto-Generate docs 🤖 2024-12-29 03:57:48 +00:00
Issues Docs [BOT]
370f4ccd99 Auto-Generate docs 🤖 2024-12-29 02:20:56 +00:00
涵曦
0d758a47f4 bump: version 0.3.66 → 0.3.67 2024-12-29 10:19:26 +08:00
涵曦
a1a025960b build: update static version 2024-12-29 10:19:26 +08:00
涵曦
2c5ffa5645 fix: 修复默认主题搜索问题 2024-12-29 10:19:02 +08:00
Issues Docs [BOT]
f78df85bb9 Auto-Generate docs 🤖 2024-12-28 14:13:02 +00:00
Issues Docs [BOT]
a771441616 Auto-Generate docs 🤖 2024-12-28 14:03:56 +00:00
Issues Docs [BOT]
0ef36d26ff Auto-Generate docs 🤖 2024-12-28 12:19:26 +00:00
Issues Docs [BOT]
589d36f98c Auto-Generate docs 🤖 2024-12-28 02:32:11 +00:00
涵曦
ad9ce10fa2 Update README.md 2024-12-28 10:30:33 +08:00
Issues Docs [BOT]
bea986f4ef Auto-Generate docs 🤖 2024-12-27 08:23:11 +00:00
涵曦
c3451fea6a Update README.md 2024-12-27 16:21:44 +08:00
Issues Docs [BOT]
6ce99a0e62 Auto-Generate docs 🤖 2024-12-27 08:16:49 +00:00
涵曦
063688f3e6 docs: 更新文档 2024-12-27 16:15:02 +08:00
涵曦
0c4b34a554 build: 修改打包镜像 2024-12-27 09:56:55 +08:00
Issues Docs [BOT]
52b6000342 Auto-Generate docs 🤖 2024-12-26 01:41:18 +00:00
涵曦
a1962cd450 Update README.md 2024-12-26 09:39:06 +08:00
Issues Docs [BOT]
2520e5d9e5 Auto-Generate docs 🤖 2024-12-26 01:35:27 +00:00
涵曦
bd0a3a1052 docs: 更新文档 2024-12-26 09:33:42 +08:00
涵曦
24218babeb feat: 简化设置,不允许修改监听端口 2024-12-26 09:18:58 +08:00
涵曦
dd803785e1 build: 打包修改 2024-12-26 09:08:44 +08:00
Issues Docs [BOT]
78ee51c8c2 Auto-Generate docs 🤖 2024-12-26 00:45:31 +00:00
涵曦
4e3e127767 bump: version 0.3.65 → 0.3.66 2024-12-26 08:43:45 +08:00
涵曦
dafd2cec05 build: update static version 2024-12-26 08:43:44 +08:00
涵曦
59e9191f70 style: 清理无效代码 2024-12-25 16:57:21 +08:00
涵曦
f7286269af fix: 修复歌曲批量重命名的问题 2024-12-25 16:20:06 +08:00
涵曦
d98652fe5d fix: 修复自定义歌单删除后没刷新歌单列表 2024-12-25 09:48:19 +08:00
Issues Docs [BOT]
497dd07030 Auto-Generate docs 🤖 2024-12-25 00:48:00 +00:00
涵曦
6cbec5bbff fix: 尝试修复更新失败问题 2024-12-25 08:38:44 +08:00
Issues Docs [BOT]
c46c652e5d Auto-Generate docs 🤖 2024-12-24 13:04:34 +00:00
涵曦
1fbbae5f1c bump: version 0.3.64 → 0.3.65 2024-12-24 21:03:03 +08:00
涵曦
ffd04fab68 build: update static version 2024-12-24 21:03:02 +08:00
Issues Docs [BOT]
51dfe70a87 Auto-Generate docs 🤖 2024-12-23 08:43:15 +00:00
涵曦
956c569b93 docs: 修改文档代理地址 2024-12-23 16:41:12 +08:00
涵曦
617a961816 fix: 处理图像报错 2024-12-22 18:14:58 +08:00
涵曦
b37b6fd57c fix: 修改歌单名字漏更新歌单列表 2024-12-22 17:59:19 +08:00
涵曦
c09baaac15 fix: 修复获取自定义歌单接口报错 2024-12-22 13:15:35 +08:00
Issues Docs [BOT]
7ded7a08dd Auto-Generate docs 🤖 2024-12-22 03:24:55 +00:00
涵曦
f4487945db bump: version 0.3.63 → 0.3.64 2024-12-22 11:23:09 +08:00
涵曦
0bdd2986f1 build: update static version 2024-12-22 11:23:08 +08:00
涵曦
a72777317e fix: 使用自己架设的 sentry 服务,解决 Cloudflare 额度超量问题 2024-12-22 11:22:42 +08:00
Issues Docs [BOT]
f2e096da38 Auto-Generate docs 🤖 2024-12-22 02:26:41 +00:00
涵曦
f42398ec9f Update static.yml 2024-12-22 10:25:12 +08:00
涵曦
5121d141b4 bump: version 0.3.62 → 0.3.63 2024-12-22 10:11:27 +08:00
涵曦
7cf9751dde build: update static version 2024-12-22 10:11:25 +08:00
Issues Docs [BOT]
990defefc9 Auto-Generate docs 🤖 2024-12-22 02:07:10 +00:00
涵曦
4e6afa0e3e Update static.yml 2024-12-22 10:05:28 +08:00
涵曦
e501097ec2 perf: 只监控报错信息 2024-12-22 00:42:46 +08:00
涵曦
ea567fd55a bump: version 0.3.61 → 0.3.62 2024-12-21 23:50:57 +08:00
涵曦
9cb1931f90 build: update static version 2024-12-21 23:50:56 +08:00
涵曦
e50db9ea59 fix: 修复首次配置时,默认主题只有一个设备的问题。 2024-12-21 23:17:09 +08:00
涵曦
5c788ccaed fix: 修复一些报错问题 2024-12-21 19:32:52 +08:00
Issues Docs [BOT]
10a63e5568 Auto-Generate docs 🤖 2024-12-20 11:16:37 +00:00
Issues Docs [BOT]
2460cd3207 Auto-Generate docs 🤖 2024-12-19 13:10:27 +00:00
72 changed files with 5074 additions and 1694 deletions

View File

@@ -25,7 +25,7 @@ jobs:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
@@ -79,15 +79,15 @@ jobs:
- name: Test amd64 image
run: |
docker run --rm ${{ env.TEST_TAG }}-linux-amd64 /app/.venv/bin/python3 /app/xiaomusic.py -h
docker run --rm --entrypoint /bin/sh ${{ env.TEST_TAG }}-linux-amd64 -c "/app/.venv/bin/python3 /app/xiaomusic.py -h"
- name: Test arm64 image
run: |
docker run --rm ${{ env.TEST_TAG }}-linux-arm64 /app/.venv/bin/python3 /app/xiaomusic.py -h
docker run --rm --entrypoint /bin/sh ${{ env.TEST_TAG }}-linux-arm64 -c "/app/.venv/bin/python3 /app/xiaomusic.py -h"
- name: Test armv7 image
run: |
docker run --rm ${{ env.TEST_TAG }}-linux-arm-v7 /app/.venv/bin/python3 /app/xiaomusic.py -h
docker run --rm --entrypoint /bin/sh ${{ env.TEST_TAG }}-linux-arm-v7 -c "/app/.venv/bin/python3 /app/xiaomusic.py -h"
- name: Docker Hub Description
if: github.ref == 'refs/heads/main'
@@ -125,34 +125,37 @@ jobs:
- name: Package /app for amd64
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')
run: |
docker run --rm -v $PWD:/workspace ${{ env.TEST_TAG }}-linux-amd64 tar czf /workspace/app-amd64.tar.gz -C / app
docker run --rm --entrypoint /bin/sh -v $PWD:/workspace ${{ env.TEST_TAG }}-linux-amd64 -c \
"tar czf /workspace/app-amd64.tar.gz -C / app"
- name: Package /app (lite) for amd64
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')
run: |
docker run --rm -v $PWD:/workspace ${{ env.TEST_TAG }}-linux-amd64 bash -c \
docker run --rm --entrypoint /bin/sh -v $PWD:/workspace ${{ env.TEST_TAG }}-linux-amd64 -c \
"cd /app && tar --exclude='ffmpeg' -czf /workspace/app-amd64-lite.tar.gz .[!.]* *"
- name: Package /app for arm64
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')
run: |
docker run --rm -v $PWD:/workspace ${{ env.TEST_TAG }}-linux-arm64 tar czf /workspace/app-arm64.tar.gz -C / app
docker run --rm --entrypoint /bin/sh -v $PWD:/workspace ${{ env.TEST_TAG }}-linux-arm64 -c \
"tar czf /workspace/app-arm64.tar.gz -C / app"
- name: Package /app (lite) for arm64
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')
run: |
docker run --rm -v $PWD:/workspace ${{ env.TEST_TAG }}-linux-arm64 bash -c \
docker run --rm --entrypoint /bin/sh -v $PWD:/workspace ${{ env.TEST_TAG }}-linux-arm64 -c \
"cd /app && tar --exclude='ffmpeg' -czf /workspace/app-arm64-lite.tar.gz .[!.]* *"
- name: Package /app for arm/v7
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')
run: |
docker run --rm -v $PWD:/workspace ${{ env.TEST_TAG }}-linux-arm-v7 tar czf /workspace/app-arm-v7.tar.gz -C / app
docker run --rm --entrypoint /bin/sh -v $PWD:/workspace ${{ env.TEST_TAG }}-linux-arm-v7 -c \
"tar czf /workspace/app-arm-v7.tar.gz -C / app"
- name: Package /app (lite) for arm/v7
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')
run: |
docker run --rm -v $PWD:/workspace ${{ env.TEST_TAG }}-linux-arm-v7 bash -c \
docker run --rm --entrypoint /bin/sh -v $PWD:/workspace ${{ env.TEST_TAG }}-linux-arm-v7 -c \
"cd /app && tar --exclude='ffmpeg' -czf /workspace/app-arm-v7-lite.tar.gz .[!.]* *"
- name: Publish to Docker Hub main

View File

@@ -18,6 +18,12 @@ on:
types:
- uploaded
workflow_run:
workflows:
- CI Workflow
types:
- completed
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
@@ -43,6 +49,8 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Node.js
uses: actions/setup-node@v2
@@ -62,8 +70,10 @@ jobs:
npm run docs:build
- uses: pdm-project/setup-pdm@v3
- name: Install dependencies
run: pdm install
- name: pdm
run: pdm install --prod --frozen-lockfile
- name: generate versions.json
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -84,6 +94,7 @@ jobs:
run: |
if [ "${{ steps.check_changes.outputs.changed }}" == "true" ]; then
git config --local user.name "Issues Docs [BOT]"
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git add .
git commit -m "Auto-Generate docs 🤖"
git push

4
.gitignore vendored
View File

@@ -103,7 +103,7 @@ ipython_config.py
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
@@ -169,5 +169,5 @@ setting.json
.DS_Store
cache
tmp/
xiaomusic.log.txt
xiaomusic.log.txt*
node_modules

View File

@@ -1,3 +1,120 @@
## v0.3.74 (2025-01-21)
### Feat
- 新增 Tailwind 主题
- 修改设置页面文档链接
### Fix
- 修复下载歌单重命名问题
## v0.3.73 (2025-01-16)
### Fix
- 当前歌曲不在列表中时才切换列表 close #359
- 修复默认主题播放进度时间问题
- 尝试修复获取对话记录失败的问题 close #362
## v0.3.72 (2025-01-11)
### Feat
- 新增播放文字功能
### Fix
- 修复默认主题没有单曲循环的问题 see #355
## v0.3.71 (2025-01-07)
### Feat
- 支持自动填 ip 和端口
### Fix
- 搜索歌曲窗口不自动关闭 see #351
- 解决歌词信息写入失败的问题
- 修复一些小问题
- 非播放中也返回歌曲时长 see #340
## v0.3.70 (2025-01-04)
### Fix
- 尝试修复部分设备无法启动的问题
- 解决首页提示翻译英文问题
- 尝试解决 supervisor 启动报错
## v0.3.69 (2025-01-01)
### Feat
- 支持关闭获取对话记录功能
### Fix
- 尝试解决网络卡顿问题
## v0.3.68 (2024-12-31)
### Feat
- umami 脚本改为异步加载
- 支持 python3.13 版本
- 增加均衡歌曲响度(可选) (#338)
### Fix
- 修复保存设置时可能出现报错的情况
## v0.3.67 (2024-12-29)
### Feat
- 简化设置,不允许修改监听端口
### Fix
- 修复默认主题搜索问题
## v0.3.66 (2024-12-26)
### Fix
- 修复歌曲批量重命名的问题
- 修复自定义歌单删除后没刷新歌单列表
- 尝试修复更新失败问题
## v0.3.65 (2024-12-24)
### Fix
- 处理图像报错
- 修改歌单名字漏更新歌单列表
- 修复获取自定义歌单接口报错
## v0.3.64 (2024-12-22)
### Fix
- 使用自己架设的 sentry 服务,解决 Cloudflare 额度超量问题
## v0.3.63 (2024-12-22)
### Perf
- 只监控报错信息
## v0.3.62 (2024-12-21)
### Fix
- 修复首次配置时,默认主题只有一个设备的问题。
- 修复一些报错问题
## v0.3.61 (2024-12-19)
### Fix

View File

@@ -18,14 +18,13 @@ COPY --from=builder /app/xiaomusic.py .
COPY --from=builder /app/xiaomusic/__init__.py /base_version.py
RUN touch /app/.dockerenv
COPY supervisor.conf /etc/supervisor.conf
COPY supervisord.conf /etc/supervisor/supervisord.conf
RUN rm -f /var/run/supervisor.sock
ENV XIAOMUSIC_HOSTNAME=192.168.2.5
ENV XIAOMUSIC_PORT=8090
VOLUME /app/conf
VOLUME /app/music
EXPOSE 8090
ENV TZ=Asia/Shanghai
ENV PATH=/app/.venv/bin:$PATH
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor.conf"]
ENTRYPOINT ["/bin/sh", "-c", "/usr/bin/supervisord -c /etc/supervisor/supervisord.conf && tail -F /app/supervisord.log /app/xiaomusic.log.txt"]

View File

@@ -8,6 +8,7 @@ RUN apt-get update && apt-get install -y \
libopenjp2-7 \
libxcb1 \
supervisor \
vim \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app

138
README.md
View File

@@ -1,4 +1,5 @@
# XiaoMusic: 无限听歌,解放小爱音箱
[![GitHub License](https://img.shields.io/github/license/hanxi/xiaomusic)](https://github.com/hanxi/xiaomusic)
[![Docker Image Version](https://img.shields.io/docker/v/hanxi/xiaomusic?sort=semver&label=docker%20image)](https://hub.docker.com/r/hanxi/xiaomusic)
[![Docker Pulls](https://img.shields.io/docker/pulls/hanxi/xiaomusic)](https://hub.docker.com/r/hanxi/xiaomusic)
@@ -9,7 +10,6 @@
[![Visitors](https://api.visitorbadge.io/api/daily?path=hanxi%2Fxiaomusic&label=daily%20visitor&countColor=%232ccce4&style=flat)](https://visitorbadge.io/status?path=hanxi%2Fxiaomusic)
[![Visitors](https://api.visitorbadge.io/api/visitors?path=hanxi%2Fxiaomusic&label=total%20visitor&countColor=%232ccce4&style=flat)](https://visitorbadge.io/status?path=hanxi%2Fxiaomusic)
使用小爱音箱播放音乐,音乐使用 yt-dlp 下载。
<https://github.com/hanxi/xiaomusic>
@@ -22,13 +22,13 @@
已经支持在 web 页面配置其他参数docker 启动命令如下:
```bash
docker run -p 8090:8090 -v /xiaomusic/music:/app/music -v /xiaomusic/conf:/app/conf hanxi/xiaomusic
docker run -p 58090:8090 -e XIAOMUSIC_PUBLIC_PORT=58090 -v /xiaomusic_music:/app/music -v /xiaomusic_conf:/app/conf hanxi/xiaomusic
```
🔥 国内:
```bash
docker run -p 8090:8090 -v /xiaomusic/music:/app/music -v /xiaomusic/conf:/app/conf m.daocloud.io/docker.io/hanxi/xiaomusic
docker run -p 58090:8090 -e XIAOMUSIC_PUBLIC_PORT=58090 -v /xiaomusic_music:/app/music -v /xiaomusic_conf:/app/conf docker.hanxi.cc/hanxi/xiaomusic
```
对应的 docker compose 配置如下:
@@ -40,10 +40,12 @@ services:
container_name: xiaomusic
restart: unless-stopped
ports:
- 8090:8090
- 58090:8090
environment:
XIAOMUSIC_PUBLIC_PORT: 58090
volumes:
- /xiaomusic/music:/app/music
- /xiaomusic/conf:/app/conf
- /xiaomusic_music:/app/music
- /xiaomusic_conf:/app/conf
```
🔥 国内:
@@ -51,75 +53,40 @@ services:
```yaml
services:
xiaomusic:
image: m.daocloud.io/docker.io/hanxi/xiaomusic
image: docker.hanxi.cc/hanxi/xiaomusic
container_name: xiaomusic
restart: unless-stopped
ports:
- 8090:8090
- 58090:8090
environment:
XIAOMUSIC_PUBLIC_PORT: 58090
volumes:
- /xiaomusic/music:/app/music
- /xiaomusic/conf:/app/conf
- /xiaomusic_music:/app/music
- /xiaomusic_conf:/app/conf
```
其中 conf 目录为配置文件存放目录music 目录为音乐存放目录,建议分开配置为不同的目录。
- 其中 conf 目录为配置文件存放目录music 目录为音乐存放目录,建议分开配置为不同的目录。
- /xiaomusic_music 和 /xiaomusic_conf 是 docker 所在的主机的目录,可以修改为其他目录。如果报错找不到 /xiaomusic_music 目录,可以先执行 `mkdir -p /xiaomusic_{music,conf}` 命令新建目录。
- /app/music 和 /app/conf 是 docker 容器里的目录,不要去修改。
- XIAOMUSIC_PUBLIC_PORT 是用来配置 NAS 本地端口的。8090 是容器端口,不要去修改。
- 后台访问地址为: http://NAS_IP:58090
> [!NOTE]
> 上面配置的 /xiaomusic/music 和 /xiaomusic/conf 是 docker 主机里的 /xiaomusic 目录下的,可以修改为其他目录。如果报错找不到 /xiaomusic/music 目录,可以先执行 `mkdir -p /xiaomusic/{music,conf}` 命令新建目录
docker 和 docker compose 二选一即可,启动成功后,在 web 页面可以配置其他参数,带有 `*` 号的配置是必须要配置的,其他的用不上时不用修改。初次配置时需要在页面上输入小米账号和密码保存后才能获取到设备列表。
> docker 和 docker compose 二选一即可,启动成功后,在 web 页面可以配置其他参数,带有 `*` 号的配置是必须要配置的,其他的用不上时不用修改。初次配置时需要在页面上输入小米账号和密码保存后才能获取到设备列表
> [!TIP]
> 目前安装步骤已经是最简化了,如果还是嫌安装麻烦,可以微信或者 QQ 约我远程安装,我一般周末和晚上才有时间,收个辛苦费 :moneybag: 50 元一次,安装失败不收费。
### 🔥 修改默认8090端口映射
#### 方法1 不修改监听端口 8090
【监听端口】保持为默认的 8090 不变,把【外网访问端口】改为 5678 。
```yaml
services:
xiaomusic:
image: hanxi/xiaomusic
container_name: xiaomusic
restart: unless-stopped
ports:
- 5678:8090
volumes:
- /xiaomusic/music:/app/music
- /xiaomusic/conf:/app/conf
environment:
XIAOMUSIC_PUBLIC_PORT: 5678
```
XIAOMUSIC_PUBLIC_PORT 对应后台设置里的【外网访问端口】,修改后可以不用重启。
#### 方法2 修改监听端口 8090 为 5678
如果需要修改 8090 端口为其他端口,比如 5678需要这样配3个数字都需要是 5678 。见 <https://github.com/hanxi/xiaomusic/issues/19>
```yaml
services:
xiaomusic:
image: hanxi/xiaomusic
container_name: xiaomusic
restart: unless-stopped
ports:
- 5678:5678
volumes:
- /xiaomusic/music:/app/music
- /xiaomusic/conf:/app/conf
environment:
XIAOMUSIC_PORT: 5678
```
如果不是首次修改端口,还需要修改 /xiaomusic/conf/setting.json 文件里的端口(也可以在后台修改监听端口后重启)。
遇到问题可以去 web 设置页面底部点击【下载日志文件】按钮,然后搜索一下日志文件内容确保里面没有账号密码信息后(有就删除这些敏感信息),然后在提 issues 反馈问题时把下载的日志文件带上。
> [!IMPORTANT]
> XIAOMUSIC_PORT 也可以在后台配置,对应的是监听端口,修改后记得重启
> [!TIP]
> 海外 RackNerd VPS 机器推荐,可支付宝付款
>
> - [🔥1 GB KVM VPS $11.29/年](https://my.racknerd.com/aff.php?aff=1177&pid=903)
> - [2 GB KVM VPS](https://my.racknerd.com/aff.php?aff=1177&pid=904)
> - [3.5 GB KVM VPS](https://my.racknerd.com/aff.php?aff=1177&pid=905)
> - [4 GB KVM VPS](https://my.racknerd.com/aff.php?aff=1177&pid=906)
> - [6 GB KVM VPS](https://my.racknerd.com/aff.php?aff=1177&pid=907)
### 🤐 支持语音口令
@@ -154,7 +121,7 @@ services:
\ / | | / _` | / _ \ | |\/| | | | | | / __| | | / __|
/ \ | | | (_| | | (_) | | | | | | |_| | \__ \ | | | (__
/_/\_\ |_| \__,_| \___/ |_| |_| \__,_| |___/ |_| \___|
XiaoMusic v0.3.37 by: github.com/hanxi
XiaoMusic v0.3.69 by: github.com/hanxi
usage: xiaomusic [-h] [--port PORT] [--hardware HARDWARE] [--account ACCOUNT]
[--password PASSWORD] [--cookie COOKIE] [--verbose]
@@ -214,7 +181,6 @@ docker build -t xiaomusic .
- 使用了 Docker ,在 NAS 上安装更方便。
- 默认的前端主题使用了 jQuery 。
## 已测试支持的设备
| 型号 | 名称 |
@@ -257,24 +223,6 @@ docker build -t xiaomusic .
> 已知 L05B L05C LX06 L16A 不支持 flac 格式。
> 如果格式不能播放可以打开【转换为MP3】和【型号兼容模式】选项。具体见 <https://github.com/hanxi/xiaomusic/issues/153#issuecomment-2328168689>
## 💡 简易的控制面板
浏览器进入 <http://192.168.2.5:8090>
- ip 是 XIAOMUSIC_HOSTNAME 设置的
- 8090 是默认端口
- 支持功能
- 显示正在播放的歌曲
- 模糊搜索本地歌曲
- 播放列表
- 删除歌曲
- 设置页面
- 配置网络歌单
- 日志文件下载
采用新的设置页面之后,没有必须在启动前配置的环境变量了,除非是改默认的 8090 端口才需要配置环境变量。
## 🌏 网络歌单功能
可以配置一个 json 格式的歌单,支持电台和歌曲,也可以直接用别人分享的链接,同时配备了 m3u 文件格式转换工具,可以很方便的把 m3u 电台文件转换成网络歌单格式的 json 文件,具体用法见 <https://github.com/hanxi/xiaomusic/issues/78>
@@ -284,29 +232,12 @@ docker build -t xiaomusic .
## 🍺 更多其他可选配置
- XIAOMUSIC_ACTIVE_CMD 环境变量,对应后台的 【允许唤醒的命令】,用于唤醒口令,配置成'play,random_play'在非播放状态下只有这两个指令播放歌曲和随机播放可以触发触发后xiaomusic进入playing状态其他指令则可以正常触发。具体<https://github.com/hanxi/xiaomusic/pull/43>
- XIAOMUSIC_EXCLUDE_DIRS 配置歌曲目录里需要忽略的目录,对应后台的 【忽略目录】
- XIAOMUSIC_MUSIC_PATH_DEPTH 配置歌曲目录搜索深度,对应后台的 【目录深度】,具体见 <https://github.com/hanxi/xiaomusic/issues/76>
- XIAOMUSIC_DISABLE_HTTPAUTH 配置成 false 表示开启密码访问web控制台对应后台的 【关闭密码验证】,具体见 <https://github.com/hanxi/xiaomusic/issues/47>
- XIAOMUSIC_HTTPAUTH_USERNAME 配置 web 控制台用户,对应后台的 【控制台账户】
- XIAOMUSIC_HTTPAUTH_PASSWORD 配置 web 控制台密码,对应后台的 【控制台密码】
- XIAOMUSIC_CONF_PATH 用来存放配置文件的目录,对应后台的 【配置文件目录】,记得把目录映射到主机,默认为 `/app/config` ,具体见 <https://github.com/hanxi/xiaomusic/issues/74>
- XIAOMUSIC_CACHE_DIR 用来音乐 tag 缓存,默认为 `/app/cache`,对应后台的 【缓存文件目录】。
- XIAOMUSIC_DISABLE_DOWNLOAD 设为 true 时关闭下载功能,对应后台的 【关闭下载功能】,见 <https://github.com/hanxi/xiaomusic/issues/82>
- XIAOMUSIC_USE_MUSIC_API 设为 true 时使用 player_play_music 接口播放音乐,对应后台的 【型号兼容模式】,用于兼容不能播放的型号,如果发现需要设置这个选项的时候请告知我加一下设备型号,方便以后不用设置。 见 <https://github.com/hanxi/xiaomusic/issues/30>
- XIAOMUSIC_KEYWORDS_PLAY 用来播放歌曲的口令前缀,对应后台的 【播放歌曲口令】,默认是 "播放歌曲,放歌曲" ,可以用英文逗号分割配置多个
- XIAOMUSIC_KEYWORDS_STOP 用来关机的口令,对应后台的 【停止口令】,默认是 "关机,暂停,停止" ,可以用英文逗号分割配置多个。
- XIAOMUSIC_KEYWORDS_PLAYLOCAL 用来播放本地歌曲的口令前缀,对应后台的 【播放本地歌曲口令】,本地找不到时不会下载歌曲,默认是 "播放本地歌曲,本地播放歌曲" ,可以用英文逗号分割配置多个。
- XIAOMUSIC_ENABLE_FUZZY_MATCH 设为 true 时开启模糊匹配(默认),设为 false 时关闭模糊匹配,对应后台的 【开启模糊搜索】,支持模糊匹配歌名和歌单名。 具体见 <https://github.com/hanxi/xiaomusic/issues/52>
- XIAOMUSIC_FUZZY_MATCH_CUTOFF 设置模糊搜索匹配的最低相似度阈值默认0.6可以配0到1直接的小数越小越模糊越大越精准对应后台的 【模糊匹配阈值】。具体见 <https://github.com/hanxi/xiaomusic/issues/52>
- XIAOMUSIC_PUBLIC_PORT 用于设置外网端口,对应后台的 【外网访问端口】当使用反向代理时可以设置为外网端口XIAOMUSIC_HOSTNAME 设为外网IP或者域名即可。
- XIAOMUSIC_DOWNLOAD_PATH 变量可以配置下载目录,默认为空,表示使用 music 目录为下载目录,对应后台的 【音乐下载目录】。设置这个目录必须是 music 的子目录,否则刷新列表后会找不到歌曲。具体见 <https://github.com/hanxi/xiaomusic/issues/98>
- XIAOMUSIC_PROXY 用于配置国内使用 youtube 源下载歌曲时使用的代理,参数格式参考 yt-dlp 文档说明。 见 <https://github.com/hanxi/xiaomusic/issues/2><https://github.com/hanxi/xiaomusic/issues/11>
- MIIO_TTS_CMD 用于部分机型(如:`L05C`)使用 MiIO 支持 tts 能力,默认为空,命令选择见 [MiService-fork 文档](https://github.com/yihong0618/MiService)
<https://github.com/hanxi/xiaomusic/issues/333>
### ⚠️ 安全提醒
## ⚠️ 安全提醒
> [!IMPORTANT]
>
> 1. 如果配置了公网访问 xiaomusic ,请一定要开启密码登陆,并设置复杂的密码。且不要在公共场所的 WiFi 环境下使用,否则可能造成小米账号密码泄露。
> 2. 强烈不建议将小爱音箱的小米账号绑定摄像头,代码难免会有 bug ,一旦小米账号密码泄露,可能监控录像也会泄露。
@@ -318,7 +249,8 @@ docker build -t xiaomusic .
## 📢 讨论区
- [点击链接加入QQ频道【xiaomusic】](https://pd.qq.com/s/e2jybz0ss)
- [点击链接加入群聊【xiaomusic】 604526973](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=13St5PLVcTxYlWTAs_iAawazjtdD1l-a&authKey=dJWEpaT2fDBDpdUUOWj%2FLt6NS1ePBfShDfz7a6seNURi05VvVnAGQzXF%2FM%2F5HgIm&noverify=0&group_code=604526973)
- [点击链接加入群聊【xiaomusic官方交流群1(小爱音箱)】 604526973](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=13St5PLVcTxYlWTAs_iAawazjtdD1l-a&authKey=dJWEpaT2fDBDpdUUOWj%2FLt6NS1ePBfShDfz7a6seNURi05VvVnAGQzXF%2FM%2F5HgIm&noverify=0&group_code=604526973)
- [点击链接加入群聊【xiaomusic官方交流群2(小爱音箱)】1021062499](https://qm.qq.com/q/BmVNqhDL3M)
- <https://github.com/hanxi/xiaomusic/issues>
- [微信群二维码](https://github.com/hanxi/xiaomusic/issues/86)
@@ -334,6 +266,7 @@ docker build -t xiaomusic .
- [微信小程序: XIAO晓音](https://github.com/F-loat/xiaoplayer)
- [pure 主题 xiaomusicUI](https://github.com/52fisher/xiaomusicUI)
- [移动端的播放器主题](https://github.com/52fisher/XMusicPlayer)
- [Tailwind主题](https://github.com/clarencejh/xiaomusic)
- [一个第三方的主题](https://github.com/DarrenWen/xiaomusicui)
- [Umami 统计](https://github.com/umami-software/umami)
- [Sentry 报错监控](https://github.com/getsentry/sentry)
@@ -365,4 +298,3 @@ docker build -t xiaomusic .
## License
[MIT](https://github.com/hanxi/xiaomusic/blob/main/LICENSE) License © 2024 涵曦

View File

@@ -46,23 +46,23 @@ export default async ({ mode }) => {
},
},
logLevel: 'warn',
vite:{
vite: {
plugins: [
AutoSidebar({
path:'.',
path: '.',
collapsed: true,
titleFromFile: true,
}),
GitHubIssuesPlugin({
repo: 'hanxi/xiaomusic',
token: env.VITE_GITHUB_ISSUES_TOKEN,
replaceRules:[
replaceRules: [
{
baseUrl: 'https://github.com/hanxi/xiaomusic/issues',
targetUrl: '/issues',
},
],
githubProxy: 'https://github.hanxi.cc/proxy',
githubProxy: 'https://gproxy.hanxi.cc/proxy',
}),
],
}

View File

@@ -11,8 +11,8 @@ hero:
text: 快速开始
link: /issues/index
- theme: alt
text: 文档汇总
link: /issues/211
text: FAQ
link: /issues/99
- theme: alt
text: GitHub
link: https://github.com/hanxi/xiaomusic

View File

@@ -30,7 +30,7 @@ docker pull dockerhub.anzu.vip/xiaomusic:latest
## 5. 安装完成后就进入群晖 DOCKER 配置 xiaomusic
<img width="491" alt="image" src="https://github.hanxi.cc/proxy/hanxi/xiaomusic/assets/38914725/e318062b-bd70-464c-a8df-8ce3635f2d84">
<img width="491" alt="image" src="https://gproxy.hanxi.cc/proxy/hanxi/xiaomusic/assets/38914725/e318062b-bd70-464c-a8df-8ce3635f2d84">
- MI_HARDWARE=型号 前面第4 步骤获取的
- XIAOMUSIC_SEARCH=搜索方式我填写的bilisearch: 意思是通过 bilibili 搜索
@@ -41,11 +41,11 @@ docker pull dockerhub.anzu.vip/xiaomusic:latest
## 6. 配置端口
<img width="757" alt="image (1)" src="https://github.hanxi.cc/proxy/hanxi/xiaomusic/assets/38914725/2b6b9283-296f-4845-a3ff-0ebb11f548b4">
<img width="757" alt="image (1)" src="https://gproxy.hanxi.cc/proxy/hanxi/xiaomusic/assets/38914725/2b6b9283-296f-4845-a3ff-0ebb11f548b4">
## 7. 映射路径
<img width="737" alt="image (2)" src="https://github.hanxi.cc/proxy/hanxi/xiaomusic/assets/38914725/593718dd-8302-4a69-bec9-36e70f3f0407">
<img width="737" alt="image (2)" src="https://gproxy.hanxi.cc/proxy/hanxi/xiaomusic/assets/38914725/593718dd-8302-4a69-bec9-36e70f3f0407">

View File

@@ -350,7 +350,7 @@ key_word_dict中的“播放歌曲”口令是不能修改的是吧因为以
### 评论 16 - mogeqian
不行,后台设置如图
![QQ截图20241111181411](https://github.hanxi.cc/proxy/user-attachments/assets/cc89512f-cab9-488d-b0d6-5b2a3a720ac2)
![QQ截图20241111181411](https://gproxy.hanxi.cc/proxy/user-attachments/assets/cc89512f-cab9-488d-b0d6-5b2a3a720ac2)
日志如下:
```
[2024-11-11 18:08:04] [0.3.46] [INFO] xiaomusic.py:1130: update_config_from_setting ok. data:Config(account='**', password='**', mi_did='726577518,570867755', miio_tts_command='', cookie='', verbose=False, music_path='music', download_path='music/download', conf_path='conf', cache_dir='cache', hostname='192.168.22.4', port=8090, public_port=0, proxy='', search_prefix='bilisearch:', ffmpeg_location='./ffmpeg/bin', active_cmd='play,set_random_play,playlocal,play_music_list,stop', exclude_dirs='@eaDir', music_path_depth=10, disable_httpauth=True, httpauth_username='******', httpauth_password='******', music_list_url='', music_list_json='', custom_play_list_json='', disable_download=False, key_word_dict={'播放歌曲': 'play', '播放本地歌曲': 'playlocal', '关机': 'stop', '下一首': 'play_next', '上一首': 'play_prev', '单曲循环': 'set_play_type_one', '全部循环': 'set_play_type_all', '随机播放': 'set_random_play', '分钟后关机': 'stop_after_minute', '播放列表': 'play_music_list', '刷新列表': 'gen_music_list', '加入收藏': 'add_to_favorites', '收藏歌曲': 'add_to_favorites', '取消收藏': 'del_from_favorites', '播放列表第': 'play_music_list_index', '本地播放歌曲': 'playlocal', '查找歌曲': 'play', '下载歌曲': 'play', '暂停': 'stop', '停止': 'stop', '停止播放': 'stop', '播放歌单': 'play_music_list', '测试自定义口令': 'exec#code1("hello")', '测试链接': 'exec#httpget("https://github.com/hanxi/xiaomusic")'}, key_match_order=['分钟后关机', '播放歌曲', '下一首', '上一首', '单曲循环', '全部循环', '随机播放', '关机', '刷新列表', '播放列表第', '播放列表', '加入收藏', '收藏歌曲', '取消收藏', '播放本地歌曲', '本地播放歌曲', '查找歌曲', '下载歌曲', '暂停', '停止', '停止播放', '播放歌单', '测试自定义口令', '测试链接'], use_music_api=False, use_music_audio_id='1582971365183456177', use_music_id='355454500', log_file='/tmp/xiaomusic.txt', fuzzy_match_cutoff=0.6, enable_fuzzy_match=True, stop_tts_msg='收到,再见', enable_config_example=False, keywords_playlocal='播放本地歌曲,本地播放歌曲', keywords_play='查找歌曲,下载歌曲', keywords_stop='关机,暂停,停止,停止播放', keywords_playlist='播放列表,播放歌单', user_key_word_dict={'测试自定义口令': 'exec#code1("hello")', '测试链接': 'exec#httpget("https://github.com/hanxi/xiaomusic")'}, enable_force_stop=False, devices={'726577518': Device(did='726577518', device_id='******', hardware='LX06', name='小爱音箱Pro', play_type='', cur_music='', cur_playlist='全部'), '570867755': Device(did='570867755', device_id='*********', hardware='L15A', name='小米AI音箱(第二代)', play_type='', cur_music='', cur_playlist='全部')}, group_list='', remove_id3tag=False, convert_to_mp3=False, delay_sec=3, continue_play=False, pull_ask_sec=1, crontab_json='', enable_yt_dlp_cookies=False, get_ask_by_mina=False)

View File

@@ -16,14 +16,14 @@ title: yt-dlp cookies 文件上传功能
1. 下载插件 [Get cookies.txt LOCALLY](https://chromewebstore.google.com/detail/cclelndahbckbenkjhflpdbgdldlbecc)
2. 给予插件访问权限和无痕模式允许使用
![image](https://github.hanxi.cc/proxy/user-attachments/assets/89f6ce94-bb51-4805-8c16-a867ba41e5d2)
![image](https://gproxy.hanxi.cc/proxy/user-attachments/assets/89f6ce94-bb51-4805-8c16-a867ba41e5d2)
3. 打开无痕窗口
4. 打开 youtube.com
5. 登陆 youtube.com
6. 打开新标签页
7. 关闭 youtube.com 的标签页
8. 保存 cookies.txt
![image](https://github.hanxi.cc/proxy/user-attachments/assets/64242595-7b5c-4159-a8bc-4fc922d5de9e)
![image](https://gproxy.hanxi.cc/proxy/user-attachments/assets/64242595-7b5c-4159-a8bc-4fc922d5de9e)
原因见 https://github.com/yt-dlp/yt-dlp/wiki/Extractors#exporting-youtube-cookies
@@ -31,10 +31,10 @@ title: yt-dlp cookies 文件上传功能
1. 打开设置页面
2. 设置启用yt-dlp-cookies 选项为 true
![Screenshot_2024-09-29-22-31-40-134_com android chrome-edit](https://github.hanxi.cc/proxy/user-attachments/assets/49760905-475b-493c-9ff4-271c5e797b2f)
![Screenshot_2024-09-29-22-31-40-134_com android chrome-edit](https://gproxy.hanxi.cc/proxy/user-attachments/assets/49760905-475b-493c-9ff4-271c5e797b2f)
3. 点击保存
4. 再点击选择文件,选择前面保存好的 cookies.txt 文件,点击上传。
![Screenshot_2024-09-29-22-33-21-361_com android chrome-edit](https://github.hanxi.cc/proxy/user-attachments/assets/838bfd1c-f19f-4690-86b0-8208d596fbf1)
![Screenshot_2024-09-29-22-33-21-361_com android chrome-edit](https://gproxy.hanxi.cc/proxy/user-attachments/assets/838bfd1c-f19f-4690-86b0-8208d596fbf1)
## 后续用途
@@ -50,7 +50,7 @@ title: yt-dlp cookies 文件上传功能
### 评论 1 - kingfly2016
0.3.37的版本并没有发现可以开启yt-dlp-cookies 并上传cookies文件的地方,尝试把导出的cookies.txt手工上传到conf目录下,没有生效.
![屏幕截图_11-10-2024_183725_192 168 6 202](https://github.hanxi.cc/proxy/user-attachments/assets/9b8b9750-b616-4fd3-8a3c-216b2f99d02c)
![屏幕截图_11-10-2024_183725_192 168 6 202](https://gproxy.hanxi.cc/proxy/user-attachments/assets/9b8b9750-b616-4fd3-8a3c-216b2f99d02c)
---
@@ -69,5 +69,42 @@ title: yt-dlp cookies 文件上传功能
谢谢
---
### 评论 4 - sunmiao0301
20250117实测可用
---
### 评论 5 - Lonely-Sit
> 20250117实测可用
佬你今天还可以使用吗?我按照教程操作了但是下载不下来歌曲
---
### 评论 6 - sunmiao0301
> > 20250117实测可用
>
> 佬你今天还可以使用吗?我按照教程操作了但是下载不下来歌曲
用cookie的方式可能会被封号ytb限制的是ip更好的办法是切换一下梯子节点多试几个。
---
### 评论 7 - Lonely-Sit
> > > 20250117实测可用
> >
> >
> > 大佬你今天还可以用吗?我按照教程操作了但是下载不下来歌曲
>
> 用cookie限制的方式可能会被封号ytb是ip更好的办法是切换一下梯子节点多试几个。
我使用相同ip在电脑端下载歌曲就没有问题 我无法理解
---
[链接到 GitHub Issue](https://github.com/hanxi/xiaomusic/issues/210)

View File

@@ -11,9 +11,11 @@ title: 📝 文档汇总
- [如何配置网络歌单](/issues/78.html)
- [如何添加m3u格式文件的电台](/issues/88.html)
- [xiaomusic极空间安装教程](/issues/297.html)
- [docker compose 命令行安装教程 ](/issues/360.html)
## 2⃣ 进阶文档
- [设置项功能介绍](/issues/333.html)
- [采用config.json配置方式](/issues/94.html)
- [ios系统上的捷径配置](/issues/96.html)
- [【插件】自定义口令功能](/issues/105.html)
@@ -91,5 +93,44 @@ mi.com官网重新登陆。
目前反馈的都是飞牛的用户,可能是飞牛有问题。
---
### 评论 7 - 3794313569
在同一个容器内前后分别启动了mi-gpt和xiaomusic两个应用现在通过日志发现mi-gpt的日志一直在记录语音需求基本都在mi-gpt这个应用响应了请问下按照您现在设计的框架内有没有办法可以实现这两个应用同时生效或者稍后类似应用会有专用的通讯协议保证多项应用在同一台机器上的响应。
类似:语音命令-“播放本地歌曲”触发xiaomusic“召唤”mi-gpt配置的唤醒词触发mi-gpt等等。。。。。。
暂时的办法就是买两个小爱音箱不同的命名然后一个应用配置一个did。
---
### 评论 8 - hanxi
> 在同一个容器内前后分别启动了mi-gpt和xiaomusic两个应用现在通过日志发现mi-gpt的日志一直在记录语音需求基本都在mi-gpt这个应用响应了请问下按照您现在设计的框架内有没有办法可以实现这两个应用同时生效或者稍后类似应用会有专用的通讯协议保证多项应用在同一台机器上的响应。 类似:语音命令-“播放本地歌曲”触发xiaomusic“召唤”mi-gpt配置的唤醒词触发mi-gpt等等。。。。。。 暂时的办法就是买两个小爱音箱不同的命名然后一个应用配置一个did。
可以分别部署到两个不同的容器里,两个应用的唤醒词是不同的,不会互相干扰。
---
### 评论 9 - Tranceboox
如果网页端主页内能显示播放曲目的封面就太牛了,我知道实现起来很难,就是臆想一下
---
### 评论 10 - hanxi
> 如果网页端主页内能显示播放曲目的封面就太牛了,我知道实现起来很难,就是臆想一下
xplayer 和 pure 主题就可以,你试试。
---
### 评论 11 - aries0311
Pure主题中设备列表中只有本机不显示小米音箱
![01](https://gproxy.hanxi.cc/proxy/user-attachments/assets/ca231b5f-ee4f-430b-a2b3-aca5aa395081)
![02](https://gproxy.hanxi.cc/proxy/user-attachments/assets/a3a83d1f-a822-42d0-bea9-b88bb1f5fd76)
---
[链接到 GitHub Issue](https://github.com/hanxi/xiaomusic/issues/211)

View File

@@ -10,7 +10,7 @@ title: 如何批量下载歌曲
> 默认主题 => 设置 => 歌曲下载工具
![Screenshot_2024-09-29-22-36-12-178_com android chrome-edit](https://github.hanxi.cc/proxy/user-attachments/assets/ddd2af00-cd9e-4938-9450-56503453807c)
![Screenshot_2024-09-29-22-36-12-178_com android chrome-edit](https://gproxy.hanxi.cc/proxy/user-attachments/assets/ddd2af00-cd9e-4938-9450-56503453807c)
已经测试过 B 站和 youtube 两种播放列表,播放列表的链接是有要求,不能有其他多余参数。
@@ -38,7 +38,7 @@ https://m.youtube.com/playlist?list=PLUD2d-pqyvT6_ztf31hx-5SsUUvY5UsQn
默认主题 => 设置 =>没有显示找到 歌曲下载工具,
有一个 歌单地址 歌单内容: 输入B站测试地址显示返回无效
![aaa](https://github.hanxi.cc/proxy/user-attachments/assets/31e224cb-fcbd-4841-b545-bfbd2496061b)
![aaa](https://gproxy.hanxi.cc/proxy/user-attachments/assets/31e224cb-fcbd-4841-b545-bfbd2496061b)
---

View File

@@ -19,5 +19,66 @@ title: xiaomusic立体声
我这边先用一个音箱播放,然后米家里设置全屋播放,就能多个音箱同时播了,进度也同步,而且后续会自动全屋播放
---
### 评论 3 - zazhi4
我遇到双音箱播放问题,没法立体声,没法全屋播放,详述如下:
1、基本情况原有小爱音箱ProLX06用xiaomusic0.3.69版本播放正常。看到issue里提及了立体声打算尝试新购了小爱音箱,L06A。将新音箱通过米家APP加入到自家的wifi里。
2、尝试
2.1在xiaomusic里默认面板设置发现可以在小爱音箱设置面板里有两个音箱供选择我都勾选了在设备分组配置里两个音箱的did输入配为1个组能实现同时驱动两个音箱发声但是不同步时间上差了不到1秒钟但是听起来不舒服。
2.2 在xiaomusic里默认面板设置只勾选1个音箱设备分组配置里删除原先配置清空。播放只有一只音箱有声音。然后回到米家APP。将两个音箱设置组成立体声。完成后依然只有一只音箱有声音。设置后对播放没有影响。
2.3 在米家APP中取消立体声配对改为“全屋播放”。设置好后依然只有一只音箱有声音。换言之设置后对播放没有影响。
3、检查版本在小米音箱app中检查两只音箱的版本均为最新稳定版。
![1736217346124](https://gproxy.hanxi.cc/proxy/user-attachments/assets/1fa61ded-0044-4577-8b3f-76d03bfe2453)
![1736217346117](https://gproxy.hanxi.cc/proxy/user-attachments/assets/ad3d13ea-0070-4fee-a2d8-814242efd9f8)
![1736217346120](https://gproxy.hanxi.cc/proxy/user-attachments/assets/6b43db2f-80fd-4aa7-97c7-3edaee304a5f)
![1736217346108](https://gproxy.hanxi.cc/proxy/user-attachments/assets/a274b712-d15b-4e6f-b036-c16e291b841f)
![1736217346113](https://gproxy.hanxi.cc/proxy/user-attachments/assets/194deb50-c0f6-4c09-a241-ab2360301c51)
![1736217346103](https://gproxy.hanxi.cc/proxy/user-attachments/assets/675e53fb-2f33-4c9f-9db2-39a969d549bf)
---
### 评论 4 - zazhi4
再补充一点信息,我做的尝试,以及网上都到的信息。
1、配立体声配好以后我用了当前页面的“立体声音效测试”两个音箱都能发声声音有先后有不同有联系形成了立体声效果。
2、配立体声配好以后还在米家app用qq音乐放了一首歌两个音箱都能发声有立体声效果。
3、网上查询一些信息均表明只有qq或其他在米家里播放的换言之网络来的信息通过米家向音箱播音能实现立体声。其他方法比如蓝牙或AUX都没法实现立体声。推测是米家主动发音的时候内部拆解了左右声道的声音发往左右音箱。
4、原本猜想两个音箱会一主一从主音箱拆分声音发往从音箱。但是在米家APP里配置立体声时未发现主从之分。
---
### 评论 5 - hanxi
全屋播放,控制两个音箱中的任意一个都不行吗?
---
### 评论 6 - zazhi4
全屋播放设置音箱A设置界面只选A当然只能选一个。共有3个选项音箱A音箱B手机播放音箱B没声音设置音箱B播放音箱A没声音。
---
### 评论 7 - Bazinga-git
组立体声是刚需,大佬加油
---
### 评论 8 - zazhi4
立体声想了几个路径1xiaomusic能不能拆分声音为左右两个声道分别发往两个音箱难题在于怎么保证两个音箱同时接到信息发声2能不能搞定米家app的接口发送声音给米家app由米家app发给音箱3或是搞定模拟米家app与音箱的接口通过米家接口发给音箱让音箱以为声音来自米家app。方法23要搞清楚米家app播音为什么能实现立体声然后在方法2,3中选一个方向。
---
### 评论 9 - hanxi
@zazhi4 思路是对的,感兴趣可以抓包玩玩的。目前协议是没加密的。
---
[链接到 GitHub Issue](https://github.com/hanxi/xiaomusic/issues/235)

View File

@@ -223,7 +223,7 @@ def getmy_playlist(type="netease",api_host="http://127.0.0.1/api", playlist_id=N
> 等有空我写个修改歌单内容的插件示例吧。
不用拉,插件我已经写出来了
![image](https://github.hanxi.cc/proxy/user-attachments/assets/53e593e7-1439-4968-9549-8c84b2fee42c)
![image](https://gproxy.hanxi.cc/proxy/user-attachments/assets/53e593e7-1439-4968-9549-8c84b2fee42c)
@@ -250,7 +250,7 @@ def getmy_playlist(type="netease",api_host="http://127.0.0.1/api", playlist_id=N
### 评论 13 - dissipator
# 成功了
![image](https://github.hanxi.cc/proxy/user-attachments/assets/33e22665-b1cc-4069-9e8c-46e466679b30)
![image](https://gproxy.hanxi.cc/proxy/user-attachments/assets/33e22665-b1cc-4069-9e8c-46e466679b30)
# 最好是在setting.json里去配置我测试老是不匹配在setting.json里去配置终于成功。可以直接调用 [NeteaseCloudMusicApi](http://localhost:3000/docs/#/?id=neteasecloudmusicapi) 接口甚至使用UnblockNeteaseMusic 解锁灰色,但是代码需要小调整。
setting.json
@@ -490,8 +490,8 @@ async def getmy_playlist(type="netease",api_host="http://127.0.0.1/api", playlis
### 评论 14 - dissipator
![image](https://github.hanxi.cc/proxy/user-attachments/assets/7412eec4-f7d3-4a86-b186-0118d6f331ff)
![image](https://github.hanxi.cc/proxy/user-attachments/assets/2215e520-0d40-4c2c-8d46-d3106d65fc51)
![image](https://gproxy.hanxi.cc/proxy/user-attachments/assets/7412eec4-f7d3-4a86-b186-0118d6f331ff)
![image](https://gproxy.hanxi.cc/proxy/user-attachments/assets/2215e520-0d40-4c2c-8d46-d3106d65fc51)
---
@@ -500,7 +500,7 @@ async def getmy_playlist(type="netease",api_host="http://127.0.0.1/api", playlis
NeteaseCloudMusicApi似乎获取不到播放地址其他信息倒是有。
![2024-11-28_151952](https://github.hanxi.cc/proxy/user-attachments/assets/c7e7a748-aa82-47f0-8784-f6469cc3e99b)
![2024-11-28_151952](https://gproxy.hanxi.cc/proxy/user-attachments/assets/c7e7a748-aa82-47f0-8784-f6469cc3e99b)
---

View File

@@ -23,10 +23,10 @@ title: 相关工具推荐
### 截图
<p>
<img src="https://assets-1251785959.cos.ap-beijing.myqcloud.com/xiaoplayer/screenshot/1.jpg" width="24%" />
<img src="https://assets-1251785959.cos.ap-beijing.myqcloud.com/xiaoplayer/screenshot/2.jpg" width="24%" />
<img src="https://assets-1251785959.cos.ap-beijing.myqcloud.com/xiaoplayer/screenshot/4.jpg" width="24%" />
<img src="https://assets-1251785959.cos.ap-beijing.myqcloud.com/xiaoplayer/screenshot/3.jpg" width="24%" />
<img src="https://assets-1251785959.cos.ap-beijing.myqcloud.com/xiaoplayer/screenshot/5.png" width="24%" />
<img src="https://assets-1251785959.cos.ap-beijing.myqcloud.com/xiaoplayer/screenshot/6.png" width="24%" />
<img src="https://assets-1251785959.cos.ap-beijing.myqcloud.com/xiaoplayer/screenshot/7.png" width="24%" />
<img src="https://assets-1251785959.cos.ap-beijing.myqcloud.com/xiaoplayer/screenshot/8.png" width="24%" />
</p>
---

View File

@@ -10,7 +10,7 @@ M01:在0.3.55版本【型号兼容模式】与【特殊型号获取对话记录
型号:S12A、LX04、S12 在米家APP可以联动比如客厅有人自定义指令:播放歌曲、关机...等
而M01无论【型号兼容模式】与【特殊型号获取对话记录】设为false或true都无法执行任何自定义指令…
![IMG_6460](https://github.hanxi.cc/proxy/user-attachments/assets/0913e3fa-1f1a-47b0-b8b9-d308bd7793df)
![IMG_6460](https://gproxy.hanxi.cc/proxy/user-attachments/assets/0913e3fa-1f1a-47b0-b8b9-d308bd7793df)
## 评论

View File

@@ -1,8 +1,8 @@
---
title: xiaomusic极空间安装教程2024/12/4更新)
title: xiaomusic极空间安装教程2024/12/28更新)
---
# xiaomusic极空间安装教程2024-12-4更新)
# xiaomusic极空间安装教程2024-12-28更新)
> 本教程同步更新于最新版的xiaomusic
@@ -16,10 +16,10 @@ title: xiaomusic极空间安装教程2024/12/4更新
1.**搜索框** 中输入 `hanxi/xiaomusic`,在搜索的结果中直接选择第一个,点击**下载**
![图片](https://github.hanxi.cc/proxy/user-attachments/assets/ef18b479-aef3-4e76-a299-6f220fc9e549)
![图片](https://gproxy.hanxi.cc/proxy/user-attachments/assets/ef18b479-aef3-4e76-a299-6f220fc9e549)
2. 在新弹出的版本选择窗口中,根据你的情况选择。
![图片](https://github.hanxi.cc/proxy/user-attachments/assets/20dd0b64-9223-47ae-a3e4-0b0af05796f8)
![图片](https://gproxy.hanxi.cc/proxy/user-attachments/assets/20dd0b64-9223-47ae-a3e4-0b0af05796f8)
### 版本说明
- 获取 **最新版** 直接点击 **下载** 即可,建议使用默认的 `latest`
@@ -28,7 +28,7 @@ title: xiaomusic极空间安装教程2024/12/4更新
3. 接着弹出如图所示的页面,耐心等待下载完成。
![图片](https://github.hanxi.cc/proxy/user-attachments/assets/5ea2621a-bba5-4269-b896-0e6ca323beb8)
![图片](https://gproxy.hanxi.cc/proxy/user-attachments/assets/5ea2621a-bba5-4269-b896-0e6ca323beb8)
4. 下载完成后切换到 **本地镜像** 选项卡
@@ -37,19 +37,20 @@ title: xiaomusic极空间安装教程2024/12/4更新
## 国内环境:
1. 打开docker在左侧的菜单中选择 **镜像** 切换到 **仓库** 选项卡,点击 **自定义拉取** 按钮
![图片](https://github.hanxi.cc/proxy/user-attachments/assets/bf4ac64e-ce50-4456-bc7b-05530b5abc1b)
![图片](https://gproxy.hanxi.cc/proxy/user-attachments/assets/bf4ac64e-ce50-4456-bc7b-05530b5abc1b)
2. 在弹出的对话框中输入 ` m.daocloud.io/docker.io/hanxi/xiaomusic ` ,点击 **拉取** 按钮
![图片](https://github.hanxi.cc/proxy/user-attachments/assets/a8f91db7-eac9-472d-a920-a77c280bbc5e)
![图片](https://gproxy.hanxi.cc/proxy/user-attachments/assets/a8f91db7-eac9-472d-a920-a77c280bbc5e)
3. 下载完成后切换到 **本地镜像** 选项卡
# 部署镜像
1. 找到刚才已经拉取好的镜像,*单击选中*,点击 **添加到容器**
![图片](https://github.hanxi.cc/proxy/user-attachments/assets/6e0bcf60-d1aa-46ac-9053-5ad957f3d509)
![图片](https://gproxy.hanxi.cc/proxy/user-attachments/assets/6e0bcf60-d1aa-46ac-9053-5ad957f3d509)
2. 在弹出的 **创建容器** 菜单中,切换到 **文件夹路径** 选项卡中,按图中的提示进行配置。
![图片](https://github.hanxi.cc/proxy/user-attachments/assets/cca8bc1c-de8f-4d03-81eb-a0f2b06c121e)
![图片](https://gproxy.hanxi.cc/proxy/user-attachments/assets/cca8bc1c-de8f-4d03-81eb-a0f2b06c121e)
**注意:**
* 装载路径中的 **配置文件目录** 和 **音乐目录** 必须进行配置
* 装载路径中的 **配置文件目录** 和 **音乐目录** 必须进行配置**其他目录非必要请勿配置**
* 主题目录为方便开发主题调试时的配置选项,普通用户不能理解明确用途请**不要配置主题目录**,否则会报**HTTP Status 500 Internal Server Error** 错误
* 如有多个音乐目录,请按照下面的格式进行配置
| 文件/文件夹 | 装载路径 |
@@ -60,7 +61,7 @@ title: xiaomusic极空间安装教程2024/12/4更新
3. 切换到 **端口** 选项卡,修改成与你的极空间 *不冲突* 的本地端口号,如 `5678` 示例按照本地端口号5678来进行配置下同
> 友情提醒: 尽量不要修改容器端口号,否则要到配置文件目录修改对应的`setting.json`文件中的配置,会增加很多麻烦
![图片](https://github.hanxi.cc/proxy/user-attachments/assets/182b32ef-d91f-47c5-ba9d-7ef3542ebf40)
![图片](https://gproxy.hanxi.cc/proxy/user-attachments/assets/182b32ef-d91f-47c5-ba9d-7ef3542ebf40)
5. 切换到 **环境** 选项卡,将`XIAOMUSIC_HOSTNAME` 修改为你的 **极空间的IP地址**
> 友情提醒:
@@ -68,26 +69,26 @@ title: xiaomusic极空间安装教程2024/12/4更新
> 2. 不要尝试修改XIAOMUSIC_PORT除非你没有看上一条的友情提醒
> 3. 不要在此处配置`ACCOUNT`和`PASSWORD`,没有过风控仍然无法使用!上古时代的教程不要再看了,容易走火入魔!
![图片](https://github.hanxi.cc/proxy/user-attachments/assets/b41b7359-f2b9-4ad8-b2a2-0ce2a1601739)
![图片](https://gproxy.hanxi.cc/proxy/user-attachments/assets/b41b7359-f2b9-4ad8-b2a2-0ce2a1601739)
6. 点击 **应用**按钮,此时容器已经配置完成了,切换到左侧的 **容器概况** 菜单,可查看容器详情
![图片](https://github.hanxi.cc/proxy/user-attachments/assets/5c5b3497-49d8-4f17-9acb-6d1e551caf4f)
![图片](https://gproxy.hanxi.cc/proxy/user-attachments/assets/5c5b3497-49d8-4f17-9acb-6d1e551caf4f)
# 进入xiaomusic网页端进行配置
1.请关闭代理,打开浏览器,地址栏输入 **极空间IP:本地端口号**`192.168.2.5:5678`,打开网页后点击 **默认主题**
![图片](https://github.hanxi.cc/proxy/user-attachments/assets/1b286d0f-f10e-46ff-89a0-cdff9e192f9b)
![图片](https://gproxy.hanxi.cc/proxy/user-attachments/assets/1b286d0f-f10e-46ff-89a0-cdff9e192f9b)
**注意:**
* 不要复制此处的地址必须输入极空间的IP地址。不知道的建议上咸鱼50块换个不锈钢盆
* 不要输入容器的端口号8090极空间不能使用这个端口号。
2. 点击 **设置** 按钮进入设置页面
![图片](https://github.hanxi.cc/proxy/user-attachments/assets/f3aca07a-3663-4bb6-bb93-0329b2d4c433)
![图片](https://gproxy.hanxi.cc/proxy/user-attachments/assets/f3aca07a-3663-4bb6-bb93-0329b2d4c433)
3. 输入**小米账号**、**小米密码**、**XIAOMUSIC_HOSTNAME(IP或域名):**、**外网访问端口**,滑到页面最下方点击 **保存**
![图片](https://github.hanxi.cc/proxy/user-attachments/assets/db03af0c-851a-4185-a7fd-b5b02b6d8d2b)
![图片](https://github.hanxi.cc/proxy/user-attachments/assets/dd42a653-d364-4eec-9f87-efb3c52e57a7)
![图片](https://gproxy.hanxi.cc/proxy/user-attachments/assets/db03af0c-851a-4185-a7fd-b5b02b6d8d2b)
![图片](https://gproxy.hanxi.cc/proxy/user-attachments/assets/dd42a653-d364-4eec-9f87-efb3c52e57a7)
**注意:**
* 小米账号非手机号,请在手机设置-个人中心中查看小米ID
@@ -95,10 +96,10 @@ title: xiaomusic极空间安装教程2024/12/4更新
* XIAOMUSIC_HOSTNAME(IP或域名): 可以输入当前页面的IP地址在地址栏**不要在此处输入端口号!!!**如果域名需要使用https协议请加上https://
4.如果以上步骤没错,你将在设置中心看见设备列表
![图片](https://github.hanxi.cc/proxy/user-attachments/assets/04074894-6599-4b35-95ea-0618ed906d15)
![图片](https://gproxy.hanxi.cc/proxy/user-attachments/assets/04074894-6599-4b35-95ea-0618ed906d15)
5. 回到首页,出现设备列表,切换对应设备即可畅享
![图片](https://github.hanxi.cc/proxy/user-attachments/assets/1ce4791f-7ae7-40b4-8c90-eca6b0799e19)
![图片](https://gproxy.hanxi.cc/proxy/user-attachments/assets/1ce4791f-7ae7-40b4-8c90-eca6b0799e19)
## 评论
@@ -108,7 +109,7 @@ title: xiaomusic极空间安装教程2024/12/4更新
[xiaomusic.txt](https://github.com/user-attachments/files/18011572/xiaomusic.txt)
<img width="559" alt="截屏2024-12-05 00 43 24" src="https://github.hanxi.cc/proxy/user-attachments/assets/160aeacc-e1c0-40fa-b219-6b6f5183c43c">
<img width="559" alt="截屏2024-12-05 00 43 24" src="https://gproxy.hanxi.cc/proxy/user-attachments/assets/160aeacc-e1c0-40fa-b219-6b6f5183c43c">
an'zh
无法使用语音播放歌曲小爱s12a。极空间z4pro。
1. 按照教程点击播放本地歌曲提示hostname和设置的端口映射不匹配。映射5678容器端口8090.
@@ -128,10 +129,10 @@ an'zh
### 评论 3 - xiaohuobanhahaha
我没讲清楚。我试了两种极空间的桥接和host模式。桥接模式。我按照教程走的。报错如图
<img width="847" alt="截屏2024-12-05 01 46 52" src="https://github.hanxi.cc/proxy/user-attachments/assets/e7f58907-a216-41e8-bafa-5d49db8eca45">
<img width="516" alt="截屏2024-12-05 01 49 11" src="https://github.hanxi.cc/proxy/user-attachments/assets/4261c2e2-fe0c-4ff6-ae06-ead7f928af57">
<img width="647" alt="截屏2024-12-05 01 47 02" src="https://github.hanxi.cc/proxy/user-attachments/assets/35b195d1-9512-40bb-b336-847e0bb2e6c9">
<img width="667" alt="截屏2024-12-05 01 47 15" src="https://github.hanxi.cc/proxy/user-attachments/assets/b917a977-38cf-4126-8754-c46abe9360a2">
<img width="847" alt="截屏2024-12-05 01 46 52" src="https://gproxy.hanxi.cc/proxy/user-attachments/assets/e7f58907-a216-41e8-bafa-5d49db8eca45">
<img width="516" alt="截屏2024-12-05 01 49 11" src="https://gproxy.hanxi.cc/proxy/user-attachments/assets/4261c2e2-fe0c-4ff6-ae06-ead7f928af57">
<img width="647" alt="截屏2024-12-05 01 47 02" src="https://gproxy.hanxi.cc/proxy/user-attachments/assets/35b195d1-9512-40bb-b336-847e0bb2e6c9">
<img width="667" alt="截屏2024-12-05 01 47 15" src="https://gproxy.hanxi.cc/proxy/user-attachments/assets/b917a977-38cf-4126-8754-c46abe9360a2">
提到的第二个问题和日志是我将网络模式改为host的情况能连上音箱但是没法使用语音控制。
@@ -186,8 +187,8 @@ an'zh
### 评论 9 - xiaohuobanhahaha
<img width="660" alt="截屏2024-12-05 02 23 53" src="https://github.hanxi.cc/proxy/user-attachments/assets/b9d26de9-3dcf-4e65-9460-36603735c887">
<img width="780" alt="截屏2024-12-05 02 24 49" src="https://github.hanxi.cc/proxy/user-attachments/assets/6a204cdb-bb10-4f35-822d-613aeed0fae0">
<img width="660" alt="截屏2024-12-05 02 23 53" src="https://gproxy.hanxi.cc/proxy/user-attachments/assets/b9d26de9-3dcf-4e65-9460-36603735c887">
<img width="780" alt="截屏2024-12-05 02 24 49" src="https://gproxy.hanxi.cc/proxy/user-attachments/assets/6a204cdb-bb10-4f35-822d-613aeed0fae0">
> > 确实是变了。192.168.31.143是我电脑的ip。 hostname='192.168.31.165'是极空间的。小爱是192.168.31.77。现在我的网络结构是电脑连nas上的istoreos旁路由。nas直连主路由小爱直连主路由。主路由dhcp都绑定了。 大佬,这种情况该怎么解决呢。所有设置都是默认,没修改哈。
@@ -228,5 +229,36 @@ an'zh
已自查解决。问题是账号问题。绑定设备的一定是创建者,不能是管理员。
---
### 评论 12 - McCree2020
这个主题目录不能设置吧没人遇到这个issue我原来用的张大妈平台的教程设置的能用后来看到这个教程后就修改了后台的路径映射但是dockers启动正常网页不能打开提示internal sever error后来ssh进docker看了日志文件 提示static那个路径有问题下边的index什么的文件找不到 删除主题映射以后重启docker后网页正常显示了
---
### 评论 13 - 52fisher
> 这个主题目录不能设置吧没人遇到这个issue我原来用的张大妈平台的教程设置的能用后来看到这个教程后就修改了后台的路径映射但是dockers启动正常网页不能打开提示internal sever error后来ssh进docker看了日志文件 提示static那个路径有问题下边的index什么的文件找不到 删除主题映射以后重启docker后网页正常显示了
要注意看提示:
装载路径中的 配置文件目录 和 音乐目录 必须进行配置。
其他的路径非必要不要配置,主题目录路径是方便开发调试的时候用的,普通用户不要映射主题目录。我已经把这个提示更新到文档中了
---
### 评论 14 - zxhans
就不能让xiaomusic支持服务器部署吗服务器部署为啥设备不能读取呢home assistant 通过xiaomi home assistant都可以读取呀
---
### 评论 15 - hanxi
> 就不能让xiaomusic支持服务器部署吗服务器部署为啥设备不能读取呢home assistant 通过xiaomi home assistant都可以读取呀
支持服务器部署的,你需要在服务器上装个浏览器登陆过风控。
---
[链接到 GitHub Issue](https://github.com/hanxi/xiaomusic/issues/297)

31
docs/issues/333.md Normal file
View File

@@ -0,0 +1,31 @@
---
title: 设置项功能介绍
---
# 设置项功能介绍
- XIAOMUSIC_ACTIVE_CMD 环境变量,对应后台的 【允许唤醒的命令】,用于唤醒口令,配置成'play,random_play'在非播放状态下只有这两个指令播放歌曲和随机播放可以触发触发后xiaomusic进入playing状态其他指令则可以正常触发。具体见 <https://github.com/hanxi/xiaomusic/pull/43>
- XIAOMUSIC_EXCLUDE_DIRS 配置歌曲目录里需要忽略的目录,对应后台的 【忽略目录】
- XIAOMUSIC_MUSIC_PATH_DEPTH 配置歌曲目录搜索深度,对应后台的 【目录深度】,具体见 </issues/76.html>
- XIAOMUSIC_DISABLE_HTTPAUTH 配置成 false 表示开启密码访问web控制台对应后台的 【关闭密码验证】,具体见 </issues/47.html>
- XIAOMUSIC_HTTPAUTH_USERNAME 配置 web 控制台用户,对应后台的 【控制台账户】
- XIAOMUSIC_HTTPAUTH_PASSWORD 配置 web 控制台密码,对应后台的 【控制台密码】
- XIAOMUSIC_CONF_PATH 用来存放配置文件的目录,对应后台的 【配置文件目录】,记得把目录映射到主机,默认为 `/app/config` ,具体见 </issues/74.html>
- XIAOMUSIC_CACHE_DIR 用来音乐 tag 缓存,默认为 `/app/cache`,对应后台的 【缓存文件目录】。
- XIAOMUSIC_DISABLE_DOWNLOAD 设为 true 时关闭下载功能,对应后台的 【关闭下载功能】,见 </issues/82.html>
- XIAOMUSIC_USE_MUSIC_API 设为 true 时使用 player_play_music 接口播放音乐,对应后台的 【型号兼容模式】,用于兼容不能播放的型号,如果发现需要设置这个选项的时候请告知我加一下设备型号,方便以后不用设置。 见 </issues/30.html>
- XIAOMUSIC_KEYWORDS_PLAY 用来播放歌曲的口令前缀,对应后台的 【播放歌曲口令】,默认是 "播放歌曲,放歌曲" ,可以用英文逗号分割配置多个
- XIAOMUSIC_KEYWORDS_STOP 用来关机的口令,对应后台的 【停止口令】,默认是 "关机,暂停,停止" ,可以用英文逗号分割配置多个。
- XIAOMUSIC_KEYWORDS_PLAYLOCAL 用来播放本地歌曲的口令前缀,对应后台的 【播放本地歌曲口令】,本地找不到时不会下载歌曲,默认是 "播放本地歌曲,本地播放歌曲" ,可以用英文逗号分割配置多个。
- XIAOMUSIC_ENABLE_FUZZY_MATCH 设为 true 时开启模糊匹配(默认),设为 false 时关闭模糊匹配,对应后台的 【开启模糊搜索】,支持模糊匹配歌名和歌单名。 具体见 </issues/52.html>
- XIAOMUSIC_FUZZY_MATCH_CUTOFF 设置模糊搜索匹配的最低相似度阈值默认0.6可以配0到1直接的小数越小越模糊越大越精准对应后台的 【模糊匹配阈值】。具体见 </issues/52.html>
- XIAOMUSIC_PUBLIC_PORT 用于设置外网端口,对应后台的 【外网访问端口】当使用反向代理时可以设置为外网端口XIAOMUSIC_HOSTNAME 设为外网IP或者域名即可。
- XIAOMUSIC_DOWNLOAD_PATH 变量可以配置下载目录,默认为空,表示使用 music 目录为下载目录,对应后台的 【音乐下载目录】。设置这个目录必须是 music 的子目录,否则刷新列表后会找不到歌曲。具体见 </issues/98.html>
- XIAOMUSIC_PROXY 用于配置国内使用 youtube 源下载歌曲时使用的代理,参数格式参考 yt-dlp 文档说明。 见 </issues/2.html> 和 </issues/11.html>
- MIIO_TTS_CMD 用于部分机型(如:`L05C`)使用 MiIO 支持 tts 能力,默认为空,命令选择见 [MiService-fork 文档](https://github.com/yihong0618/MiService)
## 评论
没有评论。
[链接到 GitHub Issue](https://github.com/hanxi/xiaomusic/issues/333)

29
docs/issues/350.md Normal file
View File

@@ -0,0 +1,29 @@
---
title: 播放本地歌曲无法切歌
---
# 播放本地歌曲无法切歌
播放本地歌曲时通过语音控制小爱音箱切歌测试指令小爱同学切歌小爱同学播放下一首每次都是重新播放上一首歌曲版本为docker最新版本[0.3.70]
## 评论
### 评论 1 - Leenshady
测试出来了,只有“小爱同学,下一首”指令才能正常切歌
---
### 评论 2 - sam0773
可以在conf文件夹的setting.json中把自己习惯的命令添加进去...
---
### 评论 3 - hanxi
楼上正解。
---
[链接到 GitHub Issue](https://github.com/hanxi/xiaomusic/issues/350)

74
docs/issues/360.md Normal file
View File

@@ -0,0 +1,74 @@
---
title: docker compose 命令行安装教程
---
# docker compose 命令行安装教程
本教程针对于有命令行环境,且已经安装好 docker compose 的用户。步骤超级简单,基本只要复制粘贴就能跑起来。如果需要修改路径或者端口,可以复制到编辑器,修改后再复制粘贴到命令行执行。编辑时注意不要修改到文件格式,包括缩进。
## 创建 docker-compose.yml 文件
假设 `docker-compose.yml` 文件的存放到路径为 `/xiaomusic/docker-compose.yml` 。执行下面的命令即可:
```shell
mkdir -p /xiaomusic
cat <<EOF > /xiaomusic/docker-compose.yml
services:
xiaomusic:
image: docker.hanxi.cc/hanxi/xiaomusic
container_name: xiaomusic
restart: unless-stopped
ports:
- 58090:8090
environment:
XIAOMUSIC_PUBLIC_PORT: 58090
volumes:
- /xiaomusic_conf:/app/conf
- /xiaomusic_music:/app/music
EOF
```
- `/xiaomusic_conf` 为配置文件存放目录,一般不需要修改。
- `/xiaomusic_music` 为音乐存放目录,你可以替换为自己想要存放的目录,注意填绝对路径,在 Linux 下是 `/` 开头的,在 Windows 下是盘符开头,比如: `D:/music`
- 端口 8090 不要修改,是容器内的端口。
- 端口 58090 可以修改,如果想要修改,两个 58090 都需要同时修改,这个端口是访问 web 后台的端口。
## 启动
```shell
cd /xiaomusic
docker compose up -d
```
启动后,就能使用 <http://nasip:58090> 来访问 web 后台了,把 nasip 替换成你的 nas 的 IP 。
## 后台设置
![image](https://gproxy.hanxi.cc/proxy/user-attachments/assets/424c45af-6937-4fee-bb7d-855973ef0d5d)
填好账号密码,和自动填 IP 和端口,然后滚动到页面最下面,点击保存按钮。然后刷新设置页面,再勾选小爱音箱,再保存即可。
![image](https://gproxy.hanxi.cc/proxy/user-attachments/assets/c63c3ff1-3a80-4f47-971e-761eb9187ae0)
## 更新
想要更新镜像,只需要复制粘贴下面的命令就行,注意 `/xiaomusic` 目录是 `docker-compose.yml` 文件所在的目录。
```shell
cd /xiaomusic
docker compose pull
docker compose up -d
```
## 关闭
```shell
cd /xiaomusic
docker compose down
```
## 评论
没有评论。
[链接到 GitHub Issue](https://github.com/hanxi/xiaomusic/issues/360)

28
docs/issues/365.md Normal file
View File

@@ -0,0 +1,28 @@
---
title: 已知 ttsCommand
---
# 已知 ttsCommand
参考: https://github.com/idootop/mi-gpt/blob/main/docs/compatibility.md
- 小爱音箱 Pro LX06 `5-1`
- 小爱音箱 mini LX01 `5-1`
- 小爱音箱 Play2019 款) LX05 `5-1`
- 小爱音箱 万能遥控版 LX5A `5-1`
- 小米 AI 音箱 S12 `5-1` `5-3`
- 小米 AI 音箱(第二代) L15A `7-3`
- 小爱智能家庭屏 10 X10A `7-3`
- Xiaomi Sound Pro L17A `7-3`
- 小爱音箱 L06A `5-1`
- 小爱音箱 Play L05B `5-3`
- 小米小爱音箱 Play 增强版 L05C `5-3`
- Xiaomi 智能家庭屏 6 X6A `7-3` `7-1`
- Redmi 小爱触屏音箱 Pro 8 英寸 X08E `7-3`
- 小爱音箱 Art L09A `3-1`
- 小爱触屏音箱 LX04 `5-1`
## 评论
没有评论。
[链接到 GitHub Issue](https://github.com/hanxi/xiaomusic/issues/365)

55
docs/issues/366.md Normal file
View File

@@ -0,0 +1,55 @@
---
title: 多设备单独播放功能设计
---
# 多设备单独播放功能设计
## 分组功能
为设备设计分组功能,可以把一个或者多个设备加入到一个分组,一个分组内的设备会被控制同时播放。设备的音量需要支持独立配置。
分组用 group_list 字段配置,比如 `did1:客厅,did2:客厅` 表示 did1和did2用同一个组名。不配置这个参数就说明一个设备一个分组。后台勾选设备的意图改为哪些设备可以接入。比如:
`319762914:a,319518426:a,1236547:b`
单个设备的存储配置结构如下:
```json
{
"devices": {
"10086": {
"cur_music": "当前播放的歌曲",
"cur_playlist": "当前播放的列表",
"name": "客厅的小爱1",
"play_type": 1
},
"10087": {
"cur_music": "当前播放的歌曲",
"cur_playlist": "当前播放的列表",
"name": "客厅的小爱2",
"play_type": 1
}
}
}
```
设备名字从音箱app设置里读取过来不用在后台修改。
配置采用组名相同为一组,可以考虑不设置组名就用设备名作为组名,也就是一个设备为一组。
后端提供的接口都改为支持操作多个设备,
单曲循环,随机播放这些操作都会同步修改同一个组里的其他设备。
歌单列表所有设备共享,当前选择的歌单和当前播放的歌曲组内共享,一个组共用一份播放列表,也就是共用一个定时器。
## 主页设备切换
主页主要是用于播放操作的,所有操作都是针对于单个设备的,所以在顶部加入一个切换设备的功能。除了修改声音不会同步修改组内设备,其他操作都会同时操作组内所有设备。
> /issues/65.html#issuecomment-2215736529
## 评论
没有评论。
[链接到 GitHub Issue](https://github.com/hanxi/xiaomusic/issues/366)

View File

@@ -256,7 +256,7 @@ stderr: [08:58:10] [0.3.37] [INFO] xiaomusic.py:1094: 播放 80后音悦台 失
### 评论 5 - 201692929
怎么获取 他正在播放什么?或者是播放进度 ?播放列表?我想给他加进去
![233333](https://github.hanxi.cc/proxy/user-attachments/assets/013cd952-69e9-4754-870f-2d5321865179)
![233333](https://gproxy.hanxi.cc/proxy/user-attachments/assets/013cd952-69e9-4754-870f-2d5321865179)
---
@@ -308,20 +308,20 @@ potplayer里播放完全正常~~
> 发出来看看?
经过实验发现本地生成的m3u用potplayer播放正常
![image](https://github.hanxi.cc/proxy/user-attachments/assets/754e4344-9262-4ad1-bf17-dd83f5e3b6e5)
![image](https://gproxy.hanxi.cc/proxy/user-attachments/assets/754e4344-9262-4ad1-bf17-dd83f5e3b6e5)
转换为json去掉"type":"radio")后用小爱播放也正常
![image](https://github.hanxi.cc/proxy/user-attachments/assets/9f1a9f02-6cf1-4536-91bd-e5e3677d6513)
![image](https://gproxy.hanxi.cc/proxy/user-attachments/assets/9f1a9f02-6cf1-4536-91bd-e5e3677d6513)
但是alist链接就不正常alist生成的m3u格式如下
`#EXTM3U
#EXTINF:-1,Let Me Hear.mp3
http://192.168.1.198:5244/d/%E7%BD%91%E6%98%93%E4%BA%91%E9%9F%B3%E4%B9%90%20%E9%9F%B3%E4%B9%90%E4%BA%91%E7%9B%98/Let%20Me%20Hear.mp3?sign=xxxx=:0`
没有时长信息但是用potplayer一播放就出现时长了
![image](https://github.hanxi.cc/proxy/user-attachments/assets/34ac4b9f-8b7f-40d7-9ac9-aa4621b59aa3)
![image](https://gproxy.hanxi.cc/proxy/user-attachments/assets/34ac4b9f-8b7f-40d7-9ac9-aa4621b59aa3)
而用小爱播放就始终没有时长(切歌、等待都试过了)
![image](https://github.hanxi.cc/proxy/user-attachments/assets/a42b62e4-7a48-46b8-b83b-a4c8cb219c0b)
![image](https://gproxy.hanxi.cc/proxy/user-attachments/assets/a42b62e4-7a48-46b8-b83b-a4c8cb219c0b)
大佬你的示例链接gist.github.com/hanxi/dda82d964a28f8110f8fba81c3ff8314里的又是正常的感觉可能是alist的流比较特殊。。
![image](https://github.hanxi.cc/proxy/user-attachments/assets/f84ab805-54a6-40f1-937c-67832ff0b9d6)
![image](https://gproxy.hanxi.cc/proxy/user-attachments/assets/f84ab805-54a6-40f1-937c-67832ff0b9d6)
---

View File

@@ -4,7 +4,10 @@ title: 微信交流群二维码
# 微信交流群二维码
![mmqrcode1734136802660](https://github.hanxi.cc/proxy/user-attachments/assets/a53867c9-f841-4873-b91b-35b877221fe1)
![Image](https://gproxy.hanxi.cc/proxy/user-attachments/assets/99c9524d-8df7-45f8-a393-8aad7fe0ef92)
如果你刚好在买流量卡,可以在我的微信卡店里看看有没有合适的。
![mmexportc6bd050862507d2806a2da710a82cb28_1735878113870](https://gproxy.hanxi.cc/proxy/user-attachments/assets/ca5a86e0-f753-42d3-8dcb-8583d50d64aa)
## 评论
@@ -24,7 +27,7 @@ title: 微信交流群二维码
### 评论 3 - hanxi
![mm_reward_qrcode_1726365700471](https://github.hanxi.cc/proxy/user-attachments/assets/7863e361-7e61-48a7-bd71-8f8f609f11b4)
![mm_reward_qrcode_1726365700471](https://gproxy.hanxi.cc/proxy/user-attachments/assets/7863e361-7e61-48a7-bd71-8f8f609f11b4)
---

View File

@@ -8,15 +8,15 @@ title: 如何添加m3u格式文件的电台
1. 复制文件内容,粘贴到 m3u 转换工具里,点击转换为 json 格式:
![Screenshot_2024-06-29-11-28-58-904_com android chrome](https://github.hanxi.cc/proxy/hanxi/xiaomusic/assets/1185757/bb812a47-17c5-4483-9234-4cf33367b181)
![Screenshot_2024-06-29-11-28-58-904_com android chrome](https://gproxy.hanxi.cc/proxy/hanxi/xiaomusic/assets/1185757/bb812a47-17c5-4483-9234-4cf33367b181)
2. 然后复制 json 内容,粘贴到歌单内容里,点击保存,再返回首页:
![Screenshot_2024-06-29-11-29-22-248_com android chrome](https://github.hanxi.cc/proxy/hanxi/xiaomusic/assets/1185757/2fb4ca44-6b79-4438-9bc6-cfbd01272f20)
![Screenshot_2024-06-29-11-29-22-248_com android chrome](https://gproxy.hanxi.cc/proxy/hanxi/xiaomusic/assets/1185757/2fb4ca44-6b79-4438-9bc6-cfbd01272f20)
3. 在首页点击刷新列表,选择所有电台,再点击播放列表歌曲:
![Screenshot_2024-06-29-11-29-55-621_com android chrome](https://github.hanxi.cc/proxy/hanxi/xiaomusic/assets/1185757/c94e4667-f83e-4cd5-9662-e680316cb5b4)
![Screenshot_2024-06-29-11-29-55-621_com android chrome](https://gproxy.hanxi.cc/proxy/hanxi/xiaomusic/assets/1185757/c94e4667-f83e-4cd5-9662-e680316cb5b4)
4. 也可以用口令播放电台: `播放列表所有电台` ,或者口令: `播放歌曲北京城市广播`

View File

@@ -14,7 +14,7 @@ pip install xiaomusic
依赖的 ffmpeg 需要自己安装。
![image](https://github.hanxi.cc/proxy/hanxi/xiaomusic/assets/1185757/6912e3ec-c42f-42de-b027-a296f5a26ba1)
![image](https://gproxy.hanxi.cc/proxy/hanxi/xiaomusic/assets/1185757/6912e3ec-c42f-42de-b027-a296f5a26ba1)
仓库中有个 config-example.json 文件,可以把这个文件拷贝为 config.json 然后修改 config.json 里的配置,再用下面的命令启动。

View File

@@ -6,9 +6,9 @@ title: ios系统上的捷径配置
下面是播放音乐和关机两个示例。只要在 web 页面上能看到的功能,都有对应的 http 请求接口,都可以用来配置捷径。
![mmexport1719767452647](https://github.hanxi.cc/proxy/hanxi/xiaomusic/assets/1185757/db0a1856-e1ed-47cb-972d-d997f71bf92b)
![mmexport1719767452647](https://gproxy.hanxi.cc/proxy/hanxi/xiaomusic/assets/1185757/db0a1856-e1ed-47cb-972d-d997f71bf92b)
![mmexport1719767449742](https://github.hanxi.cc/proxy/hanxi/xiaomusic/assets/1185757/92b7bc4b-9699-49cc-956a-4bddb6bd50fa)
![mmexport1719767449742](https://gproxy.hanxi.cc/proxy/hanxi/xiaomusic/assets/1185757/92b7bc4b-9699-49cc-956a-4bddb6bd50fa)
## 评论

View File

@@ -4,153 +4,194 @@ title: 💬 FAQ问题集合
# 💬 FAQ问题集合
> [!NOTE]
> 这个 issue 用来总结报错日志和对应的解决方法。
## ❓ XIAOMUSIC_HOSTNAME 怎么填
填写 docker 主机的 ip **不是小爱音箱的ip**,一般就是网页访问的后台地址里的 ip ,只要确保 ip 和小爱音箱在一个局域网内就行。
同时也支持 xx.xx.com 的域名格式,用于配置反代供外网访问,比如小爱音箱和 docker 主机不在同一个局域网内。
## ❓ Login Failed 登陆失败
表现就是 **后台看不到设备列表** ,日志中会有对应的报错。
这个有专门的讨论,见 </issues/16.html> 一般是因为开了加速代理关代理再尝试即可。也可以试试在局域网设备里的米家app上退出再重新登录一下。
在小米官网 www.mi.com 登陆过人脸或滑块验证基本上能解决 99%的 login failed 问题。
来自 @yilikun 的友情提示:
> 1. 关闭本地代理。
> 2. 如果是nas运行的网络由bridge改为host。
> 3. 米家app重新登陆。
> 4. mi.com官网重新登陆。
> 5. 检查 setting.json 文件里的账号密码是否正确。
## ❓ 网页后台可以播放,语音控制无效
这种情况是拉取不到对话记录导致的。
如果是首次在网页后台保存 did 后需要重启一次容器。
其他情况可能是被限制拉取对话记录次数,也可以尝试重启容器。
还有一种情况是配错了唤醒口令可以在小爱音箱app里查看对话记录也可以查看 xiaomusic 的日志。默认口令前缀是【播放歌曲】,没有这个前缀是无法识别的,说播放音乐是没用的,除非自己设置其他口令词。
已知 `M01/XMYX01JY 小米小爱音箱HD` 获取对话记录的接口比较特殊,需要开启【特殊型号获取对话记录:】开关才能正常语音控制。
## ❓ 日志显示正在播放,却没有声音
可以点击播放链接按钮,看看默认的那个链接能否播放。
已知部分触屏版不能播放可以在后台设置 【型号兼容模式】为 true 试试。
其他情况可能是 XIAOMUSIC_HOSTNAME 配错了地址,不是 docker 主机地址会导致小爱音箱无法访问到,而且需要和小爱音箱在同一个**局域网**下的地址。还有可能是端口配错了,**修改了默认 8090 端口映射**,需要同步修改其他参数,可以翻阅端口修改的文档。
如果端口不是8090首次启动没配好端口的话需要手动修改setting.json文件里的端口或者把setting.json文件删除重新配置或者在后台修改监听端口后重启。
可以点击播放歌曲后查看日志里的歌曲链接放到浏览器里打开试试不能访问说明是端口或者hostname问题如果是异地访问需要把 hostname 修改为外网ip或者域名需要注意音箱只支持访问ipv4不能是ipv6的公网。
如果是配了公网反代端口,注意区分是 http 还是 https ,如果是 https 的,配置 XIAOMUSIC_HOSTNAME 时需要加上 `https:// ` 前缀。
## ❓ 无法播放 flac 格式歌曲
因设备差异和文件格式差异,已知部分设备不支持 flac 格式,比如 L05B L05C 。
## ❓ docker 镜像拉取失败
请更换镜像源或者使用代理。不同环境更换镜像源的方式不一样,可以网上搜索自己的 NAS 如何更换镜像源。
已经可以通过 [DaoCloud](https://github.com/DaoCloud/public-image-mirror) 拉取镜像。
```
docker pull m.daocloud.io/docker.io/hanxi/xiaomusic:latest
docker tag m.daocloud.io/docker.io/hanxi/xiaomusic:latest hanxi/xiaomusic:latest
```
## ❓ 启动失败,日志中出现 RuntimeError: can't start new thread
一般是 docker 版本太低,或者系统限制了 docker 使用的 cpu 数量,可以尝试升级 docker 到最新版本。
## ❓ DNS 解析错误
一般会出现下面这样的日志,表现就是设置页面看不到设备列表。
```
aiohttp.client_ _exceptions. ClientConnectorError: Cannot connect to host account.xiaomi.com:443 ssl:False [Temporary failure in name resolution]
```
可以尝试把主机的 DNS 设为 223.5.5.5 之后重启 docker 主机。
如果还是不行可以把 docker 的网络模式改成 host 模式。
## ❓ 点击播放后需要很久才开始播放的问题
这个问题新版本已经解决,如果还存在请反馈。
~目前0.3.x版本还存在这个问题没有完全解决可以暂时回退到0.2.0版本继续使用。~
## ❓ 如何配置多个歌曲目录
```yaml
services:
xiaomusic:
image: hanxi/xiaomusic
container_name: xiaomusic
restart: unless-stopped
ports:
- 8090:8090
volumes:
- /data/music1:/app/music/music1
- /data/music2:/app/music/music2
- /data/xiaomusic/conf:/app/conf
```
冒号左边的 `/data/music1``/data/music2` 改成你的目录即可。如果你是 windows 的 docker ,可以改成 `D:/music1``D:/music2`,盘符号开头,用 `/` 分割。
如果是 docker 部署的,建议不要去修改 web 后台里的音乐路径和配置路径等等所有路径除非你熟悉 docker 的目录映射机制。
## ❓ 能不能中文名
```yaml
services:
xiaomusic:
image: hanxi/xiaomusic
container_name: xiaomusic
restart: unless-stopped
ports:
- 8090:8090
volumes:
- /data/music1:/app/music/歌曲目录1
- /data/music2:/app/music/歌曲目录2
- /data/xiaomusic/conf:/app/conf
```
## ❓ 能不能多层目录
可以,每层的每个目录会识别为一个播放列表。
## ❓ 是否需要手动获取 did
新版本不需要手动获取配置 did不需要配置环境变量直接在 web 后台填入小米账号密码保存后会自动获取 did ,然后勾选对应的设备即可。
## ❓ 报错 601
报错日志大致如下:
```txt
Exception: Error https://api2.mina.mi.com/remote/ubus: {"code":601,"message":"illegal argument exception","data":"IllegalArgumentException: ubus call format illegal!"}
```
原因是没有配置 did ,或者 did 配置错误。可以到设置页面选择正确的设备类型和 did 然后保存。
## ❓ 新功能没有生效
在设置页面重新保存一下,或者删除 setting.json 文件,重新在后台设置一次。
## ❓ 为什么会先说小爱音箱自带的回答,再说下载中或者过一会儿才播放本地歌曲
> [!NOTE]
> 这个 issue 用来总结报错日志和对应的解决方法。
## ❓ XIAOMUSIC_HOSTNAME 怎么填
填写 docker 主机的 ip **不是小爱音箱的ip**,一般就是网页访问的后台地址里的 ip ,只要确保 ip 和小爱音箱在一个局域网内就行。
同时也支持 xx.xx.com 的域名格式,用于配置反代供外网访问,比如小爱音箱和 docker 主机不在同一个局域网内。
## ❓ Login Failed 登陆失败
表现就是 **后台看不到设备列表** ,日志中会有对应的报错。
这个有专门的讨论,见 </issues/16.html> 一般是因为开了加速代理关代理再尝试即可。也可以试试在局域网设备里的米家app上退出再重新登录一下。
在小米官网 www.mi.com 登陆过人脸或滑块验证基本上能解决 99%的 login failed 问题。
来自 @yilikun 的友情提示:
> 1. 关闭本地代理。
> 2. 如果是nas运行的网络由bridge改为host。
> 3. 米家app重新登陆。
> 4. mi.com官网重新登陆。
> 5. 检查 setting.json 文件里的账号密码是否正确。
## ❓ 网页后台可以播放,语音控制无效
这种情况是拉取不到对话记录导致的。
如果是首次在网页后台保存 did 后需要重启一次容器。
其他情况可能是被限制拉取对话记录次数,也可以尝试重启容器。
还有一种情况是配错了唤醒口令可以在小爱音箱app里查看对话记录也可以查看 xiaomusic 的日志。默认口令前缀是【播放歌曲】,没有这个前缀是无法识别的,说播放音乐是没用的,除非自己设置其他口令词。
已知 `M01/XMYX01JY 小米小爱音箱HD` 获取对话记录的接口比较特殊,需要开启【特殊型号获取对话记录:】开关才能正常语音控制。
## ❓ 日志显示正在播放,却没有声音
可以点击播放链接按钮,看看默认的那个链接能否播放。
已知部分触屏版不能播放可以在后台设置 【型号兼容模式】为 true 试试。
其他情况可能是 XIAOMUSIC_HOSTNAME 配错了地址,不是 docker 主机地址会导致小爱音箱无法访问到,而且需要和小爱音箱在同一个**局域网**下的地址。还有可能是端口配错了,**修改了默认 8090 端口映射**,需要同步修改其他参数,可以翻阅端口修改的文档。
如果端口不是8090首次启动没配好端口的话需要手动修改setting.json文件里的端口或者把setting.json文件删除重新配置或者在后台修改监听端口后重启。
可以点击播放歌曲后查看日志里的歌曲链接放到浏览器里打开试试不能访问说明是端口或者hostname问题如果是异地访问需要把 hostname 修改为外网ip或者域名需要注意音箱只支持访问ipv4不能是ipv6的公网。
如果是配了公网反代端口,注意区分是 http 还是 https ,如果是 https 的,配置 XIAOMUSIC_HOSTNAME 时需要加上 `https:// ` 前缀。
## ❓ 无法播放 flac 格式歌曲
因设备差异和文件格式差异,已知部分设备不支持 flac 格式,比如 L05B L05C 。
## ❓ docker 镜像拉取失败
请更换镜像源或者使用代理。不同环境更换镜像源的方式不一样,可以网上搜索自己的 NAS 如何更换镜像源。
已经可以通过 [DaoCloud](https://github.com/DaoCloud/public-image-mirror) 拉取镜像。
```
docker pull m.daocloud.io/docker.io/hanxi/xiaomusic:latest
docker tag m.daocloud.io/docker.io/hanxi/xiaomusic:latest hanxi/xiaomusic:latest
```
## ❓ 启动失败,日志中出现 RuntimeError: can't start new thread
一般是 docker 版本太低,或者系统限制了 docker 使用的 cpu 数量,可以尝试升级 docker 到最新版本。
## ❓ DNS 解析错误
一般会出现下面这样的日志,表现就是设置页面看不到设备列表。
```
aiohttp.client_ _exceptions. ClientConnectorError: Cannot connect to host account.xiaomi.com:443 ssl:False [Temporary failure in name resolution]
```
可以尝试把主机的 DNS 设为 223.5.5.5 之后重启 docker 主机。
如果还是不行可以把 docker 的网络模式改成 host 模式。
## ❓ 点击播放后需要很久才开始播放的问题
这个问题新版本已经解决,如果还存在请反馈。
~目前0.3.x版本还存在这个问题没有完全解决可以暂时回退到0.2.0版本继续使用。~
## ❓ 如何配置多个歌曲目录
```yaml
services:
xiaomusic:
image: hanxi/xiaomusic
container_name: xiaomusic
restart: unless-stopped
ports:
- 8090:8090
volumes:
- /data/music1:/app/music/music1
- /data/music2:/app/music/music2
- /data/download:/app/music/download
- /data/xiaomusic/conf:/app/conf
```
冒号左边的 `/data/music1``/data/music2` 改成你的目录即可。如果你是 windows 的 docker ,可以改成 `D:/music1``D:/music2`,盘符号开头,用 `/` 分割。
如果是 docker 部署的,建议不要去修改 web 后台里的音乐路径和配置路径等等所有路径除非你熟悉 docker 的目录映射机制。
## ❓ 能不能中文名
```yaml
services:
xiaomusic:
image: hanxi/xiaomusic
container_name: xiaomusic
restart: unless-stopped
ports:
- 8090:8090
volumes:
- /data/music1:/app/music/歌曲目录1
- /data/music2:/app/music/歌曲目录2
- /data/download:/app/music/download
- /data/xiaomusic/conf:/app/conf
```
## ❓ 能不能多层目录
可以,每层的每个目录会识别为一个播放列表。
## ❓ 是否需要手动获取 did
新版本不需要手动获取配置 did不需要配置环境变量直接在 web 后台填入小米账号密码保存后会自动获取到 did ,然后勾选对应的设备即可。
## ❓ 报错 601
报错日志大致如下:
```txt
Exception: Error https://api2.mina.mi.com/remote/ubus: {"code":601,"message":"illegal argument exception","data":"IllegalArgumentException: ubus call format illegal!"}
```
原因是没有配置 did ,或者 did 配置错误。可以到设置页面选择正确的设备类型和 did 然后保存。
## ❓ 新功能没有生效
在设置页面重新保存一下,或者删除 setting.json 文件,重新在后台设置一次。
## ❓ 为什么会先说小爱音箱自带的回答,再说下载中或者过一会儿才播放本地歌曲
设计原理就是每秒不停的抓取对话记录,然后再打断小爱音箱自带的处理流程。整个过程下来会有延时,所以打断不会很及时,做不到无缝衔接。
## ❓ 云服务器上能否安装
可以安装,登录 mi.com 这个步骤可以使用终端里的浏览器 [carbonyl](https://github.com/fathyb/carbonyl) 来操作:
```shell
docker run --rm -ti fathyb/carbonyl https://mi.com
```
或者使用 [browsh](https://github.com/browsh-org/browsh)
```shell
docker run --rm -it browsh/browsh --startup-url https://mi.com
```
## 在播放歌曲时,问小爱查询天气,小爱查询天气时,中途会断掉。
播放中会被xiaomusic接管会跟原有功能冲突需要先说关机来关闭xiaomusic的功能再问小爱查询天气。
## 我家有个奇怪的问题,你给它暂停了,它过一会儿又自己开始唱了,不勘其扰。小爱重启都没用。
要说【关机】才能关掉 xiaomusic ,否则下一曲定时器到了会继续播放下一曲。
## 为什么播放进度条不能拖动
没有接口,目前做不到。
## 小爱触屏能不能显示本地的歌名歌词封面
可以,设置页面打开【启用继续播放】开关。
## 本机有声音,小爱音箱没声音,请问什么原因?
排查步骤:
1. 测试链接是否能播放,能播放说明小爱音箱控制没问题,继续下一步排查。不能播放说明控制不了你的小爱音箱,一般是【型号兼容模式】设置问题。
3. 小爱音箱和 NAS 是否在同一个局域网,检查 NAS 的 IP 和音箱的 IP 是否在同一个网段,不在同一个网段会导致音箱无法访问到 NAS 。如果在同一个局域网,检查 NAS 上的防火墙配置,关闭防火墙再测试,如果还是不行就继续下一步。
4. 查看容器日志中的歌曲链接是否正常,点击后台页面上的播放歌曲时,容器中会有歌曲链接,一般是 http 开头的链接,复制完整链接到浏览器试试看能否打开,能打开说明网络没问题,继续下一步排查。不能打开有可能是 ip 和端口配置错误,请使用设置页面的自动填按钮自动填 ip 和端口。
5. 歌曲文件格式是否是 mp3 格式,有些型号无法播放 flac 格式的歌曲,请使用 mp3 格式的歌曲文件测试,一个不行就多找几个文件测试。
## 评论
@@ -201,7 +242,7 @@ RUN pip install -U xiaomusic
> ```
我直接用pip安装好之后执行仍然有缺少的依赖和docker里缺的一样。截图的module安装了之后还会有其他依赖缺失
![image](https://github.hanxi.cc/proxy/user-attachments/assets/9fb182e2-ad41-488d-8633-4bae06202f73)
![image](https://gproxy.hanxi.cc/proxy/user-attachments/assets/9fb182e2-ad41-488d-8633-4bae06202f73)
---
@@ -236,7 +277,7 @@ RUN pip install -U xiaomusic
### 评论 9 - sqmcool
为什么我的没有显示设备?
![Snipaste_2024-09-14_15-51-00](https://github.hanxi.cc/proxy/user-attachments/assets/245d9a85-4ee1-4c82-be0d-865a29827072)
![Snipaste_2024-09-14_15-51-00](https://gproxy.hanxi.cc/proxy/user-attachments/assets/245d9a85-4ee1-4c82-be0d-865a29827072)
---
@@ -252,7 +293,7 @@ RUN pip install -U xiaomusic
### 评论 11 - schppd
楼主您好,请问这个我需要怎么处理?
![微信截图_20240915225040](https://github.hanxi.cc/proxy/user-attachments/assets/d4ecb7fb-6a47-4c66-bbab-72babf4afb9c)
![微信截图_20240915225040](https://gproxy.hanxi.cc/proxy/user-attachments/assets/d4ecb7fb-6a47-4c66-bbab-72babf4afb9c)
---
@@ -316,7 +357,7 @@ You are receiving this because you commented.Message ID: ***@***.***&gt;
### 评论 16 - agigogo
![image](https://github.hanxi.cc/proxy/user-attachments/assets/4fed0748-5497-47b5-ac9c-9cbc1d826a94)
![image](https://gproxy.hanxi.cc/proxy/user-attachments/assets/4fed0748-5497-47b5-ac9c-9cbc1d826a94)
在docker里可以运行但是没法播放设置页面中的播放链接选中设备那里是空的是不是没成功怎么调整
@@ -342,7 +383,7 @@ You are receiving this because you commented.Message ID: ***@***.***&gt;
>
> 设置页面输入小米的账号密码后,再勾选一个设备。
![image](https://github.hanxi.cc/proxy/user-attachments/assets/a4185b88-89b2-4682-b931-47fa39463c0c)
![image](https://gproxy.hanxi.cc/proxy/user-attachments/assets/a4185b88-89b2-4682-b931-47fa39463c0c)
设置页面没有可勾选项?
---
@@ -363,7 +404,7 @@ You are receiving this because you commented.Message ID: ***@***.***&gt;
>
> ![image](https://private-user-images.githubusercontent.com/73272860/369589185-a4185b88-89b2-4682-b931-47fa39463c0c.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjY4ODUzMzgsIm5iZiI6MTcyNjg4NTAzOCwicGF0aCI6Ii83MzI3Mjg2MC8zNjk1ODkxODUtYTQxODViODgtODliMi00NjgyLWI5MzEtNDdmYTM5NDYzYzBjLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA5MjElMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwOTIxVDAyMTcxOFomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTA3NzU1YjcwYWY2ZTNmYTRiZTY4NGU0MDMyZGIxNDBjYjE3ZThhNzdjMmJhYWEzYjE4MjJjMjgyNzk4OWVlODUmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.0MwpJNlNUU9XhjwOFcLisXQHFTAjsU8lscTm5-sfZpw) 设置页面没有可勾选项?
![image](https://github.hanxi.cc/proxy/user-attachments/assets/6bdf44b1-03cd-436f-a222-4889301affaa)
![image](https://gproxy.hanxi.cc/proxy/user-attachments/assets/6bdf44b1-03cd-436f-a222-4889301affaa)
显示未检测到设备设备型号是MDZ-25-DA
@@ -421,9 +462,9 @@ You are receiving this because you commented.Message ID: ***@***.***&gt;
### 评论 27 - zealler9560
![Screenshot_2024-10-31-23-28-57-903_com.android.chrome.jpg](https://github.hanxi.cc/proxy/user-attachments/assets/541ff644-0dcd-4bda-a142-2eb4a0f94b9d)
![Screenshot_2024-10-31-23-28-57-903_com.android.chrome.jpg](https://gproxy.hanxi.cc/proxy/user-attachments/assets/541ff644-0dcd-4bda-a142-2eb4a0f94b9d)
istore系统可以拉取创建镜像但是无法启动错误提示见图一求助大佬路由器信息见图二![Screenshot_2024-10-31-23-36-42-846-edit_com.android.chrome.jpg](https://github.hanxi.cc/proxy/user-attachments/assets/767383a5-8f84-471b-ab15-61e0fe9cbb22)
istore系统可以拉取创建镜像但是无法启动错误提示见图一求助大佬路由器信息见图二![Screenshot_2024-10-31-23-36-42-846-edit_com.android.chrome.jpg](https://gproxy.hanxi.cc/proxy/user-attachments/assets/767383a5-8f84-471b-ab15-61e0fe9cbb22)
@@ -626,8 +667,8 @@ You are receiving this because you commented.Message ID: ***@***.***&gt;
### 评论 41 - CallEdison
![image](https://github.hanxi.cc/proxy/user-attachments/assets/6724300b-ce48-44e6-9729-7b844bc0751e)
![image](https://github.hanxi.cc/proxy/user-attachments/assets/e7e87adb-a54d-42dd-bfc9-f84a01116a48)
![image](https://gproxy.hanxi.cc/proxy/user-attachments/assets/6724300b-ce48-44e6-9729-7b844bc0751e)
![image](https://gproxy.hanxi.cc/proxy/user-attachments/assets/e7e87adb-a54d-42dd-bfc9-f84a01116a48)
问题一能进控制面板进不了设置页面容器没有log生成我昨天已经设置好了现在功能能正常使用但是进不了设置页面了问题二昨天能进的时候发现本地下载目录有歌曲但是设置里面的全部歌曲里面没有搜索框搜索又能搜的到。
---
@@ -719,7 +760,7 @@ You are receiving this because you commented.Message ID: ***@***.***&gt;
### 评论 47 - like1020
![Screenshot_2024-12-03-06-58-52-853_com yjllq kito](https://github.hanxi.cc/proxy/user-attachments/assets/5d37bfa6-d63a-46b1-b5a8-554814fc7dce)
![Screenshot_2024-12-03-06-58-52-853_com yjllq kito](https://gproxy.hanxi.cc/proxy/user-attachments/assets/5d37bfa6-d63a-46b1-b5a8-554814fc7dce)
请教一下,本地列表歌单里的歌曲即便设置为全部循环或随机播放,依然是不断地单曲循环,只能自己手动点下一首,请问是什么情况?
---
@@ -1101,5 +1142,144 @@ You are receiving this because you commented.Message ID: ***@***.***&gt;
绿联的NAS怎么更新到58版本啊没找到要用口令吗
---
### 评论 72 - zjzj52
容器一直重启,网页后台也进不去
---
### 评论 73 - hanxi
> 容器一直重启,网页后台也进不去
这种情况有日志吗?可能是端口冲突?
---
### 评论 74 - BladPit
不知道有没有用unraid系统NAS的朋友
我这里使用docker安装xiaomusic有一个很奇怪的现象不知道有没有大佬能够解惑
我的unraid系统版本是6.8.2通过docker安装后发现如果没有开启特权模式Privileged那么从内网访问webGUI的时候在首页选择了主题之后会直接网页报错【Internal Server Error】+显示空白页面查看docker运行日志是正常的没有什么相关的报错
`2025-01-04 00:29:06,055 CRIT Supervisor is running as root. Privileges were not dropped because no user is specified in the config file. If you intend to run as root, you can set user=root in the config file to avoid this message.
2025-01-04 00:29:06,064 INFO RPC interface 'supervisor' initialized
2025-01-04 00:29:06,064 CRIT Server 'unix_http_server' running without any HTTP authentication checking
2025-01-04 00:29:06,065 INFO supervisord started with pid 1
2025-01-04 00:29:07,068 INFO spawned: 'xiaomusic' with pid 6`
然而如果开启特权模式运行docker则会完全正常webGUI能够正常访问。感觉非常疑惑不知道是什么原因。
这个问题之前在安装docker版迅雷的时候有类似情况必须开启特权模式迅雷的docker才能启动但迅雷的docker应该是所有人都如此但xiaomusic的这种情况我询问过其他unraid群友似乎没有遇到该问题。
---
### 评论 75 - ZYT1601
容器一直重启,日志一直循环一段
Unlinking stale socket /var/run/supervisor.sock
/usr/lib/python3/dist-packages/supervisor/options.py:474: UserWarning: Supervisord is running as root and it is searching for its configuration file in default locations (including its current working directory); you probably want to specify a "-c" argument specifying an absolute path to a configuration file for improved security.
self.warnings.warn(
Unlinking stale socket /var/run/supervisor.sock
---
### 评论 76 - hanxi
@ZYT1601 试试看这个方法: /issues/348.html#issuecomment-2568722472
---
### 评论 77 - ZYT1601
可以了,飞牛把容器设置里面的命令全部删掉也是一个道理
---
### 评论 78 - ZYT1601
> 可以了,飞牛把容器设置里面的命令全部删掉也是一个道理
好像不能一劳永逸
---
### 评论 79 - hanxi
> > 可以了,飞牛把容器设置里面的命令全部删掉也是一个道理
>
> 好像不能一劳永逸
等后续版本吧。
---
### 评论 80 - Ivysaur-91
有个问题请教下建立容器的时候指定了nas本地的位置映射到容器的音乐路径但是在nas路径防止文件无法被识别出来。
![屏幕截图 2025-01-05 183306](https://gproxy.hanxi.cc/proxy/user-attachments/assets/c3a8a107-1fb9-456d-8f03-da0d03b3d770)
直接在xiaomusic里面下载音乐是可以播放的进入到docker里面的路径也是有音乐文件的
![image](https://gproxy.hanxi.cc/proxy/user-attachments/assets/fdb6ea7a-8ccf-4580-a983-b793c591869b)
建容器的命令如下:
docker run -p 58090:8090 -e XIAOMUSIC_PUBLIC_PORT=58090 -v /Public/Music/[[xiaomusic]]:/app/music -v /Public/Music/[[xiaomusic]]:/app/conf m.daocloud.io/docker.io/hanxi/xiaomusic
---
### 评论 81 - hanxi
> 有个问题请教下建立容器的时候指定了nas本地的位置映射到容器的音乐路径但是在nas路径防止文件无法被识别出来。 ![屏幕截图 2025-01-05 183306](https://private-user-images.githubusercontent.com/193787091/400193889-c3a8a107-1fb9-456d-8f03-da0d03b3d770.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MzYwNzY2MDYsIm5iZiI6MTczNjA3NjMwNiwicGF0aCI6Ii8xOTM3ODcwOTEvNDAwMTkzODg5LWMzYThhMTA3LTFmYjktNDU2ZC04ZjAzLWRhMGQwM2IzZDc3MC5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjUwMTA1JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI1MDEwNVQxMTI1MDZaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT1kMTA2YmM4ZDI4MTk1OWFjZTAxZTZlODE1YmYwMTk4ZDE3NmMyNzI1ZDVmYjNhOWVhMTdhZTJjMDEzYjM2NjllJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCJ9.45ZS_c09oRK43CTcgUJTEbzXNDRUW0fSpWtw4PMUn3g) 直接在xiaomusic里面下载音乐是可以播放的进入到docker里面的路径也是有音乐文件的 ![image](https://private-user-images.githubusercontent.com/193787091/400194129-fdb6ea7a-8ccf-4580-a983-b793c591869b.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MzYwNzY2MDYsIm5iZiI6MTczNjA3NjMwNiwicGF0aCI6Ii8xOTM3ODcwOTEvNDAwMTk0MTI5LWZkYjZlYTdhLThjY2YtNDU4MC1hOTgzLWI3OTNjNTkxODY5Yi5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjUwMTA1JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI1MDEwNVQxMTI1MDZaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT1mMWMyYmZmNWFjMzU5Yzg3MDk5N2M5MTMyMmE0ZDJlYmY5YWY4OGU3MzhiYmVkMDYyNjFjZGQzNTUyYWM4MzI0JlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCJ9.AmsxpldZ738tCXE2y_2AQuN14I4FERkOjn23JFrnRuM)
>
> 建容器的命令如下: docker run -p 58090:8090 -e XIAOMUSIC_PUBLIC_PORT=58090 -v /Public/Music/[[xiaomusic]]:/app/music -v /Public/Music/[[xiaomusic]]:/app/conf m.daocloud.io/docker.io/hanxi/xiaomusic
为啥路径要加方括号?另外两个路径不能重复。
---
### 评论 82 - Ivysaur-91
> > 有个问题请教下建立容器的时候指定了nas本地的位置映射到容器的音乐路径但是在nas路径防止文件无法被识别出来。 ![屏幕截图 2025-01-05 183306](https://private-user-images.githubusercontent.com/193787091/400193889-c3a8a107-1fb9-456d-8f03-da0d03b3d770.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MzYwNzY2MDYsIm5iZiI6MTczNjA3NjMwNiwicGF0aCI6Ii8xOTM3ODcwOTEvNDAwMTkzODg5LWMzYThhMTA3LTFmYjktNDU2ZC04ZjAzLWRhMGQwM2IzZDc3MC5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjUwMTA1JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI1MDEwNVQxMTI1MDZaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT1kMTA2YmM4ZDI4MTk1OWFjZTAxZTZlODE1YmYwMTk4ZDE3NmMyNzI1ZDVmYjNhOWVhMTdhZTJjMDEzYjM2NjllJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCJ9.45ZS_c09oRK43CTcgUJTEbzXNDRUW0fSpWtw4PMUn3g) 直接在xiaomusic里面下载音乐是可以播放的进入到docker里面的路径也是有音乐文件的 ![image](https://private-user-images.githubusercontent.com/193787091/400194129-fdb6ea7a-8ccf-4580-a983-b793c591869b.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MzYwNzY2MDYsIm5iZiI6MTczNjA3NjMwNiwicGF0aCI6Ii8xOTM3ODcwOTEvNDAwMTk0MTI5LWZkYjZlYTdhLThjY2YtNDU4MC1hOTgzLWI3OTNjNTkxODY5Yi5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjUwMTA1JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI1MDEwNVQxMTI1MDZaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT1mMWMyYmZmNWFjMzU5Yzg3MDk5N2M5MTMyMmE0ZDJlYmY5YWY4OGU3MzhiYmVkMDYyNjFjZGQzNTUyYWM4MzI0JlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCJ9.AmsxpldZ738tCXE2y_2AQuN14I4FERkOjn23JFrnRuM)
> > 建容器的命令如下: docker run -p 58090:8090 -e XIAOMUSIC_PUBLIC_PORT=58090 -v /Public/Music/[[xiaomusic]]:/app/music -v /Public/Music/[[xiaomusic]]:/app/conf m.daocloud.io/docker.io/hanxi/xiaomusic
>
> 为啥路径要加方括号?另外两个路径不能重复。
方括号是为了让文件夹在第一位,重新安装容器,路径不一样后还是一样的问题:
![屏幕截图 2025-01-06 214204](https://gproxy.hanxi.cc/proxy/user-attachments/assets/3bf283cc-c951-433b-95d9-dda6abeea7b4)
语句:
docker run -p 58090:8090 -e XIAOMUSIC_PUBLIC_PORT=58090 -v /Public/Music/xiaomusic/music:/app/music -v /Public/Music/xiaomusic/config:/app/conf m.daocloud.io/docker.io/hanxi/xiaomusic
---
### 评论 83 - Ivysaur-91
> > > 有个问题请教下建立容器的时候指定了nas本地的位置映射到容器的音乐路径但是在nas路径防止文件无法被识别出来。 ![屏幕截图 2025-01-05 183306](https://private-user-images.githubusercontent.com/193787091/400193889-c3a8a107-1fb9-456d-8f03-da0d03b3d770.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MzYwNzY2MDYsIm5iZiI6MTczNjA3NjMwNiwicGF0aCI6Ii8xOTM3ODcwOTEvNDAwMTkzODg5LWMzYThhMTA3LTFmYjktNDU2ZC04ZjAzLWRhMGQwM2IzZDc3MC5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjUwMTA1JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI1MDEwNVQxMTI1MDZaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT1kMTA2YmM4ZDI4MTk1OWFjZTAxZTZlODE1YmYwMTk4ZDE3NmMyNzI1ZDVmYjNhOWVhMTdhZTJjMDEzYjM2NjllJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCJ9.45ZS_c09oRK43CTcgUJTEbzXNDRUW0fSpWtw4PMUn3g) 直接在xiaomusic里面下载音乐是可以播放的进入到docker里面的路径也是有音乐文件的 ![image](https://private-user-images.githubusercontent.com/193787091/400194129-fdb6ea7a-8ccf-4580-a983-b793c591869b.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MzYwNzY2MDYsIm5iZiI6MTczNjA3NjMwNiwicGF0aCI6Ii8xOTM3ODcwOTEvNDAwMTk0MTI5LWZkYjZlYTdhLThjY2YtNDU4MC1hOTgzLWI3OTNjNTkxODY5Yi5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjUwMTA1JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI1MDEwNVQxMTI1MDZaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT1mMWMyYmZmNWFjMzU5Yzg3MDk5N2M5MTMyMmE0ZDJlYmY5YWY4OGU3MzhiYmVkMDYyNjFjZGQzNTUyYWM4MzI0JlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCJ9.AmsxpldZ738tCXE2y_2AQuN14I4FERkOjn23JFrnRuM)
> > > 建容器的命令如下: docker run -p 58090:8090 -e XIAOMUSIC_PUBLIC_PORT=58090 -v /Public/Music/[[xiaomusic]]:/app/music -v /Public/Music/[[xiaomusic]]:/app/conf m.daocloud.io/docker.io/hanxi/xiaomusic
> >
> >
> > 为啥路径要加方括号?另外两个路径不能重复。
>
> 方括号是为了让文件夹在第一位,重新安装容器,路径不一样后还是一样的问题:
>
> ![屏幕截图 2025-01-06 214204](https://private-user-images.githubusercontent.com/193787091/400439202-3bf283cc-c951-433b-95d9-dda6abeea7b4.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MzYxNzEzMjIsIm5iZiI6MTczNjE3MTAyMiwicGF0aCI6Ii8xOTM3ODcwOTEvNDAwNDM5MjAyLTNiZjI4M2NjLWM5NTEtNDMzYi05NWQ5LWRkYTZhYmVlYTdiNC5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjUwMTA2JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI1MDEwNlQxMzQzNDJaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT02MTExNDE3MmFkMDFlYzFlZTRlMTg0OTdiMTQ3ODY0MjIxODlmMjEzMjUyMWUwYmNjYWNkZGEzNTA0MDIyYWIxJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCJ9.cdKynorOPxYE9nBrETp-_E98B6D1cVpITIUzRdEu49M)
>
> 语句: docker run -p 58090:8090 -e XIAOMUSIC_PUBLIC_PORT=58090 -v /Public/Music/xiaomusic/music:/app/music -v /Public/Music/xiaomusic/config:/app/conf m.daocloud.io/docker.io/hanxi/xiaomusic
![屏幕截图 2025-01-06 215510](https://gproxy.hanxi.cc/proxy/user-attachments/assets/cc7e218c-f215-4c54-9c2e-aea7be692e22)
yi以为是文件夹关联失败了但是进入容器看应该是成功的
---
[链接到 GitHub Issue](https://github.com/hanxi/xiaomusic/issues/99)

View File

@@ -1,5 +1,121 @@
# 版本日志
## v0.3.73 (2025-01-16)
### Fix
- 当前歌曲不在列表中时才切换列表 close #359
- 修复默认主题播放进度时间问题
- 尝试修复获取对话记录失败的问题 close #362
## v0.3.72 (2025-01-11)
### Feat
- 新增播放文字功能
### Fix
- 修复默认主题没有单曲循环的问题 see #355
## v0.3.71 (2025-01-07)
### Feat
- 支持自动填 ip 和端口
### Fix
- 搜索歌曲窗口不自动关闭 see #351
- 解决歌词信息写入失败的问题
- 修复一些小问题
- 非播放中也返回歌曲时长 see #340
## v0.3.70 (2025-01-04)
### Fix
- 尝试修复部分设备无法启动的问题
- 解决首页提示翻译英文问题
- 尝试解决 supervisor 启动报错
## v0.3.69 (2025-01-01)
### Feat
- 支持关闭获取对话记录功能
### Fix
- 尝试解决网络卡顿问题
## v0.3.68 (2024-12-31)
### Feat
- umami 脚本改为异步加载
- 支持 python3.13 版本
- 增加均衡歌曲响度(可选) (#338)
### Fix
- 修复保存设置时可能出现报错的情况
## v0.3.67 (2024-12-29)
### Feat
- 简化设置,不允许修改监听端口
### Fix
- 修复默认主题搜索问题
## v0.3.66 (2024-12-26)
### Fix
- 修复歌曲批量重命名的问题
- 修复自定义歌单删除后没刷新歌单列表
- 尝试修复更新失败问题
## v0.3.65 (2024-12-24)
### Fix
- 处理图像报错
- 修改歌单名字漏更新歌单列表
- 修复获取自定义歌单接口报错
## v0.3.64 (2024-12-22)
### Fix
- 使用自己架设的 sentry 服务,解决 Cloudflare 额度超量问题
## v0.3.63 (2024-12-22)
### Perf
- 只监控报错信息
## v0.3.62 (2024-12-21)
### Fix
- 修复首次配置时,默认主题只有一个设备的问题。
- 修复一些报错问题
## v0.3.61 (2024-12-19)
### Fix
- 尝试修复更新问题
### Refactor
- 重构更新流程
## v0.3.60 (2024-12-19)
## v0.3.59 (2024-12-19)

View File

@@ -1,4 +1,5 @@
# XiaoMusic: 无限听歌,解放小爱音箱
[![GitHub License](https://img.shields.io/github/license/hanxi/xiaomusic)](https://github.com/hanxi/xiaomusic)
[![Docker Image Version](https://img.shields.io/docker/v/hanxi/xiaomusic?sort=semver&label=docker%20image)](https://hub.docker.com/r/hanxi/xiaomusic)
[![Docker Pulls](https://img.shields.io/docker/pulls/hanxi/xiaomusic)](https://hub.docker.com/r/hanxi/xiaomusic)
@@ -9,7 +10,6 @@
[![Visitors](https://api.visitorbadge.io/api/daily?path=hanxi%2Fxiaomusic&label=daily%20visitor&countColor=%232ccce4&style=flat)](https://visitorbadge.io/status?path=hanxi%2Fxiaomusic)
[![Visitors](https://api.visitorbadge.io/api/visitors?path=hanxi%2Fxiaomusic&label=total%20visitor&countColor=%232ccce4&style=flat)](https://visitorbadge.io/status?path=hanxi%2Fxiaomusic)
使用小爱音箱播放音乐,音乐使用 yt-dlp 下载。
<https://github.com/hanxi/xiaomusic>
@@ -22,13 +22,13 @@
已经支持在 web 页面配置其他参数docker 启动命令如下:
```bash
docker run -p 8090:8090 -v /xiaomusic/music:/app/music -v /xiaomusic/conf:/app/conf hanxi/xiaomusic
docker run -p 58090:8090 -e XIAOMUSIC_PUBLIC_PORT=58090 -v /xiaomusic_music:/app/music -v /xiaomusic_conf:/app/conf hanxi/xiaomusic
```
🔥 国内:
```bash
docker run -p 8090:8090 -v /xiaomusic/music:/app/music -v /xiaomusic/conf:/app/conf m.daocloud.io/docker.io/hanxi/xiaomusic
docker run -p 58090:8090 -e XIAOMUSIC_PUBLIC_PORT=58090 -v /xiaomusic_music:/app/music -v /xiaomusic_conf:/app/conf docker.hanxi.cc/hanxi/xiaomusic
```
对应的 docker compose 配置如下:
@@ -40,10 +40,12 @@ services:
container_name: xiaomusic
restart: unless-stopped
ports:
- 8090:8090
- 58090:8090
environment:
XIAOMUSIC_PUBLIC_PORT: 58090
volumes:
- /xiaomusic/music:/app/music
- /xiaomusic/conf:/app/conf
- /xiaomusic_music:/app/music
- /xiaomusic_conf:/app/conf
```
🔥 国内:
@@ -51,75 +53,40 @@ services:
```yaml
services:
xiaomusic:
image: m.daocloud.io/docker.io/hanxi/xiaomusic
image: docker.hanxi.cc/hanxi/xiaomusic
container_name: xiaomusic
restart: unless-stopped
ports:
- 8090:8090
- 58090:8090
environment:
XIAOMUSIC_PUBLIC_PORT: 58090
volumes:
- /xiaomusic/music:/app/music
- /xiaomusic/conf:/app/conf
- /xiaomusic_music:/app/music
- /xiaomusic_conf:/app/conf
```
其中 conf 目录为配置文件存放目录music 目录为音乐存放目录,建议分开配置为不同的目录。
- 其中 conf 目录为配置文件存放目录music 目录为音乐存放目录,建议分开配置为不同的目录。
- /xiaomusic_music 和 /xiaomusic_conf 是 docker 所在的主机的目录,可以修改为其他目录。如果报错找不到 /xiaomusic_music 目录,可以先执行 `mkdir -p /xiaomusic_{music,conf}` 命令新建目录。
- /app/music 和 /app/conf 是 docker 容器里的目录,不要去修改。
- XIAOMUSIC_PUBLIC_PORT 是用来配置 NAS 本地端口的。8090 是容器端口,不要去修改。
- 后台访问地址为: http://NAS_IP:58090
> [!NOTE]
> 上面配置的 /xiaomusic/music 和 /xiaomusic/conf 是 docker 主机里的 /xiaomusic 目录下的,可以修改为其他目录。如果报错找不到 /xiaomusic/music 目录,可以先执行 `mkdir -p /xiaomusic/{music,conf}` 命令新建目录
docker 和 docker compose 二选一即可,启动成功后,在 web 页面可以配置其他参数,带有 `*` 号的配置是必须要配置的,其他的用不上时不用修改。初次配置时需要在页面上输入小米账号和密码保存后才能获取到设备列表。
> docker 和 docker compose 二选一即可,启动成功后,在 web 页面可以配置其他参数,带有 `*` 号的配置是必须要配置的,其他的用不上时不用修改。初次配置时需要在页面上输入小米账号和密码保存后才能获取到设备列表
> [!TIP]
> 目前安装步骤已经是最简化了,如果还是嫌安装麻烦,可以微信或者 QQ 约我远程安装,我一般周末和晚上才有时间,收个辛苦费 :moneybag: 50 元一次,安装失败不收费。
### 🔥 修改默认8090端口映射
#### 方法1 不修改监听端口 8090
【监听端口】保持为默认的 8090 不变,把【外网访问端口】改为 5678 。
```yaml
services:
xiaomusic:
image: hanxi/xiaomusic
container_name: xiaomusic
restart: unless-stopped
ports:
- 5678:8090
volumes:
- /xiaomusic/music:/app/music
- /xiaomusic/conf:/app/conf
environment:
XIAOMUSIC_PUBLIC_PORT: 5678
```
XIAOMUSIC_PUBLIC_PORT 对应后台设置里的【外网访问端口】,修改后可以不用重启。
#### 方法2 修改监听端口 8090 为 5678
如果需要修改 8090 端口为其他端口,比如 5678需要这样配3个数字都需要是 5678 。见 <https://github.com/hanxi/xiaomusic/issues/19>
```yaml
services:
xiaomusic:
image: hanxi/xiaomusic
container_name: xiaomusic
restart: unless-stopped
ports:
- 5678:5678
volumes:
- /xiaomusic/music:/app/music
- /xiaomusic/conf:/app/conf
environment:
XIAOMUSIC_PORT: 5678
```
如果不是首次修改端口,还需要修改 /xiaomusic/conf/setting.json 文件里的端口(也可以在后台修改监听端口后重启)。
遇到问题可以去 web 设置页面底部点击【下载日志文件】按钮,然后搜索一下日志文件内容确保里面没有账号密码信息后(有就删除这些敏感信息),然后在提 issues 反馈问题时把下载的日志文件带上。
> [!IMPORTANT]
> XIAOMUSIC_PORT 也可以在后台配置,对应的是监听端口,修改后记得重启
> [!TIP]
> 海外 RackNerd VPS 机器推荐,可支付宝付款
>
> - [🔥1 GB KVM VPS $11.29/年](https://my.racknerd.com/aff.php?aff=1177&pid=903)
> - [2 GB KVM VPS](https://my.racknerd.com/aff.php?aff=1177&pid=904)
> - [3.5 GB KVM VPS](https://my.racknerd.com/aff.php?aff=1177&pid=905)
> - [4 GB KVM VPS](https://my.racknerd.com/aff.php?aff=1177&pid=906)
> - [6 GB KVM VPS](https://my.racknerd.com/aff.php?aff=1177&pid=907)
### 🤐 支持语音口令
@@ -154,7 +121,7 @@ services:
\ / | | / _` | / _ \ | |\/| | | | | | / __| | | / __|
/ \ | | | (_| | | (_) | | | | | | |_| | \__ \ | | | (__
/_/\_\ |_| \__,_| \___/ |_| |_| \__,_| |___/ |_| \___|
XiaoMusic v0.3.37 by: github.com/hanxi
XiaoMusic v0.3.69 by: github.com/hanxi
usage: xiaomusic [-h] [--port PORT] [--hardware HARDWARE] [--account ACCOUNT]
[--password PASSWORD] [--cookie COOKIE] [--verbose]
@@ -214,7 +181,6 @@ docker build -t xiaomusic .
- 使用了 Docker ,在 NAS 上安装更方便。
- 默认的前端主题使用了 jQuery 。
## 已测试支持的设备
| 型号 | 名称 |
@@ -257,24 +223,6 @@ docker build -t xiaomusic .
> 已知 L05B L05C LX06 L16A 不支持 flac 格式。
> 如果格式不能播放可以打开【转换为MP3】和【型号兼容模式】选项。具体见 <https://github.com/hanxi/xiaomusic/issues/153#issuecomment-2328168689>
## 💡 简易的控制面板
浏览器进入 <http://192.168.2.5:8090>
- ip 是 XIAOMUSIC_HOSTNAME 设置的
- 8090 是默认端口
- 支持功能
- 显示正在播放的歌曲
- 模糊搜索本地歌曲
- 播放列表
- 删除歌曲
- 设置页面
- 配置网络歌单
- 日志文件下载
采用新的设置页面之后,没有必须在启动前配置的环境变量了,除非是改默认的 8090 端口才需要配置环境变量。
## 🌏 网络歌单功能
可以配置一个 json 格式的歌单,支持电台和歌曲,也可以直接用别人分享的链接,同时配备了 m3u 文件格式转换工具,可以很方便的把 m3u 电台文件转换成网络歌单格式的 json 文件,具体用法见 <https://github.com/hanxi/xiaomusic/issues/78>
@@ -284,29 +232,12 @@ docker build -t xiaomusic .
## 🍺 更多其他可选配置
- XIAOMUSIC_ACTIVE_CMD 环境变量,对应后台的 【允许唤醒的命令】,用于唤醒口令,配置成'play,random_play'在非播放状态下只有这两个指令播放歌曲和随机播放可以触发触发后xiaomusic进入playing状态其他指令则可以正常触发。具体<https://github.com/hanxi/xiaomusic/pull/43>
- XIAOMUSIC_EXCLUDE_DIRS 配置歌曲目录里需要忽略的目录,对应后台的 【忽略目录】
- XIAOMUSIC_MUSIC_PATH_DEPTH 配置歌曲目录搜索深度,对应后台的 【目录深度】,具体见 <https://github.com/hanxi/xiaomusic/issues/76>
- XIAOMUSIC_DISABLE_HTTPAUTH 配置成 false 表示开启密码访问web控制台对应后台的 【关闭密码验证】,具体见 <https://github.com/hanxi/xiaomusic/issues/47>
- XIAOMUSIC_HTTPAUTH_USERNAME 配置 web 控制台用户,对应后台的 【控制台账户】
- XIAOMUSIC_HTTPAUTH_PASSWORD 配置 web 控制台密码,对应后台的 【控制台密码】
- XIAOMUSIC_CONF_PATH 用来存放配置文件的目录,对应后台的 【配置文件目录】,记得把目录映射到主机,默认为 `/app/config` ,具体见 <https://github.com/hanxi/xiaomusic/issues/74>
- XIAOMUSIC_CACHE_DIR 用来音乐 tag 缓存,默认为 `/app/cache`,对应后台的 【缓存文件目录】。
- XIAOMUSIC_DISABLE_DOWNLOAD 设为 true 时关闭下载功能,对应后台的 【关闭下载功能】,见 <https://github.com/hanxi/xiaomusic/issues/82>
- XIAOMUSIC_USE_MUSIC_API 设为 true 时使用 player_play_music 接口播放音乐,对应后台的 【型号兼容模式】,用于兼容不能播放的型号,如果发现需要设置这个选项的时候请告知我加一下设备型号,方便以后不用设置。 见 <https://github.com/hanxi/xiaomusic/issues/30>
- XIAOMUSIC_KEYWORDS_PLAY 用来播放歌曲的口令前缀,对应后台的 【播放歌曲口令】,默认是 "播放歌曲,放歌曲" ,可以用英文逗号分割配置多个
- XIAOMUSIC_KEYWORDS_STOP 用来关机的口令,对应后台的 【停止口令】,默认是 "关机,暂停,停止" ,可以用英文逗号分割配置多个。
- XIAOMUSIC_KEYWORDS_PLAYLOCAL 用来播放本地歌曲的口令前缀,对应后台的 【播放本地歌曲口令】,本地找不到时不会下载歌曲,默认是 "播放本地歌曲,本地播放歌曲" ,可以用英文逗号分割配置多个。
- XIAOMUSIC_ENABLE_FUZZY_MATCH 设为 true 时开启模糊匹配(默认),设为 false 时关闭模糊匹配,对应后台的 【开启模糊搜索】,支持模糊匹配歌名和歌单名。 具体见 <https://github.com/hanxi/xiaomusic/issues/52>
- XIAOMUSIC_FUZZY_MATCH_CUTOFF 设置模糊搜索匹配的最低相似度阈值默认0.6可以配0到1直接的小数越小越模糊越大越精准对应后台的 【模糊匹配阈值】。具体见 <https://github.com/hanxi/xiaomusic/issues/52>
- XIAOMUSIC_PUBLIC_PORT 用于设置外网端口,对应后台的 【外网访问端口】当使用反向代理时可以设置为外网端口XIAOMUSIC_HOSTNAME 设为外网IP或者域名即可。
- XIAOMUSIC_DOWNLOAD_PATH 变量可以配置下载目录,默认为空,表示使用 music 目录为下载目录,对应后台的 【音乐下载目录】。设置这个目录必须是 music 的子目录,否则刷新列表后会找不到歌曲。具体见 <https://github.com/hanxi/xiaomusic/issues/98>
- XIAOMUSIC_PROXY 用于配置国内使用 youtube 源下载歌曲时使用的代理,参数格式参考 yt-dlp 文档说明。 见 <https://github.com/hanxi/xiaomusic/issues/2><https://github.com/hanxi/xiaomusic/issues/11>
- MIIO_TTS_CMD 用于部分机型(如:`L05C`)使用 MiIO 支持 tts 能力,默认为空,命令选择见 [MiService-fork 文档](https://github.com/yihong0618/MiService)
<https://github.com/hanxi/xiaomusic/issues/333>
### ⚠️ 安全提醒
## ⚠️ 安全提醒
> [!IMPORTANT]
>
> 1. 如果配置了公网访问 xiaomusic ,请一定要开启密码登陆,并设置复杂的密码。且不要在公共场所的 WiFi 环境下使用,否则可能造成小米账号密码泄露。
> 2. 强烈不建议将小爱音箱的小米账号绑定摄像头,代码难免会有 bug ,一旦小米账号密码泄露,可能监控录像也会泄露。
@@ -318,7 +249,8 @@ docker build -t xiaomusic .
## 📢 讨论区
- [点击链接加入QQ频道【xiaomusic】](https://pd.qq.com/s/e2jybz0ss)
- [点击链接加入群聊【xiaomusic】 604526973](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=13St5PLVcTxYlWTAs_iAawazjtdD1l-a&authKey=dJWEpaT2fDBDpdUUOWj%2FLt6NS1ePBfShDfz7a6seNURi05VvVnAGQzXF%2FM%2F5HgIm&noverify=0&group_code=604526973)
- [点击链接加入群聊【xiaomusic官方交流群1(小爱音箱)】 604526973](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=13St5PLVcTxYlWTAs_iAawazjtdD1l-a&authKey=dJWEpaT2fDBDpdUUOWj%2FLt6NS1ePBfShDfz7a6seNURi05VvVnAGQzXF%2FM%2F5HgIm&noverify=0&group_code=604526973)
- [点击链接加入群聊【xiaomusic官方交流群2(小爱音箱)】1021062499](https://qm.qq.com/q/BmVNqhDL3M)
- <https://github.com/hanxi/xiaomusic/issues>
- [微信群二维码](https://github.com/hanxi/xiaomusic/issues/86)
@@ -334,6 +266,7 @@ docker build -t xiaomusic .
- [微信小程序: XIAO晓音](https://github.com/F-loat/xiaoplayer)
- [pure 主题 xiaomusicUI](https://github.com/52fisher/xiaomusicUI)
- [移动端的播放器主题](https://github.com/52fisher/XMusicPlayer)
- [Tailwind主题](https://github.com/clarencejh/xiaomusic)
- [一个第三方的主题](https://github.com/DarrenWen/xiaomusicui)
- [Umami 统计](https://github.com/umami-software/umami)
- [Sentry 报错监控](https://github.com/getsentry/sentry)
@@ -365,4 +298,3 @@ docker build -t xiaomusic .
## License
[MIT](https://github.com/hanxi/xiaomusic/blob/main/LICENSE) License © 2024 涵曦

1113
pdm.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
[project]
name = "xiaomusic"
version = "0.3.61"
version = "0.3.74"
description = "Play Music with xiaomi AI speaker"
authors = [
{name = "涵曦", email = "im.hanxi@gmail.com"},
@@ -20,9 +20,9 @@ dependencies = [
"pillow>=10.4.0",
"python-multipart>=0.0.12",
"requests>=2.32.3",
"sentry-sdk[fastapi]>=2.19.2",
"sentry-sdk[fastapi]==1.45.1",
]
requires-python = ">=3.10,<=3.12"
requires-python = ">=3.10"
readme = "README.md"
license = {text = "MIT"}

View File

@@ -3,8 +3,12 @@ file=/var/run/supervisor.sock ; Unix套接字文件路径
chmod=0777 ; 套接字权限
[supervisord]
nodaemon=true ; 非守护模式,适合容器运行
pidfile=/tmp/supervisord.pid ; PID文件路径
logfile=/app/supervisord.log ; 日志文件路径
logfile_maxbytes=50MB ; 日志文件的最大大小
logfile_backups=3 ; 保留的旧日志文件数量
loglevel=info ; 日志级别
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
@@ -17,7 +21,7 @@ command=/app/.venv/bin/python3 /app/xiaomusic.py
directory=/app
autostart=true
autorestart=true
startretries=0
startretries=99999
startsecs=60
stderr_logfile=/app/xiaomusic.log.txt
stdout_logfile=/app/xiaomusic.log.txt

View File

@@ -1,8 +1,29 @@
from xiaomusic.utils import (
remove_common_prefix,
)
import re
def removepre(filename):
match = re.search(r"^[pP]?(\d+)\s+\d*(.+?)\.(.*$)", filename.strip())
new_filename = filename
if match:
num = match.group(1)
name = match.group(2).replace(".", " ").strip()
suffix = match.group(3)
# print(name)
# print(num)
# print(suffix)
new_filename = f"{num}.{name}.{suffix}"
print(filename, "=>", new_filename)
if __name__ == "__main__":
remove_common_prefix(
"./tmp/【无损音质】2024年9月酷狗热歌榜TOP100合集只选热歌最高的首首王炸分P合集"
)
removepre(" 17 《白色风车》.mp3")
removepre(" 17 《白色风车》.mp3")
removepre(" 17 17 《白色风车》.mp3")
removepre(" 17 17 《白色风车》.mp3")
removepre(" 18 风车.mp3")
removepre(" 18 色风车.mp3")
removepre(" 18 18 你好.mp3")
removepre(" 18 18 我好.mp3")
removepre("p09 009. 梁静茹-亲亲.mp3")

View File

@@ -1 +1 @@
__version__ = "0.3.61"
__version__ = "0.3.74"

View File

@@ -57,11 +57,10 @@ class Analytics:
await self._send(event)
async def _send(self, event):
await self.post_to_umami(event)
events = [event]
await self.run_with_cancel(self._google_send, events)
asyncio.create_task(self.post_to_umami(event))
await self.run_with_cancel(self._google_send, [event])
async def _google_send(self, events):
def _google_send(self, events):
try:
self.gtag.send(events)
except Exception as e:
@@ -69,7 +68,7 @@ class Analytics:
async def run_with_cancel(self, func, *args, **kwargs):
try:
asyncio.ensure_future(asyncio.to_thread(func, *args, **kwargs))
asyncio.create_task(asyncio.to_thread(func, *args, **kwargs))
self.log.info("analytics run_with_cancel success")
except Exception as e:
self.log.warning(f"analytics run_with_cancel failed {e}")
@@ -96,6 +95,7 @@ class Analytics:
"type": "event",
}
self.log.info(f"umami data: {data}")
async with aiohttp.ClientSession() as session:
headers = {
"User-Agent": user_agent,

View File

@@ -7,7 +7,7 @@ import signal
import sentry_sdk
from sentry_sdk.integrations.asyncio import AsyncioIntegration
from sentry_sdk.integrations.logging import LoggingIntegration
from sentry_sdk.integrations.logging import LoggingIntegration, ignore_logger
LOGO = r"""
__ __ _ __ __ _
@@ -20,9 +20,8 @@ LOGO = r"""
sentry_sdk.init(
dsn="https://659690a901a37237df8097a9eb95e60f@github.hanxi.cc/sentry/4508470200434688",
traces_sample_rate=0.1,
profiles_sample_rate=0.05,
# dsn="https://659690a901a37237df8097a9eb95e60f@github.hanxi.cc/sentry/4508470200434688",
dsn="https://ffe4962642d04b29afe62ebd1a065231@glitchtip.hanxi.cc/1",
integrations=[
AsyncioIntegration(),
LoggingIntegration(
@@ -32,6 +31,7 @@ sentry_sdk.init(
],
# debug=True,
)
ignore_logger("miservice")
def main():

View File

@@ -75,7 +75,7 @@ class Device:
device_id: str = ""
hardware: str = ""
name: str = ""
play_type: int = ""
play_type: int = PLAY_TYPE_RND
cur_music: str = ""
cur_playlist: str = ""
@@ -97,6 +97,7 @@ class Config:
port: int = int(os.getenv("XIAOMUSIC_PORT", "8090")) # 监听端口
public_port: int = int(os.getenv("XIAOMUSIC_PUBLIC_PORT", 0)) # 歌曲访问端口
proxy: str = os.getenv("XIAOMUSIC_PROXY", None)
loudnorm: str = os.getenv("XIAOMUSIC_LOUDNORM", None) # 均衡音量参数
search_prefix: str = os.getenv(
"XIAOMUSIC_SEARCH", "bilisearch:"
) # "bilisearch:" or "ytsearch:"
@@ -169,6 +170,9 @@ class Config:
os.getenv("XIAOMUSIC_CONTINUE_PLAY", "false").lower() == "true"
)
pull_ask_sec: int = int(os.getenv("XIAOMUSIC_PULL_ASK_SEC", "1"))
enable_pull_ask: bool = (
os.getenv("XIAOMUSIC_ENABLE_PULL_ASK", "true").lower() == "true"
)
crontab_json: str = os.getenv("XIAOMUSIC_CRONTAB_JSON", "") # 定时任务
enable_yt_dlp_cookies: bool = (
os.getenv("XIAOMUSIC_ENABLE_YT_DLP_COOKIES", "false").lower() == "true"

View File

@@ -2,7 +2,6 @@ import asyncio
import hashlib
import json
import os
import re
import secrets
import shutil
import tempfile
@@ -443,6 +442,16 @@ async def playurl(did: str, url: str, Verifcation=Depends(verification)):
return await xiaomusic.play_url(did=did, arg1=decoded_url)
@app.get("/playtts")
async def playtts(did: str, text: str, Verifcation=Depends(verification)):
if not xiaomusic.did_exist(did):
return {"ret": "Did not exist"}
log.info(f"tts {did} {text}")
await xiaomusic.do_tts(did=did, value=text)
return {"ret": "OK"}
@app.post("/refreshmusictag")
async def refreshmusictag(Verifcation=Depends(verification)):
xiaomusic.refresh_music_tag()
@@ -580,6 +589,7 @@ async def playlistupdatename(
@app.get("/playlistnames")
async def getplaylistnames(Verifcation=Depends(verification)):
names = xiaomusic.get_play_list_names()
log.info(f"names {names}")
return {
"ret": "OK",
"names": names,
@@ -688,9 +698,6 @@ def access_key_verification(file_path, key, code):
return False
range_pattern = re.compile(r"bytes=(\d+)-(\d*)")
def safe_redirect(url):
url = try_add_access_control_param(config, url)
url = url.replace("\\", "")

View File

@@ -6,9 +6,9 @@
<meta name="viewport" content="width=device-width">
<title>Debug For XiaoMusic</title>
<link rel="stylesheet" type="text/css" href="./main.css?version=1734613728">
<link rel="stylesheet" type="text/css" href="./main.css?version=1737418297">
<script src="https://unpkg.com/vconsole@latest/dist/vconsole.min.js"></script>
<script src="./jquery-3.7.1.min.js?version=1734613728"></script>
<script src="./jquery-3.7.1.min.js?version=1737418297"></script>
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-Z09NC1K7ZW"></script>
@@ -20,7 +20,7 @@
</script>
<!-- umami -->
<script defer src="https://umami.hanxi.cc/script.js" data-website-id="7bfb0890-4115-4260-8892-b391513e7e99"></script>
<script async defer src="https://umami.hanxi.cc/script.js" data-website-id="7bfb0890-4115-4260-8892-b391513e7e99"></script>
<script>
var vConsole = new window.VConsole();

View File

@@ -4,8 +4,8 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<title>歌曲下载工具</title>
<link rel="stylesheet" type="text/css" href="./main.css?version=1734613728">
<script src="./jquery-3.7.1.min.js?version=1734613728"></script>
<link rel="stylesheet" type="text/css" href="./main.css?version=1737418297">
<script src="./jquery-3.7.1.min.js?version=1737418297"></script>
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-Z09NC1K7ZW"></script>
@@ -17,7 +17,7 @@
</script>
<!-- umami -->
<script defer src="https://umami.hanxi.cc/script.js" data-website-id="7bfb0890-4115-4260-8892-b391513e7e99"></script>
<script async defer src="https://umami.hanxi.cc/script.js" data-website-id="7bfb0890-4115-4260-8892-b391513e7e99"></script>
</head>
<body>

View File

@@ -6,8 +6,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>小爱音箱操控面板</title>
<link href="https://fonts.googleapis.com/css?family=Material+Icons|Material+Icons+Outlined" rel="stylesheet">
<script src="./jquery-3.7.1.min.js?version=1734613728"></script>
<link rel="stylesheet" href="./main.css?version=1734613728">
<script src="./jquery-3.7.1.min.js?version=1737418297"></script>
<link rel="stylesheet" href="./main.css?version=1737418297">
<link rel="icon" href="./favicon.ico">
<!-- Google tag (gtag.js) -->
@@ -20,7 +20,7 @@
</script>
<!-- umami -->
<script defer src="https://umami.hanxi.cc/script.js" data-website-id="7bfb0890-4115-4260-8892-b391513e7e99"></script>
<script async defer src="https://umami.hanxi.cc/script.js" data-website-id="7bfb0890-4115-4260-8892-b391513e7e99"></script>
</head>
<body class="index_page">
@@ -95,24 +95,18 @@
<span class="material-icons">volume_up</span>
<p>音量</p>
</div>
<!--
<div onclick="toggleLocalPlay()" id="web_play">
<span class="material-icons">headphones</span>
<span class="tooltip">网页播放</span>
</div>
-->
<div onclick="toggleSearch()" class="icon-item device-enable">
<span class="material-icons">search</span>
<p>搜索</p>
</div>
<div onclick="togglePlayLink()" class="icon-item device-enable">
<span class="material-icons">link</span>
<p>链接</p>
</div>
<div onclick="toggleTimer()" class="icon-item device-enable">
<span class="material-icons">timer</span>
<p>定时</p>
</div>
<div onclick="togglePlayLink()" class="icon-item device-enable">
<span class="material-icons">emoji_nature</span>
<p>测试</p>
</div>
<div onclick="openSettings()" class="icon-item">
<span class="material-icons">settings</span>
<p>设置</p>
@@ -154,9 +148,14 @@
<h2>播放链接</h2>
<input type="text" id="music-url" class="search-input" placeholder="请输入播放链接"
value="https://lhttp.qtfm.cn/live/4915/64k.mp3">
<h2>播放文字</h2>
<input type="text" id="text-tts" class="search-input" placeholder="请输入文字"
value="播放文字测试">
<div class="component-button-group">
<button id="playurl">播放链接</button>
<button onclick="togglePlayLink()">关闭</button>
<button onclick="playUrl()">播放链接</button>
<button onclick="playTts()">播放文字</button>
<button onclick="togglePlayLink()">关闭</button>
</div>
</div>
@@ -220,7 +219,7 @@
Powered by XiaoMusic
</div>
<script src="./md.js?version=1734613728">
<script src="./md.js?version=1737418297">
</script>
</body>

View File

@@ -5,7 +5,7 @@
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width">
<title>M3U to JSON Converter</title>
<link rel="stylesheet" type="text/css" href="./main.css?version=1734613728">
<link rel="stylesheet" type="text/css" href="./main.css?version=1737418297">
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-Z09NC1K7ZW"></script>
@@ -17,7 +17,7 @@
</script>
<!-- umami -->
<script defer src="https://umami.hanxi.cc/script.js" data-website-id="7bfb0890-4115-4260-8892-b391513e7e99"></script>
<script async defer src="https://umami.hanxi.cc/script.js" data-website-id="7bfb0890-4115-4260-8892-b391513e7e99"></script>
<!--
<script src="https://unpkg.com/vconsole@latest/dist/vconsole.min.js"></script>

View File

@@ -351,3 +351,8 @@ span,p {
margin-left: auto;
text-decoration: none;
}
.setting-label {
display: flex;
align-items: center;
}

View File

@@ -83,6 +83,9 @@ function nextTrack() {
function togglePlayMode(isSend = true) {
const modeBtnIcon = $("#modeBtn .material-icons");
if (playModeIndex === '') {
playModeIndex = 2;
}
modeBtnIcon.text(playModes[playModeIndex].icon);
$("#modeBtn .tooltip").text(playModes[playModeIndex].cmd);
// return;
@@ -93,7 +96,7 @@ function togglePlayMode(isSend = true) {
function addToFavorites() {
const isLiked = $(".favorite").hasClass("favorite-active");
const cmd = isLiked? "取消收藏": "加入收藏";
const cmd = isLiked ? "取消收藏" : "加入收藏";
if (isLiked) {
$(".favorite").removeClass("favorite-active");
// 取消收藏
@@ -371,14 +374,20 @@ $("#play_music_list").on("click", () => {
});
});
$("#playurl").on("click", () => {
function playUrl() {
var url = $("#music-url").val();
const encoded_url = encodeURIComponent(url);
$.get(`/playurl?url=${encoded_url}&did=${did}`, function (data, status) {
console.log(data);
});
});
}
function playTts() {
var value = $("#text-tts").val();
$.get(`/playtts?text=${value}&did=${did}`, function (data, status) {
console.log(data);
});
}
function do_play_music(musicname, searchkey) {
$.ajax({
@@ -563,8 +572,10 @@ function get_playing_music() {
if (data.ret == "OK") {
if (data.is_playing) {
$("#playering-music").text(`【播放中】 ${data.cur_music}`);
isPlaying = true;
} else {
$("#playering-music").text(`【空闲中】 ${data.cur_music}`);
isPlaying = false;
}
offset = data.offset;
duration = data.duration;
@@ -585,9 +596,11 @@ function get_playing_music() {
}
setInterval(() => {
if (duration > 0) {
offset++;
$("#progress").val((offset / duration) * 100);
$("#current-time").text(formatTime(offset));
if (isPlaying) {
offset++;
$("#progress").val((offset / duration) * 100);
$("#current-time").text(formatTime(offset));
}
$("#duration").text(formatTime(duration));
} else {
$("#current-time").text(formatTime(0));
@@ -652,7 +665,7 @@ function timedShutDown(cmd) {
}
// 绑定点击事件,显示弹窗
$('#version').on('click', function() {
$('#version').on('click', function () {
$.get("https://xdocs.hanxi.cc/versions.json", function (data, status) {
console.log(data);
const versionSelect = document.getElementById("update-version");
@@ -692,3 +705,20 @@ function doUpdates() {
},
});
}
function confirmSearch() {
var search_key = $("#search").val();
if (search_key == null) {
search_key = "";
}
var filename = $("#music-name").val();
var musicfilename = $("#music-filename").val();
if ((filename == null || filename == "" || filename == search_key)
&& (musicfilename != null && musicfilename != "")) {
filename = musicfilename;
}
console.log("confirmSearch", filename, search_key);
do_play_music(filename, search_key);
toggleSearch();
}

View File

@@ -5,9 +5,9 @@
<meta name="viewport" content="width=device-width">
<title>小爱音箱操控面板</title>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<script src="./jquery-3.7.1.min.js?version=1734613728"></script>
<script src="./setting.js?version=1734613728"></script>
<link rel="stylesheet" type="text/css" href="./main.css?version=1734613728">
<script src="./jquery-3.7.1.min.js?version=1737418297"></script>
<script src="./setting.js?version=1737418297"></script>
<link rel="stylesheet" type="text/css" href="./main.css?version=1737418297">
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-Z09NC1K7ZW"></script>
@@ -19,7 +19,7 @@
</script>
<!-- umami -->
<script defer src="https://umami.hanxi.cc/script.js" data-website-id="7bfb0890-4115-4260-8892-b391513e7e99"></script>
<script async defer src="https://umami.hanxi.cc/script.js" data-website-id="7bfb0890-4115-4260-8892-b391513e7e99"></script>
<!--
<script src="https://unpkg.com/vconsole@latest/dist/vconsole.min.js"></script>
@@ -50,24 +50,32 @@ var vConsole = new window.VConsole();
<label for="password">*小米密码:</label>
<input id="password" type="password" placeholder="填写小米登录密码" />
<label for="hostname">*XIAOMUSIC_HOSTNAME(IP或域名):</label>
<label for="hostname" class="setting-label">*NAS的IP或域名:
<button class="option-inline mini-button" id="auto-hostname">
<span class="material-icons">edit</span>
<span>自动填</span>
</button>
</label>
<input id="hostname" type="text" />
<label for="public_port" class="setting-label">*本地端口:
<button class="option-inline mini-button" id="auto-port">
<span class="material-icons">edit</span>
<span>自动填</span>
</button>
</label>
<input id="public_port" type="number" value="0" />
</div>
<hr>
<div class="rows">
<label for="verbose">是否开启调试日志:</label>
<select id="verbose">
<option value="true" selected>true</option>
<option value="false">false</option>
<option value="true">true</option>
<option value="false" selected>false</option>
</select>
<label for="port">监听端口(修改后需要重启):</label>
<input id="port" type="number" value="8090" />
<label for="public_port">外网访问端口(0表示跟监听端口一致):</label>
<input id="public_port" type="number" value="0" />
<label for="group_list">设备分组配置:<a href="https://github.com/hanxi/xiaomusic/issues/65#issuecomment-2215736529" target="_blank">文档</a></label>
<label for="group_list">设备分组配置(不推荐,声音不同步):<a href="https://xdocs.hanxi.cc/issues/366.html" target="_blank">文档</a></label>
<input id="group_list" type="text" placeholder="did1:组名1,did2:组名1,did3:组名2" />
<label for="music_path">音乐目录:</label>
@@ -112,6 +120,9 @@ var vConsole = new window.VConsole();
<label for="proxy">XIAOMUSIC_PROXY(ytsearch需要):</label>
<input id="proxy" type="text" placeholder="http://192.168.2.5:8080" />
<label for="loudnorm">均衡歌曲音量大小(loudnorm滤镜):</label>
<input id="loudnorm" type="text" placeholder="loudnorm=I=-14:TP=-1.5:LRA=6" />
<label for="remove_id3tag">去除MP3 ID3v2和填充:</label>
<select id="remove_id3tag">
<option value="true">true</option>
@@ -124,7 +135,7 @@ var vConsole = new window.VConsole();
<option value="false" selected>false</option>
</select>
<label for="miio_tts_command">MiIO tts 指令(解决部分型号没有提示音的问题):</label>
<label for="miio_tts_command">MiIO ttsCommand 指令(解决部分型号没有提示音的问题):<a href="https://xdocs.hanxi.cc/issues/365.html" target="_blank">格式文档</a></label>
<input id="miio_tts_command" type="text" placeholder="如5 或者 5-3" />
<label for="disable_httpauth">关闭控制台密码验证:</label>
@@ -169,6 +180,12 @@ var vConsole = new window.VConsole();
<option value="false" selected>false</option>
</select>
<label for="enable_pull_ask">获取对话记录:</label>
<select id="enable_pull_ask">
<option value="true" selected>true</option>
<option value="false">false</option>
</select>
<label for="pull_ask_sec">获取对话记录间隔(秒):</label>
<input id="pull_ask_sec" type="number" value="1" />
@@ -207,6 +224,12 @@ var vConsole = new window.VConsole();
<option value="false" selected>false</option>
</select>
<label for="enable_save_tag">启用ID3标签写入文件:</label>
<select id="enable_save_tag">
<option value="true">true</option>
<option value="false" selected>false</option>
</select>
<label for="get_ask_by_mina">特殊型号获取对话记录:</label>
<select id="get_ask_by_mina">
<option value="true">true</option>
@@ -216,7 +239,7 @@ var vConsole = new window.VConsole();
<label for="recently_added_playlist_len">最近新增的歌曲数量:</label>
<input id="recently_added_playlist_len" type="number" value="50" />
<label for="music_list_url" style="display: flex;align-items: center;">歌单地址:
<label for="music_list_url" class="setting-label">歌单地址:
<button class="option-inline mini-button" id="get_music_list">
<span class="material-icons">sync_alt</span>
<span>获取歌单</span>
@@ -224,17 +247,17 @@ var vConsole = new window.VConsole();
</label>
<input id="music_list_url" type="text" value="https://gist.githubusercontent.com/hanxi/dda82d964a28f8110f8fba81c3ff8314/raw/example.json" />
<label for="music_list_json">歌单内容:<a href="https://github.com/hanxi/xiaomusic/issues/78" target="_blank">格式文档</a></label>
<label for="music_list_json">歌单内容:<a href="https://xdocs.hanxi.cc/issues/78.html" target="_blank">格式文档</a></label>
<textarea id="music_list_json" type="text"></textarea>
<label for="crontab_json">定时任务:<a href="https://github.com/hanxi/xiaomusic/issues/182" target="_blank">格式文档</a></label>
<label for="crontab_json">定时任务:<a href="https://xdocs.hanxi.cc/issues/182.html" target="_blank">格式文档</a></label>
<textarea id="crontab_json" type="text"></textarea>
</div>
</div>
<hr>
<div class="rows">
<label for="yt_dlp_cookies_file">上传yt_dlp_cookies.txt文件:<a href="https://github.com/hanxi/xiaomusic/issues/210" target="_blank">文档</a></label>
<label for="yt_dlp_cookies_file">上传yt_dlp_cookies.txt文件:<a href="https://xdocs.hanxi.cc/issues/210.html" target="_blank">文档</a></label>
<input id="yt_dlp_cookies_file" name="file" type="file">
<button id="upload_yt_dlp_cookie">上传</button>
</div>

View File

@@ -1,13 +1,13 @@
$(function(){
$(function () {
// 拉取版本
$.get("/getversion", function(data, status) {
$.get("/getversion", function (data, status) {
console.log(data, status, data["version"]);
$("#version").text(`${data.version}`);
});
// 遍历所有的select元素默认选中只有1个选项的
const autoSelectOne = () => {
$('select').each(function() {
$('select').each(function () {
// 如果select元素仅有一个option子元素
if ($(this).children('option').length === 1) {
// 选中这个option
@@ -16,7 +16,7 @@ $(function(){
});
};
function updateCheckbox(selector, mi_did, device_list,accountPassValid) {
function updateCheckbox(selector, mi_did, device_list, accountPassValid) {
// 清除现有的内容
$(selector).empty();
@@ -29,7 +29,7 @@ $(function(){
$(selector).append(loginTips);
return;
}
$.each(device_list, function(index, device) {
$.each(device_list, function (index, device) {
var did = device.miotDID;
var hardware = device.hardware;
var name = device.name;
@@ -59,7 +59,7 @@ $(function(){
var selectedDids = [];
// 仅选择给定容器中选中的复选框
$(containerSelector + ' .custom-checkbox:checked').each(function() {
$(containerSelector + ' .custom-checkbox:checked').each(function () {
var did = this.value;
selectedDids.push(did);
});
@@ -68,23 +68,23 @@ $(function(){
}
// 拉取现有配置
$.get("/getsetting?need_device_list=true", function(data, status) {
$.get("/getsetting?need_device_list=true", function (data, status) {
console.log(data, status);
const accountPassValid = data.account && data.password;
updateCheckbox("#mi_did", data.mi_did, data.device_list, accountPassValid);
// 初始化显示
for (const key in data) {
const $element = $("#" + key);
if ($element.length) {
if (data[key] === true) {
$element.val('true');
} else if (data[key] === false) {
$element.val('false');
} else {
$element.val(data[key]);
}
const $element = $("#" + key);
if ($element.length) {
if (data[key] === true) {
$element.val('true');
} else if (data[key] === false) {
$element.val('false');
} else {
$element.val(data[key]);
}
}
}
autoSelectOne();
@@ -94,7 +94,7 @@ $(function(){
var setting = $('#setting');
var inputs = setting.find('input, select, textarea');
var data = {};
inputs.each(function() {
inputs.each(function () {
var id = this.id;
if (id) {
data[id] = $(this).val();
@@ -173,17 +173,17 @@ $(function(){
data: formData,
processData: false,
contentType: false,
success: function(res) {
success: function (res) {
console.log(res);
alert("上传成功");
},
error: function(jqXHR, textStatus, errorThrown) {
error: function (jqXHR, textStatus, errorThrown) {
console.log(res);
alert("上传失败");
}
});
} else {
alert("请选择一个文件");
alert("请选择一个文件");
}
});
@@ -191,14 +191,29 @@ $(function(){
$("#clear_cache").on("click", () => {
localStorage.clear();
});
$("#hostname").on("change", function(){
$("#hostname").on("change", function () {
const hostname = $(this).val();
// 检查是否包含端口号1到5位数字
if (hostname.match(/:\d{1,5}$/)) {
alert("hostname禁止带端口号");
// 移除端口号
$(this).val(hostname.replace(/:\d{1,5}$/,""));
$(this).val(hostname.replace(/:\d{1,5}$/, ""));
}
});
$("#auto-hostname").on("click", () => {
const protocol = window.location.protocol;
const hostname = window.location.hostname;
const baseUrl = `${protocol}//${hostname}`;
console.log(baseUrl);
$("#hostname").val(baseUrl);
});
$("#auto-port").on("click", () => {
const port = window.location.port;
console.log(port);
$("#public_port").val(port);
});
});

View File

@@ -20,7 +20,7 @@
</script>
<!-- umami -->
<script defer src="https://umami.hanxi.cc/script.js" data-website-id="7bfb0890-4115-4260-8892-b391513e7e99"></script>
<script async defer src="https://umami.hanxi.cc/script.js" data-website-id="7bfb0890-4115-4260-8892-b391513e7e99"></script>
<script>
var vConsole = new window.VConsole();

View File

@@ -17,7 +17,7 @@
</script>
<!-- umami -->
<script defer src="https://umami.hanxi.cc/script.js" data-website-id="7bfb0890-4115-4260-8892-b391513e7e99"></script>
<script async defer src="https://umami.hanxi.cc/script.js" data-website-id="7bfb0890-4115-4260-8892-b391513e7e99"></script>
</head>
<body>

View File

@@ -18,7 +18,7 @@
</script>
<!-- umami -->
<script defer src="https://umami.hanxi.cc/script.js" data-website-id="7bfb0890-4115-4260-8892-b391513e7e99"></script>
<script async defer src="https://umami.hanxi.cc/script.js" data-website-id="7bfb0890-4115-4260-8892-b391513e7e99"></script>
<!--
<script src="https://unpkg.com/vconsole@latest/dist/vconsole.min.js"></script>

View File

@@ -17,7 +17,7 @@
</script>
<!-- umami -->
<script defer src="https://umami.hanxi.cc/script.js" data-website-id="7bfb0890-4115-4260-8892-b391513e7e99"></script>
<script async defer src="https://umami.hanxi.cc/script.js" data-website-id="7bfb0890-4115-4260-8892-b391513e7e99"></script>
<!--
<script src="https://unpkg.com/vconsole@latest/dist/vconsole.min.js"></script>

View File

@@ -18,7 +18,7 @@
</script>
<!-- umami -->
<script defer src="https://umami.hanxi.cc/script.js" data-website-id="7bfb0890-4115-4260-8892-b391513e7e99"></script>
<script async defer src="https://umami.hanxi.cc/script.js" data-website-id="7bfb0890-4115-4260-8892-b391513e7e99"></script>
<!--
<script src="https://unpkg.com/vconsole@latest/dist/vconsole.min.js"></script>
@@ -111,6 +111,9 @@ var vConsole = new window.VConsole();
<label for="proxy">XIAOMUSIC_PROXY(ytsearch需要):</label>
<input id="proxy" type="text" placeholder="http://192.168.2.5:8080" />
<label for="loudnorm">均衡歌曲音量大小(loudnorm滤镜):</label>
<input id="loudnorm" type="text" placeholder="loudnorm=I=-14:TP=-1.5:LRA=6" />
<label for="remove_id3tag">去除MP3 ID3v2和填充:</label>
<select id="remove_id3tag">
<option value="true">true</option>

View File

@@ -1,5 +1,5 @@
<!DOCTYPE html>
<html lang="en">
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
@@ -20,7 +20,7 @@
</script>
<!-- umami -->
<script defer src="https://umami.hanxi.cc/script.js" data-website-id="7bfb0890-4115-4260-8892-b391513e7e99"></script>
<script async defer src="https://umami.hanxi.cc/script.js" data-website-id="7bfb0890-4115-4260-8892-b391513e7e99"></script>
<script type="text/javascript">
if (navigator.serviceWorker != null) {
@@ -48,6 +48,9 @@
<div class="options_list">
<a href="/static/default/index.html">默认主题</a>
</div>
<div class="options_list">
<a href="/static/tailwind/index.html">Tailwind主题</a>
</div>
<div class="options_list">
<a href="/static/default_past/index.html">怀旧主题</a>
</div>

View File

@@ -23,7 +23,7 @@
</script>
<!-- umami -->
<script defer src="https://umami.hanxi.cc/script.js" data-website-id="7bfb0890-4115-4260-8892-b391513e7e99"></script>
<script async defer src="https://umami.hanxi.cc/script.js" data-website-id="7bfb0890-4115-4260-8892-b391513e7e99"></script>
</body>
</html>

View File

@@ -0,0 +1,78 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width">
<title>Debug For XiaoMusic</title>
<link rel="stylesheet" type="text/css" href="./main.css?version=1736211336">
<script src="https://unpkg.com/vconsole@latest/dist/vconsole.min.js"></script>
<script src="./jquery-3.7.1.min.js?version=1736211336"></script>
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-Z09NC1K7ZW"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments)};
gtag('js', new Date());
gtag('config', 'G-Z09NC1K7ZW');
</script>
<!-- umami -->
<script async defer src="https://umami.hanxi.cc/script.js" data-website-id="7bfb0890-4115-4260-8892-b391513e7e99"></script>
<script>
var vConsole = new window.VConsole();
function postJSON() {
var data = $('#post-input').val();
$.ajax({
type: 'POST',
url: '/debug_play_by_music_url',
data: data,
contentType: "application/json; charset=utf-8",
success: (err) => {
console.log("succ", res);
},
error: (res) => {
console.log("error", res);
}
});
}
function sendDebugCmd() {
var cmd = $("#cmd").val();
var did = localStorage.getItem('cur_did');
$.ajax({
type: "POST",
url: "/cmd",
contentType: "application/json; charset=utf-8",
data: JSON.stringify({did: did, cmd: cmd}),
success: () => {
},
error: () => {
// 请求失败时执行的操作
}
});
}
</script>
</head>
<body>
<h1>Debug For XiaoMusic</h1>
<div class="debug">
<textarea id="post-input" rows="10" cols="50" placeholder="粘贴json数据..."></textarea><br>
<button onclick="postJSON()">提交</button><br>
</div>
<hr>
<div class="debug">
<input id="cmd" type="text"></input>
<button onclick="sendDebugCmd()">测试自定义口令</button><br>
</div>
</body>
<footer>
<p>Powered by <a href="https://xdocs.hanxi.cc" target="_blank">XiaoMusic</a></p>
</footer>
</html>

View File

@@ -0,0 +1,238 @@
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<title>歌曲下载工具</title>
<script src="./jquery-3.7.1.min.js?version=1736211336"></script>
<script src="./tailwind.js"></script>
<link rel="icon" href="./favicon.ico">
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-Z09NC1K7ZW"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() { dataLayer.push(arguments) };
gtag('js', new Date());
gtag('config', 'G-Z09NC1K7ZW');
</script>
<!-- umami -->
<script async defer src="https://umami.hanxi.cc/script.js"
data-website-id="7bfb0890-4115-4260-8892-b391513e7e99"></script>
</head>
<body class="bg-gray-100 min-h-screen p-6">
<div class="max-w-4xl mx-auto">
<div class="bg-white rounded-lg shadow-md p-6">
<div class="flex justify-between items-center mb-6">
<h1 class="text-2xl font-bold text-gray-900">歌曲下载工具</h1>
<button onclick="location.href='/static/default/setting.html';"
class="px-4 py-2 bg-gray-100 text-gray-700 rounded-md hover:bg-gray-200">
返回设置
</button>
</div>
<!-- 歌单下载部分 -->
<div class="space-y-4 mb-8">
<div class="space-y-4">
<div>
<label for="playlistUrl" class="block text-sm font-medium text-gray-700 mb-1">输入歌单 URL:</label>
<input type="text" id="playlistUrl" value="https://m.bilibili.com/video/BV1WUsDezE88"
class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500">
</div>
<div>
<label for="dirname" class="block text-sm font-medium text-gray-700 mb-1">输入歌单名字:</label>
<input type="text" id="dirname" placeholder="流行歌曲"
class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500">
</div>
<button id="downloadPlaylistBtn"
class="w-full px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors">
下载歌单
</button>
</div>
</div>
<div class="border-t border-gray-200 my-6"></div>
<!-- 单曲下载部分 -->
<div class="space-y-4">
<div>
<label for="songUrl" class="block text-sm font-medium text-gray-700 mb-1">输入歌曲 URL:</label>
<input type="text" id="songUrl" value="https://m.bilibili.com/video/BV1qD4y1U7fs"
class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500">
</div>
<div>
<label for="songName" class="block text-sm font-medium text-gray-700 mb-1">输入歌曲名字:</label>
<input type="text" id="songName" placeholder="歌曲名"
class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500">
</div>
<button id="downloadSongBtn"
class="w-full px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors">
下载单曲
</button>
</div>
</div>
<!-- 使用说明部分 -->
<div class="bg-white rounded-lg shadow-md p-6 mt-6">
<h2 class="text-lg font-medium text-gray-900 mb-4">使用说明</h2>
<div class="prose prose-blue">
<div class="bg-blue-50 border-l-4 border-blue-500 p-4 rounded">
<ul class="space-y-2 text-gray-600">
<li>• 支持下载B站和YouTube的播放列表或单个视频</li>
<li>• 播放列表链接格式要求:
<ul class="ml-4 mt-1 space-y-1">
<li>- B站示例<code
class="bg-blue-100 px-2 py-0.5 rounded">https://m.bilibili.com/video/BV1WUsDezE88</code>
</li>
<li>- YouTube示例<code
class="bg-blue-100 px-2 py-0.5 rounded">https://m.youtube.com/playlist?list=PLUD2d-pqyvT6_ztf31hx-5SsUUvY5UsQn</code>
</li>
<li>- 链接中不能包含其他多余参数</li>
</ul>
</li>
<li>• 歌单名称用于创建保存文件夹,建议每次使用新的名称</li>
<li>• YouTube下载需要上传cookies.txt文件<a href="https://github.com/hanxi/xiaomusic/issues/210"
class="text-blue-600 hover:text-blue-800 underline" target="_blank">查看详细说明</a></li>
<li>• 也支持下载单个视频的音频</li>
</ul>
</div>
</div>
</div>
<!-- 底部按钮组 - 改进移动端显示 -->
<div class="fixed bottom-0 left-0 right-0 bg-white border-t">
<div class="container mx-auto px-4 py-3">
<!-- 所有按钮的容器 -->
<div class="flex flex-col sm:flex-row sm:justify-end gap-2">
<!-- 工具按钮 -->
<div class="grid grid-cols-3 sm:flex sm:flex-wrap gap-2">
<a href="/docs" target="_blank" class="flex-1 sm:flex-none">
<button
class="w-full px-4 py-2 bg-white border border-gray-300 text-gray-700 rounded-md hover:bg-gray-50">
<span class="hidden sm:inline">接口文档</span>
<span class="sm:hidden">文档</span>
</button>
</a>
<a href="./m3u.html" target="_blank" class="flex-1 sm:flex-none">
<button
class="w-full px-4 py-2 bg-white border border-gray-300 text-gray-700 rounded-md hover:bg-gray-50">
<span class="hidden sm:inline">m3u转换</span>
<span class="sm:hidden">m3u</span>
</button>
</a>
<a href="./downloadtool.html" target="_blank" class="flex-1 sm:flex-none">
<button
class="w-full px-4 py-2 bg-white border border-gray-300 text-gray-700 rounded-md hover:bg-gray-50">
<span class="hidden sm:inline">歌曲下载工具</span>
<span class="sm:hidden">下载</span>
</button>
</a>
<a href="./debug.html" target="_blank" class="flex-1 sm:flex-none">
<button
class="w-full px-4 py-2 bg-white border border-gray-300 text-gray-700 rounded-md hover:bg-gray-50">
<span class="hidden sm:inline">调试工具</span>
<span class="sm:hidden">调试</span>
</button>
</a>
<a href="https://github.com/hanxi/xiaomusic" target="_blank" class="flex-1 sm:flex-none">
<button
class="w-full px-4 py-2 bg-white border border-gray-300 text-gray-700 rounded-md hover:bg-gray-50">
GitHub
</button>
</a>
<a href="https://afdian.com/a/imhanxi" target="_blank" class="flex-1 sm:flex-none">
<button
class="w-full px-4 py-2 bg-blue-500 border border-gray-300 text-white rounded-md hover:bg-blue-600">
<span class="hidden sm:inline">💰 爱发电</span>
<span class="sm:hidden">💰爱发电</span>
</button>
</a>
</div>
</div>
</div>
</div>
<!-- 二维码 -->
<div class="text-center mt-12 mb-24">
<div class="bg-white p-6 rounded-lg border inline-block">
<img class="qrcode mx-auto w-40 sm:w-64 h-40 sm:h-64" src="./qrcode.png" alt="请涵曦喝奶茶🧋">
<p class="mt-4 text-gray-600 font-medium">扫码请涵曦喝奶茶🧋</p>
</div>
<footer class="mt-6 text-sm sm:text-base text-gray-600">
<p>Powered by <a href="https://xdocs.hanxi.cc" target="_blank"
class="text-blue-600 hover:text-blue-800">XiaoMusic</a></p>
</footer>
</div>
</div>
</div>
<script>
// 下载歌单
$('#downloadPlaylistBtn').click(function () {
var playlistUrl = $('#playlistUrl').val();
var dirname = $('#dirname').val();
if (!playlistUrl || !dirname) {
alert('请填写完整的歌单 URL 和歌单名字');
return;
}
var data = {
dirname: dirname,
url: playlistUrl
};
$.ajax({
type: "POST",
url: "/downloadplaylist",
contentType: "application/json",
data: JSON.stringify(data),
success: (msg) => {
alert('歌单下载请求已发送!');
console.log(response);
},
error: (msg) => {
alert('歌单下载请求失败,请重试。');
}
});
});
// 下载单曲
$('#downloadSongBtn').click(function () {
var songName = $('#songName').val();
var songUrl = $('#songUrl').val();
if (!songUrl || !songName) {
alert('请填写完整的歌曲 URL 和歌曲名字');
return;
}
var data = {
name: songName,
url: songUrl
};
$.ajax({
type: "POST",
url: "/downloadonemusic",
contentType: "application/json",
data: JSON.stringify(data),
success: (msg) => {
alert('单曲下载请求已发送!');
console.log(response);
},
error: (msg) => {
alert('单曲下载请求失败,请重试。');
}
});
});
</script>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 894 B

View File

@@ -0,0 +1,259 @@
<!DOCTYPE html>
<html lang="zh" class="h-full">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>小爱音箱音乐播放器</title>
<link href="https://fonts.googleapis.com/css?family=Material+Icons|Material+Icons+Outlined" rel="stylesheet">
<script src="./jquery-3.7.1.min.js?version=1736211336"></script>
<script src="./tailwind.js"></script>
<script src="./theme.js"></script>
<link rel="icon" href="./favicon.ico">
<style>
.dark .dark\:bg-gray-900 { background-color: #121212; }
.dark .dark\:text-white { color: #ffffff; }
.dark .dark\:bg-gray-800 { background-color: #282828; }
.dark .dark\:hover\:bg-gray-700:hover { background-color: #383838; }
</style>
</head>
<body class="h-full bg-gray-100 dark:bg-gray-900 text-gray-900 dark:text-white transition-colors duration-200">
<div class="h-full flex flex-col md:flex-row pb-24 md:pb-20">
<!-- 左侧边栏 - 播放列表选择 -->
<div class="w-full md:w-64 bg-white dark:bg-gray-800 p-6 flex-shrink-0 overflow-y-auto">
<!-- 标题 - 仅在桌面端显示 -->
<div class="mb-8 hidden md:block">
<h1 class="text-2xl font-bold mb-4 text-gray-900 dark:text-white">小爱音箱播放器
<a id="version" href="https://github.com/hanxi/xiaomusic" class="text-sm text-blue-500 dark:text-blue-400 ml-2">1.0.0</a>
<span id="versionnew" class="new-badge"></span>
</h1>
</div>
<!-- 设备选择 -->
<div class="mb-6">
<h2 class="text-sm font-semibold text-gray-600 dark:text-white uppercase tracking-wider mb-3 hidden md:block">播放设备</h2>
<div id="device-buttons" class="md:space-y-2 flex md:flex-col overflow-x-auto md:overflow-visible space-x-2 md:space-x-0 pb-2">
<!-- 设备按钮将通过 JavaScript 动态添加 -->
</div>
</div>
<!-- 歌单分类 -->
<div class="mb-6">
<!-- 刷新按钮单独放置 -->
<div class="fixed top-16 right-4 z-10 md:static md:mb-3">
<button onclick="refresh_music_list()" class="w-8 h-8 flex items-center justify-center rounded-full hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors" title="刷新歌单列表">
<span class="material-icons text-gray-600 dark:text-gray-400">refresh</span>
</button>
</div>
<!-- 歌单列表 -->
<div id="system-playlists" class="flex-1 md:space-y-2 flex md:flex-col overflow-x-auto md:overflow-visible space-x-2 md:space-x-0 mt-2 md:mt-0">
<!-- 系统播放列表将通过 JavaScript 动态添加 -->
</div>
</div>
<!-- 专辑分类 -->
<div class="mb-6">
<h2 class="text-sm font-semibold text-gray-600 dark:text-white uppercase tracking-wider mb-3 hidden md:block">专辑</h2>
<div id="album-list" class="md:space-y-2 flex md:flex-col overflow-x-auto md:overflow-visible space-x-2 md:space-x-0">
<!-- 专辑列表将通过 JavaScript 动态添加 -->
</div>
<div class="border-t border-gray-200 dark:border-gray-700 my-3"></div>
</div>
</div>
<!-- 主内容区 -->
<div class="flex-1 overflow-auto bg-white dark:bg-gray-900">
<!-- 顶部操作栏 -->
<div class="sticky top-0 bg-white dark:bg-gray-900 p-4 z-10">
<div class="flex items-center justify-between space-x-4">
<!-- 搜索框 -->
<div class="relative flex-1">
<span class="material-icons absolute left-3 top-2.5 text-gray-400">search</span>
<input type="text" id="search-input" placeholder="搜索歌曲" class="w-full bg-gray-200 dark:bg-gray-700 text-gray-900 dark:text-white pl-10 pr-4 py-2 rounded-full" oninput="searchSongs()">
</div>
<!-- 操作按钮 -->
<div class="flex items-center space-x-2">
<button onclick="toggleTheme()" class="w-10 h-10 flex items-center justify-center rounded-full hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors">
<span class="material-icons block dark:hidden">light_mode</span>
<span class="material-icons hidden dark:block">dark_mode</span>
</button>
<button onclick="openSettings()" class="w-10 h-10 flex items-center justify-center rounded-full hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors">
<span class="material-icons">settings</span>
</button>
</div>
</div>
</div>
<!-- 歌曲列表区域 -->
<div class="p-6">
<div class="mb-6 flex items-center justify-between">
<div class="flex items-center space-x-4">
<h2 class="text-2xl font-bold">歌曲列表</h2>
<button onclick="toggleDeleteButtons()" class="w-8 h-8 flex items-center justify-center rounded-full hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors">
<span class="material-icons text-gray-600 dark:text-gray-400">delete_outline</span>
</button>
</div>
</div>
<!-- 歌曲列表 -->
<div id="song-list" class="space-y-2">
<!-- 歌曲行示例 -->
<div class="song-item flex items-center justify-between p-3 bg-gray-200 dark:bg-gray-800 rounded-lg hover:bg-gray-300 dark:hover:bg-gray-700 transition-colors">
<div class="flex items-center space-x-3 flex-1">
<div class="w-10 h-10 bg-gray-300 dark:bg-gray-700 rounded flex items-center justify-center flex-shrink-0">
<span class="material-icons text-gray-500 dark:text-gray-400">music_note</span>
</div>
<div class="min-w-0 flex-1">
<h3 class="font-semibold truncate dark:text-blue-400">歌曲名称</h3>
</div>
</div>
<button onclick="playMusic(this.parentElement.querySelector('h3').textContent)" class="w-10 h-10 flex items-center justify-center rounded-full hover:bg-gray-400 dark:hover:bg-gray-600 transition-colors">
<span class="material-icons text-gray-600 dark:text-gray-300">play_arrow</span>
</button>
</div>
</div>
</div>
</div>
</div>
<!-- 底部播放控制栏 -->
<div class="fixed bottom-0 left-0 right-0 bg-white dark:bg-gray-800 border-t border-gray-300 dark:border-gray-700 p-4">
<div class="max-w-screen-xl mx-auto">
<!-- 移动端布局 -->
<div class="md:hidden">
<div class="flex items-center justify-between mb-3">
<div class="flex items-center space-x-3">
<div class="w-10 h-10 bg-gray-300 dark:bg-gray-700 rounded flex items-center justify-center">
<span class="material-icons text-gray-500 dark:text-gray-400">album</span>
</div>
<div>
<h3 id="playering-music-mobile" class="font-semibold text-sm truncate">当前播放歌曲:无</h3>
<p class="text-xs text-gray-600 dark:text-gray-400 truncate">艺术家</p>
</div>
</div>
<div class="flex items-center space-x-2">
<button onclick="toggleTimer()" class="p-2 hover:bg-gray-200 dark:hover:bg-gray-700 rounded-full">
<span class="material-icons">timer</span>
</button>
<button onclick="play()" class="w-12 h-12 flex items-center justify-center rounded-full bg-blue-500 text-white hover:bg-blue-600 transition-colors">
<span class="material-icons-outlined play">play_circle_outline</span>
</button>
</div>
</div>
<div class="flex items-center space-x-2 text-xs">
<span id="current-time-mobile" class="text-gray-600 dark:text-gray-400">0:00</span>
<div class="flex-1 h-1 bg-gray-300 dark:bg-gray-600 rounded-full">
<div id="progress-mobile" class="h-full bg-blue-500 rounded-full" style="width: 0%"></div>
</div>
<span id="duration-mobile" class="text-gray-600 dark:text-gray-400">0:00</span>
</div>
</div>
<!-- 桌面端布局 -->
<div class="hidden md:flex items-center justify-between">
<div class="flex items-center space-x-4 w-1/4">
<div class="w-14 h-14 bg-gray-300 dark:bg-gray-700 rounded flex items-center justify-center">
<span class="material-icons text-2xl text-gray-500 dark:text-gray-400">album</span>
</div>
<div>
<h3 id="playering-music" class="font-semibold truncate">当前播放歌曲:无</h3>
<p class="text-sm text-gray-600 dark:text-gray-400 truncate">艺术家</p>
</div>
</div>
<div class="flex flex-col items-center w-2/4">
<div class="flex items-center space-x-4 mb-2">
<button id="modeBtn" onclick="togglePlayMode()" class="w-10 h-10 flex items-center justify-center rounded-full hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors relative group">
<span class="material-icons">shuffle</span>
<span class="tooltip absolute bottom-full left-1/2 transform -translate-x-1/2 mb-2 px-2 py-1 text-xs text-white bg-gray-800 rounded whitespace-nowrap opacity-0 group-hover:opacity-100 transition-opacity">随机播放</span>
</button>
<button onclick="prevTrack()" class="w-10 h-10 flex items-center justify-center rounded-full hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors">
<span class="material-icons">skip_previous</span>
</button>
<button onclick="play()" class="w-12 h-12 flex items-center justify-center rounded-full bg-blue-500 text-white hover:bg-blue-600 transition-colors">
<span class="material-icons-outlined play">play_circle_outline</span>
</button>
<button onclick="nextTrack()" class="w-10 h-10 flex items-center justify-center rounded-full hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors">
<span class="material-icons">skip_next</span>
</button>
<button onclick="stopPlay()" class="w-10 h-10 flex items-center justify-center rounded-full hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors">
<span class="material-icons">stop</span>
</button>
<button onclick="addToFavorites()" class="w-10 h-10 flex items-center justify-center rounded-full hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors">
<span class="material-icons favorite-icon">favorite_border</span>
</button>
<button onclick="toggleTimer()" class="w-10 h-10 flex items-center justify-center rounded-full hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors relative">
<span class="material-icons">timer</span>
</button>
</div>
<div class="w-full flex items-center space-x-3">
<span id="current-time" class="text-xs text-gray-600 dark:text-gray-400">0:00</span>
<div class="flex-1 h-1 bg-gray-300 dark:bg-gray-600 rounded-full">
<div id="progress" class="h-full bg-blue-500 rounded-full" style="width: 0%"></div>
</div>
<span id="duration" class="text-xs text-gray-600 dark:text-gray-400">0:00</span>
</div>
</div>
<div class="flex items-center justify-end space-x-4 w-1/4">
<span class="material-icons text-gray-600 dark:text-gray-400">volume_up</span>
<input type="range" id="volume-slider" min="0" max="1" step="0.01" class="w-24" oninput="adjustVolume(this.value)">
</div>
</div>
</div>
</div>
<!-- 隐藏的音频元素 -->
<audio id="audio" src="" autoplay class="hidden"></audio>
<!-- 定时关机组件 -->
<div class="component hidden fixed inset-0 z-50" id="timer-component">
<!-- 定时选择框 -->
<div class="fixed top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-64 bg-white dark:bg-gray-800 rounded-lg shadow-lg border border-gray-200 dark:border-gray-700 overflow-hidden">
<div class="p-4 border-b border-gray-200 dark:border-gray-700">
<h3 class="text-lg font-semibold text-gray-900 dark:text-white">定时关机</h3>
</div>
<div class="divide-y divide-gray-200 dark:divide-gray-700">
<button onclick="timedShutDown('10分钟后关机')" class="w-full p-3 text-left hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors flex items-center space-x-3">
<span class="material-icons text-gray-500 dark:text-gray-400">timer</span>
<span class="text-gray-700 dark:text-white">10分钟后关机</span>
</button>
<button onclick="timedShutDown('30分钟后关机')" class="w-full p-3 text-left hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors flex items-center space-x-3">
<span class="material-icons text-gray-500 dark:text-gray-400">timer</span>
<span class="text-gray-700 dark:text-white">30分钟后关机</span>
</button>
<button onclick="timedShutDown('60分钟后关机')" class="w-full p-3 text-left hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors flex items-center space-x-3">
<span class="material-icons text-gray-500 dark:text-gray-400">timer</span>
<span class="text-gray-700 dark:text-white">60分钟后关机</span>
</button>
</div>
<div class="p-3 text-center border-t border-gray-200 dark:border-gray-700">
<span class="timer-tooltip hidden text-green-500 text-sm">已发送指令</span>
</div>
</div>
<!-- 背景遮罩 -->
<div class="fixed inset-0 bg-black bg-opacity-25" onclick="toggleTimer()"></div>
</div>
<!-- 设置组件 -->
<div class="component hidden fixed inset-0 bg-black bg-opacity-50 backdrop-blur-sm z-50" id="settings-component">
<div class="relative top-20 mx-auto p-5 border w-96 max-w-[90%] shadow-lg rounded-md bg-white dark:bg-gray-800">
<h2 class="text-lg font-bold mb-4">设置</h2>
<!-- 在这里添加设置选项 -->
<div class="flex justify-end mt-4">
<button onclick="closeSettings()" class="px-4 py-2 bg-gray-300 dark:bg-gray-700 rounded hover:bg-gray-400 dark:hover:bg-gray-600 focus:outline-none">关闭</button>
</div>
</div>
</div>
<script src="./md.js?version=1736211336"></script>
<script>
// 初始化主题和音量
document.addEventListener('DOMContentLoaded', function() {
initTheme();
initVolume();
});
</script>
</body>
</html>

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,78 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width">
<title>M3U to JSON Converter</title>
<link rel="stylesheet" type="text/css" href="./main.css?version=1736211336">
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-Z09NC1K7ZW"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments)};
gtag('js', new Date());
gtag('config', 'G-Z09NC1K7ZW');
</script>
<!-- umami -->
<script async defer src="https://umami.hanxi.cc/script.js" data-website-id="7bfb0890-4115-4260-8892-b391513e7e99"></script>
<!--
<script src="https://unpkg.com/vconsole@latest/dist/vconsole.min.js"></script>
<script>
// VConsole 默认会挂载到 `window.VConsole` 上
var vConsole = new window.VConsole();
</script>
-->
<script>
function handleFileSelect(evt) {
var file = evt.target.files[0];
if (file) {
var reader = new FileReader();
reader.onload = function(e) {
document.getElementById('m3u-input').value = e.target.result;
};
reader.readAsText(file);
} else {
alert('无法加载文件');
}
}
function convertToJSON() {
var m3uContent = document.getElementById('m3u-input').value;
var lines = m3uContent.split('\n');
console.log(lines);
var musicsArray = [];
var currentName = '';
lines.forEach(function(line) {
line = line.trim();
if (line.startsWith('#EXTINF:')) {
currentName = line.replace(/.*,/g, '');
} else if (line.startsWith('http') && currentName !== '') {
musicsArray.push({"name": currentName, "type": "radio", "url": line});
currentName = ''; // Reset the name for the next entry
}
});
var output = [{
"name": "m3u电台",
"musics": musicsArray
}];
document.getElementById('json-output').value = JSON.stringify(output, null, 2);
}
</script>
</head>
<body>
<h1>M3U to JSON Converter</h1>
<input type="file" id="file-input" accept=".m3u" onchange="handleFileSelect(event)"/><br>
<textarea id="m3u-input" rows="10" cols="50" placeholder="粘贴m3u内容或上传文件..."></textarea><br>
<button onclick="convertToJSON()">转换</button><br>
<textarea id="json-output" rows="10" cols="50" placeholder="转换后的JSON..."></textarea>
</body>
<footer>
<p>Powered by <a href="https://xdocs.hanxi.cc" target="_blank">XiaoMusic</a></p>
</footer>
</html>

View File

@@ -0,0 +1,358 @@
body {
font-family: Arial, sans-serif;
background-color: #f0f0f0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
margin: 0;
padding: 0;
}
.index_page {
height: 100vh;
}
.player {
background-color: #ffffff;
padding: 20px;
border-radius: 12px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
text-align: center;
max-width: 360px;
position: relative;
overflow: hidden;
}
h1 {
font-size: 28px;
margin-bottom: 15px;
color: #333;
display: flex;
justify-content: center;
align-items: center;
}
h1 a {
margin-left: 10px;
font-size: 14px;
color: #007bff;
text-decoration: none;
}
h1 a:hover {
text-decoration: underline;
}
.new-badge {
background-color: #ff4757;
color: white;
border-radius: 12px;
padding: 2px 6px;
font-size: 12px;
margin-left: 5px;
display: none;
width: fit-content;
}
label {
font-size: 14px;
color: #555;
margin: 5px 0;
display: block;
text-align: left;
}
select,
input[type="range"],
input[type="text"],
input[type="password"],
input[type="number"] {
padding: 10px;
border: 1px solid #cccccc;
border-radius: 6px;
margin-bottom: 12px;
font-size: 14px;
transition: border 0.2s ease;
box-sizing: border-box
}
select:focus,
input[type="text"]:focus {
border-color: #007bff;
outline: none;
}
select {
overflow: hidden;
}
button {
background-color: #007bff;
color: white;
border: none;
border-radius: 6px;
padding: 10px 15px;
cursor: pointer;
margin: 5px;
font-size: 16px;
transition: background-color 0.3s;
position: relative; /* 为tooltip绝对定位做准备 */
}
button:hover {
background-color: #0056b3;
}
.tooltip {
visibility: hidden;
background-color: #555;
color: #fff;
text-align: center;
border-radius: 6px;
padding: 5px;
position: absolute;
z-index: 1;
bottom: 150%; /* 控制tooltip相对按钮的位置 */
left: 50%;
margin-left: -50px; /* 调整位置以居中显示 Tooltip */
width: 80px; /* 设置固定宽度以保证足够的显示空间 */
white-space: nowrap; /* 防止换行 */
opacity: 0;
transition: opacity 0.3s;
}
button:hover .tooltip,.option-inline:hover .tooltip,.control-button:hover .tooltip {
visibility: visible;
opacity: 1;
}
.option-inline{
display: flex;
margin-left: auto;
position: relative;
align-items: center;
}
.option-inline:hover .tooltip {
/* 位置调整到左边 */
left: -50px; /* 调整位置以居中显示 Tooltip */
bottom: 0;
}
.control-button{
position: relative; /* 为tooltip绝对定位做准备 */
}
.progress {
width: 90%;
height: 6px;
background: #e0e0e0;
border-radius: 6px;
margin: 15px 0;
cursor: pointer;
}
progress::-webkit-progress-bar {
background: #e0e0e0;
}
progress::-moz-progress-bar,
progress::-webkit-progress-value {
background: #007bff;
}
.current-song {
color: #333;
margin: 10px 0;
font-weight: bold;
text-align: center;
}
.component {
display: none;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: #ffffff;
padding: 5px 15px;
border-radius: 12px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
z-index: 100;
width: 300px;
}
.component input {
width: 90%;
}
.component-button-group {
display: flex;
justify-content: space-between;
}
.component-button-one {
display: flex;
justify-content: center;
}
#warning-component p span {
color: #007bff;
}
.button-group {
display: flex;
justify-content: center;
margin: 5px 0;
}
.player-controls {
display: flex;
justify-content: space-around;
align-items: center;
margin-top: 20px;
margin-bottom: 20px;
}
.play {
font-size: 48px;
}
.footer {
position: absolute;
bottom: 20px;
font-size: 14px;
color: #555;
user-select: none;
}
.timer-tooltip {
bottom: 50%;
visibility: visible;
opacity: 1;
}
.favorite.favorite-active .material-icons {
color: #ff6347;
}
#audio {
width: 100%;
display: none;
}
.qrcode {
width: 100%;
max-width: 400px;
height: auto;
}
.login-tips {
color: red;
font-size: 12px;
margin-left: 10px;
}
.login-tips a {
color: rgb(9, 105, 218);
text-decoration: underline;
}
/* setting.html */
.rows {
display: flex;
flex-direction: column;
justify-content: center;
}
.rows a {
color: rgb(9, 105, 218);
text-decoration: none;
}
.rows a:hover {
color: rgb(9, 95, 198);
text-decoration: underline;
}
textarea {
margin-left: 5%;
margin-right: 5%;
margin-top: 10px;
margin-bottom: 10px;
width: 90%;
/* max-width: 400px; */
height: 200px;
}
.custom-checkbox {
display: inline-block;
margin: 10px;
width: 20px;
height: 20px;
vertical-align: middle; /* 确保与标签垂直居中对齐 */
}
.checkbox-label {
display: inline-block;
width: 180px;
background-color: #fff;
border: 0px solid #ccc;
border-radius: 3px;
position: relative;
cursor: pointer;
vertical-align: middle; /* 确保与复选框垂直居中对齐 */
margin-left: 1px; /* 给复选框和标签之间一些距离,如果需要的话 */
padding: 5px 10px;
}
.debug {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
@media screen and (max-width: 440px) {
.player{
width: 90%;
}
.footer {
position: relative;
}
}
.mini-button {
padding: 0px 0px;
margin: 0px;
font-size: 14px;
margin-left: auto;
}
.playlist-selector,
.device-selector,
.version-selector,
.song-selector {
width: 300px;
}
.mode-controls {
display: flex;
justify-content: space-around;
align-items: center;
padding: 10px 0;
border-top: 1px solid #ddd;
color: #555;
}
.icon-item {
text-align: center;
}
.icon-item p {
font-size: 12px;
margin: 5px 0 0;
}
.disabled {
color: #ccc;
pointer-events: none;
}
span,p {
cursor: pointer;
user-select: none;
}
.changelog-button {
padding: 0px 0px;
margin: 0px;
font-size: 14px;
margin-left: auto;
text-decoration: none;
}
.setting-label {
display: flex;
align-items: center;
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

View File

@@ -0,0 +1,658 @@
<!DOCTYPE html>
<html>
<head>
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width">
<title>小爱音箱操控面板</title>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<script src="./jquery-3.7.1.min.js?version=1736211336"></script>
<script src="./setting.js?version=1736211336"></script>
<script src="./tailwind.js"></script>
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-Z09NC1K7ZW"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() { dataLayer.push(arguments) };
gtag('js', new Date());
gtag('config', 'G-Z09NC1K7ZW');
</script>
<!-- umami -->
<script async defer src="https://umami.hanxi.cc/script.js"
data-website-id="7bfb0890-4115-4260-8892-b391513e7e99"></script>
<style>
/* 只保留一些必要的自定义样式 */
.custom-checkbox {
width: 20px;
height: 20px;
vertical-align: middle;
}
.login-tips {
color: red;
font-size: 12px;
}
.login-tips a {
color: rgb(9, 105, 218);
text-decoration: underline;
}
/* 添加平滑滚动 */
html {
scroll-behavior: smooth;
}
/* 修复toast样式 */
.toast {
position: fixed;
top: 1rem;
left: 50%;
transform: translateX(-50%);
z-index: 50;
padding: 0.75rem 1.5rem;
border-radius: 0.375rem;
transition: all 0.3s ease;
}
</style>
</head>
<body class="bg-gray-50 min-h-screen">
<div id="toast" class="toast bg-green-500 text-white hidden">
<span id="toast-message"></span>
</div>
<nav class="bg-white border-b top-0 z-50">
<div class="container mx-auto px-4 py-3">
<div class="flex justify-between items-center">
<h1 class="text-xl font-bold text-gray-900">
小爱音箱设置面板
<a id="version" href="https://xdocs.hanxi.cc/issues/changelog.html"
class="text-sm text-blue-600 hover:text-blue-800">
(版本未知)
</a>
</h1>
<button onclick="location.href='/static/default/index.html';"
class="px-4 py-2 bg-white border border-gray-300 text-gray-700 rounded-md hover:bg-gray-50">
返回首页
</button>
</div>
</div>
</nav>
<!-- 主要内容区 -->
<div class="container mx-auto px-4 py-6">
<!-- 设置内容区 - 改进移动端布局 -->
<div class="flex flex-col lg:flex-row gap-6">
<!-- 左侧导航 - 移动端变为水平滚动 -->
<div class="lg:w-72 flex-shrink-0">
<nav
class="lg:sticky lg:top-20 overflow-x-auto lg:overflow-x-visible flex lg:flex-col gap-1 pb-2 lg:pb-0 bg-white rounded-lg border p-2"
id="settings-nav">
<a href="#devices"
class="nav-item whitespace-nowrap px-4 py-2 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded-md flex-shrink-0 lg:flex-shrink">
设备选择
</a>
<a href="#account_section"
class="nav-item whitespace-nowrap px-4 py-2 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded-md flex-shrink-0 lg:flex-shrink">
账号设置
</a>
<a href="#music"
class="nav-item whitespace-nowrap px-4 py-2 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded-md flex-shrink-0 lg:flex-shrink">
音乐设置
</a>
<a href="#playback"
class="nav-item whitespace-nowrap px-4 py-2 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded-md flex-shrink-0 lg:flex-shrink">
播放控制
</a>
<a href="#playlist"
class="nav-item whitespace-nowrap px-4 py-2 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded-md flex-shrink-0 lg:flex-shrink">
歌单管理
</a>
<a href="#advanced"
class="nav-item whitespace-nowrap px-4 py-2 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded-md flex-shrink-0 lg:flex-shrink">
高级设置
</a>
</nav>
</div>
<!-- 右侧设置内容 -->
<div class="flex-1 space-y-6" id="setting">
<!-- 设备选择部分 -->
<section id="devices" class="setting-section bg-white rounded-lg border hover:shadow-md transition-shadow">
<div class="p-4 sm:p-6">
<h2 class="text-lg font-medium text-gray-900 mb-4 flex items-center">
<span class="material-icons mr-2 text-gray-500">devices</span>
设备选择
</h2>
<div class="space-y-4">
<div class="mb-4">
<label class="block text-sm font-medium text-gray-700">
勾选设备 (至少选择一个)
</label>
<div id="mi_did" class="mt-2"></div>
</div>
</div>
</div>
</section>
<!-- 账号设置部分 -->
<section id="account_section" class="setting-section bg-white rounded-lg shadow">
<div class="p-4 sm:p-6">
<h2 class="text-lg font-medium text-gray-900 mb-4">账号设置</h2>
<div class="grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-4 sm:gap-6">
<div class="space-y-4">
<div class="mb-4">
<label for="account" class="block text-sm font-medium text-gray-700">
小米账号
<span class="text-red-500">*</span>
</label>
<input id="account" type="text" class="mt-1 block w-full rounded-md border border-gray-300 bg-white px-4 py-2.5 text-gray-900 placeholder:text-gray-500 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 hover:border-gray-400" value="" placeholder="填写小米登录账号" />
</div>
<div class="mb-4">
<label for="password" class="block text-sm font-medium text-gray-700">
小米密码
<span class="text-red-500">*</span>
</label>
<input id="password" type="password" class="mt-1 block w-full rounded-md border border-gray-300 bg-white px-4 py-2.5 text-gray-900 placeholder:text-gray-500 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 hover:border-gray-400" placeholder="填写小米登录密码" />
</div>
</div>
<div class="space-y-4">
<div class="mb-4">
<label for="hostname" class="block text-sm font-medium text-gray-700">
NAS的IP或域名
<span class="text-red-500">*</span>
<button id="auto-hostname"
class="ml-2 inline-flex items-center text-sm text-blue-600 hover:text-blue-800">
<span class="material-icons text-sm">edit</span>
自动填写
</button>
</label>
<input id="hostname" type="text" class="mt-1 block w-full rounded-md border border-gray-300 bg-white px-4 py-2.5 text-gray-900 placeholder:text-gray-500 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 hover:border-gray-400" />
</div>
<div class="mb-4">
<label for="public_port" class="block text-sm font-medium text-gray-700">
本地端口
<span class="text-red-500">*</span>
<button id="auto-port"
class="ml-2 inline-flex items-center text-sm text-blue-600 hover:text-blue-800">
<span class="material-icons text-sm">edit</span>
自动填写
</button>
</label>
<input id="public_port" type="number" value="0" class="mt-1 block w-full rounded-md border border-gray-300 bg-white px-4 py-2.5 text-gray-900 placeholder:text-gray-500 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 hover:border-gray-400" />
</div>
</div>
</div>
</div>
</section>
<!-- 音乐设置部分 -->
<section id="music" class="setting-section bg-white rounded-lg shadow">
<div class="p-4 sm:p-6">
<h2 class="text-lg font-medium text-gray-900 mb-4">音乐设置</h2>
<div class="grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-4 sm:gap-6">
<div class="space-y-4">
<div class="mb-4">
<label for="music_path" class="block text-sm font-medium text-gray-700">
音乐目录
</label>
<input id="music_path" type="text" value="music" class="mt-1 block w-full rounded-md border border-gray-300 bg-white px-4 py-2.5 text-gray-900 placeholder:text-gray-500 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 hover:border-gray-400" />
</div>
<div class="mb-4">
<label for="download_path" class="block text-sm font-medium text-gray-700">
音乐下载目录
<span class="text-gray-500 text-xs">(必须是music的子目录)</span>
</label>
<input id="download_path" type="text" value="music/download" class="mt-1 block w-full rounded-md border border-gray-300 bg-white px-4 py-2.5 text-gray-900 placeholder:text-gray-500 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 hover:border-gray-400" />
</div>
<div class="mb-4">
<label for="temp_path" class="block text-sm font-medium text-gray-700">
临时文件目录
</label>
<input id="temp_path" type="text" value="music/tmp" class="mt-1 block w-full rounded-md border border-gray-300 bg-white px-4 py-2.5 text-gray-900 placeholder:text-gray-500 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 hover:border-gray-400" />
</div>
</div>
<div class="space-y-4">
<div class="mb-4">
<label for="exclude_dirs" class="block text-sm font-medium text-gray-700">
忽略目录
<span class="text-gray-500 text-xs">(逗号分割)</span>
</label>
<input id="exclude_dirs" type="text" value="@eaDir,tmp" class="mt-1 block w-full rounded-md border border-gray-300 bg-white px-4 py-2.5 text-gray-900 placeholder:text-gray-500 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 hover:border-gray-400" />
</div>
<div class="mb-4">
<label for="music_path_depth" class="block text-sm font-medium text-gray-700">
目录深度
</label>
<input id="music_path_depth" type="number" value="10" class="mt-1 block w-full rounded-md border border-gray-300 bg-white px-4 py-2.5 text-gray-900 placeholder:text-gray-500 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 hover:border-gray-400" />
</div>
<div class="mb-4">
<label for="ffmpeg_location" class="block text-sm font-medium text-gray-700">
ffmpeg路径
</label>
<input id="ffmpeg_location" type="text" value="./ffmpeg/bin" class="mt-1 block w-full rounded-md border border-gray-300 bg-white px-4 py-2.5 text-gray-900 placeholder:text-gray-500 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 hover:border-gray-400" />
</div>
</div>
</div>
</div>
</section>
<!-- 播放控制部分 -->
<section id="playback" class="setting-section bg-white rounded-lg shadow">
<div class="p-4 sm:p-6">
<h2 class="text-lg font-medium text-gray-900 mb-4">播放控制</h2>
<!-- 命令词设置 -->
<div class="mb-8">
<h3 class="text-md font-medium text-gray-800 mb-4">命令词设置</h3>
<div class="grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-4 sm:gap-6">
<div class="mb-4">
<label for="keywords_playlocal" class="block text-sm font-medium text-gray-700">
播放本地歌曲口令
</label>
<input id="keywords_playlocal" type="text" value="播放本地歌曲,本地播放歌曲" class="mt-1 block w-full rounded-md border border-gray-300 bg-white px-4 py-2.5 text-gray-900 placeholder:text-gray-500 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 hover:border-gray-400" />
</div>
<div class="mb-4">
<label for="keywords_play" class="block text-sm font-medium text-gray-700">
播放歌曲口令
</label>
<input id="keywords_play" type="text" value="播放歌曲,放歌曲" class="mt-1 block w-full rounded-md border border-gray-300 bg-white px-4 py-2.5 text-gray-900 placeholder:text-gray-500 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 hover:border-gray-400" />
</div>
<div class="mb-4">
<label for="keywords_stop" class="block text-sm font-medium text-gray-700">
停止口令
</label>
<input id="keywords_stop" type="text" value="关机,暂停,停止,停止播放" class="mt-1 block w-full rounded-md border border-gray-300 bg-white px-4 py-2.5 text-gray-900 placeholder:text-gray-500 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 hover:border-gray-400" />
</div>
<div class="mb-4">
<label for="delay_sec" class="block text-sm font-medium text-gray-700">
下一首歌延迟播放秒数
</label>
<input id="delay_sec" type="number" value="3" class="mt-1 block w-full rounded-md border border-gray-300 bg-white px-4 py-2.5 text-gray-900 placeholder:text-gray-500 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 hover:border-gray-400" />
</div>
</div>
</div>
<!-- 提示音设置 -->
<div>
<h3 class="text-md font-medium text-gray-800 mb-4">提示音设置</h3>
<div class="grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-4 sm:gap-6">
<div class="mb-4">
<label for="stop_tts_msg" class="block text-sm font-medium text-gray-700">
停止提示音
</label>
<input id="stop_tts_msg" type="text" value="收到,再见" class="mt-1 block w-full rounded-md border border-gray-300 bg-white px-4 py-2.5 text-gray-900 placeholder:text-gray-500 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 hover:border-gray-400" />
</div>
<div class="mb-4">
<label for="play_type_one_tts_msg" class="block text-sm font-medium text-gray-700">
单曲循环提示音
</label>
<input id="play_type_one_tts_msg" type="text" value="已经设置为单曲循环" class="mt-1 block w-full rounded-md border border-gray-300 bg-white px-4 py-2.5 text-gray-900 placeholder:text-gray-500 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 hover:border-gray-400" />
</div>
<div class="mb-4">
<label for="play_type_all_tts_msg" class="block text-sm font-medium text-gray-700">
全部循环提示音
</label>
<input id="play_type_all_tts_msg" type="text" value="已经设置为全部循环" class="mt-1 block w-full rounded-md border border-gray-300 bg-white px-4 py-2.5 text-gray-900 placeholder:text-gray-500 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 hover:border-gray-400" />
</div>
<div class="mb-4">
<label for="play_type_rnd_tts_msg" class="block text-sm font-medium text-gray-700">
随机播放提示音
</label>
<input id="play_type_rnd_tts_msg" type="text" value="已经设置为随机播放" class="mt-1 block w-full rounded-md border border-gray-300 bg-white px-4 py-2.5 text-gray-900 placeholder:text-gray-500 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 hover:border-gray-400" />
</div>
<div class="mb-4">
<label for="play_type_sin_tts_msg" class="block text-sm font-medium text-gray-700">
单曲播放提示音
</label>
<input id="play_type_sin_tts_msg" type="text" value="已经设置为单曲播放" class="mt-1 block w-full rounded-md border border-gray-300 bg-white px-4 py-2.5 text-gray-900 placeholder:text-gray-500 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 hover:border-gray-400" />
</div>
<div class="mb-4">
<label for="play_type_seq_tts_msg" class="block text-sm font-medium text-gray-700">
顺序播放提示音
</label>
<input id="play_type_seq_tts_msg" type="text" value="已经设置为顺序播放" class="mt-1 block w-full rounded-md border border-gray-300 bg-white px-4 py-2.5 text-gray-900 placeholder:text-gray-500 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 hover:border-gray-400" />
</div>
</div>
</div>
</div>
</section>
<!-- 歌单管理部分 -->
<section id="playlist" class="setting-section bg-white rounded-lg shadow">
<div class="p-4 sm:p-6">
<h2 class="text-lg font-medium text-gray-900 mb-4">歌单管理</h2>
<!-- 歌单设置 -->
<div class="mb-8">
<div class="mb-6">
<div class="flex items-center justify-between mb-2">
<label for="music_list_url" class="block text-sm font-medium text-gray-700">
歌单地址
</label>
<button id="get_music_list"
class="inline-flex items-center px-3 py-1 text-sm bg-blue-50 text-blue-700 rounded-md hover:bg-blue-100">
<span class="material-icons text-sm mr-1">sync_alt</span>
获取歌单
</button>
</div>
<input id="music_list_url" type="text"
value="https://gist.githubusercontent.com/hanxi/dda82d964a28f8110f8fba81c3ff8314/raw/example.json"
class="mt-1 block w-full rounded-md border border-gray-300 bg-white px-4 py-2.5 text-gray-900 placeholder:text-gray-500 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 hover:border-gray-400" />
</div>
<div class="mb-4">
<div class="flex items-center gap-2 mb-2">
<label for="music_list_json" class="block text-sm font-medium text-gray-700">
歌单内容
</label>
<a href="https://github.com/hanxi/xiaomusic/issues/78" target="_blank"
class="text-sm text-blue-600 hover:text-blue-800">
格式文档
</a>
</div>
<textarea id="music_list_json" class="mt-1 block w-full h-48 rounded-md border border-gray-300 bg-white px-4 py-2.5 text-gray-900 placeholder:text-gray-500 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 hover:border-gray-400"
placeholder=''></textarea>
</div>
</div>
<!-- 定时任务设置 -->
<div>
<div class="mb-4">
<div class="flex items-center gap-2 mb-2">
<label for="crontab_json" class="block text-sm font-medium text-gray-700">
定时任务配置
</label>
<a href="https://github.com/hanxi/xiaomusic/issues/182" target="_blank"
class="text-sm text-blue-600 hover:text-blue-800">
格式文档
</a>
</div>
<textarea id="crontab_json" class="mt-1 block w-full h-48 rounded-md border border-gray-300 bg-white px-4 py-2.5 text-gray-900 placeholder:text-gray-500 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 hover:border-gray-400"
placeholder=''></textarea>
</div>
</div>
</div>
</section>
<!-- 高级设置部分 -->
<section id="advanced" class="setting-section bg-white rounded-lg shadow">
<div class="p-4 sm:p-6">
<h2 class="text-lg font-medium text-gray-900 mb-4">高级设置</h2>
<!-- 功能开关 -->
<div class="mb-8">
<h3 class="text-md font-medium text-gray-800 mb-4">功能开关</h3>
<div class="grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-4 sm:gap-6">
<div class="mb-4">
<label for="verbose" class="block text-sm font-medium text-gray-700">
调试日志
</label>
<select id="verbose"
class="mt-1 block w-full rounded-md border border-gray-300 bg-white px-4 py-2.5 text-gray-900 placeholder:text-gray-500 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 hover:border-gray-400 bg-white py-2 px-3 text-gray-900 cursor-pointer hover:bg-gray-50">
<option value="true">开启</option>
<option value="false" selected>关闭</option>
</select>
</div>
<div class="mb-4">
<label for="disable_download" class="block text-sm font-medium text-gray-700">
下载功能
</label>
<select id="disable_download"
class="mt-1 block w-full rounded-md border border-gray-300 bg-white px-4 py-2.5 text-gray-900 placeholder:text-gray-500 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 hover:border-gray-400 bg-white py-2 px-3 text-gray-900 cursor-pointer hover:bg-gray-50">
<option value="true">关闭</option>
<option value="false" selected>开启</option>
</select>
</div>
<div class="mb-4">
<label for="enable_fuzzy_match" class="block text-sm font-medium text-gray-700">
模糊搜索
</label>
<select id="enable_fuzzy_match"
class="mt-1 block w-full rounded-md border border-gray-300 bg-white px-4 py-2.5 text-gray-900 placeholder:text-gray-500 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 hover:border-gray-400 bg-white py-2 px-3 text-gray-900 cursor-pointer hover:bg-gray-50">
<option value="true" selected>开启</option>
<option value="false">关闭</option>
</select>
</div>
<div class="mb-4">
<label for="fuzzy_match_cutoff" class="block text-sm font-medium text-gray-700">
模糊匹配阈值(0.1~0.9)
</label>
<input id="fuzzy_match_cutoff" type="number" value="0.6" step="0.1" min="0.1" max="0.9" class="mt-1 block w-full rounded-md border border-gray-300 bg-white px-4 py-2.5 text-gray-900 placeholder:text-gray-500 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 hover:border-gray-400" />
</div>
</div>
</div>
<!-- 安全设置 -->
<div class="mb-8">
<h3 class="text-md font-medium text-gray-800 mb-4">安全设置</h3>
<div class="grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-4 sm:gap-6">
<div class="mb-4">
<label for="disable_httpauth" class="block text-sm font-medium text-gray-700">
控制台密码验证
</label>
<select id="disable_httpauth"
class="mt-1 block w-full rounded-md border border-gray-300 bg-white px-4 py-2.5 text-gray-900 placeholder:text-gray-500 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 hover:border-gray-400 bg-white py-2 px-3 text-gray-900 cursor-pointer hover:bg-gray-50">
<option value="true" selected>关闭</option>
<option value="false">开启</option>
</select>
</div>
<div class="mb-4">
<label for="httpauth_username" class="block text-sm font-medium text-gray-700">
控制台账户
</label>
<input id="httpauth_username" type="text" class="mt-1 block w-full rounded-md border border-gray-300 bg-white px-4 py-2.5 text-gray-900 placeholder:text-gray-500 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 hover:border-gray-400" />
</div>
<div class="mb-4">
<label for="httpauth_password" class="block text-sm font-medium text-gray-700">
控制台密码
</label>
<input id="httpauth_password" type="password" class="mt-1 block w-full rounded-md border border-gray-300 bg-white px-4 py-2.5 text-gray-900 placeholder:text-gray-500 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 hover:border-gray-400" />
</div>
</div>
</div>
<!-- 文件上传 -->
<div>
<h3 class="text-md font-medium text-gray-800 mb-4">文件上传</h3>
<div class="mb-4">
<div class="flex items-center gap-2 mb-2">
<label for="yt_dlp_cookies_file" class="text-sm font-medium text-gray-700">
上传yt_dlp_cookies.txt文件
</label>
<a href="https://github.com/hanxi/xiaomusic/issues/210" target="_blank"
class="text-sm text-blue-600 hover:text-blue-800">
文档
</a>
</div>
<div class="flex gap-2">
<input id="yt_dlp_cookies_file" name="file" type="file" class="block w-full text-sm text-gray-500
file:mr-4 file:py-2 file:px-4
file:rounded-md file:border-0
file:text-sm file:font-semibold
file:bg-blue-50 file:text-blue-700
hover:file:bg-blue-100" />
<button id="upload_yt_dlp_cookie"
class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
上传
</button>
</div>
</div>
</div>
<div class="mb-8">
<h3 class="text-md font-medium text-gray-800 mb-4">下载设置</h3>
<div class="grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-4 sm:gap-6">
<div class="mb-4">
<label for="search_prefix" class="block text-sm font-medium text-gray-700">
歌曲下载方式
</label>
<select id="search_prefix"
class="mt-1 block w-full rounded-md border border-gray-300 bg-white px-4 py-2.5 text-gray-900 placeholder:text-gray-500 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 hover:border-gray-400 bg-white py-2 px-3 text-gray-900 cursor-pointer hover:bg-gray-50">
<option value="bilisearch:">bilisearch:</option>
<option value="ytsearch:">ytsearch:</option>
</select>
</div>
<div class="mb-4">
<label for="proxy" class="block text-sm font-medium text-gray-700">
代理设置
<span class="text-gray-500 text-xs">(ytsearch需要)</span>
</label>
<input id="proxy" type="text" placeholder="http://192.168.2.5:8080" class="mt-1 block w-full rounded-md border border-gray-300 bg-white px-4 py-2.5 text-gray-900 placeholder:text-gray-500 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 hover:border-gray-400" />
</div>
</div>
</div>
<div class="mb-8">
<h3 class="text-md font-medium text-gray-800 mb-4">其他设置</h3>
<div class="grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-4 sm:gap-6">
<div class="mb-4">
<label for="enable_save_tag" class="block text-sm font-medium text-gray-700">
启用ID3标签写入文件
</label>
<select id="enable_save_tag"
class="mt-1 block w-full rounded-md border border-gray-300 bg-white px-4 py-2.5 text-gray-900 placeholder:text-gray-500 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 hover:border-gray-400 bg-white py-2 px-3 text-gray-900 cursor-pointer hover:bg-gray-50">
<option value="true">开启</option>
<option value="false" selected>关闭</option>
</select>
</div>
<div class="mb-4">
<label for="get_ask_by_mina" class="block text-sm font-medium text-gray-700">
特殊型号获取对话记录
</label>
<select id="get_ask_by_mina"
class="mt-1 block w-full rounded-md border border-gray-300 bg-white px-4 py-2.5 text-gray-900 placeholder:text-gray-500 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 hover:border-gray-400 bg-white py-2 px-3 text-gray-900 cursor-pointer hover:bg-gray-50">
<option value="true">开启</option>
<option value="false" selected>关闭</option>
</select>
</div>
</div>
</div>
</div>
</section>
<!-- 继续添加其他设置部分... -->
</div>
</div>
<!-- 底部按钮组 - 改进移动端显示 -->
<div class="fixed bottom-0 left-0 right-0 bg-white border-t">
<div class="container mx-auto px-4 py-3">
<!-- 所有按钮的容器 -->
<div class="flex flex-col sm:flex-row sm:justify-between gap-2">
<!-- 主要操作按钮 -->
<div class="flex flex-wrap justify-center gap-2">
<button
class="save-button px-4 py-2 bg-black text-white rounded-md hover:bg-gray-700 flex-1 sm:flex-none">
保存设置
</button>
<button id="refresh_music_tag"
class="px-4 py-2 bg-gray-300 border border-gray-300 text-black rounded-md hover:bg-gray-200 flex-1 sm:flex-none">
刷新tag
</button>
<button id="clear_cache"
class="px-4 py-2 bg-gray-300 border border-gray-300 text-black rounded-md hover:bg-gray-200 flex-1 sm:flex-none">
清空缓存
</button>
</div>
<!-- 工具按钮 -->
<div class="grid grid-cols-3 sm:flex sm:flex-wrap gap-2">
<a href="/docs" target="_blank" class="flex-1 sm:flex-none">
<button class="w-full px-4 py-2 bg-white border border-gray-300 text-gray-700 rounded-md hover:bg-gray-50">
<span class="hidden sm:inline">接口文档</span>
<span class="sm:hidden">文档</span>
</button>
</a>
<a href="./m3u.html" target="_blank" class="flex-1 sm:flex-none">
<button class="w-full px-4 py-2 bg-white border border-gray-300 text-gray-700 rounded-md hover:bg-gray-50">
<span class="hidden sm:inline">m3u转换</span>
<span class="sm:hidden">m3u</span>
</button>
</a>
<a href="./downloadtool.html" target="_blank" class="flex-1 sm:flex-none">
<button class="w-full px-4 py-2 bg-white border border-gray-300 text-gray-700 rounded-md hover:bg-gray-50">
<span class="hidden sm:inline">歌曲下载工具</span>
<span class="sm:hidden">下载</span>
</button>
</a>
<a href="./debug.html" target="_blank" class="flex-1 sm:flex-none">
<button class="w-full px-4 py-2 bg-white border border-gray-300 text-gray-700 rounded-md hover:bg-gray-50">
<span class="hidden sm:inline">调试工具</span>
<span class="sm:hidden">调试</span>
</button>
</a>
<a href="https://github.com/hanxi/xiaomusic" target="_blank" class="flex-1 sm:flex-none">
<button class="w-full px-4 py-2 bg-white border border-gray-300 text-gray-700 rounded-md hover:bg-gray-50">
GitHub
</button>
</a>
<a href="https://afdian.com/a/imhanxi" target="_blank" class="flex-1 sm:flex-none">
<button class="w-full px-4 py-2 bg-blue-500 border border-gray-300 text-white rounded-md hover:bg-blue-600">
<span class="hidden sm:inline">💰 爱发电</span>
<span class="sm:hidden">💰爱发电</span>
</button>
</a>
</div>
</div>
</div>
</div>
<!-- 二维码 -->
<div class="text-center mt-12 mb-24">
<div class="bg-white p-6 rounded-lg border inline-block">
<img class="qrcode mx-auto w-40 sm:w-64 h-40 sm:h-64" src="./qrcode.png" alt="请涵曦喝奶茶🧋">
<p class="mt-4 text-gray-600 font-medium">扫码请涵曦喝奶茶🧋</p>
</div>
<footer class="mt-6 text-sm sm:text-base text-gray-600">
<p>Powered by <a href="https://xdocs.hanxi.cc" target="_blank"
class="text-blue-600 hover:text-blue-800">XiaoMusic</a></p>
</footer>
</div>
</div>
<!-- 回到顶部按钮 -->
<button id="back-to-top" onclick="window.scrollTo({top: 0, behavior: 'smooth'})"
class="fixed bottom-24 right-6 w-10 h-10 flex items-center justify-center bg-white border border-gray-300 rounded-full shadow-lg text-gray-700 hover:bg-gray-50 transition-all duration-200 opacity-0 invisible">
<span class="material-icons text-xl">arrow_upward</span>
</button>
<!-- 添加必要的 JavaScript -->
<script>
// 保留导航高亮功能
const navItems = $('.nav-item');
const sections = $('.setting-section');
function highlightNav() {
const scrollPos = $(window).scrollTop();
sections.each(function () {
const top = $(this).offset().top - 100;
const bottom = top + $(this).outerHeight();
if (scrollPos >= top && scrollPos <= bottom) {
const id = $(this).attr('id');
navItems.removeClass('bg-gray-100 text-gray-900');
$(`a[href="#${id}"]`).addClass('bg-gray-100 text-gray-900');
}
});
// 控制回到顶部按钮的显示和隐藏
const backToTop = $('#back-to-top');
if (scrollPos > 300) {
backToTop.removeClass('opacity-0 invisible').addClass('opacity-100');
} else {
backToTop.removeClass('opacity-100').addClass('opacity-0 invisible');
}
}
$(window).on('scroll', highlightNav);
highlightNav();
</script>
</body>
</html>

View File

@@ -0,0 +1,219 @@
$(function () {
// 拉取版本
$.get("/getversion", function (data, status) {
console.log(data, status, data["version"]);
$("#version").text(`${data.version}`);
});
// 遍历所有的select元素默认选中只有1个选项的
const autoSelectOne = () => {
$('select').each(function () {
// 如果select元素仅有一个option子元素
if ($(this).children('option').length === 1) {
// 选中这个option
$(this).find('option').prop('selected', true);
}
});
};
function updateCheckbox(selector, mi_did, device_list, accountPassValid) {
// 清除现有的内容
$(selector).empty();
// 将 mi_did 字符串通过逗号分割转换为数组,以便于判断默认选中项
var selected_dids = mi_did.split(',');
//如果device_list为空则可能是未设置小米账号密码或者已设置密码但是没有过小米验证此处需要提示用户
if (device_list.length == 0) {
const loginTips = accountPassValid ? `<div class="login-tips">未发现可用的小爱设备,请检查账号密码是否输错,并关闭加速代理或在<a href="https://www.mi.com">小米官网</a>登陆过人脸或滑块验证。如仍未解决。请根据<a href="https://github.com/hanxi/xiaomusic/issues/99">FAQ</a>的内容解决问题。</div>` : `<div class="login-tips">未发现可用的小爱设备,请先在下面的输入框中设置小米的<b>账号、密码</b></div>`;
$(selector).append(loginTips);
return;
}
$.each(device_list, function (index, device) {
var did = device.miotDID;
var hardware = device.hardware;
var name = device.name;
// 创建复选框元素
var checkbox = $('<input>', {
type: 'checkbox',
id: did,
value: `${did}`,
class: 'custom-checkbox', // 添加样式类
// 如果mi_did中包含了该did则默认选中
checked: selected_dids.indexOf(did) !== -1
});
// 创建标签元素
var label = $('<label>', {
for: did,
class: 'checkbox-label', // 添加样式类
text: `${hardware} ${did}${name}` // 设定标签内容
});
// 将复选框和标签添加到目标选择器元素中
$(selector).append(checkbox).append(label);
});
}
function getSelectedDids(containerSelector) {
var selectedDids = [];
// 仅选择给定容器中选中的复选框
$(containerSelector + ' .custom-checkbox:checked').each(function () {
var did = this.value;
selectedDids.push(did);
});
return selectedDids.join(',');
}
// 拉取现有配置
$.get("/getsetting?need_device_list=true", function (data, status) {
console.log(data, status);
const accountPassValid = data.account && data.password;
updateCheckbox("#mi_did", data.mi_did, data.device_list, accountPassValid);
// 初始化显示
for (const key in data) {
const $element = $("#" + key);
if ($element.length) {
if (data[key] === true) {
$element.val('true');
} else if (data[key] === false) {
$element.val('false');
} else {
$element.val(data[key]);
}
}
}
autoSelectOne();
});
$(".save-button").on("click", () => {
var setting = $('#setting');
var inputs = setting.find('input, select, textarea');
var data = {};
inputs.each(function () {
var id = this.id;
if (id) {
data[id] = $(this).val();
}
});
var did_list = getSelectedDids("#mi_did");
data["mi_did"] = did_list;
console.log(data)
$.ajax({
type: "POST",
url: "/savesetting",
contentType: "application/json",
data: JSON.stringify(data),
success: (msg) => {
alert(msg);
location.reload();
},
error: (msg) => {
alert(msg);
}
});
});
$("#get_music_list").on("click", () => {
var music_list_url = $("#music_list_url").val();
console.log("music_list_url", music_list_url);
var data = {
url: music_list_url,
};
$.ajax({
type: "POST",
url: "/downloadjson",
contentType: "application/json",
data: JSON.stringify(data),
success: (res) => {
if (res.ret == "OK") {
$("#music_list_json").val(res.content);
} else {
console.log(res);
alert(res.ret);
}
},
error: (res) => {
console.log(res);
alert(res);
}
});
});
$("#refresh_music_tag").on("click", () => {
$.ajax({
type: "POST",
url: "/refreshmusictag",
contentType: "application/json",
success: (res) => {
console.log(res);
alert(res.ret);
},
error: (res) => {
console.log(res);
alert(res);
}
});
});
$("#upload_yt_dlp_cookie").on("click", () => {
var fileInput = document.getElementById('yt_dlp_cookies_file');
var file = fileInput.files[0]; // 获取文件对象
if (file) {
var formData = new FormData();
formData.append("file", file);
$.ajax({
url: "/uploadytdlpcookie",
type: "POST",
data: formData,
processData: false,
contentType: false,
success: function (res) {
console.log(res);
alert("上传成功");
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(res);
alert("上传失败");
}
});
} else {
alert("请选择一个文件");
}
});
$("#clear_cache").on("click", () => {
localStorage.clear();
});
$("#hostname").on("change", function () {
const hostname = $(this).val();
// 检查是否包含端口号1到5位数字
if (hostname.match(/:\d{1,5}$/)) {
alert("hostname禁止带端口号");
// 移除端口号
$(this).val(hostname.replace(/:\d{1,5}$/, ""));
}
});
$("#auto-hostname").on("click", () => {
const protocol = window.location.protocol;
const hostname = window.location.hostname;
const baseUrl = `${protocol}//${hostname}`;
console.log(baseUrl);
$("#hostname").val(baseUrl);
});
$("#auto-port").on("click", () => {
const port = window.location.port;
console.log(port);
$("#public_port").val(port);
});
});

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,21 @@
// 初始化主题
function initTheme() {
const theme = localStorage.getItem('theme');
if (theme === 'dark' || (!theme && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
document.documentElement.classList.add('dark');
}
}
// 切换深色/浅色主题
function toggleTheme() {
const html = document.documentElement;
const isDark = html.classList.contains('dark');
if (isDark) {
html.classList.remove('dark');
localStorage.setItem('theme', 'light');
} else {
html.classList.add('dark');
localStorage.setItem('theme', 'dark');
}
}

View File

@@ -20,7 +20,7 @@
</script>
<!-- umami -->
<script defer src="https://umami.hanxi.cc/script.js" data-website-id="7bfb0890-4115-4260-8892-b391513e7e99"></script>
<script async defer src="https://umami.hanxi.cc/script.js" data-website-id="7bfb0890-4115-4260-8892-b391513e7e99"></script>
</head>
<body>
<div id="app"></div>

View File

@@ -336,7 +336,7 @@ async def get_local_music_duration(filename, ffmpeg_location="./ffmpeg/bin"):
m = await loop.run_in_executor(None, mutagen.File, filename)
duration = m.info.length
except Exception as e:
log.error(f"Error getting local music {filename} duration: {e}")
log.warning(f"Error getting local music {filename} duration: {e}")
return duration
@@ -487,6 +487,11 @@ def convert_file_to_mp3(input_file: str, config) -> str:
log.info(f"File {out_file_path} already exists. Skipping convert_file_to_mp3.")
return relative_path
# 检查是否存在 loudnorm 参数
loudnorm_args = []
if config.loudnorm:
loudnorm_args = ["-af", config.loudnorm]
command = [
os.path.join(config.ffmpeg_location, "ffmpeg"),
"-i",
@@ -495,6 +500,7 @@ def convert_file_to_mp3(input_file: str, config) -> str:
"mp3",
"-vn",
"-y",
*loudnorm_args,
out_file_path,
]
@@ -643,14 +649,19 @@ def _save_picture(picture_data, save_root, file_path):
try:
_resize_save_image(picture_data, picture_path)
except Exception as e:
log.exception(f"Error _resize_save_image: {e}")
log.warning(f"Error _resize_save_image: {e}")
return picture_path
def _resize_save_image(image_bytes, save_path, max_size=300):
# 将 bytes 转换为 PIL Image 对象
image = Image.open(io.BytesIO(image_bytes))
image = image.convert("RGB")
image = None
try:
image = Image.open(io.BytesIO(image_bytes))
image = image.convert("RGB")
except Exception as e:
log.warning(f"Error _resize_save_image: {e}")
return
# 获取原始尺寸
original_width, original_height = image.size
@@ -673,8 +684,16 @@ def _resize_save_image(image_bytes, save_path, max_size=300):
def extract_audio_metadata(file_path, save_root):
audio = mutagen.File(file_path)
metadata = Metadata()
audio = None
try:
audio = mutagen.File(file_path)
except Exception as e:
log.warning(f"Error extract_audio_metadata file: {file_path} {e}")
if audio is None:
return asdict(metadata)
tags = audio.tags
if tags is None:
return asdict(metadata)
@@ -786,19 +805,25 @@ def set_music_tag_to_file(file_path, info):
def _set_mp3_tags(audio, info):
audio.tags = ID3()
audio["TIT2"] = TIT2(encoding=3, text=info.title)
audio["TPE1"] = TPE1(encoding=3, text=info.artist)
audio["TALB"] = TALB(encoding=3, text=info.album)
audio["TDRC"] = TDRC(encoding=3, text=info.year)
audio["TCON"] = TCON(encoding=3, text=info.genre)
# 使用 USLT 存储歌词
if info.lyrics:
audio["USLT"] = USLT(encoding=3, lang="eng", text=info.lyrics)
# 添加封面图片
if info.picture:
with open(info.picture, "rb") as img_file:
image_data = img_file.read()
audio["APIC"] = APIC(
encoding=3, mime="image/jpeg", type=3, desc="Cover", data=image_data
)
audio.save() # 保存修改
def _set_flac_tags(audio, info):
@@ -816,11 +841,11 @@ def _set_flac_tags(audio, info):
def _set_mp4_tags(audio, info):
audio["\xa9nam"] = info.title
audio["\xa9ART"] = info.artist
audio["\xa9alb"] = info.album
audio["\xa9day"] = info.year
audio["\xa9gen"] = info.genre
audio["nam"] = info.title
audio["ART"] = info.artist
audio["alb"] = info.album
audio["day"] = info.year
audio["gen"] = info.genre
if info.picture:
with open(info.picture, "rb") as img_file:
image_data = img_file.read()
@@ -883,6 +908,9 @@ async def download_playlist(config, url, dirname):
if config.enable_yt_dlp_cookies:
sbp_args += ("--cookies", f"{config.yt_dlp_cookies_path}")
if config.loudnorm:
sbp_args += ("--postprocessor-args", f"-af {config.loudnorm}")
sbp_args += (url,)
cmd = " ".join(sbp_args)
@@ -918,6 +946,9 @@ async def download_one_music(config, url, name=""):
if config.enable_yt_dlp_cookies:
sbp_args += ("--cookies", f"{config.yt_dlp_cookies_path}")
if config.loudnorm:
sbp_args += ("--postprocessor-args", f"-af {config.loudnorm}")
sbp_args += (url,)
cmd = " ".join(sbp_args)
@@ -952,7 +983,7 @@ def remove_common_prefix(directory):
log.info(f'Common prefix identified: "{common_prefix}"')
pattern = re.compile(r"(\d+)[\t  ]*\1")
pattern = re.compile(r"^[pP]?(\d+)\s+\d*(.+?)\.(.*$)")
for filename in files:
if filename == common_prefix:
continue
@@ -960,9 +991,12 @@ def remove_common_prefix(directory):
if filename.startswith(common_prefix):
# 构造新的文件名
new_filename = filename[len(common_prefix) :]
match = pattern.match(new_filename)
match = pattern.search(new_filename.strip())
if match:
new_filename = match.group(1) + new_filename[match.end() :]
num = match.group(1)
name = match.group(2).replace(".", " ").strip()
suffix = match.group(3)
new_filename = f"{num}.{name}.{suffix}"
# 生成完整的文件路径
old_file_path = os.path.join(directory, filename)
new_file_path = os.path.join(directory, new_filename)
@@ -1047,7 +1081,7 @@ async def update_version(version: str, lite: bool = True):
log.warning(f"update_version failed: {arch}")
return arch
# https://github.com/hanxi/xiaomusic/releases/download/main/app-amd64-lite.tar.gz
url = f"https://github.hanxi.cc/proxy/hanxi/xiaomusic/releases/download/{version}/app-{arch}{lite_tag}.tar.gz"
url = f"https://gproxy.hanxi.cc/proxy/hanxi/xiaomusic/releases/download/{version}/app-{arch}{lite_tag}.tar.gz"
target_directory = "/app"
return await download_and_extract(url, target_directory)

View File

@@ -12,7 +12,6 @@ import urllib.parse
from collections import OrderedDict
from dataclasses import asdict
from logging.handlers import RotatingFileHandler
from pathlib import Path
from aiohttp import ClientSession, ClientTimeout
from miservice import MiAccount, MiIOService, MiNAService, miio_command
@@ -64,7 +63,8 @@ class XiaoMusic:
def __init__(self, config: Config):
self.config = config
self.mi_token_home = Path.home() / ".mi.token"
self.mi_token_home = os.path.join(self.config.conf_path, ".mi.token")
self.session = None
self.last_timestamp = {} # key为 did. timestamp last call mi speaker
self.last_record = None
self.cookie_jar = None
@@ -76,6 +76,7 @@ class XiaoMusic:
self.all_music = {}
self._all_radio = {} # 电台列表
self.music_list = {} # 播放列表 key 为目录名, value 为 play_list
self.default_music_list_names = [] # 非自定义个歌单
self.devices = {} # key 为 did
self.running_task = []
self.all_music_tags = {} # 歌曲额外信息
@@ -177,6 +178,11 @@ class XiaoMusic:
async def poll_latest_ask(self):
async with ClientSession() as session:
while True:
if not self.config.enable_pull_ask:
self.log.debug("Listening new message disabled")
await asyncio.sleep(5)
continue
self.log.debug(
f"Listening new message, timestamp: {self.last_timestamp}"
)
@@ -213,6 +219,7 @@ class XiaoMusic:
break
async def init_all_data(self, session):
self.mi_token_home = os.path.join(self.config.conf_path, ".mi.token")
await self.login_miboy(session)
await self.try_update_device_id()
cookie_jar = self.get_cookie()
@@ -253,6 +260,7 @@ class XiaoMusic:
device.device_id = device_id
device.hardware = hardware
device.name = name
device.play_type = PLAY_TYPE_RND
devices[did] = device
self.config.devices = devices
self.log.info(f"选中的设备: {devices}")
@@ -265,7 +273,7 @@ class XiaoMusic:
return cookie_jar
if not os.path.exists(self.mi_token_home):
self.log.error(f"{self.mi_token_home} file not exist")
self.log.warning(f"{self.mi_token_home} file not exist")
return None
with open(self.mi_token_home, encoding="utf-8") as f:
@@ -325,7 +333,10 @@ class XiaoMusic:
# 检查响应状态码
if r.status != 200:
self.log.error(f"Request failed with status {r.status}")
self.log.warning(f"Request failed with status {r.status}")
# fix #362
if i == 2 and r.status == 401:
await self.init_all_data(self.session)
continue
except asyncio.CancelledError:
@@ -698,6 +709,9 @@ class XiaoMusic:
for _, play_list in self.music_list.items():
play_list.sort(key=custom_sort_key)
# 非自定义个歌单
self.default_music_list_names = list(self.music_list.keys())
# 刷新自定义歌单
self.refresh_custom_play_list()
@@ -716,6 +730,11 @@ class XiaoMusic:
def refresh_custom_play_list(self):
try:
# 删除旧的自定义个歌单
for k in list(self.music_list.keys()):
if k not in self.default_music_list_names:
del self.music_list[k]
# 合并新的自定义个歌单
custom_play_list = self.get_custom_play_list()
for k, v in custom_play_list.items():
self.music_list[k] = list(v)
@@ -764,15 +783,17 @@ class XiaoMusic:
await asyncio.sleep(3600)
async def run_forever(self):
self.log.info("run_forever start")
self.try_gen_all_music_tag() # 事件循环开始后调用一次
self.crontab.start()
await self.analytics.send_startup_event()
asyncio.create_task(self.analytics.send_startup_event())
analytics_task = asyncio.create_task(self.analytics_task_daily())
assert (
analytics_task is not None
) # to keep the reference to task, do not remove this
async with ClientSession() as session:
self.session = session
self.log.info(f"run_forever session:{self.session}")
await self.init_all_data(session)
task = asyncio.create_task(self.poll_latest_ask())
assert task is not None # to keep the reference to task, do not remove this
@@ -1170,12 +1191,13 @@ class XiaoMusic:
play_list = custom_play_list[oldname]
custom_play_list.pop(oldname)
custom_play_list[newname] = play_list
self.save_custom_play_list()
return True
# 获取所有自定义歌单
def get_play_list_names(self):
custom_play_list = self.get_custom_play_list()
return custom_play_list.keys()
return list(custom_play_list.keys())
# 获取歌单中所有歌曲
def play_list_musics(self, name):
@@ -1233,6 +1255,9 @@ class XiaoMusic:
# 设置音量
async def set_volume(self, did="", arg1=0, **kwargs):
if did not in self.devices:
self.log.info(f"设备 did:{did} 不存在, 不能设置音量")
return
volume = int(arg1)
return await self.devices[did].set_volume(volume)
@@ -1326,7 +1351,8 @@ class XiaoMusic:
for handler in self.log.handlers:
handler.close()
self.setup_logger()
await self.init_all_data(self.session)
if self.session:
await self.init_all_data(self.session)
self._gen_all_music_list()
self.update_devices()
@@ -1407,10 +1433,10 @@ class XiaoMusicDevice:
return self.device.cur_music
def get_offset_duration(self):
if not self.isplaying():
return -1, -1
offset = time.time() - self._start_time - self._paused_time
duration = self._duration
if not self.isplaying():
return 0, duration
offset = time.time() - self._start_time - self._paused_time
return offset, duration
# 初始化播放列表
@@ -1480,7 +1506,7 @@ class XiaoMusicDevice:
self.device.cur_playlist = "临时搜索列表"
self.update_playlist(reorder=False)
name = names[0]
if update_cur_list:
if update_cur_list and (name not in self._play_list):
# 根据当前歌曲匹配歌曲列表
self.device.cur_playlist = self.find_cur_playlist(name)
self.update_playlist()
@@ -1646,7 +1672,7 @@ class XiaoMusicDevice:
)
await self.stop_if_xiaoai_is_playing(device_id)
except Exception as e:
self.log.exception(f"Execption {e}")
self.log.warning(f"Execption {e}")
async def get_if_xiaoai_is_playing(self):
playing_info = await self.xiaomusic.mina_service.player_get_status(
@@ -1714,6 +1740,9 @@ class XiaoMusicDevice:
if self.config.enable_yt_dlp_cookies:
sbp_args += ("--cookies", f"{self.config.yt_dlp_cookies_path}")
if self.config.loudnorm:
sbp_args += ("--postprocessor-args", f"-af {self.config.loudnorm}")
cmd = " ".join(sbp_args)
self.log.info(f"download cmd: {cmd}")
self._download_proc = await asyncio.create_subprocess_exec(*sbp_args)