File size: 3,519 Bytes
345855e 59215bb 345855e 59215bb 345855e 59215bb 345855e 59215bb | 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 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | from moviepy.editor import VideoFileClip
import logging
from pathlib import Path
logger = logging.getLogger(__name__)
# =====================================================
# SEGMENT NORMALIZER (CRITICAL V8 FIX)
# =====================================================
def normalize_segments(segments):
"""
Accepts:
- dict segments: {"start": x, "end": y}
- list segments: [{"start":x,"end":y}, ...]
- tuple/list segments: [(start,end), ...]
Returns:
- clean list of dicts
"""
if not segments:
return []
normalized = []
# Case 1: single dict
if isinstance(segments, dict):
segments = [segments]
for s in segments:
# dict format (preferred)
if isinstance(s, dict):
if "start" in s and "end" in s:
normalized.append({
"start": float(s["start"]),
"end": float(s["end"])
})
continue
# grouped word segments from detect_highlights()
if (
isinstance(s, (list, tuple))
and s
and isinstance(s[0], dict)
and isinstance(s[-1], dict)
and "start" in s[0]
and "end" in s[-1]
):
normalized.append({
"start": float(s[0]["start"]),
"end": float(s[-1]["end"]),
})
continue
# list/tuple format
if isinstance(s, (list, tuple)) and len(s) >= 2:
try:
normalized.append({
"start": float(s[0]),
"end": float(s[1])
})
except Exception:
continue
return normalized
# =====================================================
# CORE CLIP GENERATOR (SAFE VERSION)
# =====================================================
def create_clip(video_path, start, end, index):
"""
Creates a single clip safely with validation
"""
try:
start = float(start)
end = float(end)
if end <= start:
logger.warning(f"Invalid segment skipped: {start}-{end}")
return None
clip = VideoFileClip(video_path).subclip(start, end)
source = Path(video_path)
output = str(source.with_name(f"{source.stem}_clip_{index}.mp4"))
clip.write_videofile(
output,
codec="libx264",
audio_codec="aac",
preset="ultrafast",
threads=2,
logger=None # prevents HF log spam
)
return output
except Exception as e:
logger.error(f"Clip creation failed: {str(e)}")
return None
# =====================================================
# BATCH CLIP ENGINE (V8 AUTOCUT CORE FIX)
# =====================================================
def create_clips(video_path, segments):
"""
Main entry used by V8 Highlights / AutoClip engine
"""
segments = normalize_segments(segments)
if not segments:
logger.warning("No valid segments found")
return []
outputs = []
for i, seg in enumerate(segments):
try:
out = create_clip(
video_path,
seg["start"],
seg["end"],
i
)
if out:
outputs.append(out)
except Exception as e:
logger.error(f"Segment {i} failed: {str(e)}")
continue
return outputs
|