auto-editor 27.1.1__py3-none-any.whl → 28.0.1__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.
Files changed (37) hide show
  1. auto_editor/__init__.py +1 -1
  2. auto_editor/__main__.py +0 -8
  3. auto_editor/cmds/cache.py +1 -1
  4. auto_editor/cmds/desc.py +8 -9
  5. auto_editor/cmds/info.py +4 -17
  6. auto_editor/cmds/palet.py +1 -1
  7. auto_editor/cmds/subdump.py +2 -4
  8. auto_editor/cmds/test.py +50 -31
  9. auto_editor/edit.py +52 -52
  10. auto_editor/{formats → exports}/fcp11.py +11 -7
  11. auto_editor/{formats → exports}/fcp7.py +7 -239
  12. auto_editor/exports/json.py +32 -0
  13. auto_editor/{formats → exports}/shotcut.py +8 -17
  14. auto_editor/ffwrapper.py +1 -3
  15. auto_editor/help.py +6 -17
  16. auto_editor/imports/__init__.py +0 -0
  17. auto_editor/imports/fcp7.py +275 -0
  18. auto_editor/{formats → imports}/json.py +16 -43
  19. auto_editor/json.py +2 -2
  20. auto_editor/lang/palet.py +6 -43
  21. auto_editor/lang/stdenv.py +8 -20
  22. auto_editor/lib/contracts.py +4 -6
  23. auto_editor/lib/data_structs.py +0 -3
  24. auto_editor/make_layers.py +13 -13
  25. auto_editor/preview.py +1 -2
  26. auto_editor/render/audio.py +9 -6
  27. auto_editor/render/video.py +3 -2
  28. auto_editor/timeline.py +35 -52
  29. {auto_editor-27.1.1.dist-info → auto_editor-28.0.1.dist-info}/METADATA +2 -2
  30. auto_editor-28.0.1.dist-info/RECORD +56 -0
  31. {auto_editor-27.1.1.dist-info → auto_editor-28.0.1.dist-info}/WHEEL +1 -1
  32. auto_editor/formats/utils.py +0 -56
  33. auto_editor-27.1.1.dist-info/RECORD +0 -54
  34. /auto_editor/{formats → exports}/__init__.py +0 -0
  35. {auto_editor-27.1.1.dist-info → auto_editor-28.0.1.dist-info}/entry_points.txt +0 -0
  36. {auto_editor-27.1.1.dist-info → auto_editor-28.0.1.dist-info}/licenses/LICENSE +0 -0
  37. {auto_editor-27.1.1.dist-info → auto_editor-28.0.1.dist-info}/top_level.txt +0 -0
@@ -11,7 +11,7 @@ from auto_editor.ffwrapper import FileInfo
11
11
  from auto_editor.lang.palet import Lexer, Parser, env, interpret, is_boolean_array
12
12
  from auto_editor.lib.data_structs import print_str
13
13
  from auto_editor.lib.err import MyError
14
- from auto_editor.timeline import ASpace, Template, TlAudio, TlVideo, VSpace, v1, v3
14
+ from auto_editor.timeline import ASpace, Clip, Template, VSpace, v1, v3
15
15
  from auto_editor.utils.func import mut_margin
16
16
  from auto_editor.utils.types import CoerceError, time
17
17
 
@@ -26,7 +26,7 @@ if TYPE_CHECKING:
26
26
  BoolList = NDArray[np.bool_]
27
27
 
28
28
 
29
- class Clip(NamedTuple):
29
+ class VirClip(NamedTuple):
30
30
  start: int
31
31
  dur: int
32
32
  offset: int
@@ -34,8 +34,8 @@ class Clip(NamedTuple):
34
34
  src: FileInfo
35
35
 
36
36
 
37
- def clipify(chunks: Chunks, src: FileInfo, start: int = 0) -> list[Clip]:
38
- clips: list[Clip] = []
37
+ def clipify(chunks: Chunks, src: FileInfo, start: int = 0) -> list[VirClip]:
38
+ clips: list[VirClip] = []
39
39
  i = 0
40
40
  for chunk in chunks:
41
41
  if chunk[2] > 0 and chunk[2] < 99999.0:
@@ -46,14 +46,14 @@ def clipify(chunks: Chunks, src: FileInfo, start: int = 0) -> list[Clip]:
46
46
  offset = int(chunk[0] / chunk[2])
47
47
 
48
48
  if not (clips and clips[-1].start == round(start)):
49
- clips.append(Clip(start, dur, offset, chunk[2], src))
49
+ clips.append(VirClip(start, dur, offset, chunk[2], src))
50
50
  start += dur
51
51
  i += 1
52
52
 
53
53
  return clips
54
54
 
55
55
 
56
- def make_av(src: FileInfo, all_clips: list[list[Clip]]) -> tuple[VSpace, ASpace]:
56
+ def make_av(src: FileInfo, all_clips: list[list[VirClip]]) -> tuple[VSpace, ASpace]:
57
57
  assert type(src) is FileInfo
58
58
  vtl: VSpace = []
59
59
  atl: ASpace = [[] for _ in range(len(src.audios))]
@@ -63,11 +63,11 @@ def make_av(src: FileInfo, all_clips: list[list[Clip]]) -> tuple[VSpace, ASpace]
63
63
  if src.videos:
64
64
  if len(vtl) == 0:
65
65
  vtl.append([])
66
- vtl[0].append(TlVideo(c.start, c.dur, c.src, c.offset, c.speed, 0))
66
+ vtl[0].append(Clip(c.start, c.dur, c.src, c.offset, 0, c.speed))
67
67
 
68
68
  for c in clips:
69
69
  for a in range(len(src.audios)):
70
- atl[a].append(TlAudio(c.start, c.dur, c.src, c.offset, c.speed, 1, a))
70
+ atl[a].append(Clip(c.start, c.dur, c.src, c.offset, a, c.speed))
71
71
 
72
72
  return vtl, atl
73
73
 
@@ -139,7 +139,7 @@ def make_timeline(
139
139
  interpret(env, parser)
140
140
 
141
141
  results = []
142
- for i, src in enumerate(sources):
142
+ for src in sources:
143
143
  try:
144
144
  parser = Parser(Lexer("`--edit`", args.edit))
145
145
  if log.is_debug:
@@ -247,7 +247,7 @@ def make_timeline(
247
247
  check_monotonic = len(sources) == 1
248
248
  last_i = 0
249
249
 
250
- clips: list[Clip] = []
250
+ clips: list[VirClip] = []
251
251
  start = 0
252
252
 
253
253
  for chunk in echunk(speed_index, src_index):
@@ -265,7 +265,7 @@ def make_timeline(
265
265
  raise ValueError("not monotonic", sources, this_i, last_i)
266
266
  last_i = this_i
267
267
 
268
- clips.append(Clip(start, dur, offset, chunk[3], chunk[0]))
268
+ clips.append(VirClip(start, dur, offset, chunk[3], chunk[0]))
269
269
 
270
270
  start += dur
271
271
 
@@ -275,13 +275,13 @@ def make_timeline(
275
275
  if c.src.videos:
276
276
  if len(vtl) == 0:
277
277
  vtl.append([])
278
- vtl[0].append(TlVideo(c.start, c.dur, c.src, c.offset, c.speed, 0))
278
+ vtl[0].append(Clip(c.start, c.dur, c.src, c.offset, 0, c.speed))
279
279
 
280
280
  for c in clips:
281
281
  for a in range(len(c.src.audios)):
282
282
  if a >= len(atl):
283
283
  atl.append([])
284
- atl[a].append(TlAudio(c.start, c.dur, c.src, c.offset, c.speed, 1, a))
284
+ atl[a].append(Clip(c.start, c.dur, c.src, c.offset, a, c.speed))
285
285
 
286
286
  # Turn long silent/loud array to formatted chunk list.
287
287
  # Example: [1, 1, 1, 2, 2], {1: 1.0, 2: 1.5} => [(0, 3, 1.0), (3, 5, 1.5)]
auto_editor/preview.py CHANGED
@@ -68,8 +68,7 @@ def preview(tl: v3, log: Log) -> None:
68
68
  for src in all_sources:
69
69
  in_len += initLevels(src, tb, bar, False, log).media_length
70
70
 
71
- out_len = tl.out_len()
72
-
71
+ out_len = len(tl)
73
72
  diff = out_len - in_len
74
73
 
75
74
  fp = sys.stdout
@@ -15,7 +15,7 @@ from auto_editor.json import load
15
15
  from auto_editor.lang.palet import env
16
16
  from auto_editor.lib.contracts import andc, between_c, is_int_or_float
17
17
  from auto_editor.lib.err import MyError
18
- from auto_editor.timeline import TlAudio, v3
18
+ from auto_editor.timeline import Clip, v3
19
19
  from auto_editor.utils.cmdkw import ParserError, parse_with_palet, pAttr, pAttrs
20
20
  from auto_editor.utils.func import parse_bitrate
21
21
  from auto_editor.utils.log import Log
@@ -155,7 +155,7 @@ def apply_audio_normalization(
155
155
  output_file.close()
156
156
 
157
157
 
158
- def process_audio_clip(clip: TlAudio, data: np.ndarray, sr: int) -> np.ndarray:
158
+ def process_audio_clip(clip: Clip, data: np.ndarray, sr: int, log: Log) -> np.ndarray:
159
159
  to_s16 = bv.AudioResampler(format="s16", layout="stereo", rate=sr)
160
160
  input_buffer = BytesIO()
161
161
 
@@ -217,6 +217,9 @@ def process_audio_clip(clip: TlAudio, data: np.ndarray, sr: int) -> np.ndarray:
217
217
  except (bv.BlockingIOError, bv.EOFError):
218
218
  break
219
219
 
220
+ if not all_frames:
221
+ log.debug(f"No audio frames at {clip=}")
222
+ return np.zeros_like(data)
220
223
  return np.concatenate(all_frames, axis=1)
221
224
 
222
225
 
@@ -272,7 +275,7 @@ def mix_audio_files(sr: int, audio_paths: list[str], output_path: str) -> None:
272
275
  max_val = np.max(np.abs(mixed_audio))
273
276
  if max_val > 0:
274
277
  mixed_audio = mixed_audio * (32767 / max_val)
275
- mixed_audio = mixed_audio.astype(np.int16) # type: ignore
278
+ mixed_audio = mixed_audio.astype(np.int16)
276
279
 
277
280
  output_container = bv.open(output_path, mode="w")
278
281
  output_stream = output_container.add_stream("pcm_s16le", rate=sr)
@@ -383,7 +386,7 @@ class Getter:
383
386
 
384
387
  def __init__(self, path: Path, stream: int, rate: int):
385
388
  self.container = bv.open(path)
386
- self.stream = self.container.streams.audio[0]
389
+ self.stream = self.container.streams.audio[stream]
387
390
  self.rate = rate
388
391
 
389
392
  def get(self, start: int, end: int) -> np.ndarray:
@@ -454,7 +457,7 @@ def _make_new_audio(tl: v3, fmt: bv.AudioFormat, args: Args, log: Log) -> list[A
454
457
  arr: np.ndarray | None = None
455
458
  use_iter = False
456
459
 
457
- for c, clip in enumerate(layer):
460
+ for clip in layer:
458
461
  if (clip.src, clip.stream) not in samples:
459
462
  samples[(clip.src, clip.stream)] = Getter(
460
463
  clip.src.path, clip.stream, sr
@@ -473,7 +476,7 @@ def _make_new_audio(tl: v3, fmt: bv.AudioFormat, args: Args, log: Log) -> list[A
473
476
 
474
477
  if clip.speed != 1 or clip.volume != 1:
475
478
  clip_arr = process_audio_clip(
476
- clip, getter.get(samp_start, samp_end), sr
479
+ clip, getter.get(samp_start, samp_end), sr, log
477
480
  )
478
481
  else:
479
482
  clip_arr = getter.get(samp_start, samp_end)
@@ -6,7 +6,7 @@ from typing import TYPE_CHECKING
6
6
  import bv
7
7
  import numpy as np
8
8
 
9
- from auto_editor.timeline import TlImage, TlRect, TlVideo
9
+ from auto_editor.timeline import Clip, TlImage, TlRect
10
10
  from auto_editor.utils.func import parse_bitrate
11
11
 
12
12
  if TYPE_CHECKING:
@@ -120,6 +120,7 @@ def render_av(
120
120
 
121
121
  del codec
122
122
  output_stream = output.add_stream(args.video_codec, rate=target_fps)
123
+ output_stream.options = {"x265-params": "log-level=error"} # type: ignore
123
124
 
124
125
  cc = output_stream.codec_context
125
126
  if args.vprofile is not None:
@@ -193,7 +194,7 @@ def render_av(
193
194
  obj_list: list[VideoFrame | TlRect | TlImage] = []
194
195
  for layer in tl.v:
195
196
  for lobj in layer:
196
- if isinstance(lobj, TlVideo):
197
+ if isinstance(lobj, Clip):
197
198
  if index >= lobj.start and index < (lobj.start + lobj.dur):
198
199
  _i = round((lobj.offset + index - lobj.start) * lobj.speed)
199
200
  obj_list.append(VideoFrame(_i, lobj.src))
auto_editor/timeline.py CHANGED
@@ -12,7 +12,6 @@ if TYPE_CHECKING:
12
12
  from collections.abc import Iterator
13
13
  from fractions import Fraction
14
14
  from pathlib import Path
15
- from typing import Any
16
15
 
17
16
  from auto_editor.ffwrapper import FileInfo
18
17
  from auto_editor.utils.chunks import Chunks
@@ -39,45 +38,24 @@ class v1:
39
38
 
40
39
 
41
40
  @dataclass(slots=True)
42
- class TlVideo:
41
+ class Clip:
43
42
  start: int
44
43
  dur: int
45
44
  src: FileInfo
46
45
  offset: int
47
- speed: float
48
46
  stream: int
49
47
 
50
- def as_dict(self) -> dict:
51
- return {
52
- "name": "video",
53
- "src": self.src,
54
- "start": self.start,
55
- "dur": self.dur,
56
- "offset": self.offset,
57
- "speed": self.speed,
58
- "stream": self.stream,
59
- }
60
-
61
-
62
- @dataclass(slots=True)
63
- class TlAudio:
64
- start: int
65
- dur: int
66
- src: FileInfo
67
- offset: int
68
- speed: float
69
- volume: float
70
- stream: int
48
+ speed: float = 1.0
49
+ volume: float = 1.0
71
50
 
72
51
  def as_dict(self) -> dict:
73
52
  return {
74
- "name": "audio",
53
+ "name": "video",
75
54
  "src": self.src,
76
55
  "start": self.start,
77
56
  "dur": self.dur,
78
57
  "offset": self.offset,
79
58
  "speed": self.speed,
80
- "volume": self.volume,
81
59
  "stream": self.stream,
82
60
  }
83
61
 
@@ -177,14 +155,12 @@ rect_builder = pAttrs(
177
155
  visual_objects = {
178
156
  "rect": (TlRect, rect_builder),
179
157
  "image": (TlImage, img_builder),
180
- "video": (TlVideo, video_builder),
158
+ "video": (Clip, video_builder),
181
159
  }
182
160
 
183
- VLayer = list[TlVideo | TlImage | TlRect]
161
+ VLayer = list[Clip | TlImage | TlRect]
184
162
  VSpace = list[VLayer]
185
-
186
- ALayer = list[TlAudio]
187
- ASpace = list[ALayer]
163
+ ASpace = list[list[Clip]]
188
164
 
189
165
 
190
166
  @dataclass(slots=True)
@@ -249,7 +225,7 @@ video\n"""
249
225
  for i, layer in enumerate(self.v):
250
226
  result += f" v{i} "
251
227
  for obj in layer:
252
- if isinstance(obj, TlVideo):
228
+ if isinstance(obj, Clip):
253
229
  result += (
254
230
  f"[#:start {obj.start} #:dur {obj.dur} #:off {obj.offset}] "
255
231
  )
@@ -284,7 +260,7 @@ video\n"""
284
260
  def sources(self) -> Iterator[FileInfo]:
285
261
  for vclips in self.v:
286
262
  for v in vclips:
287
- if isinstance(v, TlVideo):
263
+ if isinstance(v, Clip):
288
264
  yield v.src
289
265
  for aclips in self.a:
290
266
  for a in aclips:
@@ -297,29 +273,36 @@ video\n"""
297
273
  seen.add(source.path)
298
274
  yield source
299
275
 
300
- def _duration(self, layer: Any) -> int:
301
- total_dur = 0
302
- for clips in layer:
303
- dur = 0
304
- for clip in clips:
305
- dur += clip.dur
306
- total_dur = max(total_dur, dur)
307
- return total_dur
276
+ def __len__(self) -> int:
277
+ result = 0
278
+ for clips in self.v + self.a:
279
+ if len(clips) > 0:
280
+ lastClip = clips[-1]
281
+ result = max(result, lastClip.start + lastClip.dur)
308
282
 
309
- def out_len(self) -> int:
310
- # Calculates the duration of the timeline
311
- return max(self._duration(self.v), self._duration(self.a))
283
+ return result
312
284
 
313
285
  def as_dict(self) -> dict:
286
+ def aclip_to_dict(self: Clip) -> dict:
287
+ return {
288
+ "name": "audio",
289
+ "src": self.src,
290
+ "start": self.start,
291
+ "dur": self.dur,
292
+ "offset": self.offset,
293
+ "speed": self.speed,
294
+ "volume": self.volume,
295
+ "stream": self.stream,
296
+ }
297
+
314
298
  v = []
315
- for i, vlayer in enumerate(self.v):
299
+ a = []
300
+ for vlayer in self.v:
316
301
  vb = [vobj.as_dict() for vobj in vlayer]
317
302
  if vb:
318
303
  v.append(vb)
319
-
320
- a = []
321
- for i, alayer in enumerate(self.a):
322
- ab = [aobj.as_dict() for aobj in alayer]
304
+ for layer in self.a:
305
+ ab = [aclip_to_dict(clip) for clip in layer]
323
306
  if ab:
324
307
  a.append(ab)
325
308
 
@@ -347,7 +330,7 @@ video\n"""
347
330
  return self.T.sr
348
331
 
349
332
 
350
- def make_tracks_dir(tracks_dir: Path, path: Path) -> None:
333
+ def make_tracks_dir(tracks_dir: Path) -> None:
351
334
  from os import mkdir
352
335
  from shutil import rmtree
353
336
 
@@ -358,7 +341,7 @@ def make_tracks_dir(tracks_dir: Path, path: Path) -> None:
358
341
  mkdir(tracks_dir)
359
342
 
360
343
 
361
- def set_stream_to_0(src: FileInfo, tl: v3, log: Log) -> None:
344
+ def set_stream_to_0(tl: v3, log: Log) -> None:
362
345
  dir_exists = False
363
346
  cache: dict[Path, FileInfo] = {}
364
347
 
@@ -367,7 +350,7 @@ def set_stream_to_0(src: FileInfo, tl: v3, log: Log) -> None:
367
350
 
368
351
  fold = path.parent / f"{path.stem}_tracks"
369
352
  if not dir_exists:
370
- make_tracks_dir(fold, path)
353
+ make_tracks_dir(fold)
371
354
  dir_exists = True
372
355
 
373
356
  newtrack = fold / f"{path.stem}_{i}.wav"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: auto-editor
3
- Version: 27.1.1
3
+ Version: 28.0.1
4
4
  Summary: Auto-Editor: Effort free video editing!
5
5
  Author-email: WyattBlue <wyattblue@auto-editor.com>
6
6
  License-Expression: Unlicense
@@ -12,7 +12,7 @@ Requires-Python: <3.14,>=3.10
12
12
  Description-Content-Type: text/markdown
13
13
  License-File: LICENSE
14
14
  Requires-Dist: numpy<3.0,>=2
15
- Requires-Dist: basswood-av<16,>=15.0.0
15
+ Requires-Dist: basswood-av<16,>=15.2.1
16
16
  Dynamic: license-file
17
17
 
18
18
  <p align="center"><img src="https://auto-editor.com/img/auto-editor-banner.webp" title="Auto-Editor" width="700"></p>
@@ -0,0 +1,56 @@
1
+ auto_editor/__init__.py,sha256=qvc7djhJkqlXmlxcWZWLvK6JKBp01_I3fJuFV5euTBg,23
2
+ auto_editor/__main__.py,sha256=t5Um7M9ess9xYRfmn6iDvJoBqj_KRQLhlkpFdfhx3MU,15478
3
+ auto_editor/analyze.py,sha256=CeJG0LI9wXZk1R-QPrNGPS4za-_Avd8y7H-D437DqLg,12300
4
+ auto_editor/edit.py,sha256=GhOfKIe_FdbBGDQ_WH02CJl7Oi-AwaaSSh73F81h_kA,19234
5
+ auto_editor/ffwrapper.py,sha256=ueYdN7-cBAdJBJbv5yT05iuQP_BPFIrR5hFeMkk5c3U,5040
6
+ auto_editor/help.py,sha256=8Kkos7Bpcn-3YN7ngv0fZp-8a8Qw6b70ZZKerL8SEQ4,7901
7
+ auto_editor/json.py,sha256=g6ZsrSOXtjQj-8Otea3TIY2G-HZ6g-IXUblwukgTO1g,9332
8
+ auto_editor/make_layers.py,sha256=Udxn7Vw0Jz9HOarLeswQ-WwTu87PWcsyduBdtFwSOyc,10079
9
+ auto_editor/preview.py,sha256=yYn5jJLQ3TiJiNC6JffaggLVPQfBU558zJeRQz7nCDY,3046
10
+ auto_editor/timeline.py,sha256=ebnEX23HubNm444SIB2QNPkNdZcxHGhci1BpAeVDwcQ,9186
11
+ auto_editor/vanparse.py,sha256=Ug5A2QaRqGiw4l55Z_h9T2QU1x0WqRibR7yY5rQ0WTk,10002
12
+ auto_editor/cmds/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
+ auto_editor/cmds/cache.py,sha256=rK06dX3Z1pDAK0t5rqR7S2cMEpnT_Tv17t3Q5qPQKLI,1959
14
+ auto_editor/cmds/desc.py,sha256=kdRJfabdde5thuFOoTXlW3J3G8F0ZvbsJoOkUn7E3GA,805
15
+ auto_editor/cmds/info.py,sha256=NwzZu6l6IIdK0ajZdn8WX_iiJwlsMrGIZ2vffDRu3gc,6535
16
+ auto_editor/cmds/levels.py,sha256=2Hbvoy6wMbRRoHdZf25PMqq1uvhRKyPcITNPMpZFo7s,5632
17
+ auto_editor/cmds/palet.py,sha256=t2O_xM82PXUjnSgcHxyt9OG24gwQS4ksR2sKiQ1SvUA,743
18
+ auto_editor/cmds/repl.py,sha256=HSUTDaVykPb5Bd-v_jz_8R7HvFmKOcT_ZVmP-d0AbUY,3247
19
+ auto_editor/cmds/subdump.py,sha256=Zxs9X0gEaQYA5F1EqccJmVUYfI1o3J7ltyc9bvy1tA4,2393
20
+ auto_editor/cmds/test.py,sha256=p7z2cojsiyWnRN_UVeT4iYakkGlsQTjt_dRZ4cSvIQg,29835
21
+ auto_editor/exports/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
+ auto_editor/exports/fcp11.py,sha256=LiWHtA-jgwzbiSoBzNBUaTjOEuqnvr3dYBQmdlw7m3Y,5244
23
+ auto_editor/exports/fcp7.py,sha256=shZtn5i66hqGVrpR1PP1hiwKiZirr1cRUxATzbW-BOo,12069
24
+ auto_editor/exports/json.py,sha256=Z7RKtD5-OB3saOtWG9qfI9OrLtylhU9VyfpnVRNcuU8,768
25
+ auto_editor/exports/shotcut.py,sha256=MpzYqDO_XSnd-bKCKQjJFqOf_mSdR9QOWi8_Y1Y_BwY,4696
26
+ auto_editor/imports/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
+ auto_editor/imports/fcp7.py,sha256=Vep1syViRZOrtZBlF6Ek_eRy0rLINpTso5nrh3uY3zk,8563
28
+ auto_editor/imports/json.py,sha256=5c_vKoS8FzxAWagCetrwATHdnZ2beWQ77g8JYKVM0i8,6993
29
+ auto_editor/lang/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
+ auto_editor/lang/libintrospection.py,sha256=6H1rGp0wqaCud5IPaoEmzULGnYt6ec7_0h32ATcw2oY,261
31
+ auto_editor/lang/libmath.py,sha256=z33A161Oe6vYYK7R6pgYjdZZe63dQkN38Qf36TL3prg,847
32
+ auto_editor/lang/palet.py,sha256=bsuEWNEefTb0-69Dc4lq4aotqu7aarH1okETK8ab-Gw,22794
33
+ auto_editor/lang/stdenv.py,sha256=munuKA5rkg_5krQ_km92JhoNY6Vio9wo5E79YWlD2eg,43654
34
+ auto_editor/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
+ auto_editor/lib/contracts.py,sha256=bADXnFXyq_-Tku59saxwDOlvexfS3wMAMdrKNL-Ql2w,7494
36
+ auto_editor/lib/data_structs.py,sha256=2SxsOXKiY0H95wRIFOrQBjv1ykJUQar0Vr5dK9zZOiQ,6971
37
+ auto_editor/lib/err.py,sha256=UlszQJdzMZwkbT8x3sY4GkCV_5x9yrd6uVVUzvA8iiI,35
38
+ auto_editor/render/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
+ auto_editor/render/audio.py,sha256=08Leg9R66ROz8meZyY03e7yfUd5otxdd6DdNO9vX5ys,17518
40
+ auto_editor/render/subtitle.py,sha256=F27T8OsAojUIGTGBWqTdH36h0BnHXSExxIqzOtqyZoE,6129
41
+ auto_editor/render/video.py,sha256=8somlAxtbGMSRREab8psTdIlaETZQ2s2gY20PWY9sww,12072
42
+ auto_editor/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
43
+ auto_editor/utils/bar.py,sha256=Ky9JRf37JTgLyvNuIXDfucaUE8H1vBbCqKLjttmsmmo,4156
44
+ auto_editor/utils/chunks.py,sha256=J-eGKtEz68gFtRrj1kOSgH4Tj_Yz6prNQ7Xr-d9NQJw,52
45
+ auto_editor/utils/cmdkw.py,sha256=aUGBvBel2Ko1o6Rwmr4rEL-BMc5hEnzYLbyZ1GeJdcY,5729
46
+ auto_editor/utils/container.py,sha256=CNHChHbhzIrjmDdWw6UzMqscrr9u7A-ZqKWejGjJwYE,2628
47
+ auto_editor/utils/func.py,sha256=ODyjXnzSDatEu08w398K8_xBKYdXMY3IPHiJpGRZDyQ,3250
48
+ auto_editor/utils/log.py,sha256=wPNf6AabV-0cnoS_bPLv1Lh7llQBtNqPKeh07einOuc,3701
49
+ auto_editor/utils/types.py,sha256=j2hd4zMQ9EftDy41Ji2_PFru_7HEZObd9yKA0BJxFaY,7616
50
+ auto_editor-28.0.1.dist-info/licenses/LICENSE,sha256=yiq99pWITHfqS0pbZMp7cy2dnbreTuvBwudsU-njvIM,1210
51
+ docs/build.py,sha256=g1uc1H9T_naGaermUiVMMwUpbT0IWElRhjgT0fvCh8w,1914
52
+ auto_editor-28.0.1.dist-info/METADATA,sha256=DqTFmUbe3CYS0CefGlNadtwH80JaemOw0MOCXtDGCsg,6176
53
+ auto_editor-28.0.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
54
+ auto_editor-28.0.1.dist-info/entry_points.txt,sha256=UAsTc7qJQbnAzHd7KWg-ALo_X9Hj2yDs3M9I2DV3eyI,212
55
+ auto_editor-28.0.1.dist-info/top_level.txt,sha256=jBV5zlbWRbKOa-xaWPvTD45QL7lGExx2BDzv-Ji4dTw,17
56
+ auto_editor-28.0.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.1.0)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,56 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import TYPE_CHECKING
4
- from xml.etree.ElementTree import Element
5
-
6
- if TYPE_CHECKING:
7
- from auto_editor.utils.log import Log
8
-
9
-
10
- def show(ele: Element, limit: int, depth: int = 0) -> None:
11
- print(
12
- f"{' ' * (depth * 4)}<{ele.tag} {ele.attrib}> {ele.text.strip() if ele.text is not None else ''}"
13
- )
14
- for child in ele:
15
- if isinstance(child, Element) and depth < limit:
16
- show(child, limit, depth + 1)
17
-
18
-
19
- class Validator:
20
- def __init__(self, log: Log):
21
- self.log = log
22
-
23
- def parse(self, ele: Element, schema: dict) -> dict:
24
- new: dict = {}
25
-
26
- for key, val in schema.items():
27
- if isinstance(val, dict) and "__arr" in val:
28
- new[key] = []
29
-
30
- is_arr = False
31
- for child in ele:
32
- if child.tag not in schema:
33
- continue
34
-
35
- if schema[child.tag] is None:
36
- new[child.tag] = child
37
- continue
38
-
39
- if isinstance(schema[child.tag], dict):
40
- val = self.parse(child, schema[child.tag])
41
- is_arr = "__arr" in schema[child.tag]
42
- else:
43
- val = schema[child.tag](child.text)
44
-
45
- if child.tag in new:
46
- if not is_arr:
47
- self.log.error(f"<{child.tag}> can only occur once")
48
- new[child.tag].append(val)
49
- else:
50
- new[child.tag] = [val] if is_arr else val
51
-
52
- return new
53
-
54
- def check(self, ele: Element, tag: str) -> None:
55
- if tag != ele.tag:
56
- self.log.error(f"Expected '{tag}' tag, got '{ele.tag}'")
@@ -1,54 +0,0 @@
1
- auto_editor/__init__.py,sha256=0ioEHfOkA9Eoup9m_rzaYLCKq4b4PYoylPtUx3iCRPE,23
2
- auto_editor/__main__.py,sha256=WfNtjKwx5fDMPpfSNLarigXD3Jp0My98FpzQqSAxQZ8,15807
3
- auto_editor/analyze.py,sha256=CeJG0LI9wXZk1R-QPrNGPS4za-_Avd8y7H-D437DqLg,12300
4
- auto_editor/edit.py,sha256=qeuStjcBbRVhLweap_pxxAfME3Jh6tHyxywOjrYJ_ts,19125
5
- auto_editor/ffwrapper.py,sha256=Wet6B5nohgnjpBX7o20Zq0rYr-H9mUuOqHrbQAPPj38,5128
6
- auto_editor/help.py,sha256=CzfDTsL4GuGu596ySHKj_wKnxGR9h8B0KUdkZpo33oE,8044
7
- auto_editor/json.py,sha256=8IVhZJSLx2IVqJsbR5YKDvbHOhgIOvdQmYNpMdMG_xA,9332
8
- auto_editor/make_layers.py,sha256=nSEeCHysMot2eze23q05g2HFDuskN_4Jk108xlk2Rw8,10102
9
- auto_editor/preview.py,sha256=cqQdozM2IB-5qXHNxeqiSrSdEIzlMfjD4SU-NX9sYZ0,3052
10
- auto_editor/timeline.py,sha256=wUduvIB7JRoV_kswSBWJar_aNJH6i-RO917xrON6lIM,9521
11
- auto_editor/vanparse.py,sha256=Ug5A2QaRqGiw4l55Z_h9T2QU1x0WqRibR7yY5rQ0WTk,10002
12
- auto_editor/cmds/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
- auto_editor/cmds/cache.py,sha256=bViYbtVXefTeEIUvSanDfA6cG35ep1N_Jvtz7ZjgIkY,1959
14
- auto_editor/cmds/desc.py,sha256=DSAWPKt8PS9soBTgzpsFIEWoTe4gPTWwjXpNL-p3WsI,866
15
- auto_editor/cmds/info.py,sha256=VA2WkTBbQPvrVHjDaJyqryoVMtiiN6cguiUMdWgBJfU,7002
16
- auto_editor/cmds/levels.py,sha256=2Hbvoy6wMbRRoHdZf25PMqq1uvhRKyPcITNPMpZFo7s,5632
17
- auto_editor/cmds/palet.py,sha256=ONzTqemaQq9YEfIOsDRNnwzfqnEMUMSXIQrETxyroRU,749
18
- auto_editor/cmds/repl.py,sha256=HSUTDaVykPb5Bd-v_jz_8R7HvFmKOcT_ZVmP-d0AbUY,3247
19
- auto_editor/cmds/subdump.py,sha256=kHg8nfUi6I6VeJjEgMxupPa666qsYUh7ZEUxint7Gqo,2443
20
- auto_editor/cmds/test.py,sha256=UNN1r6J69-woqA6QU7TeY0WlPxukQzwCRl5DGBTLK8g,28837
21
- auto_editor/formats/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
- auto_editor/formats/fcp11.py,sha256=uaJbLiwiVxqoVy5JCA14wZj-m1wqZIzWh7rS-BsnSQM,5219
23
- auto_editor/formats/fcp7.py,sha256=Q_raDxOBqo8QcnhaiXrIFPB-Un7wUvQ4SYt6KALOI1s,19212
24
- auto_editor/formats/json.py,sha256=UUBhFR_79vn4Lxu73B0cVBFgw4qytrmMP-TiCmDFMd0,7666
25
- auto_editor/formats/shotcut.py,sha256=-ES854LLFCMCBe100JRJedDmuk8zPev17aQMTrzPv-g,4923
26
- auto_editor/formats/utils.py,sha256=LYXDiqOk9WwUorLGw2D0M7In9BNDkoKikNawuks7hqE,1648
27
- auto_editor/lang/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
- auto_editor/lang/libintrospection.py,sha256=6H1rGp0wqaCud5IPaoEmzULGnYt6ec7_0h32ATcw2oY,261
29
- auto_editor/lang/libmath.py,sha256=z33A161Oe6vYYK7R6pgYjdZZe63dQkN38Qf36TL3prg,847
30
- auto_editor/lang/palet.py,sha256=RQjyIZMJSWnzDkHTu-5mt74o9_4zO4VrcH-wLojCF7A,24113
31
- auto_editor/lang/stdenv.py,sha256=o7kFu7EbaH71XPFGxJUXYGxSeZ8O3i1_C5Hmi9uya4Q,44150
32
- auto_editor/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
33
- auto_editor/lib/contracts.py,sha256=lExGQymcQUmwG5lC1lO4qm4GY8W0q_yzK_miTaAoPA4,7586
34
- auto_editor/lib/data_structs.py,sha256=Hnzl5gWvo-geTU0g-lGejj6HQW3VvPv0NBEj2XoGskY,7089
35
- auto_editor/lib/err.py,sha256=UlszQJdzMZwkbT8x3sY4GkCV_5x9yrd6uVVUzvA8iiI,35
36
- auto_editor/render/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
37
- auto_editor/render/audio.py,sha256=ejV_NIvrmxMJt6mf7nPNIzlPHOumNhcIO2J-irHO-k8,17427
38
- auto_editor/render/subtitle.py,sha256=F27T8OsAojUIGTGBWqTdH36h0BnHXSExxIqzOtqyZoE,6129
39
- auto_editor/render/video.py,sha256=uIrYzF4bDZ3vwfX2F6TdR6F73GI4yruGssto9xEQ-AA,11999
40
- auto_editor/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
41
- auto_editor/utils/bar.py,sha256=Ky9JRf37JTgLyvNuIXDfucaUE8H1vBbCqKLjttmsmmo,4156
42
- auto_editor/utils/chunks.py,sha256=J-eGKtEz68gFtRrj1kOSgH4Tj_Yz6prNQ7Xr-d9NQJw,52
43
- auto_editor/utils/cmdkw.py,sha256=aUGBvBel2Ko1o6Rwmr4rEL-BMc5hEnzYLbyZ1GeJdcY,5729
44
- auto_editor/utils/container.py,sha256=CNHChHbhzIrjmDdWw6UzMqscrr9u7A-ZqKWejGjJwYE,2628
45
- auto_editor/utils/func.py,sha256=ODyjXnzSDatEu08w398K8_xBKYdXMY3IPHiJpGRZDyQ,3250
46
- auto_editor/utils/log.py,sha256=wPNf6AabV-0cnoS_bPLv1Lh7llQBtNqPKeh07einOuc,3701
47
- auto_editor/utils/types.py,sha256=j2hd4zMQ9EftDy41Ji2_PFru_7HEZObd9yKA0BJxFaY,7616
48
- auto_editor-27.1.1.dist-info/licenses/LICENSE,sha256=yiq99pWITHfqS0pbZMp7cy2dnbreTuvBwudsU-njvIM,1210
49
- docs/build.py,sha256=g1uc1H9T_naGaermUiVMMwUpbT0IWElRhjgT0fvCh8w,1914
50
- auto_editor-27.1.1.dist-info/METADATA,sha256=ri7aLym52FDEnnDR7czUR3xqZ025BLmepV0Em6GXjQc,6176
51
- auto_editor-27.1.1.dist-info/WHEEL,sha256=wXxTzcEDnjrTwFYjLPcsW_7_XihufBwmpiBeiXNBGEA,91
52
- auto_editor-27.1.1.dist-info/entry_points.txt,sha256=UAsTc7qJQbnAzHd7KWg-ALo_X9Hj2yDs3M9I2DV3eyI,212
53
- auto_editor-27.1.1.dist-info/top_level.txt,sha256=jBV5zlbWRbKOa-xaWPvTD45QL7lGExx2BDzv-Ji4dTw,17
54
- auto_editor-27.1.1.dist-info/RECORD,,
File without changes