From 406e09922c4a6cbf4ebc5711ec382461c506b1db Mon Sep 17 00:00:00 2001 From: hui <760261797@qq.com> Date: Tue, 3 Sep 2024 14:20:06 +0800 Subject: [PATCH] =?UTF-8?q?fix:m4a=E6=97=A0=E6=B3=95=E6=AD=A3=E7=A1=AE?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E6=92=AD=E6=94=BE=E6=97=B6=E9=95=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- xiaomusic/utils.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/xiaomusic/utils.py b/xiaomusic/utils.py index 6fcc693..2f5c979 100644 --- a/xiaomusic/utils.py +++ b/xiaomusic/utils.py @@ -4,6 +4,7 @@ from __future__ import annotations import asyncio import copy import difflib +import json import logging import mimetypes import os @@ -189,6 +190,13 @@ def is_mp3(url): return False +def is_m4a(url): + mt = mimetypes.guess_type(url) + if mt and mt[0] == "audio/m4a": + return True + return False + + async def _get_web_music_duration(session, url, start=0, end=500): duration = 0 headers = {"Range": f"bytes={start}-{end}"} @@ -199,6 +207,8 @@ async def _get_web_music_duration(session, url, start=0, end=500): try: if is_mp3(url): m = mutagen.mp3.MP3(tmp) + elif is_m4a(url): + return get_duration_by_ffprobe(tmp) else: m = mutagen.File(tmp) duration = m.info.length @@ -244,6 +254,9 @@ async def get_local_music_duration(filename): try: if is_mp3(filename): m = await loop.run_in_executor(None, mutagen.mp3.MP3, filename) + elif is_m4a(filename): + duration = get_duration_by_ffprobe(filename) + return duration else: m = await loop.run_in_executor(None, mutagen.File, filename) duration = m.info.length @@ -252,6 +265,27 @@ async def get_local_music_duration(filename): return duration +def get_duration_by_ffprobe(file_path): + # 使用 ffprobe 获取文件的元数据,并以 JSON 格式输出 + result = subprocess.run( + [ os.path.join(os.getenv("XIAOMUSIC_FFMPEG_LOCATION", "./ffmpeg/bin"),"ffprobe"), + "-v", "error", # 只输出错误信息,避免混杂在其他输出中 + "-show_entries", "format=duration", # 仅显示时长 + "-of", "json", # 以 JSON 格式输出 + file_path + ], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + universal_newlines=True + ) + + # 解析 JSON 输出 + ffprobe_output = json.loads(result.stdout) + + # 获取时长 + duration = float(ffprobe_output['format']['duration']) + + return duration def get_random(length): return "".join(random.sample(string.ascii_letters + string.digits, length))