initial commit
This commit is contained in:
+124
@@ -0,0 +1,124 @@
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
.python-version
|
||||
|
||||
# celery beat schedule file
|
||||
celerybeat-schedule
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyderworkspace
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
@@ -0,0 +1,414 @@
|
||||
{
|
||||
"last_node_id": 8,
|
||||
"last_link_id": 7,
|
||||
"nodes": [
|
||||
{
|
||||
"id": 1,
|
||||
"type": "CoreVideoMocks:EncodeVideoStream",
|
||||
"pos": [
|
||||
1402.6351318359375,
|
||||
2591.9091796875
|
||||
],
|
||||
"size": [
|
||||
258.4818115234375,
|
||||
78
|
||||
],
|
||||
"flags": {},
|
||||
"order": 5,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "images",
|
||||
"type": "IMAGE",
|
||||
"link": 1
|
||||
},
|
||||
{
|
||||
"name": "codec",
|
||||
"type": 0,
|
||||
"link": 2
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "encoded_stream",
|
||||
"type": "STRING",
|
||||
"links": [
|
||||
7
|
||||
],
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "CoreVideoMocks:EncodeVideoStream"
|
||||
},
|
||||
"widgets_values": [
|
||||
30
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "CoreVideoMocks:SaveVideo",
|
||||
"pos": [
|
||||
2069.162109375,
|
||||
2575.619384765625
|
||||
],
|
||||
"size": [
|
||||
297.9570007324219,
|
||||
82
|
||||
],
|
||||
"flags": {},
|
||||
"order": 7,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "video_stream",
|
||||
"type": "STRING",
|
||||
"widget": {
|
||||
"name": "video_stream"
|
||||
},
|
||||
"link": 3
|
||||
}
|
||||
],
|
||||
"outputs": [],
|
||||
"properties": {
|
||||
"Node name for S&R": "CoreVideoMocks:SaveVideo"
|
||||
},
|
||||
"widgets_values": [
|
||||
"",
|
||||
"video_output"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"type": "CoreVideoMocks:LoadVideo",
|
||||
"pos": [
|
||||
13.905184745788574,
|
||||
2593.997802734375
|
||||
],
|
||||
"size": [
|
||||
315,
|
||||
284
|
||||
],
|
||||
"flags": {},
|
||||
"order": 0,
|
||||
"mode": 0,
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "video",
|
||||
"type": "STRING",
|
||||
"links": [
|
||||
5
|
||||
],
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "CoreVideoMocks:LoadVideo"
|
||||
},
|
||||
"widgets_values": [
|
||||
"AnimateDiff_00037.webm",
|
||||
"image",
|
||||
""
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"type": "CoreVideoMocks:DecodeVideoStream",
|
||||
"pos": [
|
||||
663.9580078125,
|
||||
2592.559814453125
|
||||
],
|
||||
"size": [
|
||||
315,
|
||||
130
|
||||
],
|
||||
"flags": {},
|
||||
"order": 3,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "stream",
|
||||
"type": "STRING",
|
||||
"widget": {
|
||||
"name": "stream"
|
||||
},
|
||||
"link": 4
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "images",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
6
|
||||
],
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "CoreVideoMocks:DecodeVideoStream"
|
||||
},
|
||||
"widgets_values": [
|
||||
"",
|
||||
1,
|
||||
0,
|
||||
-1
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"type": "CoreVideoMocks:SplitVideo",
|
||||
"pos": [
|
||||
385.1243896484375,
|
||||
2612.85546875
|
||||
],
|
||||
"size": [
|
||||
210,
|
||||
98
|
||||
],
|
||||
"flags": {},
|
||||
"order": 2,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "video",
|
||||
"type": "STRING",
|
||||
"widget": {
|
||||
"name": "video"
|
||||
},
|
||||
"link": 5
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "video_streams",
|
||||
"type": "STRING",
|
||||
"links": [
|
||||
4
|
||||
],
|
||||
"slot_index": 0
|
||||
},
|
||||
{
|
||||
"name": "audio_streams",
|
||||
"type": "STRING",
|
||||
"links": [],
|
||||
"slot_index": 1
|
||||
},
|
||||
{
|
||||
"name": "subtitle_streams",
|
||||
"type": "STRING",
|
||||
"links": [],
|
||||
"slot_index": 2
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "CoreVideoMocks:SplitVideo"
|
||||
},
|
||||
"widgets_values": [
|
||||
""
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"type": "ImageInvert",
|
||||
"pos": [
|
||||
1079.687255859375,
|
||||
2592.758544921875
|
||||
],
|
||||
"size": [
|
||||
210,
|
||||
26
|
||||
],
|
||||
"flags": {},
|
||||
"order": 4,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"link": 6
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "IMAGE",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
1
|
||||
],
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "ImageInvert"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"type": "CoreVideoMocks:VP9Codec",
|
||||
"pos": [
|
||||
1079.7886962890625,
|
||||
2687.97998046875
|
||||
],
|
||||
"size": [
|
||||
210,
|
||||
58
|
||||
],
|
||||
"flags": {},
|
||||
"order": 1,
|
||||
"mode": 0,
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "codec",
|
||||
"type": "DICT",
|
||||
"links": [
|
||||
2
|
||||
],
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "CoreVideoMocks:VP9Codec"
|
||||
},
|
||||
"widgets_values": [
|
||||
30
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"type": "CoreVideoMocks:CombineVideo",
|
||||
"pos": [
|
||||
1740.941162109375,
|
||||
2573.982666015625
|
||||
],
|
||||
"size": [
|
||||
253.60000610351562,
|
||||
170
|
||||
],
|
||||
"flags": {},
|
||||
"order": 6,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "video_stream",
|
||||
"type": "STRING",
|
||||
"widget": {
|
||||
"name": "video_stream"
|
||||
},
|
||||
"link": 7
|
||||
},
|
||||
{
|
||||
"name": "audio_stream",
|
||||
"type": "STRING",
|
||||
"widget": {
|
||||
"name": "audio_stream"
|
||||
},
|
||||
"link": null
|
||||
},
|
||||
{
|
||||
"name": "subtitle_stream",
|
||||
"type": "STRING",
|
||||
"widget": {
|
||||
"name": "subtitle_stream"
|
||||
},
|
||||
"link": null
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "combined_video",
|
||||
"type": "STRING",
|
||||
"links": [
|
||||
3
|
||||
],
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "CoreVideoMocks:CombineVideo"
|
||||
},
|
||||
"widgets_values": [
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"webm"
|
||||
]
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
[
|
||||
1,
|
||||
6,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
2,
|
||||
7,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
"DICT"
|
||||
],
|
||||
[
|
||||
3,
|
||||
8,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
4,
|
||||
5,
|
||||
0,
|
||||
4,
|
||||
0,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
5,
|
||||
3,
|
||||
0,
|
||||
5,
|
||||
0,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
6,
|
||||
4,
|
||||
0,
|
||||
6,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
7,
|
||||
1,
|
||||
0,
|
||||
8,
|
||||
0,
|
||||
"STRING"
|
||||
]
|
||||
],
|
||||
"groups": [],
|
||||
"config": {},
|
||||
"extra": {
|
||||
"ds": {
|
||||
"scale": 0.6934334949441647,
|
||||
"offset": [
|
||||
126.5493336827142,
|
||||
-2054.117802022672
|
||||
]
|
||||
},
|
||||
"VHS_latentpreview": false,
|
||||
"VHS_latentpreviewrate": 0,
|
||||
"VHS_MetadataImage": true,
|
||||
"VHS_KeepIntermediate": true
|
||||
},
|
||||
"version": 0.4
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
from .nodes import NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS
|
||||
@@ -0,0 +1,456 @@
|
||||
import hashlib
|
||||
import os
|
||||
import folder_paths
|
||||
|
||||
class LoadVideo:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
input_dir = folder_paths.get_input_directory()
|
||||
files = [f for f in os.listdir(input_dir) if os.path.isfile(os.path.join(input_dir, f))]
|
||||
return {"required":
|
||||
{"video": (sorted(files), {"video_upload": True})},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
RETURN_NAMES = ("video",)
|
||||
|
||||
OUTPUT_NODE = False
|
||||
|
||||
CATEGORY = "video"
|
||||
|
||||
FUNCTION = "load_video"
|
||||
def load_video(self, video):
|
||||
# Mock implementation
|
||||
return (f"Mock Loaded Video: {video}",)
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(self, image):
|
||||
if not folder_paths.exists_annotated_filepath(image):
|
||||
return "Invalid image file: {}".format(image)
|
||||
|
||||
return True
|
||||
|
||||
class GetVideoStream:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {"required":
|
||||
{"streams": ("STRING", {"forceInput": True} ),
|
||||
"stream_index": ("INT", {"default": 0, "min": 0, "max": 10000, "tooltip": "The zero-based index of the stream to extract."})},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
RETURN_NAMES = ("stream",)
|
||||
|
||||
OUTPUT_NODE = False
|
||||
|
||||
CATEGORY = "video"
|
||||
|
||||
FUNCTION = "get_video_stream"
|
||||
def get_video_stream(self, streams, stream_index):
|
||||
# Mock implementation
|
||||
return ("Mock Video Stream",)
|
||||
|
||||
class GetAudioStream:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {"required":
|
||||
{"streams": ("STRING", {"forceInput": True}),
|
||||
"stream_index": ("INT", {"default": 0, "min": 0, "max": 10000, "tooltip": "The zero-based index of the stream to extract."})},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
RETURN_NAMES = ("stream",)
|
||||
|
||||
OUTPUT_NODE = False
|
||||
|
||||
CATEGORY = "audio"
|
||||
|
||||
FUNCTION = "get_audio_stream"
|
||||
def get_audio_stream(self, streams, stream_index):
|
||||
# Mock implementation
|
||||
return ("Mock Audio Stream",)
|
||||
|
||||
class GetSubtitleStream:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {"required":
|
||||
{"streams": ("STRING", {"forceInput": True}),
|
||||
"stream_index": ("INT", {"default": 0, "min": 0, "max": 10000, "tooltip": "The zero-based index of the stream to extract."})},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",) # Create a new "Video Stream" class, it should contain what codec to use to decode it, and metadata that usually is found on the container such as frame count and other things
|
||||
RETURN_NAMES = ("stream",)
|
||||
|
||||
OUTPUT_NODE = False
|
||||
|
||||
CATEGORY = "subtitle"
|
||||
|
||||
FUNCTION = "get_subtitle_stream"
|
||||
def get_subtitle_stream(self, streams, stream_index):
|
||||
# Mock implementation
|
||||
return ("Mock Subtitle Stream",)
|
||||
|
||||
class DecodeVideoStream:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {"required":
|
||||
{"stream": ("STRING", {"forceInput": True}),
|
||||
"frame_interval": ("INT", {"default": 1, "min": 1, "max": 1000, "tooltip": "Decode every nth frame."}),
|
||||
"start_frame": ("INT", {"default": 0, "min": 0, "tooltip": "The first frame to decode."}),
|
||||
"end_frame": ("INT", {"default": -1, "min": -1, "tooltip": "The last frame to decode (-1 for all frames)."})},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("IMAGE",)
|
||||
RETURN_NAMES = ("images",)
|
||||
|
||||
OUTPUT_NODE = False
|
||||
|
||||
CATEGORY = "video"
|
||||
|
||||
FUNCTION = "decode_video_stream"
|
||||
def decode_video_stream(self, stream, frame_interval, start_frame, end_frame):
|
||||
# Mock implementation
|
||||
return (["Mock Frame 1", "Mock Frame 2", "Mock Frame 3"],)
|
||||
|
||||
class EncodeVideoStream:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {"required":
|
||||
{"images": ("IMAGE", {"forceInput": True}),
|
||||
"codec": ({"forceInput": True}),
|
||||
"frames_per_second": ("FLOAT", {"default": 30, "min": 1, "max": 120, "tooltip": "Frames per second for the encoded video."}),
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
RETURN_NAMES = ("encoded_stream",)
|
||||
|
||||
OUTPUT_NODE = False
|
||||
|
||||
CATEGORY = "video"
|
||||
|
||||
FUNCTION = "encode_video_stream"
|
||||
def encode_video_stream(self, images, codec, bitrate, frames_per_second):
|
||||
# Mock implementation
|
||||
return (f"Mock Encoded Stream with {codec} at {bitrate} kbps and {frames_per_second} fps",)
|
||||
|
||||
class VP9Codec:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {"required":
|
||||
{"crf": ("INT", {"default": 30, "min": 0, "max": 63, "tooltip": "Constant Rate Factor (CRF) for VP9 encoding. Lower values mean better quality."})},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("DICT",)
|
||||
RETURN_NAMES = ("codec",)
|
||||
|
||||
OUTPUT_NODE = False
|
||||
|
||||
CATEGORY = "video"
|
||||
|
||||
FUNCTION = "get_vp9_options"
|
||||
def get_vp9_options(self, crf):
|
||||
# Mock implementation
|
||||
return ({"codec": "VP9", "crf": crf},)
|
||||
|
||||
class AV1Codec:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {"required":
|
||||
{"crf": ("INT", {"default": 30, "min": 0, "max": 63, "tooltip": "Constant Rate Factor (CRF) for AV1 encoding. Lower values mean better quality."})},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("DICT",)
|
||||
RETURN_NAMES = ("codec",)
|
||||
|
||||
OUTPUT_NODE = False
|
||||
|
||||
CATEGORY = "video"
|
||||
|
||||
FUNCTION = "get_av1_options"
|
||||
def get_av1_options(self, crf):
|
||||
# Mock implementation
|
||||
return ({"codec": "AV1", "crf": crf},)
|
||||
|
||||
class BatchVideoStreams:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {"required": {
|
||||
"video_stream_1": ("STRING", {"forceInput": True}),
|
||||
"video_stream_2": ("STRING", {"forceInput": True}),
|
||||
}}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
RETURN_NAMES = ("batched_video_streams",)
|
||||
|
||||
OUTPUT_NODE = False
|
||||
|
||||
CATEGORY = "video"
|
||||
|
||||
FUNCTION = "batch_video_streams"
|
||||
def batch_video_streams(self, video_stream_1, video_stream_2):
|
||||
# Mock implementation
|
||||
return (f"Mock Batched Video Streams: {video_stream_1} + {video_stream_2}",)
|
||||
|
||||
class BatchAudioStreams:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {"required": {
|
||||
"audio_stream_1": ("STRING", {"forceInput": True}),
|
||||
"audio_stream_2": ("STRING", {"forceInput": True}),
|
||||
}}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
RETURN_NAMES = ("batched_audio_streams",)
|
||||
|
||||
OUTPUT_NODE = False
|
||||
|
||||
CATEGORY = "audio"
|
||||
|
||||
FUNCTION = "batch_audio_streams"
|
||||
def batch_audio_streams(self, audio_stream_1, audio_stream_2):
|
||||
# Mock implementation
|
||||
return (f"Mock Batched Audio Streams: {audio_stream_1} + {audio_stream_2}",)
|
||||
|
||||
class BatchSubtitlesStreams:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {"required": {
|
||||
"subtitle_stream_1": ("STRING", {"forceInput": True}),
|
||||
"subtitle_stream_2": ("STRING", {"forceInput": True}),
|
||||
}}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
RETURN_NAMES = ("batched_subtitle_streams",)
|
||||
|
||||
OUTPUT_NODE = False
|
||||
|
||||
CATEGORY = "subtitle"
|
||||
|
||||
FUNCTION = "batch_subtitle_streams"
|
||||
def batch_subtitle_streams(self, subtitle_stream_1, subtitle_stream_2):
|
||||
# Mock implementation
|
||||
return (f"Mock Batched Subtitle Streams: {subtitle_stream_1} + {subtitle_stream_2}",)
|
||||
|
||||
class CombineVideo:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {"required": {
|
||||
"video_stream": ("STRING", {"forceInput": True}),
|
||||
"audio_stream": ("STRING", {"forceInput": True}),
|
||||
"subtitle_stream": ("STRING", {"forceInput": True}),
|
||||
"container": (["webm"], {"tooltip": "Select the video container format."}),
|
||||
}}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
RETURN_NAMES = ("combined_video",)
|
||||
|
||||
OUTPUT_NODE = False
|
||||
|
||||
CATEGORY = "video"
|
||||
|
||||
FUNCTION = "combine_video"
|
||||
def combine_video(self, video_stream, audio_stream, subtitle_stream, container):
|
||||
# Mock implementation
|
||||
return (f"Mock Combined Video: {video_stream}, {audio_stream}, {subtitle_stream} in {container} container",)
|
||||
|
||||
class SaveVideo:
|
||||
def __init__(self):
|
||||
self.output_dir = folder_paths.get_output_directory()
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {"required": {
|
||||
"video_stream": ("STRING", {"forceInput": True}),
|
||||
"filename_prefix": ("STRING", {"default": "video_output", "tooltip": "The prefix for the saved video file."}),
|
||||
}}
|
||||
|
||||
RETURN_TYPES = ()
|
||||
FUNCTION = "save_video"
|
||||
|
||||
OUTPUT_NODE = True
|
||||
|
||||
CATEGORY = "video"
|
||||
|
||||
def save_video(self, video_stream, filename_prefix="video_output"):
|
||||
output_path = os.path.join(self.output_dir, f"{filename_prefix}.webm")
|
||||
# Mock implementation for saving
|
||||
with open(output_path, "w") as f:
|
||||
f.write(f"Mock video content for stream: {video_stream}")
|
||||
return {"ui": {"saved_video": [{"filename": f"{filename_prefix}.webm", "type": "output"}]}}
|
||||
|
||||
class PreviewVideo:
|
||||
def __init__(self):
|
||||
self.output_dir = folder_paths.get_temp_directory()
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {"required": {
|
||||
"video_stream": ("STRING", {"forceInput": True}),
|
||||
}}
|
||||
|
||||
RETURN_TYPES = ()
|
||||
FUNCTION = "preview_video"
|
||||
|
||||
OUTPUT_NODE = True
|
||||
|
||||
CATEGORY = "video"
|
||||
|
||||
def preview_video(self, video_stream, preview_name="video_preview"):
|
||||
preview_path = os.path.join(self.output_dir, f"{preview_name}.webm")
|
||||
# Mock implementation for preview
|
||||
with open(preview_path, "w") as f:
|
||||
f.write(f"Mock video preview content for stream: {video_stream}")
|
||||
return {"ui": {"preview_video": [{"filename": f"{preview_name}.webm", "type": "preview"}]}}
|
||||
|
||||
class CodecFromVideoStream:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {"required": {
|
||||
"video_stream": ("STRING", {"forceInput": True}),
|
||||
}}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
RETURN_NAMES = ("codec",)
|
||||
|
||||
OUTPUT_NODE = False
|
||||
|
||||
CATEGORY = "video"
|
||||
|
||||
FUNCTION = "extract_codec"
|
||||
|
||||
def extract_codec(self, video_stream):
|
||||
# Mock implementation
|
||||
return ("Mock Codec: VP9 and Options",)
|
||||
|
||||
class SplitVideo:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {"required": {
|
||||
"video": ("STRING", {"forceInput": True}),
|
||||
}}
|
||||
|
||||
RETURN_TYPES = ("STRING", "STRING", "STRING")
|
||||
RETURN_NAMES = ("video_streams", "audio_streams", "subtitle_streams")
|
||||
|
||||
OUTPUT_NODE = False
|
||||
|
||||
CATEGORY = "video"
|
||||
|
||||
FUNCTION = "split_video"
|
||||
|
||||
def split_video(self, video):
|
||||
# Mock implementation
|
||||
return ("Mock Video Streams", "Mock Audio Streams", "Mock Subtitle Streams")
|
||||
|
||||
class VideoStreamData:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {"required": {
|
||||
"video_stream": ("STRING", {"forceInput": True}),
|
||||
}}
|
||||
|
||||
RETURN_TYPES = ("FLOAT", "INT", "FLOAT", "INT", "INT")
|
||||
RETURN_NAMES = ("frames_per_second", "frame_count", "duration", "width", "height")
|
||||
|
||||
OUTPUT_NODE = False
|
||||
|
||||
CATEGORY = "video"
|
||||
|
||||
FUNCTION = "extract_metadata"
|
||||
|
||||
def extract_metadata(self, video_stream):
|
||||
# Mock implementation
|
||||
fps = 30.0
|
||||
frame_count = 300
|
||||
duration = 10.0
|
||||
width = 1920
|
||||
height = 1080
|
||||
return (fps, frame_count, duration, width, height)
|
||||
|
||||
# NOTE: names should be globally unique
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"CoreVideoMocks:LoadVideo": LoadVideo,
|
||||
"CoreVideoMocks:GetVideoStream": GetVideoStream,
|
||||
"CoreVideoMocks:GetAudioStream": GetAudioStream,
|
||||
"CoreVideoMocks:GetSubtitleStream": GetSubtitleStream,
|
||||
"CoreVideoMocks:DecodeVideoStream": DecodeVideoStream,
|
||||
"CoreVideoMocks:EncodeVideoStream": EncodeVideoStream,
|
||||
"CoreVideoMocks:VP9Codec": VP9Codec,
|
||||
"CoreVideoMocks:AV1Codec": AV1Codec,
|
||||
"CoreVideoMocks:BatchVideoStreams": BatchVideoStreams,
|
||||
"CoreVideoMocks:BatchAudioStreams": BatchAudioStreams,
|
||||
"CoreVideoMocks:BatchSubtitlesStreams": BatchSubtitlesStreams,
|
||||
"CoreVideoMocks:CombineVideo": CombineVideo,
|
||||
"CoreVideoMocks:SaveVideo": SaveVideo,
|
||||
"CoreVideoMocks:PreviewVideo": PreviewVideo,
|
||||
"CoreVideoMocks:CodecFromVideoStream": CodecFromVideoStream,
|
||||
"CoreVideoMocks:SplitVideo": SplitVideo,
|
||||
"CoreVideoMocks:VideoStreamData": VideoStreamData,
|
||||
}
|
||||
|
||||
# A dictionary that contains the friendly/humanly readable titles for the nodes
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"CoreVideoMocks:LoadVideo": "Load Video",
|
||||
"CoreVideoMocks:GetVideoStream": "Get Video Stream",
|
||||
"CoreVideoMocks:GetAudioStream": "Get Audio Stream",
|
||||
"CoreVideoMocks:GetSubtitleStream": "Get Subtitle Stream",
|
||||
"CoreVideoMocks:DecodeVideoStream": "Decode Video Stream",
|
||||
"CoreVideoMocks:EncodeVideoStream": "Encode Video Stream",
|
||||
"CoreVideoMocks:VP9Codec": "VP9 Codec",
|
||||
"CoreVideoMocks:AV1Codec": "AV1 Codec",
|
||||
"CoreVideoMocks:BatchVideoStreams": "Batch Video Streams",
|
||||
"CoreVideoMocks:BatchAudioStreams": "Batch Audio Streams",
|
||||
"CoreVideoMocks:BatchSubtitlesStreams": "Batch Subtitle Streams",
|
||||
"CoreVideoMocks:CombineVideo": "Combine Video",
|
||||
"CoreVideoMocks:SaveVideo": "Save Video",
|
||||
"CoreVideoMocks:PreviewVideo": "Preview Video",
|
||||
"CoreVideoMocks:CodecFromVideoStream": "Codec From Video Stream",
|
||||
"CoreVideoMocks:SplitVideo": "Split Video",
|
||||
"CoreVideoMocks:VideoStreamData": "Video Stream Data",
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
A mock of a possible implementation of for ComfyUI Core video nodes. Intended Use:
|
||||

|
||||
[workflow](<Simple Video Workflow Mock.json>)
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 131 KiB |
Reference in New Issue
Block a user