- DecodeTranscriptNode to parse transcript text - YoutubeUploadNode to upload videos to YouTube - Audio metadata and file list nodes - Image stack blending and stripping alpha channel - Sampler dataset creation node - Utils for deep copying tensors and arrays Also includes: - Testing for new utils module - Git nodes marked with base class - Renamed nodes.py to avoid conflicts - Import refactoring to handle naming Specifics: - descript.py: New transcript parsing node - youtube_nodes.py: New YouTube upload node - audio.py: New audio metadata and file list nodes - utils.py: Deep copy utility functions - image.py: New image stack blending and alpha stripping - tests/test_utils.py: Tests for new utils - git.py: Marked git nodes with base class - __init__.py: Refactored imports and mappings - requirements.txt: Added YouTube dependencies - functional.py: Minor tweaks - modules/youtube.py: Helper for upload node - video.py: Minor cleanup - tests/test_youtube_nodes.py: Test for YouTube upload
74 lines
2.7 KiB
Python
74 lines
2.7 KiB
Python
import subprocess
|
|
import os
|
|
|
|
NODE_CLASS_MAPPINGS = {}
|
|
NODE_DISPLAY_NAME_MAPPINGS = {}
|
|
|
|
|
|
def ETK_youtube_base(cls):
|
|
cls.CATEGORY = "ETK/Youtube"
|
|
NODE_CLASS_MAPPINGS[cls.__name__] = cls
|
|
return cls
|
|
|
|
|
|
@ETK_youtube_base
|
|
class YoutubeUploadNode:
|
|
VALID_PRIVACY_STATUSES = ["public", "private", "unlisted"]
|
|
VALID_CATEGORIES = [1, 2, 10, 15, 17, 19, 20, 22, 23, 24, 25, 26, 27, 28, 29]
|
|
CATEGORY_NAMES = ['Film & Animation', 'Autos & Vehicles', 'Music', 'Pets & Animals', 'Sports', 'Travel & Events',
|
|
'Gaming', 'People & Blogs', 'Comedy', 'Entertainment', 'News & Politics', 'Howto & Style',
|
|
'Education', 'Science & Technology', 'Nonprofits & Activism']
|
|
|
|
OUTPUT_NODE = True
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"file_path": ("STRING", {"description": "Path to the video file to upload"}),
|
|
"category": (cls.CATEGORY_NAMES,),
|
|
"title": ("STRING", {"default": "My video", "description": "Title of the video"}),
|
|
"description": ("STRING", {"default": "My video description", "multiline": True,
|
|
"description": "Description of the video"}),
|
|
"keywords": ("STRING", {"default": "tag1, tag2, tag3", "description": "Keywords for the video"}),
|
|
"privacy_status": (cls.VALID_PRIVACY_STATUSES,)
|
|
}
|
|
}
|
|
|
|
RETURN_TYPES = ('STRING',)
|
|
FUNCTION = "upload_video"
|
|
CATEGORY = "ETK/Youtube"
|
|
|
|
def upload_video(self, file_path, category, title, description, keywords, privacy_status):
|
|
import sys
|
|
my_python_exe = sys.executable
|
|
|
|
category = self.CATEGORY_NAMES.index(category)
|
|
|
|
args = ["--file", file_path, "--category", str(category), "--title", title, "--description", description,
|
|
"--keywords", keywords, "--privacyStatus", privacy_status]
|
|
|
|
current_dir = os.getcwd()
|
|
os.chdir(os.path.dirname(os.path.realpath(__file__)))
|
|
|
|
# result = subprocess.run([my_python_exe, "./modules/youtube.py"] + args,
|
|
# capture_output=True,
|
|
# text=True)
|
|
|
|
# the above does not capture the output, so we use the below instead
|
|
result = subprocess.run([my_python_exe, "./modules/youtube.py"] + args,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.PIPE,
|
|
text=True)
|
|
|
|
os.chdir(current_dir)
|
|
error = result.stderr
|
|
if error:
|
|
raise Exception(error)
|
|
|
|
return (result.stdout,)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
pass
|