Spaces:
Sleeping
Sleeping
File size: 9,567 Bytes
16c970a |
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 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 |
import cv2
from moviepy.editor import VideoFileClip, concatenate_videoclips
import tempfile
import os
class ClipGenerator:
def __init__(self, target_duration: int = 60, min_confidence: float = 0.9):
self.target_duration = target_duration # durée cible en secondes
self.min_confidence = min_confidence
print(f"[DEBUG] Initialized ClipGenerator with target_duration={target_duration}s, min_confidence={min_confidence}")
def _time_to_seconds(self, time_str: str) -> float:
h, m, s = time_str.split(':')
return int(h) * 3600 + int(m) * 60 + float(s)
def _seconds_to_time(self, seconds: float) -> str:
h = int(seconds // 3600)
m = int((seconds % 3600) // 60)
s = seconds % 60
return f"{h:02d}:{m:02d}:{s:06.3f}"
def generate_clips(self, video_path: str, scenes: list, sport_id: str) -> list:
print(f"\n[DEBUG] Starting clip generation for {sport_id}")
print(f"[DEBUG] Input scenes: {len(scenes)}")
# Debug chaque scène avant filtrage
for scene in scenes:
print(f"[DEBUG] Pre-filter scene:")
print(f" - Start: {scene['start']}")
print(f" - End: {scene['end']}")
print(f" - Sport: {scene['recognized_sport']}")
print(f" - Confidence: {scene['confidence']}")
print(f" - Would pass sport filter: {scene['recognized_sport'] == sport_id}")
print(f" - Would pass confidence filter: {scene['confidence'] >= self.min_confidence}")
filtered_scenes = [
scene for scene in scenes
if scene["recognized_sport"].lower() == sport_id.lower()
and scene["confidence"] >= self.min_confidence
]
print(f"[DEBUG] Filtered scenes: {len(filtered_scenes)}")
for scene in filtered_scenes:
print(f"[DEBUG] Scene: {scene['start']} -> {scene['end']} (conf: {scene['confidence']:.2%}) sport_id: {sport_id}")
if not filtered_scenes:
print("[DEBUG] No valid scenes found after filtering")
return []
clips_data = []
current_segments = []
current_duration = 0
clip_number = 1
for scene in filtered_scenes:
print(f"\n[DEBUG] Processing scene {scene['start']} -> {scene['end']}")
scene_start = self._time_to_seconds(scene["start"])
scene_end = self._time_to_seconds(scene["end"])
scene_duration = scene_end - scene_start
print(f"[DEBUG] Scene duration: {scene_duration:.2f}s")
print(f"[DEBUG] Current accumulated duration: {current_duration:.2f}s")
if current_duration + scene_duration > self.target_duration:
remaining_duration = self.target_duration - current_duration
print(f"[DEBUG] Scene would exceed target duration. Remaining space: {remaining_duration:.2f}s")
if remaining_duration > 0:
segment_end = self._seconds_to_time(scene_start + remaining_duration)
current_segments.append({
"start": scene["start"],
"end": segment_end,
"confidence": scene["confidence"]
})
print(f"[DEBUG] Added partial segment: {scene['start']} -> {segment_end}")
clip_data = self._create_clip(video_path, current_segments, clip_number)
clips_data.append(clip_data)
print(f"[DEBUG] Created clip {clip_number} with {len(current_segments)} segments")
clip_number += 1
current_segments = []
current_duration = 0
remaining_scene_duration = scene_duration - remaining_duration
print(f"[DEBUG] Remaining scene duration to process: {remaining_scene_duration:.2f}s")
while remaining_scene_duration > 0:
if remaining_scene_duration >= self.target_duration:
segment_start = self._seconds_to_time(scene_start + scene_duration - remaining_scene_duration)
segment_end = self._seconds_to_time(scene_start + scene_duration - remaining_scene_duration + self.target_duration)
segment = {
"start": segment_start,
"end": segment_end,
"confidence": scene["confidence"]
}
print(f"[DEBUG] Creating full clip from remaining: {segment_start} -> {segment_end}")
clip_data = self._create_clip(video_path, [segment], clip_number)
clips_data.append(clip_data)
clip_number += 1
remaining_scene_duration -= self.target_duration
else:
segment_start = self._seconds_to_time(scene_end - remaining_scene_duration)
current_segments = [{
"start": segment_start,
"end": scene["end"],
"confidence": scene["confidence"]
}]
print(f"[DEBUG] Keeping remainder for next clip: {segment_start} -> {scene['end']}")
current_duration = remaining_scene_duration
break
else:
current_segments.append({
"start": scene["start"],
"end": scene["end"],
"confidence": scene["confidence"]
})
current_duration += scene_duration
print(f"[DEBUG] Added full scene to current clip. New duration: {current_duration:.2f}s")
if current_segments:
print(f"\n[DEBUG] Processing remaining segments")
clip_data = self._create_clip(video_path, current_segments, clip_number)
clips_data.append(clip_data)
print(f"[DEBUG] Created final clip {clip_number} with {len(current_segments)} segments")
print(f"\n[DEBUG] Generated {len(clips_data)} clips in total")
return clips_data
def _create_clip(self, video_path: str, segments: list, clip_number: int) -> dict:
"""Crée un clip à partir des segments donnés."""
total_duration = sum(
self._time_to_seconds(segment["end"]) - self._time_to_seconds(segment["start"])
for segment in segments
)
print(f"[DEBUG] Creating clip {clip_number}")
print(f"[DEBUG] Total duration: {total_duration:.2f}s")
# Créer les sous-clips pour chaque segment
subclips = []
video = VideoFileClip(video_path)
for segment in segments:
start_time = self._time_to_seconds(segment["start"])
end_time = self._time_to_seconds(segment["end"])
print(f"[DEBUG] Extracting segment: {segment['start']} -> {segment['end']}")
subclip = video.subclip(start_time, end_time)
subclips.append(subclip)
# Concaténer tous les sous-clips
final_clip = concatenate_videoclips(subclips)
# Créer un fichier temporaire pour le clip
temp_clip_file = tempfile.NamedTemporaryFile(suffix='.mp4', delete=False)
final_clip.write_videofile(
temp_clip_file.name,
codec='libx264',
audio_codec='aac',
temp_audiofile='temp-audio.m4a',
remove_temp=True
)
# Fermer les clips pour libérer la mémoire
final_clip.close()
for subclip in subclips:
subclip.close()
video.close()
total_confidence = sum(segment["confidence"] for segment in segments)
avg_confidence = total_confidence / len(segments)
return {
"segments": segments,
"clip_number": clip_number,
"confidence": avg_confidence,
"duration": total_duration,
"file_path": temp_clip_file.name # Ajouter le chemin du fichier
}
if __name__ == "__main__":
# Test local
test_video_path = "test_video.mp4" # Remplacer par un chemin réel
test_scenes = [
{
"start": "00:00:00.000",
"end": "00:00:30.000",
"recognized_sport": "surf",
"confidence": 0.95
},
{
"start": "00:00:40.000",
"end": "00:01:20.000",
"recognized_sport": "surf",
"confidence": 0.92
},
{
"start": "00:01:30.000",
"end": "00:02:00.000",
"recognized_sport": "not_surf",
"confidence": 0.88
}
]
clip_generator = ClipGenerator(target_duration=60, min_confidence=0.9)
clips = clip_generator.generate_clips(test_video_path, test_scenes, "surf")
print("\nClips générés :")
for i, clip in enumerate(clips, 1):
print(f"\nClip {i}:")
print(f"Confidence: {clip['confidence']:.2%}")
print("Segments:")
for segment in clip['segments']:
print(f" {segment['start']} -> {segment['end']} (conf: {segment['confidence']:.2%})") |