Chaitanya-aitf commited on
Commit
657867c
·
verified ·
1 Parent(s): f27e836

Update core/clip_extractor.py

Browse files
Files changed (1) hide show
  1. core/clip_extractor.py +47 -7
core/clip_extractor.py CHANGED
@@ -123,14 +123,16 @@ class ClipExtractor:
123
  candidates: List[ClipCandidate],
124
  num_clips: int,
125
  enforce_diversity: bool = True,
 
126
  ) -> List[ClipCandidate]:
127
  """
128
- Select top clips from candidates.
129
 
130
  Args:
131
  candidates: List of clip candidates with scores
132
  num_clips: Number of clips to select
133
  enforce_diversity: Enforce minimum gap between clips
 
134
 
135
  Returns:
136
  List of selected ClipCandidate objects
@@ -147,9 +149,23 @@ class ClipExtractor:
147
  if not enforce_diversity:
148
  return sorted_candidates[:num_clips]
149
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
  # Select with diversity constraint
151
  selected = []
152
- min_gap = self.config.min_gap_between_clips
153
 
154
  for candidate in sorted_candidates:
155
  if len(selected) >= num_clips:
@@ -167,11 +183,33 @@ class ClipExtractor:
167
  if is_diverse:
168
  selected.append(candidate)
169
 
170
- # If we couldn't get enough with diversity, relax constraint
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
  if len(selected) < num_clips:
172
  logger.warning(
173
  f"Only {len(selected)} diverse clips found, "
174
- f"relaxing diversity constraint"
175
  )
176
  for candidate in sorted_candidates:
177
  if candidate not in selected:
@@ -179,7 +217,7 @@ class ClipExtractor:
179
  if len(selected) >= num_clips:
180
  break
181
 
182
- logger.info(f"Selected {len(selected)} clips from {len(candidates)} candidates")
183
  return selected
184
 
185
  def adjust_to_scene_boundaries(
@@ -246,6 +284,7 @@ class ClipExtractor:
246
  num_clips: Optional[int] = None,
247
  generate_thumbnails: bool = True,
248
  reencode: bool = False,
 
249
  ) -> List[ExtractedClip]:
250
  """
251
  Extract clips from video.
@@ -257,6 +296,7 @@ class ClipExtractor:
257
  num_clips: Number of clips to extract (None = use config default)
258
  generate_thumbnails: Whether to generate thumbnails
259
  reencode: Whether to re-encode clips (slower but precise)
 
260
 
261
  Returns:
262
  List of ExtractedClip objects
@@ -266,8 +306,8 @@ class ClipExtractor:
266
  num_clips = num_clips or self.config.default_num_clips
267
 
268
  with LogTimer(logger, f"Extracting {num_clips} clips"):
269
- # Select top clips
270
- selected = self.select_clips(candidates, num_clips)
271
 
272
  if not selected:
273
  logger.warning("No clips to extract")
 
123
  candidates: List[ClipCandidate],
124
  num_clips: int,
125
  enforce_diversity: bool = True,
126
+ video_duration: Optional[float] = None,
127
  ) -> List[ClipCandidate]:
128
  """
129
+ Select top clips from candidates with adaptive diversity.
130
 
131
  Args:
132
  candidates: List of clip candidates with scores
133
  num_clips: Number of clips to select
134
  enforce_diversity: Enforce minimum gap between clips
135
+ video_duration: Total video duration for adaptive gap calculation
136
 
137
  Returns:
138
  List of selected ClipCandidate objects
 
149
  if not enforce_diversity:
150
  return sorted_candidates[:num_clips]
151
 
152
+ # Calculate adaptive minimum gap based on video duration
153
+ # For longer videos, we want clips spread across the entire video
154
+ if video_duration and video_duration > 0:
155
+ # Target: clips should be spread across the video
156
+ # Divide video into (num_clips + 1) sections, min_gap is section size
157
+ adaptive_gap = video_duration / (num_clips + 1)
158
+ # But don't go below config minimum or above 1/3 of video
159
+ min_gap = max(
160
+ self.config.min_gap_between_clips,
161
+ min(adaptive_gap, video_duration / 3)
162
+ )
163
+ logger.debug(f"Adaptive min_gap: {min_gap:.1f}s for {video_duration:.1f}s video")
164
+ else:
165
+ min_gap = self.config.min_gap_between_clips
166
+
167
  # Select with diversity constraint
168
  selected = []
 
169
 
170
  for candidate in sorted_candidates:
171
  if len(selected) >= num_clips:
 
183
  if is_diverse:
184
  selected.append(candidate)
185
 
186
+ # If we couldn't get enough with strict diversity, progressively relax
187
+ if len(selected) < num_clips:
188
+ # Try with 50% of the gap
189
+ relaxed_gap = min_gap * 0.5
190
+ logger.info(f"Relaxing diversity to {relaxed_gap:.1f}s gap")
191
+
192
+ for candidate in sorted_candidates:
193
+ if len(selected) >= num_clips:
194
+ break
195
+ if candidate in selected:
196
+ continue
197
+
198
+ is_diverse = True
199
+ for existing in selected:
200
+ gap = abs(candidate.start_time - existing.start_time)
201
+ if gap < relaxed_gap:
202
+ is_diverse = False
203
+ break
204
+
205
+ if is_diverse:
206
+ selected.append(candidate)
207
+
208
+ # Final fallback: just take top clips if still not enough
209
  if len(selected) < num_clips:
210
  logger.warning(
211
  f"Only {len(selected)} diverse clips found, "
212
+ f"filling remaining from top candidates"
213
  )
214
  for candidate in sorted_candidates:
215
  if candidate not in selected:
 
217
  if len(selected) >= num_clips:
218
  break
219
 
220
+ logger.info(f"Selected {len(selected)} clips from {len(candidates)} candidates (gap={min_gap:.1f}s)")
221
  return selected
222
 
223
  def adjust_to_scene_boundaries(
 
284
  num_clips: Optional[int] = None,
285
  generate_thumbnails: bool = True,
286
  reencode: bool = False,
287
+ video_duration: Optional[float] = None,
288
  ) -> List[ExtractedClip]:
289
  """
290
  Extract clips from video.
 
296
  num_clips: Number of clips to extract (None = use config default)
297
  generate_thumbnails: Whether to generate thumbnails
298
  reencode: Whether to re-encode clips (slower but precise)
299
+ video_duration: Total video duration for diversity calculation
300
 
301
  Returns:
302
  List of ExtractedClip objects
 
306
  num_clips = num_clips or self.config.default_num_clips
307
 
308
  with LogTimer(logger, f"Extracting {num_clips} clips"):
309
+ # Select top clips with adaptive diversity
310
+ selected = self.select_clips(candidates, num_clips, video_duration=video_duration)
311
 
312
  if not selected:
313
  logger.warning("No clips to extract")