1
0
mirror of https://github.com/hanxi/xiaomusic.git synced 2025-12-07 15:02:55 +08:00

Compare commits

..

20 Commits

Author SHA1 Message Date
涵曦
e4efa0d879 bump: version 0.3.35 → 0.3.36 2024-09-19 07:08:47 +08:00
涵曦
2ebc0f11d2 build: update static version 2024-09-19 07:08:46 +08:00
52fisher
180f28800e feat: Pure 主题更新 (#178)
* 使用hash路由以改进后端服务器无法返回正确* 路由的结果
* 更新关于界面
* 播放列表界面优化
* 增加欢迎页的功能说明
2024-09-19 06:48:19 +08:00
涵曦
7f5692d6cd feat: 支持配置获取对话记录间隔时间 #169 2024-09-19 00:45:08 +08:00
涵曦
8d7b5337eb feat: 允许在后台设置监听端口 2024-09-18 23:32:00 +08:00
hui
dcbf4330be fix: 修复开启继续播放时歌曲播放不完整问题 (#177) 2024-09-18 20:14:55 +08:00
涵曦
2e53f20d80 Update README.md 2024-09-18 12:01:02 +08:00
涵曦
2914ddcc36 bump: version 0.3.34 → 0.3.35 2024-09-18 07:17:12 +08:00
涵曦
442756e3cc build: update static version 2024-09-18 07:17:11 +08:00
涵曦
b55a2a67c9 feat: 允许跨域访问 #172 2024-09-18 06:57:49 +08:00
52fisher
09545c7015 fix: 修复 Pure 主题白屏无法打开的问题 (#176)
* 修复 白屏无法打开的问题
* 增加清空已缓存的设置和拉取最新设置功能
* 增加刷新页面按钮及说明
2024-09-18 06:48:38 +08:00
涵曦
1f82efa2a1 bump: version 0.3.33 → 0.3.34 2024-09-18 01:08:13 +08:00
涵曦
e509052242 build: update static version 2024-09-18 01:08:12 +08:00
涵曦
046cdade5a fix: 主页适配移动端 2024-09-18 00:32:53 +08:00
涵曦
7f8e639b86 Update README.md 2024-09-17 19:46:02 +08:00
涵曦
bfbd36f7f9 feat: 新增 pure 主题 vue + elementUI (#172)
* allow CROS

* feat: vue + elementUI

* fixed 设置后打开主页白屏的问题

* fixed 设置中获取device_list失败的问题

* Update Theme

* Update Theme

---------

Co-authored-by: 52fisher <32198215+52fisher@users.noreply.github.com>
Co-authored-by: fisher <i@qnmlgb.trade>
2024-09-17 19:42:58 +08:00
涵曦
c5d623547c Update README.md 2024-09-17 01:53:22 +08:00
涵曦
31c61675bf refactor: 优化代码:输入框处理抖动问题,网页播放修改实现方式 see #166 2024-09-17 01:17:38 +08:00
涵曦
9900bd9ee9 fix: 修复网页播放点击后没有关闭旧声音的问题 #166 2024-09-16 22:35:36 +08:00
涵曦
8459494c61 fix: 修复单曲循环的情况下歌曲不在当前播放列表时失效的情况 2024-09-16 21:43:49 +08:00
25 changed files with 345 additions and 119 deletions

2
.gitignore vendored
View File

@@ -25,7 +25,7 @@ share/python-wheels/
.installed.cfg
*.egg
MANIFEST
*_bak/
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.

View File

@@ -1,3 +1,41 @@
## v0.3.36 (2024-09-19)
### Feat
- Pure 主题更新 (#178)
- 支持配置获取对话记录间隔时间 #169
- 允许在后台设置监听端口
### Fix
- 修复开启继续播放时歌曲播放不完整问题 (#177)
## v0.3.35 (2024-09-18)
### Feat
- 允许跨域访问 #172
### Fix
- 修复 Pure 主题白屏无法打开的问题 (#176)
## v0.3.34 (2024-09-18)
### Feat
- 新增 pure 主题 vue + elementUI (#172)
### Fix
- 主页适配移动端
- 修复网页播放点击后没有关闭旧声音的问题 #166
- 修复单曲循环的情况下歌曲不在当前播放列表时失效的情况
### Refactor
- 优化代码:输入框处理抖动问题,网页播放修改实现方式 see #166
## v0.3.33 (2024-09-15)
### Feat

View File

@@ -210,8 +210,6 @@ docker build -t xiaomusic .
采用新的设置页面之后,没有必须在启动前配置的环境变量了,除非是改默认的 8090 端口才需要配置环境变量。
后台的
## 网络歌单功能
可以配置一个 json 格式的歌单,支持电台和歌曲,也可以直接用别人分享的链接,同时配备了 m3u 文件格式转换工具,可以很方便的把 m3u 电台文件转换成网络歌单格式的 json 文件,具体用法见 <https://github.com/hanxi/xiaomusic/issues/78>
@@ -261,9 +259,11 @@ docker build -t xiaomusic .
- [PDM](https://pdm.fming.dev/latest/)
- [xiaogpt](https://github.com/yihong0618/xiaogpt)
- [MiService](https://github.com/yihong0618/MiService)
- [实现原理](https://github.com/yihong0618/gitblog/issues/258)
- [yt-dlp](https://github.com/yt-dlp/yt-dlp)
- [awesome-xiaoai](https://github.com/zzz6519003/awesome-xiaoai)
- [微信小程序: XIAO晓音](https://github.com/F-loat/xiaoplayer)
- [pure 主题 xiaomusicUI](https://github.com/52fisher/xiaomusicUI)
- 所有帮忙调试和测试的朋友
- 所有反馈问题和建议的朋友

View File

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

View File

@@ -16,13 +16,12 @@ def get_html_files(directory):
def update_html_version(html_files, version):
"""
更新HTML文件中所有以 /static/ 开头的CSS和JS文件引用的版本号。
更新HTML文件中所有以 ./ 开头的CSS和JS文件引用的版本号。
:param html_files: 需要更新的HTML文件路径的列表。
:param version: 新的版本号字符串。
"""
pattern = re.compile(r'(/static/.*(css|js))\?version=[^"]*"')
# pattern = re.compile(r'(/static/.*html)\?version=[^"]*"')
pattern = re.compile(r'(\./.*(css|js))\?version=[^"]*"')
for html_file in html_files:
if not html_file.exists():
@@ -48,7 +47,7 @@ if __name__ == "__main__":
t = str(int(time.time()))
# 指定目录
html_directory = "xiaomusic/static" # 修改为实际的HTML文件目录路径
html_directory = "xiaomusic/static/default" # 修改为实际的HTML文件目录路径
# 获取HTML文件列表
html_files_to_update = get_html_files(html_directory)

View File

@@ -1 +1 @@
__version__ = "0.3.33"
__version__ = "0.3.36"

View File

@@ -148,6 +148,7 @@ class Config:
continue_play: bool = (
os.getenv("XIAOMUSIC_CONTINUE_PLAY", "false").lower() == "true"
)
pull_ask_sec: int = int(os.getenv("XIAOMUSIC_PULL_ASK_SEC", "1"))
def append_keyword(self, keys, action):
for key in keys.split(","):

View File

@@ -13,6 +13,7 @@ from typing import Annotated
import aiofiles
from fastapi import Depends, FastAPI, HTTPException, Request, status
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import StreamingResponse
from fastapi.security import HTTPBasic, HTTPBasicCredentials
from fastapi.staticfiles import StaticFiles
@@ -75,6 +76,14 @@ app = FastAPI(
version=__version__,
)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # 允许访问的源
allow_credentials=False, # 支持 cookie
allow_methods=["*"], # 允许使用的请求方法
allow_headers=["*"], # 允许携带的 Headers
)
def reset_http_server():
log.info(f"disable_httpauth:{config.disable_httpauth}")

View File

@@ -147,8 +147,7 @@ $(function(){
$.get(`/musicinfo?name=${music_name}`, function(data, status) {
console.log(data);
if (data.ret == "OK") {
const music = new Audio(data.url);
music.play();
$('audio').attr('src',data.url);
}
});
});
@@ -244,8 +243,15 @@ $(function(){
});
}
// 监听输入框的输入事件
$("#music-name").on('input', function() {
// 监听输入框的输入事件
function debounce(func, delay) {
let timeout;
return function(...args) {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, args), delay);
};
}
$("#music-name").on('input', debounce(function() {
var inputValue = $(this).val();
// 发送Ajax请求
$.ajax({
@@ -264,7 +270,7 @@ $(function(){
});
}
});
});
},300));
function get_playing_music() {
$.get(`/playingmusic?did=${did}`, function(data, status) {
@@ -294,7 +300,4 @@ $(function(){
var remainingSeconds =Math.floor(seconds % 60);
return `${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`;
}
});
});

View File

@@ -5,9 +5,9 @@
<meta name="viewport" content="width=device-width">
<title>Debug For XiaoMusic</title>
<link rel="stylesheet" type="text/css" href="/static/style.css?version=1726415744">
<link rel="stylesheet" type="text/css" href="./style.css?version=1726700926">
<script src="https://unpkg.com/vconsole@latest/dist/vconsole.min.js"></script>
<script src="/static/jquery-3.7.1.min.js?version=1726415744"></script>
<script src="./jquery-3.7.1.min.js?version=1726700926"></script>
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-Z09NC1K7ZW"></script>

View File

@@ -0,0 +1,92 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width">
<title>小爱音箱操控面板</title>
<script src="./jquery-3.7.1.min.js?version=1726700926"></script>
<script src="./app.js?version=1726700926"></script>
<link rel="stylesheet" type="text/css" href="./style.css?version=1726700926">
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-Z09NC1K7ZW"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments)};
gtag('js', new Date());
gtag('config', 'G-Z09NC1K7ZW');
</script>
<!--
<script src="https://unpkg.com/vconsole@latest/dist/vconsole.min.js"></script>
<script>
var vConsole = new window.VConsole();
</script>
-->
</head>
<body>
<h2>小爱音箱操控面板
(<a id="version" href="https://github.com/hanxi/xiaomusic/blob/main/CHANGELOG.md">
版本未知
</a>)
</h2>
<hr>
<div class="rows">
<select id="did">
</select>
</div>
<div id="cmds">
<a class="button" href="./setting.html">设置</a>
</div>
<hr>
<div style="margin: 20px;">
<div style="display: flex; align-items: center;">
<svg 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 class="rows">
<datalist id="autocomplete-list"></datalist>
<input id="music-name" type="text" placeholder="请输入搜索关键词(如:MV高清版 周杰伦 七里香)" list="autocomplete-list"></input>
<input id="music-filename" type="text" placeholder="请输入保存为的文件名称(如:周杰伦七里香)"></input>
<div style="display: flex; align-items: center">
<progress id="progress" value="0" max="100" style="width: 270px"></progress>
<div id="play-time" style="margin-left: 10px">00:00/00:00</div>
</div>
<div>
<button id="play">播放</button>
<div id="playering-music" class="text"></div>
</div>
</div>
<hr>
<div class="rows">
<label for="music_list">播放列表:</label>
<select id="music_list"></select>
<label for="music_name">歌曲:</label>
<select id="music_name"></select>
<div>
<button id="play_music_list">播放列表歌曲</button>
<button id="del_music">删除选中歌曲</button>
<button id="web_play">网页播放</button>
</div>
<div class="play_pannel">
<audio autoplay controls src=""></audio>
</div>
</div>
<hr>
<div class="rows">
<input id="music-url" type="text" value="https://lhttp.qtfm.cn/live/4915/64k.mp3"></input>
<button id="playurl">播放链接</button>
</div>
<footer>
<p>Powered by <a href="https://github.com/hanxi/xiaomusic" target="_blank">xiaomusic</a></p>
</footer>
</body>
</html>

View File

@@ -4,7 +4,7 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<title>M3U to JSON Converter</title>
<link rel="stylesheet" type="text/css" href="/static/style.css?version=1726415744">
<link rel="stylesheet" type="text/css" href="./style.css?version=1726700926">
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-Z09NC1K7ZW"></script>

View File

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 47 KiB

View File

@@ -3,9 +3,9 @@
<head>
<meta name="viewport" content="width=device-width">
<title>小爱音箱操控面板</title>
<script src="/static/jquery-3.7.1.min.js?version=1726415744"></script>
<script src="/static/setting.js?version=1726415744"></script>
<link rel="stylesheet" type="text/css" href="/static/style.css?version=1726415744">
<script src="./jquery-3.7.1.min.js?version=1726700926"></script>
<script src="./setting.js?version=1726700926"></script>
<link rel="stylesheet" type="text/css" href="./style.css?version=1726700926">
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-Z09NC1K7ZW"></script>
@@ -142,15 +142,21 @@ var vConsole = new window.VConsole();
<option value="false" selected>false</option>
</select>
<label for="continue_play">启用继续播放(可能导致兼容性问题及歌曲无法完整播放):</label>
<label for="continue_play">启用继续播放(可能导致兼容性问题):</label>
<select id="continue_play">
<option value="true">true</option>
<option value="false" selected>false</option>
</select>
<label for="port">监听端口(修改后需要重启):</label>
<input id="port" type="number" value="8090"></input>
<label for="public_port">外网访问端口(0表示跟监听端口一致):</label>
<input id="public_port" type="number" value="0"></input>
<label for="pull_ask_sec">获取对话记录间隔(秒):</label>
<input id="pull_ask_sec" type="number" value="1"></input>
<label for="delay_sec">下一首歌延迟播放秒数:</label>
<input id="delay_sec" type="number" value="3"></input>
@@ -180,15 +186,15 @@ var vConsole = new window.VConsole();
<a class="button" href="/downloadlog" download="xiaomusic.txt">下载日志文件</a>
<button onclick="location.href='/docs';">查看接口文档</button>
<a class="button" href="/static/m3u.html" target="_blank">m3u文件转换</a>
<a class="button" href="./m3u.html" target="_blank">m3u文件转换</a>
<hr>
<a class="button" href="/static/debug.html" target="_blank">调试工具</a>
<a class="button" href="./debug.html" target="_blank">调试工具</a>
<a class="button" href="https://afdian.com/a/imhanxi" target="_blank">💰 爱发电</a>
<a class="button" href="https://github.com/hanxi/xiaomusic" target="_blank">点个 Star ⭐</a>
<div class="rows">
<img class="qrcode" src="/static/qrcode.png" alt="请涵曦喝奶茶🧋">
<img class="qrcode" src="./qrcode.png" alt="请涵曦喝奶茶🧋">
</div>
<footer>
<p>Powered by <a href="https://github.com/hanxi/xiaomusic" target="_blank">xiaomusic</a></p>

View File

@@ -1,89 +1,61 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width">
<title>小爱音箱操控面板</title>
<script src="/static/jquery-3.7.1.min.js?version=1726415744"></script>
<script src="/static/app.js?version=1726415744"></script>
<link rel="stylesheet" type="text/css" href="/static/style.css?version=1726415744">
<html lang="en">
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-Z09NC1K7ZW"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments)};
gtag('js', new Date());
gtag('config', 'G-Z09NC1K7ZW');
</script>
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>小爱音箱操控面板</title>
<!--
<script src="https://unpkg.com/vconsole@latest/dist/vconsole.min.js"></script>
<script>
var vConsole = new window.VConsole();
</script>
-->
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-Z09NC1K7ZW"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments)};
gtag('js', new Date());
gtag('config', 'G-Z09NC1K7ZW');
</script>
</head>
<body>
<h2>小爱音箱操控面板
(<a id="version" href="https://github.com/hanxi/xiaomusic/blob/main/CHANGELOG.md">
版本未知
</a>)
</h2>
<hr>
</head>
<div class="rows">
<select id="did">
</select>
<body>
<div class="container_wrapper">
<div class="logo">
<img src="/static/xiaoai.png" alt="">
</div>
<div id="cmds">
<a class="button" href="/static/setting.html">设置</a>
<div class="desc">
<h1>谁家灯火夜通明</h1>
<p class="call">小爱同学?</p>
<p class="answer">哎,我在</p>
</div>
<hr>
<div style="margin: 20px;">
<div style="display: flex; align-items: center;">
<svg 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 class="rows">
<datalist id="autocomplete-list"></datalist>
<input id="music-name" type="text" placeholder="请输入搜索关键词(如:MV高清版 周杰伦 七里香)" list="autocomplete-list"></input>
<input id="music-filename" type="text" placeholder="请输入保存为的文件名称(如:周杰伦七里香)"></input>
<div style="display: flex; align-items: center">
<progress id="progress" value="0" max="100" style="width: 270px"></progress>
<div id="play-time" style="margin-left: 10px">00:00/00:00</div>
</div>
<div>
<button id="play">播放</button>
<div id="playering-music" class="text"></div>
</div>
<div class="options">
<!-- 选择主题 /static/[theme] -->
<a href="/static/default/index.html" class="href">默认主题</a>
<a href="/static/pure/index.html" class="href">Pure主题</a>
<a href="https://afdian.com/a/imhanxi" target="_blank">爱发电</a>
<a href="https://github.com/hanxi/xiaomusic" target="_blank">GitHub</a>
</div>
</div>
<footer>
power by <a href="https://github.com/hanxi/xiaomusic">XiaoMusic</a>
</footer>
<style>
@font-face{ font-family: "得意黑 斜体"; font-weight: 400; src: url("//at.alicdn.com/wf/webfont/603VmyqiyGMz/gJk2ny0v51vn.woff2") format("woff2"), url("//at.alicdn.com/wf/webfont/603VmyqiyGMz/e2C1wSBHH86h.woff") format("woff"); font-display: swap;} @font-face{ font-family: "阿里妈妈数黑体 Bold"; font-weight: 700; src: url("//at.alicdn.com/wf/webfont/603VmyqiyGMz/4DWYdFK3dz5J.woff2") format("woff2"), url("//at.alicdn.com/wf/webfont/603VmyqiyGMz/V7EBEKlNSdxC.woff") format("woff"); font-display: swap;} body{ background-color: rgb(47, 44, 67); height: 100%; overflow: hidden;}
.container_wrapper{display: flex; justify-content: space-around; align-items: center; flex-wrap: wrap; height: 90vh; cursor: default;}
h1{ font-weight: bold; color: #a2a9af; max-width: 600px; font-family: '得意黑 斜体', 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode', Geneva, Verdana, sans-serif; font-size: 2.5em; border-bottom: 1px solid #a2a9af;}
.container_wrapper .logo img{ width: 140px; height: auto; filter: drop-shadow(10px 10px 10px rgba(0, 0, 0, 0.5));}
.desc{ text-align: center; color: #fff; margin: auto 30px; backdrop-filter: blur(5px);}
.desc p{ font-size: 1.2em; margin: 0; padding: 0; font-family: '阿里妈妈数黑体 Bold'; font-weight: 800;}
p.call{ letter-spacing: 0.4em; font-size: 2.2em; line-height: 1.5; font-style: normal;}
p.answer{ letter-spacing: 0.23em; line-height: 1.5; font-style: normal; color: #a2a9af; margin-top: 10px;}
.desc p::before, .desc p::after{ font-family: 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode', Geneva, Verdana, sans-serif; font-size: 1.5em; color: #4c5870;}
.desc p::before{ content: "“";} .desc p::after{ content: "”";}
.options{ display: flex; flex-direction: column;}
.options a{ color: #a2a9af; text-decoration: none; font-size: 1.1em; position: relative; display: inline; margin: 10px auto;}
.options a::before{ content: ''; position: absolute; bottom: 0; left: 0; right: 0; height: 2px; background-color: #ebedec; transform-origin: bottom right; transform: scaleX(0); transition: transform 0.3s ease;}
.options a:hover::before{ transform-origin: bottom left; transform: scaleX(1);} .options a:hover{ color:#ebedec;}
footer{ display: flex; justify-content: center; color: #4c5870;} footer a{ color:inherit; text-decoration: none; margin: auto 10px;}
</style>
</body>
<hr>
<div class="rows">
<label for="music_list">播放列表:</label>
<select id="music_list"></select>
<label for="music_name">歌曲:</label>
<select id="music_name"></select>
<div>
<button id="play_music_list">播放列表歌曲</button>
<button id="del_music">删除选中歌曲</button>
<button id="web_play">网页播放</button>
</div>
</div>
<hr>
<div class="rows">
<input id="music-url" type="text" value="https://lhttp.qtfm.cn/live/4915/64k.mp3"></input>
<button id="playurl">播放链接</button>
</div>
<footer>
<p>Powered by <a href="https://github.com/hanxi/xiaomusic" target="_blank">xiaomusic</a></p>
</footer>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -0,0 +1,26 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/static/pure/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>小爱音箱操控面板</title>
<script type="module" crossorigin src="/static/pure/assets/index-C9BDvfvm.js"></script>
<link rel="stylesheet" crossorigin href="/static/pure/assets/index-DUo8JY-R.css">
</head>
<body>
<div id="app"></div>
<!-- 作者的统计代码 -->
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-Z09NC1K7ZW"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() { dataLayer.push(arguments) };
gtag('js', new Date());
gtag('config', 'G-Z09NC1K7ZW');
</script>
</body>
</html>

BIN
xiaomusic/static/xiaoai.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 528 KiB

View File

@@ -158,9 +158,9 @@ class XiaoMusic:
async def poll_latest_ask(self):
async with ClientSession() as session:
while True:
# self.log.debug(
# f"Listening new message, timestamp: {self.last_timestamp}"
# )
self.log.debug(
f"Listening new message, timestamp: {self.last_timestamp}"
)
session._cookie_jar = self.cookie_jar
# 拉取所有音箱的对话记录
@@ -171,13 +171,17 @@ class XiaoMusic:
await asyncio.gather(*tasks)
start = time.perf_counter()
# self.log.debug(f"Polling_event, timestamp: {self.last_timestamp}")
await self.polling_event.wait()
if (d := time.perf_counter() - start) < 1:
# sleep to avoid too many request
# self.log.debug(f"Sleep {d}, timestamp: {self.last_timestamp}")
await asyncio.sleep(1 - d)
await self.analytics.send_daily_event()
if self.config.pull_ask_sec <= 1:
if (d := time.perf_counter() - start) < 1:
await asyncio.sleep(1 - d)
else:
sleep_sec = 0
while True:
await asyncio.sleep(1)
sleep_sec = sleep_sec + 1
if sleep_sec >= self.config.pull_ask_sec:
break
async def init_all_data(self, session):
await self.login_miboy(session)
@@ -520,8 +524,17 @@ class XiaoMusic:
except Exception as e:
self.log.exception(f"Execption {e}")
async def analytics_task_daily(self):
while True:
await self.analytics.send_daily_event()
await asyncio.sleep(3600)
async def run_forever(self):
await 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
await self.init_all_data(session)
@@ -536,6 +549,11 @@ class XiaoMusic:
query = new_record.get("query", "").strip()
did = new_record.get("did", "").strip()
await self.do_check_cmd(did, query, False)
answers = new_record.get("answers", [{}])
if answers:
answer = answers[0].get("tts", {}).get("text", "").strip()
await self.reset_timer_when_answer(len(answer), did)
self.log.debug(f"query:{query} did:{did} answer:{answer}")
# 匹配命令
async def do_check_cmd(self, did="", query="", ctrl_panel=True, **kwargs):
@@ -552,6 +570,10 @@ class XiaoMusic:
except Exception as e:
self.log.exception(f"Execption {e}")
# 重置计时器
async def reset_timer_when_answer(self, answer_length, did):
await self.devices[did].reset_timer_when_answer(answer_length)
def append_running_task(self, task):
self.running_task.append(task)
@@ -938,6 +960,7 @@ class XiaoMusicDevice:
# 播放进度
self._start_time = 0
self._duration = 0
self._paused_time = 0
# 关机定时器
self._stop_timer = None
@@ -948,9 +971,9 @@ class XiaoMusicDevice:
return self.device.cur_music
def get_offset_duration(self):
if not self._playing:
if not self.isplaying():
return -1, -1
offset = time.time() - self._start_time
offset = time.time() - self._start_time - self._paused_time
duration = self._duration
return offset, duration
@@ -1005,7 +1028,9 @@ class XiaoMusicDevice:
self.device.play_type == PLAY_TYPE_ALL
or self.device.play_type == PLAY_TYPE_RND
or name == ""
or (name not in self._play_list)
or (
(name not in self._play_list) and self.device.play_type != PLAY_TYPE_ONE
)
):
name = self.get_next_music()
self.log.info(f"_play_next. name:{name}, cur_music:{self.get_cur_music()}")
@@ -1082,6 +1107,7 @@ class XiaoMusicDevice:
sec = sec + self.config.delay_sec
self._start_time = time.time()
self._duration = sec
self._paused_time = 0
await self.set_next_music_timeout(sec)
self.xiaomusic.save_cur_config()
@@ -1333,6 +1359,19 @@ class XiaoMusicDevice:
self.log.error(f"_get_audio_id {e}")
return str(audio_id)
# 重置计时器
async def reset_timer_when_answer(self, answer_length):
if not (self.isplaying() and self.config.continue_play):
return
pause_time = answer_length / 5 + 1
offset, duration = self.get_offset_duration()
self._paused_time += pause_time
new_time = duration - offset + pause_time
await self.set_next_music_timeout(new_time)
self.log.info(
f"reset_timer 延长定时器. answer_length:{answer_length} pause_time:{pause_time}"
)
# 设置下一首歌曲的播放定时器
async def set_next_music_timeout(self, sec):
self.cancel_next_timer()