From a0cee359da84e116464fee8729a11365590e9a53 Mon Sep 17 00:00:00 2001 From: thsrite Date: Thu, 4 Jan 2024 09:18:30 +0800 Subject: [PATCH] =?UTF-8?q?fix=20=E4=BF=9D=E7=95=99=E6=AF=94=E4=BE=8B?= =?UTF-8?q?=E6=88=AA=E5=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- docs/ShortPlayMonitor.md | 1 + package.json | 2 +- plugins/shortplaymonitor/__init__.py | 299 +++++++++++++++------------ 4 files changed, 171 insertions(+), 133 deletions(-) diff --git a/README.md b/README.md index ec22ccf..e4ed878 100644 --- a/README.md +++ b/README.md @@ -24,5 +24,5 @@ MoviePilot三方插件市场:https://github.com/thsrite/MoviePilot-Plugins/ - [订阅提醒 1.1](docs%2FSubscribeReminder.md) - [Emby观影报告 1.4](docs%2FEmbyReporter.md) - [豆瓣明星热映订阅 1.2](docs%2FActorSubscribe.md) -- [短剧刮削 1.5](docs%2FShortPlayMonitor.md) +- [短剧刮削 2.0](docs%2FShortPlayMonitor.md) diff --git a/docs/ShortPlayMonitor.md b/docs/ShortPlayMonitor.md index 636751c..e29ea5e 100644 --- a/docs/ShortPlayMonitor.md +++ b/docs/ShortPlayMonitor.md @@ -2,6 +2,7 @@ ### 更新记录 +- 2.0 保留比例截图 - 1.5 生成tvshow.nfo - 1.4 修复转移后路径重命名 - 1.3 智能重命名 diff --git a/package.json b/package.json index 8a4f4e3..a840aec 100644 --- a/package.json +++ b/package.json @@ -122,7 +122,7 @@ "ShortPlayMonitor": { "name": "短剧刮削", "description": "监控视频短剧创建,刮削。", - "version": "1.5", + "version": "2.0", "icon": "Amule_B.png", "author": "thsrite", "level": 1 diff --git a/plugins/shortplaymonitor/__init__.py b/plugins/shortplaymonitor/__init__.py index 1a94f3e..f41ffc9 100644 --- a/plugins/shortplaymonitor/__init__.py +++ b/plugins/shortplaymonitor/__init__.py @@ -7,7 +7,7 @@ from pathlib import Path from typing import Any, List, Dict, Tuple, Optional from xml.dom import minidom from app.utils.dom import DomUtils - +from PIL import Image import pytz from apscheduler.schedulers.background import BackgroundScheduler from watchdog.events import FileSystemEventHandler @@ -48,7 +48,7 @@ class ShortPlayMonitor(_PluginBase): # 插件图标 plugin_icon = "Amule_B.png" # 插件版本 - plugin_version = "1.5" + plugin_version = "2.0" # 插件作者 plugin_author = "thsrite" # 作者主页 @@ -66,7 +66,7 @@ class ShortPlayMonitor(_PluginBase): _onlyonce = False _exclude_keywords = "" _observer = [] - _timeline = "00:00:20" + _timeline = "00:00:10" _dirconf = {} _renameconf = {} _coverconf = {} @@ -285,8 +285,7 @@ class ShortPlayMonitor(_PluginBase): # 生成缩略图 if not (target_path.parent / "poster.jpg").exists(): - thumb_path = self.gen_file_thumb(file_path=target_path, - cover_conf=cover_conf) + thumb_path = self.gen_file_thumb(file_path=target_path) if thumb_path and Path(thumb_path).exists(): SystemUtils.move(thumb_path, target_path.parent / "poster.jpg") else: @@ -294,8 +293,17 @@ class ShortPlayMonitor(_PluginBase): thumb_files = SystemUtils.list_files(directory=target_path.parent, extensions=[".jpg"]) if thumb_files: + # 生成poster for thumb in thumb_files: - SystemUtils.move(thumb, target_path.parent / "poster.jpg") + self.__save_poster(input_path=thumb, + poster_path=target_path.parent / "poster.jpg", + cover_conf=cover_conf) + break + # 删除多余jpg + for thumb in thumb_files: + Path(thumb).unlink() + + else: logger.error(f"文件 {event_path} 硬链接失败,错误码:{retcode}") @@ -303,6 +311,42 @@ class ShortPlayMonitor(_PluginBase): logger.error(f"event_handler_created error: {e}") print(str(e)) + def __save_poster(self, input_path, poster_path, cover_conf): + """ + 截取图片做封面 + """ + image = Image.open(input_path) + + # 需要截取的长宽比(比如 16:9) + if not cover_conf: + target_ratio = 2 / 3 + else: + covers = cover_conf.split(":") + target_ratio = covers[0] / covers[1] + + # 获取原始图片的长宽比 + original_ratio = image.width / image.height + + # 计算截取后的大小 + if original_ratio > target_ratio: + new_height = image.height + new_width = int(new_height * target_ratio) + else: + new_width = image.width + new_height = int(new_width / target_ratio) + + # 计算截取的位置 + left = (image.width - new_width) // 2 + top = (image.height - new_height) // 2 + right = left + new_width + bottom = top + new_height + + # 截取图片 + cropped_image = image.crop((left, top, right, bottom)) + + # 保存截取后的图片 + cropped_image.save(poster_path) + def __gen_tv_nfo_file(self, dir_path: Path, title: str): """ 生成电视剧的NFO描述文件 @@ -329,7 +373,7 @@ class ShortPlayMonitor(_PluginBase): file_path.write_bytes(xml_str) logger.info(f"NFO文件已保存:{file_path}") - def gen_file_thumb(self, file_path: Path, cover_conf: str): + def gen_file_thumb(self, file_path: Path): """ 处理一个文件 """ @@ -342,7 +386,6 @@ class ShortPlayMonitor(_PluginBase): return self.get_thumb(video_path=str(file_path), image_path=str(thumb_path), - cover_conf=str(cover_conf), frames=self._timeline) if Path(thumb_path).exists(): logger.info(f"{file_path} 缩略图已生成:{thumb_path}") @@ -352,23 +395,17 @@ class ShortPlayMonitor(_PluginBase): return None @staticmethod - def get_thumb(video_path: str, image_path: str, frames: str = None, cover_conf: str = None): + def get_thumb(video_path: str, image_path: str, frames: str = None): """ 使用ffmpeg从视频文件中截取缩略图 """ - if not cover_conf: - cover_conf = "720:1080" - else: - covers = cover_conf.split(":") - cover_conf = f"{covers[0] * 360}:{covers[1] * 360}" if not frames: - frames = "00:00:20" + frames = "00:00:10" if not video_path or not image_path: return False - cmd = 'ffmpeg -y -i "{video_path}" -ss {frames} -frames 1 -vf "scale={cover_conf}" "{image_path}"'.format( + cmd = 'ffmpeg -y -i "{video_path}" -ss {frames} -frames 1 "{image_path}"'.format( video_path=video_path, frames=frames, - cover_conf=cover_conf, image_path=image_path) result = SystemUtils.execute(cmd) if result: @@ -401,120 +438,120 @@ class ShortPlayMonitor(_PluginBase): 拼装插件配置页面,需要返回两块数据:1、页面配置;2、数据结构 """ return [ - { - 'component': 'VForm', - 'content': [ - { - 'component': 'VRow', - 'content': [ - { - 'component': 'VCol', - 'props': { - 'cols': 12, - 'md': 6 - }, - 'content': [ - { - 'component': 'VSwitch', - 'props': { - 'model': 'enabled', - 'label': '启用插件', - } - } - ] - }, - { - 'component': 'VCol', - 'props': { - 'cols': 12, - 'md': 6 - }, - 'content': [ - { - 'component': 'VSwitch', - 'props': { - 'model': 'onlyonce', - 'label': '立即运行一次', - } - } - ] - } - ] - }, - { - 'component': 'VRow', - 'content': [ - { - 'component': 'VCol', - 'props': { - 'cols': 12 - }, - 'content': [ - { - 'component': 'VTextarea', - 'props': { - 'model': 'monitor_confs', - 'label': '监控目录', - 'rows': 5, - 'placeholder': '监控方式#监控目录#目的目录#是否重命名#封面比例' - } - } - ] - } - ] - }, - { - 'component': 'VRow', - 'content': [ - { - 'component': 'VCol', - 'props': { - 'cols': 12, - }, - 'content': [ - { - 'component': 'VTextarea', - 'props': { - 'model': 'exclude_keywords', - 'label': '排除关键词', - 'rows': 2, - 'placeholder': '每一行一个关键词' - } - } - ] - } - ] - }, - { - 'component': 'VRow', - 'content': [ - { - 'component': 'VCol', - 'props': { - 'cols': 12, - }, - 'content': [ - { - 'component': 'VAlert', - 'props': { - 'type': 'info', - 'variant': 'tonal', - 'text': '配置说明:' - 'https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/docs/ShortPlayMonitor.md' - } - } - ] - } - ] - } - ] - } - ], { - "enabled": False, - "onlyonce": False, - "monitor_confs": "", - "exclude_keywords": "" - } + { + 'component': 'VForm', + 'content': [ + { + 'component': 'VRow', + 'content': [ + { + 'component': 'VCol', + 'props': { + 'cols': 12, + 'md': 6 + }, + 'content': [ + { + 'component': 'VSwitch', + 'props': { + 'model': 'enabled', + 'label': '启用插件', + } + } + ] + }, + { + 'component': 'VCol', + 'props': { + 'cols': 12, + 'md': 6 + }, + 'content': [ + { + 'component': 'VSwitch', + 'props': { + 'model': 'onlyonce', + 'label': '立即运行一次', + } + } + ] + } + ] + }, + { + 'component': 'VRow', + 'content': [ + { + 'component': 'VCol', + 'props': { + 'cols': 12 + }, + 'content': [ + { + 'component': 'VTextarea', + 'props': { + 'model': 'monitor_confs', + 'label': '监控目录', + 'rows': 5, + 'placeholder': '监控方式#监控目录#目的目录#是否重命名#封面比例' + } + } + ] + } + ] + }, + { + 'component': 'VRow', + 'content': [ + { + 'component': 'VCol', + 'props': { + 'cols': 12, + }, + 'content': [ + { + 'component': 'VTextarea', + 'props': { + 'model': 'exclude_keywords', + 'label': '排除关键词', + 'rows': 2, + 'placeholder': '每一行一个关键词' + } + } + ] + } + ] + }, + { + 'component': 'VRow', + 'content': [ + { + 'component': 'VCol', + 'props': { + 'cols': 12, + }, + 'content': [ + { + 'component': 'VAlert', + 'props': { + 'type': 'info', + 'variant': 'tonal', + 'text': '配置说明:' + 'https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/docs/ShortPlayMonitor.md' + } + } + ] + } + ] + } + ] + } + ], { + "enabled": False, + "onlyonce": False, + "monitor_confs": "", + "exclude_keywords": "" + } def get_page(self) -> List[dict]: pass