mirror of
https://github.com/hanxi/xiaomusic.git
synced 2025-12-06 14:52:50 +08:00
Compare commits
135 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5ce49d7cbe | ||
|
|
f835bc51bb | ||
|
|
dab4903487 | ||
|
|
11c1ac4753 | ||
|
|
80bacdee0f | ||
|
|
867d16700c | ||
|
|
1ca8955b94 | ||
|
|
8f19b9b33b | ||
|
|
b88712d6b0 | ||
|
|
859c12f047 | ||
|
|
a0ec94e036 | ||
|
|
bbc6c30557 | ||
|
|
4a61ff8074 | ||
|
|
0a1b467507 | ||
|
|
d244575d7b | ||
|
|
a8161579b4 | ||
|
|
fac7816c64 | ||
|
|
4adfc0e3b1 | ||
|
|
abe70b1146 | ||
|
|
e47c6eaf9d | ||
|
|
be636abaa0 | ||
|
|
6b41b7b18e | ||
|
|
198963897e | ||
|
|
2deab08351 | ||
|
|
7048e38e32 | ||
|
|
dab756da7f | ||
|
|
2cf883bcf4 | ||
|
|
f71b594a75 | ||
|
|
3a4d0b6c9b | ||
|
|
3f8bae4568 | ||
|
|
a4f21670bb | ||
|
|
fdc57d1b47 | ||
|
|
0797f2ef3f | ||
|
|
1da94f5730 | ||
|
|
12427151f5 | ||
|
|
526193f0f6 | ||
|
|
c9d0c8720a | ||
|
|
0bd661c98f | ||
|
|
b9534d3a1f | ||
|
|
27c6dd31fc | ||
|
|
5906daade6 | ||
|
|
4c36d90ad2 | ||
|
|
66905fae7e | ||
|
|
65e02540e8 | ||
|
|
bf2d29790a | ||
|
|
a28c65febf | ||
|
|
1cb01f43bf | ||
|
|
62f90422bb | ||
|
|
402c417eeb | ||
|
|
3899623a32 | ||
|
|
bdfcf43083 | ||
|
|
90e660165a | ||
|
|
a87c1fcbcf | ||
|
|
b880e861d4 | ||
|
|
33d6594029 | ||
|
|
33ca5138ee | ||
|
|
35d715526e | ||
|
|
be0687819d | ||
|
|
f5c4a6505f | ||
|
|
328cb03f8e | ||
|
|
a6742938eb | ||
|
|
8f63bc181d | ||
|
|
6bc3c46d00 | ||
|
|
f2f1f43b93 | ||
|
|
8435c10964 | ||
|
|
ff54f11a4b | ||
|
|
e8b705e9d1 | ||
|
|
2c3a95b98d | ||
|
|
52bce6af9d | ||
|
|
e5af13208a | ||
|
|
370f4ccd99 | ||
|
|
0d758a47f4 | ||
|
|
a1a025960b | ||
|
|
2c5ffa5645 | ||
|
|
f78df85bb9 | ||
|
|
a771441616 | ||
|
|
0ef36d26ff | ||
|
|
589d36f98c | ||
|
|
ad9ce10fa2 | ||
|
|
bea986f4ef | ||
|
|
c3451fea6a | ||
|
|
6ce99a0e62 | ||
|
|
063688f3e6 | ||
|
|
0c4b34a554 | ||
|
|
52b6000342 | ||
|
|
a1962cd450 | ||
|
|
2520e5d9e5 | ||
|
|
bd0a3a1052 | ||
|
|
24218babeb | ||
|
|
dd803785e1 | ||
|
|
78ee51c8c2 | ||
|
|
4e3e127767 | ||
|
|
dafd2cec05 | ||
|
|
59e9191f70 | ||
|
|
f7286269af | ||
|
|
d98652fe5d | ||
|
|
497dd07030 | ||
|
|
6cbec5bbff | ||
|
|
c46c652e5d | ||
|
|
1fbbae5f1c | ||
|
|
ffd04fab68 | ||
|
|
51dfe70a87 | ||
|
|
956c569b93 | ||
|
|
617a961816 | ||
|
|
b37b6fd57c | ||
|
|
c09baaac15 | ||
|
|
7ded7a08dd | ||
|
|
f4487945db | ||
|
|
0bdd2986f1 | ||
|
|
a72777317e | ||
|
|
f2e096da38 | ||
|
|
f42398ec9f | ||
|
|
5121d141b4 | ||
|
|
7cf9751dde | ||
|
|
990defefc9 | ||
|
|
4e6afa0e3e | ||
|
|
e501097ec2 | ||
|
|
ea567fd55a | ||
|
|
9cb1931f90 | ||
|
|
e50db9ea59 | ||
|
|
5c788ccaed | ||
|
|
10a63e5568 | ||
|
|
2460cd3207 | ||
|
|
2595451280 | ||
|
|
2c4b131c19 | ||
|
|
fb84f36b55 | ||
|
|
811e9377f7 | ||
|
|
00733ad669 | ||
|
|
4cdfd68c4d | ||
|
|
2b28bf8551 | ||
|
|
1023caf80a | ||
|
|
fba021d8fb | ||
|
|
8bac3ee961 | ||
|
|
2f18e1935e | ||
|
|
6c208eb1ce |
67
.github/workflows/ci.yml
vendored
67
.github/workflows/ci.yml
vendored
@@ -23,6 +23,8 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
@@ -77,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'
|
||||
@@ -123,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
|
||||
@@ -189,8 +194,29 @@ jobs:
|
||||
sudo apt install -y gh
|
||||
|
||||
# 创建或更新 Release
|
||||
- name: Create or update Release
|
||||
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')
|
||||
- name: Create or update Release main
|
||||
if: github.ref == 'refs/heads/main'
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} # 设置 GH_TOKEN 环境变量
|
||||
run: |
|
||||
RELEASE_NAME=test
|
||||
RELEASE_BODY="This release is automatically updated from the main branch."
|
||||
|
||||
# 检查是否已有同名 Release
|
||||
EXISTING_RELEASE=$(gh release view "${RELEASE_NAME}" --json id --jq .id || echo "")
|
||||
|
||||
if [[ -n "${EXISTING_RELEASE}" ]]; then
|
||||
echo "release exist"
|
||||
else
|
||||
# 创建新的 Release
|
||||
gh release create "${RELEASE_NAME}" \
|
||||
--prerelease=false \
|
||||
--title "${RELEASE_NAME}" \
|
||||
--notes "${RELEASE_BODY}"
|
||||
fi
|
||||
|
||||
- name: Create or update Release tag
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} # 设置 GH_TOKEN 环境变量
|
||||
run: |
|
||||
@@ -210,9 +236,23 @@ jobs:
|
||||
--notes "${RELEASE_BODY}"
|
||||
fi
|
||||
|
||||
|
||||
# 上传多个文件并覆盖
|
||||
- name: Upload assets to Release
|
||||
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')
|
||||
- name: Upload assets to Release main
|
||||
if: github.ref == 'refs/heads/main'
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} # 设置 GH_TOKEN 环境变量
|
||||
run: |
|
||||
RELEASE_NAME=test
|
||||
|
||||
FILES=$(find . -type f -name "app-*.tar.gz")
|
||||
for FILE in ${FILES}; do
|
||||
echo "type upload ${FILE}"
|
||||
gh release upload "${RELEASE_NAME}" "${FILE}" --clobber
|
||||
done
|
||||
|
||||
- name: Upload assets to Release tag
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} # 设置 GH_TOKEN 环境变量
|
||||
run: |
|
||||
@@ -223,4 +263,3 @@ jobs:
|
||||
echo "type upload ${FILE}"
|
||||
gh release upload "${RELEASE_NAME}" "${FILE}" --clobber
|
||||
done
|
||||
|
||||
|
||||
17
.github/workflows/static.yml
vendored
17
.github/workflows/static.yml
vendored
@@ -8,7 +8,7 @@ on:
|
||||
paths:
|
||||
- 'docs/**'
|
||||
- 'README.md'
|
||||
- 'CHANGELOG..md'
|
||||
- 'CHANGELOG.md'
|
||||
- '.github/workflows/static.yml'
|
||||
# Runs on issue events
|
||||
issues:
|
||||
@@ -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
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -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
|
||||
|
||||
110
CHANGELOG.md
110
CHANGELOG.md
@@ -1,3 +1,113 @@
|
||||
## 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)
|
||||
|
||||
### Feat
|
||||
|
||||
@@ -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"]
|
||||
|
||||
@@ -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
|
||||
|
||||
137
README.md
137
README.md
@@ -1,4 +1,5 @@
|
||||
# XiaoMusic: 无限听歌,解放小爱音箱
|
||||
|
||||
[](https://github.com/hanxi/xiaomusic)
|
||||
[](https://hub.docker.com/r/hanxi/xiaomusic)
|
||||
[](https://hub.docker.com/r/hanxi/xiaomusic)
|
||||
@@ -9,7 +10,6 @@
|
||||
[](https://visitorbadge.io/status?path=hanxi%2Fxiaomusic)
|
||||
[](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)
|
||||
|
||||
@@ -365,4 +297,3 @@ docker build -t xiaomusic .
|
||||
## License
|
||||
|
||||
[MIT](https://github.com/hanxi/xiaomusic/blob/main/LICENSE) License © 2024 涵曦
|
||||
|
||||
|
||||
@@ -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',
|
||||
}),
|
||||
],
|
||||
}
|
||||
|
||||
@@ -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">
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -350,7 +350,7 @@ key_word_dict中的“播放歌曲”口令是不能修改的是吧?因为以
|
||||
### 评论 16 - mogeqian
|
||||
|
||||
不行,后台设置如图
|
||||

|
||||

|
||||
日志如下:
|
||||
```
|
||||
[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)
|
||||
|
||||
@@ -16,14 +16,14 @@ title: yt-dlp cookies 文件上传功能
|
||||
|
||||
1. 下载插件 [Get cookies.txt LOCALLY](https://chromewebstore.google.com/detail/cclelndahbckbenkjhflpdbgdldlbecc)
|
||||
2. 给予插件访问权限和无痕模式允许使用
|
||||

|
||||

|
||||
3. 打开无痕窗口
|
||||
4. 打开 youtube.com
|
||||
5. 登陆 youtube.com
|
||||
6. 打开新标签页
|
||||
7. 关闭 youtube.com 的标签页
|
||||
8. 保存 cookies.txt
|
||||

|
||||

|
||||
|
||||
原因见 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
|
||||

|
||||

|
||||
3. 点击保存
|
||||
4. 再点击选择文件,选择前面保存好的 cookies.txt 文件,点击上传。
|
||||

|
||||

|
||||
|
||||
|
||||
## 后续用途
|
||||
@@ -50,7 +50,7 @@ title: yt-dlp cookies 文件上传功能
|
||||
### 评论 1 - kingfly2016
|
||||
|
||||
0.3.37的版本并没有发现可以开启yt-dlp-cookies 并上传cookies文件的地方,尝试把导出的cookies.txt手工上传到conf目录下,没有生效.
|
||||

|
||||

|
||||
|
||||
|
||||
---
|
||||
|
||||
@@ -14,6 +14,7 @@ title: 📝 文档汇总
|
||||
|
||||
## 2️⃣ 进阶文档
|
||||
|
||||
- [设置项功能介绍](/issues/333.html)
|
||||
- [采用config.json配置方式](/issues/94.html)
|
||||
- [ios系统上的捷径配置](/issues/96.html)
|
||||
- [【插件】自定义口令功能](/issues/105.html)
|
||||
@@ -91,5 +92,35 @@ 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 主题就可以,你试试。
|
||||
|
||||
---
|
||||
[链接到 GitHub Issue](https://github.com/hanxi/xiaomusic/issues/211)
|
||||
|
||||
@@ -10,7 +10,7 @@ title: 如何批量下载歌曲
|
||||
|
||||
> 默认主题 => 设置 => 歌曲下载工具
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
已经测试过 B 站和 youtube 两种播放列表,播放列表的链接是有要求,不能有其他多余参数。
|
||||
@@ -38,7 +38,7 @@ https://m.youtube.com/playlist?list=PLUD2d-pqyvT6_ztf31hx-5SsUUvY5UsQn
|
||||
默认主题 => 设置 =>没有显示找到 歌曲下载工具,
|
||||
有一个 歌单地址 歌单内容: 输入B站测试地址显示返回无效
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
---
|
||||
|
||||
@@ -19,5 +19,66 @@ title: xiaomusic立体声
|
||||
|
||||
我这边先用一个音箱播放,然后米家里设置全屋播放,就能多个音箱同时播了,进度也同步,而且后续会自动全屋播放
|
||||
|
||||
---
|
||||
|
||||
### 评论 3 - zazhi4
|
||||
|
||||
我遇到双音箱播放问题,没法立体声,没法全屋播放,详述如下:
|
||||
1、基本情况:原有小爱音箱Pro,LX06,用xiaomusic,0.3.69版本,播放正常。看到issue里提及了立体声,打算尝试,新购了小爱音箱,L06A。将新音箱通过米家APP加入到自家的wifi里。
|
||||
2、尝试:
|
||||
2.1,在xiaomusic里,默认面板,设置,发现可以在小爱音箱设置面板里有两个音箱供选择,我都勾选了,在设备分组配置里,两个音箱的did输入,配为1个组,能实现同时驱动两个音箱发声,但是不同步,时间上差了不到1秒钟,但是听起来不舒服。
|
||||
2.2 在xiaomusic里,默认面板,设置,只勾选1个音箱;设备分组配置里,删除原先配置,清空。播放,只有一只音箱有声音。然后回到米家APP。将两个音箱设置,组成立体声。完成后,依然只有一只音箱有声音。设置后,对播放没有影响。
|
||||
2.3 在米家APP中,取消立体声配对,改为“全屋播放”。设置好后,依然只有一只音箱有声音。换言之,设置后对播放没有影响。
|
||||
3、检查版本,在小米音箱app中,检查两只音箱的版本,均为最新稳定版。
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
### 评论 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
|
||||
|
||||
立体声,想了几个路径:1,xiaomusic能不能拆分声音为左右两个声道,分别发往两个音箱,难题在于,怎么保证两个音箱同时接到信息,发声;2,能不能搞定米家app的接口,发送声音给米家app,由米家app发给音箱;3,或是搞定模拟米家app与音箱的接口,通过米家接口,发给音箱,让音箱以为声音来自米家app。方法2,3,要搞清楚,米家app播音,为什么能实现立体声,然后在方法2,3中选一个方向。
|
||||
|
||||
---
|
||||
|
||||
### 评论 9 - hanxi
|
||||
|
||||
@zazhi4 思路是对的,感兴趣可以抓包玩玩的。目前协议是没加密的。
|
||||
|
||||
---
|
||||
[链接到 GitHub Issue](https://github.com/hanxi/xiaomusic/issues/235)
|
||||
|
||||
@@ -223,7 +223,7 @@ def getmy_playlist(type="netease",api_host="http://127.0.0.1/api", playlist_id=N
|
||||
> 等有空我写个修改歌单内容的插件示例吧。
|
||||
|
||||
不用拉,插件我已经写出来了
|
||||

|
||||

|
||||
|
||||
|
||||
|
||||
@@ -250,7 +250,7 @@ def getmy_playlist(type="netease",api_host="http://127.0.0.1/api", playlist_id=N
|
||||
### 评论 13 - dissipator
|
||||
|
||||
# 成功了
|
||||

|
||||

|
||||
# 最好是在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
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
|
||||
---
|
||||
@@ -500,7 +500,7 @@ async def getmy_playlist(type="netease",api_host="http://127.0.0.1/api", playlis
|
||||
|
||||
NeteaseCloudMusicApi似乎获取不到播放地址?其他信息倒是有。
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
---
|
||||
|
||||
@@ -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>
|
||||
|
||||
---
|
||||
|
||||
@@ -10,7 +10,7 @@ M01:在0.3.55版本【型号兼容模式】与【特殊型号获取对话记录
|
||||
型号:S12A、LX04、S12 在米家APP可以联动,比如客厅有人自定义指令:播放歌曲、关机...等
|
||||
而M01无论【型号兼容模式】与【特殊型号获取对话记录】设为false或true,都无法执行任何自定义指令…
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
## 评论
|
||||
|
||||
@@ -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`,在搜索的结果中直接选择第一个,点击**下载**
|
||||
|
||||

|
||||

|
||||
|
||||
2. 在新弹出的版本选择窗口中,根据你的情况选择。
|
||||

|
||||

|
||||
|
||||
### 版本说明
|
||||
- 获取 **最新版** 直接点击 **下载** 即可,建议使用默认的 `latest`
|
||||
@@ -28,7 +28,7 @@ title: xiaomusic极空间安装教程(2024/12/4更新)
|
||||
|
||||
|
||||
3. 接着弹出如图所示的页面,耐心等待下载完成。
|
||||

|
||||

|
||||
|
||||
|
||||
4. 下载完成后切换到 **本地镜像** 选项卡
|
||||
@@ -37,19 +37,20 @@ title: xiaomusic极空间安装教程(2024/12/4更新)
|
||||
|
||||
## 国内环境:
|
||||
1. 打开docker,在左侧的菜单中选择 **镜像** 切换到 **仓库** 选项卡,点击 **自定义拉取** 按钮
|
||||

|
||||

|
||||
2. 在弹出的对话框中输入 ` m.daocloud.io/docker.io/hanxi/xiaomusic ` ,点击 **拉取** 按钮
|
||||

|
||||

|
||||
3. 下载完成后切换到 **本地镜像** 选项卡
|
||||
|
||||
# 部署镜像
|
||||
1. 找到刚才已经拉取好的镜像,*单击选中*,点击 **添加到容器**
|
||||

|
||||

|
||||
2. 在弹出的 **创建容器** 菜单中,切换到 **文件夹路径** 选项卡中,按图中的提示进行配置。
|
||||

|
||||

|
||||
|
||||
**注意:**
|
||||
* 装载路径中的 **配置文件目录** 和 **音乐目录** 必须进行配置。
|
||||
* 装载路径中的 **配置文件目录** 和 **音乐目录** 必须进行配置,**其他目录非必要请勿配置**
|
||||
* 主题目录为方便开发主题调试时的配置选项,普通用户不能理解明确用途请**不要配置主题目录**,否则会报**HTTP Status 500 – Internal Server Error** 错误
|
||||
* 如有多个音乐目录,请按照下面的格式进行配置
|
||||
|
||||
| 文件/文件夹 | 装载路径 |
|
||||
@@ -60,7 +61,7 @@ title: xiaomusic极空间安装教程(2024/12/4更新)
|
||||
3. 切换到 **端口** 选项卡,修改成与你的极空间 *不冲突* 的本地端口号,如 `5678` (示例按照本地端口号5678来进行配置,下同)
|
||||
> 友情提醒: 尽量不要修改容器端口号,否则要到配置文件目录修改对应的`setting.json`文件中的配置,会增加很多麻烦
|
||||
|
||||

|
||||

|
||||
|
||||
5. 切换到 **环境** 选项卡,将`XIAOMUSIC_HOSTNAME` 修改为你的 **极空间的IP地址**
|
||||
> 友情提醒:
|
||||
@@ -68,26 +69,26 @@ title: xiaomusic极空间安装教程(2024/12/4更新)
|
||||
> 2. 不要尝试修改XIAOMUSIC_PORT!除非你没有看上一条的友情提醒
|
||||
> 3. 不要在此处配置`ACCOUNT`和`PASSWORD`,没有过风控仍然无法使用!上古时代的教程不要再看了,容易走火入魔!
|
||||
|
||||

|
||||

|
||||
|
||||
6. 点击 **应用**按钮,此时容器已经配置完成了,切换到左侧的 **容器概况** 菜单,可查看容器详情
|
||||

|
||||

|
||||
|
||||
# 进入xiaomusic网页端进行配置
|
||||
1.请关闭代理,打开浏览器,地址栏输入 **极空间IP:本地端口号** 如`192.168.2.5:5678`,打开网页后点击 **默认主题**
|
||||
|
||||

|
||||

|
||||
|
||||
**注意:**
|
||||
* 不要复制此处的地址,必须输入极空间的IP地址。不知道的建议上咸鱼50块换个不锈钢盆
|
||||
* 不要输入容器的端口号8090,极空间不能使用这个端口号。
|
||||
|
||||
2. 点击 **设置** 按钮进入设置页面
|
||||

|
||||

|
||||
|
||||
3. 输入**小米账号**、**小米密码**、**XIAOMUSIC_HOSTNAME(IP或域名):**、**外网访问端口**,滑到页面最下方点击 **保存**
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
**注意:**
|
||||
* 小米账号非手机号,请在手机设置-个人中心中查看小米ID
|
||||
@@ -95,10 +96,10 @@ title: xiaomusic极空间安装教程(2024/12/4更新)
|
||||
* XIAOMUSIC_HOSTNAME(IP或域名): 可以输入当前页面的IP地址(在地址栏),**不要在此处输入端口号!!!**,如果域名需要使用https协议,请加上https://
|
||||
|
||||
4.如果以上步骤没错,你将在设置中心看见设备列表
|
||||

|
||||

|
||||
|
||||
5. 回到首页,出现设备列表,切换对应设备即可畅享
|
||||

|
||||

|
||||
|
||||
|
||||
## 评论
|
||||
@@ -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
31
docs/issues/333.md
Normal 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
29
docs/issues/350.md
Normal 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)
|
||||
@@ -256,7 +256,7 @@ stderr: [08:58:10] [0.3.37] [INFO] xiaomusic.py:1094: 播放 80后音悦台 失
|
||||
### 评论 5 - 201692929
|
||||
|
||||
怎么获取 他正在播放什么?或者是播放进度 ?播放列表?我想给他加进去
|
||||

|
||||

|
||||
|
||||
|
||||
---
|
||||
@@ -308,20 +308,20 @@ potplayer里播放完全正常~~
|
||||
> 发出来看看?
|
||||
|
||||
经过实验发现,本地生成的m3u用potplayer播放正常
|
||||

|
||||

|
||||
转换为json(去掉"type":"radio")后用小爱播放也正常
|
||||

|
||||

|
||||
|
||||
但是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一播放就出现时长了
|
||||

|
||||

|
||||
而用小爱播放就始终没有时长(切歌、等待都试过了)
|
||||

|
||||

|
||||
大佬你的示例链接(gist.github.com/hanxi/dda82d964a28f8110f8fba81c3ff8314)里的又是正常的,感觉可能是alist的流比较特殊。。
|
||||

|
||||

|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -4,7 +4,11 @@ title: 微信交流群二维码
|
||||
|
||||
# 微信交流群二维码
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
如果你刚好在买流量卡,可以在我的微信卡店里看看有没有合适的。
|
||||

|
||||
|
||||
|
||||
## 评论
|
||||
@@ -24,7 +28,7 @@ title: 微信交流群二维码
|
||||
|
||||
### 评论 3 - hanxi
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
---
|
||||
|
||||
@@ -8,15 +8,15 @@ title: 如何添加m3u格式文件的电台
|
||||
|
||||
1. 复制文件内容,粘贴到 m3u 转换工具里,点击转换为 json 格式:
|
||||
|
||||

|
||||

|
||||
|
||||
2. 然后复制 json 内容,粘贴到歌单内容里,点击保存,再返回首页:
|
||||
|
||||

|
||||

|
||||
|
||||
3. 在首页点击刷新列表,选择所有电台,再点击播放列表歌曲:
|
||||
|
||||

|
||||

|
||||
|
||||
4. 也可以用口令播放电台: `播放列表所有电台` ,或者口令: `播放歌曲北京城市广播`
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ pip install xiaomusic
|
||||
|
||||
依赖的 ffmpeg 需要自己安装。
|
||||
|
||||

|
||||

|
||||
|
||||
仓库中有个 config-example.json 文件,可以把这个文件拷贝为 config.json 然后修改 config.json 里的配置,再用下面的命令启动。
|
||||
|
||||
|
||||
@@ -6,9 +6,9 @@ title: ios系统上的捷径配置
|
||||
|
||||
下面是播放音乐和关机两个示例。只要在 web 页面上能看到的功能,都有对应的 http 请求接口,都可以用来配置捷径。
|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
## 评论
|
||||
|
||||
@@ -149,7 +149,22 @@ Exception: Error https://api2.mina.mi.com/remote/ubus: {"code":601,"message":"il
|
||||
|
||||
## ❓ 为什么会先说小爱音箱自带的回答,再说下载中或者过一会儿才播放本地歌曲
|
||||
|
||||
设计原理就是每秒不停的抓取对话记录,然后再打断小爱音箱自带的处理流程。整个过程下来会有延时,所以打断不会很及时,做不到无缝衔接。
|
||||
设计原理就是每秒不停的抓取对话记录,然后再打断小爱音箱自带的处理流程。整个过程下来会有延时,所以打断不会很及时,做不到无缝衔接。
|
||||
|
||||
## ❓ 云服务器上能否安装
|
||||
|
||||
可以安装,登录 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
|
||||
```
|
||||
|
||||
|
||||
## 评论
|
||||
|
||||
@@ -201,7 +216,7 @@ RUN pip install -U xiaomusic
|
||||
> ```
|
||||
|
||||
我直接用pip安装好之后,执行仍然有缺少的依赖,和docker里缺的一样。截图的module安装了之后还会有其他依赖缺失
|
||||

|
||||

|
||||
|
||||
|
||||
---
|
||||
@@ -236,7 +251,7 @@ RUN pip install -U xiaomusic
|
||||
### 评论 9 - sqmcool
|
||||
|
||||
为什么我的没有显示设备?
|
||||

|
||||

|
||||
|
||||
|
||||
---
|
||||
@@ -252,7 +267,7 @@ RUN pip install -U xiaomusic
|
||||
### 评论 11 - schppd
|
||||
|
||||
楼主您好,请问这个我需要怎么处理?
|
||||

|
||||

|
||||
|
||||
|
||||
---
|
||||
@@ -316,7 +331,7 @@ You are receiving this because you commented.Message ID: ***@***.***>
|
||||
|
||||
### 评论 16 - agigogo
|
||||
|
||||

|
||||

|
||||
在docker里可以运行,但是没法播放设置页面中的播放链接,选中设备那里是空的,是不是没成功?怎么调整?
|
||||
|
||||
|
||||
@@ -342,7 +357,7 @@ You are receiving this because you commented.Message ID: ***@***.***>
|
||||
>
|
||||
> 设置页面输入小米的账号密码后,再勾选一个设备。
|
||||
|
||||

|
||||

|
||||
设置页面没有可勾选项?
|
||||
|
||||
---
|
||||
@@ -363,7 +378,7 @@ You are receiving this because you commented.Message ID: ***@***.***>
|
||||
>
|
||||
>  设置页面没有可勾选项?
|
||||
|
||||

|
||||

|
||||
|
||||
显示未检测到设备,设备型号是MDZ-25-DA
|
||||
|
||||
@@ -421,9 +436,9 @@ You are receiving this because you commented.Message ID: ***@***.***>
|
||||
|
||||
### 评论 27 - zealler9560
|
||||
|
||||

|
||||

|
||||
|
||||
istore系统可以拉取创建镜像,但是无法启动,错误提示见图一,求助大佬!路由器信息见图二
|
||||
istore系统可以拉取创建镜像,但是无法启动,错误提示见图一,求助大佬!路由器信息见图二
|
||||
|
||||
|
||||
|
||||
@@ -626,8 +641,8 @@ You are receiving this because you commented.Message ID: ***@***.***>
|
||||
|
||||
### 评论 41 - CallEdison
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
问题一:能进控制面板,进不了设置页面,容器没有log生成,我昨天已经设置好了,现在功能能正常使用,但是进不了设置页面了问题二:昨天能进的时候发现本地下载目录有歌曲,但是设置里面的全部歌曲里面没有,搜索框搜索又能搜的到。
|
||||
|
||||
---
|
||||
@@ -719,7 +734,7 @@ You are receiving this because you commented.Message ID: ***@***.***>
|
||||
|
||||
### 评论 47 - like1020
|
||||
|
||||

|
||||

|
||||
请教一下,本地列表歌单里的歌曲即便设置为全部循环或随机播放,依然是不断地单曲循环,只能自己手动点下一首,请问是什么情况?
|
||||
|
||||
---
|
||||
@@ -1101,5 +1116,144 @@ You are receiving this because you commented.Message ID: ***@***.***>
|
||||
|
||||
绿联的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路径防止文件无法被识别出来。
|
||||

|
||||
直接在xiaomusic里面下载音乐是可以播放的,进入到docker里面的路径也是有音乐文件的
|
||||

|
||||
|
||||
建容器的命令如下:
|
||||
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路径防止文件无法被识别出来。  直接在xiaomusic里面下载音乐是可以播放的,进入到docker里面的路径也是有音乐文件的 
|
||||
>
|
||||
> 建容器的命令如下: 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路径防止文件无法被识别出来。  直接在xiaomusic里面下载音乐是可以播放的,进入到docker里面的路径也是有音乐文件的 
|
||||
> > 建容器的命令如下: 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
|
||||
>
|
||||
> 为啥路径要加方括号?另外两个路径不能重复。
|
||||
|
||||
方括号是为了让文件夹在第一位,重新安装容器,路径不一样后还是一样的问题:
|
||||
|
||||

|
||||
|
||||
|
||||
语句:
|
||||
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路径防止文件无法被识别出来。  直接在xiaomusic里面下载音乐是可以播放的,进入到docker里面的路径也是有音乐文件的 
|
||||
> > > 建容器的命令如下: 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
|
||||
> >
|
||||
> >
|
||||
> > 为啥路径要加方括号?另外两个路径不能重复。
|
||||
>
|
||||
> 方括号是为了让文件夹在第一位,重新安装容器,路径不一样后还是一样的问题:
|
||||
>
|
||||
> 
|
||||
>
|
||||
> 语句: 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
|
||||
|
||||

|
||||
yi以为是文件夹关联失败了,但是进入容器看应该是成功的
|
||||
|
||||
---
|
||||
[链接到 GitHub Issue](https://github.com/hanxi/xiaomusic/issues/99)
|
||||
|
||||
@@ -1,5 +1,125 @@
|
||||
# 版本日志
|
||||
|
||||
## 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)
|
||||
|
||||
### Feat
|
||||
|
||||
- 新增更多的歌单编辑相关接口
|
||||
- 一键更新功能
|
||||
- 接入 sentry 平台
|
||||
- 实现更新接口
|
||||
- 下载完成之后修改文件权限为755 close #316
|
||||
|
||||
### Fix
|
||||
|
||||
- 解决飞牛平台报错问题
|
||||
|
||||
### Refactor
|
||||
|
||||
- 优化代码日志级别
|
||||
- 更新等消息推送到客户端再重启
|
||||
- 更新接口修改
|
||||
|
||||
## v0.3.58 (2024-12-15)
|
||||
|
||||
### Fix
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# XiaoMusic: 无限听歌,解放小爱音箱
|
||||
|
||||
[](https://github.com/hanxi/xiaomusic)
|
||||
[](https://hub.docker.com/r/hanxi/xiaomusic)
|
||||
[](https://hub.docker.com/r/hanxi/xiaomusic)
|
||||
@@ -9,7 +10,6 @@
|
||||
[](https://visitorbadge.io/status?path=hanxi%2Fxiaomusic)
|
||||
[](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)
|
||||
|
||||
@@ -365,4 +297,3 @@ docker build -t xiaomusic .
|
||||
## License
|
||||
|
||||
[MIT](https://github.com/hanxi/xiaomusic/blob/main/LICENSE) License © 2024 涵曦
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "xiaomusic"
|
||||
version = "0.3.59"
|
||||
version = "0.3.72"
|
||||
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"}
|
||||
|
||||
|
||||
@@ -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,6 +21,7 @@ command=/app/.venv/bin/python3 /app/xiaomusic.py
|
||||
directory=/app
|
||||
autostart=true
|
||||
autorestart=true
|
||||
startretries=99999
|
||||
startsecs=60
|
||||
stderr_logfile=/app/xiaomusic.log.txt
|
||||
stdout_logfile=/app/xiaomusic.log.txt
|
||||
|
||||
@@ -1,8 +1,29 @@
|
||||
from xiaomusic.utils import (
|
||||
remove_common_prefix,
|
||||
)
|
||||
import re
|
||||
|
||||
|
||||
def removepre(filename):
|
||||
match = re.search(r"^(\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("09 009. 梁静茹-亲亲.mp3")
|
||||
|
||||
@@ -1 +1 @@
|
||||
__version__ = "0.3.59"
|
||||
__version__ = "0.3.72"
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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():
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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("\\", "")
|
||||
|
||||
@@ -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=1734568930">
|
||||
<link rel="stylesheet" type="text/css" href="./main.css?version=1736576310">
|
||||
<script src="https://unpkg.com/vconsole@latest/dist/vconsole.min.js"></script>
|
||||
<script src="./jquery-3.7.1.min.js?version=1734568930"></script>
|
||||
<script src="./jquery-3.7.1.min.js?version=1736576310"></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();
|
||||
|
||||
@@ -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=1734568930">
|
||||
<script src="./jquery-3.7.1.min.js?version=1734568930"></script>
|
||||
<link rel="stylesheet" type="text/css" href="./main.css?version=1736576310">
|
||||
<script src="./jquery-3.7.1.min.js?version=1736576310"></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>
|
||||
|
||||
@@ -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=1734568930"></script>
|
||||
<link rel="stylesheet" href="./main.css?version=1734568930">
|
||||
<script src="./jquery-3.7.1.min.js?version=1736576310"></script>
|
||||
<link rel="stylesheet" href="./main.css?version=1736576310">
|
||||
<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>
|
||||
|
||||
@@ -202,7 +201,7 @@
|
||||
</label>
|
||||
|
||||
<select id="update-version" class="version-selector">
|
||||
<option value="main" selected>测试版</option>
|
||||
<option value="test" selected>test</option>
|
||||
</select>
|
||||
|
||||
<label for="lite">选择类型:</label>
|
||||
@@ -220,7 +219,7 @@
|
||||
Powered by XiaoMusic
|
||||
</div>
|
||||
|
||||
<script src="./md.js?version=1734568930">
|
||||
<script src="./md.js?version=1736576310">
|
||||
</script>
|
||||
</body>
|
||||
|
||||
|
||||
@@ -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=1734568930">
|
||||
<link rel="stylesheet" type="text/css" href="./main.css?version=1736576310">
|
||||
|
||||
<!-- 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>
|
||||
|
||||
@@ -351,3 +351,8 @@ span,p {
|
||||
margin-left: auto;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.setting-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@@ -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({
|
||||
@@ -652,7 +661,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");
|
||||
@@ -660,11 +669,7 @@ $('#version').on('click', function() {
|
||||
data.forEach((item) => {
|
||||
const option = document.createElement("option");
|
||||
option.value = item.version;
|
||||
if (item.version=="main"){
|
||||
option.textContent = "测试版";
|
||||
} else {
|
||||
option.textContent = item.version;
|
||||
}
|
||||
option.textContent = item.version;
|
||||
versionSelect.appendChild(option);
|
||||
});
|
||||
});
|
||||
@@ -696,3 +701,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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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=1734568930"></script>
|
||||
<script src="./setting.js?version=1734568930"></script>
|
||||
<link rel="stylesheet" type="text/css" href="./main.css?version=1734568930">
|
||||
<script src="./jquery-3.7.1.min.js?version=1736576310"></script>
|
||||
<script src="./setting.js?version=1736576310"></script>
|
||||
<link rel="stylesheet" type="text/css" href="./main.css?version=1736576310">
|
||||
|
||||
<!-- 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,23 +50,31 @@ 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>
|
||||
<input id="group_list" type="text" placeholder="did1:组名1,did2:组名1,did3:组名2" />
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -17,7 +17,6 @@ import re
|
||||
import shutil
|
||||
import string
|
||||
import subprocess
|
||||
import tarfile
|
||||
import tempfile
|
||||
import urllib.parse
|
||||
from collections.abc import AsyncIterator
|
||||
@@ -337,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
|
||||
|
||||
|
||||
@@ -488,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",
|
||||
@@ -496,6 +500,7 @@ def convert_file_to_mp3(input_file: str, config) -> str:
|
||||
"mp3",
|
||||
"-vn",
|
||||
"-y",
|
||||
*loudnorm_args,
|
||||
out_file_path,
|
||||
]
|
||||
|
||||
@@ -644,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
|
||||
@@ -674,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)
|
||||
@@ -787,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):
|
||||
@@ -817,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()
|
||||
@@ -884,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)
|
||||
@@ -919,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)
|
||||
@@ -953,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"^(\d+)\s+\d*(.+?)\.(.*$)")
|
||||
for filename in files:
|
||||
if filename == common_prefix:
|
||||
continue
|
||||
@@ -961,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)
|
||||
@@ -1048,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)
|
||||
|
||||
@@ -1091,17 +1124,29 @@ async def download_and_extract(url: str, target_directory: str):
|
||||
async for chunk in response.content.iter_any():
|
||||
f.write(chunk)
|
||||
log.info(f"文件下载完成: {file_name}")
|
||||
|
||||
# 解压下载的文件
|
||||
if file_name.endswith(".tar.gz"):
|
||||
with tarfile.open(file_name, "r:gz") as tar:
|
||||
tar.extractall(path=target_directory)
|
||||
log.info(f"文件解压完成到: {target_directory}")
|
||||
await extract_tar_gz(file_name, target_directory)
|
||||
else:
|
||||
ret = f"下载失败, 包有问题: {file_name}"
|
||||
log.warning(ret)
|
||||
|
||||
else:
|
||||
ret = f"下载失败, 状态码: {response.status}"
|
||||
log.warning(ret)
|
||||
return ret
|
||||
|
||||
|
||||
async def extract_tar_gz(file_name: str, target_directory: str):
|
||||
# 使用 asyncio.create_subprocess_exec 执行 tar 解压命令
|
||||
command = ["tar", "-xzvf", file_name, "-C", target_directory]
|
||||
# 启动子进程执行解压命令
|
||||
await asyncio.create_subprocess_exec(*command)
|
||||
# 不等待子进程完成
|
||||
log.info(f"extract_tar_gz ing {file_name}")
|
||||
|
||||
|
||||
def chmodfile(file_path: str):
|
||||
try:
|
||||
os.chmod(file_path, 0o775)
|
||||
|
||||
@@ -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,7 @@ 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}")
|
||||
continue
|
||||
|
||||
except asyncio.CancelledError:
|
||||
@@ -698,6 +706,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 +727,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 +780,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 +1188,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 +1252,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 +1348,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 +1430,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
|
||||
|
||||
# 初始化播放列表
|
||||
@@ -1646,7 +1669,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 +1737,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)
|
||||
|
||||
Reference in New Issue
Block a user