支持flac格式的本地文件
This commit is contained in:
parent
63eb0c22cb
commit
8e8a605816
@ -37,12 +37,18 @@ KEY_WORD_DICT = {
|
|||||||
"播放歌曲": "play",
|
"播放歌曲": "play",
|
||||||
"放歌曲": "play",
|
"放歌曲": "play",
|
||||||
"下一首": "play_next",
|
"下一首": "play_next",
|
||||||
"单曲循环":"set_play_type_one",
|
"单曲循环": "set_play_type_one",
|
||||||
"全部循环":"set_play_type_all",
|
"全部循环": "set_play_type_all",
|
||||||
"关机":"stop",
|
"关机": "stop",
|
||||||
"停止播放":"stop",
|
"停止播放": "stop",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SUPPORT_MUSIC_TYPE = [
|
||||||
|
"mp3",
|
||||||
|
"flac",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Config:
|
class Config:
|
||||||
hardware: str = os.getenv("MI_HARDWARE", "L07A")
|
hardware: str = os.getenv("MI_HARDWARE", "L07A")
|
||||||
|
@ -29,6 +29,7 @@ from xiaomusic.config import (
|
|||||||
COOKIE_TEMPLATE,
|
COOKIE_TEMPLATE,
|
||||||
LATEST_ASK_API,
|
LATEST_ASK_API,
|
||||||
KEY_WORD_DICT,
|
KEY_WORD_DICT,
|
||||||
|
SUPPORT_MUSIC_TYPE,
|
||||||
Config,
|
Config,
|
||||||
)
|
)
|
||||||
from xiaomusic.utils import (
|
from xiaomusic.utils import (
|
||||||
@ -38,8 +39,9 @@ from xiaomusic.utils import (
|
|||||||
|
|
||||||
EOF = object()
|
EOF = object()
|
||||||
|
|
||||||
PLAY_TYPE_ONE = 0 # 单曲循环
|
PLAY_TYPE_ONE = 0 # 单曲循环
|
||||||
PLAY_TYPE_ALL = 1 # 全部循环
|
PLAY_TYPE_ALL = 1 # 全部循环
|
||||||
|
|
||||||
|
|
||||||
class ThreadedHTTPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
|
class ThreadedHTTPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
|
||||||
pass
|
pass
|
||||||
@ -61,6 +63,7 @@ class HTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
|
|||||||
# ignore this or TODO find out why the error later
|
# ignore this or TODO find out why the error later
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class XiaoMusic:
|
class XiaoMusic:
|
||||||
def __init__(self, config: Config):
|
def __init__(self, config: Config):
|
||||||
self.config = config
|
self.config = config
|
||||||
@ -286,8 +289,7 @@ class XiaoMusic:
|
|||||||
def is_downloading(self):
|
def is_downloading(self):
|
||||||
if not self.download_proc:
|
if not self.download_proc:
|
||||||
return False
|
return False
|
||||||
if self.download_proc.returncode != None \
|
if self.download_proc.returncode != None and self.download_proc.returncode < 0:
|
||||||
and self.download_proc.returncode < 0:
|
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -300,11 +302,18 @@ class XiaoMusic:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
sbp_args = (
|
sbp_args = (
|
||||||
"yt-dlp", f"ytsearch:{name}",
|
"yt-dlp",
|
||||||
"-x", "--audio-format", "mp3",
|
f"ytsearch:{name}",
|
||||||
"--paths", self.music_path,
|
"-x",
|
||||||
"-o", f"{name}.mp3",
|
"--audio-format",
|
||||||
"--ffmpeg-location", "./ffmpeg/bin")
|
"mp3",
|
||||||
|
"--paths",
|
||||||
|
self.music_path,
|
||||||
|
"-o",
|
||||||
|
f"{name}.mp3",
|
||||||
|
"--ffmpeg-location",
|
||||||
|
"./ffmpeg/bin",
|
||||||
|
)
|
||||||
|
|
||||||
if self.proxy:
|
if self.proxy:
|
||||||
sbp_args += ("--proxy", f"{self.proxy}")
|
sbp_args += ("--proxy", f"{self.proxy}")
|
||||||
@ -313,43 +322,53 @@ class XiaoMusic:
|
|||||||
await self.do_tts(f"正在下载歌曲{name}")
|
await self.do_tts(f"正在下载歌曲{name}")
|
||||||
|
|
||||||
def get_filename(self, name):
|
def get_filename(self, name):
|
||||||
filename = os.path.join(self.music_path, f"{name}.mp3")
|
filename = os.path.join(self.music_path, name)
|
||||||
return filename
|
return filename
|
||||||
|
|
||||||
# 本地是否存在歌曲
|
# 本地是否存在歌曲
|
||||||
def local_exist(self, name):
|
def local_exist(self, name):
|
||||||
filename = self.get_filename(name)
|
for tp in SUPPORT_MUSIC_TYPE:
|
||||||
self.log.debug("local_exist. filename:%s", filename)
|
filename = self.get_filename(f"{name}.{tp}")
|
||||||
return os.path.exists(filename)
|
self.log.debug("try local_exist. filename:%s", filename)
|
||||||
|
if os.path.exists(filename):
|
||||||
|
return filename
|
||||||
|
return ""
|
||||||
|
|
||||||
# 获取歌曲播放地址
|
# 获取歌曲播放地址
|
||||||
def get_file_url(self, name):
|
def get_file_url(self, filename):
|
||||||
encoded_name = urllib.parse.quote(os.path.basename(name))
|
encoded_name = urllib.parse.quote(os.path.basename(filename))
|
||||||
return f"http://{self.hostname}:{self.port}/{encoded_name}.mp3"
|
return f"http://{self.hostname}:{self.port}/{encoded_name}"
|
||||||
|
|
||||||
# 随机获取一首音乐
|
# 随机获取一首音乐
|
||||||
def random_music(self):
|
def random_music(self):
|
||||||
files = os.listdir(self.music_path)
|
files = os.listdir(self.music_path)
|
||||||
# 过滤 mp3 文件
|
# 过滤音乐文件
|
||||||
mp3_files = [file for file in files if file.endswith(".mp3")]
|
music_files = []
|
||||||
if len(mp3_files) == 0:
|
for file in files:
|
||||||
|
for tp in SUPPORT_MUSIC_TYPE:
|
||||||
|
if file.endswith(f".{tp}"):
|
||||||
|
music_files.append(file)
|
||||||
|
|
||||||
|
if len(music_files) == 0:
|
||||||
self.log.warning(f"没有随机到歌曲")
|
self.log.warning(f"没有随机到歌曲")
|
||||||
return ""
|
return ""
|
||||||
# 随机选择一个文件
|
# 随机选择一个文件
|
||||||
mp3_file = random.choice(mp3_files)
|
music_file = random.choice(music_files)
|
||||||
name = mp3_file[:-4]
|
(filename, extension) = os.path.splitext(music_file)
|
||||||
self.log.info(f"随机到歌曲{name}")
|
self.log.info(f"随机到歌曲{filename}.{extension}")
|
||||||
return name
|
return filename
|
||||||
|
|
||||||
# 获取mp3文件播放时长
|
# 获取文件播放时长
|
||||||
def get_mp3_duration(self, name):
|
def get_file_duration(self, filename):
|
||||||
filename = self.get_filename(name)
|
# 获取音频文件对象
|
||||||
audio = mutagen.mp3.MP3(filename)
|
audio = mutagen.File(filename)
|
||||||
return audio.info.length
|
# 获取播放时长
|
||||||
|
duration = audio.info.length
|
||||||
|
return duration
|
||||||
|
|
||||||
# 设置下一首歌曲的播放定时器
|
# 设置下一首歌曲的播放定时器
|
||||||
def set_next_music_timeout(self):
|
def set_next_music_timeout(self):
|
||||||
sec = int(self.get_mp3_duration(self.cur_music))
|
sec = int(self.get_file_duration(self.cur_music))
|
||||||
self.log.info(f"歌曲{self.cur_music}的时长{sec}秒")
|
self.log.info(f"歌曲{self.cur_music}的时长{sec}秒")
|
||||||
if self._next_timer:
|
if self._next_timer:
|
||||||
self._next_timer.cancel()
|
self._next_timer.cancel()
|
||||||
@ -372,7 +391,9 @@ class XiaoMusic:
|
|||||||
await self.init_all_data(session)
|
await self.init_all_data(session)
|
||||||
task = asyncio.create_task(self.poll_latest_ask())
|
task = asyncio.create_task(self.poll_latest_ask())
|
||||||
assert task is not None # to keep the reference to task, do not remove this
|
assert task is not None # to keep the reference to task, do not remove this
|
||||||
self.log.info(f"Running xiaomusic now, 用`{'/'.join(KEY_WORD_DICT.keys())}`开头来控制")
|
self.log.info(
|
||||||
|
f"Running xiaomusic now, 用`{'/'.join(KEY_WORD_DICT.keys())}`开头来控制"
|
||||||
|
)
|
||||||
while True:
|
while True:
|
||||||
self.polling_event.set()
|
self.polling_event.set()
|
||||||
await self.new_record_event.wait()
|
await self.new_record_event.wait()
|
||||||
@ -396,12 +417,12 @@ class XiaoMusic:
|
|||||||
|
|
||||||
opkey = match.groups()[0]
|
opkey = match.groups()[0]
|
||||||
opvalue = KEY_WORD_DICT[opkey]
|
opvalue = KEY_WORD_DICT[opkey]
|
||||||
oparg = query[len(opkey):]
|
oparg = query[len(opkey) :]
|
||||||
self.log.info("收到指令:%s %s", opkey, oparg)
|
self.log.info("收到指令:%s %s", opkey, oparg)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
func = getattr(self, opvalue)
|
func = getattr(self, opvalue)
|
||||||
await func(name = oparg)
|
await func(name=oparg)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.log.warning(f"执行出错 {str(e)}\n{traceback.format_exc()}")
|
self.log.warning(f"执行出错 {str(e)}\n{traceback.format_exc()}")
|
||||||
|
|
||||||
@ -413,13 +434,15 @@ class XiaoMusic:
|
|||||||
return
|
return
|
||||||
|
|
||||||
await self.do_tts(f"即将播放{name}")
|
await self.do_tts(f"即将播放{name}")
|
||||||
if not self.local_exist(name):
|
filename = self.local_exist(name)
|
||||||
|
if len(filename) <= 0:
|
||||||
await self.download(name)
|
await self.download(name)
|
||||||
self.log.info("正在下载中 %s", name)
|
self.log.info("正在下载中 %s", name)
|
||||||
|
filename = self.get_filename(f"{name}.mp3")
|
||||||
await self.download_proc.wait()
|
await self.download_proc.wait()
|
||||||
|
|
||||||
self.cur_music = name
|
self.cur_music = filename
|
||||||
url = self.get_file_url(name)
|
url = self.get_file_url(filename)
|
||||||
self.log.info("播放 %s", url)
|
self.log.info("播放 %s", url)
|
||||||
await self.stop_if_xiaoai_is_playing()
|
await self.stop_if_xiaoai_is_playing()
|
||||||
await self.mina_service.play_by_url(self.device_id, url)
|
await self.mina_service.play_by_url(self.device_id, url)
|
||||||
|
Loading…
Reference in New Issue
Block a user