@@ -215,6 +215,7 @@ def _get_target_frames_count(video_path, target_fps):
215215 """
216216 Get video frames count
217217 """
218+ # deprecated : because cv2.CAP_PROP_FPS in not reliable
218219 video = cv2 .VideoCapture (str (video_path ), cv2 .CAP_FFMPEG )
219220 total_num_of_frames = 0
220221 flag = True
@@ -225,7 +226,7 @@ def _get_target_frames_count(video_path, target_fps):
225226 else :
226227 break
227228
228- return math .ceil ((total_num_of_frames * target_fps ) / video .get (cv2 .CAP_PROP_FPS ))
229+ return math .ceil ((total_num_of_frames * target_fps ) / video .get (cv2 .CAP_PROP_FPS ))
229230
230231
231232def _get_video_frames_count (video_path ):
@@ -244,22 +245,22 @@ def _get_video_frames_count(video_path):
244245 return total_num_of_frames
245246
246247
247- def _get_video_fps_ration (target_fps , video , ratio ):
248+ def _get_video_fps_ration (target_fps , video , ratio , log ):
248249 """
249250 Get video fps / target fps ratio
250251 """
251252 video_fps = float (video .get (cv2 .CAP_PROP_FPS ))
252- if target_fps >= video_fps :
253+ if target_fps >= video_fps and log :
253254 logger .warning (
254255 "Video frame rate %s smaller than target frame rate %s. Cannot change frame rate." ,
255256 video_fps , target_fps
256257 )
257258 else :
258-
259- logger .info (
260- "Changing video frame rate from %s to target frame rate %s." ,
261- video_fps , target_fps
262- )
259+ if log :
260+ logger .info (
261+ "Changing video frame rate from %s to target frame rate %s." ,
262+ video_fps , target_fps
263+ )
263264 ratio = video_fps / target_fps
264265 return ratio
265266
@@ -274,7 +275,7 @@ def _get_available_image_counts(project, folder):
274275 return res ['availableImageCount' ]
275276
276277
277- def _get_video_rotate_code (video_path ):
278+ def _get_video_rotate_code (video_path , log = True ):
278279 rotate_code = None
279280 try :
280281 cv2_rotations = {
@@ -286,42 +287,43 @@ def _get_video_rotate_code(video_path):
286287 meta_dict = ffmpeg .probe (str (video_path ))
287288 rot = int (meta_dict ['streams' ][0 ]['tags' ]['rotate' ])
288289 rotate_code = cv2_rotations [rot ]
289- if rot != 0 :
290+ if rot != 0 and log :
290291 logger .info (
291292 "Frame rotation of %s found. Output images will be rotated accordingly." ,
292293 rot
293294 )
294295 except Exception as e :
295296 warning_str = ""
296- if "ffprobe" in str (e ):
297+ if "ffprobe" in str (e ) and log :
297298 warning_str = "This could be because ffmpeg package is not installed. To install it, run: sudo apt install ffmpeg"
298299
299- logger .warning (
300- "Couldn't read video metadata to determine rotation. %s" ,
301- warning_str
302- )
300+ if log :
301+ logger .warning (
302+ "Couldn't read video metadata to determine rotation. %s" ,
303+ warning_str
304+ )
303305 return rotate_code
304306
305307
306308def _extract_frames_from_video (
307- start_time , end_time , video_path , tempdir , limit , target_fps , chunk_size
309+ start_time , end_time , video_path , tempdir , limit , target_fps , chunk_size , save
308310):
309311 video = cv2 .VideoCapture (str (video_path ), cv2 .CAP_FFMPEG )
310312 if not video .isOpened ():
311313 raise SABaseException (0 , "Couldn't open video file " + str (video_path ))
312314 total_num_of_frames = _get_video_frames_count (video_path )
313-
314- logger .info ("Video frame count is %s." , total_num_of_frames )
315+ if save :
316+ logger .info ("Video frame count is %s." , total_num_of_frames )
315317 ratio = 1.0
316318 if target_fps :
317- ratio = _get_video_fps_ration (target_fps , video , ratio )
318- rotate_code = _get_video_rotate_code (video_path )
319+ ratio = _get_video_fps_ration (target_fps , video , ratio , log = save )
320+ rotate_code = _get_video_rotate_code (video_path , log = save )
319321 video_name = Path (video_path ).stem
320322 frame_no = 0
321323 frame_no_with_change = 1.0
322324 extracted_frame_no = 1
323-
324- logger .info ("Extracting frames from video to %s." , tempdir .name )
325+ if save :
326+ logger .info ("Extracting frames from video to %s." , tempdir .name )
325327 zero_fill_count = len (str (total_num_of_frames ))
326328 extracted_frames_paths = []
327329 all_paths = []
@@ -346,8 +348,8 @@ def _extract_frames_from_video(
346348 str (extracted_frame_no ).zfill (zero_fill_count ) + ".jpg"
347349 )
348350 )
349-
350- cv2 .imwrite (path , frame )
351+ if save :
352+ cv2 .imwrite (path , frame )
351353 extracted_frames_paths .append (path )
352354 extracted_frame_no += 1
353355 if len (extracted_frames_paths ) % chunk_size == 0 :
@@ -362,6 +364,7 @@ def _extract_frames_from_video(
362364 yield q
363365 return extracted_frames_paths
364366
367+
365368@Trackable
366369def upload_video_to_project (
367370 project ,
@@ -420,10 +423,16 @@ def upload_video_to_project(
420423 tempdir = tempfile .TemporaryDirectory ()
421424 upload_file_names = []
422425 chunk_size = 100
423- all_frames_count = _get_target_frames_count (video_path , target_fps )
426+ all_frames_count = 0
427+
428+ for frames_path in _extract_frames_from_video (
429+ start_time , end_time , video_path , tempdir , limit , target_fps , chunk_size , False
430+ ):
431+ all_frames_count += len (frames_path )
432+
424433 pbar = None
425434 for _ in _extract_frames_from_video (
426- start_time , end_time , video_path , tempdir , limit , target_fps , chunk_size
435+ start_time , end_time , video_path , tempdir , limit , target_fps , chunk_size , save = True
427436 ):
428437 if not pbar :
429438 pbar = tqdm (total = all_frames_count )
@@ -471,7 +480,7 @@ def upload_videos_from_folder_to_project(
471480 :type project: str
472481 :param folder_path: from which folder to upload the videos
473482 :type folder_path: Pathlike (str or Path)
474- :param extensions: tuple or list of filename extensions to include from folder
483+ :param extensions: tuple or list of filename extensions to include from folder
475484 :type extensions: tuple or list of strs
476485 :param exclude_file_patterns: filename patterns to exclude from uploading
477486 :type exclude_file_patterns: listlike of strs
@@ -751,7 +760,7 @@ def attach_image_urls_to_project(
751760 project , attachments , annotation_status = "NotStarted"
752761):
753762 """Link images on external storage to SuperAnnotate.
754-
763+
755764 :param project: project name or project folder path
756765 :type project: str or dict
757766 :param attachments: path to csv file on attachments metadata
0 commit comments