diff --git a/__init__.py b/__init__.py index bb9688f..4031cd4 100644 --- a/__init__.py +++ b/__init__.py @@ -9,7 +9,7 @@ from .nodes.cos import COSUpload, COSDownload from .nodes.face_detect import FaceDetect from .nodes.face_extract import FaceExtract from .nodes.log2db import LogToDB -from .nodes.videocut import VideoCut, VideoCutByFramePoint +from .nodes.video import VideoCut, VideoCutByFramePoint, VideoChangeFPS from .nodes.vod2local import VodToLocalNode # A dictionary that contains all nodes you want to export with their names @@ -23,6 +23,7 @@ NODE_CLASS_MAPPINGS = { "S3Download": S3Download, "VideoCutCustom": VideoCut, "VideoCutByFramePoint": VideoCutByFramePoint, + "VideoChangeFPS": VideoChangeFPS, "VodToLocal": VodToLocalNode, "LogToDB": LogToDB, "VideoPointCompute": VideoStartPointDurationCompute, @@ -45,6 +46,7 @@ NODE_DISPLAY_NAME_MAPPINGS = { "S3Download": "S3下载", "VideoCutCustom": "视频剪裁", "VideoCutByFramePoint": "视频剪裁(精确帧位)", + "VideoChangeFPS": "视频转换帧率", "VodToLocal": "腾讯云VOD下载", "LogToDB": "状态持久化DB", "VideoPointCompute": "视频帧位计算", diff --git a/nodes/face_detect.py b/nodes/face_detect.py index 6e6d286..8f3ea66 100644 --- a/nodes/face_detect.py +++ b/nodes/face_detect.py @@ -51,7 +51,7 @@ class FaceDetect: FUNCTION = "predict" - CATEGORY = "不忘科技-自定义节点🚩" + CATEGORY = "不忘科技-自定义节点🚩/面部" def predict(self, image, main_seed, model, length, threshold): image, image_selected, cls, prob, nums, period = test_node( diff --git a/nodes/face_extract.py b/nodes/face_extract.py index dd4028b..ccc65cf 100644 --- a/nodes/face_extract.py +++ b/nodes/face_extract.py @@ -23,7 +23,7 @@ class FaceExtract: FUNCTION = "crop" - CATEGORY = "不忘科技-自定义节点🚩" + CATEGORY = "不忘科技-自定义节点🚩/面部" def crop(self, image): device = model_management.get_torch_device() diff --git a/nodes/heygem.py b/nodes/heygem.py index 55ac549..6321982 100644 --- a/nodes/heygem.py +++ b/nodes/heygem.py @@ -140,7 +140,7 @@ class HeyGemF2F: RETURN_TYPES = ("STRING",) RETURN_NAMES = ("视频存储路径",) FUNCTION = "f2f" - CATEGORY = "不忘科技-自定义节点🚩" + CATEGORY = "不忘科技-自定义节点🚩/口型同步" def f2f(self, video:Tensor, audio:dict, heygem_url:str, heygem_temp_path:str, is_Windows:bool): uid = str(uuid.uuid4()) @@ -206,7 +206,7 @@ class HeyGemF2FFromFile: RETURN_TYPES = ("STRING",) RETURN_NAMES = ("视频存储路径",) FUNCTION = "f2f" - CATEGORY = "不忘科技-自定义节点🚩" + CATEGORY = "不忘科技-自定义节点🚩/口型同步" def f2f(self, video:str, audio:str, heygem_url:str, heygem_temp_path:str, is_Windows:bool): uid = str(uuid.uuid4()) diff --git a/nodes/s3.py b/nodes/s3.py index 1f9383b..a63cfa3 100644 --- a/nodes/s3.py +++ b/nodes/s3.py @@ -20,7 +20,7 @@ class S3Download: RETURN_TYPES = ("STRING",) RETURN_NAMES = ("视频存储路径",) FUNCTION = "download" - CATEGORY = "不忘科技-自定义节点🚩" + CATEGORY = "不忘科技-自定义节点🚩/S3" def download(self, s3_bucket, s3_key): s3_key_in = s3_key.replace("/",os.sep) @@ -62,7 +62,7 @@ class S3Upload: RETURN_NAMES = ("S3文件Key",) FUNCTION = "upload" - CATEGORY = "不忘科技-自定义节点🚩" + CATEGORY = "不忘科技-自定义节点🚩/S3" def upload(self, s3_bucket, path, subfolder): loguru.logger.info(f"S3 UPLOAD {path} to {s3_bucket}/{subfolder}") diff --git a/nodes/videocut.py b/nodes/video.py similarity index 81% rename from nodes/videocut.py rename to nodes/video.py index b3bd973..7ad4f76 100644 --- a/nodes/videocut.py +++ b/nodes/video.py @@ -6,6 +6,7 @@ import uuid from datetime import datetime import ffmpy +import loguru import torchvision.io video_extensions = ['webm', 'mp4', 'mkv', 'gif', 'mov'] @@ -32,7 +33,7 @@ class VideoCut: # OUTPUT_NODE = False - CATEGORY = "不忘科技-自定义节点🚩" + CATEGORY = "不忘科技-自定义节点🚩/视频" def cut(self, video_path, start, end): try: @@ -111,7 +112,6 @@ class VideoCut: files = glob.glob(output.replace("%03d", "*")) traceback.print_exc() video, audio, info = torchvision.io.read_video(files[0]) - video.mul_(255) audio.unsqueeze_(0) try: os.remove(files[0]) @@ -144,7 +144,7 @@ class VideoCutByFramePoint: # OUTPUT_NODE = False - CATEGORY = "不忘科技-自定义节点🚩" + CATEGORY = "不忘科技-自定义节点🚩/视频" def cut(self, video_path, start_point, duration, fps, force_match_fps): try: @@ -234,3 +234,54 @@ class VideoCutByFramePoint: except: traceback.print_exc() raise Exception("Cut Failed") + +class VideoChangeFPS: + """FFMPEG视频FPS转换""" + + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "video_path": ("STRING",{"placeholder": "X://insert/path/here.mp4", "vhs_path_extensions": video_extensions}), + "fps": ("INT", {"default": 30}), + }, + } + + RETURN_TYPES = ("STRING",) + RETURN_NAMES = ("视频路径",) + + FUNCTION = "changeFps" + + OUTPUT_NODE = True + + CATEGORY = "不忘科技-自定义节点🚩/视频" + + def changeFps(self, video_path, fps): + try: + print(video_path[1]) + if not (video_path.startswith("/") or video_path.startswith("output/") or video_path[1] == ":"): + video_path = "output/" + video_path + loguru.logger.info("Processing video: %s", video_path) + output = ".".join([video_path.split(".")[-2]+"-%dfps" % fps,video_path.split(".")[-1]]) + ff = ffmpy.FFmpeg( + inputs={video_path: None}, + outputs={ + output: [ + "-vf", + "fps=%d" % fps, + "-c:v", + "libx264", + "-crf", + "16", + "-preset", + "slow", + "-c:a", + "copy" + ] + }) + print(ff.cmd) + ff.run() + return (output,) + except: + traceback.print_exc() + raise Exception("ChangeFPS Failed") \ No newline at end of file