94 lines
2.9 KiB
Python
94 lines
2.9 KiB
Python
import logging
|
|
import os
|
|
import tempfile
|
|
from subprocess import CalledProcessError
|
|
from typing import Optional
|
|
from urllib.request import urlopen
|
|
|
|
from ytdl_sub.entries.entry import Entry
|
|
from ytdl_sub.utils.ffmpeg import FFMPEG
|
|
from ytdl_sub.utils.file_handler import FileHandler
|
|
from ytdl_sub.utils.logger import Logger
|
|
from ytdl_sub.utils.retry import retry
|
|
|
|
|
|
class ThumbnailTypes:
|
|
LATEST_ENTRY = "latest_entry"
|
|
|
|
|
|
logger: logging.Logger = Logger.get("thumbnail")
|
|
|
|
|
|
def try_convert_download_thumbnail(entry: Entry) -> None:
|
|
"""
|
|
Converts an entry's downloaded thumbnail into jpg format.
|
|
Log with a warning if the thumbnail is not found or fails to convert
|
|
|
|
Parameters
|
|
----------
|
|
entry
|
|
Entry with the thumbnail
|
|
"""
|
|
download_thumbnail_path: Optional[str] = entry.try_get_ytdlp_download_thumbnail_path()
|
|
download_thumbnail_path_as_jpg = entry.get_download_thumbnail_path()
|
|
|
|
# If it was already converted, do not convert again
|
|
if entry.is_thumbnail_downloaded():
|
|
return
|
|
|
|
if not download_thumbnail_path:
|
|
logger.warning("Thumbnail for '%s' was not downloaded", entry.title)
|
|
return
|
|
|
|
if not download_thumbnail_path == download_thumbnail_path_as_jpg:
|
|
try:
|
|
FFMPEG.run(
|
|
["-y", "-bitexact", "-i", download_thumbnail_path, download_thumbnail_path_as_jpg]
|
|
)
|
|
except CalledProcessError:
|
|
logger.warning("Failed to convert thumbnail for '%s' to jpg", entry.title)
|
|
finally:
|
|
FileHandler.delete(download_thumbnail_path)
|
|
|
|
|
|
@retry(times=3, exceptions=(Exception,))
|
|
def download_and_convert_url_thumbnail(
|
|
thumbnail_url: Optional[str], output_thumbnail_path: str
|
|
) -> Optional[bool]:
|
|
"""
|
|
Downloads and converts a thumbnail from a url into a jpg
|
|
|
|
Parameters
|
|
----------
|
|
thumbnail_url
|
|
URL of the thumbnail
|
|
output_thumbnail_path
|
|
Thumbnail file destination after its converted to jpg
|
|
|
|
Returns
|
|
-------
|
|
True to indicate it converted the thumbnail from url. None if the retry failed.
|
|
"""
|
|
if not thumbnail_url:
|
|
return None
|
|
|
|
with urlopen(thumbnail_url, timeout=7.0) as file:
|
|
with tempfile.NamedTemporaryFile(delete=False) as thumbnail:
|
|
thumbnail.write(file.read())
|
|
|
|
try:
|
|
os.makedirs(os.path.dirname(output_thumbnail_path), exist_ok=True)
|
|
|
|
tmp_output_path = FFMPEG.tmp_file_path(
|
|
relative_file_path=thumbnail.name, extension="jpg"
|
|
)
|
|
# Add timeout of 1 second in case ffmpeg hangs from a bad thumbnail
|
|
FFMPEG.run(["-y", "-bitexact", "-i", thumbnail.name, tmp_output_path], timeout=1)
|
|
|
|
# Have FileHandler handle the move to a potential cross-device
|
|
FileHandler.move(tmp_output_path, output_thumbnail_path)
|
|
finally:
|
|
FileHandler.delete(tmp_output_path)
|
|
FileHandler.delete(thumbnail.name)
|
|
|
|
return True
|