diff --git a/differential/constants.py b/differential/constants.py index 47b2e0a..95ba54b 100644 --- a/differential/constants.py +++ b/differential/constants.py @@ -4,7 +4,7 @@ BOOLEAN_STATES = {'1': True, 'yes': True, 'true': True, 'on': True, '0': False, 'no': False, 'false': False, 'off': False} -BOOLEAN_ARGS = ('generate_nfo', 'make_torrent', 'easy_upload', 'trim_description') +BOOLEAN_ARGS = ('generate_nfo', 'make_torrent', 'easy_upload', 'trim_description', 'combine_screenshots') class ImageHosting(Enum): diff --git a/differential/plugins/base.py b/differential/plugins/base.py index e1a3783..a012d22 100644 --- a/differential/plugins/base.py +++ b/differential/plugins/base.py @@ -20,8 +20,7 @@ from differential.constants import ImageHosting from differential.utils.torrent import make_torrent from differential.utils.binary import ffprobe, execute -from differential.utils.mediainfo import get_track_attr -from differential.utils.mediainfo import get_full_mediainfo +from differential.utils.mediainfo import get_track_attr, get_full_mediainfo, get_resolution, get_duration from differential.utils.image import byr_upload, ptpimg_upload, smms_upload, imgurl_upload, chevereto_api_upload, chevereto_username_upload @@ -146,7 +145,6 @@ def __init__( self._mediainfo: Optional[MediaInfo] = None self._screenshots: list = [] - def upload_screenshots(self, img_dir: str) -> list: img_urls = [] for count, img in enumerate(sorted(Path(img_dir).glob("*.png"))): @@ -247,45 +245,11 @@ def _generate_nfo(self): with open(self.folder.joinpath(f"{self.folder.name}.nfo"), 'wb') as f: f.write(self.mediaInfo.encode()) - def _get_screenshots(self) -> list: - if self._main_file is None: - logger.error("未找到可以被截图的资源,请确认目标目录含有支持的资源!") - return [] - - # 利用ffprobe获取视频基本信息 - ffprobe_out = ffprobe(self._main_file) - m = re.search(r"Stream.*?Video.*?(\d{2,5})x(\d{2,5})", ffprobe_out) - if not m: - logger.debug(ffprobe_out) - logger.warning(f"无法获取到视频的分辨率") - return [] - - # 获取视频分辨率以及长度等信息 - width, height = int(m.group(1)), int(m.group(2)) - for track in self._mediainfo.tracks: - if track.track_type == "Video": - duration = Decimal(track.duration) - pixel_aspect_ratio = Decimal(track.pixel_aspect_ratio) - break - else: - logger.error(f"未找到视频Track,请检查{self._main_file}是否为支持的文件") - return [] - - if pixel_aspect_ratio <= 1: - pheight = int(height * pixel_aspect_ratio) + ( - int(height * pixel_aspect_ratio) % 2 - ) - resolution = f"{width}x{pheight}" - else: - pwidth = int(width * pixel_aspect_ratio) + ( - int(width * pixel_aspect_ratio) % 2 - ) - resolution = f"{pwidth}x{height}" - logger.trace( - f"duration: {duration}, " - f"width: {width} height: {height}, " - f"PAR: {pixel_aspect_ratio}, resolution: {resolution}" - ) + def _make_screenshots(self) -> Optional[str]: + resolution = get_resolution(self._main_file, self._mediainfo) + duration = get_duration(self._mediainfo) + if resolution is None or duration is None: + return None temp_dir = None # 查找已有的截图 @@ -308,6 +272,16 @@ def _get_screenshots(self) -> list: if self.optimize_screenshot: image = Image.open(screenshot_path) image.save(f"{screenshot_path}", format="PNG", optimized=True) + return temp_dir + + def _get_screenshots(self) -> list: + if self._main_file is None: + logger.error("未找到可以被截图的资源,请确认目标目录含有支持的资源!") + return [] + + temp_dir = self._make_screenshots() + if temp_dir is None: + return [] # 上传截图 screenshots = self.upload_screenshots(temp_dir) diff --git a/differential/plugins/league_official.py b/differential/plugins/league_official.py index 3c0a81a..6073596 100644 --- a/differential/plugins/league_official.py +++ b/differential/plugins/league_official.py @@ -1,5 +1,11 @@ import string import argparse +import tempfile +from pathlib import Path +from typing import Optional + +from PIL import Image +from loguru import logger from differential.plugins.lemonhd import LemonHD from differential.utils.mediainfo import get_track_attr, get_track_attrs @@ -41,13 +47,37 @@ def add_parser(cls, parser: argparse.ArgumentParser) -> argparse.ArgumentParser: parser.add_argument('--source-name', type=str, help='资源来源,HDTV/WEB-DL等', default=argparse.SUPPRESS) parser.add_argument('--uploader', type=str, help="发布者者名字,默认Anonymous", default=argparse.SUPPRESS) parser.add_argument('--team', type=str, help="官组名,LeagueTV/LeagueWeb/LeagueNF等等", default=argparse.SUPPRESS) + parser.add_argument('--combine-screenshots', type=bool, help='是否合并所有截图为一张图,默认开启', default=argparse.SUPPRESS) return parser - def __init__(self, folder: str, url: str, source_name: str, team: str, uploader: str = "Anonymous", **kwargs): + def __init__(self, folder: str, url: str, source_name: str, team: str, uploader: str = "Anonymous", combine_screenshots: bool = True, **kwargs): super().__init__(folder, url, **kwargs) self.team = team self.uploader = uploader self.source_name = source_name + self.combine_screenshots = combine_screenshots + + def _make_screenshots(self) -> Optional[str]: + screenshots_dir = super()._make_screenshots() + if not self.combine_screenshots: + return screenshots_dir + + images = [Image.open(i) for i in sorted(Path(screenshots_dir).glob("*.png"))] + + width, height = images[0].size + new_width = 2 * width + new_height = (self.screenshot_count // 2 + self.screenshot_count % 2) * height + + new_im = Image.new('RGBA', (new_width, new_height)) + for idx, im in enumerate(images): + x = (idx % 2) * width + y = (idx // 2) * height + new_im.paste(im, (x, y)) + + temp_dir = tempfile.mkdtemp() + screenshot_path = f'{temp_dir}/{self._main_file.stem}.thumb.png' + new_im.save(screenshot_path, format='png') + return temp_dir @property def subtitle(self): diff --git a/differential/utils/mediainfo.py b/differential/utils/mediainfo.py index 519c27a..c900275 100644 --- a/differential/utils/mediainfo.py +++ b/differential/utils/mediainfo.py @@ -1,4 +1,5 @@ import os +import re import sys import shutil import platform @@ -6,12 +7,14 @@ import subprocess import webbrowser from pathlib import Path +from decimal import Decimal from typing import Optional, List from configparser import ConfigParser from loguru import logger from pymediainfo import Track, MediaInfo +from differential.utils.binary import ffprobe from differential.constants import ImageHosting, BOOLEAN_STATES, BOOLEAN_ARGS @@ -171,3 +174,46 @@ def get_full_mediainfo(mediainfo: MediaInfo) -> str: media_info += "\n" media_info.strip() return media_info + +def get_duration(media_info: MediaInfo) -> Optional[Decimal]: + for track in media_info.tracks: + if track.track_type == "Video": + return Decimal(track.duration) + logger.error(f"未找到视频Track,请检查{main_file}是否为支持的文件") + return None + +def get_resolution(main_file: Path, media_info: MediaInfo) -> Optional[str]: + # 利用ffprobe获取视频基本信息 + ffprobe_out = ffprobe(main_file) + m = re.search(r"Stream.*?Video.*?(\d{2,5})x(\d{2,5})", ffprobe_out) + if not m: + logger.debug(ffprobe_out) + logger.warning(f"无法获取到视频的分辨率") + return None + + # 获取视频分辨率以及长度等信息 + width, height = int(m.group(1)), int(m.group(2)) + for track in media_info.tracks: + if track.track_type == "Video": + pixel_aspect_ratio = Decimal(track.pixel_aspect_ratio) + break + else: + logger.error(f"未找到视频Track,请检查{main_file}是否为支持的文件") + return None + + resolution = None + if pixel_aspect_ratio <= 1: + pheight = int(height * pixel_aspect_ratio) + ( + int(height * pixel_aspect_ratio) % 2 + ) + resolution = f"{width}x{pheight}" + else: + pwidth = int(width * pixel_aspect_ratio) + ( + int(width * pixel_aspect_ratio) % 2 + ) + resolution = f"{pwidth}x{height}" + logger.trace( + f"width: {width} height: {height}, " + f"PAR: {pixel_aspect_ratio}, resolution: {resolution}" + ) + return resolution