mirror of
https://github.com/hanxi/xiaomusic.git
synced 2026-05-07 00:15:59 +08:00
fix: 支持代理 m3u8 格式链接 close #711
This commit is contained in:
@@ -289,8 +289,13 @@ async def get_picture(request: Request, file_path: str, key: str = "", code: str
|
||||
|
||||
|
||||
@router.get("/proxy", summary="基于正常下载逻辑的代理接口")
|
||||
async def proxy(urlb64: str):
|
||||
"""代理接口"""
|
||||
async def proxy(urlb64: str, radio: bool = None):
|
||||
"""代理接口
|
||||
|
||||
Args:
|
||||
urlb64: Base64编码的URL
|
||||
radio: 是否为电台直播流。None时自动识别,True强制使用长超时,False强制使用短超时
|
||||
"""
|
||||
try:
|
||||
# 将Base64编码的URL解码为字符串
|
||||
url_bytes = base64.b64decode(urlb64)
|
||||
@@ -310,9 +315,14 @@ async def proxy(urlb64: str):
|
||||
status_code=400, detail="无效的URL格式"
|
||||
) from invalid_url_exc
|
||||
|
||||
# 创建会话并确保关闭
|
||||
# 直播流使用更长的超时时间(24小时),普通文件使用10分钟
|
||||
timeout_seconds = 86400 if radio else 600
|
||||
log.info(
|
||||
f"代理模式: {'电台直播流' if radio else '普通文件'}, 超时时间: {timeout_seconds}秒"
|
||||
)
|
||||
|
||||
session = aiohttp.ClientSession(
|
||||
timeout=aiohttp.ClientTimeout(total=600),
|
||||
timeout=aiohttp.ClientTimeout(total=timeout_seconds, sock_read=300),
|
||||
connector=aiohttp.TCPConnector(ssl=True),
|
||||
)
|
||||
|
||||
@@ -363,8 +373,22 @@ async def proxy(urlb64: str):
|
||||
finally:
|
||||
await close_session()
|
||||
|
||||
# 提取文件名
|
||||
filename = parsed_url.path.split("/")[-1].split("?")[0] or "output.mp3"
|
||||
# 提取文件名,根据URL扩展名智能判断
|
||||
filename = parsed_url.path.split("/")[-1].split("?")[0]
|
||||
if not filename:
|
||||
# 根据URL扩展名或Content-Type设置默认文件名
|
||||
path_lower = parsed_url.path.lower()
|
||||
if path_lower.endswith(".m3u8"):
|
||||
filename = "stream.m3u8"
|
||||
elif path_lower.endswith(".m3u"):
|
||||
filename = "stream.m3u"
|
||||
else:
|
||||
# 根据Content-Type推断
|
||||
content_type = resp.headers.get("Content-Type", "").lower()
|
||||
if "mpegurl" in content_type or "m3u8" in content_type:
|
||||
filename = "stream.m3u8"
|
||||
else:
|
||||
filename = "output.mp3"
|
||||
|
||||
return StreamingResponse(
|
||||
stream_generator(),
|
||||
|
||||
@@ -1023,7 +1023,9 @@ class MusicLibrary:
|
||||
|
||||
# 是否需要代理
|
||||
if self.config.web_music_proxy or url.startswith("self://"):
|
||||
proxy_url = self._get_proxy_url(url)
|
||||
# 判断是否为电台,传入 radio 参数
|
||||
is_radio = self.is_web_radio_music(name)
|
||||
proxy_url = self._get_proxy_url(url, radio=is_radio)
|
||||
return proxy_url, url
|
||||
|
||||
return url, None
|
||||
@@ -1044,11 +1046,12 @@ class MusicLibrary:
|
||||
self.log.error(f"_get_url_from_api use api fail. name:{name}, url:{url}")
|
||||
return url
|
||||
|
||||
def _get_proxy_url(self, origin_url):
|
||||
def _get_proxy_url(self, origin_url, radio=None):
|
||||
"""获取代理URL
|
||||
|
||||
Args:
|
||||
origin_url: 原始URL
|
||||
radio: 是否为电台直播流,None时不传参数
|
||||
|
||||
Returns:
|
||||
str: 代理URL
|
||||
@@ -1057,6 +1060,8 @@ class MusicLibrary:
|
||||
proxy_url = (
|
||||
f"{self.config.hostname}:{self.config.public_port}/proxy?urlb64={urlb64}"
|
||||
)
|
||||
if radio is not None:
|
||||
proxy_url += f"&radio={'true' if radio else 'false'}"
|
||||
self.log.info(f"Using proxy url: {proxy_url}")
|
||||
return proxy_url
|
||||
|
||||
|
||||
Reference in New Issue
Block a user