File size: 3,226 Bytes
ead274c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
"""End-to-end: run the full Oz_ShotSplitter pipeline on real samples."""

import importlib.util
import os
import sys

import pytest

PACK_DIR = "/workspace/ComfyUI/custom_nodes/ComfyUI-ShotSplitter"


def _load_pack():
    """Load the hyphenated-name pack as a proper Python package."""
    if "/workspace/ComfyUI" not in sys.path:
        sys.path.insert(0, "/workspace/ComfyUI")

    if "ComfyUI_ShotSplitter" in sys.modules:
        return sys.modules["ComfyUI_ShotSplitter"]

    spec = importlib.util.spec_from_file_location(
        "ComfyUI_ShotSplitter",
        os.path.join(PACK_DIR, "__init__.py"),
        submodule_search_locations=[PACK_DIR],
    )
    mod = importlib.util.module_from_spec(spec)
    sys.modules["ComfyUI_ShotSplitter"] = mod
    spec.loader.exec_module(mod)
    return mod


THREESHOT = "test_3shots.mp4"
REEL = "reel_multishot.mp4"


@pytest.mark.skipif(
    not os.path.exists(f"/workspace/ComfyUI/input/{THREESHOT}"),
    reason="synthetic sample missing",
)
def test_e2e_3shot_synthetic_produces_three_clips():
    pack = _load_pack()
    node = pack.Oz_ShotSplitter()
    out = node.run(
        video=THREESHOT,
        detector="ensemble",
        min_shot_seconds=0.3,
        merge_window_frames=3,
        adaptive_threshold=3.0,
        transnet_threshold=0.5,
        output_subfolder="shots/e2e_syn_test",
        filename_prefix="shot",
        crf=23,
        preset="veryfast",
        keep_audio=True,
    )
    assert "result" in out
    clip_paths, first_frames, shot_count, manifest_json = out["result"]
    print(f"\n[E2E synthetic] shot_count={shot_count}")
    print(f"[E2E synthetic] clip_paths={clip_paths}")
    assert shot_count == 3, f"expected 3 shots for synthetic red/green/blue, got {shot_count}"
    assert len(clip_paths) == 3
    assert first_frames.shape[0] == 3
    assert all(os.path.isfile(p) for p in clip_paths)
    import json as _json
    manifest = _json.loads(manifest_json)
    assert len(manifest) == 3

    # Verify the ui.videos payload is populated
    assert "ui" in out
    assert "videos" in out["ui"]
    assert len(out["ui"]["videos"]) == 3
    for v in out["ui"]["videos"]:
        assert v["filename"].endswith(".mp4")
        assert v["subfolder"] == "shots/e2e_syn_test"
        assert v["type"] == "output"


@pytest.mark.skipif(
    not os.path.exists(f"/workspace/ComfyUI/input/{REEL}"),
    reason="reel sample missing",
)
def test_e2e_real_reel_produces_two_or_more_clips():
    pack = _load_pack()
    node = pack.Oz_ShotSplitter()
    out = node.run(
        video=REEL,
        detector="ensemble",
        min_shot_seconds=0.5,
        merge_window_frames=3,
        adaptive_threshold=3.0,
        transnet_threshold=0.5,
        output_subfolder="shots/e2e_reel_test",
        filename_prefix="shot",
        crf=23,
        preset="veryfast",
        keep_audio=True,
    )
    clip_paths, first_frames, shot_count, manifest_json = out["result"]
    print(f"\n[E2E reel] shot_count={shot_count}")
    print(f"[E2E reel] clip_paths={clip_paths}")
    assert shot_count >= 2, f"expected >=2 shots in reel, got {shot_count}"
    assert all(os.path.isfile(p) for p in clip_paths)
    assert first_frames.shape[0] == shot_count