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 +1 -1
- auto_editor/analyze.py +0 -7
- auto_editor/cmds/levels.py +0 -2
- auto_editor/cmds/test.py +16 -0
- auto_editor/edit.py +113 -23
- auto_editor/ffwrapper.py +1 -2
- auto_editor/lang/stdenv.py +1 -1
- auto_editor/render/video.py +8 -36
- auto_editor/utils/bar.py +16 -10
- auto_editor/utils/log.py +1 -10
- {auto_editor-26.2.0.dist-info → auto_editor-26.3.1.dist-info}/METADATA +2 -2
- {auto_editor-26.2.0.dist-info → auto_editor-26.3.1.dist-info}/RECORD +16 -16
- {auto_editor-26.2.0.dist-info → auto_editor-26.3.1.dist-info}/LICENSE +0 -0
- {auto_editor-26.2.0.dist-info → auto_editor-26.3.1.dist-info}/WHEEL +0 -0
- {auto_editor-26.2.0.dist-info → auto_editor-26.3.1.dist-info}/entry_points.txt +0 -0
- {auto_editor-26.2.0.dist-info → auto_editor-26.3.1.dist-info}/top_level.txt +0 -0
auto_editor/__init__.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = "26.
|
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
|
auto_editor/cmds/levels.py
CHANGED
@@ -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
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
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
|
-
|
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
|
-
|
376
|
-
|
377
|
-
|
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
|
-
|
387
|
-
|
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
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
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
|
-
|
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: {
|
403
|
-
"
|
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
|
-
|
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,
|
auto_editor/lang/stdenv.py
CHANGED
@@ -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,
|
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),
|
auto_editor/render/video.py
CHANGED
@@ -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
|
-
|
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
|
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,
|
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
|
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 -
|
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
|
-
|
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
|
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.
|
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
|
+
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=
|
4
|
-
auto_editor/edit.py,sha256=
|
5
|
-
auto_editor/ffwrapper.py,sha256=
|
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=
|
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=
|
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=
|
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=
|
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=
|
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=
|
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.
|
52
|
-
auto_editor-26.
|
53
|
-
auto_editor-26.
|
54
|
-
auto_editor-26.
|
55
|
-
auto_editor-26.
|
56
|
-
auto_editor-26.
|
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,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|