yta-video-opengl 0.0.24__py3-none-any.whl → 0.0.26__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.
@@ -1,6 +1,6 @@
1
1
  from yta_video_opengl.nodes.video.opengl import WavingNode
2
2
  from yta_video_opengl.nodes.audio import ChorusNode
3
- from yta_video_opengl.nodes import Node, TimedNode
3
+ from yta_video_opengl.nodes import TimedNode
4
4
  from yta_validation.parameter import ParameterValidator
5
5
  from yta_programming.decorators import singleton_old
6
6
  from typing import Union
@@ -20,9 +20,9 @@ class _AudioEffects:
20
20
 
21
21
  def __init__(
22
22
  self,
23
- effects: '_Effects'
23
+ effects: 'Effects'
24
24
  ):
25
- self._effects: _Effects = effects
25
+ self._effects: Effects = effects
26
26
  """
27
27
  The parent instance that includes this
28
28
  class instance as a property.
@@ -66,9 +66,9 @@ class _VideoEffects:
66
66
 
67
67
  def __init__(
68
68
  self,
69
- effects: '_Effects'
69
+ effects: 'Effects'
70
70
  ):
71
- self._effects: _Effects = effects
71
+ self._effects: Effects = effects
72
72
  """
73
73
  The parent instance that includes this
74
74
  class instance as a property.
@@ -101,7 +101,7 @@ class _VideoEffects:
101
101
  """
102
102
  return _create_node(
103
103
  WavingNode(
104
- context = self._effects._opengl_editor.context,
104
+ context = self._effects.opengl_context,
105
105
  size = size,
106
106
  amplitude = amplitude,
107
107
  frequency = frequency,
@@ -114,45 +114,8 @@ class _VideoEffects:
114
114
  # TODO: Include definitive and tested video
115
115
  # effects here below
116
116
 
117
- class _Effects:
118
- """
119
- *For internal use only*
120
-
121
- Class to be used within the OpenglEditor
122
- as a property to simplify the access to
123
- the effect nodes and also to have the
124
- single context always available through
125
- the OpenglEditor instance that is a
126
- singleton one.
127
-
128
- Even though we can have more effects,
129
- this class is also the way we expose only
130
- the ones we actually want to expose to
131
- the user.
132
- """
133
-
134
- def __init__(
135
- self,
136
- opengl_editor: 'OpenglEditor'
137
- ):
138
- self._opengl_editor: OpenglEditor = opengl_editor
139
- """
140
- The parent instance that includes this
141
- class instance as a property.
142
- """
143
- self.audio: _AudioEffects = _AudioEffects(self)
144
- """
145
- Shortcut to the audio effects that are
146
- available.
147
- """
148
- self.video: _VideoEffects = _VideoEffects(self)
149
- """
150
- Shortcut to the video effects that are
151
- available.
152
- """
153
-
154
117
  @singleton_old
155
- class OpenglEditor:
118
+ class Effects:
156
119
  """
157
120
  Singleton instance.
158
121
 
@@ -163,6 +126,15 @@ class OpenglEditor:
163
126
  the nodes we have available for the
164
127
  user.
165
128
 
129
+ This class is to simplify the access to
130
+ the effect nodes and also to have the
131
+ single context always available.
132
+
133
+ Even though we can have more effects,
134
+ this class is also the way we expose only
135
+ the ones we actually want to expose to
136
+ the user.
137
+
166
138
  The GPU will make the calculations in
167
139
  parallel by itself, so we can handle a
168
140
  single context to make the nodes share
@@ -172,32 +144,33 @@ class OpenglEditor:
172
144
  def __init__(
173
145
  self
174
146
  ):
175
- self.context = moderngl.create_context(standalone = True)
147
+ self.opengl_context = moderngl.create_context(standalone = True)
176
148
  """
177
- The context that will be shared by all
178
- the nodes.
149
+ The opengl context that will be shared
150
+ by all the opengl nodes.
179
151
  """
180
- self.effects: _Effects = _Effects(self)
152
+ self.audio: _AudioEffects = _AudioEffects(self)
181
153
  """
182
- Shortcut to the effects.
154
+ Shortcut to the audio effects that are
155
+ available.
156
+ """
157
+ self.video: _VideoEffects = _VideoEffects(self)
158
+ """
159
+ Shortcut to the video effects that are
160
+ available.
183
161
  """
184
- # TODO: I should do something like
185
- # editor.effects.waving_node() to create
186
- # an instance of that effect node
187
-
188
162
 
189
163
  def _create_node(
190
164
  node: Union['_AudioNode', '_VideoNode'],
191
165
  start: Union[int, float, 'Fraction'],
192
166
  end: Union[int, float, 'Fraction', None]
193
167
  ):
194
- # The class we pass has to inherit from this
195
- # 'Node' class, but could be other classes
196
- # in the middle, because an OpenglNode
197
- # inherits from other class
198
- ParameterValidator.validate_mandatory_subclass_of('node', node, ['_AudioNode', '_VideoNode'])
168
+ # We could be other classes in the middle,
169
+ # because an OpenglNode inherits from
170
+ # other class
171
+ ParameterValidator.validate_mandatory_subclass_of('node', node, ['_AudioNode', '_VideoNode', 'OpenglNodeBase'])
199
172
 
200
- # We have to create a Node wrapper with the
173
+ # We have to create a node wrapper with the
201
174
  # time range in which it has to be applied
202
175
  # to all the frames.
203
176
  return TimedNode(
@@ -215,6 +188,26 @@ class _EffectStacked:
215
188
  and lower when higher value.
216
189
  """
217
190
 
191
+ @property
192
+ def is_audio_effect(
193
+ self
194
+ ) -> bool:
195
+ """
196
+ Flag to indicate if it is an audio effect
197
+ or not.
198
+ """
199
+ return self.effect.is_audio_node
200
+
201
+ @property
202
+ def is_video_effect(
203
+ self
204
+ ) -> bool:
205
+ """
206
+ Flag to indicate if it is a video effect
207
+ or not.
208
+ """
209
+ return self.effect.is_video_node
210
+
218
211
  def __init__(
219
212
  self,
220
213
  effect: TimedNode,
@@ -243,34 +236,66 @@ class EffectsStack:
243
236
  """
244
237
 
245
238
  @property
246
- def effects(
239
+ def video_effects(
247
240
  self
248
241
  ) -> list[_EffectStacked]:
249
242
  """
250
- The effects but ordered from their 'start'
251
- time moment.
243
+ The video effects but ordered by 'priority'
244
+ and 'start' time moment.
252
245
  """
253
- return sorted(self._effects, key = lambda effect: (effect.priority, effect.effect.start))
246
+ return sorted(
247
+ [
248
+ effect
249
+ for effect in self._effects
250
+ if effect.is_video_effect
251
+ ],
252
+ key = lambda effect: (effect.priority, effect.effect.start)
253
+ )
254
254
 
255
255
  @property
256
- def most_priority_effect(
256
+ def audio_effects(
257
257
  self
258
- ) -> _EffectStacked:
258
+ ) -> list[_EffectStacked]:
259
259
  """
260
- The effect with the highest priority,
261
- that is the lower priority value.
260
+ The audio effects but ordered by 'priority'
261
+ and 'start' time moment.
262
262
  """
263
- return min(self._effects, key = lambda effect: effect.priority)
263
+ return sorted(
264
+ [
265
+ effect
266
+ for effect in self._effects
267
+ if effect.is_audio_effect
268
+ ],
269
+ key = lambda effect: (effect.priority, effect.effect.start)
270
+ )
271
+
272
+ @property
273
+ def lowest_audio_priority(
274
+ self
275
+ ) -> int:
276
+ """
277
+ The priority of the audio effect with the
278
+ lowest one, or 0 if no audio effects.
279
+ """
280
+ return min(
281
+ self.audio_effects,
282
+ key = lambda effect: effect.priority,
283
+ default = 0
284
+ )
264
285
 
265
286
  @property
266
- def less_priority_effect(
287
+ def lowest_video_priority(
267
288
  self
268
- ) -> _EffectStacked:
289
+ ) -> int:
269
290
  """
270
- The effect with the lowest priority,
271
- that is the biggest priority value.
291
+ The priority of the video effect with the
292
+ lowest one, or 0 if no video effects.
272
293
  """
273
- return max(self._effects, key = lambda effect: effect.priority)
294
+ return min(
295
+ self.video_effects,
296
+ key = lambda effect: effect.priority,
297
+ default = 0
298
+ )
274
299
 
275
300
  def __init__(
276
301
  self
@@ -281,20 +306,35 @@ class EffectsStack:
281
306
  have been added to this stack, unordered.
282
307
  """
283
308
 
284
- def get_effects_for_t(
309
+ def get_audio_effects_for_t(
310
+ self,
311
+ t: Union[int, float, 'Fraction']
312
+ ) -> list[TimedNode]:
313
+ """
314
+ Get the audio effects, ordered by priority
315
+ and the 'start' field, that must be applied
316
+ within the 't' time moment provided because
317
+ it is within the [start, end) time range.
318
+ """
319
+ return [
320
+ effect.effect
321
+ for effect in self.audio_effects
322
+ if effect.effect.is_within_time(t)
323
+ ]
324
+
325
+ def get_video_effects_for_t(
285
326
  self,
286
327
  t: Union[int, float, 'Fraction']
287
328
  ) -> list[TimedNode]:
288
329
  """
289
- Get the effects, ordered by priority
290
- and the 'start' field, that must be
291
- applied within the 't' time moment
292
- provided because it is within the
293
- [start, end) time range.
330
+ Get the video effects, ordered by priority
331
+ and the 'start' field, that must be applied
332
+ within the 't' time moment provided because
333
+ it is within the [start, end) time range.
294
334
  """
295
335
  return [
296
336
  effect.effect
297
- for effect in self.effects
337
+ for effect in self.video_effects
298
338
  if effect.effect.is_within_time(t)
299
339
  ]
300
340
 
@@ -307,6 +347,7 @@ class EffectsStack:
307
347
  Add the provided 'effect' to the stack.
308
348
  """
309
349
  ParameterValidator.validate_mandatory_instance_of('effect', effect, TimedNode)
350
+ ParameterValidator.validate_positive_int('priority', priority, do_include_zero = True)
310
351
 
311
352
  # TODO: What about the same effect added
312
353
  # twice during the same time range? Can we
@@ -318,8 +359,16 @@ class EffectsStack:
318
359
  # Should we let some effects have the same
319
360
  # priority (?)
320
361
  priority = (
321
- self.less_priority_effect.priority + 1
322
- if priority is None else
362
+ self.lowest_audio_priority + 1
363
+ if (
364
+ priority is None and
365
+ effect.is_audio_node
366
+ ) else
367
+ self.lowest_video_priority + 1
368
+ if (
369
+ priority is None and
370
+ effect.is_video_node
371
+ ) else
323
372
  priority
324
373
  )
325
374
 
@@ -330,4 +379,6 @@ class EffectsStack:
330
379
 
331
380
  return self
332
381
 
382
+ # TODO: Maybe create an 'apply_video_effects' (?)
383
+ # TODO: Maybe create an 'apply_audio_effects' (?)
333
384
  # TODO: Create 'remove_effect'
@@ -1,6 +1,7 @@
1
1
  from yta_video_opengl.nodes.video import _VideoNode
2
2
  from yta_video_opengl.nodes.audio import _AudioNode
3
3
  from yta_validation.parameter import ParameterValidator
4
+ from yta_validation import PythonValidator
4
5
  from typing import Union
5
6
 
6
7
  import moderngl
@@ -32,6 +33,30 @@ class TimedNode:
32
33
  The 'start' and 'end' values by default
33
34
  """
34
35
 
36
+ @property
37
+ def is_audio_node(
38
+ self
39
+ ) -> bool:
40
+ """
41
+ Flag to indicate if the node (or effect)
42
+ is an audio effect or not.
43
+ """
44
+ # TODO: Is this checking not only the
45
+ # first level (?)
46
+ return PythonValidator.is_subclass_of(self.node, _AudioNode)
47
+
48
+ @property
49
+ def is_video_node(
50
+ self
51
+ ) -> bool:
52
+ """
53
+ Flag to indicate if the node (or effect)
54
+ is a video effect or not.
55
+ """
56
+ # TODO: Is this checking not only the
57
+ # first level (?)
58
+ return PythonValidator.is_subclass_of(self.node, _VideoNode)
59
+
35
60
  def __init__(
36
61
  self,
37
62
  node: Union[_VideoNode, _AudioNode],
@@ -47,7 +72,7 @@ class TimedNode:
47
72
  ):
48
73
  raise Exception('The "end" parameter provided must be greater or equal to the "start" parameter.')
49
74
 
50
- self.node: Node = node
75
+ self.node: Union[_VideoNode, _AudioNode] = node
51
76
  """
52
77
  The node we are wrapping and we want to
53
78
  apply as a modification of the frame in
@@ -16,7 +16,6 @@ working in GPU. Doing this below most of the
16
16
  changes would work:
17
17
  - `import numpy as np` → `import cupy as np`
18
18
  """
19
- from yta_video_opengl.nodes import TimedNode
20
19
  from abc import abstractmethod
21
20
  from typing import Union
22
21
 
@@ -33,9 +32,9 @@ class _AudioNode:
33
32
  @abstractmethod
34
33
  def process(
35
34
  self,
36
- input: Union['AudioFrame', 'np.ndarray'],
35
+ input: np.ndarray,
37
36
  t: float
38
- ) -> Union['AudioFrame', 'np.ndarray']:
37
+ ) -> np.ndarray:
39
38
  """
40
39
  Process the provided audio 'input' that
41
40
  is played on the given 't' time moment.
@@ -60,20 +59,13 @@ class VolumeNode(_AudioNode):
60
59
 
61
60
  def process(
62
61
  self,
63
- input: Union['AudioFrame', 'np.ndarray'],
62
+ input: np.ndarray,
64
63
  t: float
65
- ) -> Union['AudioFrame', 'np.ndarray']:
64
+ ) -> np.ndarray:
66
65
  """
67
66
  Process the provided audio 'input' that
68
67
  is played on the given 't' time moment.
69
68
  """
70
- # if PythonValidator.is_instance_of(input, 'AudioFrame'):
71
- # input = input.to_ndarray().astype(np.float32)
72
-
73
- # TODO: I think we should receive only
74
- # numpy arrays and the AudioFrame should
75
- # be handled outside, but I'm not sure
76
-
77
69
  factor = self.factor_fn(t, 0)
78
70
 
79
71
  samples = input
@@ -87,15 +79,6 @@ class VolumeNode(_AudioNode):
87
79
  # samples.astype(np.float32)
88
80
  # )
89
81
 
90
- # new_frame = AudioFrame.from_ndarray(
91
- # samples,
92
- # format = input.format.name,
93
- # layout = input.layout.name
94
- # )
95
- # new_frame.sample_rate = input.sample_rate
96
- # new_frame.pts = input.pts
97
- # new_frame.time_base = input.time_base
98
-
99
82
  return samples
100
83
 
101
84
  class ChorusNode(_AudioNode):
@@ -122,17 +105,13 @@ class ChorusNode(_AudioNode):
122
105
 
123
106
  def process(
124
107
  self,
125
- input: Union['AudioFrame', 'np.ndarray'],
108
+ input: Union[np.ndarray],
126
109
  t: float
127
- ) -> Union['AudioFrame', 'np.ndarray']:
110
+ ) -> np.ndarray:
128
111
  """
129
112
  Process the provided audio 'input' that
130
113
  is played on the given 't' time moment.
131
114
  """
132
- # TODO: I think we should receive only
133
- # numpy arrays and the AudioFrame should
134
- # be handled outside, but I'm not sure
135
-
136
115
  n_samples = input.shape[0]
137
116
  t = np.arange(n_samples) / self.rate
138
117
 
@@ -144,81 +123,11 @@ class ChorusNode(_AudioNode):
144
123
 
145
124
  for i in range(n_samples):
146
125
  d = delay[i]
147
- if i - d >= 0:
148
- output[i] = 0.7 * input[i] + 0.7 * input[i - d]
149
- else:
150
- output[i] = input[i]
151
126
 
152
- return output
127
+ output[i]= (
128
+ 0.7 * input[i] + 0.7 * input[i - d]
129
+ if (i - d) >= 0 else
130
+ input[i]
131
+ )
153
132
 
154
- # TODO: Remove this below
155
- """
156
- Here you have an example. The 'private'
157
- node class is the modifier, that we don't
158
- want to expose, and the 'public' class is
159
- the one that inherits from TimedNode and
160
- wraps the 'private' class to build the
161
- functionality.
162
- """
163
- # class VolumeAudioNode(TimedNode):
164
- # """
165
- # TimedNode to set the audio volume of a video
166
- # in a specific frame.
167
- # """
168
-
169
- # def __init__(
170
- # self,
171
- # factor_fn,
172
- # start: float = 0.0,
173
- # end: Union[float, None] = None
174
- # ):
175
- # super().__init__(
176
- # node = _SetVolumeAudioNode(factor_fn),
177
- # start = start,
178
- # end = end
179
- # )
180
-
181
- # class _SetVolumeAudioNode(AudioNode):
182
- # """
183
- # Audio node to change the volume of an
184
- # audio frame.
185
- # """
186
-
187
- # def __init__(
188
- # self,
189
- # factor_fn
190
- # ):
191
- # """
192
- # factor_fn: function (t, index) -> factor volumen
193
- # """
194
- # self.factor_fn = factor_fn
195
-
196
- # def process(
197
- # self,
198
- # frame: av.AudioFrame,
199
- # t: float,
200
- # ) -> av.AudioFrame:
201
- # # TODO: Why index (?) Maybe 'total_frames'
202
- # factor = self.factor_fn(t, 0)
203
-
204
- # samples = frame.to_ndarray().astype(np.float32)
205
- # samples *= factor
206
-
207
- # # Determine dtype according to format
208
- # samples = (
209
- # samples.astype(np.int16)
210
- # # 'fltp', 's16', 's16p'
211
- # if 's16' in frame.format.name else
212
- # samples.astype(np.float32)
213
- # )
214
-
215
- # new_frame = av.AudioFrame.from_ndarray(
216
- # samples,
217
- # format = frame.format.name,
218
- # layout = frame.layout.name
219
- # )
220
- # new_frame.sample_rate = frame.sample_rate
221
- # new_frame.pts = frame.pts
222
- # new_frame.time_base = frame.time_base
223
-
224
- # return new_frame
133
+ return output
@@ -8,6 +8,10 @@ from abc import ABC, abstractmethod
8
8
 
9
9
  import moderngl
10
10
 
11
+
12
+ # TODO: Expose all the nodes here and move
13
+ # this abstract to an abstract file (?)
14
+
11
15
  class _VideoNode(ABC):
12
16
  """
13
17
  Base abstract class to represent a video
@@ -199,7 +199,7 @@ class OpenglNodeBase(_VideoNode):
199
199
 
200
200
  def process(
201
201
  self,
202
- input: Union[moderngl.Texture, 'VideoFrame', 'np.ndarray']
202
+ input: Union[moderngl.Texture, np.ndarray]
203
203
  ) -> moderngl.Texture:
204
204
  """
205
205
  Apply the shader to the 'input', that
@@ -209,7 +209,7 @@ class OpenglNodeBase(_VideoNode):
209
209
  We use and return textures to maintain
210
210
  the process in GPU and optimize it.
211
211
  """
212
- if PythonValidator.is_instance_of(input, ['VideoFrame', 'ndarray']):
212
+ if PythonValidator.is_instance_of(input, np.ndarray):
213
213
  # TODO: What about the numpy format (?)
214
214
  input = frame_to_texture(input, self.context)
215
215
 
@@ -293,7 +293,7 @@ class WavingNode(OpenglNodeBase):
293
293
  # processed by the code
294
294
  def process(
295
295
  self,
296
- input: Union[moderngl.Texture, 'VideoFrame', 'np.ndarray'],
296
+ input: Union[moderngl.Texture, 'np.ndarray'],
297
297
  t: float = 0.0,
298
298
  ) -> moderngl.Texture:
299
299
  """
@@ -65,7 +65,7 @@ class BreathingFrame(OpenglNodeBase):
65
65
 
66
66
  def process(
67
67
  self,
68
- input: Union[moderngl.Texture, 'VideoFrame', 'np.ndarray'],
68
+ input: Union[moderngl.Texture, 'np.ndarray'],
69
69
  t: float = 0.0,
70
70
  ) -> moderngl.Texture:
71
71
  """
@@ -165,7 +165,7 @@ class HandheldFrame(OpenglNodeBase):
165
165
 
166
166
  def process(
167
167
  self,
168
- input: Union[moderngl.Texture, 'VideoFrame', 'np.ndarray'],
168
+ input: Union[moderngl.Texture, np.ndarray],
169
169
  t: float = 0.0,
170
170
  ) -> moderngl.Texture:
171
171
  """
@@ -351,7 +351,7 @@ class OrbitingFrame(OpenglNodeBase):
351
351
 
352
352
  def process(
353
353
  self,
354
- input: Union[moderngl.Texture, 'VideoFrame', 'np.ndarray'],
354
+ input: Union[moderngl.Texture, np.ndarray],
355
355
  t: float = 0.0,
356
356
  ) -> moderngl.Texture:
357
357
  """
@@ -446,7 +446,7 @@ class RotatingInCenterFrame(OpenglNodeBase):
446
446
 
447
447
  def process(
448
448
  self,
449
- input: Union[moderngl.Texture, 'VideoFrame', 'np.ndarray'],
449
+ input: Union[moderngl.Texture, np.ndarray],
450
450
  t: float = 0.0,
451
451
  ) -> moderngl.Texture:
452
452
  """
@@ -636,7 +636,7 @@ class StrangeTvFrame(OpenglNodeBase):
636
636
 
637
637
  def process(
638
638
  self,
639
- input: Union[moderngl.Texture, 'VideoFrame', 'np.ndarray'],
639
+ input: Union[moderngl.Texture, np.ndarray],
640
640
  t: float = 0.0,
641
641
  ) -> moderngl.Texture:
642
642
  """
@@ -744,7 +744,7 @@ class GlitchRgbFrame(OpenglNodeBase):
744
744
 
745
745
  def process(
746
746
  self,
747
- input: Union[moderngl.Texture, 'VideoFrame', 'np.ndarray'],
747
+ input: Union[moderngl.Texture, np.ndarray],
748
748
  t: float = 0.0,
749
749
  ) -> moderngl.Texture:
750
750
  """
yta_video_opengl/tests.py CHANGED
@@ -606,9 +606,9 @@ def video_modified_stored():
606
606
  # size = video.size,
607
607
  # first_frame = video.next_frame
608
608
  # )
609
- from yta_video_opengl.editor import OpenglEditor
609
+ from yta_video_opengl.effects import Effects
610
610
 
611
- editor = OpenglEditor()
611
+ editor = Effects()
612
612
  # waving_node_effect = editor.effects.video.waving_node(video.size, amplitude = 0.2, frequency = 9, speed = 3)
613
613
  # chorus_effect = editor.effects.audio.chorus(audio.sample_rate)
614
614
  # print(waving_node_effect)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: yta-video-opengl
3
- Version: 0.0.24
3
+ Version: 0.0.26
4
4
  Summary: Youtube Autonomous Video OpenGL Module
5
5
  Author: danialcala94
6
6
  Author-email: danielalcalavalera@gmail.com
@@ -0,0 +1,13 @@
1
+ yta_video_opengl/__init__.py,sha256=ycAx_XYMVDfkuObSvtW6irQ0Wo-fgxEz3fjIRMe8PpY,205
2
+ yta_video_opengl/effects.py,sha256=BqXN3dKw63MB-1eTpQm3TjoPYogX3TkVMBt__AqBa_4,10599
3
+ yta_video_opengl/nodes/__init__.py,sha256=mDqQBfOjDKqPqp_CNY38ROM_5lhyzQ9AgT0pRswpYUY,4464
4
+ yta_video_opengl/nodes/audio/__init__.py,sha256=LnGes6u1K0pa4CXP0LrHftLwv0zi-JYvHmYEkJqw_J8,3302
5
+ yta_video_opengl/nodes/video/__init__.py,sha256=I6F4JRNFKsj1jjy-nXoD9hj7rA47DtAIhAk6-m6vgjY,948
6
+ yta_video_opengl/nodes/video/opengl/__init__.py,sha256=nqe803cLoxE0NVMadYU8fgdEXrocDjoD-NEZvs1lERw,8542
7
+ yta_video_opengl/nodes/video/opengl/experimental.py,sha256=9MPudKhl_mDjOyVj89GGLJUVW2esc0PK15EsRpijtzI,22064
8
+ yta_video_opengl/tests.py,sha256=OPD1Caxt-VYHOtgjIhSfG8pqu8YMREgNsEUBZ22kd3o,24256
9
+ yta_video_opengl/utils.py,sha256=w6jYnZcBYPNAsTolkAlA6dxph0u_8-mcUzKvADlIlW8,3098
10
+ yta_video_opengl-0.0.26.dist-info/LICENSE,sha256=6kbiFSfobTZ7beWiKnHpN902HgBx-Jzgcme0SvKqhKY,1091
11
+ yta_video_opengl-0.0.26.dist-info/METADATA,sha256=d5l55MFB2wrIC4roMkkGyY0I8_LqyRw54WPQeQoL258,589
12
+ yta_video_opengl-0.0.26.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
13
+ yta_video_opengl-0.0.26.dist-info/RECORD,,
@@ -1,13 +0,0 @@
1
- yta_video_opengl/__init__.py,sha256=ycAx_XYMVDfkuObSvtW6irQ0Wo-fgxEz3fjIRMe8PpY,205
2
- yta_video_opengl/editor.py,sha256=ILzeGAe6uO5IptwrplbvnFu8e0j8v9AOaAmuvFH4YjI,9218
3
- yta_video_opengl/nodes/__init__.py,sha256=Rbh6HxWpKrdF_qlcGVKYBGW6i10NodoExa5qGEMcmIM,3738
4
- yta_video_opengl/nodes/audio/__init__.py,sha256=upKsYZrrNW2DxP77RyMCw2I16Lj9JsHbXGALw5grxbQ,6143
5
- yta_video_opengl/nodes/video/__init__.py,sha256=Nf1CnUaz6m7mOvVsuoTKMsq5QIVqEqZaiGseNOre8_k,859
6
- yta_video_opengl/nodes/video/opengl/__init__.py,sha256=bVPdS_wpz4HNurmLRDEHUmNZU7Qz8LptKfJ9yN_2PJM,8587
7
- yta_video_opengl/nodes/video/opengl/experimental.py,sha256=XuriXcOuJU5P0FruKffudCpMuO-ht8weJud88Qn8GKk,22158
8
- yta_video_opengl/tests.py,sha256=uvTU1_cvz5r7fETd4X8hvsYw4jViMDA0x-LsDNplFPM,24265
9
- yta_video_opengl/utils.py,sha256=w6jYnZcBYPNAsTolkAlA6dxph0u_8-mcUzKvADlIlW8,3098
10
- yta_video_opengl-0.0.24.dist-info/LICENSE,sha256=6kbiFSfobTZ7beWiKnHpN902HgBx-Jzgcme0SvKqhKY,1091
11
- yta_video_opengl-0.0.24.dist-info/METADATA,sha256=WKcDQFnZS0TvesGJM9N-bbPjOx0DdTNZb6yU-4nzUqY,589
12
- yta_video_opengl-0.0.24.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
13
- yta_video_opengl-0.0.24.dist-info/RECORD,,