auto-editor 26.2.0__py3-none-any.whl → 26.3.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.
auto_editor/__init__.py CHANGED
@@ -1 +1 @@
1
- __version__ = "26.2.0"
1
+ __version__ = "26.3.1"
auto_editor/analyze.py CHANGED
@@ -178,7 +178,6 @@ class Levels:
178
178
 
179
179
  with av.open(self.src.path, "r") as container:
180
180
  audio_stream = container.streams.audio[0]
181
- self.log.experimental(audio_stream.codec)
182
181
  result = sum(1 for _ in iter_audio(audio_stream, self.tb))
183
182
 
184
183
  self.log.debug(f"Audio Length: {result}")
@@ -263,9 +262,6 @@ class Levels:
263
262
  container = av.open(self.src.path, "r")
264
263
  audio = container.streams.audio[stream]
265
264
 
266
- if audio.codec.experimental:
267
- self.log.error(f"`{audio.codec.name}` is an experimental codec")
268
-
269
265
  if audio.duration is not None and audio.time_base is not None:
270
266
  inaccurate_dur = int(audio.duration * audio.time_base * self.tb)
271
267
  elif container.duration is not None:
@@ -304,9 +300,6 @@ class Levels:
304
300
  container = av.open(self.src.path, "r")
305
301
  video = container.streams.video[stream]
306
302
 
307
- if video.codec.experimental:
308
- self.log.experimental(video.codec)
309
-
310
303
  inaccurate_dur = (
311
304
  1024
312
305
  if video.duration is None or video.time_base is None
@@ -136,7 +136,6 @@ def main(sys_args: list[str] = sys.argv[1:]) -> None:
136
136
  else:
137
137
  container = av.open(src.path, "r")
138
138
  audio_stream = container.streams.audio[obj["stream"]]
139
- log.experimental(audio_stream.codec)
140
139
 
141
140
  values = []
142
141
 
@@ -158,7 +157,6 @@ def main(sys_args: list[str] = sys.argv[1:]) -> None:
158
157
  else:
159
158
  container = av.open(src.path, "r")
160
159
  video_stream = container.streams.video[obj["stream"]]
161
- log.experimental(video_stream.codec)
162
160
 
163
161
  values = []
164
162
 
auto_editor/cmds/test.py CHANGED
@@ -9,6 +9,7 @@ from fractions import Fraction
9
9
  from time import perf_counter
10
10
  from typing import TYPE_CHECKING
11
11
 
12
+ import av
12
13
  import numpy as np
13
14
 
14
15
  from auto_editor.ffwrapper import FileInfo, initFileInfo
@@ -235,6 +236,11 @@ def main(sys_args: list[str] | None = None):
235
236
 
236
237
  def example():
237
238
  out = run.main(inputs=["example.mp4"], cmd=[])
239
+
240
+ with av.open(out) as container:
241
+ assert container.streams[0].type == "video"
242
+ assert container.streams[1].type == "audio"
243
+
238
244
  cn = fileinfo(out)
239
245
  video = cn.videos[0]
240
246
 
@@ -549,6 +555,15 @@ def main(sys_args: list[str] | None = None):
549
555
  def yuv442p():
550
556
  return run.main(["resources/test_yuv422p.mp4"], [])
551
557
 
558
+ def prores():
559
+ run.main(["resources/testsrc.mp4", "-c:v", "prores", "-o", "out.mkv"], [])
560
+ assert fileinfo("out.mkv").videos[0].pix_fmt == "yuv422p10le"
561
+
562
+ run.main(["out.mkv", "-c:v", "prores", "-o", "out2.mkv"], [])
563
+ assert fileinfo("out2.mkv").videos[0].pix_fmt == "yuv422p10le"
564
+
565
+ return "out.mkv", "out2.mkv"
566
+
552
567
  # Issue 280
553
568
  def SAR():
554
569
  out = run.main(["resources/SAR-2by3.mp4"], [])
@@ -735,6 +750,7 @@ def main(sys_args: list[str] | None = None):
735
750
  premiere,
736
751
  SAR,
737
752
  yuv442p,
753
+ prores,
738
754
  edit_negative_tests,
739
755
  edit_positive_tests,
740
756
  audio_norm_f,
auto_editor/edit.py CHANGED
@@ -3,6 +3,7 @@ from __future__ import annotations
3
3
  import os
4
4
  import sys
5
5
  from fractions import Fraction
6
+ from heapq import heappop, heappush
6
7
  from os.path import splitext
7
8
  from subprocess import run
8
9
  from typing import Any
@@ -309,6 +310,13 @@ def edit_media(paths: list[str], args: Args, log: Log) -> None:
309
310
  else:
310
311
  audio_paths = []
311
312
 
313
+ # Setup video
314
+ if ctr.default_vid != "none" and tl.v:
315
+ vframes = render_av(output, tl, args, log)
316
+ output_stream = next(vframes)
317
+ else:
318
+ output_stream, vframes = None, iter([])
319
+
312
320
  # Setup audio
313
321
  if audio_paths:
314
322
  try:
@@ -363,19 +371,87 @@ def edit_media(paths: list[str], args: Args, log: Log) -> None:
363
371
  subtitle_streams.append(subtitle_stream)
364
372
  sub_gen_frames.append(subtitle_input.demux(subtitles=0))
365
373
 
366
- # Setup video
367
- if ctr.default_vid != "none" and tl.v:
368
- vframes = render_av(output, tl, args, bar, log)
369
- output_stream = next(vframes)
374
+ no_color = log.no_color or log.machine
375
+ encoder_titles = []
376
+ if output_stream is not None:
377
+ name = output_stream.codec.canonical_name
378
+ encoder_titles.append(name if no_color else f"\033[95m{name}")
379
+ if audio_streams:
380
+ name = audio_streams[0].codec.canonical_name
381
+ encoder_titles.append(name if no_color else f"\033[96m{name}")
382
+ if subtitle_streams:
383
+ name = subtitle_streams[0].codec.canonical_name
384
+ encoder_titles.append(name if no_color else f"\033[32m{name}")
385
+
386
+ title = f"({os.path.splitext(output_path)[1][1:]}) "
387
+ if no_color:
388
+ title += "+".join(encoder_titles)
370
389
  else:
371
- output_stream, vframes = None, iter([])
390
+ title += "\033[0m+".join(encoder_titles) + "\033[0m"
391
+ bar.start(tl.end, title)
392
+
393
+ MAX_AUDIO_AHEAD = 30 # In timebase, how far audio can be ahead of video.
394
+ MAX_SUB_AHEAD = 30
395
+
396
+ class Priority:
397
+ __slots__ = ("index", "frame_type", "frame", "stream")
398
+
399
+ def __init__(self, value: int | Fraction, frame, stream):
400
+ self.frame_type: str = stream.type
401
+ assert self.frame_type in ("audio", "subtitle", "video")
402
+ if self.frame_type in {"audio", "subtitle"}:
403
+ self.index: int | float = round(value * frame.time_base * tl.tb)
404
+ else:
405
+ self.index = float("inf") if value is None else int(value)
406
+ self.frame = frame
407
+ self.stream = stream
408
+
409
+ def __lt__(self, other):
410
+ return self.index < other.index
411
+
412
+ def __eq__(self, other):
413
+ return self.index == other.index
414
+
415
+ # Priority queue for ordered frames by time_base.
416
+ frame_queue: list[Priority] = []
417
+ latest_audio_index = float("-inf")
418
+ latest_sub_index = float("-inf")
419
+ earliest_video_index = None
372
420
 
373
- # Process frames
374
421
  while True:
375
- audio_frames = [next(frames, None) for frames in audio_gen_frames]
376
- video_frame = next(vframes, None)
377
- subtitle_frames = [next(packet, None) for packet in sub_gen_frames]
422
+ if earliest_video_index is None:
423
+ should_get_audio = True
424
+ should_get_sub = True
425
+ else:
426
+ for item in frame_queue:
427
+ if item.frame_type == "audio":
428
+ latest_audio_index = max(latest_audio_index, item.index)
429
+ elif item.frame_type == "subtitle":
430
+ latest_sub_index = max(latest_sub_index, item.index)
431
+
432
+ should_get_audio = (
433
+ latest_audio_index <= earliest_video_index + MAX_AUDIO_AHEAD
434
+ )
435
+ should_get_sub = (
436
+ latest_sub_index <= earliest_video_index + MAX_SUB_AHEAD
437
+ )
378
438
 
439
+ index, video_frame = next(vframes, (0, None))
440
+
441
+ if video_frame:
442
+ earliest_video_index = index
443
+ heappush(frame_queue, Priority(index, video_frame, output_stream))
444
+
445
+ if should_get_audio:
446
+ audio_frames = [next(frames, None) for frames in audio_gen_frames]
447
+ else:
448
+ audio_frames = [None]
449
+ if should_get_sub:
450
+ subtitle_frames = [next(packet, None) for packet in sub_gen_frames]
451
+ else:
452
+ subtitle_frames = [None]
453
+
454
+ # Break if no more frames
379
455
  if (
380
456
  all(frame is None for frame in audio_frames)
381
457
  and video_frame is None
@@ -383,34 +459,48 @@ def edit_media(paths: list[str], args: Args, log: Log) -> None:
383
459
  ):
384
460
  break
385
461
 
386
- for audio_stream, audio_frame in zip(audio_streams, audio_frames):
387
- if audio_frame:
462
+ if should_get_audio:
463
+ for audio_stream, audio_frame in zip(audio_streams, audio_frames):
388
464
  for reframe in resampler.resample(audio_frame):
389
- output.mux(audio_stream.encode(reframe))
390
-
391
- for subtitle_stream, packet in zip(subtitle_streams, subtitle_frames):
392
- if not packet or packet.dts is None:
393
- continue
394
- packet.stream = subtitle_stream
395
- output.mux(packet)
396
-
397
- if video_frame:
465
+ assert reframe.pts is not None
466
+ heappush(
467
+ frame_queue,
468
+ Priority(reframe.pts, reframe, audio_stream),
469
+ )
470
+ if should_get_sub:
471
+ for subtitle_stream, packet in zip(subtitle_streams, subtitle_frames):
472
+ if packet and packet.pts is not None:
473
+ packet.stream = subtitle_stream
474
+ heappush(
475
+ frame_queue, Priority(packet.pts, packet, subtitle_stream)
476
+ )
477
+
478
+ while frame_queue and frame_queue[0].index <= index:
479
+ item = heappop(frame_queue)
480
+ frame_type = item.frame_type
398
481
  try:
399
- output.mux(output_stream.encode(video_frame))
482
+ if frame_type in {"video", "audio"}:
483
+ output.mux(item.stream.encode(item.frame))
484
+ elif frame_type == "subtitle":
485
+ output.mux(item.frame)
400
486
  except av.error.ExternalError:
401
487
  log.error(
402
- f"Generic error for encoder: {output_stream.name}\n"
403
- "Perhaps video quality settings are too low?"
488
+ f"Generic error for encoder: {item.stream.name}\n"
489
+ f"at {item.index} time_base\nPerhaps video quality settings are too low?"
404
490
  )
405
491
  except av.FFmpegError as e:
406
492
  log.error(e)
407
493
 
494
+ bar.tick(index)
495
+
408
496
  # Flush streams
409
497
  if output_stream is not None:
410
498
  output.mux(output_stream.encode(None))
411
499
  for audio_stream in audio_streams:
412
500
  output.mux(audio_stream.encode(None))
413
501
 
502
+ bar.end()
503
+
414
504
  # Close resources
415
505
  for audio_input in audio_inputs:
416
506
  audio_input.close()
auto_editor/ffwrapper.py CHANGED
@@ -147,10 +147,9 @@ def initFileInfo(path: str, log: Log) -> FileInfo:
147
147
  adur = float(a.duration * a.time_base)
148
148
 
149
149
  a_cc = a.codec_context
150
- name = a_cc.name if a_cc.name != "mp3float" else "mp3"
151
150
  audios += (
152
151
  AudioStream(
153
- name,
152
+ a_cc.codec.canonical_name,
154
153
  0 if a_cc.sample_rate is None else a_cc.sample_rate,
155
154
  a.layout.name,
156
155
  a_cc.channels,
@@ -1045,7 +1045,7 @@ def make_standard_env() -> dict[str, Any]:
1045
1045
  # reals
1046
1046
  "pow": Proc("pow", pow, (2, 2), is_real),
1047
1047
  "abs": Proc("abs", abs, (1, 1), is_real),
1048
- "round": Proc("round", round, (1, 1), is_real),
1048
+ "round": Proc("round", round, (1, 2), is_real, is_int),
1049
1049
  "max": Proc("max", lambda *v: max(v), (1, None), is_real),
1050
1050
  "min": Proc("min", lambda *v: min(v), (1, None), is_real),
1051
1051
  "max-seq": Proc("max-seq", max, (1, 1), is_sequence),
@@ -15,7 +15,6 @@ if TYPE_CHECKING:
15
15
 
16
16
  from auto_editor.ffwrapper import FileInfo
17
17
  from auto_editor.timeline import v3
18
- from auto_editor.utils.bar import Bar
19
18
  from auto_editor.utils.log import Log
20
19
  from auto_editor.utils.types import Args
21
20
 
@@ -26,35 +25,12 @@ class VideoFrame:
26
25
  src: FileInfo
27
26
 
28
27
 
29
- # From: github.com/PyAV-Org/PyAV/blob/main/av/video/frame.pyx
30
- allowed_pix_fmt = {
31
- "yuv420p",
32
- "yuvj420p",
33
- "yuv444p",
34
- "yuvj444p",
35
- "rgb48be",
36
- "rgb48le",
37
- "rgb64be",
38
- "rgb64le",
39
- "rgb24",
40
- "bgr24",
41
- "argb",
42
- "rgba",
43
- "abgr",
44
- "bgra",
45
- "gray",
46
- "gray8",
47
- "gray16be",
48
- "gray16le",
49
- "rgb8",
50
- "bgr8",
51
- "pal8",
52
- }
28
+ allowed_pix_fmt = av.video.frame.supported_np_pix_fmts
53
29
 
54
30
 
55
31
  def make_solid(width: int, height: int, pix_fmt: str, bg: str) -> av.VideoFrame:
56
32
  hex_color = bg.lstrip("#").upper()
57
- rgb_color = tuple(int(hex_color[i : i + 2], 16) for i in {0, 2, 4})
33
+ rgb_color = tuple(int(hex_color[i : i + 2], 16) for i in (0, 2, 4))
58
34
 
59
35
  rgb_array = np.full((height, width, 3), rgb_color, dtype=np.uint8)
60
36
  rgb_frame = av.VideoFrame.from_ndarray(rgb_array, format="rgb24")
@@ -65,7 +41,7 @@ def make_image_cache(tl: v3) -> dict[tuple[FileInfo, int], np.ndarray]:
65
41
  img_cache = {}
66
42
  for clip in tl.v:
67
43
  for obj in clip:
68
- if isinstance(obj, TlImage) and obj.src not in img_cache:
44
+ if isinstance(obj, TlImage) and (obj.src, obj.width) not in img_cache:
69
45
  with av.open(obj.src.path) as cn:
70
46
  my_stream = cn.streams.video[0]
71
47
  for frame in cn.decode(my_stream):
@@ -85,7 +61,7 @@ def make_image_cache(tl: v3) -> dict[tuple[FileInfo, int], np.ndarray]:
85
61
 
86
62
 
87
63
  def render_av(
88
- output: av.container.OutputContainer, tl: v3, args: Args, bar: Bar, log: Log
64
+ output: av.container.OutputContainer, tl: v3, args: Args, log: Log
89
65
  ) -> Any:
90
66
  from_ndarray = av.VideoFrame.from_ndarray
91
67
 
@@ -132,13 +108,15 @@ def render_av(
132
108
 
133
109
  codec = av.Codec(args.video_codec, "w")
134
110
 
135
- if args.video_codec == "gif":
111
+ if codec.canonical_name == "gif":
136
112
  if codec.video_formats is not None and target_pix_fmt in (
137
113
  f.name for f in codec.video_formats
138
114
  ):
139
115
  target_pix_fmt = target_pix_fmt
140
116
  else:
141
117
  target_pix_fmt = "rgb8"
118
+ elif codec.canonical_name == "prores":
119
+ target_pix_fmt = "yuv422p10le"
142
120
  else:
143
121
  target_pix_fmt = (
144
122
  target_pix_fmt if target_pix_fmt in allowed_pix_fmt else "yuv420p"
@@ -212,8 +190,6 @@ def render_av(
212
190
  seek_frame = None
213
191
  frames_saved = 0
214
192
 
215
- bar.start(tl.end, "Creating new video")
216
-
217
193
  bg = args.background
218
194
  null_frame = make_solid(target_width, target_height, target_pix_fmt, bg)
219
195
  frame_index = -1
@@ -334,11 +310,7 @@ def render_av(
334
310
 
335
311
  if frame.format.name != target_pix_fmt:
336
312
  frame = frame.reformat(format=target_pix_fmt)
337
- bar.tick(index)
338
- elif index % 3 == 0:
339
- bar.tick(index)
340
313
 
341
- yield from_ndarray(frame.to_ndarray(), format=frame.format.name)
314
+ yield (index, from_ndarray(frame.to_ndarray(), format=frame.format.name))
342
315
 
343
- bar.end()
344
316
  log.debug(f"Total frames saved seeking: {frames_saved}")
auto_editor/utils/bar.py CHANGED
@@ -89,20 +89,26 @@ class Bar:
89
89
  percent = round(progress * 100, 1)
90
90
  p_pad = " " * (4 - len(str(percent)))
91
91
  columns = get_terminal_size().columns
92
- bar_len = max(1, columns - (len_title + 32))
92
+ bar_len = max(1, columns - len_title - 35)
93
93
  bar_str = self._bar_str(progress, bar_len)
94
94
 
95
- bar = f" {self.icon}{title} {bar_str} {p_pad}{percent}% ETA {new_time}"
96
-
97
- if len(bar) > columns - 2:
98
- bar = bar[: columns - 2]
99
- else:
100
- bar += " " * (columns - len(bar) - 4)
101
-
102
- sys.stdout.write(bar + "\r")
95
+ bar = f" {self.icon}{title} {bar_str} {p_pad}{percent}% ETA {new_time} \r"
96
+ sys.stdout.write(bar)
103
97
 
104
98
  def start(self, total: float, title: str = "Please wait") -> None:
105
- self.stack.append((title, len(title), total, time()))
99
+ len_title = 0
100
+ in_escape = False
101
+
102
+ for char in title:
103
+ if not in_escape:
104
+ if char == "\033":
105
+ in_escape = True
106
+ else:
107
+ len_title += 1
108
+ elif char == "m":
109
+ in_escape = False
110
+
111
+ self.stack.append((title, len_title, total, time()))
106
112
 
107
113
  try:
108
114
  self.tick(0)
auto_editor/utils/log.py CHANGED
@@ -1,14 +1,9 @@
1
- from __future__ import annotations
2
-
3
1
  import sys
4
2
  from datetime import timedelta
5
3
  from shutil import get_terminal_size, rmtree
6
4
  from tempfile import mkdtemp
7
5
  from time import perf_counter, sleep
8
- from typing import TYPE_CHECKING, NoReturn
9
-
10
- if TYPE_CHECKING:
11
- import av
6
+ from typing import NoReturn
12
7
 
13
8
 
14
9
  class Log:
@@ -100,10 +95,6 @@ class Log:
100
95
 
101
96
  sys.stdout.write(f"Finished. took {second_len} seconds ({minute_len})\n")
102
97
 
103
- def experimental(self, codec: av.Codec) -> None:
104
- if codec.experimental:
105
- self.error(f"`{codec.name}` is an experimental codec")
106
-
107
98
  @staticmethod
108
99
  def deprecated(message: str) -> None:
109
100
  sys.stderr.write(f"\033[1m\033[33m{message}\033[0m\n")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: auto-editor
3
- Version: 26.2.0
3
+ Version: 26.3.1
4
4
  Summary: Auto-Editor: Effort free video editing!
5
5
  Author-email: WyattBlue <wyattblue@auto-editor.com>
6
6
  License: 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,>=1.24
15
- Requires-Dist: pyav==14.*
15
+ Requires-Dist: pyav==14.2.*
16
16
 
17
17
  <p align="center"><img src="https://auto-editor.com/img/auto-editor-banner.webp" title="Auto-Editor" width="700"></p>
18
18
 
@@ -1,8 +1,8 @@
1
- auto_editor/__init__.py,sha256=1-JJ1Kd-PXkwShJyQvOWjlyj_pGZI56jaozFas4DX70,23
1
+ auto_editor/__init__.py,sha256=cbuXE-xYiZp6P9Ipk0EAUgPxPvaOpg-ve_HurO96fCM,23
2
2
  auto_editor/__main__.py,sha256=g-9q3i6oFeNPeFMeNJEwZua6ZloOPLcaLN-B0FlxWXo,11371
3
- auto_editor/analyze.py,sha256=7p_SDRRKQzlc6wtoW6MXYvJkDV4NO4DSOtJPFAuYcwM,12721
4
- auto_editor/edit.py,sha256=cZbt5a4AH2U8pwtBb_VNOhcvjE3JEaBwkXfvriEcHYY,16573
5
- auto_editor/ffwrapper.py,sha256=1uUTPV61RWKbUrONLvQdu2piNziz44vZjzQgd-e9YCU,4807
3
+ auto_editor/analyze.py,sha256=tkNZdRz1Nf1mQfC3jKHaiLbHRkacX_7-2TrKTKvwpxY,12463
4
+ auto_editor/edit.py,sha256=unOxLPiPUMoLgM_ScdRA3rNnxOicUUu7iLO1lG0zcfc,20260
5
+ auto_editor/ffwrapper.py,sha256=1lYYfq8gVgMVkYWeAEYDPAHCwFCYbKQwy0FxYBxMzk8,4765
6
6
  auto_editor/help.py,sha256=CzfDTsL4GuGu596ySHKj_wKnxGR9h8B0KUdkZpo33oE,8044
7
7
  auto_editor/make_layers.py,sha256=vEeJt0PnE1vc9-cQZ_AlXVDjvWhObRCWJSCQGraoMvU,9016
8
8
  auto_editor/output.py,sha256=ho8Lpqz4Sv_Gw0Vj2OvG39s83xHpyZlvtRNryTPbXqc,2563
@@ -14,11 +14,11 @@ auto_editor/cmds/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,
14
14
  auto_editor/cmds/cache.py,sha256=bViYbtVXefTeEIUvSanDfA6cG35ep1N_Jvtz7ZjgIkY,1959
15
15
  auto_editor/cmds/desc.py,sha256=GDrKJYiHMaeTrplZAceXl1JwoqD78XsV2_5lc0Xd7po,869
16
16
  auto_editor/cmds/info.py,sha256=vYa1hYdE8kDTE8AS3kwXlnd59X6CrE2GtIEQ7UmlpRY,7010
17
- auto_editor/cmds/levels.py,sha256=qMxTOlj4ezna0K2jYWDFyZ0Srn4pT6nIdR-479IOEvw,5758
17
+ auto_editor/cmds/levels.py,sha256=RBBs0YM8Qb7XteCy7Pr4QpU9b5maMsDe6xEkAuyGs1c,5644
18
18
  auto_editor/cmds/palet.py,sha256=ONzTqemaQq9YEfIOsDRNnwzfqnEMUMSXIQrETxyroRU,749
19
19
  auto_editor/cmds/repl.py,sha256=TF_I7zsFY7-KdgidrqjafTz7o_eluVbLvgTcOBG-UWQ,3449
20
20
  auto_editor/cmds/subdump.py,sha256=af_XBf7kaevqHn1A71z8C-7x8pS5WKD9FE_ugkCw6rk,665
21
- auto_editor/cmds/test.py,sha256=hX7g8tNa8DNk3vqx15DOtFj82zWKUImP_UHPCYPPdMQ,25787
21
+ auto_editor/cmds/test.py,sha256=D8l4Zr0UjrUtFkqsADqlVQ1wvNP3s97ifNnyf1UBTFU,26327
22
22
  auto_editor/formats/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
23
  auto_editor/formats/fcp11.py,sha256=sqjC36jI47ICPLjZJYiqGwY7foOnWOiNjkPFLdgSnI4,5208
24
24
  auto_editor/formats/fcp7.py,sha256=x5cagTzGCAW3i3M6m7TZC1h8gLfSmX1UK-iiDuCpdfs,20289
@@ -30,7 +30,7 @@ auto_editor/lang/json.py,sha256=D84vwyLtX5t5xl8S4r4jFXGVkbIg1L4IcexlS_a_k6w,9231
30
30
  auto_editor/lang/libintrospection.py,sha256=6H1rGp0wqaCud5IPaoEmzULGnYt6ec7_0h32ATcw2oY,261
31
31
  auto_editor/lang/libmath.py,sha256=z33A161Oe6vYYK7R6pgYjdZZe63dQkN38Qf36TL3prg,847
32
32
  auto_editor/lang/palet.py,sha256=ZOzNxLfzY8FTCYlF_mZtU2XoNzdg-eseUVkMtnWkVaI,24139
33
- auto_editor/lang/stdenv.py,sha256=CIlQ9tTKscVNjajtDJeCG24Rk2J9sYqKJK4moI67Kag,43754
33
+ auto_editor/lang/stdenv.py,sha256=sQyOD3bttjcieWMtTMNpE6blEZriAfHtSZHbuvC09R8,43762
34
34
  auto_editor/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
35
  auto_editor/lib/contracts.py,sha256=lExGQymcQUmwG5lC1lO4qm4GY8W0q_yzK_miTaAoPA4,7586
36
36
  auto_editor/lib/data_structs.py,sha256=Hnzl5gWvo-geTU0g-lGejj6HQW3VvPv0NBEj2XoGskY,7089
@@ -38,19 +38,19 @@ auto_editor/lib/err.py,sha256=UlszQJdzMZwkbT8x3sY4GkCV_5x9yrd6uVVUzvA8iiI,35
38
38
  auto_editor/render/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
39
  auto_editor/render/audio.py,sha256=_GuX0WNY1YeumgBN3bWqgwVXiuhpvx7sijABxqyO2ag,12580
40
40
  auto_editor/render/subtitle.py,sha256=jtNRKvgo1fpHTrAfGZqdkNeNgGgasw-K-4PwIKiWwfM,6231
41
- auto_editor/render/video.py,sha256=svyHUZRV3sAXjEcfrnKPW7gJkqd-724lYGrZnwKEnSA,12591
41
+ auto_editor/render/video.py,sha256=JBVl8w-hQ6zrs97iA527LPsBZ9s601SVSJs2bSMCq88,12185
42
42
  auto_editor/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
43
- auto_editor/utils/bar.py,sha256=miij9BW6mqn85gARh-bf2jP9dEHSwOyI3d4JIxQo36s,3998
43
+ auto_editor/utils/bar.py,sha256=Ky9JRf37JTgLyvNuIXDfucaUE8H1vBbCqKLjttmsmmo,4156
44
44
  auto_editor/utils/chunks.py,sha256=J-eGKtEz68gFtRrj1kOSgH4Tj_Yz6prNQ7Xr-d9NQJw,52
45
45
  auto_editor/utils/cmdkw.py,sha256=aUGBvBel2Ko1o6Rwmr4rEL-BMc5hEnzYLbyZ1GeJdcY,5729
46
46
  auto_editor/utils/container.py,sha256=C_Ahh7nlMEX4DNQ2M_cITPPbYcIL68r4I_AgFy0OD6o,2487
47
47
  auto_editor/utils/func.py,sha256=C8ucgsSEzPyBc-8obhsCXd_uQW0cnCdBn1KVxB7FHjU,2747
48
- auto_editor/utils/log.py,sha256=8fOdyTG3vjKhA1tJTMKRjXVqhrY2q3tFnXU8tKm_twA,3937
48
+ auto_editor/utils/log.py,sha256=wPNf6AabV-0cnoS_bPLv1Lh7llQBtNqPKeh07einOuc,3701
49
49
  auto_editor/utils/types.py,sha256=r5f6QB81xH7NRwGntITIOCVx-fupOl8l3X3LSFkt3nE,10756
50
50
  docs/build.py,sha256=POy8X8QOBYe_8A8HI_yiVI_Qg9E5mLpn1z7AHQr0_vQ,1888
51
- auto_editor-26.2.0.dist-info/LICENSE,sha256=yiq99pWITHfqS0pbZMp7cy2dnbreTuvBwudsU-njvIM,1210
52
- auto_editor-26.2.0.dist-info/METADATA,sha256=cy6NADq5iQR2-kkjagsaCvfz7ZuDW0kaM83TKMdqZTU,6109
53
- auto_editor-26.2.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
54
- auto_editor-26.2.0.dist-info/entry_points.txt,sha256=UAsTc7qJQbnAzHd7KWg-ALo_X9Hj2yDs3M9I2DV3eyI,212
55
- auto_editor-26.2.0.dist-info/top_level.txt,sha256=jBV5zlbWRbKOa-xaWPvTD45QL7lGExx2BDzv-Ji4dTw,17
56
- auto_editor-26.2.0.dist-info/RECORD,,
51
+ auto_editor-26.3.1.dist-info/LICENSE,sha256=yiq99pWITHfqS0pbZMp7cy2dnbreTuvBwudsU-njvIM,1210
52
+ auto_editor-26.3.1.dist-info/METADATA,sha256=4r9rtkLWEDaVMcJauMcljdAw-cnz2h6xS9sixAnWVlQ,6111
53
+ auto_editor-26.3.1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
54
+ auto_editor-26.3.1.dist-info/entry_points.txt,sha256=UAsTc7qJQbnAzHd7KWg-ALo_X9Hj2yDs3M9I2DV3eyI,212
55
+ auto_editor-26.3.1.dist-info/top_level.txt,sha256=jBV5zlbWRbKOa-xaWPvTD45QL7lGExx2BDzv-Ji4dTw,17
56
+ auto_editor-26.3.1.dist-info/RECORD,,