yta-video-opengl 0.0.12__py3-none-any.whl → 0.0.14__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.
- yta_video_opengl/complete/timeline.py +41 -44
- yta_video_opengl/complete/track.py +40 -32
- yta_video_opengl/complete/video_on_track.py +27 -16
- yta_video_opengl/reader/__init__.py +27 -82
- yta_video_opengl/reader/cache.py +250 -245
- yta_video_opengl/t.py +233 -0
- yta_video_opengl/tests.py +4 -2
- yta_video_opengl/utils.py +108 -86
- yta_video_opengl/video.py +90 -12
- yta_video_opengl/writer.py +13 -14
- {yta_video_opengl-0.0.12.dist-info → yta_video_opengl-0.0.14.dist-info}/METADATA +2 -1
- yta_video_opengl-0.0.14.dist-info/RECORD +21 -0
- yta_video_opengl-0.0.12.dist-info/RECORD +0 -20
- {yta_video_opengl-0.0.12.dist-info → yta_video_opengl-0.0.14.dist-info}/LICENSE +0 -0
- {yta_video_opengl-0.0.12.dist-info → yta_video_opengl-0.0.14.dist-info}/WHEEL +0 -0
@@ -4,6 +4,7 @@ that, using ffmpeg, detects the video.
|
|
4
4
|
"""
|
5
5
|
from yta_video_opengl.reader.cache import VideoFrameCache
|
6
6
|
from yta_video_opengl.utils import iterate_stream_frames_demuxing
|
7
|
+
from yta_video_opengl.t import T
|
7
8
|
from yta_validation import PythonValidator
|
8
9
|
from av.video.frame import VideoFrame
|
9
10
|
from av.audio.frame import AudioFrame
|
@@ -11,7 +12,7 @@ from av.packet import Packet
|
|
11
12
|
from av.video.stream import VideoStream
|
12
13
|
from av.audio.stream import AudioStream
|
13
14
|
from av.container.input import InputContainer
|
14
|
-
from
|
15
|
+
from quicktions import Fraction
|
15
16
|
from av import open as av_open
|
16
17
|
from typing import Union
|
17
18
|
from dataclasses import dataclass
|
@@ -58,7 +59,7 @@ class VideoReaderFrame:
|
|
58
59
|
self,
|
59
60
|
# TODO: Add the type, please
|
60
61
|
frame: any,
|
61
|
-
t: float = None,
|
62
|
+
t: Union[int, float, Fraction] = None,
|
62
63
|
pixel_format: str = 'rgb24'
|
63
64
|
):
|
64
65
|
self.value: Union[AudioFrame, VideoFrame] = frame
|
@@ -66,7 +67,7 @@ class VideoReaderFrame:
|
|
66
67
|
The frame content, that can be audio or video
|
67
68
|
frame.
|
68
69
|
"""
|
69
|
-
self.t:
|
70
|
+
self.t: Fraction = Fraction(t)
|
70
71
|
"""
|
71
72
|
The 't' time moment of the frame.
|
72
73
|
"""
|
@@ -139,6 +140,8 @@ class VideoReader:
|
|
139
140
|
"""
|
140
141
|
return self.container.decode(self.video_stream)
|
141
142
|
|
143
|
+
# TODO: Remove this when possible, we are not
|
144
|
+
# using 'next' properties
|
142
145
|
@property
|
143
146
|
def next_frame(
|
144
147
|
self
|
@@ -159,16 +162,6 @@ class VideoReader:
|
|
159
162
|
"""
|
160
163
|
return self.container.decode(self.audio_stream)
|
161
164
|
|
162
|
-
@property
|
163
|
-
def next_audio_frame(
|
164
|
-
self
|
165
|
-
) -> Union[AudioFrame, None]:
|
166
|
-
"""
|
167
|
-
Get the next audio frame (decoded) from the
|
168
|
-
iterator.
|
169
|
-
"""
|
170
|
-
return next(self.audio_frame_iterator)
|
171
|
-
|
172
165
|
@property
|
173
166
|
def packet_iterator(
|
174
167
|
self
|
@@ -179,16 +172,6 @@ class VideoReader:
|
|
179
172
|
"""
|
180
173
|
return self.container.demux(self.video_stream)
|
181
174
|
|
182
|
-
@property
|
183
|
-
def next_packet(
|
184
|
-
self
|
185
|
-
) -> Union[Packet, None]:
|
186
|
-
"""
|
187
|
-
Get the next video packet (not decoded) from
|
188
|
-
the iterator.
|
189
|
-
"""
|
190
|
-
return next(self.packet_iterator)
|
191
|
-
|
192
175
|
@property
|
193
176
|
def audio_packet_iterator(
|
194
177
|
self
|
@@ -199,16 +182,6 @@ class VideoReader:
|
|
199
182
|
"""
|
200
183
|
return self.container.demux(self.audio_stream)
|
201
184
|
|
202
|
-
@property
|
203
|
-
def next_audio_packet(
|
204
|
-
self
|
205
|
-
) -> Union[Packet, None]:
|
206
|
-
"""
|
207
|
-
Get the next audio packet (not decoded) from
|
208
|
-
the iterator.
|
209
|
-
"""
|
210
|
-
return next(self.packet_iterator)
|
211
|
-
|
212
185
|
@property
|
213
186
|
def packet_with_audio_iterator(
|
214
187
|
self
|
@@ -220,18 +193,6 @@ class VideoReader:
|
|
220
193
|
"""
|
221
194
|
return self.container.demux((self.video_stream, self.audio_stream))
|
222
195
|
|
223
|
-
@property
|
224
|
-
def next_packet_with_audio(
|
225
|
-
self
|
226
|
-
) -> Union[Packet, None]:
|
227
|
-
"""
|
228
|
-
Get the next video frames packet (or audio
|
229
|
-
frames packet) from the iterator. Depending
|
230
|
-
on the position, the packet can be video or
|
231
|
-
audio.
|
232
|
-
"""
|
233
|
-
return next(self.packet_with_audio_iterator)
|
234
|
-
|
235
196
|
@property
|
236
197
|
def has_video(
|
237
198
|
self
|
@@ -312,8 +273,6 @@ class VideoReader:
|
|
312
273
|
The fps of the video.
|
313
274
|
"""
|
314
275
|
return (
|
315
|
-
# They return it as a Fraction but we usually
|
316
|
-
# use it as float or even int
|
317
276
|
self.video_stream.average_rate
|
318
277
|
if self.has_video else
|
319
278
|
None
|
@@ -515,6 +474,7 @@ class VideoReader:
|
|
515
474
|
)
|
516
475
|
# TODO: Should this be 'AUTO' (?)
|
517
476
|
self.video_stream.thread_type = 'AUTO'
|
477
|
+
|
518
478
|
self.audio_stream = (
|
519
479
|
self.container.streams.audio[0]
|
520
480
|
if self.container.streams.audio else
|
@@ -534,7 +494,7 @@ class VideoReader:
|
|
534
494
|
|
535
495
|
def seek(
|
536
496
|
self,
|
537
|
-
pts,
|
497
|
+
pts: int,
|
538
498
|
stream = None
|
539
499
|
) -> 'VideoReader':
|
540
500
|
"""
|
@@ -567,7 +527,8 @@ class VideoReader:
|
|
567
527
|
for frame in self.frame_iterator:
|
568
528
|
yield VideoReaderFrame(
|
569
529
|
frame = frame,
|
570
|
-
|
530
|
+
# TODO: Maybe use util to transform it (?)
|
531
|
+
t = frame.pts * self.time_base,
|
571
532
|
pixel_format = self.pixel_format
|
572
533
|
)
|
573
534
|
|
@@ -659,50 +620,29 @@ class VideoReader:
|
|
659
620
|
):
|
660
621
|
yield frame
|
661
622
|
|
662
|
-
# TODO: Will we use this (?)
|
663
|
-
def get_frame(
|
664
|
-
self,
|
665
|
-
index: int
|
666
|
-
) -> 'VideoFrame':
|
667
|
-
"""
|
668
|
-
Get the video frame with the given 'index',
|
669
|
-
using the video cache system.
|
670
|
-
"""
|
671
|
-
return self.video_cache.get_frame(index)
|
672
|
-
|
673
623
|
def get_frame_from_t(
|
674
624
|
self,
|
675
|
-
t: float
|
625
|
+
t: Union[int, float, Fraction]
|
676
626
|
) -> 'VideoFrame':
|
677
627
|
"""
|
678
628
|
Get the video frame with the given 't' time
|
679
629
|
moment, using the video cache system.
|
680
630
|
"""
|
681
|
-
return self.video_cache.
|
631
|
+
return self.video_cache.get_video_frame(t)
|
682
632
|
|
683
|
-
def get_audio_frame(
|
684
|
-
self,
|
685
|
-
index: int
|
686
|
-
) -> 'AudioFrame':
|
687
|
-
"""
|
688
|
-
Get the audio frame with the given 'index',
|
689
|
-
using the audio cache system.
|
690
|
-
"""
|
691
|
-
return self.audio_cache.get_frame(index)
|
692
|
-
|
693
633
|
def get_audio_frame_from_t(
|
694
634
|
self,
|
695
|
-
t: float
|
635
|
+
t: Union[int, float, Fraction]
|
696
636
|
) -> 'AudioFrame':
|
697
637
|
"""
|
698
638
|
Get the audio frame with the given 't' time
|
699
639
|
moment, using the audio cache system.
|
700
640
|
"""
|
701
|
-
return self.audio_cache.
|
641
|
+
return self.audio_cache.get_audio_frame_from_t(t)
|
702
642
|
|
703
643
|
def get_audio_frames_from_t(
|
704
644
|
self,
|
705
|
-
t: float
|
645
|
+
t: Union[int, float, Fraction]
|
706
646
|
):
|
707
647
|
"""
|
708
648
|
Get the sequence of audio frames for the
|
@@ -715,14 +655,17 @@ class VideoReader:
|
|
715
655
|
(remember that a video frame is associated
|
716
656
|
with more than 1 audio frame).
|
717
657
|
"""
|
718
|
-
|
719
|
-
|
658
|
+
t: T = T.from_fps(t, self.fps)
|
659
|
+
# We want all the audios that must be played
|
660
|
+
# during the video frame that starts in the
|
661
|
+
# 't' time moment
|
662
|
+
for frame in self.audio_cache.get_audio_frames(t.truncated, t.next(1).truncated):
|
720
663
|
yield frame
|
721
664
|
|
722
665
|
def get_frames(
|
723
666
|
self,
|
724
|
-
start: float = 0.0,
|
725
|
-
end: Union[float, None] = None
|
667
|
+
start: Union[int, float, Fraction] = 0.0,
|
668
|
+
end: Union[int, float, Fraction, None] = None
|
726
669
|
):
|
727
670
|
"""
|
728
671
|
Iterator to get the video frames in between
|
@@ -733,14 +676,14 @@ class VideoReader:
|
|
733
676
|
|
734
677
|
def get_audio_frames(
|
735
678
|
self,
|
736
|
-
start: float = 0.0,
|
737
|
-
end: Union[float, None] = None
|
679
|
+
start: Union[int, float, Fraction] = 0.0,
|
680
|
+
end: Union[int, float, Fraction, None] = None
|
738
681
|
):
|
739
682
|
"""
|
740
683
|
Iterator to get the audio frames in between
|
741
684
|
the provided 'start' and 'end' time moments.
|
742
685
|
"""
|
743
|
-
for frame in self.audio_cache.
|
686
|
+
for frame in self.audio_cache.get_audio_frames(start, end):
|
744
687
|
yield frame
|
745
688
|
|
746
689
|
def close(
|
@@ -752,6 +695,8 @@ class VideoReader:
|
|
752
695
|
self.container.close()
|
753
696
|
|
754
697
|
|
698
|
+
# TODO: I think I'm not using this...
|
699
|
+
# Remove it please
|
755
700
|
def audio_ts_for_video_t(
|
756
701
|
t: float,
|
757
702
|
video_fps: float,
|