Moxie-Multimedia / __init__.py
turtle89431's picture
Upload folder using huggingface_hub
cbbe5c7 verified
Raw History Blame Contribute Delete
6.32 kB
import os
import server
import yaml
import nodes as _nodes
from typing_extensions import override
from comfy_api.latest import ComfyExtension, io
from aiohttp import web
from .nodes import *
from .routes import *
from .utils.bernini_s2v_model_patch import apply_bernini_s2v_model_patches
from .utils.log import install_console_privacy_filter
from .moxie_loader import MoxieMultimediaLoader
from .moxie_project import MoxieProject
from .moxie_combine import MoxieCombine
from .moxie_preview import ModelPreviewOverrideKJ as MoxiePreviewOverride
apply_bernini_s2v_model_patches()
# Keep internal model/vendor names out of the console (incl. ComfyUI core logs).
install_console_privacy_filter()
# Define the path
root_path = os.path.dirname(__file__)
project_name = os.path.basename(root_path)
web_default_version = 'release'
data = None
config_path = os.path.join(root_path, "config.yaml")
if os.path.isfile(config_path):
with open(config_path, 'r') as f:
data = yaml.load(f, Loader=yaml.FullLoader)
if data and "WEB_VERSION" in data:
dist_path = f"dist/{data['WEB_VERSION']}"
else:
dist_path = f"dist/{web_default_version}"
else:
dist_path = f"dist/{web_default_version}"
web_version = data.get("WEB_VERSION", web_default_version) if data else web_default_version
if not os.path.exists(os.path.join(root_path, dist_path)):
print(f"web root {web_version} not found, using default")
dist_path = f"dist/{web_default_version}"
dist_path = os.path.join(root_path, dist_path)
if os.path.exists(dist_path):
# Editor delivery (see web/js/editor-loader.js for the full story):
# core lets WEB_DIRECTORY (./web) overwrite this pack's EXTENSION_WEB_DIRS
# entry, so the browser /extensions listing only contains the helper JS in
# web/js - never dist/release. web/js/editor-loader.js is listed instead
# and imports the editor entry from this pack's own static mount below.
#
# The entry file (index.js) keeps a stable URL across releases, so it is
# served with no-cache and always revalidated (304 when unchanged); its
# relative chunk imports resolve against the same mount and are
# content-hashed, so those may be cached forever.
async def _serve_editor_index(request: web.Request) -> web.StreamResponse:
return web.FileResponse(
os.path.join(dist_path, 'index.js'),
headers={'Cache-Control': 'no-cache, must-revalidate'},
)
server.PromptServer.instance.app.add_routes([
# Do NOT register "/extensions/<pack>/index.js" here: relative chunk
# imports under that URL would resolve into web/ (core's mount) and
# 404. The loader imports "/<pack>/index.js" from this mount instead.
web.get(f"/{project_name}/index.js", _serve_editor_index),
web.static(f"/{project_name}/", dist_path),
])
else:
print(f"Warning: Dist directory not found for {project_name}. Frontend assets will be served.")
# Our own frontend assets (Moxie Preview Override widget)
WEB_DIRECTORY = "./web"
# Register extension
class EasyMediaExtension(ComfyExtension):
@override
async def get_node_list(self) -> list[type[io.ComfyNode]]:
nodes = [
# Moxie consolidated nodes
MoxieMultimediaLoader,
MoxiePreviewOverride,
MoxieProject,
MoxieCombine,
# TimelineEditor
TimelineEditor,
TimelineInfoOutput,
TimelineSegmentOutput,
TimelineSegmentCount,
# MultiTrack
MultiTrackEditor,
MultiImagesLoader,
MultiTrackTaskOutput,
MultiTrackPromptEnhancer,
MultiTrackPromptEnhanceToProject,
MultiTrackPromptEnhanceToProjectApply,
MultiTrackPromptEnhancerImageListBridge,
MultiTrackInfoOutput,
MultiTrackAudioOutput,
# Subtitle
MultiTrackAddSubtitleToVideo,
RecognizeSubtitle,
AddSubtitleToVideo,
# Image
MakeRefsCompositeBySam3,
ImageIndexesToIntList,
# Audio
EasyAudioMerge,
EasyMinimaxH3AudioLock,
# Video
EasySaveVideo,
EasyCompareVideos,
EasyGetAudioFromVideo,
EasyMergeVideos,
EasyMergeVideosFromPaths,
# Split
SplitImages,
SplitAudios,
SplitVideos,
# Make List
MakeImageList,
MakeAudioList,
MakeVideoList,
# Common
EasyModelLoaderPack,
MatchLine,
APIWorkflowGate,
# MiniMax
EasyMiniMaxH3MotionContextHard,
EasyMiniMaxH3ContextSwap,
EasyMiniMaxH3HiResContinuity,
EasyH3MotionContextLatentTrim,
EasyH3ProjectContextLatentLoad,
EasyH3ConditioningCache,
EasyH3SegmentSamplingStart,
EasyH3SamplingPreviewSampler,
EasyMiniMaxH3LatentUpscaler,
EasyMiniMaxH3SelfLiftSampler,
EasyH3SegmentSaveEnd,
EasyH3ContextMediaTrim,
EasyH3PassthroughVideo,
EasyH3AudioContextLatent,
EasyH3LockedAudioDurationAlign,
EasyH3LockedAudioSelect,
EasyH3ProjectArtifact,
EasyH3ProjectStaticPrepare,
EasyMultiTrackProject,
EasyMultiTrackProjectVideoCombine,
EasyMiniMaxH3ToVideo,
EasyMinimaxPromptOverride,
EasyMiniMaxH3ReferenceToVideoBridge,
EasyRemoveH3MotionContextLatent,
# Wan
BerniniModelPatch,
EasyBerniniS2VConditioning,
# LTXV
LTXMultiTrackEncode,
LTXI2VInplaceAndUpsample,
LTXSamplerSimple,
LTXVAddGuidesFromBatchIndexes,
LTXVMakeRefVideo,
]
try:
from comfy_extras.nodes_bernini import BerniniConditioning as CoreBerniniConditioning
except ImportError:
nodes.extend([BerniniConditioning])
nodes.extend(get_minimax_h3_fallback_nodes())
return nodes
async def comfy_entrypoint() -> EasyMediaExtension:
return EasyMediaExtension()