1
0
mirror of https://github.com/hanxi/xiaomusic.git synced 2026-06-01 12:15:48 +08:00

fix: 修复LX在未换源解析完成的情况跳歌 (#887)

This commit is contained in:
ALITTLESEEDX
2026-05-26 14:10:35 +08:00
committed by GitHub
parent f0676d3cab
commit 08cafae7f9
2 changed files with 43 additions and 4 deletions

View File

@@ -35,6 +35,9 @@ from xiaomusic.utils.text_utils import (
parse_ordinal_suffix,
)
DEFAULT_PROXY_PROBE_TIMEOUT = 3.0
LX_SERVER_PROXY_PROBE_TIMEOUT = 8.0
class XiaoMusicDevice:
"""设备播放控制类
@@ -510,7 +513,9 @@ class XiaoMusicDevice:
self.log.info(f"cur_music {self.get_cur_music()}")
# 获取该歌单下的播放 URL
url, _ = await self.xiaomusic.music_library.get_music_url(name, cur_playlist)
url, origin_url = await self.xiaomusic.music_library.get_music_url(
name, cur_playlist
)
# 1. 命中硬盘级负向缓存墓碑url为空的秒切拦截
if not url:
@@ -536,11 +541,15 @@ class XiaoMusicDevice:
# 3. 极速探路器:帮小爱吃下所有的 404/401 炸弹
if not is_system_or_tts and url and url.startswith("http") and "/proxy/" in url:
self.log.info(f"极速探路启动,触发后端代理解析: {url}")
probe_timeout = self._get_proxy_probe_timeout(origin_url)
is_lx_server_music = probe_timeout == LX_SERVER_PROXY_PROBE_TIMEOUT
self.log.info(
"极速探路启动,触发后端代理解析: "
f"timeout={probe_timeout}s lx_server={is_lx_server_music} url={url}"
)
is_url_ok = False
try:
# 给了 3.0 秒超时,让本地解析服务有足够时间反应
timeout = aiohttp.ClientTimeout(total=3.0)
timeout = aiohttp.ClientTimeout(total=probe_timeout)
async with aiohttp.ClientSession(timeout=timeout) as session:
async with session.get(url) as resp:
# 如果 music.py 报了 404在这里会直接被抓个正着
@@ -657,6 +666,14 @@ class XiaoMusicDevice:
if sec > 20:
await self.prefetch_next_song(20)
def _get_proxy_probe_timeout(self, origin_url):
try:
if self.xiaomusic.music_library.is_lx_server_proxy_url(origin_url):
return LX_SERVER_PROXY_PROBE_TIMEOUT
except Exception as e:
self.log.debug(f"判断 LX Server 探路超时失败: {e}")
return DEFAULT_PROXY_PROBE_TIMEOUT
async def do_tts(self, value):
"""执行TTS文字转语音"""
self.log.info(f"try do_tts value:{value}")

View File

@@ -834,6 +834,28 @@ class MusicLibrary:
self.log.debug(f"提取缓存路径失败: {e}")
return ""
def is_lx_server_proxy_url(self, origin_url: str) -> bool:
"""判断原始 plugin-url 是否来自 LX Server 搜索结果。"""
if not origin_url or not origin_url.startswith("self:///api/proxy/plugin-url"):
return False
try:
query = urlparse(origin_url).query
params = parse_qs(query)
datab64 = params.get("data", [""])[0].replace(" ", "+")
if not datab64:
return False
missing_padding = len(datab64) % 4
if missing_padding:
datab64 += "=" * (4 - missing_padding)
payload = json.loads(base64.b64decode(datab64).decode("utf-8"))
return isinstance(payload, dict) and isinstance(payload.get("_raw"), dict)
except Exception as e:
self.log.debug(f"判断 LX Server 代理 URL 失败: {e}")
return False
async def get_music_duration(self, name: str, playlist_name: str = None) -> float:
"""获取歌曲时长