diff --git a/Dockerfile b/Dockerfile index a70aac0..aedcd4b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,9 +12,6 @@ COPY install_dependencies.sh . RUN bash install_dependencies.sh FROM python:3.10-slim -RUN pip install pydub -RUN python3 -m venv /app/.venv -RUN /app/.venv/bin/pip install pydub WORKDIR /app COPY --from=builder /app/.venv /app/.venv COPY --from=builder /app/ffmpeg /app/ffmpeg diff --git a/config-example.json b/config-example.json index 36c11e2..ebee903 100644 --- a/config-example.json +++ b/config-example.json @@ -12,7 +12,7 @@ "public_port": 0, "proxy": null, "search_prefix": "bilisearch:", - "ffmpeg_location": "./ffmpeg/bin/ffmpeg", + "ffmpeg_location": "./ffmpeg/bin", "active_cmd": "play,set_random_play,playlocal,play_music_list,stop", "exclude_dirs": "@eaDir", "music_path_depth": 10, diff --git a/xiaomusic/cli.py b/xiaomusic/cli.py index f34d842..a8fea21 100644 --- a/xiaomusic/cli.py +++ b/xiaomusic/cli.py @@ -3,7 +3,6 @@ import argparse import json import os import signal -import subprocess import uvicorn diff --git a/xiaomusic/config.py b/xiaomusic/config.py index 33544d9..1c28500 100644 --- a/xiaomusic/config.py +++ b/xiaomusic/config.py @@ -83,7 +83,7 @@ class Config: search_prefix: str = os.getenv( "XIAOMUSIC_SEARCH", "bilisearch:" ) # "bilisearch:" or "ytsearch:" - ffmpeg_location: str = os.getenv("XIAOMUSIC_FFMPEG_LOCATION", "./ffmpeg/bin/ffmpeg") + ffmpeg_location: str = os.getenv("XIAOMUSIC_FFMPEG_LOCATION", "./ffmpeg/bin") active_cmd: str = os.getenv( "XIAOMUSIC_ACTIVE_CMD", "play,set_random_play,playlocal,play_music_list,stop" ) @@ -136,9 +136,7 @@ class Config: remove_id3tag: bool = ( os.getenv("XIAOMUSIC_REMOVE_ID3TAG", "false").lower() == "true" ) - convert_to_mp3: bool = ( - os.getenv("CONVERT_TO_MP3", "false").lower() == "true" - ) + convert_to_mp3: bool = os.getenv("CONVERT_TO_MP3", "false").lower() == "true" delay_sec: int = int(os.getenv("XIAOMUSIC_DELAY_SEC", 3)) # 下一首歌延迟播放秒数 def append_keyword(self, keys, action): diff --git a/xiaomusic/convert_to_mp3.py b/xiaomusic/convert_to_mp3.py deleted file mode 100644 index 959f3b3..0000000 --- a/xiaomusic/convert_to_mp3.py +++ /dev/null @@ -1,59 +0,0 @@ -# convert_to_mp3.py -import os -import subprocess -import tempfile -from pydub import AudioSegment -from pydub.playback import play -from xiaomusic.config import Config - -class Convert_To_MP3: - def __init__(self, config: Config): - self.config = config - self.music_path = self.config.music_path - self.ffmpeg_location = self.config.ffmpeg_location - - @staticmethod - def convert_to_mp3(input_file: str, ffmpeg_location: str, music_path: str) -> str: - """ - Convert the music file to MP3 format and return the path of the temporary MP3 file. - """ - # 指定临时文件的目录为 music_path 目录下的 tmp 文件夹 - temp_dir = os.path.join(music_path, 'tmp') - if not os.path.exists(temp_dir): - os.makedirs(temp_dir) # 确保目录存在 - - temp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.mp3', dir=temp_dir) - temp_file.close() - temp_file_path = temp_file.name - - command = [ - ffmpeg_location, - '-i', input_file, - '-f', 'mp3', - '-y', - temp_file_path - ] - - try: - subprocess.run(command, check=True) - except subprocess.CalledProcessError as e: - print(f"Error during conversion: {e}") - return None - - return temp_file_path - - @classmethod - def convert_and_play(cls, input_file: str, ffmpeg_location: str): - """ - 将音乐文件转码为 MP3 格式,播放,然后不删除临时文件,依赖于 xiaomusic 启动时的清理逻辑。 - """ - temp_mp3_file = cls.convert_to_mp3(input_file, ffmpeg_location, cls.music_path) - if temp_mp3_file: - try: - # 假设 xiaomusic_playmusic 是一个播放 MP3 文件的函数 - cls.xiaomusic.xiaomusic_playmusic(temp_mp3_file) - finally: - # 此处不再删除临时文件,依赖 xiaomusic 的清理逻辑 - pass - else: - print("Conversion failed") \ No newline at end of file diff --git a/xiaomusic/utils.py b/xiaomusic/utils.py index aa3b512..6fcc693 100644 --- a/xiaomusic/utils.py +++ b/xiaomusic/utils.py @@ -11,8 +11,8 @@ import random import re import shutil import string -import tempfile import subprocess +import tempfile from collections.abc import AsyncIterator from http.cookies import SimpleCookie from urllib.parse import urlparse @@ -331,3 +331,35 @@ def remove_id3_tags(file_path): change = True return change + + +def convert_file_to_mp3(input_file: str, ffmpeg_location: str, music_path: str) -> str: + """ + Convert the music file to MP3 format and return the path of the temporary MP3 file. + """ + # 指定临时文件的目录为 music_path 目录下的 tmp 文件夹 + temp_dir = os.path.join(music_path, "tmp") + if not os.path.exists(temp_dir): + os.makedirs(temp_dir) # 确保目录存在 + + out_file_name = os.path.splitext(os.path.basename(input_file))[0] + out_file_path = os.path.join(temp_dir, f"{out_file_name}.mp3") + + command = [ + os.path.join(ffmpeg_location, "ffmpeg"), + "-i", + input_file, + "-f", + "mp3", + "-y", + out_file_path, + ] + + try: + subprocess.run(command, check=True) + except subprocess.CalledProcessError as e: + print(f"Error during conversion: {e}") + return None + + relative_path = os.path.relpath(out_file_path, music_path) + return relative_path diff --git a/xiaomusic/xiaomusic.py b/xiaomusic/xiaomusic.py index 140667c..83af352 100644 --- a/xiaomusic/xiaomusic.py +++ b/xiaomusic/xiaomusic.py @@ -32,6 +32,7 @@ from xiaomusic.const import ( ) from xiaomusic.plugin import PluginManager from xiaomusic.utils import ( + convert_file_to_mp3, custom_sort_key, deepcopy_data_no_sensitive_info, find_best_match, @@ -45,8 +46,6 @@ from xiaomusic.utils import ( traverse_music_directory, ) -from xiaomusic.convert_to_mp3 import Convert_To_MP3 - class XiaoMusic: def __init__(self, config: Config): @@ -66,12 +65,6 @@ class XiaoMusic: self.devices = {} # key 为 did self.running_task = [] - # 在程序启动时调用清理函数 - self.cleanup_old_temp_files() - - self.convert_to_mp3 = self.config.convert_to_mp3 - self.ffmpeg_location = self.config.ffmpeg_location - self.music_path = self.config.music_path # 初始化配置 self.init_config() @@ -327,23 +320,6 @@ class XiaoMusic: return filename return "" - def cleanup_old_temp_files(self): - """ - 清理在 /tmp 目录下旧的临时 MP3 文件。 - """ - temp_dir = '/tmp' # 临时文件存储的目录 - file_ext = '.mp3' # 临时文件的扩展名 - try: - for filename in os.listdir(temp_dir): - if filename.endswith(file_ext): - file_path = os.path.join(temp_dir, filename) - # 如果文件是超过一天的旧文件,则删除它 - if (time.time() - os.path.getmtime(file_path)) > 86400: - os.remove(file_path) - self.log.info(f"Deleted old temporary file: {file_path}") - except Exception as e: - self.log.error(f"Failed to cleanup old temp files: {e}") - # 判断本地音乐是否存在,网络歌曲不判断 def is_music_exist(self, name): if name not in self.all_music: @@ -410,34 +386,27 @@ class XiaoMusic: # 如果开启了MP3转换功能,且文件不是MP3格式,则进行转换 if self.convert_to_mp3 and not is_mp3(filename): self.log.info(f"convert_to_mp3 is enabled. Checking file: {filename}") - temp_mp3_file = self.convert_file_to_mp3(filename) + temp_mp3_file = convert_file_to_mp3( + filename, self.config.ffmpeg_location, self.config.music_path + ) if temp_mp3_file: - # 转换成功后,修改文件名为music_path/tmp下的相对路径 - relative_path = os.path.relpath(temp_mp3_file, self.config.music_path) - self.log.info(f"Converted file: {temp_mp3_file} to {relative_path}") - filename = relative_path + self.log.info(f"Converted file: {filename} to {temp_mp3_file}") + filename = temp_mp3_file else: self.log.warning(f"Failed to convert file to MP3 format: {filename}") - return "" # 转换失败,返回空字符串表示无法获取播放URL # 构造音乐文件的URL filename = filename.replace("\\", "/") if filename.startswith(self.config.music_path): - filename = filename[len(self.config.music_path):] + filename = filename[len(self.config.music_path) :] if filename.startswith("/"): filename = filename[1:] + + self.log.info(f"get_music_url local music. name:{name}, filename:{filename}") + encoded_name = urllib.parse.quote(filename) return f"http://{self.hostname}:{self.public_port}/music/{encoded_name}" - def convert_file_to_mp3(self, input_file): - """ - Convert the file to MP3 format using convert_to_mp3.py. - """ - # 创建 Convert_To_MP3 类的实例,只传递 config 对象 - converter = Convert_To_MP3(self.config) - # 调用静态方法 convert_to_mp3,并传递所需的文件路径和 ffmpeg 位置 - return converter.convert_to_mp3(input_file, self.ffmpeg_location, self.music_path) - # 获取目录下所有歌曲,生成随机播放列表 def _gen_all_music_list(self): self.all_music = {} @@ -452,7 +421,7 @@ class XiaoMusic: if len(files) == 0: continue if dir_name == os.path.basename(self.music_path): - dir_name = "默认" + dir_name = "其他" if self.music_path != self.download_path and dir_name == os.path.basename( self.download_path ):