Commit a39afaf

benny-dou <60535774+benny-dou@users.noreply.github.com>
2025-09-22 03:53:23
feat(audio): support extracting audio from ytdlp links
1 parent 4bb783f
Changed files (1)
src
src/others/extract_audio.py
@@ -12,13 +12,16 @@ from messages.progress import modify_progress
 from messages.sender import send2tg
 from messages.utils import equal_prefix, get_reply_to, startswith_prefix
 from multimedia import convert_to_audio, parse_media_info
+from networking import match_social_media_link
 from utils import to_int
+from ytdlp.download import ytdlp_download
 
 HELP = f"""
 🎧**消息转音频或语音**
 使用方式:
 1. `{PREFIX.AUDIO}` 回复消息转换为音频文件
 2. `{PREFIX.VOICE}` 回复消息转换为语音消息
+3. `{PREFIX.AUDIO}` 或 `{PREFIX.VOICE}` + 油管/B站链接: 下载其中的音频
 """
 
 
@@ -28,41 +31,38 @@ async def extract_audio_file(client: Client, message: Message, **kwargs) -> None
     if equal_prefix(message.text, prefix=[PREFIX.AUDIO, PREFIX.VOICE]) and not message.reply_to_message:
         await send2tg(client, message, texts=HELP, **kwargs)
         return
-
-    info = parse_msg(message)
-    command = info["text"]
-    if not startswith_prefix(info["text"], prefix=[PREFIX.AUDIO, PREFIX.VOICE]):
+    if not startswith_prefix(message.content, prefix=[PREFIX.AUDIO, PREFIX.VOICE]):
         return
 
-    # reply a message with /audio or /voice
-    if message.reply_to_message:
-        message = message.reply_to_message
-        info = parse_msg(message, silent=True)  # parse again
-    if info["mtype"] == "audio" and startswith_prefix(command, prefix=[PREFIX.AUDIO]):
+    info = parse_msg(message.reply_to_message) if message.reply_to_message else parse_msg(message)
+    if info["mtype"] == "audio" and equal_prefix(message.content, prefix=PREFIX.AUDIO):
         await message.reply("🎧该消息已经为音频, 无需提取")
         return
-    if info["mtype"] == "voice" and startswith_prefix(command, prefix=[PREFIX.VOICE]):
+    if info["mtype"] == "voice" and equal_prefix(message.content, prefix=PREFIX.VOICE):
         await message.reply("🎧该消息已经为语音, 无需提取")
         return
 
-    if info["mtype"] not in ["video", "audio", "voice"]:
-        return
+    if info["mtype"] in ["video", "audio", "voice"]:
+        kwargs["progress"] = kwargs.get("progress", await message.reply_text(f"[{info['mtype']}]收到消息, 开始提取🎧音频...", quote=True))
+        video: str = await message.download()  # type: ignore
+        if not Path(video).expanduser().resolve().is_file():
+            await modify_progress(text=f"❌{info['mtype']}下载失败, 请稍后重试...", force_update=True, **kwargs)
+            return
+        path = await convert_to_audio(video, ext="m4a")
+    else:  # match social media links
+        kwargs["progress"] = kwargs.get("progress", await message.reply_text("使用ytdlp提取🎧音频...", quote=True))
+        matched = await match_social_media_link(info["text"])
+        if matched["platform"] not in ["youtube", "bilibili", "ytdlp"]:
+            await modify_progress(text="❌未找到ytdlp支持的链接", force_update=True, **kwargs)
+            return
+        downloaded = await ytdlp_download(matched["url"], ytdlp_download_video=False, **kwargs)
+        path = downloaded["audio_path"]
 
-    msg = f"[{info['mtype']}]收到消息, 开始提取🎧音频..."
-    if kwargs.get("show_progress"):
-        res = await send2tg(client, message, texts=msg, **kwargs)
-        kwargs["progress"] = res[0]
-    video: str = await message.download()  # type: ignore
-    if Path(video).expanduser().resolve().is_file():
-        await modify_progress(text=f"[{info['mtype']}]下载完成, 提取🎧音频中...", force_update=True, **kwargs)
-    else:
-        await modify_progress(text=f"[{info['mtype']}]下载失败, 请稍后重试...", force_update=True, **kwargs)
-        return
-    path = await convert_to_audio(video, ext="m4a")
-    if not Path(path).expanduser().resolve().is_file():
+    path = Path(path).expanduser().resolve()
+    if not path.is_file():
         logger.trace(f"File not found: {path}")
+        await modify_progress(text="❌ytdlp下载失败", force_update=True, **kwargs)
         return
-    path = Path(path).expanduser().resolve()
     if path.name.endswith(".final.m4a"):  # remove final suffix
         path.rename(path.with_name(path.name.replace(".final.m4a", ".m4a")))
         path = path.with_name(path.name.replace(".final.m4a", ".m4a"))
@@ -73,10 +73,9 @@ async def extract_audio_file(client: Client, message: Message, **kwargs) -> None
     target_chat = kwargs["target_chat"] if kwargs.get("target_chat") else message.chat.id
     reply_msg_id = kwargs.get("reply_msg_id", 0)
     reply_parameters = get_reply_to(message.id, reply_msg_id)
-    if startswith_prefix(command, prefix=[PREFIX.AUDIO]):
+    if startswith_prefix(message.content, prefix=PREFIX.AUDIO):
         await client.send_audio(to_int(target_chat), Path(path).as_posix(), duration=duration, reply_parameters=reply_parameters)
-    elif startswith_prefix(command, prefix=[PREFIX.VOICE]):
+    elif startswith_prefix(message.content, prefix=PREFIX.VOICE):
         await client.send_voice(to_int(target_chat), Path(path).as_posix(), duration=duration, reply_parameters=reply_parameters)
-    Path(video).unlink(missing_ok=True)
     path.unlink(missing_ok=True)
     await modify_progress(del_status=True, **kwargs)