Files
Claude 3adebb731f Rename FunPack to FunUI (5.0.3 Classy Chopper): /fun endpoint, wink logo, load-time migration of old names
Old project/workflow names and browser settings migrate on load; /funpack redirects to /fun.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016acRss69eH1235eRdFTZHY
2026-10-25 13:11:03 +00:00

45 lines
2.0 KiB
Python

"""FunUI Cut Opening. See the module docstring."""
from comfy_api.latest import io
class FunUICutOpening(io.ComfyNode):
@classmethod
def define_schema(cls) -> io.Schema:
return io.Schema(
node_id="FunUICutOpening",
display_name="FunUI Cut Opening",
category="FunUI/Output",
description="Drop frames off the front of a clip, and the matching stretch of sound.",
inputs=[
io.Image.Input("images"),
io.Int.Input("frames", default=0, min=0, max=4096,
tooltip="How many frames to cut off the front. 0 = keep everything."),
io.Float.Input("fps", default=24.0, min=1.0, max=240.0, step=0.01,
tooltip="The clip's frame rate, so the sound is cut by the same time."),
io.Audio.Input("audio", optional=True),
],
outputs=[
io.Image.Output(display_name="images"),
io.Audio.Output(display_name="audio"),
io.String.Output(display_name="status"),
],
)
@classmethod
def execute(cls, images, frames: int, fps: float, audio=None) -> io.NodeOutput:
total = int(images.shape[0])
# Never an empty clip: that is an obscure crash downstream, where a clip
# that is visibly too short says what happened.
cut = max(0, min(int(frames), total - 1))
if cut == 0:
return io.NodeOutput(images, audio, "nothing cut")
status = f"cut {cut} of {total} frames ({cut / fps:.2f}s)"
if int(frames) > cut:
status += f"; asked for {int(frames)}, but one frame has to stay"
if audio is not None:
wave, rate = audio["waveform"], int(audio["sample_rate"])
samples = min(int(round(cut / float(fps) * rate)), int(wave.shape[-1]))
audio = {**audio, "waveform": wave[..., samples:]}
return io.NodeOutput(images[cut:], audio, status)