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

Compare commits

...

9 Commits

Author SHA1 Message Date
涵曦
c68fa71d24 new version v0.1.13 2024-02-02 22:11:54 +08:00
涵曦
24b46729e3 优化控制面板,声音设置改为进度条 2024-02-02 22:10:55 +08:00
涵曦
13336cd02c 支持配置歌曲下载源 #12 2024-02-02 20:56:18 +08:00
涵曦
67be9125d8 Update README.md 2024-02-01 23:40:30 +08:00
涵曦
1b0a6dd7f4 Update README.md 2024-01-31 09:17:13 +08:00
涵曦
11053ecfa7 Update README.md 2024-01-31 09:03:38 +08:00
涵曦
0736cb0fb7 new version v0.1.12 2024-01-30 08:21:48 +08:00
涵曦
2acb668101 fix: set volume failed 2024-01-30 08:21:31 +08:00
涵曦
32fb0e9548 add script to update version 2024-01-29 23:28:31 +08:00
8 changed files with 116 additions and 63 deletions

View File

@@ -51,12 +51,44 @@ docker run -e MI_USER=<your-xiaomi-account> -e MI_PASS=<your-xiaomi-password> -e
- 注意端口必须映射为与容器内一致XIAOMUSIC_HOSTNAME 需要设置为宿主机的 IP 地址,否则小爱无法正常播放。
- 可以把 /app/music 目录映射到本地,用于保存下载的歌曲。
XIAOMUSIC_PROXY参数格式参考 yt-dlp 文档说明:
```
Use the specified HTTP/HTTPS/SOCKS proxy. To
enable SOCKS proxy, specify a proper scheme,
e.g. socks5://user:pass@127.0.0.1:1080/.
Pass in an empty string (--proxy "") for
direct connection
```
### 本地编译Docker Image
```shell
docker build -t xiaomusic .
```
### docker compose 示例
```yaml
version: '3'
services:
xiaomusic:
image: hanxi/xiaomusic
container_name: xiaomusic
restart: unless-stopped
ports:
- 8090:8090
volumes:
- ./music:/app/music
environment:
- MI_USER: '小米账号'
- MI_PASS: '小米密码'
- MI_DID: 00000
- MI_HARDWARE: 'L07A'
- XIAOMUSIC_PROXY: 'http://192.168.2.5:8080'
- XIAOMUSIC_HOSTNAME: '192.168.2.5'
```
## 简易的控制面板
浏览器进入 <http://192.168.2.5:8090>
@@ -71,3 +103,7 @@ docker build -t xiaomusic .
- [xiaogpt](https://github.com/yihong0618/xiaogpt)
- [yt-dlp](https://github.com/yt-dlp/yt-dlp)
## Star History
[![Star History Chart](https://api.star-history.com/svg?repos=hanxi/xiaomusic&type=Date)](https://star-history.com/#hanxi/xiaomusic&Date)

View File

@@ -4,4 +4,4 @@ git diff
git add ./pyproject.toml
git commit -m "new version v$version"
git tag v$version
#git push --tags
git push -u origin main --tags

View File

@@ -1,6 +1,6 @@
[project]
name = "xiaomusic"
version = "0.1.11"
version = "0.1.13"
description = "Play Music with xiaomi AI speaker"
authors = [
{name = "涵曦", email = "im.hanxi@gmail.com"},

View File

@@ -31,7 +31,7 @@ HARDWARE_COMMAND_DICT = {
# add more here
}
DEFAULT_COMMAND = ("5-1", "5-5")
DEFAULT_COMMAND = ("5-1", "5-5", "2-1")
KEY_WORD_DICT = {
"播放歌曲": "play",
@@ -79,12 +79,15 @@ class Config:
mi_did: str = os.getenv("MI_DID", "")
mute_xiaoai: bool = True
cookie: str = ""
use_command: bool = True
use_command: bool = False
verbose: bool = False
music_path: str = os.getenv("XIAOMUSIC_MUSIC_PATH", "music")
hostname: str = os.getenv("XIAOMUSIC_HOSTNAME", "192.168.2.5")
port: int = int(os.getenv("XIAOMUSIC_PORT", "8090"))
proxy: str | None = os.getenv("XIAOMUSIC_PROXY", None)
search_prefix: str = os.getenv(
"XIAOMUSIC_SEARCH", "ytsearch:"
) # "bilisearch:" or "ytsearch:"
def __post_init__(self) -> None:
if self.proxy:

View File

@@ -22,6 +22,13 @@ def allcmds():
return KEY_WORD_DICT
@app.route("/getvolume")
def getvolume():
return {
"volume": xiaomusic.get_volume(),
}
@app.route("/", methods=["GET"])
def redirect_to_index():
return send_from_directory("static", "index.html")

View File

@@ -1,69 +1,55 @@
$(function(){
// 拉取所有可操作的命令
$.get("/allcmds", function(data, status) {
console.log(data, status);
$container=$("#cmds");
append_op_button_name("下一首");
append_op_button_name("全部循环");
append_op_button_name("关机");
append_op_button_name("单曲循环");
append_op_button_name("播放歌曲");
append_op_button_name("随机播放");
$container=$("#cmds");
// 遍历数据
for (const [key, value] of Object.entries(data)) {
if (key != "分钟后关机"
&& key != "放歌曲"
&& key != "停止播放"
&& !key.includes("#")) {
append_op_button_name(key);
}
}
$container.append($("<hr>"));
$container.append($("<hr>"));
append_op_button_name("10分钟后关机");
append_op_button_name("30分钟后关机");
append_op_button_name("60分钟后关机");
append_op_button_name("10分钟后关机");
append_op_button_name("30分钟后关机");
append_op_button_name("60分钟后关机");
$container.append($("<hr>"));
append_op_button_volume("声音设为5", 5);
append_op_button_volume("声音设为10", 10);
append_op_button_volume("声音设为30", 30);
append_op_button_volume("声音设为50", 50);
append_op_button_volume("声音设为80", 80);
append_op_button_volume("声音设为100", 100);
// 拉取声音
$.get("/getvolume", function(data, status) {
console.log(data, status, data["volume"]);
$("#volume").val(data.volume);
});
function append_op_button_volume(name, value) {
append_op_button(name, "set_volume#"+value);
}
function append_op_button_name(name) {
append_op_button(name, name);
}
function append_op_button(name, cmd) {
// 创建按钮
const $button = $("<button>");
$button.text(name);
$button.attr("type", "button");
// 创建按钮
const $button = $("<button>");
$button.text(name);
$button.attr("type", "button");
// 设置按钮点击事件
$button.on("click", () => {
// 发起post请求
$.ajax({
type: "POST",
url: "/cmd",
contentType: "application/json",
data: JSON.stringify({"cmd": cmd}),
success: () => {
// 请求成功时执行的操作
},
error: () => {
// 请求失败时执行的操作
}
});
});
// 设置按钮点击事件
$button.on("click", () => {
sendcmd(cmd);
});
// 添加按钮到容器
$container.append($button);
// 添加按钮到容器
$container.append($button);
}
$("#play").on("click", () => {
name = $("#music-name").val();
let cmd = "播放歌曲"+name;
sendcmd(cmd);
});
$("#volume").on('input', function () {
var value = $(this).val();
sendcmd("set_volume#"+value);
});
function sendcmd(cmd) {
$.ajax({
type: "POST",
url: "/cmd",
@@ -76,5 +62,5 @@ $(function(){
// 请求失败时执行的操作
}
});
});
}
});

View File

@@ -10,13 +10,18 @@
margin: 10px;
width: 100px;
height: 50px;
border: none; /* 无边框 */
color: white; /* 白色文字 */
text-align: center; /* 文字居中 */
text-decoration: none; /* 无下划线 */
display: inline-block; /* 行内块元素 */
border-radius: 10px; /* 圆角 */
background-color: #008CBA; /* 蓝色 */
border: none;
color: white;
text-align: center;
text-decoration: none;
display: inline-block;
border-radius: 10px;
background-color: #008CBA;
}
button:active {
font-weight:bold;
background-color: #007CBA;
transform: translateY(2px);
}
input {
margin: 10px;
@@ -31,6 +36,13 @@
<div id="cmds">
</div>
<hr>
<div style="margin-left: 20px;">
<div style="display: flex; align-items: center;">
<svg class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" fill="#8e43e7" style="height: 48px; width: 48px;"><path d="M550.826667 154.666667a47.786667 47.786667 0 0 0-19.84 4.48L298.666667 298.666667H186.453333A80 80 0 0 0 106.666667 378.453333v267.093334A80 80 0 0 0 186.453333 725.333333H298.666667l232.32 139.52a47.786667 47.786667 0 0 0 19.84 4.48A46.506667 46.506667 0 0 0 597.333333 822.826667V201.173333a46.506667 46.506667 0 0 0-46.506666-46.506666zM554.666667 822.826667c0 3.413333-3.84 3.84-3.84 3.84L320 688.853333l-9.6-6.186666H186.453333A37.12 37.12 0 0 1 149.333333 645.546667V378.453333A37.12 37.12 0 0 1 186.453333 341.333333h123.946667l10.24-6.186666 229.546667-137.6s3.84 0 3.84 3.84zM667.52 346.026667a21.333333 21.333333 0 0 0 0 30.293333 192 192 0 0 1 0 271.36 21.333333 21.333333 0 0 0 0 30.293333 21.333333 21.333333 0 0 0 30.293333 0 234.666667 234.666667 0 0 0 0-331.946666 21.333333 21.333333 0 0 0-30.293333 0z"></path><path d="M804.48 219.52a21.333333 21.333333 0 0 0-30.293333 30.293333 370.986667 370.986667 0 0 1 0 524.373334 21.333333 21.333333 0 0 0 0 30.293333 21.333333 21.333333 0 0 0 30.293333 0 414.08 414.08 0 0 0 0-584.96z"></path></svg>
<input id="volume" type="range"></input>
</div>
</div>
<hr>
<div>
<input id="music-name" type="text" placeholder="请输入歌曲名称"></input>
<button id="play">播放</button>

View File

@@ -56,6 +56,7 @@ class XiaoMusic:
self.hostname = config.hostname
self.port = config.port
self.proxy = config.proxy
self.search_prefix = config.search_prefix
# 下载对象
self.download_proc = None
@@ -64,6 +65,7 @@ class XiaoMusic:
self.cur_music = ""
self._next_timer = None
self._timeout = 0
self._volume = 50
# 关机定时器
self._stop_timer = None
@@ -237,16 +239,19 @@ class XiaoMusic:
await self.wait_for_tts_finish()
async def do_set_volume(self, value):
value = int(value)
if not self.config.use_command:
try:
self.log.debug("do_set_volume not use_command value:%d", value)
await self.mina_service.player_set_volume(self.device_id, value)
except Exception:
pass
else:
self.log.debug("do_set_volume use_command value:%d", value)
await miio_command(
self.miio_service,
self.config.mi_did,
f"{self.config.volume_command} {value}",
f"{self.config.volume_command}=#{value}",
)
async def wait_for_tts_finish(self):
@@ -295,7 +300,7 @@ class XiaoMusic:
sbp_args = (
"yt-dlp",
f"ytsearch:{name}",
f"{self.search_prefix}{name}",
"-x",
"--audio-format",
"mp3",
@@ -512,4 +517,8 @@ class XiaoMusic:
async def set_volume(self, **kwargs):
value = kwargs["arg1"]
await self.do_set_volume(value)
self._volume = int(value)
self.log.info(f"声音设置为{value}")
def get_volume(self):
return self._volume