yta-video-frame-time 0.0.1__tar.gz → 0.0.14__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,12 +1,14 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: yta-video-frame-time
3
- Version: 0.0.1
3
+ Version: 0.0.14
4
4
  Summary: Youtube Autonomous Video Frame Time Module
5
+ License-File: LICENSE
5
6
  Author: danialcala94
6
7
  Author-email: danielalcalavalera@gmail.com
7
8
  Requires-Python: ==3.9
8
9
  Classifier: Programming Language :: Python :: 3
9
10
  Classifier: Programming Language :: Python :: 3.9
11
+ Requires-Dist: quicktions (>=0.0.1,<9.0.0)
10
12
  Requires-Dist: yta_validation (>=0.0.1,<1.0.0)
11
13
  Description-Content-Type: text/markdown
12
14
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "yta-video-frame-time"
3
- version = "0.0.1"
3
+ version = "0.0.14"
4
4
  description = "Youtube Autonomous Video Frame Time Module"
5
5
  authors = [
6
6
  {name = "danialcala94",email = "danielalcalavalera@gmail.com"}
@@ -9,6 +9,7 @@ readme = "README.md"
9
9
  requires-python = "==3.9"
10
10
  dependencies = [
11
11
  "yta_validation (>=0.0.1,<1.0.0)",
12
+ "quicktions (>=0.0.1,<9.0.0)"
12
13
  ]
13
14
 
14
15
  [tool.poetry]
@@ -16,6 +17,7 @@ packages = [{include = "yta_video_frame_time", from = "src"}]
16
17
 
17
18
  [tool.poetry.group.dev.dependencies]
18
19
  pytest = "^8.3.5"
20
+ yta_testing = ">=0.0.1"
19
21
 
20
22
  [build-system]
21
23
  requires = ["poetry-core>=2.0.0,<3.0.0"]
@@ -2,6 +2,7 @@
2
2
  Module to handle frame indexes and times.
3
3
  """
4
4
  from yta_validation.parameter import ParameterValidator
5
+ from typing import Union
5
6
 
6
7
 
7
8
  SMALL_AMOUNT_TO_FIX = 0.0000000001
@@ -14,7 +15,6 @@ be 10 frames and it is happening due to a minimal
14
15
  floating point difference.
15
16
  """
16
17
 
17
-
18
18
  class T:
19
19
  """
20
20
  Class to wrap the functionality related
@@ -36,11 +36,13 @@ class T:
36
36
  ParameterValidator.validate_mandatory_positive_number('t', t, do_include_zero = True)
37
37
  ParameterValidator.validate_mandatory_positive_number('fps', fps, do_include_zero = False)
38
38
 
39
- return T.frame_time_to_frame_index(t, fps) / fps + SMALL_AMOUNT_TO_FIX
40
-
39
+ return T.video_frame_time_to_video_frame_index(t, fps) / fps + SMALL_AMOUNT_TO_FIX
40
+
41
41
  def get_frame_indexes(
42
42
  duration: float,
43
43
  fps: float,
44
+ start: Union[float, None] = None,
45
+ end: Union[float, None] = None,
44
46
  do_invert_order: bool = False
45
47
  ):
46
48
  """
@@ -59,6 +61,28 @@ class T:
59
61
  # If you remove 'list' you get a generator instead
60
62
  frame_indexes = list(range(get_number_of_frames(duration, fps)))
61
63
 
64
+ # TODO: Maybe move this to a helper (?)
65
+ # Limit to ['start', 'end'] range
66
+ if (
67
+ start is not None or
68
+ end is not None
69
+ ):
70
+ start = (
71
+ T.video_frame_time_to_video_frame_index(start, fps)
72
+ if start is not None else
73
+ 0.0
74
+ )
75
+ end = (
76
+ T.video_frame_time_to_video_frame_index(end, fps)
77
+ if end is not None else
78
+ 9999999999
79
+ )
80
+ frame_indexes = [
81
+ frame_index
82
+ for frame_index in frame_indexes
83
+ if start <= frame_index < end
84
+ ]
85
+
62
86
  return (
63
87
  frame_indexes[::-1]
64
88
  if do_invert_order else
@@ -286,6 +310,8 @@ class T:
286
310
  def get_frame_time_moments(
287
311
  duration: float,
288
312
  fps: float,
313
+ start: Union[float, None] = None,
314
+ end: Union[float, None] = None,
289
315
  do_invert_order: bool = False
290
316
  ):
291
317
  """
@@ -313,6 +339,28 @@ class T:
313
339
  for i in range(get_number_of_frames(duration, fps) + 1)
314
340
  ][:-1]
315
341
 
342
+ # TODO: Maybe move this to a helper (?)
343
+ # Limit to ['start', 'end'] range
344
+ if (
345
+ start is not None or
346
+ end is not None
347
+ ):
348
+ start = (
349
+ start
350
+ if start is not None else
351
+ 0.0
352
+ )
353
+ end = (
354
+ end
355
+ if end is not None else
356
+ 9999999999
357
+ )
358
+ frame_time_moments = [
359
+ frame_time_moment
360
+ for frame_time_moment in frame_time_moments
361
+ if start <= frame_time_moment < end
362
+ ]
363
+
316
364
  return (
317
365
  frame_time_moments[::-1]
318
366
  if do_invert_order else
@@ -409,19 +457,20 @@ class T:
409
457
  ParameterValidator.validate_mandatory_positive_number('audio_fps', audio_fps, do_include_zero = False)
410
458
  ParameterValidator.validate_mandatory_bool('do_invert_order', do_invert_order)
411
459
 
412
- from yta_general_utils.math.progression import Progression
413
-
414
460
  audio_frames_per_video_frame = int(audio_fps / video_fps)
415
461
  audio_frame_duration = 1 / audio_fps
416
462
  video_frame_duration = 1 / video_fps
417
463
 
418
464
  t = T.get_frame_time_base(video_t, video_fps)
419
465
 
420
- audio_time_moments = Progression(
421
- start = t,
466
+ # This is replacing a 'Progression' from
467
+ # the 'yta_general_utils' library because
468
+ # it has many imports we don't want here...
469
+ audio_time_moments = _linspace(
470
+ start = t,
422
471
  end = t + video_frame_duration - audio_frame_duration,
423
472
  n = audio_frames_per_video_frame
424
- ).values
473
+ )
425
474
 
426
475
  return (
427
476
  audio_time_moments[::-1]
@@ -540,4 +589,29 @@ def get_number_of_frames(
540
589
  The formula is:
541
590
  - `int(duration * fps + SMALL_AMOUNT)`
542
591
  """
543
- return int(duration * fps + SMALL_AMOUNT_TO_FIX)
592
+ return int(duration * fps + SMALL_AMOUNT_TO_FIX)
593
+
594
+ def _linspace(
595
+ start: float,
596
+ end: float,
597
+ n: int,
598
+ ):
599
+ """
600
+ *For internal use only*
601
+
602
+ A simplified version of the 'Progression'
603
+ class we have in 'yta_general_utils', to
604
+ avoid importing that library that has other
605
+ dependencies I don't need here.
606
+
607
+ This method should be removed when the
608
+ Progression class is refactored and all
609
+ those dependencies are removed.
610
+ """
611
+ if n < 2:
612
+ raise Exception('The "n" parameter must be greater or equal than 2.')
613
+
614
+ return [
615
+ start + i * ((end - start) / (n - 1))
616
+ for i in range(n)
617
+ ]
@@ -0,0 +1,52 @@
1
+ """
2
+ TODO: I think this module should not be here, or maybe
3
+ yes, but I need this decorator.
4
+ """
5
+ from functools import wraps
6
+
7
+
8
+ def parameter_to_time_interval(
9
+ param_name: str
10
+ ):
11
+ """
12
+ Force the parameter with the given `param_name` to
13
+ be a `TimeInterval` instance.
14
+
15
+ Values accepted:
16
+ - `TimeInterval` instance
17
+ - `tuple[float, float]` that will be `(start, end)`
18
+ """
19
+ def decorator(
20
+ func
21
+ ):
22
+ @wraps(func)
23
+ def wrapper(
24
+ *args,
25
+ **kwargs
26
+ ):
27
+ from inspect import signature
28
+ from yta_validation import PythonValidator
29
+ from yta_video_frame_time.interval import TimeInterval
30
+
31
+ sig = signature(func)
32
+ bound = sig.bind(*args, **kwargs)
33
+ bound.apply_defaults()
34
+
35
+ value = bound.arguments[param_name]
36
+
37
+ if PythonValidator.is_instance_of(value, TimeInterval):
38
+ pass
39
+ elif (
40
+ PythonValidator.is_tuple(value) and
41
+ len(value) == 2
42
+ ):
43
+ value = TimeInterval(*value)
44
+ bound.arguments[param_name] = value
45
+ else:
46
+ raise Exception(f'The "{param_name}" parameter must be a TimeInterval or a tuple[float, float].')
47
+
48
+ return func(*bound.args, **bound.kwargs)
49
+
50
+ return wrapper
51
+
52
+ return decorator