yta-video-frame-time 0.0.5__py3-none-any.whl → 0.0.6__py3-none-any.whl

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.

Potentially problematic release.


This version of yta-video-frame-time might be problematic. Click here for more details.

@@ -15,7 +15,11 @@ from yta_validation import PythonValidator
15
15
  from quicktions import Fraction
16
16
  from typing import Union
17
17
 
18
+ import math
18
19
 
20
+
21
+ # TODO: This T class has to be removed
22
+ # and replaced by the THandler
19
23
  class T:
20
24
  """
21
25
  Class to simplify the way we work with a
@@ -149,16 +153,9 @@ class T:
149
153
  return T(pts * time_base, time_base)
150
154
 
151
155
 
152
- # TODO: Careful with this below
153
- """
154
- To obtain the pts step, or frame duration in
155
- ticks, you need to apply 2 formulas that are
156
- different according to if the frame is video
157
- or audio:
158
- - Audio: .samples
159
- - Video: int(round((1 / .fps) / .time_base))
160
- """
161
-
156
+ # TODO: This below is interesting, above
157
+ # is old...
158
+
162
159
  def get_ts(
163
160
  start: Union[int, float, Fraction],
164
161
  end: Union[int, float, Fraction],
@@ -173,21 +170,21 @@ def get_ts(
173
170
  [start, end) because the last frame is the
174
171
  start of another time range.
175
172
  """
176
- start = T.from_fps(start, fps).truncated
177
- end = T.from_fps(end, fps).truncated
173
+ thandler = THandler(fps)
174
+
175
+ start = thandler.t.truncated(start)
176
+ end = thandler.t.truncated(end)
178
177
 
179
- time_base = fps_to_time_base(fps)
180
-
181
178
  return [
182
- start + i * time_base
183
- for i in range((end - start) // time_base)
179
+ start + i * thandler.time_base
180
+ for i in range((end - start) // thandler.time_base)
184
181
  ]
185
182
 
186
183
  def round_t(
187
184
  t: Union[int, float, Fraction],
188
185
  time_base = Fraction(1, 60),
189
186
  do_truncate: bool = True
190
- ):
187
+ ) -> Fraction:
191
188
  """
192
189
  Round the given 't' time moment to the most
193
190
  near multiple of the given 'time_base' (or
@@ -216,19 +213,513 @@ def round_t(
216
213
  round(steps) # round(float(steps))
217
214
  )
218
215
 
219
- return snapped_steps * time_base
216
+ return parse_fraction(snapped_steps * time_base)
217
+
218
+ def round_pts(
219
+ pts: int,
220
+ fps: Union[int, float, Fraction] = 60,
221
+ time_base = Fraction(1, 60),
222
+ do_truncate: bool = True
223
+ ) -> int:
224
+ """
225
+ Round the given 'pts' presentation
226
+ timestamp to the most near index
227
+ corresponding pts value (or the previous
228
+ one always if 'do_truncate' is True).
229
+
230
+ This method is very useful to truncate
231
+ 'pts' values in order to get the frames or
232
+ samples for the specific and exact time
233
+ moments according to their fps or sample
234
+ rate (that should be passed as the
235
+ 'time_base' parameter).
236
+
237
+ Pts value is calculated based on the 'fps'
238
+ and 'time_base', but here is an easier
239
+ example using the time moments.
240
+
241
+ Examples below, with `time_base = 1/5`:
242
+ - `t = 0.25` => `0.2` (truncated or rounded)
243
+ - `t = 0.35` => `0.2` (truncated)
244
+ - `t = 0.45` => `0.4` (truncated or rounded)
245
+ - `t = 0.55` => `0.6` (rounded)
246
+ """
247
+ ticks_per_frame = get_ticks_per_frame(fps, time_base)
248
+
249
+ frame_index = pts / ticks_per_frame
250
+
251
+ frame_index = (
252
+ math.floor(frame_index)
253
+ if do_truncate else
254
+ round(frame_index)
255
+ )
256
+
257
+ return int(frame_index * ticks_per_frame)
258
+
259
+ # TODO: Create a 'round_pts'
260
+
261
+ """
262
+ When we are working with the 't' time
263
+ moment we need to use the fps, and when
264
+ we are working with the 'pts' we need
265
+ to use the 'time_base'.
266
+ """
267
+
268
+ class _T:
269
+ """
270
+ Internal class to be used by the THandler
271
+ as a shortcut to the functionality
272
+ related with 't' values.
273
+ """
274
+
275
+ def __init__(
276
+ self,
277
+ t_handler: 'THandler'
278
+ ):
279
+ self._t_handler: THandler = t_handler
280
+ """
281
+ Instance of the parent THandler to
282
+ access to its properties.
283
+ """
284
+
285
+ def from_pts(
286
+ self,
287
+ pts: int,
288
+ do_truncate: Union[bool, None] = True
289
+ ) -> Fraction:
290
+ """
291
+ Get the 't' time moment for the frame
292
+ defined by the 'pts' presentation
293
+ timestamp.
294
+
295
+ If 't' is in a [start, end) range, we
296
+ will obtain the 'start' value if 't'
297
+ value is closer to it than to the 'end
298
+ value.
299
+
300
+ If 'do_truncate' is True, we will
301
+ always receive the 'start' value. If
302
+ None, we will not make any conversion
303
+ and the value received could be useless
304
+ because it is in the middle of a range.
305
+ """
306
+ pts = (
307
+ self._t_handler.pts.truncated(pts)
308
+ if do_truncate is True else
309
+ self._t_handler.pts.rounded(pts)
310
+ if do_truncate is False else
311
+ pts # if None
312
+ )
313
+
314
+ return Fraction(pts * self._t_handler.time_base)
315
+
316
+ def to_pts(
317
+ self,
318
+ t: Union[int, float, Fraction],
319
+ do_truncate: Union[bool, None] = True
320
+ ) -> int:
321
+ """
322
+ Transform the given 't' to a 'pts' value
323
+ truncating, rounding or applying no
324
+ variation.
325
+ """
326
+ return self._t_handler.pts.from_t(t, do_truncate)
327
+
328
+ def truncated(
329
+ self,
330
+ t: Union[int, float, Fraction]
331
+ ):
332
+ """
333
+ Get the 't' value provided but truncated.
334
+
335
+ This means that if 't' is in a
336
+ [start, end) range, we will obtain the
337
+ 'start' value always.
338
+ """
339
+ return round_t(t, Fraction(1, self._t_handler.fps), do_truncate = True)
340
+
341
+ def rounded(
342
+ self,
343
+ t: Union[int, float, Fraction]
344
+ ):
345
+ """
346
+ Get the 't' value provided but rounded.
347
+
348
+ This means that if 't' is in a
349
+ [start, end) range, we will obtain
350
+ the 'start' or the 'end' value according
351
+ to which one is closer to the that 't'
352
+ value provided.
353
+ """
354
+ return round_t(t, Fraction(1, self._t_handler.fps), do_truncate = False)
355
+
356
+ def next(
357
+ self,
358
+ t: Union[int, float, Fraction],
359
+ n: int = 1,
360
+ do_truncate: bool = True
361
+ ) -> Fraction:
362
+ """
363
+ Get the value that is 'n' times ahead of
364
+ the 't' property of this instance
365
+ (truncated or rounded according to the
366
+ 'do_truncate' parameter provided).
367
+
368
+ Useful when you need the next value for a
369
+ range in an iteration or similar.
370
+ """
371
+ t = (
372
+ self.truncated(t)
373
+ if do_truncate else
374
+ self.rounded(t)
375
+ )
376
+
377
+ return t + n * self._t_handler.time_base
378
+
379
+ def previous(
380
+ self,
381
+ t: Union[int, float, Fraction],
382
+ n: int = 1,
383
+ do_truncate: bool = True
384
+ ) -> Fraction:
385
+ """
386
+ Get the value that is 'n' times before
387
+ the 't' property of this instance
388
+ (truncated or rounded according to the
389
+ 'do_truncate' parameter provided).
390
+
391
+ Useful when you need the previous value to
392
+ check if the current is the next one or
393
+ similar.
394
+
395
+ Be careful, if the 'truncated' value is 0
396
+ this will give you an unexpected negative
397
+ value.
398
+ """
399
+ t = (
400
+ self.truncated(t)
401
+ if do_truncate else
402
+ self.rounded(t)
403
+ )
404
+
405
+ return t - n * self._t_handler.time_base
406
+
407
+ class _Pts:
408
+ """
409
+ Internal class to be used by the THandler
410
+ as a shortcut to the functionality
411
+ related with 'pts' values.
412
+ """
413
+
414
+ def __init__(
415
+ self,
416
+ t_handler: 'THandler'
417
+ ):
418
+ self._t_handler: THandler = t_handler
419
+ """
420
+ Instance of the parent THandler to
421
+ access to its properties.
422
+ """
423
+
424
+ def from_t(
425
+ self,
426
+ t: Union[int, float, Fraction],
427
+ do_truncate: Union[bool, None] = True
428
+ ) -> int:
429
+ """
430
+ Get the pts (the amount of accumulated
431
+ ticks, also called presentation timestamp),
432
+ for the frame defined by the 't' time
433
+ moment provided.
434
+
435
+ If 't' is in a [start, end) range, we
436
+ will obtain the 'start' value if 't'
437
+ value is closer to it than to the 'end
438
+ value.
439
+
440
+ If 'do_truncate' is True, we will
441
+ always receive the 'start' value. If
442
+ None, we will not make any conversion
443
+ and the value received could be useless
444
+ because it is in the middle of a range.
445
+ """
446
+ t = (
447
+ self._t_handler.t.truncated(t)
448
+ if do_truncate is True else
449
+ self._t_handler.t.rounded(t)
450
+ if do_truncate is False else
451
+ t # if None
452
+ )
453
+
454
+ return int(t / self._t_handler.time_base)
455
+
456
+ def to_t(
457
+ self,
458
+ pts: int,
459
+ do_truncate: Union[bool, None] = True
460
+ ) -> Fraction:
461
+ """
462
+ Transform the given 'pts' to a 't' value
463
+ truncating, rounding or applying no
464
+ variation.
465
+ """
466
+ return self._t_handler.t.from_pts(pts, do_truncate)
467
+
468
+ def truncated(
469
+ self,
470
+ pts: int
471
+ ):
472
+ """
473
+ Get the 'pts' value provided but truncated.
474
+
475
+ This means that if 't' is in a
476
+ [start, end) range, we will obtain the
477
+ 'start' value always.
478
+ """
479
+ return round_pts(
480
+ pts = pts,
481
+ fps = self._t_handler.fps,
482
+ time_base = self._t_handler.time_base,
483
+ do_truncate = True
484
+ )
485
+
486
+ def rounded(
487
+ self,
488
+ pts: int
489
+ ) -> int:
490
+ """
491
+ Get the 'pts' value provided but rounded.
492
+
493
+ This means that if 't' is in a
494
+ [start, end) range, we will obtain
495
+ the 'start' or the 'end' value according
496
+ to which one is closer to the that 't'
497
+ value provided.
498
+ """
499
+ return round_pts(
500
+ pts = pts,
501
+ fps = self._t_handler.fps,
502
+ time_base = self._t_handler.time_base,
503
+ do_truncate = False
504
+ )
505
+
506
+ def next(
507
+ self,
508
+ pts: int,
509
+ n: int = 1,
510
+ do_truncate: bool = True
511
+ ) -> int:
512
+ """
513
+ Get the value that is 'n' times ahead of
514
+ the 'pts' value provided (truncated or
515
+ rounded according to the 'do_truncate'
516
+ parameter provided).
517
+
518
+ Useful when you need the next value for a
519
+ range in an iteration or similar.
520
+ """
521
+ pts = (
522
+ self.truncated(pts)
523
+ if do_truncate else
524
+ self.rounded(pts)
525
+ )
526
+
527
+ return pts + n * get_ticks_per_frame(self._t_handler.fps, self._t_handler.time_base)
528
+
529
+ def previous(
530
+ self,
531
+ pts: int,
532
+ n: int = 1,
533
+ do_truncate: bool = True
534
+ ) -> int:
535
+ """
536
+ Get the value that is 'n' times before
537
+ the 't' property of this instance
538
+ (truncated or rounded according to the
539
+ 'do_truncate' parameter provided).
540
+
541
+ Useful when you need the previous value to
542
+ check if the current is the next one or
543
+ similar.
544
+
545
+ Be careful, if the 'truncated' value is 0
546
+ this will give you an unexpected negative
547
+ value.
548
+ """
549
+ pts = (
550
+ self.truncated(pts)
551
+ if do_truncate else
552
+ self.rounded(pts)
553
+ )
554
+
555
+ return pts - n * get_ticks_per_frame(self._t_handler.fps, self._t_handler.time_base)
556
+
557
+ class THandler:
558
+ """
559
+ Class to simplify the way we work with
560
+ pyav frames time moments, indexes and
561
+ pts values.
562
+
563
+ This is an example of what a video has:
564
+ - `fps = 60`
565
+ - `time_base = 1 / 15360`
566
+ - `tick = fps * time_base = 256`
567
+
568
+ So, considering this above:
569
+ - Frame #1: `pts[0] = 256 * 0 = 0`
570
+ - Frame #2: `pts[1] = 256 * 1 = 256`
571
+ - Frame #16: `pts[15] = 256 * 15 = 3840`
572
+ """
573
+
574
+ def __init__(
575
+ self,
576
+ fps: Union[int, float, Fraction],
577
+ time_base: Union[Fraction, None] = None
578
+ ):
579
+ """
580
+ If the 'time_base' provided is None it will
581
+ be automatically `1/fps`.
582
+ """
583
+ ParameterValidator.validate_mandatory_positive_number('fps', fps, do_include_zero = False)
584
+ ParameterValidator.validate_instance_of('time_base', time_base, 'Fraction')
585
+
586
+ self.fps: Fraction = parse_fraction(fps)
587
+ """
588
+ The frames per second.
589
+ """
590
+ self.time_base: Fraction = (
591
+ time_base
592
+ if time_base is not None else
593
+ fps_to_time_base(self.fps)
594
+ )
595
+ """
596
+ The time base.
597
+ """
598
+ self.t: _T = _T(self)
599
+ """
600
+ Shortcut to the instance that handles
601
+ the 't' related functionality.
602
+ """
603
+ self.pts: _Pts = _Pts(self)
604
+ """
605
+ Shortcut to the instance that handles
606
+ the 'pts' related functionality.
607
+ """
608
+
609
+ # TODO: I think I should create a THandler
610
+ # that receives 'fps' and 'time_base' and
611
+ # then, by passing a 't' value, we can
612
+ # calculate everything we need, so we
613
+ # simplify all these processes
614
+ def frame_t_to_index(
615
+ t: Union[float, int, Fraction],
616
+ fps: Union[float, int, Fraction]
617
+ ) -> int:
618
+ """
619
+ Get the index of the frame with the
620
+ given 't' time moment, based on the
621
+ also provided 'fps'.
622
+
623
+ The formula:
624
+ - `int(t * fps)`
625
+ """
626
+ return int(parse_fraction(t) * fps)
627
+
628
+ def frame_index_to_t(
629
+ index: int,
630
+ fps: Union[float, int, Fraction]
631
+ ):
632
+ """
633
+ Get the 't' time moment for the frame
634
+ with the given 'index', based on the
635
+ also provided 'fps'.
636
+
637
+ The formula:
638
+ - `frame_index * (1 / fps)`
639
+ """
640
+ return index * parse_fraction(1, parse_fraction(fps))
641
+
642
+ def frame_t_to_pts(
643
+ t: Union[float, int, Fraction],
644
+ fps: Union[float, int, Fraction],
645
+ time_base: Fraction
646
+ ):
647
+ """
648
+ Get the pts (the amount of accumulated
649
+ ticks, also called presentation timestamp),
650
+ for the frame defined by the 't' time
651
+ moment provided, based on the also provided
652
+ 'fps' and 'time_base'.
653
+
654
+ The formula:
655
+ - `frame_index * ticks_per_frame`
656
+ """
657
+ return frame_t_to_index(t, fps) * get_ticks_per_frame(fps, time_base)
658
+
659
+ def frame_pts_to_t(
660
+ pts: int,
661
+ time_base: Fraction
662
+ ) -> Fraction:
663
+ """
664
+ Get the 't' time moment of the frame with
665
+ the given 'pts' (the amount of accumulated
666
+ ticks, also called presentation timestamp),
667
+ based on the also provided 'time_base'.
668
+
669
+ The formula:
670
+ - `pts * time_base`
671
+ """
672
+ return parse_fraction(pts * time_base)
673
+
674
+ def get_ticks_per_frame(
675
+ fps: Union[float, int, Fraction],
676
+ time_base: Fraction
677
+ ) -> int:
678
+ """
679
+ Get the amount of ticks per frame. A
680
+ tick is the minimum amount of time we
681
+ spend from one frame to the next.
682
+
683
+ The formula:
684
+ - `1 / (fps * time_base)`
685
+ """
686
+ return int(Fraction(1, 1) / (fps * time_base))
687
+
688
+ def fps_to_frame_duration(
689
+ fps: Union[float, int, Fraction]
690
+ ) -> Fraction:
691
+ """
692
+ Get the frame duration based on the 'fps'
693
+ provided.
694
+
695
+ The formula:
696
+ - `1 / fps`
697
+ """
698
+ return Fraction(1, parse_fraction(fps))
220
699
 
221
700
  def fps_to_time_base(
222
- fps: Union[int, float, Fraction]
701
+ fps: Union[float, int, Fraction]
702
+ ) -> Fraction:
703
+ """
704
+ Get the time base based on the given 'fps',
705
+ that will be basically `1/fps`. This is a
706
+ bit useless, just when we don't want to
707
+ think too much to use a time base and we
708
+ want to use the fps.
709
+
710
+ The formula:
711
+ - `1 / fps`
712
+ """
713
+ return Fraction(1, parse_fraction(fps))
714
+
715
+ def parse_fraction(
716
+ value: Union[float, int, Fraction]
223
717
  ) -> Fraction:
224
718
  """
225
- Get the pyav time base from the given
226
- 'fps'.
719
+ Parse the provided 'value' as a Fraction
720
+ and limits its denominator.
227
721
  """
228
- return (
229
- Fraction(1, fps)
230
- if NumberValidator.is_int(fps) else
231
- Fraction(1, 1) / fps
232
- if PythonValidator.is_instance_of(fps, 'Fraction') else
233
- Fraction(1, 1) / Fraction.from_float(fps).limit_denominator(1000000) # if float
234
- )
722
+ fraction = Fraction(value)#.limit_denominator(100_000)
723
+
724
+ return fraction
725
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: yta-video-frame-time
3
- Version: 0.0.5
3
+ Version: 0.0.6
4
4
  Summary: Youtube Autonomous Video Frame Time Module
5
5
  Author: danialcala94
6
6
  Author-email: danielalcalavalera@gmail.com
@@ -0,0 +1,6 @@
1
+ yta_video_frame_time/__init__.py,sha256=-YOa7lOKdiA3FwDEHHU1tHobnmhjFpTaVLfJQLZqoMI,22252
2
+ yta_video_frame_time/t_fraction.py,sha256=c0sz-ncVV_Qt--rM2k1xKyjZpPF_pH5bFKPFx6WmxQc,20027
3
+ yta_video_frame_time-0.0.6.dist-info/LICENSE,sha256=6kbiFSfobTZ7beWiKnHpN902HgBx-Jzgcme0SvKqhKY,1091
4
+ yta_video_frame_time-0.0.6.dist-info/METADATA,sha256=is6UfhRMg48ToFwXBgwHOuPT2K6aqGTSt05KedCnAiw,515
5
+ yta_video_frame_time-0.0.6.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
6
+ yta_video_frame_time-0.0.6.dist-info/RECORD,,
@@ -1,6 +0,0 @@
1
- yta_video_frame_time/__init__.py,sha256=-YOa7lOKdiA3FwDEHHU1tHobnmhjFpTaVLfJQLZqoMI,22252
2
- yta_video_frame_time/t_fraction.py,sha256=JR2GNDjk06I2YFKTVJpNQ2hxlEwUF3QG02Ba2sEDrj0,6639
3
- yta_video_frame_time-0.0.5.dist-info/LICENSE,sha256=6kbiFSfobTZ7beWiKnHpN902HgBx-Jzgcme0SvKqhKY,1091
4
- yta_video_frame_time-0.0.5.dist-info/METADATA,sha256=Lh-jnjYVJh5mmLYq0ngkgMP1u9L_ta23nMQrfgNkZKQ,515
5
- yta_video_frame_time-0.0.5.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
6
- yta_video_frame_time-0.0.5.dist-info/RECORD,,