Commit 594d287

benny-dou <60535774+benny-dou@users.noreply.github.com>
2025-08-30 18:01:35
chore(ytdlp): add thumbnail extraction
1 parent 429eb80
Changed files (3)
src/ytdlp/download.py
@@ -17,7 +17,7 @@ from yt_dlp.utils import DownloadError, ExtractorError, YoutubeDLError
 from config import DOWNLOAD_DIR, PROXY, YTDLP_DOWNLOAD_MAX_FILE_BYTES
 from messages.progress import modify_progress
 from utils import readable_size, readable_time, true
-from ytdlp.utils import ProxyError, get_ytdlp_opts, platform_emoji, uploader_url
+from ytdlp.utils import ProxyError, find_thumbnail, get_ytdlp_opts, platform_emoji, uploader_url
 
 
 async def ytdlp_download(
@@ -33,6 +33,7 @@ async def ytdlp_download(
     {
         "video_path": Path("video_path"),
         "audio_path": Path("audio_path"),
+        "thumb": str(thumbnail_path),
         "author": "author",
         "author_url": "author_url",
         "title": "title",
@@ -105,7 +106,7 @@ def download_video_info(url: str, ytdlp_opts: dict, json_path: str | Path) -> di
             else:
                 info["video_path"] = Path("/non-exist")
                 info["audio_path"] = Path("/non-exist")
-
+            info["thumb"] = find_thumbnail(info["video_path"], info["audio_path"])
             summary = ""
             if info["author"]:
                 summary += f"\n{platform_emoji(info['extractor'])}{info['author']}"
src/ytdlp/main.py
@@ -19,7 +19,7 @@ from messages.preprocess import preprocess_media
 from messages.progress import modify_progress, telegram_uploading
 from messages.sender import send2tg
 from messages.utils import blockquote, count_without_entities, get_reply_to, smart_split, warp_comments
-from multimedia import convert_to_h264, generate_cover
+from multimedia import convert_to_h264
 from preview.bilibili import get_bilibili_comments, get_bilibili_vinfo, make_bvid_clickable
 from preview.youtube import get_youtube_comments, get_youtube_vinfo
 from publish import publish_telegraph
@@ -259,15 +259,13 @@ async def send_media(
     """
     video_path: Path = info["video_path"]
     audio_path: Path = info["audio_path"]
+    thumb = info["thumb"]
     video_messages = []
     audio_message = None
     video_target, audio_target = get_target_chats(message, ytdlp_video_target, ytdlp_audio_target, **kwargs)
 
     reply_msg_id = kwargs.get("reply_msg_id", 0)
     reply_parameters = get_reply_to(message.id, reply_msg_id)
-    thumb = generate_cover(video_path) if video_path.is_file() else generate_cover(audio_path)
-    if not Path(thumb).is_file():
-        thumb = None
 
     # split large videos into multiple parts (less than 2GB)
     if true(ytdlp_send_video) and video_path.is_file():
src/ytdlp/utils.py
@@ -10,6 +10,7 @@ from yt_dlp.utils import YoutubeDLError
 
 from config import COOKIE, DOWNLOAD_DIR, PROXY
 from cookies import ytdlp_bilibili_cookie
+from multimedia import convert_img_to_telegram_format, generate_cover
 from utils import remove_none_values
 
 
@@ -157,6 +158,25 @@ def platform_emoji(extractor: str) -> str:
     return "๐Ÿ†”"
 
 
+def find_thumbnail(video_path: str | Path, audio_path: str | Path) -> str | None:
+    video_path = Path(video_path)
+    audio_path = Path(audio_path)
+    if video_path.is_file():
+        for suffix in [".jpg", ".png", ".jpeg", ".webp"]:
+            if video_path.with_suffix(suffix).is_file():
+                return convert_img_to_telegram_format(video_path.with_suffix(suffix)).as_posix()
+    if audio_path.is_file():
+        stem = audio_path.stem.split(".")[0]  # remove format_id
+        for suffix in [".jpg", ".png", ".jpeg", ".webp"]:
+            if audio_path.parent.joinpath(stem + suffix).is_file():
+                return convert_img_to_telegram_format(audio_path.parent.joinpath(stem + suffix)).as_posix()
+    # no thumbnail found, generate one
+    thumb = generate_cover(video_path) if video_path.is_file() else generate_cover(audio_path)
+    if Path(thumb).is_file():
+        return convert_img_to_telegram_format(thumb).as_posix()
+    return None
+
+
 def cleanup_ytdlp(vid: str):
     if not vid:
         return