歌曲目录支持子目录,优化随机播放列表 #18
This commit is contained in:
parent
2261b5ba53
commit
17d7f54c20
@ -66,8 +66,8 @@ KEY_MATCH_ORDER = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
SUPPORT_MUSIC_TYPE = [
|
SUPPORT_MUSIC_TYPE = [
|
||||||
"mp3",
|
".mp3",
|
||||||
"flac",
|
".flac",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -66,6 +66,8 @@ class XiaoMusic:
|
|||||||
self._next_timer = None
|
self._next_timer = None
|
||||||
self._timeout = 0
|
self._timeout = 0
|
||||||
self._volume = 50
|
self._volume = 50
|
||||||
|
self._all_music = {}
|
||||||
|
self._play_list = []
|
||||||
|
|
||||||
# 关机定时器
|
# 关机定时器
|
||||||
self._stop_timer = None
|
self._stop_timer = None
|
||||||
@ -319,42 +321,75 @@ class XiaoMusic:
|
|||||||
self.download_proc = await asyncio.create_subprocess_exec(*sbp_args)
|
self.download_proc = await asyncio.create_subprocess_exec(*sbp_args)
|
||||||
await self.do_tts(f"正在下载歌曲{name}")
|
await self.do_tts(f"正在下载歌曲{name}")
|
||||||
|
|
||||||
def get_filename(self, name):
|
|
||||||
filename = os.path.join(self.music_path, name)
|
|
||||||
return filename
|
|
||||||
|
|
||||||
# 本地是否存在歌曲
|
# 本地是否存在歌曲
|
||||||
def local_exist(self, name):
|
def get_filename(self, name):
|
||||||
for tp in SUPPORT_MUSIC_TYPE:
|
filename = self._all_music[name]
|
||||||
filename = self.get_filename(f"{name}.{tp}")
|
self.log.debug("try get_filename. filename:%s", filename)
|
||||||
self.log.debug("try local_exist. filename:%s", filename)
|
if os.path.exists(filename):
|
||||||
if os.path.exists(filename):
|
return filename
|
||||||
return filename
|
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
# 获取歌曲播放地址
|
# 获取歌曲播放地址
|
||||||
def get_file_url(self, filename):
|
def get_file_url(self, name):
|
||||||
self.log.debug("get_file_url. filename:%s", filename)
|
filename = self.get_filename(name)
|
||||||
|
self.log.debug("get_file_url. name:%s, filename:%s", name, filename)
|
||||||
encoded_name = urllib.parse.quote(filename)
|
encoded_name = urllib.parse.quote(filename)
|
||||||
return f"http://{self.hostname}:{self.port}/{encoded_name}"
|
return f"http://{self.hostname}:{self.port}/{encoded_name}"
|
||||||
|
|
||||||
# 随机获取一首音乐
|
# 递归获取目录下所有歌曲,生成随机播放列表
|
||||||
def random_music(self):
|
def gen_all_music_list(self):
|
||||||
files = os.listdir(self.music_path)
|
self._all_music = {}
|
||||||
# 过滤音乐文件
|
for root, dirs, filenames in os.walk(self.music_path):
|
||||||
music_files = []
|
for filename in filenames:
|
||||||
for file in files:
|
self.log.debug("gen_all_music_list. filename:%s", filename)
|
||||||
for tp in SUPPORT_MUSIC_TYPE:
|
# 过滤隐藏文件
|
||||||
if file.endswith(f".{tp}"):
|
if filename.startswith("."):
|
||||||
music_files.append(file)
|
continue
|
||||||
|
# 过滤非音乐文件
|
||||||
|
(name, extension) = os.path.splitext(filename)
|
||||||
|
self.log.debug(
|
||||||
|
"gen_all_music_list. filename:%s, name:%s, extension:%s",
|
||||||
|
filename,
|
||||||
|
name,
|
||||||
|
extension,
|
||||||
|
)
|
||||||
|
if extension not in SUPPORT_MUSIC_TYPE:
|
||||||
|
continue
|
||||||
|
|
||||||
if len(music_files) == 0:
|
# 歌曲名字相同会覆盖
|
||||||
|
self._all_music[name] = os.path.join(root, filename)
|
||||||
|
self._play_list = list(self._all_music.keys())
|
||||||
|
random.shuffle(self._play_list)
|
||||||
|
self.log.debug(self._all_music)
|
||||||
|
|
||||||
|
# 把下载的音乐加入播放列表
|
||||||
|
def add_download_music(self, name):
|
||||||
|
self._all_music[name] = os.path.join(self.music_path, f"{name}.mp3")
|
||||||
|
if name not in self._play_list:
|
||||||
|
self._play_list.append(name)
|
||||||
|
self.log.debug("add_music %s", name)
|
||||||
|
self.log.debug(self._play_list)
|
||||||
|
|
||||||
|
# 获取下一首
|
||||||
|
def get_next_music(self):
|
||||||
|
play_list_len = len(self._play_list)
|
||||||
|
if play_list_len == 0:
|
||||||
|
# 尝试重新生成一次播放列表
|
||||||
|
self.gen_all_music_list()
|
||||||
|
play_list_len = len(self._play_list)
|
||||||
|
if play_list_len == 0:
|
||||||
self.log.warning(f"没有随机到歌曲")
|
self.log.warning(f"没有随机到歌曲")
|
||||||
return ""
|
return ""
|
||||||
# 随机选择一个文件
|
# 随机选择一个文件
|
||||||
music_file = random.choice(music_files)
|
index = 0
|
||||||
(filename, extension) = os.path.splitext(music_file)
|
try:
|
||||||
self.log.info(f"随机到歌曲{filename}{extension}")
|
index = self._play_list.index(self.cur_music)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
next_index = index + 1
|
||||||
|
if next_index > play_list_len:
|
||||||
|
next_index = 0
|
||||||
|
filename = self._play_list[next_index]
|
||||||
return filename
|
return filename
|
||||||
|
|
||||||
# 获取文件播放时长
|
# 获取文件播放时长
|
||||||
@ -367,8 +402,9 @@ class XiaoMusic:
|
|||||||
|
|
||||||
# 设置下一首歌曲的播放定时器
|
# 设置下一首歌曲的播放定时器
|
||||||
def set_next_music_timeout(self):
|
def set_next_music_timeout(self):
|
||||||
sec = int(self.get_file_duration(self.cur_music))
|
filename = self.get_filename(self.cur_music)
|
||||||
self.log.info(f"歌曲{self.cur_music}的时长{sec}秒")
|
sec = int(self.get_file_duration(filename))
|
||||||
|
self.log.info(f"歌曲 {self.cur_music} : {filename} 的时长 {sec} 秒")
|
||||||
if self._next_timer:
|
if self._next_timer:
|
||||||
self._next_timer.cancel()
|
self._next_timer.cancel()
|
||||||
self.log.info(f"定时器已取消")
|
self.log.info(f"定时器已取消")
|
||||||
@ -449,15 +485,17 @@ class XiaoMusic:
|
|||||||
await self.play_next()
|
await self.play_next()
|
||||||
return
|
return
|
||||||
|
|
||||||
filename = self.local_exist(name)
|
filename = self.get_filename(name)
|
||||||
if len(filename) <= 0:
|
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.add_download_music(name)
|
||||||
|
|
||||||
self.cur_music = filename
|
self.cur_music = name
|
||||||
url = self.get_file_url(filename)
|
self.log.info("cur_music %s", self.cur_music)
|
||||||
|
url = self.get_file_url(name)
|
||||||
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)
|
||||||
@ -468,10 +506,10 @@ class XiaoMusic:
|
|||||||
# 下一首
|
# 下一首
|
||||||
async def play_next(self, **kwargs):
|
async def play_next(self, **kwargs):
|
||||||
self.log.info("下一首")
|
self.log.info("下一首")
|
||||||
(name, _) = os.path.splitext(os.path.basename(self.cur_music))
|
name = self.cur_music
|
||||||
self.log.debug("play_next. name:%s, cur_music:%s", name, self.cur_music)
|
self.log.debug("play_next. name:%s, cur_music:%s", name, self.cur_music)
|
||||||
if self.play_type == PLAY_TYPE_ALL or name == "":
|
if self.play_type == PLAY_TYPE_ALL or name == "":
|
||||||
name = self.random_music()
|
name = self.get_next_music()
|
||||||
if name == "":
|
if name == "":
|
||||||
await self.do_tts(f"本地没有歌曲")
|
await self.do_tts(f"本地没有歌曲")
|
||||||
return
|
return
|
||||||
@ -491,6 +529,8 @@ class XiaoMusic:
|
|||||||
async def random_play(self, **kwargs):
|
async def random_play(self, **kwargs):
|
||||||
self.play_type = PLAY_TYPE_ALL
|
self.play_type = PLAY_TYPE_ALL
|
||||||
await self.do_tts(f"已经设置为全部循环并随机播放")
|
await self.do_tts(f"已经设置为全部循环并随机播放")
|
||||||
|
# 重新生成随机播放列表
|
||||||
|
self.gen_all_music_list()
|
||||||
await self.play_next()
|
await self.play_next()
|
||||||
|
|
||||||
async def stop(self, **kwargs):
|
async def stop(self, **kwargs):
|
||||||
|
Loading…
Reference in New Issue
Block a user