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.
- {yta_video_frame_time-0.0.1 → yta_video_frame_time-0.0.14}/PKG-INFO +4 -2
- {yta_video_frame_time-0.0.1 → yta_video_frame_time-0.0.14}/pyproject.toml +3 -1
- {yta_video_frame_time-0.0.1 → yta_video_frame_time-0.0.14}/src/yta_video_frame_time/__init__.py +83 -9
- yta_video_frame_time-0.0.14/src/yta_video_frame_time/decorators.py +52 -0
- yta_video_frame_time-0.0.14/src/yta_video_frame_time/interval.py +951 -0
- yta_video_frame_time-0.0.14/src/yta_video_frame_time/t_fraction.py +914 -0
- {yta_video_frame_time-0.0.1 → yta_video_frame_time-0.0.14}/LICENSE +0 -0
- {yta_video_frame_time-0.0.1 → yta_video_frame_time-0.0.14}/README.md +0 -0
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: yta-video-frame-time
|
|
3
|
-
Version: 0.0.
|
|
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.
|
|
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"]
|
{yta_video_frame_time-0.0.1 → yta_video_frame_time-0.0.14}/src/yta_video_frame_time/__init__.py
RENAMED
|
@@ -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.
|
|
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
|
-
|
|
421
|
-
|
|
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
|
-
)
|
|
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
|