From 7c9576874bce0905ee35268fc6f61b182f64956d Mon Sep 17 00:00:00 2001 From: "Gao, Ruiyuan" <905370712@qq.com> Date: Mon, 23 Sep 2024 02:31:28 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=20tags=20=E7=BC=93?= =?UTF-8?q?=E5=AD=98=20(#193)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + config-example.json | 1 + xiaomusic/config.py | 11 ++++++++++ xiaomusic/xiaomusic.py | 50 +++++++++++++++++++++++++++++++++++++++--- 4 files changed, 60 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f0cbec3..30b697f 100644 --- a/README.md +++ b/README.md @@ -235,6 +235,7 @@ docker build -t xiaomusic . - XIAOMUSIC_HTTPAUTH_USERNAME 配置 web 控制台用户,对应后台的 【web控制台账户】 - XIAOMUSIC_HTTPAUTH_PASSWORD 配置 web 控制台密码,对应后台的 【web控制台密码】 - XIAOMUSIC_CONF_PATH 用来存放配置文件的目录,对应后台的 【配置文件目录】,记得把目录映射到主机,默认为 `/app/config` ,具体见 +- XIAOMUSIC_TAG_CACHE_DIR 用来音乐 tag 缓存,默认为空(不缓存) - XIAOMUSIC_DISABLE_DOWNLOAD 设为 true 时关闭下载功能,对应后台的 【关闭下载功能】,见 - XIAOMUSIC_USE_MUSIC_API 设为 true 时使用 player_play_music 接口播放音乐,对应后台的 【触屏版兼容模式】,用于兼容不能播放的型号,如果发现需要设置这个选项的时候请告知我加一下设备型号,方便以后不用设置。 见 - XIAOMUSIC_KEYWORDS_PLAY 用来播放歌曲的口令前缀,对应后台的 【播放歌曲口令】,默认是 "播放歌曲,放歌曲" ,可以用英文逗号分割配置多个 diff --git a/config-example.json b/config-example.json index ebee903..b24b940 100644 --- a/config-example.json +++ b/config-example.json @@ -7,6 +7,7 @@ "music_path": "music", "download_path": "", "conf_path": null, + "tag_cache_dir": null, "hostname": "192.168.2.5", "port": 8090, "public_port": 0, diff --git a/xiaomusic/config.py b/xiaomusic/config.py index 163280c..1349b6f 100644 --- a/xiaomusic/config.py +++ b/xiaomusic/config.py @@ -84,6 +84,7 @@ class Config: ) # 只能是music目录下的子目录 download_path: str = os.getenv("XIAOMUSIC_DOWNLOAD_PATH", "music/download") conf_path: str = os.getenv("XIAOMUSIC_CONF_PATH", "conf") + tag_cache_dir: str = os.getenv("XIAOMUSIC_TAG_CACHE_DIR", None) hostname: str = os.getenv("XIAOMUSIC_HOSTNAME", "192.168.2.5") port: int = int(os.getenv("XIAOMUSIC_PORT", "8090")) # 监听端口 public_port: int = int(os.getenv("XIAOMUSIC_PUBLIC_PORT", 0)) # 歌曲访问端口 @@ -246,3 +247,13 @@ class Config: os.makedirs(self.conf_path) filename = os.path.join(self.conf_path, "setting.json") return filename + + @property + def tag_cache_path(self): + if self.tag_cache_dir is None: + return None + + if not os.path.exists(self.tag_cache_dir): + os.makedirs(self.tag_cache_dir) + filename = os.path.join(self.tag_cache_dir, "tag_cache.json") + return filename diff --git a/xiaomusic/xiaomusic.py b/xiaomusic/xiaomusic.py index 8e9fe6f..4281a66 100644 --- a/xiaomusic/xiaomusic.py +++ b/xiaomusic/xiaomusic.py @@ -437,10 +437,47 @@ class XiaoMusic: encoded_name = urllib.parse.quote(filename) return f"{self.hostname}:{self.public_port}/music/{encoded_name}" + # 给前端调用 + def refresh_music_tag(self): + filename = self.config.tag_cache_path + if filename is not None: + # 清空 cache + with open(filename, "w", encoding="utf-8") as f: + json.dump({}, f, ensure_ascii=False, indent=2) + self.log.info(f"刷新:已清空 tag cache") + else: + self.log.info(f"刷新:tag cache 未启用") + #TODO: 优化性能? + self._gen_all_music_list() + self.log.debug(f"刷新:已重建 tag cache") + + def try_load_from_tag_cache(self) -> dict: + filename = self.config.tag_cache_path + tag_cache = {} + if filename is not None: + if os.path.exists(filename): + with open(filename, "r", encoding="utf-8") as f: + tag_cache = json.load(f) + self.log.info(f"已从【{filename}】加载 tag cache") + else: + self.log.info(f"【{filename}】tag cache 已启用,但文件不存在") + else: + self.log.info(f"加载:tag cache 未启用") + return tag_cache + + def try_save_tag_cache(self): + filename = self.config.tag_cache_path + if filename is not None: + with open(filename, "w", encoding="utf-8") as f: + json.dump(self.all_music_tags, f, ensure_ascii=False, indent=2) + self.log.info(f"保存:tag cache 已保存到【{filename}】") + else: + self.log.info(f"保存:tag cache 未启用") + # 获取目录下所有歌曲,生成随机播放列表 def _gen_all_music_list(self): self.all_music = {} - self.all_music_tags = {} + self.all_music_tags = self.try_load_from_tag_cache() all_music_by_dir = {} local_musics = traverse_music_directory( self.music_path, @@ -464,7 +501,10 @@ class XiaoMusic: filename = os.path.basename(file) (name, _) = os.path.splitext(filename) self.all_music[name] = file - self.all_music_tags[name] = get_audio_metadata(file) + if name not in self.all_music_tags: + self.all_music_tags[name] = { + k: str(v) for k, v in get_audio_metadata(file).items()} + print(f"加载 {name} tag") all_music_by_dir[dir_name][name] = True self.log.debug(f"_gen_all_music_list {name}:{dir_name}:{file}") @@ -505,6 +545,9 @@ class XiaoMusic: if not (v.startswith("http") or v.startswith("https")): self._extra_index_search[v] = k + # 刷新 tag cache + self.try_save_tag_cache() + def _append_custom_play_list(self): if not self.config.custom_play_list_json: return @@ -537,7 +580,8 @@ class XiaoMusic: continue self.all_music[name] = url # TODO: 网络歌曲获取歌曲额外信息 - # self.all_music_tags[name] = get_audio_metadata(url) + # if name not in self.all_music_tags: + # self.all_music_tags[name] = get_audio_metadata(url) one_music_list.append(name) # 处理电台列表