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

Compare commits

...

24 Commits

Author SHA1 Message Date
涵曦
23d321a722 new version v0.1.84 2024-06-30 09:44:25 +00:00
涵曦
20945954b1 feat: config.json 支持更多配置选项 2024-06-30 09:43:51 +00:00
涵曦
d6c2078917 docs: 文档更新 2024-06-30 09:43:28 +00:00
涵曦
a5b8dc639c feat: 新增 XIAOMUSIC_STOP_TTS_MSG 配置关机提示音 2024-06-30 07:32:33 +00:00
涵曦
84751e0d68 new version v0.1.83 2024-06-30 06:38:09 +00:00
涵曦
e759658481 bugfix: pip安装运行名字错误 2024-06-30 06:38:04 +00:00
涵曦
d83100588f new version v0.1.82 2024-06-30 06:34:03 +00:00
涵曦
83d0e02eb4 feat: 优化指令匹配规则 2024-06-30 06:33:53 +00:00
涵曦
20f1f33b6c update readme 2024-06-30 05:53:54 +00:00
涵曦
fbb5d26c28 new version v0.1.81 2024-06-30 05:42:26 +00:00
涵曦
2c21778675 update project 2024-06-30 05:40:08 +00:00
涵曦
959acd8fb7 优化关机提示 2024-06-30 05:27:44 +00:00
涵曦
148c5b7621 命令行新增LOGO 2024-06-30 05:19:38 +00:00
涵曦
d7a2afba48 Update README.md 2024-06-30 12:06:01 +08:00
涵曦
559ed23214 Update README.md 2024-06-30 12:05:10 +08:00
涵曦
1d1e63df8a Update README.md 2024-06-30 12:04:29 +08:00
涵曦
27e9d92a0a 提交config.json模板文件 2024-06-30 03:54:39 +00:00
涵曦
69573f3fa4 new version v0.1.80 2024-06-30 01:07:29 +00:00
涵曦
edafd79140 fix: #91 修复下载歌曲报错 2024-06-30 01:07:25 +00:00
涵曦
7c45d93fea new version v0.1.79 2024-06-29 15:37:38 +00:00
涵曦
f19a7e1080 优化关机的问题 2024-06-29 15:37:08 +00:00
涵曦
5e0ae07978 new version v0.1.78 2024-06-29 15:35:15 +00:00
涵曦
116a05ce4b 修复播放列表的问题 2024-06-29 15:35:15 +00:00
涵曦
d6fdee5905 Update README.md 2024-06-29 21:33:09 +08:00
7 changed files with 136 additions and 22 deletions

View File

@@ -48,7 +48,10 @@ docker run -e MI_USER='小米账号' \
启动成功后,在 web 页面可以配置 MI_DID, MI_HARDWARE, XIAOMUSIC_SEARCH, XIAOMUSIC_PROXY 参数。
如果需要修改 8090 端口为其他端口,比如 5678需要这样配3个数字都需要是 5678
### ✨ 修改8090端口
如果需要修改 8090 端口为其他端口,比如 5678需要这样配3个数字都需要是 5678 。见 <https://github.com/hanxi/xiaomusic/issues/19>
```yaml
services:
xiaomusic:
@@ -69,6 +72,37 @@ services:
其中 XIAOMUSIC_VERBOSE 设置为 'true' 时表示开启 debug 日志,遇到问题可以去 web 设置页面底部【下载日志文件】按钮,然后搜索一下日志文件内容确保里面没有账号密码信息后(有就删除这些敏感信息),然后在提 issues 反馈问题时把下载的日志文件带上。
## pip 方式安装运行
```shell
> pip install xiaomusic
> xiaomusic --help
__ __ _ __ __ _
\ \/ / (_) __ _ ___ | \/ | _ _ ___ (_) ___
\ / | | / _` | / _ \ | |\/| | | | | | / __| | | / __|
/ \ | | | (_| | | (_) | | | | | | |_| | \__ \ | | | (__
/_/\_\ |_| \__,_| \___/ |_| |_| \__,_| |___/ |_| \___|
XiaoMusic v0.1.81 by: github.com/hanxi
usage: xiaomusic.py [-h] [--hardware HARDWARE] [--account ACCOUNT]
[--password PASSWORD] [--cookie COOKIE] [--verbose]
[--config CONFIG] [--ffmpeg_location FFMPEG_LOCATION]
options:
-h, --help show this help message and exit
--hardware HARDWARE 小爱 hardware
--account ACCOUNT xiaomi account
--password PASSWORD xiaomi password
--cookie COOKIE xiaomi cookie
--verbose show info
--config CONFIG config file path
--ffmpeg_location FFMPEG_LOCATION
ffmpeg bin path
> xiaomusic --config config.json
```
其中 `config.json` 文件可以参考 `config-example.json` 文件配置。见 <https://github.com/hanxi/xiaomusic/issues/94>
## 开发环境运行
- 使用 install_dependencies.sh 下载依赖
@@ -291,6 +325,8 @@ services:
- 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>
## 讨论区

32
config-example.json Normal file
View File

@@ -0,0 +1,32 @@
{
"hardware": "L07A",
"account": "",
"password": "",
"mi_did": "",
"cookie": "",
"verbose": false,
"music_path": "music",
"conf_path": null,
"hostname": "192.168.2.5",
"port": 8090,
"proxy": null,
"search_prefix": "ytsearch:",
"ffmpeg_location": "./ffmpeg/bin",
"active_cmd": "play,random_play,playlocal,play_music_list,stop",
"exclude_dirs": "@eaDir",
"music_path_depth": 10,
"disable_httpauth": true,
"httpauth_username": "admin",
"httpauth_password": "admin",
"music_list_url": "",
"music_list_json": "",
"disable_download": false,
"use_music_api": false,
"log_file": "/tmp/xiaomusic.txt",
"fuzzy_match_cutoff": 0.6,
"enable_fuzzy_match": true,
"stop_tts_msg": "收到,再见",
"keywords_playlocal": "播放本地歌曲,本地播放歌曲",
"keywords_play": "播放歌曲,放歌曲",
"keywords_stop": "关机,暂停,停止,停止播放"
}

View File

@@ -1,6 +1,6 @@
[project]
name = "xiaomusic"
version = "0.1.77"
version = "0.1.84"
description = "Play Music with xiaomi AI speaker"
authors = [
{name = "涵曦", email = "im.hanxi@gmail.com"},
@@ -19,6 +19,12 @@ requires-python = ">=3.10"
readme = "README.md"
license = {text = "MIT"}
[project.urls]
Homepage = "https://github.com/hanxi/xiaomusic"
[project.scripts]
xiaomusic = "xiaomusic.cli:main"
[build-system]
requires = ["pdm-backend"]
build-backend = "pdm.backend"

View File

@@ -1 +1 @@
__version__ = "0.1.77"
__version__ = "0.1.84"

View File

@@ -1,9 +1,21 @@
import argparse
import asyncio
from xiaomusic import (
__version__,
)
from xiaomusic.config import Config
from xiaomusic.xiaomusic import XiaoMusic
LOGO = r"""
__ __ _ __ __ _
\ \/ / (_) __ _ ___ | \/ | _ _ ___ (_) ___
\ / | | / _` | / _ \ | |\/| | | | | | / __| | | / __|
/ \ | | | (_| | | (_) | | | | | | |_| | \__ \ | | | (__
/_/\_\ |_| \__,_| \___/ |_| |_| \__,_| |___/ |_| \___|
{}
"""
def main():
parser = argparse.ArgumentParser()
@@ -45,6 +57,8 @@ def main():
help="ffmpeg bin path",
)
print(LOGO.format(f"XiaoMusic v{__version__} by: github.com/hanxi"))
options = parser.parse_args()
config = Config.from_options(options)

View File

@@ -88,6 +88,13 @@ class Config:
enable_fuzzy_match: bool = (
os.getenv("XIAOMUSIC_ENABLE_FUZZY_MATCH", "true").lower() == "true"
)
stop_tts_msg: str = os.getenv("XIAOMUSIC_STOP_TTS_MSG", "收到,再见")
keywords_playlocal: str = os.getenv(
"XIAOMUSIC_KEYWORDS_PLAYLOCAL", "播放本地歌曲,本地播放歌曲"
)
keywords_play: str = os.getenv("XIAOMUSIC_KEYWORDS_PLAY", "播放歌曲,放歌曲")
keywords_stop: str = os.getenv("XIAOMUSIC_KEYWORDS_STOP", "关机,暂停,停止,停止播放")
def append_keyword(self, keys, action):
for key in keys.split(","):
@@ -98,14 +105,14 @@ class Config:
def __post_init__(self) -> None:
if self.proxy:
validate_proxy(self.proxy)
keywords_playlocal = os.getenv(
"XIAOMUSIC_KEYWORDS_PLAYLOCAL", "播放本地歌曲,本地播放歌曲"
)
self.append_keyword(keywords_playlocal, "playlocal")
keywords_play = os.getenv("XIAOMUSIC_KEYWORDS_PLAY", "播放歌曲,放歌曲")
self.append_keyword(keywords_play, "play")
keywords_stop = os.getenv("XIAOMUSIC_KEYWORDS_STOP", "关机,暂停,停止")
self.append_keyword(keywords_stop, "stop")
self.append_keyword(self.keywords_playlocal, "playlocal")
self.append_keyword(self.keywords_play, "play")
self.append_keyword(self.keywords_stop, "stop")
# 保存配置到 config-example.json 文件
# with open("config-example.json", "w") as f:
# data = asdict(self)
# json.dump(data, f, ensure_ascii=False, indent=4)
@classmethod
def from_options(cls, options: argparse.Namespace) -> Config:

View File

@@ -291,7 +291,7 @@ class XiaoMusic:
except Exception as e:
self.log.error(f"Execption {e}")
# 最大等8秒
sec = min(8, int(len(value) / 3.3))
sec = min(8, int(len(value) / 3))
await asyncio.sleep(sec)
self.log.debug(f"do_tts. cur_music:{self.cur_music}")
if self._playing and not self.is_downloading():
@@ -311,8 +311,8 @@ class XiaoMusic:
async def force_stop_xiaoai(self):
ret = await self.mina_service.player_pause(self.device_id)
self.log.debug(f"force_stop_xiaoai player_pause ret:{ret}")
ret = await self.mina_service.player_stop(self.device_id)
self.log.debug(f"force_stop_xiaoai player_stop ret:{ret}")
# ret = await self.mina_service.player_stop(self.device_id)
# self.log.debug(f"force_stop_xiaoai player_stop ret:{ret}")
# 是否在下载中
def is_downloading(self):
@@ -610,8 +610,26 @@ class XiaoMusic:
except Exception as e:
self.log.warning(f"执行出错 {str(e)}\n{traceback.format_exc()}")
# 检查是否匹配到完全一样的指令
def check_full_match_cmd(self, query, ctrl_panel):
if query in self.config.key_match_order:
opkey = query
opvalue = self.config.key_word_dict.get(opkey)
if ctrl_panel or self._playing:
return opvalue
else:
if not self.active_cmd or opvalue in self.active_cmd:
return opvalue
return None
# 匹配命令
def match_cmd(self, query, ctrl_panel):
# 优先处理完全匹配
opvalue = self.check_full_match_cmd(query, ctrl_panel)
if opvalue:
self.log.info(f"完全匹配指令. query:{query} opvalue:{opvalue}")
return (opvalue, None)
for opkey in self.config.key_match_order:
patternarg = rf"(.*){opkey}(.*)"
# 匹配参数
@@ -629,16 +647,14 @@ class XiaoMusic:
argafter,
)
oparg = argafter
if opkey in KEY_WORD_ARG_BEFORE_DICT:
oparg = argpre
opvalue = self.config.key_word_dict.get(opkey)
if not ctrl_panel and not self._playing:
if self.active_cmd and opvalue not in self.active_cmd:
self.log.debug(f"不在激活命令中 {opvalue}")
self.log.ifno(f"不在激活命令中 {opvalue}")
continue
if opkey in KEY_WORD_ARG_BEFORE_DICT:
oparg = argpre
self.log.info(
"匹配到指令. opkey:%s opvalue:%s oparg:%s", opkey, opvalue, oparg
)
self.log.info(f"匹配到指令. opkey:{opkey} opvalue:{opvalue} oparg:{oparg}")
return (opvalue, oparg)
if self._playing:
self.log.info("未匹配到指令,自动停止")
@@ -703,6 +719,7 @@ class XiaoMusic:
self.log.info(f"根据【{name}】找到歌曲【{real_name}")
return real_name
self.log.info(f"没找到歌曲【{name}")
return name
# 播放本地歌曲
async def playlocal(self, **kwargs):
@@ -759,7 +776,7 @@ class XiaoMusic:
await self.do_tts(f"本地不存在歌曲{name}")
return
await self.download(search_key, name)
self.log.info("正在下载中 %s", search_key + ":" + name)
self.log.info(f"正在下载中 {search_key} {name}")
await self.download_proc.wait()
# 把文件插入到播放列表里
self.add_download_music(name)
@@ -828,6 +845,7 @@ class XiaoMusic:
self.log.info(f"根据【{list_name}】找到播放列表【{real_name}")
list_name = real_name
self.log.info(f"没找到播放列表【{list_name}")
return list_name
# 播放一个播放列表
async def play_music_list(self, **kwargs):
@@ -853,7 +871,8 @@ class XiaoMusic:
async def stop(self, **kwargs):
self._playing = False
if kwargs.get("arg1", "") != "notts":
await self.do_tts("收到关机口令,再见")
if self.config.stop_tts_msg:
await self.do_tts(self.config.stop_tts_msg)
if self._next_timer:
self._next_timer.cancel()
self.log.info("定时器已取消")